Fix the non-ELF build.
[mono.git] / mono / mini / aot-compiler.c
1 /*
2  * aot.c: mono Ahead of Time compiler
3  *
4  * Author:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *   Zoltan Varga (vargaz@gmail.com)
7  *
8  * (C) 2002 Ximian, Inc.
9  */
10
11 /* Remaining AOT-only work:
12  * - reduce the length of the wrapper names.
13  * - aot IMT tables, so we don't have two kinds of aot code.
14  * - optimize the trampolines, generate more code in the arch files.
15  * - make things more consistent with how elf works, for example, use ELF 
16  *   relocations.
17  * Remaining generics sharing work:
18  * - optimize the size of the data which is encoded.
19  * - optimize the runtime loading of data:
20  *   - the trampoline code calls mono_jit_info_table_find () to find the rgctx, 
21  *     which loads the debugging+exception handling info for the method. This is a 
22  *     huge waste of time and code, since the rgctx structure is currently empty.
23  *   - every shared method has a MonoGenericJitInfo structure which is only really
24  *     used for handling catch clauses with open types, not a very common use case.
25  */
26
27 #include "config.h"
28 #include <sys/types.h>
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32 #include <fcntl.h>
33 #include <ctype.h>
34 #include <string.h>
35 #ifndef PLATFORM_WIN32
36 #include <sys/time.h>
37 #else
38 #include <winsock2.h>
39 #include <windows.h>
40 #endif
41
42 #include <errno.h>
43 #include <sys/stat.h>
44 #include <limits.h>    /* for PAGESIZE */
45 #ifndef PAGESIZE
46 #define PAGESIZE 4096
47 #endif
48
49 #include <mono/metadata/tabledefs.h>
50 #include <mono/metadata/class.h>
51 #include <mono/metadata/object.h>
52 #include <mono/metadata/tokentype.h>
53 #include <mono/metadata/appdomain.h>
54 #include <mono/metadata/debug-helpers.h>
55 #include <mono/metadata/assembly.h>
56 #include <mono/metadata/metadata-internals.h>
57 #include <mono/metadata/marshal.h>
58 #include <mono/metadata/gc-internal.h>
59 #include <mono/metadata/method-builder.h>
60 #include <mono/metadata/monitor.h>
61 #include <mono/metadata/mempool-internals.h>
62 #include <mono/metadata/mono-endian.h>
63 #include <mono/utils/mono-logger.h>
64 #include <mono/utils/mono-compiler.h>
65 #include <mono/utils/mono-time.h>
66
67 #ifndef PLATFORM_WIN32
68 #include <mono/utils/freebsd-elf32.h>
69 #include <mono/utils/freebsd-elf64.h>
70 #endif
71
72 #include <mono/utils/freebsd-dwarf.h>
73
74 #include "mini.h"
75
76 #ifndef DISABLE_AOT
77
78 #define TV_DECLARE(name) gint64 name
79 #define TV_GETTIME(tv) tv = mono_100ns_ticks ()
80 #define TV_ELAPSED(start,end) (((end) - (start)) / 10)
81
82 #ifdef PLATFORM_WIN32
83 #define SHARED_EXT ".dll"
84 #elif defined(__ppc__) && defined(__MACH__)
85 #define SHARED_EXT ".dylib"
86 #else
87 #define SHARED_EXT ".so"
88 #endif
89
90 #if defined(sparc) || defined(__ppc__) || defined(__powerpc__) || defined(__MACH__)
91 #define AS_STRING_DIRECTIVE ".asciz"
92 #else
93 /* GNU as */
94 #define AS_STRING_DIRECTIVE ".string"
95 #endif
96
97
98 // __MACH__
99 // .byte generates 1 byte per expression.
100 // .short generates 2 bytes per expression.
101 // .long generates 4 bytes per expression.
102 // .quad generates 8 bytes per expression.
103
104 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
105 #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
106 #define ROUND_DOWN(VALUE,SIZE)  ((VALUE) & ~((SIZE) - 1))
107
108 typedef struct MonoAotOptions {
109         char *outfile;
110         gboolean save_temps;
111         gboolean write_symbols;
112         gboolean metadata_only;
113         gboolean bind_to_runtime_version;
114         gboolean full_aot;
115         gboolean no_dlsym;
116         gboolean static_link;
117         gboolean asm_only;
118         int nthreads;
119 } MonoAotOptions;
120
121 typedef struct MonoAotStats {
122         int ccount, mcount, lmfcount, abscount, wrappercount, gcount, ocount, genericcount;
123         int code_size, info_size, ex_info_size, got_size, class_info_size, got_info_size, got_info_offsets_size;
124         int methods_without_got_slots, direct_calls, all_calls;
125         int got_slots;
126         int got_slot_types [MONO_PATCH_INFO_NONE];
127         int jit_time, gen_time, link_time;
128 } MonoAotStats;
129
130 #if defined(__x86_64__) && !defined(PLATFORM_WIN32)
131 #define USE_ELF_WRITER 1
132 #define USE_ELF_RELA 1
133 #endif
134
135 #if defined(__i386__) && !defined(PLATFORM_WIN32)
136 #define USE_ELF_WRITER 1
137 #endif
138
139 #if defined(__arm__) && !defined(__MACH__)
140 #define USE_ELF_WRITER 1
141 #endif
142
143 #if defined(__mips__)
144 #define USE_ELF_WRITER 1
145 #endif
146
147 #if defined(USE_ELF_WRITER)
148 #define USE_BIN_WRITER 1
149 #endif
150
151 #ifdef USE_BIN_WRITER
152
153 typedef struct _BinSymbol BinSymbol;
154 typedef struct _BinReloc BinReloc;
155 typedef struct _BinSection BinSection;
156
157 #endif
158
159 /* emit mode */
160 enum {
161         EMIT_NONE,
162         EMIT_BYTE,
163         EMIT_WORD,
164         EMIT_LONG
165 };
166
167 typedef struct MonoAotCompile {
168         MonoImage *image;
169         GPtrArray *methods;
170         GHashTable *method_indexes;
171         MonoCompile **cfgs;
172         int cfgs_size;
173         GHashTable *patch_to_plt_offset;
174         GHashTable *plt_offset_to_patch;
175         GHashTable *patch_to_shared_got_offset;
176         GPtrArray *shared_patches;
177         GHashTable *image_hash;
178         GHashTable *method_to_cfg;
179         GHashTable *token_info_hash;
180         GPtrArray *extra_methods;
181         GPtrArray *image_table;
182         GPtrArray *globals;
183         GList *method_order;
184         guint32 *plt_got_info_offsets;
185         /* Number of trampolines emitted into the AOT file */
186         guint32 num_aot_trampolines;
187         guint32 got_offset, plt_offset, plt_got_offset_base;
188         /* Number of GOT entries reserved for trampolines */
189         guint32 num_trampoline_got_entries;
190         guint32 trampoline_got_offset_base;
191         MonoAotOptions aot_opts;
192         guint32 nmethods;
193         guint32 opts;
194         MonoMemPool *mempool;
195         MonoAotStats stats;
196         int method_index;
197         char *static_linking_symbol;
198         CRITICAL_SECTION mutex;
199         gboolean use_bin_writer;
200         /* Bin writer */
201 #ifdef USE_BIN_WRITER
202         BinSymbol *symbols;
203         BinSection *sections;
204         BinSection *cur_section;
205         BinReloc *relocations;
206         GHashTable *labels;
207         int num_relocs;
208 #endif
209         /* Asm writer */
210         FILE *fp;
211         char *tmpfname;
212         int mode; /* emit mode */
213         int col_count; /* bytes emitted per .byte line */
214         /* xdebug */
215         GHashTable *class_to_die;
216         int fde_index, tdie_index;
217 } MonoAotCompile;
218
219 #define mono_acfg_lock(acfg) EnterCriticalSection (&((acfg)->mutex))
220 #define mono_acfg_unlock(acfg) LeaveCriticalSection (&((acfg)->mutex))
221
222 #ifdef HAVE_ARRAY_ELEM_INIT
223 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
224 #define MSGSTRFIELD1(line) str##line
225 static const struct msgstr_t {
226 #define PATCH_INFO(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
227 #include "patch-info.h"
228 #undef PATCH_INFO
229 } opstr = {
230 #define PATCH_INFO(a,b) b,
231 #include "patch-info.h"
232 #undef PATCH_INFO
233 };
234 static const gint16 opidx [] = {
235 #define PATCH_INFO(a,b) [MONO_PATCH_INFO_ ## a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
236 #include "patch-info.h"
237 #undef PATCH_INFO
238 };
239
240 static const char*
241 get_patch_name (int info)
242 {
243         return (const char*)&opstr + opidx [info];
244 }
245
246 #else
247 #define PATCH_INFO(a,b) b,
248 static const char* const
249 patch_types [MONO_PATCH_INFO_NUM + 1] = {
250 #include "patch-info.h"
251         NULL
252 };
253
254 static const char*
255 get_patch_name (int info)
256 {
257         return patch_types [info];
258 }
259
260 #endif
261
262 static void
263 emit_global (MonoAotCompile *acfg, const char *name, gboolean func);
264
265 static gboolean 
266 is_got_patch (MonoJumpInfoType patch_type)
267 {
268         return TRUE;
269 }
270
271 static G_GNUC_UNUSED int
272 ilog2(register int value)
273 {
274         int count = -1;
275         while (value & ~0xf) count += 4, value >>= 4;
276         while (value) count++, value >>= 1;
277         return count;
278 }
279
280 #ifdef USE_BIN_WRITER
281
282 typedef struct _BinLabel BinLabel;
283 struct _BinLabel {
284         char *name;
285         BinSection *section;
286         int offset;
287 };
288
289 struct _BinReloc {
290         BinReloc *next;
291         char *val1;
292         char *val2;
293         BinSection *val2_section;
294         int val2_offset;
295         int offset;
296         BinSection *section;
297         int section_offset;
298         int reloc_type;
299 };
300
301 struct _BinSymbol {
302         BinSymbol *next;
303         char *name;
304         BinSection *section;
305         int offset;
306         gboolean is_function;
307         gboolean is_global;
308         char *end_label;
309 };
310
311 struct _BinSection {
312         BinSection *next;
313         BinSection *parent;
314         char *name;
315         int subsection;
316         guint8 *data;
317         int data_len;
318         int cur_offset;
319         int file_offset;
320         int virt_offset;
321         int shidx;
322 };
323
324 static void
325 bin_writer_emit_start (MonoAotCompile *acfg)
326 {
327         acfg->labels = g_hash_table_new (g_str_hash, g_str_equal);
328 }
329
330 static void
331 bin_writer_emit_section_change (MonoAotCompile *acfg, const char *section_name, int subsection_index)
332 {
333         BinSection *section;
334
335         if (acfg->cur_section && acfg->cur_section->subsection == subsection_index
336                         && strcmp (acfg->cur_section->name, section_name) == 0)
337                 return;
338         for (section = acfg->sections; section; section = section->next) {
339                 if (section->subsection == subsection_index && strcmp (section->name, section_name) == 0) {
340                         acfg->cur_section = section;
341                         return;
342                 }
343         }
344         if (!section) {
345                 section = g_new0 (BinSection, 1);
346                 section->name = g_strdup (section_name);
347                 section->subsection = subsection_index;
348                 section->next = acfg->sections;
349                 acfg->sections = section;
350                 acfg->cur_section = section;
351         }
352 }
353
354 static void
355 bin_writer_emit_symbol_inner (MonoAotCompile *acfg, const char *name, const char *end_label, gboolean is_global, gboolean func)
356 {
357         BinSymbol *symbol = g_new0 (BinSymbol, 1);
358         symbol->name = g_strdup (name);
359         if (end_label)
360                 symbol->end_label = g_strdup (end_label);
361         symbol->is_function = func;
362         symbol->is_global = is_global;
363         symbol->section = acfg->cur_section;
364         /* FIXME: we align after this call... */
365         symbol->offset = symbol->section->cur_offset;
366         symbol->next = acfg->symbols;
367         acfg->symbols = symbol;
368 }
369
370 static void
371 bin_writer_emit_global_inner (MonoAotCompile *acfg, const char *name, gboolean func)
372 {
373         bin_writer_emit_symbol_inner (acfg, name, NULL, TRUE, func);
374 }
375
376 static void
377 bin_writer_emit_local_symbol (MonoAotCompile *acfg, const char *name, const char *end_label, gboolean func)
378 {
379         bin_writer_emit_symbol_inner (acfg, name, end_label, FALSE, func);
380 }
381
382 static void
383 bin_writer_emit_label (MonoAotCompile *acfg, const char *name)
384 {
385         BinLabel *label = g_new0 (BinLabel, 1);
386         label->name = g_strdup (name);
387         label->section = acfg->cur_section;
388         label->offset = acfg->cur_section->cur_offset;
389         g_hash_table_insert (acfg->labels, label->name, label);
390 }
391
392 static void
393 bin_writer_emit_ensure_buffer (BinSection *section, int size)
394 {
395         int new_offset = section->cur_offset + size;
396         if (new_offset >= section->data_len) {
397                 int new_size = section->data_len? section->data_len * 2: 256;
398                 guint8 *data;
399                 while (new_size <= new_offset)
400                         new_size *= 2;
401                 data = g_malloc0 (new_size);
402                 memcpy (data, section->data, section->data_len);
403                 g_free (section->data);
404                 section->data = data;
405                 section->data_len = new_size;
406         }
407 }
408
409 static void
410 bin_writer_emit_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
411 {
412         bin_writer_emit_ensure_buffer (acfg->cur_section, size);
413         memcpy (acfg->cur_section->data + acfg->cur_section->cur_offset, buf, size);
414         acfg->cur_section->cur_offset += size;
415 }
416
417 static void
418 bin_writer_emit_string (MonoAotCompile *acfg, const char *value)
419 {
420         int size = strlen (value) + 1;
421         bin_writer_emit_bytes (acfg, (const guint8*)value, size);
422 }
423
424 static void
425 bin_writer_emit_line (MonoAotCompile *acfg)
426 {
427         /* Nothing to do in binary writer */
428 }
429
430 static void 
431 bin_writer_emit_alignment (MonoAotCompile *acfg, int size)
432 {
433         int offset = acfg->cur_section->cur_offset;
434         int add;
435         offset += (size - 1);
436         offset &= ~(size - 1);
437         add = offset - acfg->cur_section->cur_offset;
438         if (add) {
439                 bin_writer_emit_ensure_buffer (acfg->cur_section, add);
440                 acfg->cur_section->cur_offset += add;
441         }
442 }
443
444 static void
445 bin_writer_emit_pointer_unaligned (MonoAotCompile *acfg, const char *target)
446 {
447         BinReloc *reloc;
448
449         if (!target)
450                 // FIXME:
451                 g_assert_not_reached ();
452         reloc = g_new0 (BinReloc, 1);
453         reloc->val1 = g_strdup (target);
454         reloc->section = acfg->cur_section;
455         reloc->section_offset = acfg->cur_section->cur_offset;
456         reloc->next = acfg->relocations;
457         acfg->relocations = reloc;
458         if (strcmp (reloc->section->name, ".data") == 0) {
459                 acfg->num_relocs++;
460                 g_print ("reloc: %s at %d\n", target, acfg->cur_section->cur_offset);
461         }
462         acfg->cur_section->cur_offset += sizeof (gpointer);
463 }
464
465 static void
466 bin_writer_emit_pointer (MonoAotCompile *acfg, const char *target)
467 {
468         bin_writer_emit_alignment (acfg, sizeof (gpointer));
469         bin_writer_emit_pointer_unaligned (acfg, target);
470 }
471
472 static void
473 bin_writer_emit_int16 (MonoAotCompile *acfg, int value)
474 {
475         guint8 *data;
476         bin_writer_emit_ensure_buffer (acfg->cur_section, 2);
477         data = acfg->cur_section->data + acfg->cur_section->cur_offset;
478         acfg->cur_section->cur_offset += 2;
479         /* FIXME: little endian */
480         data [0] = value;
481         data [1] = value >> 8;
482 }
483
484 static void
485 bin_writer_emit_int32 (MonoAotCompile *acfg, int value)
486 {
487         guint8 *data;
488         bin_writer_emit_ensure_buffer (acfg->cur_section, 4);
489         data = acfg->cur_section->data + acfg->cur_section->cur_offset;
490         acfg->cur_section->cur_offset += 4;
491         /* FIXME: little endian */
492         data [0] = value;
493         data [1] = value >> 8;
494         data [2] = value >> 16;
495         data [3] = value >> 24;
496 }
497
498 static BinReloc*
499 create_reloc (MonoAotCompile *acfg, const char *end, const char* start, int offset)
500 {
501         BinReloc *reloc;
502         reloc = mono_mempool_alloc0 (acfg->mempool, sizeof (BinReloc));
503         reloc->val1 = mono_mempool_strdup (acfg->mempool, end);
504         if (strcmp (start, ".") == 0) {
505                 reloc->val2_section = acfg->cur_section;
506                 reloc->val2_offset = acfg->cur_section->cur_offset;
507         } else {
508                 reloc->val2 = mono_mempool_strdup (acfg->mempool, start);
509         }
510         reloc->offset = offset;
511         reloc->section = acfg->cur_section;
512         reloc->section_offset = acfg->cur_section->cur_offset;
513         reloc->next = acfg->relocations;
514         acfg->relocations = reloc;
515         return reloc;
516 }
517
518 static void
519 bin_writer_emit_symbol_diff (MonoAotCompile *acfg, const char *end, const char* start, int offset)
520 {
521         create_reloc (acfg, end, start, offset);
522         acfg->cur_section->cur_offset += 4;
523         /*if (strcmp (reloc->section->name, ".data") == 0) {
524                 acfg->num_relocs++;
525                 g_print ("reloc: %s - %s + %d at %d\n", end, start, offset, acfg->cur_section->cur_offset - 4);
526         }*/
527 }
528
529 /* 
530  * Emit a relocation entry of type RELOC_TYPE against symbol SYMBOL at the current PC.
531  * Do not advance PC.
532  */
533 static G_GNUC_UNUSED void
534 bin_writer_emit_reloc (MonoAotCompile *acfg, int reloc_type, const char *symbol, int addend)
535 {
536         BinReloc *reloc = create_reloc (acfg, symbol, ".", addend);
537         reloc->reloc_type = reloc_type;
538 }
539
540 static void
541 bin_writer_emit_zero_bytes (MonoAotCompile *acfg, int num)
542 {
543         bin_writer_emit_ensure_buffer (acfg->cur_section, num);
544         acfg->cur_section->cur_offset += num;
545 }
546
547 #ifdef USE_ELF_WRITER
548
549 enum {
550         SECT_NULL,
551         SECT_HASH,
552         SECT_DYNSYM,
553         SECT_DYNSTR,
554         SECT_REL_DYN,
555         SECT_RELA_DYN,
556         SECT_TEXT,
557         SECT_DYNAMIC,
558         SECT_GOT_PLT,
559         SECT_DATA,
560         SECT_BSS,
561         SECT_DEBUG_FRAME,
562         SECT_DEBUG_INFO,
563         SECT_DEBUG_ABBREV,
564         SECT_SHSTRTAB,
565         SECT_SYMTAB,
566         SECT_STRTAB,
567         SECT_NUM
568 };
569
570 /* Relocation types */
571 #define R_ARM_CALL 28
572 #define R_ARM_ALU_PC_G0_NC 59
573
574 #if SIZEOF_VOID_P == 4
575
576 typedef Elf32_Ehdr ElfHeader;
577 typedef Elf32_Shdr ElfSectHeader;
578 typedef Elf32_Phdr ElfProgHeader;
579 typedef Elf32_Sym ElfSymbol;
580 typedef Elf32_Rel ElfReloc;
581 typedef Elf32_Rela ElfRelocA;
582 typedef Elf32_Dyn ElfDynamic;
583
584 #else
585
586 typedef Elf64_Ehdr ElfHeader;
587 typedef Elf64_Shdr ElfSectHeader;
588 typedef Elf64_Phdr ElfProgHeader;
589 typedef Elf64_Sym ElfSymbol;
590 typedef Elf64_Rel ElfReloc;
591 typedef Elf64_Rela ElfRelocA;
592 typedef Elf64_Dyn ElfDynamic;
593
594 #endif
595
596 typedef struct {
597         const char *name;
598         int type;
599         int esize;
600         int flags;
601         int align;
602 } SectInfo;
603
604 static SectInfo section_info [] = {
605         {"", 0, 0, 0, 0},
606         {".hash", SHT_HASH, 4, 2, SIZEOF_VOID_P},
607         {".dynsym", SHT_DYNSYM, sizeof (ElfSymbol), 2, SIZEOF_VOID_P},
608         {".dynstr", SHT_STRTAB, 0, 2, 1},
609         {".rel.dyn", SHT_REL, sizeof (ElfReloc), 2, SIZEOF_VOID_P},
610         {".rela.dyn", SHT_RELA, sizeof (ElfRelocA), 2, SIZEOF_VOID_P},
611         {".text", SHT_PROGBITS, 0, 6, 4096},
612         {".dynamic", SHT_DYNAMIC, sizeof (ElfDynamic), 3, SIZEOF_VOID_P},
613         {".got.plt", SHT_PROGBITS, SIZEOF_VOID_P, 3, SIZEOF_VOID_P},
614         {".data", SHT_PROGBITS, 0, 3, 8},
615         {".bss", SHT_NOBITS, 0, 3, 8},
616         {".debug_frame", SHT_PROGBITS, 0, 0, 8},
617         {".debug_info", SHT_PROGBITS, 0, 0, 1},
618         {".debug_abbrev", SHT_PROGBITS, 0, 0, 1},
619         {".shstrtab", SHT_STRTAB, 0, 0, 1},
620         {".symtab", SHT_SYMTAB, sizeof (ElfSymbol), 0, SIZEOF_VOID_P},
621         {".strtab", SHT_STRTAB, 0, 0, 1}
622 };
623
624 typedef struct {
625         GString *data;
626         GHashTable *hash;
627 } ElfStrTable;
628
629 static int
630 str_table_add (ElfStrTable *table, const char* value)
631 {
632         int idx;
633         if (!table->data) {
634                 table->data = g_string_new_len ("", 1);
635                 table->hash = g_hash_table_new (g_str_hash, g_str_equal);
636         }
637         idx = GPOINTER_TO_UINT (g_hash_table_lookup (table->hash, value));
638         if (idx)
639                 return idx;
640         idx = table->data->len;
641         g_string_append (table->data, value);
642         g_string_append_c (table->data, 0);
643         g_hash_table_insert (table->hash, (void*)value, GUINT_TO_POINTER (idx));
644         return idx;
645 }
646
647 static void
648 append_subsection (MonoAotCompile *acfg, ElfSectHeader *sheaders, BinSection *sect, BinSection *add)
649 {
650         int offset = sect->cur_offset;
651         /*offset += (sheaders [sect->shidx].sh_addralign - 1);
652         offset &= ~(sheaders [sect->shidx].sh_addralign - 1);*/
653         offset += (8 - 1);
654         offset &= ~(8 - 1);
655         bin_writer_emit_ensure_buffer (sect, offset);
656         g_print ("section %s aligned to %d from %d\n", sect->name, offset, sect->cur_offset);
657         sect->cur_offset = offset;
658
659         bin_writer_emit_ensure_buffer (sect, add->cur_offset);
660         memcpy (sect->data + sect->cur_offset, add->data, add->cur_offset);
661         add->parent = sect;
662         sect->cur_offset += add->cur_offset;
663         add->cur_offset = offset; /* it becomes the offset in the parent section */
664         g_print ("subsection %d of %s added at offset %d (align: %d)\n", add->subsection, sect->name, add->cur_offset, (int)sheaders [sect->shidx].sh_addralign);
665         add->data = NULL;
666         add->data_len = 0;
667 }
668
669 /* merge the subsections */
670 static int
671 collect_sections (MonoAotCompile *acfg, ElfSectHeader *sheaders, BinSection **out, int num)
672 {
673         int i, j, maxs, num_sections;
674         BinSection *sect;
675
676         num_sections = 0;
677         maxs = 0;
678         for (sect = acfg->sections; sect; sect = sect->next) {
679                 if (sect->subsection == 0) {
680                         out [num_sections++] = sect;
681                         g_assert (num_sections < num);
682                 }
683                 maxs = MAX (maxs, sect->subsection);
684         }
685         for (i = 0; i < num_sections; i++) {
686                 for (j = 1; j <= maxs; ++j) {
687                         for (sect = acfg->sections; sect; sect = sect->next) {
688                                 if (sect->subsection == j && strcmp (out [i]->name, sect->name) == 0) {
689                                         append_subsection (acfg, sheaders, out [i], sect);
690                                 }
691                         }
692                 }
693         }
694         return num_sections;
695 }
696
697 static unsigned long
698 elf_hash (const unsigned char *name)
699 {
700         unsigned long h = 0, g;
701         while (*name) {
702                 h = (h << 4) + *name++;
703                 if ((g = h & 0xf0000000))
704                         h ^= g >> 24;
705                 h &= ~g;
706         }
707         return h;
708 }
709
710 #define NUM_BUCKETS 17
711
712 static int*
713 build_hash (MonoAotCompile *acfg, int num_sections, ElfStrTable *dynstr)
714 {
715         int *data;
716         int num_symbols = 1 + num_sections + 3;
717         BinSymbol *symbol;
718
719         for (symbol = acfg->symbols; symbol; symbol = symbol->next) {
720                 if (!symbol->is_global)
721                         continue;
722                 num_symbols++;
723                 str_table_add (dynstr, symbol->name);
724                 /*g_print ("adding sym: %s\n", symbol->name);*/
725         }
726         str_table_add (dynstr, "__bss_start");
727         str_table_add (dynstr, "_edata");
728         str_table_add (dynstr, "_end");
729
730         data = g_new0 (int, num_symbols + 2 + NUM_BUCKETS);
731         data [0] = NUM_BUCKETS;
732         data [1] = num_symbols;
733
734         return data;
735 }
736
737 static gsize
738 get_label_addr (MonoAotCompile *acfg, const char *name)
739 {
740         int offset;
741         BinLabel *lab;
742         BinSection *section;
743         gsize value;
744
745         lab = g_hash_table_lookup (acfg->labels, name);
746         if (!lab)
747                 g_error ("Undefined label: '%s'.\n", name);
748         section = lab->section;
749         offset = lab->offset;
750         if (section->parent) {
751                 value = section->parent->virt_offset + section->cur_offset + offset;
752         } else {
753                 value = section->virt_offset + offset;
754         }
755         return value;
756 }
757
758 static ElfSymbol*
759 collect_syms (MonoAotCompile *acfg, int *hash, ElfStrTable *strtab, ElfSectHeader *sheaders, int *num_syms)
760 {
761         ElfSymbol *symbols;
762         BinSymbol *symbol;
763         BinSection *section;
764         int i;
765         int *bucket;
766         int *chain;
767         unsigned long hashc;
768
769         if (hash)
770                 symbols = g_new0 (ElfSymbol, hash [1]);
771         else {
772                 i = 0;
773                 for (symbol = acfg->symbols; symbol; symbol = symbol->next)
774                         i ++;
775                 
776                 symbols = g_new0 (ElfSymbol, i + SECT_NUM + 10); /* FIXME */
777         }
778
779         /* the first symbol is undef, all zeroes */
780         i = 1;
781         if (sheaders) {
782                 int j;
783                 for (j = 1; j < SECT_NUM; ++j) {
784                         symbols [i].st_info = ELF32_ST_INFO (STB_LOCAL, STT_SECTION);
785                         symbols [i].st_shndx = j;
786                         symbols [i].st_value = sheaders [j].sh_addr;
787                         ++i;
788                 }
789         } else {
790                 for (section = acfg->sections; section; section = section->next) {
791                         if (section->parent)
792                                 continue;
793                         symbols [i].st_info = ELF32_ST_INFO (STB_LOCAL, STT_SECTION);
794                         if (strcmp (section->name, ".text") == 0) {
795                                 symbols [i].st_shndx = SECT_TEXT;
796                                 section->shidx = SECT_TEXT;
797                                 section->file_offset = 4096;
798                                 symbols [i].st_value = section->virt_offset;
799                         } else if (strcmp (section->name, ".data") == 0) {
800                                 symbols [i].st_shndx = SECT_DATA;
801                                 section->shidx = SECT_DATA;
802                                 section->file_offset = 4096 + 28; /* FIXME */
803                                 symbols [i].st_value = section->virt_offset;
804                         } else if (strcmp (section->name, ".bss") == 0) {
805                                 symbols [i].st_shndx = SECT_BSS;
806                                 section->shidx = SECT_BSS;
807                                 section->file_offset = 4096 + 28 + 8; /* FIXME */
808                                 symbols [i].st_value = section->virt_offset;
809                         }
810                         ++i;
811                 }
812         }
813         for (symbol = acfg->symbols; symbol; symbol = symbol->next) {
814                 int offset;
815                 BinLabel *lab;
816                 if (!symbol->is_global && hash)
817                         continue;
818                 symbols [i].st_info = ELF32_ST_INFO (symbol->is_global ? STB_GLOBAL : STB_LOCAL, symbol->is_function? STT_FUNC : STT_OBJECT);
819                 symbols [i].st_name = str_table_add (strtab, symbol->name);
820                 /*g_print ("sym name %s tabled to %d\n", symbol->name, symbols [i].st_name);*/
821                 section = symbol->section;
822                 symbols [i].st_shndx = section->parent? section->parent->shidx: section->shidx;
823                 lab = g_hash_table_lookup (acfg->labels, symbol->name);
824                 offset = lab->offset;
825                 if (section->parent) {
826                         symbols [i].st_value = section->parent->virt_offset + section->cur_offset + offset;
827                 } else {
828                         symbols [i].st_value = section->virt_offset + offset;
829                 }
830
831                 if (symbol->end_label) {
832                         BinLabel *elab = g_hash_table_lookup (acfg->labels, symbol->end_label);
833                         g_assert (elab);
834                         symbols [i].st_size = elab->offset - lab->offset;
835                 }
836                 ++i;
837         }
838         /* add special symbols */
839         symbols [i].st_name = str_table_add (strtab, "__bss_start");
840         symbols [i].st_shndx = 0xfff1;
841         symbols [i].st_info = ELF32_ST_INFO (STB_GLOBAL, 0);
842         ++i;
843         symbols [i].st_name = str_table_add (strtab, "_edata");
844         symbols [i].st_shndx = 0xfff1;
845         symbols [i].st_info = ELF32_ST_INFO (STB_GLOBAL, 0);
846         ++i;
847         symbols [i].st_name = str_table_add (strtab, "_end");
848         symbols [i].st_shndx = 0xfff1;
849         symbols [i].st_info = ELF32_ST_INFO (STB_GLOBAL, 0);
850         ++i;
851
852         if (num_syms)
853                 *num_syms = i;
854
855         /* add to hash table */
856         if (hash) {
857                 bucket = hash + 2;
858                 chain = hash + 2 + hash [0];
859                 for (i = 0; i < hash [1]; ++i) {
860                         int slot;
861                         /*g_print ("checking %d '%s' (sym %d)\n", symbols [i].st_name, strtab->data->str + symbols [i].st_name, i);*/
862                         if (!symbols [i].st_name)
863                                 continue;
864                         hashc = elf_hash ((guint8*)strtab->data->str + symbols [i].st_name);
865                         slot = hashc % hash [0];
866                         /*g_print ("hashing '%s' at slot %d (sym %d)\n", strtab->data->str + symbols [i].st_name, slot, i);*/
867                         if (bucket [slot]) {
868                                 chain [i] = bucket [slot];
869                                 bucket [slot] = i;
870                         } else {
871                                 bucket [slot] = i;
872                         }
873                 }
874         }
875         return symbols;
876 }
877
878 static void
879 reloc_symbols (MonoAotCompile *acfg, ElfSymbol *symbols, ElfSectHeader *sheaders, ElfStrTable *strtab, gboolean dynamic)
880 {
881         BinSection *section;
882         BinSymbol *symbol;
883         int i;
884
885         i = 1;
886         if (dynamic) {
887                 for (section = acfg->sections; section; section = section->next) {
888                         if (section->parent)
889                                 continue;
890                         symbols [i].st_value = sheaders [section->shidx].sh_addr;
891                         ++i;
892                 }
893         } else {
894                 for (i = 1; i < SECT_NUM; ++i) {
895                         symbols [i].st_value = sheaders [i].sh_addr;
896                 }
897         }
898         for (symbol = acfg->symbols; symbol; symbol = symbol->next) {
899                 int offset;
900                 BinLabel *lab;
901                 if (dynamic && !symbol->is_global)
902                         continue;
903                 section = symbol->section;
904                 lab = g_hash_table_lookup (acfg->labels, symbol->name);
905                 offset = lab->offset;
906                 if (section->parent) {
907                         symbols [i].st_value = sheaders [section->parent->shidx].sh_addr + section->cur_offset + offset;
908                 } else {
909                         symbols [i].st_value = sheaders [section->shidx].sh_addr + offset;
910                 }
911                 ++i;
912         }
913         /* __bss_start */
914         symbols [i].st_value = sheaders [SECT_BSS].sh_addr;
915         ++i;
916         /* _edata */
917         symbols [i].st_value = sheaders [SECT_DATA].sh_addr + sheaders [SECT_DATA].sh_size;
918         ++i;
919         /* _end */
920         symbols [i].st_value = sheaders [SECT_BSS].sh_addr + sheaders [SECT_BSS].sh_size;
921         ++i;
922 }
923
924 static void
925 resolve_reloc (MonoAotCompile *acfg, BinReloc *reloc, guint8 **out_data, gsize *out_vaddr, gsize *out_start_val, gsize *out_end_val)
926 {
927         guint8 *data;
928         gssize end_val, start_val;
929         gsize vaddr;
930
931         end_val = get_label_addr (acfg, reloc->val1);
932         if (reloc->val2) {
933                 start_val = get_label_addr (acfg, reloc->val2);
934         } else if (reloc->val2_section) {
935                 start_val = reloc->val2_offset;
936                 if (reloc->val2_section->parent)
937                         start_val += reloc->val2_section->parent->virt_offset + reloc->val2_section->cur_offset;
938                 else
939                         start_val += reloc->val2_section->virt_offset;
940         } else {
941                 start_val = 0;
942         }
943         end_val = end_val - start_val + reloc->offset;
944         if (reloc->section->parent) {
945                 data = reloc->section->parent->data;
946                 data += reloc->section->cur_offset;
947                 data += reloc->section_offset;
948                 vaddr = reloc->section->parent->virt_offset;
949                 vaddr += reloc->section->cur_offset;
950                 vaddr += reloc->section_offset;
951         } else {
952                 data = reloc->section->data;
953                 data += reloc->section_offset;
954                 vaddr = reloc->section->virt_offset;
955                 vaddr += reloc->section_offset;
956         }
957
958         *out_start_val = start_val;
959         *out_end_val = end_val;
960         *out_data = data;
961         *out_vaddr = vaddr;
962 }
963
964 #ifdef USE_ELF_RELA
965
966 static ElfRelocA*
967 resolve_relocations (MonoAotCompile *acfg)
968 {
969         BinReloc *reloc;
970         guint8 *data;
971         gsize end_val, start_val;
972         ElfRelocA *rr;
973         int i;
974         gsize vaddr;
975
976         rr = g_new0 (ElfRelocA, acfg->num_relocs);
977         i = 0;
978
979         for (reloc = acfg->relocations; reloc; reloc = reloc->next) {
980                 resolve_reloc (acfg, reloc, &data, &vaddr, &start_val, &end_val);
981                 /* FIXME: little endian */
982                 data [0] = end_val;
983                 data [1] = end_val >> 8;
984                 data [2] = end_val >> 16;
985                 data [3] = end_val >> 24;
986                 // FIXME:
987                 if (start_val == 0 && reloc->val1 [0] != '.') {
988                         rr [i].r_offset = vaddr;
989                         rr [i].r_info = R_X86_64_RELATIVE;
990                         rr [i].r_addend = end_val;
991                         ++i;
992                         g_assert (i <= acfg->num_relocs);
993                 }
994         }
995         return rr;
996 }
997
998 #else /* USE_ELF_RELA */
999
1000 static void
1001 do_reloc (MonoAotCompile *acfg, BinReloc *reloc, guint8 *data, gssize addr)
1002 {
1003 #ifdef __arm__
1004         /*
1005          * We use the official ARM relocation types, but implement only the stuff actually
1006          * needed by the code we generate.
1007          */
1008         switch (reloc->reloc_type) {
1009         case R_ARM_CALL: {
1010                 guint32 *code = (guint32*)(gpointer)data;
1011                 guint32 ins = *code;
1012                 int diff = addr;
1013
1014                 /* bl */
1015                 g_assert (data [3] == 0xeb);
1016                 if (diff >= 0 && diff <= 33554431) {
1017                         diff >>= 2;
1018                         ins = (ins & 0xff000000) | diff;
1019                         *code = ins;
1020                 } else if (diff <= 0 && diff >= -33554432) {
1021                         diff >>= 2;
1022                         ins = (ins & 0xff000000) | (diff & ~0xff000000);
1023                         *code = ins;
1024                 } else {
1025                         g_assert_not_reached ();
1026                 }
1027                 break;
1028         }
1029         case R_ARM_ALU_PC_G0_NC: {
1030                 /* Generated by emit_plt () */
1031                 guint8 *code = data;
1032                 guint32 val = addr;
1033
1034                 g_assert (val <= 0xffff);
1035                 ARM_ADD_REG_IMM (code, ARMREG_IP, ARMREG_PC, 0, 0);
1036                 ARM_ADD_REG_IMM (code, ARMREG_IP, ARMREG_IP, (val & 0xFF00) >> 8, 24);
1037                 ARM_LDR_IMM (code, ARMREG_PC, ARMREG_IP, val & 0xFF);
1038                 break;
1039         }               
1040         default:
1041                 g_assert_not_reached ();
1042         }
1043 #else
1044         g_assert_not_reached ();
1045 #endif
1046 }
1047
1048 static ElfReloc*
1049 resolve_relocations (MonoAotCompile *acfg)
1050 {
1051         BinReloc *reloc;
1052         guint8 *data;
1053         gsize end_val, start_val;
1054         ElfReloc *rr;
1055         int i;
1056         gsize vaddr;
1057
1058         rr = g_new0 (ElfReloc, acfg->num_relocs);
1059         i = 0;
1060
1061         for (reloc = acfg->relocations; reloc; reloc = reloc->next) {
1062                 resolve_reloc (acfg, reloc, &data, &vaddr, &start_val, &end_val);
1063                 /* FIXME: little endian */
1064                 if (reloc->reloc_type) {
1065                         /* Must be static */
1066                         g_assert (start_val > 0);
1067                         do_reloc (acfg, reloc, data, end_val);
1068                 } else {
1069                         data [0] = end_val;
1070                         data [1] = end_val >> 8;
1071                         data [2] = end_val >> 16;
1072                         data [3] = end_val >> 24;
1073                 }
1074                 // FIXME:
1075                 if (start_val == 0 && reloc->val1 [0] != '.') {
1076                         rr [i].r_offset = vaddr;
1077                         rr [i].r_info = R_386_RELATIVE;
1078                         ++i;
1079                         g_assert (i <= acfg->num_relocs);
1080                 }
1081         }
1082         return rr;
1083 }
1084
1085 #endif /* USE_ELF_RELA */
1086
1087 static int
1088 bin_writer_emit_writeout (MonoAotCompile *acfg)
1089 {
1090         char *outfile_name, *tmp_outfile_name;
1091         FILE *file;
1092         ElfHeader header;
1093         ElfProgHeader progh [3];
1094         ElfSectHeader secth [SECT_NUM];
1095 #ifdef USE_ELF_RELA
1096         ElfRelocA *relocs;
1097 #else
1098         ElfReloc *relocs;
1099 #endif
1100         ElfStrTable str_table = {NULL, NULL};
1101         ElfStrTable sh_str_table = {NULL, NULL};
1102         ElfStrTable dyn_str_table = {NULL, NULL};
1103         BinSection* all_sections [32];
1104         BinSection* sections [SECT_NUM];
1105         ElfSymbol *dynsym;
1106         ElfSymbol *symtab;
1107         ElfDynamic dynamic [14];
1108         int *hash;
1109         int i, num_sections, file_offset, virt_offset, size, num_symtab;
1110         int num_local_syms;
1111
1112         g_assert (!acfg->aot_opts.asm_only);
1113
1114         if (acfg->aot_opts.outfile)
1115                 outfile_name = g_strdup_printf ("%s", acfg->aot_opts.outfile);
1116         else
1117                 outfile_name = g_strdup_printf ("%s%s", acfg->image->name, SHARED_EXT);
1118
1119         tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
1120
1121         unlink (tmp_outfile_name);
1122         file = fopen (tmp_outfile_name, "w");
1123         g_assert (file);
1124
1125         /* Section headers */
1126         memset (&secth, 0, sizeof (secth));
1127         memset (&dynamic, 0, sizeof (dynamic));
1128         memset (&header, 0, sizeof (header));
1129
1130         for (i = 1; i < SECT_NUM; ++i) {
1131                 secth [i].sh_name = str_table_add (&sh_str_table, section_info [i].name);
1132                 secth [i].sh_type = section_info [i].type;
1133                 secth [i].sh_addralign = section_info [i].align;
1134                 secth [i].sh_flags = section_info [i].flags;
1135                 secth [i].sh_entsize = section_info [i].esize;
1136         }
1137         secth [SECT_DYNSYM].sh_info = SIZEOF_VOID_P == 4 ? 4 : 2;
1138         secth [SECT_SYMTAB].sh_info = SIZEOF_VOID_P == 4 ? 20 : 17;
1139         secth [SECT_HASH].sh_link = SECT_DYNSYM;
1140         secth [SECT_DYNSYM].sh_link = SECT_DYNSTR;
1141         secth [SECT_REL_DYN].sh_link = SECT_DYNSYM;
1142         secth [SECT_RELA_DYN].sh_link = SECT_DYNSYM;
1143         secth [SECT_DYNAMIC].sh_link = SECT_DYNSTR;
1144         secth [SECT_SYMTAB].sh_link = SECT_STRTAB;
1145
1146         num_sections = collect_sections (acfg, secth, all_sections, 8);
1147         hash = build_hash (acfg, num_sections, &dyn_str_table);
1148         num_symtab = hash [1]; /* FIXME */
1149         g_print ("num_sections: %d\n", num_sections);
1150         g_print ("dynsym: %d, dynstr size: %d\n", hash [1], (int)dyn_str_table.data->len);
1151         for (i = 0; i < num_sections; ++i) {
1152                 g_print ("section %s, size: %d, %x\n", all_sections [i]->name, all_sections [i]->cur_offset, all_sections [i]->cur_offset);
1153         }
1154
1155         /* Associate the bin sections with the ELF sections */
1156         memset (sections, 0, sizeof (sections));
1157         for (i = 0; i < num_sections; ++i) {
1158                 BinSection *sect = all_sections [i];
1159                 int j;
1160
1161                 for (j = 0; j < SECT_NUM; ++j) {
1162                         if (strcmp (sect->name, section_info [j].name) == 0) {
1163                                 sect->shidx = j;
1164                                 break;
1165                         }
1166                 }
1167
1168                 sections [all_sections [i]->shidx] = sect;
1169         }
1170
1171         /* at this point we know where in the file the first segment sections go */
1172         dynsym = collect_syms (acfg, hash, &dyn_str_table, NULL, NULL);
1173         num_local_syms = hash [1];
1174         symtab = collect_syms (acfg, NULL, &str_table, secth, &num_local_syms);
1175
1176         file_offset = virt_offset = sizeof (header) + sizeof (progh);
1177         secth [SECT_HASH].sh_addr = secth [SECT_HASH].sh_offset = file_offset;
1178         size = sizeof (int) * (2 + hash [0] + hash [1]);
1179         virt_offset = (file_offset += size);
1180         secth [SECT_HASH].sh_size = size;
1181         secth [SECT_DYNSYM].sh_addr = secth [SECT_DYNSYM].sh_offset = file_offset;
1182         size = sizeof (ElfSymbol) * hash [1];
1183         virt_offset = (file_offset += size);
1184         secth [SECT_DYNSYM].sh_size = size;
1185         secth [SECT_DYNSTR].sh_addr = secth [SECT_DYNSTR].sh_offset = file_offset;
1186         size = dyn_str_table.data->len;
1187         virt_offset = (file_offset += size);
1188         secth [SECT_DYNSTR].sh_size = size;
1189         file_offset += 4-1;
1190         file_offset &= ~(4-1);
1191         secth [SECT_REL_DYN].sh_addr = secth [SECT_REL_DYN].sh_offset = file_offset;
1192 #ifndef USE_ELF_RELA
1193         size = sizeof (ElfReloc) * acfg->num_relocs;
1194 #else
1195         size = 0;
1196 #endif
1197         virt_offset = (file_offset += size);
1198         secth [SECT_REL_DYN].sh_size = size;
1199         secth [SECT_RELA_DYN].sh_addr = secth [SECT_RELA_DYN].sh_offset = file_offset;
1200 #ifdef USE_ELF_RELA
1201         size = sizeof (ElfRelocA) * acfg->num_relocs;
1202 #else
1203         size = 0;
1204 #endif
1205         virt_offset = (file_offset += size);
1206         secth [SECT_RELA_DYN].sh_size = size;
1207
1208         file_offset = ALIGN_TO (file_offset, secth [SECT_TEXT].sh_addralign);
1209         virt_offset = file_offset;
1210         secth [SECT_TEXT].sh_addr = secth [SECT_TEXT].sh_offset = file_offset;
1211         if (sections [SECT_TEXT]) {
1212                 size = sections [SECT_TEXT]->cur_offset;
1213                 secth [SECT_TEXT].sh_size = size;
1214                 file_offset += size;
1215         }
1216
1217         file_offset = ALIGN_TO (file_offset, secth [SECT_DYNAMIC].sh_addralign);
1218         virt_offset = file_offset;
1219
1220         /* .dynamic, .got.plt, .data, .bss here */
1221         /* Have to increase the virt offset since these go to a separate segment */
1222         virt_offset += PAGESIZE;
1223         secth [SECT_DYNAMIC].sh_addr = virt_offset;
1224         secth [SECT_DYNAMIC].sh_offset = file_offset;
1225         size = sizeof (dynamic);
1226         secth [SECT_DYNAMIC].sh_size = size;
1227         file_offset += size;
1228         virt_offset += size;
1229
1230         file_offset = ALIGN_TO (file_offset, secth [SECT_GOT_PLT].sh_addralign);
1231         virt_offset = ALIGN_TO (virt_offset, secth [SECT_GOT_PLT].sh_addralign);
1232         secth [SECT_GOT_PLT].sh_addr = virt_offset;
1233         secth [SECT_GOT_PLT].sh_offset = file_offset;
1234         size = 12;
1235         secth [SECT_GOT_PLT].sh_size = size;
1236         file_offset += size;
1237         virt_offset += size;
1238
1239         file_offset = ALIGN_TO (file_offset, secth [SECT_DATA].sh_addralign);
1240         virt_offset = ALIGN_TO (virt_offset, secth [SECT_DATA].sh_addralign);
1241         secth [SECT_DATA].sh_addr = virt_offset;
1242         secth [SECT_DATA].sh_offset = file_offset;
1243         if (sections [SECT_DATA]) {
1244                 size = sections [SECT_DATA]->cur_offset;
1245                 secth [SECT_DATA].sh_size = size;
1246                 file_offset += size;
1247                 virt_offset += size;
1248         }
1249
1250         file_offset = ALIGN_TO (file_offset, secth [SECT_BSS].sh_addralign);
1251         virt_offset = ALIGN_TO (virt_offset, secth [SECT_BSS].sh_addralign);
1252         secth [SECT_BSS].sh_addr = virt_offset;
1253         secth [SECT_BSS].sh_offset = file_offset;
1254         if (sections [SECT_BSS]) {
1255                 size = sections [SECT_BSS]->cur_offset;
1256                 secth [SECT_BSS].sh_size = size;
1257         }
1258
1259         /* virtual doesn't matter anymore */
1260         file_offset = ALIGN_TO (file_offset, secth [SECT_DEBUG_FRAME].sh_addralign);
1261         secth [SECT_DEBUG_FRAME].sh_offset = file_offset;
1262         if (sections [SECT_DEBUG_FRAME])
1263                 size = sections [SECT_DEBUG_FRAME]->cur_offset;
1264         else
1265                 size = 0;
1266         secth [SECT_DEBUG_FRAME].sh_size = size;
1267         file_offset += size;
1268
1269         secth [SECT_DEBUG_INFO].sh_offset = file_offset;
1270         if (sections [SECT_DEBUG_INFO])
1271                 size = sections [SECT_DEBUG_INFO]->cur_offset;
1272         else
1273                 size = 0;
1274         secth [SECT_DEBUG_INFO].sh_size = size;
1275         file_offset += size;
1276
1277         secth [SECT_DEBUG_ABBREV].sh_offset = file_offset;
1278         if (sections [SECT_DEBUG_ABBREV])
1279                 size = sections [SECT_DEBUG_ABBREV]->cur_offset;
1280         else
1281                 size = 0;
1282         secth [SECT_DEBUG_ABBREV].sh_size = size;
1283         file_offset += size;
1284
1285         file_offset = ALIGN_TO (file_offset, secth [SECT_SHSTRTAB].sh_addralign);
1286         secth [SECT_SHSTRTAB].sh_offset = file_offset;
1287         size = sh_str_table.data->len;
1288         secth [SECT_SHSTRTAB].sh_size = size;
1289         file_offset += size;
1290
1291         file_offset = ALIGN_TO (file_offset, secth [SECT_SYMTAB].sh_addralign);
1292         secth [SECT_SYMTAB].sh_offset = file_offset;
1293         size = sizeof (ElfSymbol) * num_local_syms;
1294         secth [SECT_SYMTAB].sh_size = size;
1295         file_offset += size;
1296
1297         file_offset = ALIGN_TO (file_offset, secth [SECT_STRTAB].sh_addralign);
1298         secth [SECT_STRTAB].sh_offset = file_offset;
1299         size = str_table.data->len;
1300         secth [SECT_STRTAB].sh_size = size;
1301         file_offset += size;
1302
1303         file_offset += 4-1;
1304         file_offset &= ~(4-1);
1305
1306         header.e_ident [EI_MAG0] = ELFMAG0;
1307         header.e_ident [EI_MAG1] = ELFMAG1;
1308         header.e_ident [EI_MAG2] = ELFMAG2;
1309         header.e_ident [EI_MAG3] = ELFMAG3;
1310         header.e_ident [EI_CLASS] = SIZEOF_VOID_P == 4 ? ELFCLASS32 : ELFCLASS64;
1311         header.e_ident [EI_DATA] = ELFDATA2LSB;
1312         header.e_ident [EI_VERSION] = EV_CURRENT;
1313         header.e_ident [EI_OSABI] = ELFOSABI_NONE;
1314         header.e_ident [EI_ABIVERSION] = 0;
1315         for (i = EI_PAD; i < EI_NIDENT; ++i)
1316                 header.e_ident [i] = 0;
1317
1318         header.e_type = ET_DYN;
1319 #if defined(__i386__)
1320         header.e_machine = EM_386;
1321 #elif defined(__x86_64__)
1322         header.e_machine = EM_X86_64;
1323 #elif defined(__arm__)
1324         header.e_machine = EM_ARM;
1325 #else
1326         g_assert_not_reached ();
1327 #endif
1328         header.e_version = 1;
1329
1330         header.e_phoff = sizeof (header);
1331         header.e_ehsize = sizeof (header);
1332         header.e_phentsize = sizeof (ElfProgHeader);
1333         header.e_phnum = 3;
1334         header.e_entry = secth [SECT_TEXT].sh_addr;
1335         header.e_shstrndx = SECT_SHSTRTAB;
1336         header.e_shentsize = sizeof (ElfSectHeader);
1337         header.e_shnum = SECT_NUM;
1338         header.e_shoff = file_offset;
1339
1340         /* dynamic data */
1341         i = 0;
1342         dynamic [i].d_tag = DT_HASH;
1343         dynamic [i].d_un.d_val = secth [SECT_HASH].sh_offset;
1344         ++i;
1345         dynamic [i].d_tag = DT_STRTAB;
1346         dynamic [i].d_un.d_val = secth [SECT_DYNSTR].sh_offset;
1347         ++i;
1348         dynamic [i].d_tag = DT_SYMTAB;
1349         dynamic [i].d_un.d_val = secth [SECT_DYNSYM].sh_offset;
1350         ++i;
1351         dynamic [i].d_tag = DT_STRSZ;
1352         dynamic [i].d_un.d_val = dyn_str_table.data->len;
1353         ++i;
1354         dynamic [i].d_tag = DT_SYMENT;
1355         dynamic [i].d_un.d_val = sizeof (ElfSymbol);
1356         ++i;
1357 #ifdef USE_ELF_RELA
1358         dynamic [i].d_tag = DT_RELA;
1359         dynamic [i].d_un.d_val = secth [SECT_RELA_DYN].sh_offset;
1360         ++i;
1361         dynamic [i].d_tag = DT_RELASZ;
1362         dynamic [i].d_un.d_val = secth [SECT_RELA_DYN].sh_size;
1363         ++i;
1364         dynamic [i].d_tag = DT_RELAENT;
1365         dynamic [i].d_un.d_val = sizeof (ElfRelocA);
1366         ++i;
1367 #else
1368         dynamic [i].d_tag = DT_REL;
1369         dynamic [i].d_un.d_val = secth [SECT_REL_DYN].sh_offset;
1370         ++i;
1371         dynamic [i].d_tag = DT_RELSZ;
1372         dynamic [i].d_un.d_val = secth [SECT_REL_DYN].sh_size;
1373         ++i;
1374         dynamic [i].d_tag = DT_RELENT;
1375         dynamic [i].d_un.d_val = sizeof (ElfReloc);
1376         ++i;
1377 #endif
1378         dynamic [i].d_tag = DT_RELCOUNT;
1379         dynamic [i].d_un.d_val = acfg->num_relocs;
1380         ++i;
1381
1382         /* Program header */
1383         memset (&progh, 0, sizeof (progh));
1384         progh [0].p_type = PT_LOAD;
1385         progh [0].p_filesz = progh [0].p_memsz = secth [SECT_DYNAMIC].sh_offset;
1386         progh [0].p_align = 4096;
1387         progh [0].p_flags = 5;
1388
1389         progh [1].p_type = PT_LOAD;
1390         progh [1].p_offset = secth [SECT_DYNAMIC].sh_offset;
1391         progh [1].p_vaddr = progh [1].p_paddr = secth [SECT_DYNAMIC].sh_addr;
1392         progh [1].p_filesz = secth [SECT_BSS].sh_offset  - secth [SECT_DYNAMIC].sh_offset;
1393         progh [1].p_memsz = secth [SECT_BSS].sh_addr + secth [SECT_BSS].sh_size - secth [SECT_DYNAMIC].sh_addr;
1394         progh [1].p_align = 4096;
1395         progh [1].p_flags = 6;
1396
1397         progh [2].p_type = PT_DYNAMIC;
1398         progh [2].p_offset = secth [SECT_DYNAMIC].sh_offset;
1399         progh [2].p_vaddr = progh [2].p_paddr = secth [SECT_DYNAMIC].sh_addr;
1400         progh [2].p_filesz = progh [2].p_memsz = secth [SECT_DYNAMIC].sh_size;
1401         progh [2].p_align = SIZEOF_VOID_P;
1402         progh [2].p_flags = 6;
1403
1404         /* Compute the addresses of the bin sections, so relocation can be done */
1405         for (i = 0; i < SECT_NUM; ++i) {
1406                 if (sections [i]) {
1407                         sections [i]->file_offset = secth [i].sh_offset;
1408                         sections [i]->virt_offset = secth [i].sh_addr;
1409                 }
1410         }
1411
1412         reloc_symbols (acfg, dynsym, secth, &dyn_str_table, TRUE);
1413         reloc_symbols (acfg, symtab, secth, &str_table, FALSE);
1414         relocs = resolve_relocations (acfg);
1415
1416         fwrite (&header, sizeof (header), 1, file);
1417         fwrite (&progh, sizeof (progh), 1, file);
1418         fwrite (hash, sizeof (int) * (hash [0] + hash [1] + 2), 1, file);
1419         fwrite (dynsym, sizeof (ElfSymbol) * hash [1], 1, file);
1420         fwrite (dyn_str_table.data->str, dyn_str_table.data->len, 1, file);
1421         /* .rel.dyn */
1422         fseek (file, secth [SECT_REL_DYN].sh_offset, SEEK_SET);
1423         fwrite (relocs, sizeof (ElfReloc), acfg->num_relocs, file);
1424
1425         /* .rela.dyn */
1426         fseek (file, secth [SECT_RELA_DYN].sh_offset, SEEK_SET);
1427         fwrite (relocs, secth [SECT_RELA_DYN].sh_size, 1, file);
1428
1429         /* .text */
1430         if (sections [SECT_TEXT]) {
1431                 fseek (file, secth [SECT_TEXT].sh_offset, SEEK_SET);
1432                 fwrite (sections [SECT_TEXT]->data, sections [SECT_TEXT]->cur_offset, 1, file);
1433         }
1434         /* .dynamic */
1435         fwrite (dynamic, sizeof (dynamic), 1, file);
1436
1437         /* .got.plt */
1438         size = secth [SECT_DYNAMIC].sh_addr;
1439         fwrite (&size, sizeof (size), 1, file);
1440
1441         /* .data */
1442         if (sections [SECT_DATA]) {
1443                 fseek (file, secth [SECT_DATA].sh_offset, SEEK_SET);
1444                 fwrite (sections [SECT_DATA]->data, sections [SECT_DATA]->cur_offset, 1, file);
1445         }
1446
1447         fseek (file, secth [SECT_DEBUG_FRAME].sh_offset, SEEK_SET);
1448         if (sections [SECT_DEBUG_FRAME])
1449                 fwrite (sections [SECT_DEBUG_FRAME]->data, sections [SECT_DEBUG_FRAME]->cur_offset, 1, file);
1450         fseek (file, secth [SECT_DEBUG_INFO].sh_offset, SEEK_SET);
1451         if (sections [SECT_DEBUG_INFO])
1452                 fwrite (sections [SECT_DEBUG_INFO]->data, sections [SECT_DEBUG_INFO]->cur_offset, 1, file);
1453         fseek (file, secth [SECT_DEBUG_ABBREV].sh_offset, SEEK_SET);
1454         if (sections [SECT_DEBUG_ABBREV])
1455                 fwrite (sections [SECT_DEBUG_ABBREV]->data, sections [SECT_DEBUG_ABBREV]->cur_offset, 1, file);
1456         fseek (file, secth [SECT_SHSTRTAB].sh_offset, SEEK_SET);
1457         fwrite (sh_str_table.data->str, sh_str_table.data->len, 1, file);
1458         fseek (file, secth [SECT_SYMTAB].sh_offset, SEEK_SET);
1459         fwrite (symtab, sizeof (ElfSymbol) * num_local_syms, 1, file);
1460         fseek (file, secth [SECT_STRTAB].sh_offset, SEEK_SET);
1461         fwrite (str_table.data->str, str_table.data->len, 1, file);
1462         /*g_print ("file_offset %d vs %d\n", file_offset, ftell (file));*/
1463         /*g_assert (file_offset >= ftell (file));*/
1464         fseek (file, file_offset, SEEK_SET);
1465         fwrite (&secth, sizeof (secth), 1, file);
1466         fclose (file);
1467         rename (tmp_outfile_name, outfile_name);
1468
1469         g_free (tmp_outfile_name);
1470         g_free (outfile_name);
1471
1472         return 0;
1473 }
1474
1475 #endif /* USE_ELF_WRITER */
1476
1477 #endif /* USE_BIN_WRITER */
1478
1479 /* ASM WRITER */
1480
1481 static void
1482 asm_writer_emit_start (MonoAotCompile *acfg)
1483 {
1484         if (acfg->aot_opts.asm_only) {
1485                 if (acfg->aot_opts.outfile)
1486                         acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
1487                 else
1488                         acfg->tmpfname = g_strdup_printf ("%s.s", acfg->image->name);
1489                 acfg->fp = fopen (acfg->tmpfname, "w+");
1490         } else {
1491                 int i = g_file_open_tmp ("mono_aot_XXXXXX", &acfg->tmpfname, NULL);
1492                 acfg->fp = fdopen (i, "w+");
1493         }
1494         g_assert (acfg->fp);
1495 }
1496
1497 static void
1498 asm_writer_emit_unset_mode (MonoAotCompile *acfg)
1499 {
1500         if (acfg->mode == EMIT_NONE)
1501                 return;
1502         fprintf (acfg->fp, "\n");
1503         acfg->mode = EMIT_NONE;
1504 }
1505
1506 static void
1507 asm_writer_emit_section_change (MonoAotCompile *acfg, const char *section_name, int subsection_index)
1508 {
1509         asm_writer_emit_unset_mode (acfg);
1510 #if defined(PLATFORM_WIN32)
1511         fprintf (acfg->fp, ".section %s\n", section_name);
1512 #elif defined(__MACH__)
1513         if (strcmp(section_name, ".bss") == 0)
1514                 fprintf (acfg->fp, "%s\n", ".data");
1515         else
1516                 fprintf (acfg->fp, "%s\n", section_name);
1517 #elif defined(sparc) || defined(__arm__)
1518         /* For solaris as, GNU as should accept the same */
1519         fprintf (acfg->fp, ".section \"%s\"\n", section_name);
1520 #else
1521         if (!strcmp (section_name, ".text") || !strcmp (section_name, ".data") || !strcmp (section_name, ".bss")) {
1522                 fprintf (acfg->fp, "%s %d\n", section_name, subsection_index);
1523         } else {
1524                 fprintf (acfg->fp, ".section \"%s\"\n", section_name);
1525                 fprintf (acfg->fp, ".subsection %d\n", subsection_index);
1526         }
1527 #endif
1528 }
1529
1530 static void
1531 asm_writer_emit_symbol_type (MonoAotCompile *acfg, const char *name, gboolean func)
1532 {
1533         const char *stype;
1534
1535         if (func)
1536                 stype = "function";
1537         else
1538                 stype = "object";
1539
1540         asm_writer_emit_unset_mode (acfg);
1541 #if defined(__MACH__)
1542
1543 #elif defined(sparc) || defined(__arm__)
1544         fprintf (acfg->fp, "\t.type %s,#%s\n", name, stype);
1545 #elif defined(PLATFORM_WIN32)
1546
1547 #elif defined(__x86_64__) || defined(__i386__)
1548         fprintf (acfg->fp, "\t.type %s,@%s\n", name, stype);
1549 #else
1550         fprintf (acfg->fp, "\t.type %s,@%s\n", name, stype);
1551 #endif
1552 }
1553
1554 static void
1555 asm_writer_emit_global_inner (MonoAotCompile *acfg, const char *name, gboolean func)
1556 {
1557         asm_writer_emit_unset_mode (acfg);
1558 #if  (defined(__ppc__) && defined(__MACH__)) || defined(PLATFORM_WIN32)
1559     // mach-o always uses a '_' prefix.
1560         fprintf (acfg->fp, "\t.globl _%s\n", name);
1561 #else
1562         fprintf (acfg->fp, "\t.globl %s\n", name);
1563 #endif
1564
1565         asm_writer_emit_symbol_type (acfg, name, func);
1566 }
1567
1568 static void
1569 asm_writer_emit_label (MonoAotCompile *acfg, const char *name)
1570 {
1571         asm_writer_emit_unset_mode (acfg);
1572 #if (defined(__ppc__) && defined(__MACH__)) || defined(PLATFORM_WIN32)
1573     // mach-o always uses a '_' prefix.
1574         fprintf (acfg->fp, "_%s:\n", name);
1575 #else
1576         fprintf (acfg->fp, "%s:\n", name);
1577 #endif
1578
1579 #if defined(PLATFORM_WIN32)
1580         /* Emit a normal label too */
1581         fprintf (acfg->fp, "%s:\n", name);
1582 #endif
1583 }
1584
1585 static void
1586 asm_writer_emit_string (MonoAotCompile *acfg, const char *value)
1587 {
1588         asm_writer_emit_unset_mode (acfg);
1589         fprintf (acfg->fp, "\t%s \"%s\"\n", AS_STRING_DIRECTIVE, value);
1590 }
1591
1592 static void
1593 asm_writer_emit_line (MonoAotCompile *acfg)
1594 {
1595         asm_writer_emit_unset_mode (acfg);
1596         fprintf (acfg->fp, "\n");
1597 }
1598
1599 static void 
1600 asm_writer_emit_alignment (MonoAotCompile *acfg, int size)
1601 {
1602         asm_writer_emit_unset_mode (acfg);
1603 #if defined(__arm__)
1604         fprintf (acfg->fp, "\t.align %d\n", ilog2 (size));
1605 #elif defined(__ppc__) && defined(__MACH__)
1606         // the mach-o assembler specifies alignments as powers of 2.
1607         fprintf (acfg->fp, "\t.align %d\t; ilog2\n", ilog2(size));
1608 #elif defined(__powerpc__)
1609         /* ignore on linux/ppc */
1610 #else
1611         fprintf (acfg->fp, "\t.align %d\n", size);
1612 #endif
1613 }
1614
1615 static void
1616 asm_writer_emit_pointer (MonoAotCompile *acfg, const char *target)
1617 {
1618         asm_writer_emit_unset_mode (acfg);
1619         asm_writer_emit_alignment (acfg, sizeof (gpointer));
1620 #if defined(__x86_64__)
1621         fprintf (acfg->fp, "\t.quad %s\n", target ? target : "0");
1622 #elif defined(sparc) && SIZEOF_VOID_P == 8
1623         fprintf (acfg->fp, "\t.xword %s\n", target ? target : "0");
1624 #else
1625         fprintf (acfg->fp, "\t.long %s\n", target ? target : "0");
1626 #endif
1627 }
1628
1629 static char *byte_to_str;
1630
1631 static void
1632 asm_writer_emit_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
1633 {
1634         int i;
1635         if (acfg->mode != EMIT_BYTE) {
1636                 acfg->mode = EMIT_BYTE;
1637                 acfg->col_count = 0;
1638         }
1639
1640         if (byte_to_str == NULL) {
1641                 byte_to_str = g_new0 (char, 256 * 8);
1642                 for (i = 0; i < 256; ++i) {
1643                         sprintf (byte_to_str + (i * 8), ",%d", i);
1644                 }
1645         }
1646
1647         for (i = 0; i < size; ++i, ++acfg->col_count) {
1648                 if ((acfg->col_count % 32) == 0)
1649                         fprintf (acfg->fp, "\n\t.byte %d", buf [i]);
1650                 else
1651                         fputs (byte_to_str + (buf [i] * 8), acfg->fp);
1652         }
1653 }
1654
1655 static inline void
1656 asm_writer_emit_int16 (MonoAotCompile *acfg, int value)
1657 {
1658         if (acfg->mode != EMIT_WORD) {
1659                 acfg->mode = EMIT_WORD;
1660                 acfg->col_count = 0;
1661         }
1662         if ((acfg->col_count++ % 8) == 0)
1663 #if defined(__MACH__)
1664                 fprintf (acfg->fp, "\n\t.short ");
1665 #elif defined(__arm__)
1666                 /* FIXME: Use .hword on other archs as well */
1667                 fprintf (acfg->fp, "\n\t.hword ");
1668 #else
1669                 fprintf (acfg->fp, "\n\t.word ");
1670 #endif
1671         else
1672                 fprintf (acfg->fp, ", ");
1673         fprintf (acfg->fp, "%d", value);
1674 }
1675
1676 static inline void
1677 asm_writer_emit_int32 (MonoAotCompile *acfg, int value)
1678 {
1679         if (acfg->mode != EMIT_LONG) {
1680                 acfg->mode = EMIT_LONG;
1681                 acfg->col_count = 0;
1682         }
1683         if ((acfg->col_count++ % 8) == 0)
1684                 fprintf (acfg->fp, "\n\t.long ");
1685         else
1686                 fprintf (acfg->fp, ",");
1687         fprintf (acfg->fp, "%d", value);
1688 }
1689
1690 static void
1691 asm_writer_emit_symbol_diff (MonoAotCompile *acfg, const char *end, const char* start, int offset)
1692 {
1693         if (acfg->mode != EMIT_LONG) {
1694                 acfg->mode = EMIT_LONG;
1695                 acfg->col_count = 0;
1696         }
1697         if ((acfg->col_count++ % 8) == 0)
1698                 fprintf (acfg->fp, "\n\t.long ");
1699         else
1700                 fprintf (acfg->fp, ",");
1701         if (offset > 0)
1702                 fprintf (acfg->fp, "%s - %s + %d", end, start, offset);
1703         else if (offset < 0)
1704                 fprintf (acfg->fp, "%s - %s %d", end, start, offset);
1705         else
1706                 fprintf (acfg->fp, "%s - %s", end, start);
1707 }
1708
1709 static void
1710 asm_writer_emit_zero_bytes (MonoAotCompile *acfg, int num)
1711 {
1712         asm_writer_emit_unset_mode (acfg);
1713 #if defined(__MACH__)
1714         fprintf (acfg->fp, "\t.space %d\n", num);
1715 #else
1716         fprintf (acfg->fp, "\t.skip %d\n", num);
1717 #endif
1718 }
1719
1720 static int
1721 asm_writer_emit_writeout (MonoAotCompile *acfg)
1722 {
1723         char *command, *objfile;
1724         char *outfile_name, *tmp_outfile_name;
1725
1726         fclose (acfg->fp);
1727
1728 #if defined(__x86_64__)
1729 #define AS_OPTIONS "--64"
1730 #elif defined(sparc) && SIZEOF_VOID_P == 8
1731 #define AS_OPTIONS "-xarch=v9"
1732 #else
1733 #define AS_OPTIONS ""
1734 #endif
1735
1736         if (acfg->aot_opts.asm_only) {
1737                 printf ("Output file: '%s'.\n", acfg->tmpfname);
1738                 if (acfg->aot_opts.static_link)
1739                         printf ("Linking symbol: '%s'.\n", acfg->static_linking_symbol);
1740                 return 0;
1741         }
1742
1743         if (acfg->aot_opts.static_link) {
1744                 if (acfg->aot_opts.outfile)
1745                         objfile = g_strdup_printf ("%s", acfg->aot_opts.outfile);
1746                 else
1747                         objfile = g_strdup_printf ("%s.o", acfg->image->name);
1748         } else {
1749                 objfile = g_strdup_printf ("%s.o", acfg->tmpfname);
1750         }
1751         command = g_strdup_printf ("as %s %s -o %s", AS_OPTIONS, acfg->tmpfname, objfile);
1752         printf ("Executing the native assembler: %s\n", command);
1753         if (system (command) != 0) {
1754                 g_free (command);
1755                 g_free (objfile);
1756                 return 1;
1757         }
1758
1759         g_free (command);
1760
1761         if (acfg->aot_opts.static_link) {
1762                 printf ("Output file: '%s'.\n", objfile);
1763                 printf ("Linking symbol: '%s'.\n", acfg->static_linking_symbol);
1764                 g_free (objfile);
1765                 return 0;
1766         }
1767
1768         if (acfg->aot_opts.outfile)
1769                 outfile_name = g_strdup_printf ("%s", acfg->aot_opts.outfile);
1770         else
1771                 outfile_name = g_strdup_printf ("%s%s", acfg->image->name, SHARED_EXT);
1772
1773         tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
1774
1775 #if defined(sparc)
1776         command = g_strdup_printf ("ld -shared -G -o %s %s.o", outfile_name, acfg->tmpfname);
1777 #elif defined(__ppc__) && defined(__MACH__)
1778         command = g_strdup_printf ("gcc -dynamiclib -o %s %s.o", outfile_name, acfg->tmpfname);
1779 #elif defined(PLATFORM_WIN32)
1780         command = g_strdup_printf ("gcc -shared --dll -mno-cygwin -o %s %s.o", outfile_name, acfg->tmpfname);
1781 #else
1782         if (acfg->aot_opts.no_dlsym) {
1783                 /* 
1784                  * Need to link using gcc so our ctor function gets called.
1785                  */
1786                 command = g_strdup_printf ("gcc -shared -o %s %s.o", outfile_name, acfg->tmpfname);
1787         } else {
1788                 command = g_strdup_printf ("ld -shared -o %s %s.o", outfile_name, acfg->tmpfname);
1789         }
1790 #endif
1791         printf ("Executing the native linker: %s\n", command);
1792         if (system (command) != 0) {
1793                 g_free (tmp_outfile_name);
1794                 g_free (outfile_name);
1795                 g_free (command);
1796                 g_free (objfile);
1797                 return 1;
1798         }
1799
1800         g_free (command);
1801         unlink (objfile);
1802         /*com = g_strdup_printf ("strip --strip-unneeded %s%s", acfg->image->name, SHARED_EXT);
1803         printf ("Stripping the binary: %s\n", com);
1804         system (com);
1805         g_free (com);*/
1806
1807         rename (tmp_outfile_name, outfile_name);
1808
1809         g_free (tmp_outfile_name);
1810         g_free (outfile_name);
1811         g_free (objfile);
1812
1813         if (acfg->aot_opts.save_temps)
1814                 printf ("Retained input file.\n");
1815         else
1816                 unlink (acfg->tmpfname);
1817
1818         return 0;
1819 }
1820
1821 /* EMIT FUNCTIONS */
1822
1823 static void emit_start (MonoAotCompile *acfg)
1824 {
1825 #ifdef USE_BIN_WRITER
1826         if (acfg->use_bin_writer)
1827                 bin_writer_emit_start (acfg);
1828         else
1829                 asm_writer_emit_start (acfg);
1830 #else
1831         asm_writer_emit_start (acfg);
1832 #endif
1833 }
1834
1835 static void emit_section_change (MonoAotCompile *acfg, const char *section_name, int subsection_index)
1836 {
1837 #ifdef USE_BIN_WRITER
1838         if (acfg->use_bin_writer)
1839                 bin_writer_emit_section_change (acfg, section_name, subsection_index);
1840         else
1841                 asm_writer_emit_section_change (acfg, section_name, subsection_index);
1842 #else
1843         asm_writer_emit_section_change (acfg, section_name, subsection_index);
1844 #endif
1845 }
1846
1847 static void emit_global_inner (MonoAotCompile *acfg, const char *name, gboolean func)
1848 {
1849 #ifdef USE_BIN_WRITER
1850         if (acfg->use_bin_writer)
1851                 bin_writer_emit_global_inner (acfg, name, func);
1852         else
1853                 asm_writer_emit_global_inner (acfg, name, func);
1854 #else
1855         asm_writer_emit_global_inner (acfg, name, func);
1856 #endif
1857 }
1858
1859 static void emit_local_symbol (MonoAotCompile *acfg, const char *name, const char *end_label, gboolean func)
1860 {
1861 #ifdef USE_BIN_WRITER
1862         if (acfg->use_bin_writer)
1863                 bin_writer_emit_local_symbol (acfg, name, end_label, func);
1864         else
1865                 g_assert_not_reached ();
1866         //asm_writer_emit_local_symbol (acfg, name, end_label, func);
1867 #else
1868         g_assert_not_reached ();
1869         //asm_writer_emit_local_symbol (acfg, name, end_label, func);
1870 #endif
1871 }
1872
1873 static void emit_label (MonoAotCompile *acfg, const char *name)
1874 {
1875 #ifdef USE_BIN_WRITER
1876         if (acfg->use_bin_writer)
1877                 bin_writer_emit_label (acfg, name);
1878         else
1879                 asm_writer_emit_label (acfg, name);
1880 #else
1881         asm_writer_emit_label (acfg, name);
1882 #endif
1883 }
1884
1885 static void emit_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
1886 {
1887 #ifdef USE_BIN_WRITER
1888         if (acfg->use_bin_writer)
1889                 bin_writer_emit_bytes (acfg, buf, size);
1890         else
1891                 asm_writer_emit_bytes (acfg, buf, size);
1892 #else
1893         asm_writer_emit_bytes (acfg, buf, size);
1894 #endif
1895 }
1896
1897 static void emit_string (MonoAotCompile *acfg, const char *value)
1898 {
1899 #ifdef USE_BIN_WRITER
1900         if (acfg->use_bin_writer)
1901                 bin_writer_emit_string (acfg, value);
1902         else
1903                 asm_writer_emit_string (acfg, value);
1904 #else
1905         asm_writer_emit_string (acfg, value);
1906 #endif
1907 }
1908
1909 static void emit_line (MonoAotCompile *acfg)
1910 {
1911 #ifdef USE_BIN_WRITER
1912         if (acfg->use_bin_writer)
1913                 bin_writer_emit_line (acfg);
1914         else
1915                 asm_writer_emit_line (acfg);
1916 #else
1917                 asm_writer_emit_line (acfg);
1918 #endif
1919 }
1920
1921 static void emit_alignment (MonoAotCompile *acfg, int size)
1922 {
1923 #ifdef USE_BIN_WRITER
1924         if (acfg->use_bin_writer)
1925                 bin_writer_emit_alignment (acfg, size);
1926         else
1927                 asm_writer_emit_alignment (acfg, size);
1928 #else
1929         asm_writer_emit_alignment (acfg, size);
1930 #endif
1931 }
1932
1933 static void emit_pointer_unaligned (MonoAotCompile *acfg, const char *target)
1934 {
1935 #ifdef USE_BIN_WRITER
1936         if (acfg->use_bin_writer)
1937                 bin_writer_emit_pointer_unaligned (acfg, target);
1938         else
1939                 g_assert_not_reached ();
1940         //asm_writer_emit_pointer_unaligned (acfg, target);
1941 #else
1942         g_assert_not_reached ();
1943         //asm_writer_emit_pointer_unaligned (acfg, target);
1944 #endif
1945 }
1946
1947 static void emit_pointer (MonoAotCompile *acfg, const char *target)
1948 {
1949 #ifdef USE_BIN_WRITER
1950         if (acfg->use_bin_writer)
1951                 bin_writer_emit_pointer (acfg, target);
1952         else
1953                 asm_writer_emit_pointer (acfg, target);
1954 #else
1955         asm_writer_emit_pointer (acfg, target);
1956 #endif
1957 }
1958
1959 static void emit_int16 (MonoAotCompile *acfg, int value)
1960 {
1961 #ifdef USE_BIN_WRITER
1962         if (acfg->use_bin_writer)
1963                 bin_writer_emit_int16 (acfg, value);
1964         else
1965                 asm_writer_emit_int16 (acfg, value);
1966 #else
1967         asm_writer_emit_int16 (acfg, value);
1968 #endif
1969 }
1970
1971 static void emit_int32 (MonoAotCompile *acfg, int value)
1972 {
1973 #ifdef USE_BIN_WRITER
1974         if (acfg->use_bin_writer)
1975                 bin_writer_emit_int32 (acfg, value);
1976         else
1977                 asm_writer_emit_int32 (acfg, value);
1978 #else
1979         asm_writer_emit_int32 (acfg, value);
1980 #endif
1981 }
1982
1983 static void emit_symbol_diff (MonoAotCompile *acfg, const char *end, const char* start, int offset)
1984 {
1985 #ifdef USE_BIN_WRITER
1986         if (acfg->use_bin_writer)
1987                 bin_writer_emit_symbol_diff (acfg, end, start, offset);
1988         else
1989                 asm_writer_emit_symbol_diff (acfg, end, start, offset);
1990 #else
1991         asm_writer_emit_symbol_diff (acfg, end, start, offset);
1992 #endif
1993 }
1994
1995 static void emit_zero_bytes (MonoAotCompile *acfg, int num)
1996 {
1997 #ifdef USE_BIN_WRITER
1998         if (acfg->use_bin_writer)
1999                 bin_writer_emit_zero_bytes (acfg, num);
2000         else
2001                 asm_writer_emit_zero_bytes (acfg, num);
2002 #else
2003         asm_writer_emit_zero_bytes (acfg, num);
2004 #endif
2005 }
2006
2007 static int
2008 emit_writeout (MonoAotCompile *acfg)
2009 {
2010 #ifdef USE_BIN_WRITER
2011         if (acfg->use_bin_writer)
2012                 return bin_writer_emit_writeout (acfg);
2013         else
2014                 return asm_writer_emit_writeout (acfg);
2015 #else
2016                 return asm_writer_emit_writeout (acfg);
2017 #endif
2018 }
2019
2020 static void
2021 emit_global (MonoAotCompile *acfg, const char *name, gboolean func)
2022 {
2023         if (acfg->aot_opts.no_dlsym) {
2024                 g_ptr_array_add (acfg->globals, g_strdup (name));
2025         } else {
2026                 emit_global_inner (acfg, name, func);
2027         }
2028 }
2029
2030 static void
2031 emit_byte (MonoAotCompile *acfg, guint8 val)
2032 {
2033         emit_bytes (acfg, &val, 1);
2034 }
2035
2036 static void
2037 emit_string_symbol (MonoAotCompile *acfg, const char *name, const char *value)
2038 {
2039         emit_section_change (acfg, ".text", 1);
2040         emit_global (acfg, name, FALSE);
2041         emit_label (acfg, name);
2042         emit_string (acfg, value);
2043 }
2044
2045 /* AOT COMPILER */
2046
2047 static guint32
2048 mono_get_field_token (MonoClassField *field) 
2049 {
2050         MonoClass *klass = field->parent;
2051         int i;
2052
2053         for (i = 0; i < klass->field.count; ++i) {
2054                 if (field == &klass->fields [i])
2055                         return MONO_TOKEN_FIELD_DEF | (klass->field.first + 1 + i);
2056         }
2057
2058         g_assert_not_reached ();
2059         return 0;
2060 }
2061
2062 static inline void
2063 encode_value (gint32 value, guint8 *buf, guint8 **endbuf)
2064 {
2065         guint8 *p = buf;
2066
2067         //printf ("ENCODE: %d 0x%x.\n", value, value);
2068
2069         /* 
2070          * Same encoding as the one used in the metadata, extended to handle values
2071          * greater than 0x1fffffff.
2072          */
2073         if ((value >= 0) && (value <= 127))
2074                 *p++ = value;
2075         else if ((value >= 0) && (value <= 16383)) {
2076                 p [0] = 0x80 | (value >> 8);
2077                 p [1] = value & 0xff;
2078                 p += 2;
2079         } else if ((value >= 0) && (value <= 0x1fffffff)) {
2080                 p [0] = (value >> 24) | 0xc0;
2081                 p [1] = (value >> 16) & 0xff;
2082                 p [2] = (value >> 8) & 0xff;
2083                 p [3] = value & 0xff;
2084                 p += 4;
2085         }
2086         else {
2087                 p [0] = 0xff;
2088                 p [1] = (value >> 24) & 0xff;
2089                 p [2] = (value >> 16) & 0xff;
2090                 p [3] = (value >> 8) & 0xff;
2091                 p [4] = value & 0xff;
2092                 p += 5;
2093         }
2094         if (endbuf)
2095                 *endbuf = p;
2096 }
2097
2098 static guint32
2099 get_image_index (MonoAotCompile *cfg, MonoImage *image)
2100 {
2101         guint32 index;
2102
2103         index = GPOINTER_TO_UINT (g_hash_table_lookup (cfg->image_hash, image));
2104         if (index)
2105                 return index - 1;
2106         else {
2107                 index = g_hash_table_size (cfg->image_hash);
2108                 g_hash_table_insert (cfg->image_hash, image, GUINT_TO_POINTER (index + 1));
2109                 g_ptr_array_add (cfg->image_table, image);
2110                 return index;
2111         }
2112 }
2113
2114 static guint32
2115 find_typespec_for_class (MonoAotCompile *acfg, MonoClass *klass)
2116 {
2117         int i;
2118         MonoClass *k = NULL;
2119
2120         /* FIXME: Search referenced images as well */
2121         for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows; ++i) {
2122                 k = mono_class_get_full (acfg->image, MONO_TOKEN_TYPE_SPEC | (i + 1), NULL);
2123                 if (k == klass)
2124                         break;
2125         }
2126
2127         if (i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows)
2128                 return MONO_TOKEN_TYPE_SPEC | (i + 1);
2129         else
2130                 return 0;
2131 }
2132
2133 static void
2134 encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 **endbuf);
2135
2136 /*
2137  * encode_klass_ref:
2138  *
2139  *   Encode a reference to KLASS. We use our home-grown encoding instead of the
2140  * standard metadata encoding.
2141  */
2142 static void
2143 encode_klass_ref (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, guint8 **endbuf)
2144 {
2145         guint8 *p = buf;
2146
2147         if (klass->generic_class) {
2148                 guint32 token;
2149                 g_assert (klass->type_token);
2150
2151                 /* Find a typespec for a class if possible */
2152                 token = find_typespec_for_class (acfg, klass);
2153                 if (token) {
2154                         encode_value (token, p, &p);
2155                         encode_value (get_image_index (acfg, acfg->image), p, &p);
2156                 } else {
2157                         MonoClass *gclass = klass->generic_class->container_class;
2158                         MonoGenericInst *inst = klass->generic_class->context.class_inst;
2159                         int i;
2160
2161                         /* Encode it ourselves */
2162                         /* Marker */
2163                         encode_value (MONO_TOKEN_TYPE_SPEC, p, &p);
2164                         encode_value (MONO_TYPE_GENERICINST, p, &p);
2165                         encode_klass_ref (acfg, gclass, p, &p);
2166                         encode_value (inst->type_argc, p, &p);
2167                         for (i = 0; i < inst->type_argc; ++i)
2168                                 encode_klass_ref (acfg, mono_class_from_mono_type (inst->type_argv [i]), p, &p);
2169                 }
2170         } else if (klass->type_token) {
2171                 g_assert (mono_metadata_token_code (klass->type_token) == MONO_TOKEN_TYPE_DEF);
2172                 encode_value (klass->type_token - MONO_TOKEN_TYPE_DEF, p, &p);
2173                 encode_value (get_image_index (acfg, klass->image), p, &p);
2174         } else if ((klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR)) {
2175                 MonoGenericParam *param = klass->byval_arg.data.generic_param;
2176
2177                 /* Marker */
2178                 encode_value (MONO_TOKEN_TYPE_SPEC, p, &p);
2179                 encode_value (klass->byval_arg.type, p, &p);
2180
2181                 encode_value (param->num, p, &p);
2182                 
2183                 g_assert (param->owner);
2184                 encode_value (param->owner->is_method, p, &p);
2185                 if (param->owner->is_method)
2186                         encode_method_ref (acfg, param->owner->owner.method, p, &p);
2187                 else
2188                         encode_klass_ref (acfg, param->owner->owner.klass, p, &p);
2189         } else {
2190                 /* Array class */
2191                 g_assert (klass->rank > 0);
2192                 encode_value (MONO_TOKEN_TYPE_DEF, p, &p);
2193                 encode_value (get_image_index (acfg, klass->image), p, &p);
2194                 encode_value (klass->rank, p, &p);
2195                 encode_klass_ref (acfg, klass->element_class, p, &p);
2196         }
2197         *endbuf = p;
2198 }
2199
2200 static void
2201 encode_field_info (MonoAotCompile *cfg, MonoClassField *field, guint8 *buf, guint8 **endbuf)
2202 {
2203         guint32 token = mono_get_field_token (field);
2204         guint8 *p = buf;
2205
2206         encode_klass_ref (cfg, field->parent, p, &p);
2207         g_assert (mono_metadata_token_code (token) == MONO_TOKEN_FIELD_DEF);
2208         encode_value (token - MONO_TOKEN_FIELD_DEF, p, &p);
2209         *endbuf = p;
2210 }
2211
2212 static void
2213 encode_generic_context (MonoAotCompile *acfg, MonoGenericContext *context, guint8 *buf, guint8 **endbuf)
2214 {
2215         guint8 *p = buf;
2216         int i;
2217         MonoGenericInst *inst;
2218
2219         /* Encode the context */
2220         inst = context->class_inst;
2221         encode_value (inst ? 1 : 0, p, &p);
2222         if (inst) {
2223                 encode_value (inst->type_argc, p, &p);
2224                 for (i = 0; i < inst->type_argc; ++i)
2225                         encode_klass_ref (acfg, mono_class_from_mono_type (inst->type_argv [i]), p, &p);
2226         }
2227         inst = context->method_inst;
2228         encode_value (inst ? 1 : 0, p, &p);
2229         if (inst) {
2230                 encode_value (inst->type_argc, p, &p);
2231                 for (i = 0; i < inst->type_argc; ++i)
2232                         encode_klass_ref (acfg, mono_class_from_mono_type (inst->type_argv [i]), p, &p);
2233         }
2234
2235         *endbuf = p;
2236 }
2237
2238 #define MAX_IMAGE_INDEX 250
2239
2240 static void
2241 encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 **endbuf)
2242 {
2243         guint32 image_index = get_image_index (acfg, method->klass->image);
2244         guint32 token = method->token;
2245         MonoJumpInfoToken *ji;
2246         guint8 *p = buf;
2247
2248         g_assert (image_index < MAX_IMAGE_INDEX);
2249
2250         /* Mark methods which can't use aot trampolines because they need the further 
2251          * processing in mono_magic_trampoline () which requires a MonoMethod*.
2252          */
2253         if ((method->is_generic && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) ||
2254                 (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED))
2255                 encode_value ((252 << 24), p, &p);
2256
2257         if (method->wrapper_type) {
2258                 /* Marker */
2259                 encode_value ((253 << 24), p, &p);
2260
2261                 encode_value (method->wrapper_type, p, &p);
2262
2263                 switch (method->wrapper_type) {
2264                 case MONO_WRAPPER_REMOTING_INVOKE:
2265                 case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
2266                 case MONO_WRAPPER_XDOMAIN_INVOKE: {
2267                         MonoMethod *m;
2268
2269                         m = mono_marshal_method_from_wrapper (method);
2270                         g_assert (m);
2271                         encode_method_ref (acfg, m, p, &p);
2272                         break;
2273                 }
2274                 case MONO_WRAPPER_PROXY_ISINST:
2275                 case MONO_WRAPPER_LDFLD:
2276                 case MONO_WRAPPER_LDFLDA:
2277                 case MONO_WRAPPER_STFLD:
2278                 case MONO_WRAPPER_ISINST: {
2279                         MonoClass *proxy_class = (MonoClass*)mono_marshal_method_from_wrapper (method);
2280                         encode_klass_ref (acfg, proxy_class, p, &p);
2281                         break;
2282                 }
2283                 case MONO_WRAPPER_LDFLD_REMOTE:
2284                 case MONO_WRAPPER_STFLD_REMOTE:
2285                         break;
2286                 case MONO_WRAPPER_ALLOC: {
2287                         int alloc_type = mono_gc_get_managed_allocator_type (method);
2288                         g_assert (alloc_type != -1);
2289                         encode_value (alloc_type, p, &p);
2290                         break;
2291                 }
2292                 case MONO_WRAPPER_STELEMREF:
2293                         break;
2294                 case MONO_WRAPPER_UNKNOWN:
2295                         if (strcmp (method->name, "FastMonitorEnter") == 0)
2296                                 encode_value (MONO_AOT_WRAPPER_MONO_ENTER, p, &p);
2297                         else if (strcmp (method->name, "FastMonitorExit") == 0)
2298                                 encode_value (MONO_AOT_WRAPPER_MONO_EXIT, p, &p);
2299                         else
2300                                 g_assert_not_reached ();
2301                         break;
2302                 case MONO_WRAPPER_STATIC_RGCTX_INVOKE: {
2303                         MonoMethod *m;
2304
2305                         m = mono_marshal_method_from_wrapper (method);
2306                         g_assert (m);
2307                         encode_method_ref (acfg, m, p, &p);
2308                         break;
2309                 }
2310                 default:
2311                         g_assert_not_reached ();
2312                 }
2313         } else if (mono_method_signature (method)->is_inflated) {
2314                 /* 
2315                  * This is a generic method, find the original token which referenced it and
2316                  * encode that.
2317                  * Obtain the token from information recorded by the JIT.
2318                  */
2319                 ji = g_hash_table_lookup (acfg->token_info_hash, method);
2320                 if (ji) {
2321                         image_index = get_image_index (acfg, ji->image);
2322                         g_assert (image_index < MAX_IMAGE_INDEX);
2323                         token = ji->token;
2324
2325                         /* Marker */
2326                         encode_value ((255 << 24), p, &p);
2327                         encode_value (image_index, p, &p);
2328                         encode_value (token, p, &p);
2329                 } else {
2330                         MonoMethod *declaring;
2331                         MonoGenericContext *context = mono_method_get_context (method);
2332
2333                         g_assert (method->is_inflated);
2334                         declaring = ((MonoMethodInflated*)method)->declaring;
2335
2336                         /*
2337                          * This might be a non-generic method of a generic instance, which 
2338                          * doesn't have a token since the reference is generated by the JIT 
2339                          * like Nullable:Box/Unbox, or by generic sharing.
2340                          */
2341
2342                         /* Marker */
2343                         encode_value ((254 << 24), p, &p);
2344                         /* Encode the klass */
2345                         encode_klass_ref (acfg, method->klass, p, &p);
2346                         /* Encode the method */
2347                         image_index = get_image_index (acfg, method->klass->image);
2348                         g_assert (image_index < MAX_IMAGE_INDEX);
2349                         g_assert (declaring->token);
2350                         token = declaring->token;
2351                         g_assert (mono_metadata_token_table (token) == MONO_TABLE_METHOD);
2352                         encode_value (image_index, p, &p);
2353                         encode_value (token, p, &p);
2354                         encode_generic_context (acfg, context, p, &p);
2355                 }
2356         } else if (token == 0) {
2357                 /* This might be a method of a constructed type like int[,].Set */
2358                 /* Obtain the token from information recorded by the JIT */
2359                 ji = g_hash_table_lookup (acfg->token_info_hash, method);
2360                 g_assert (ji);
2361                 image_index = get_image_index (acfg, ji->image);
2362                 g_assert (image_index < MAX_IMAGE_INDEX);
2363                 token = ji->token;
2364
2365                 /* Marker */
2366                 encode_value ((255 << 24), p, &p);
2367                 encode_value (image_index, p, &p);
2368                 encode_value (token, p, &p);
2369         } else {
2370                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_METHOD);
2371                 encode_value ((image_index << 24) | mono_metadata_token_index (token), p, &p);
2372         }
2373         *endbuf = p;
2374 }
2375
2376 static gint
2377 compare_patches (gconstpointer a, gconstpointer b)
2378 {
2379         int i, j;
2380
2381         i = (*(MonoJumpInfo**)a)->ip.i;
2382         j = (*(MonoJumpInfo**)b)->ip.i;
2383
2384         if (i < j)
2385                 return -1;
2386         else
2387                 if (i > j)
2388                         return 1;
2389         else
2390                 return 0;
2391 }
2392
2393 /*
2394  * is_plt_patch:
2395  *
2396  *   Return whenever PATCH_INFO refers to a direct call, and thus requires a
2397  * PLT entry.
2398  */
2399 static inline gboolean
2400 is_plt_patch (MonoJumpInfo *patch_info)
2401 {
2402         switch (patch_info->type) {
2403         case MONO_PATCH_INFO_METHOD:
2404         case MONO_PATCH_INFO_INTERNAL_METHOD:
2405         case MONO_PATCH_INFO_JIT_ICALL_ADDR:
2406         case MONO_PATCH_INFO_CLASS_INIT:
2407         case MONO_PATCH_INFO_RGCTX_FETCH:
2408         case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
2409         case MONO_PATCH_INFO_MONITOR_ENTER:
2410         case MONO_PATCH_INFO_MONITOR_EXIT:
2411                 return TRUE;
2412         default:
2413                 return FALSE;
2414         }
2415 }
2416
2417 /*
2418  * is_shared_got_patch:
2419  *
2420  *   Return whenever PATCH_INFO refers to a patch which needs a shared GOT
2421  * entry.
2422  * Keep it in sync with the version in aot-runtime.c.
2423  */
2424 static inline gboolean
2425 is_shared_got_patch (MonoJumpInfo *patch_info)
2426 {
2427         switch (patch_info->type) {
2428         case MONO_PATCH_INFO_VTABLE:
2429         case MONO_PATCH_INFO_CLASS:
2430         case MONO_PATCH_INFO_IID:
2431         case MONO_PATCH_INFO_ADJUSTED_IID:
2432         case MONO_PATCH_INFO_FIELD:
2433         case MONO_PATCH_INFO_SFLDA:
2434         case MONO_PATCH_INFO_DECLSEC:
2435         case MONO_PATCH_INFO_LDTOKEN:
2436         case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
2437         case MONO_PATCH_INFO_RVA:
2438         case MONO_PATCH_INFO_METHODCONST:
2439                 return TRUE;
2440         default:
2441                 return FALSE;
2442         }
2443 }
2444
2445 static int
2446 get_plt_offset (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
2447 {
2448         int res = -1;
2449
2450         if (is_plt_patch (patch_info)) {
2451                 int idx = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->patch_to_plt_offset, patch_info));
2452
2453                 if (patch_info->type == MONO_PATCH_INFO_METHOD && (patch_info->data.method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)) {
2454                         /* 
2455                          * Allocate a separate PLT slot for each such patch, since some plt
2456                          * entries will refer to the method itself, and some will refer to
2457                          * wrapper.
2458                          */
2459                         idx = 0;
2460                 }
2461
2462                 if (idx) {
2463                         res = idx;
2464                 } else {
2465                         MonoJumpInfo *new_ji = mono_patch_info_dup_mp (acfg->mempool, patch_info);
2466
2467                         res = acfg->plt_offset;
2468                         g_hash_table_insert (acfg->plt_offset_to_patch, GUINT_TO_POINTER (res), new_ji);
2469                         g_hash_table_insert (acfg->patch_to_plt_offset, new_ji, GUINT_TO_POINTER (res));
2470                         acfg->plt_offset ++;
2471                 }
2472         }
2473
2474         return res;
2475 }
2476
2477 /**
2478  * get_got_offset:
2479  *
2480  *   Returns the offset of the GOT slot where the runtime object resulting from resolving
2481  * JI could be found if it exists, otherwise allocates a new one.
2482  */
2483 static guint32
2484 get_got_offset (MonoAotCompile *acfg, MonoJumpInfo *ji)
2485 {
2486         guint32 got_offset;
2487
2488         got_offset = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->patch_to_shared_got_offset, ji));
2489         if (got_offset)
2490                 return got_offset - 1;
2491
2492         got_offset = acfg->got_offset;
2493         acfg->got_offset ++;
2494
2495         acfg->stats.got_slots ++;
2496         acfg->stats.got_slot_types [ji->type] ++;
2497
2498         return got_offset;
2499 }
2500
2501 static guint32
2502 get_shared_got_offset (MonoAotCompile *acfg, MonoJumpInfo *ji)
2503 {
2504         MonoJumpInfo *copy;
2505         guint32 got_offset;
2506
2507         if (!g_hash_table_lookup (acfg->patch_to_shared_got_offset, ji)) {
2508                 got_offset = get_got_offset (acfg, ji);
2509                 copy = mono_patch_info_dup_mp (acfg->mempool, ji);
2510                 g_hash_table_insert (acfg->patch_to_shared_got_offset, copy, GUINT_TO_POINTER (got_offset + 1));
2511                 g_ptr_array_add (acfg->shared_patches, copy);
2512         }
2513
2514         return get_got_offset (acfg, ji);
2515 }
2516
2517 /* Add a method to the list of methods which need to be emitted */
2518 static void
2519 add_method_with_index (MonoAotCompile *acfg, MonoMethod *method, int index)
2520 {
2521         g_assert (method);
2522         if (!g_hash_table_lookup (acfg->method_indexes, method)) {
2523                 g_ptr_array_add (acfg->methods, method);
2524                 g_hash_table_insert (acfg->method_indexes, method, GUINT_TO_POINTER (index + 1));
2525                 acfg->nmethods = acfg->methods->len + 1;
2526         }
2527 }
2528
2529 static guint32
2530 get_method_index (MonoAotCompile *acfg, MonoMethod *method)
2531 {
2532         int index = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_indexes, method));
2533         
2534         g_assert (index);
2535
2536         return index - 1;
2537 }
2538
2539 static int
2540 add_method (MonoAotCompile *acfg, MonoMethod *method)
2541 {
2542         int index;
2543
2544         index = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_indexes, method));
2545         if (index)
2546                 return index - 1;
2547
2548         index = acfg->method_index;
2549         add_method_with_index (acfg, method, index);
2550
2551         /* FIXME: Fix quadratic behavior */
2552         acfg->method_order = g_list_append (acfg->method_order, GUINT_TO_POINTER (index));
2553
2554         acfg->method_index ++;
2555
2556         return index;
2557 }
2558
2559 static void
2560 add_extra_method (MonoAotCompile *acfg, MonoMethod *method)
2561 {
2562         int index;
2563
2564         index = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_indexes, method));
2565         if (index)
2566                 return;
2567         add_method (acfg, method);
2568         g_ptr_array_add (acfg->extra_methods, method);
2569 }
2570
2571 static void
2572 add_jit_icall_wrapper (gpointer key, gpointer value, gpointer user_data)
2573 {
2574         MonoAotCompile *acfg = user_data;
2575         MonoJitICallInfo *callinfo = value;
2576         MonoMethod *wrapper;
2577         char *name;
2578
2579         if (!callinfo->sig)
2580                 return;
2581
2582         name = g_strdup_printf ("__icall_wrapper_%s", callinfo->name);
2583         wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, check_for_pending_exc);
2584         g_free (name);
2585
2586         add_method (acfg, wrapper);
2587 }
2588
2589 static MonoMethod*
2590 get_runtime_invoke_sig (MonoMethodSignature *sig)
2591 {
2592         MonoMethodBuilder *mb;
2593         MonoMethod *m;
2594
2595         mb = mono_mb_new (mono_defaults.object_class, "FOO", MONO_WRAPPER_NONE);
2596         m = mono_mb_create_method (mb, sig, 16);
2597         return mono_marshal_get_runtime_invoke (m);
2598 }
2599
2600 static void
2601 add_wrappers (MonoAotCompile *acfg)
2602 {
2603         MonoMethod *method, *m;
2604         int i, j, nallocators;
2605         MonoMethodSignature *sig, *csig;
2606         guint32 token;
2607
2608         /* 
2609          * FIXME: Instead of AOTing all the wrappers, it might be better to redesign them
2610          * so there is only one wrapper of a given type, or inlining their contents into their
2611          * callers.
2612          */
2613
2614         /* 
2615          * FIXME: This depends on the fact that different wrappers have different 
2616          * names.
2617          */
2618
2619         /* FIXME: Collect these automatically */
2620
2621         /* Runtime invoke wrappers */
2622
2623         /* void runtime-invoke () [.cctor] */
2624         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
2625         csig->ret = &mono_defaults.void_class->byval_arg;
2626         add_method (acfg, get_runtime_invoke_sig (csig));
2627
2628         /* void runtime-invoke () [Finalize] */
2629         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
2630         csig->hasthis = 1;
2631         csig->ret = &mono_defaults.void_class->byval_arg;
2632         add_method (acfg, get_runtime_invoke_sig (csig));
2633
2634         /* void runtime-invoke (string) [exception ctor] */
2635         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
2636         csig->hasthis = 1;
2637         csig->ret = &mono_defaults.void_class->byval_arg;
2638         csig->params [0] = &mono_defaults.string_class->byval_arg;
2639         add_method (acfg, get_runtime_invoke_sig (csig));
2640
2641         /* void runtime-invoke (string, string) [exception ctor] */
2642         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
2643         csig->hasthis = 1;
2644         csig->ret = &mono_defaults.void_class->byval_arg;
2645         csig->params [0] = &mono_defaults.string_class->byval_arg;
2646         csig->params [1] = &mono_defaults.string_class->byval_arg;
2647         add_method (acfg, get_runtime_invoke_sig (csig));
2648
2649         /* string runtime-invoke () [Exception.ToString ()] */
2650         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
2651         csig->hasthis = 1;
2652         csig->ret = &mono_defaults.string_class->byval_arg;
2653         add_method (acfg, get_runtime_invoke_sig (csig));
2654
2655         /* void runtime-invoke (string, Exception) [exception ctor] */
2656         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
2657         csig->hasthis = 1;
2658         csig->ret = &mono_defaults.void_class->byval_arg;
2659         csig->params [0] = &mono_defaults.string_class->byval_arg;
2660         csig->params [1] = &mono_defaults.exception_class->byval_arg;
2661         add_method (acfg, get_runtime_invoke_sig (csig));
2662
2663         /* Assembly runtime-invoke (string, bool) [DoAssemblyResolve] */
2664         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
2665         csig->hasthis = 1;
2666         csig->ret = &(mono_class_from_name (
2667                                                                                 mono_defaults.corlib, "System.Reflection", "Assembly"))->byval_arg;
2668         csig->params [0] = &mono_defaults.string_class->byval_arg;
2669         csig->params [1] = &mono_defaults.boolean_class->byval_arg;
2670         add_method (acfg, get_runtime_invoke_sig (csig));
2671
2672         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
2673                 MonoMethod *method;
2674                 guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
2675                 gboolean skip = FALSE;
2676
2677                 method = mono_get_method (acfg->image, token, NULL);
2678
2679                 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
2680                         (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
2681                         (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
2682                         skip = TRUE;
2683
2684                 if (method->is_generic || method->klass->generic_container)
2685                         skip = TRUE;
2686
2687                 /* Skip methods which can not be handled by get_runtime_invoke () */
2688                 sig = mono_method_signature (method);
2689                 if ((sig->ret->type == MONO_TYPE_PTR) ||
2690                         (sig->ret->type == MONO_TYPE_TYPEDBYREF))
2691                         skip = TRUE;
2692
2693                 for (j = 0; j < sig->param_count; j++) {
2694                         if (sig->params [j]->type == MONO_TYPE_TYPEDBYREF)
2695                                 skip = TRUE;
2696                 }
2697
2698                 if (!skip)
2699                         add_method (acfg, mono_marshal_get_runtime_invoke (method));
2700         }
2701
2702         if (strcmp (acfg->image->assembly->aname.name, "mscorlib") == 0) {
2703                 MonoMethodDesc *desc;
2704                 MonoMethod *orig_method;
2705
2706                 /* JIT icall wrappers */
2707                 /* FIXME: locking */
2708                 g_hash_table_foreach (mono_get_jit_icall_info (), add_jit_icall_wrapper, acfg);
2709
2710                 /* Managed Allocators */
2711                 nallocators = mono_gc_get_managed_allocator_types ();
2712                 for (i = 0; i < nallocators; ++i) {
2713                         m = mono_gc_get_managed_allocator_by_type (i);
2714                         if (m)
2715                                 add_method (acfg, m);
2716                 }
2717
2718                 /* stelemref */
2719                 add_method (acfg, mono_marshal_get_stelemref ());
2720
2721                 /* Monitor Enter/Exit */
2722                 desc = mono_method_desc_new ("Monitor:Enter", FALSE);
2723                 orig_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
2724                 g_assert (orig_method);
2725                 mono_method_desc_free (desc);
2726                 method = mono_monitor_get_fast_path (orig_method);
2727                 if (method)
2728                         add_method (acfg, method);
2729
2730                 desc = mono_method_desc_new ("Monitor:Exit", FALSE);
2731                 orig_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
2732                 g_assert (orig_method);
2733                 mono_method_desc_free (desc);
2734                 method = mono_monitor_get_fast_path (orig_method);
2735                 if (method)
2736                         add_method (acfg, method);
2737         }
2738
2739         /* remoting-invoke wrappers */
2740         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
2741                 MonoMethodSignature *sig;
2742                 
2743                 token = MONO_TOKEN_METHOD_DEF | (i + 1);
2744                 method = mono_get_method (acfg->image, token, NULL);
2745
2746                 sig = mono_method_signature (method);
2747
2748                 if (sig->hasthis && (method->klass->marshalbyref || method->klass == mono_defaults.object_class) && 
2749                         !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
2750                         m = mono_marshal_get_remoting_invoke_with_check (method);
2751
2752                         add_method (acfg, m);
2753                 }
2754         }
2755
2756         /* delegate-invoke wrappers */
2757         for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
2758                 MonoClass *klass;
2759                 
2760                 token = MONO_TOKEN_TYPE_DEF | (i + 1);
2761                 klass = mono_class_get (acfg->image, token);
2762
2763                 if (klass->delegate && klass != mono_defaults.delegate_class && klass != mono_defaults.multicastdelegate_class && !klass->generic_container) {
2764                         method = mono_get_delegate_invoke (klass);
2765
2766                         m = mono_marshal_get_delegate_invoke (method, NULL);
2767
2768                         add_method (acfg, m);
2769                 }
2770         }
2771
2772         /* Synchronized wrappers */
2773         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
2774                 token = MONO_TOKEN_METHOD_DEF | (i + 1);
2775                 method = mono_get_method (acfg->image, token, NULL);
2776
2777                 if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
2778                         add_method (acfg, mono_marshal_get_synchronized_wrapper (method));
2779         }
2780
2781 #if 0
2782         /* static rgctx wrappers */
2783         /* FIXME: Each wrapper belongs to a given instantiation of a generic method */
2784         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
2785                 token = MONO_TOKEN_METHOD_DEF | (i + 1);
2786                 method = mono_get_method (acfg->image, token, NULL);
2787
2788                 if (((method->flags & METHOD_ATTRIBUTE_STATIC) ||
2789                          (method->is_inflated && mono_method_get_context (method)->method_inst)) &&
2790                         mono_class_generic_sharing_enabled (method->klass) &&
2791                         mono_method_is_generic_sharable_impl (method, FALSE)) {
2792                         m = mono_marshal_get_static_rgctx_invoke (method);
2793                         add_method (acfg, m);
2794                 }
2795         }
2796 #endif
2797 }
2798
2799 static gboolean
2800 has_type_vars (MonoClass *klass)
2801 {
2802         if ((klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
2803                 return TRUE;
2804         if (klass->rank)
2805                 return has_type_vars (klass->element_class);
2806         if (klass->generic_class) {
2807                 MonoGenericContext *context = &klass->generic_class->context;
2808                 if (context->class_inst) {
2809                         int i;
2810
2811                         for (i = 0; i < context->class_inst->type_argc; ++i)
2812                                 if (has_type_vars (mono_class_from_mono_type (context->class_inst->type_argv [i])))
2813                                         return TRUE;
2814                 }
2815         }
2816         return FALSE;
2817 }
2818
2819 static gboolean
2820 method_has_type_vars (MonoMethod *method)
2821 {
2822         if (has_type_vars (method->klass))
2823                 return TRUE;
2824
2825         if (method->is_inflated) {
2826                 MonoGenericContext *context = mono_method_get_context (method);
2827                 if (context->method_inst) {
2828                         int i;
2829
2830                         for (i = 0; i < context->method_inst->type_argc; ++i)
2831                                 if (has_type_vars (mono_class_from_mono_type (context->method_inst->type_argv [i])))
2832                                         return TRUE;
2833                 }
2834         }
2835         return FALSE;
2836 }
2837
2838 /*
2839  * add_generic_instances:
2840  *
2841  *   Add instances referenced by the METHODSPEC/TYPESPEC table.
2842  */
2843 static void
2844 add_generic_instances (MonoAotCompile *acfg)
2845 {
2846         int i;
2847         guint32 token;
2848         MonoMethod *method;
2849         MonoGenericContext *context;
2850
2851         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHODSPEC].rows; ++i) {
2852                 token = MONO_TOKEN_METHOD_SPEC | (i + 1);
2853                 method = mono_get_method (acfg->image, token, NULL);
2854
2855                 context = mono_method_get_context (method);
2856                 if (context && ((context->class_inst && context->class_inst->is_open) ||
2857                                                 (context->method_inst && context->method_inst->is_open)))
2858                         continue;
2859
2860                 if (method->klass->image != acfg->image)
2861                         continue;
2862
2863                 if (mono_method_is_generic_sharable_impl (method, FALSE))
2864                         /* Already added */
2865                         continue;
2866
2867                 add_extra_method (acfg, method);
2868         }
2869
2870         for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows; ++i) {
2871                 MonoClass *klass;
2872                 gpointer iter;
2873
2874                 token = MONO_TOKEN_TYPE_SPEC | (i + 1);
2875
2876                 klass = mono_class_get (acfg->image, token);
2877                 if (!klass)
2878                         continue;
2879                 mono_class_init (klass);
2880
2881                 if (klass->generic_class && klass->generic_class->context.class_inst->is_open)
2882                         continue;
2883
2884                 if (has_type_vars (klass))
2885                         continue;
2886
2887                 /* 
2888                  * Add rgctx wrappers for cctors since those are called by the runtime, so 
2889                  * there is no methodspec for them. This is needed even for shared classes,
2890                  * since rgctx wrappers belong to inflated methods.
2891                  */
2892                 method = mono_class_get_cctor (klass);
2893                 if (method)
2894                         add_extra_method (acfg, mono_marshal_get_static_rgctx_invoke (method));
2895
2896                 iter = NULL;
2897                 while ((method = mono_class_get_methods (klass, &iter))) {
2898                         if (mono_method_is_generic_sharable_impl (method, FALSE))
2899                                 /* Already added */
2900                                 continue;
2901
2902                         if (method->is_generic)
2903                                 /* FIXME: */
2904                                 continue;
2905
2906                         /*
2907                          * FIXME: Instances which are referenced by these methods are not added,
2908                          * for example Array.Resize<int> for List<int>.Add ().
2909                          */
2910                         add_extra_method (acfg, method);
2911                 }
2912         }
2913 }
2914
2915 static void
2916 emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, guint32 code_len, MonoJumpInfo *relocs, gboolean got_only)
2917 {
2918         int i, pindex, start_index, method_index;
2919         GPtrArray *patches;
2920         MonoJumpInfo *patch_info;
2921         MonoMethodHeader *header;
2922         gboolean skip, direct_call;
2923         guint32 got_slot;
2924         char direct_call_target [128];
2925
2926         if (method) {
2927                 header = mono_method_get_header (method);
2928
2929                 method_index = get_method_index (acfg, method);
2930         }
2931
2932         /* Collect and sort relocations */
2933         patches = g_ptr_array_new ();
2934         for (patch_info = relocs; patch_info; patch_info = patch_info->next)
2935                 g_ptr_array_add (patches, patch_info);
2936         g_ptr_array_sort (patches, compare_patches);
2937
2938         start_index = 0;
2939         for (i = 0; i < code_len; i++) {
2940                 patch_info = NULL;
2941                 for (pindex = start_index; pindex < patches->len; ++pindex) {
2942                         patch_info = g_ptr_array_index (patches, pindex);
2943                         if (patch_info->ip.i >= i)
2944                                 break;
2945                 }
2946
2947 #ifdef MONO_ARCH_AOT_SUPPORTED
2948                 skip = FALSE;
2949                 if (patch_info && (patch_info->ip.i == i) && (pindex < patches->len)) {
2950                         start_index = pindex;
2951
2952                         switch (patch_info->type) {
2953                         case MONO_PATCH_INFO_NONE:
2954                                 break;
2955                         case MONO_PATCH_INFO_GOT_OFFSET: {
2956                                 guint32 offset = mono_arch_get_patch_offset (code + i);
2957                                 emit_bytes (acfg, code + i, offset);
2958                                 emit_symbol_diff (acfg, "got", ".", offset);
2959
2960                                 i += offset + 4 - 1;
2961                                 skip = TRUE;
2962                                 break;
2963                         }
2964                         default: {
2965                                 if (!is_got_patch (patch_info->type))
2966                                         break;
2967
2968                                 /*
2969                                  * If this patch is a call, try emitting a direct call instead of
2970                                  * through a PLT entry. This is possible if the called method is in
2971                                  * the same assembly and requires no initialization.
2972                                  */
2973                                 direct_call = FALSE;
2974                                 if (!got_only && (patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == method->klass->image)) {
2975                                         MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
2976                                         if (callee_cfg) {
2977                                                 gboolean direct_callable = TRUE;
2978
2979                                                 if (direct_callable && !(!callee_cfg->has_got_slots && (callee_cfg->method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)))
2980                                                         direct_callable = FALSE;
2981                                                 if ((callee_cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) && method->wrapper_type != MONO_WRAPPER_SYNCHRONIZED)
2982                                                         // FIXME: Maybe call the wrapper directly ?
2983                                                         direct_callable = FALSE;
2984                                                 if (direct_callable) {
2985                                                         //printf ("DIRECT: %s %s\n", method ? mono_method_full_name (method, TRUE) : "", mono_method_full_name (callee_cfg->method, TRUE));
2986                                                         direct_call = TRUE;
2987                                                         sprintf (direct_call_target, ".Lm_%x", get_method_index (acfg, callee_cfg->orig_method));
2988                                                         patch_info->type = MONO_PATCH_INFO_NONE;
2989                                                         acfg->stats.direct_calls ++;
2990                                                 }
2991                                         }
2992
2993                                         acfg->stats.all_calls ++;
2994                                 }
2995
2996                                 if (!got_only && !direct_call) {
2997                                         int plt_offset = get_plt_offset (acfg, patch_info);
2998                                         if (plt_offset != -1) {
2999                                                 /* This patch has a PLT entry, so we must emit a call to the PLT entry */
3000                                                 direct_call = TRUE;
3001                                                 sprintf (direct_call_target, ".Lp_%d", plt_offset);
3002                 
3003                                                 /* Nullify the patch */
3004                                                 patch_info->type = MONO_PATCH_INFO_NONE;
3005                                         }
3006                                 }
3007
3008                                 if (direct_call) {
3009 #if defined(__i386__) || defined(__x86_64__)
3010                                         g_assert (code [i] == 0xe8);
3011                                         /* Need to make sure this is exactly 5 bytes long */
3012                                         emit_byte (acfg, '\xe8');
3013                                         emit_symbol_diff (acfg, direct_call_target, ".", -4);
3014                                         i += 4;
3015 #elif defined(__arm__)
3016 #ifdef USE_BIN_WRITER
3017                                         {
3018                                                 guint8 buf [4];
3019                                                 guint8 *code;
3020
3021                                                 code = buf;
3022                                                 ARM_BL (code, 0);
3023
3024                                                 emit_reloc (acfg, R_ARM_CALL, direct_call_target, -8);
3025                                                 emit_bytes (acfg, buf, 4);
3026                                         }
3027 #else
3028                                         asm_writer_emit_unset_mode (acfg);
3029                                         fprintf (acfg->fp, "bl %s\n", direct_call_target);
3030 #endif
3031                                         i += 4 - 1;
3032 #else
3033                                         g_assert_not_reached ();
3034 #endif
3035                                 } else {
3036                                         got_slot = get_got_offset (acfg, patch_info);
3037
3038                                         emit_bytes (acfg, code + i, mono_arch_get_patch_offset (code + i));
3039 #ifdef __x86_64__
3040                                         emit_symbol_diff (acfg, "got", ".", (unsigned int) ((got_slot * sizeof (gpointer)) - 4));
3041 #elif defined(__i386__)
3042                                         emit_int32 (acfg, (unsigned int) ((got_slot * sizeof (gpointer))));
3043 #elif defined(__arm__)
3044                                         emit_symbol_diff (acfg, "got", ".", (unsigned int) ((got_slot * sizeof (gpointer))) - 12);
3045 #else
3046                                         g_assert_not_reached ();
3047 #endif
3048                                         
3049                                         i += mono_arch_get_patch_offset (code + i) + 4 - 1;
3050                                 }
3051                                 skip = TRUE;
3052                         }
3053                         }
3054                 }
3055 #endif /* MONO_ARCH_AOT_SUPPORTED */
3056
3057                 if (!skip) {
3058                         /* Find next patch */
3059                         patch_info = NULL;
3060                         for (pindex = start_index; pindex < patches->len; ++pindex) {
3061                                 patch_info = g_ptr_array_index (patches, pindex);
3062                                 if (patch_info->ip.i >= i)
3063                                         break;
3064                         }
3065
3066                         /* Try to emit multiple bytes at once */
3067                         if (pindex < patches->len && patch_info->ip.i > i) {
3068                                 emit_bytes (acfg, code + i, patch_info->ip.i - i);
3069                                 i = patch_info->ip.i - 1;
3070                         } else {
3071                                 emit_bytes (acfg, code + i, 1);
3072                         }
3073                 }
3074         }
3075 }
3076
3077 static void
3078 emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg)
3079 {
3080         MonoMethod *method;
3081         int method_index;
3082         guint8 *code;
3083         char symbol [128];
3084         int func_alignment = 16;
3085         MonoMethodHeader *header;
3086
3087         method = cfg->orig_method;
3088         code = cfg->native_code;
3089         header = mono_method_get_header (method);
3090
3091         method_index = get_method_index (acfg, method);
3092
3093         /* Make the labels local */
3094         sprintf (symbol, ".Lm_%x", method_index);
3095
3096         emit_alignment (acfg, func_alignment);
3097         emit_label (acfg, symbol);
3098
3099 #ifdef USE_ELF_WRITER
3100         if (acfg->aot_opts.write_symbols) {
3101                 char *full_name;
3102                 /* Emit a local symbol into the symbol table */
3103                 full_name = mono_method_full_name (method, TRUE);
3104                 sprintf (symbol, ".Lme_%x", method_index);
3105                 emit_local_symbol (acfg, full_name, symbol, TRUE);
3106                 emit_label (acfg, full_name);
3107                 g_free (full_name);
3108         }
3109 #endif
3110
3111         if (cfg->verbose_level > 0)
3112                 g_print ("Method %s emitted as %s\n", mono_method_full_name (method, TRUE), symbol);
3113
3114         acfg->stats.code_size += cfg->code_len;
3115
3116         acfg->cfgs [method_index]->got_offset = acfg->got_offset;
3117
3118         emit_and_reloc_code (acfg, method, code, cfg->code_len, cfg->patch_info, FALSE);
3119
3120         emit_line (acfg);
3121
3122         sprintf (symbol, ".Lme_%x", method_index);
3123         emit_label (acfg, symbol);
3124 }
3125
3126 /**
3127  * encode_patch:
3128  *
3129  *  Encode PATCH_INFO into its disk representation.
3130  */
3131 static void
3132 encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint8 **endbuf)
3133 {
3134         guint8 *p = buf;
3135
3136         switch (patch_info->type) {
3137         case MONO_PATCH_INFO_NONE:
3138                 break;
3139         case MONO_PATCH_INFO_IMAGE:
3140                 encode_value (get_image_index (acfg, patch_info->data.image), p, &p);
3141                 break;
3142         case MONO_PATCH_INFO_METHOD_REL:
3143                 encode_value ((gint)patch_info->data.offset, p, &p);
3144                 break;
3145         case MONO_PATCH_INFO_SWITCH: {
3146                 gpointer *table = (gpointer *)patch_info->data.table->table;
3147                 int k;
3148
3149                 encode_value (patch_info->data.table->table_size, p, &p);
3150                 for (k = 0; k < patch_info->data.table->table_size; k++)
3151                         encode_value ((int)(gssize)table [k], p, &p);
3152                 break;
3153         }
3154         case MONO_PATCH_INFO_METHODCONST:
3155         case MONO_PATCH_INFO_METHOD:
3156         case MONO_PATCH_INFO_METHOD_JUMP:
3157         case MONO_PATCH_INFO_ICALL_ADDR:
3158         case MONO_PATCH_INFO_METHOD_RGCTX:
3159                 encode_method_ref (acfg, patch_info->data.method, p, &p);
3160                 break;
3161         case MONO_PATCH_INFO_INTERNAL_METHOD:
3162         case MONO_PATCH_INFO_JIT_ICALL_ADDR: {
3163                 guint32 len = strlen (patch_info->data.name);
3164
3165                 encode_value (len, p, &p);
3166
3167                 memcpy (p, patch_info->data.name, len);
3168                 p += len;
3169                 *p++ = '\0';
3170                 break;
3171         }
3172         case MONO_PATCH_INFO_LDSTR: {
3173                 guint32 image_index = get_image_index (acfg, patch_info->data.token->image);
3174                 guint32 token = patch_info->data.token->token;
3175                 g_assert (mono_metadata_token_code (token) == MONO_TOKEN_STRING);
3176                 encode_value (image_index, p, &p);
3177                 encode_value (patch_info->data.token->token - MONO_TOKEN_STRING, p, &p);
3178                 break;
3179         }
3180         case MONO_PATCH_INFO_RVA:
3181         case MONO_PATCH_INFO_DECLSEC:
3182         case MONO_PATCH_INFO_LDTOKEN:
3183         case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
3184                 encode_value (get_image_index (acfg, patch_info->data.token->image), p, &p);
3185                 encode_value (patch_info->data.token->token, p, &p);
3186                 encode_value (patch_info->data.token->has_context, p, &p);
3187                 if (patch_info->data.token->has_context)
3188                         encode_generic_context (acfg, &patch_info->data.token->context, p, &p);
3189                 break;
3190         case MONO_PATCH_INFO_EXC_NAME: {
3191                 MonoClass *ex_class;
3192
3193                 ex_class =
3194                         mono_class_from_name (mono_defaults.exception_class->image,
3195                                                                   "System", patch_info->data.target);
3196                 g_assert (ex_class);
3197                 encode_klass_ref (acfg, ex_class, p, &p);
3198                 break;
3199         }
3200         case MONO_PATCH_INFO_R4:
3201                 encode_value (*((guint32 *)patch_info->data.target), p, &p);
3202                 break;
3203         case MONO_PATCH_INFO_R8:
3204                 encode_value (*((guint32 *)patch_info->data.target), p, &p);
3205                 encode_value (*(((guint32 *)patch_info->data.target) + 1), p, &p);
3206                 break;
3207         case MONO_PATCH_INFO_VTABLE:
3208         case MONO_PATCH_INFO_CLASS:
3209         case MONO_PATCH_INFO_IID:
3210         case MONO_PATCH_INFO_ADJUSTED_IID:
3211                 encode_klass_ref (acfg, patch_info->data.klass, p, &p);
3212                 break;
3213         case MONO_PATCH_INFO_CLASS_INIT:
3214         case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
3215                 encode_klass_ref (acfg, patch_info->data.klass, p, &p);
3216                 break;
3217         case MONO_PATCH_INFO_FIELD:
3218         case MONO_PATCH_INFO_SFLDA:
3219                 encode_field_info (acfg, patch_info->data.field, p, &p);
3220                 break;
3221         case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
3222                 break;
3223         case MONO_PATCH_INFO_RGCTX_FETCH: {
3224                 MonoJumpInfoRgctxEntry *entry = patch_info->data.rgctx_entry;
3225
3226                 encode_method_ref (acfg, entry->method, p, &p);
3227                 encode_value (entry->in_mrgctx, p, &p);
3228                 encode_value (entry->info_type, p, &p);
3229                 encode_value (entry->data->type, p, &p);
3230                 encode_patch (acfg, entry->data, p, &p);
3231                 break;
3232         }
3233         case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
3234         case MONO_PATCH_INFO_MONITOR_ENTER:
3235         case MONO_PATCH_INFO_MONITOR_EXIT:
3236                 break;
3237         default:
3238                 g_warning ("unable to handle jump info %d", patch_info->type);
3239                 g_assert_not_reached ();
3240         }
3241
3242         *endbuf = p;
3243 }
3244
3245 static void
3246 encode_patch_list (MonoAotCompile *acfg, GPtrArray *patches, int n_patches, int first_got_offset, guint8 *buf, guint8 **endbuf)
3247 {
3248         guint8 *p = buf;
3249         guint32 last_offset, j, pindex;
3250         MonoJumpInfo *patch_info;
3251
3252         encode_value (n_patches, p, &p);
3253
3254         if (n_patches)
3255                 encode_value (first_got_offset, p, &p);
3256
3257         /* First encode the type+position table */
3258         last_offset = 0;
3259         j = 0;
3260         for (pindex = 0; pindex < patches->len; ++pindex) {
3261                 guint32 offset;
3262                 patch_info = g_ptr_array_index (patches, pindex);
3263                 
3264                 if (patch_info->type == MONO_PATCH_INFO_NONE)
3265                         /* Nothing to do */
3266                         continue;
3267
3268                 j ++;
3269                 //printf ("T: %d O: %d.\n", patch_info->type, patch_info->ip.i);
3270                 offset = patch_info->ip.i - last_offset;
3271                 last_offset = patch_info->ip.i;
3272
3273                 /* Only the type is needed */
3274                 *p = patch_info->type;
3275                 p++;
3276         }
3277
3278         /* Then encode the other info */
3279         for (pindex = 0; pindex < patches->len; ++pindex) {
3280                 patch_info = g_ptr_array_index (patches, pindex);
3281
3282                 if (is_shared_got_patch (patch_info)) {
3283                         guint32 offset = get_got_offset (acfg, patch_info);
3284                         encode_value (offset, p, &p);
3285                 } else {
3286                         encode_patch (acfg, patch_info, p, &p);
3287                 }
3288         }
3289
3290         *endbuf = p;
3291 }
3292
3293 static void
3294 emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
3295 {
3296         MonoMethod *method;
3297         GList *l;
3298         int pindex, buf_size, n_patches;
3299         guint8 *code;
3300         char symbol [128];
3301         GPtrArray *patches;
3302         MonoJumpInfo *patch_info;
3303         MonoMethodHeader *header;
3304         guint32 method_index;
3305         guint8 *p, *buf;
3306         guint32 first_got_offset;
3307
3308         method = cfg->orig_method;
3309         code = cfg->native_code;
3310         header = mono_method_get_header (method);
3311
3312         method_index = get_method_index (acfg, method);
3313
3314         /* Make the labels local */
3315         sprintf (symbol, ".Lm_%x_p", method_index);
3316
3317         /* Sort relocations */
3318         patches = g_ptr_array_new ();
3319         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next)
3320                 g_ptr_array_add (patches, patch_info);
3321         g_ptr_array_sort (patches, compare_patches);
3322
3323         first_got_offset = acfg->cfgs [method_index]->got_offset;
3324
3325         /**********************/
3326         /* Encode method info */
3327         /**********************/
3328
3329         buf_size = (patches->len < 1000) ? 40960 : 40960 + (patches->len * 64);
3330         p = buf = g_malloc (buf_size);
3331
3332         if (mono_class_get_cctor (method->klass))
3333                 encode_klass_ref (acfg, method->klass, p, &p);
3334         else
3335                 /* Not needed when loading the method */
3336                 encode_value (0, p, &p);
3337
3338         /* String table */
3339         if (cfg->opt & MONO_OPT_SHARED) {
3340                 encode_value (g_list_length (cfg->ldstr_list), p, &p);
3341                 for (l = cfg->ldstr_list; l; l = l->next) {
3342                         encode_value ((long)l->data, p, &p);
3343                 }
3344         }
3345         else
3346                 /* Used only in shared mode */
3347                 g_assert (!cfg->ldstr_list);
3348
3349         n_patches = 0;
3350         for (pindex = 0; pindex < patches->len; ++pindex) {
3351                 patch_info = g_ptr_array_index (patches, pindex);
3352                 
3353                 if ((patch_info->type == MONO_PATCH_INFO_GOT_OFFSET) ||
3354                         (patch_info->type == MONO_PATCH_INFO_NONE)) {
3355                         patch_info->type = MONO_PATCH_INFO_NONE;
3356                         /* Nothing to do */
3357                         continue;
3358                 }
3359
3360                 if ((patch_info->type == MONO_PATCH_INFO_IMAGE) && (patch_info->data.image == acfg->image)) {
3361                         /* Stored in a GOT slot initialized at module load time */
3362                         patch_info->type = MONO_PATCH_INFO_NONE;
3363                         continue;
3364                 }
3365
3366                 if (is_plt_patch (patch_info)) {
3367                         /* Calls are made through the PLT */
3368                         patch_info->type = MONO_PATCH_INFO_NONE;
3369                         continue;
3370                 }
3371
3372                 n_patches ++;
3373         }
3374
3375         if (n_patches)
3376                 g_assert (cfg->has_got_slots);
3377
3378         encode_patch_list (acfg, patches, n_patches, first_got_offset, p, &p);
3379
3380         acfg->stats.info_size += p - buf;
3381
3382         /* Emit method info */
3383
3384         emit_label (acfg, symbol);
3385
3386         g_assert (p - buf < buf_size);
3387         emit_bytes (acfg, buf, p - buf);
3388         g_free (buf);
3389 }
3390
3391 static void
3392 emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
3393 {
3394         MonoMethod *method;
3395         int k, buf_size, method_index;
3396         guint32 debug_info_size;
3397         guint8 *code;
3398         char symbol [128];
3399         MonoMethodHeader *header;
3400         guint8 *p, *buf, *debug_info;
3401         MonoJitInfo *jinfo = cfg->jit_info;
3402
3403         method = cfg->orig_method;
3404         code = cfg->native_code;
3405         header = mono_method_get_header (method);
3406
3407         method_index = get_method_index (acfg, method);
3408
3409         /* Make the labels local */
3410         sprintf (symbol, ".Le_%x_p", method_index);
3411
3412         mono_debug_serialize_debug_info (cfg, &debug_info, &debug_info_size);
3413
3414         buf_size = header->num_clauses * 256 + debug_info_size + 128;
3415         p = buf = g_malloc (buf_size);
3416
3417         encode_value (jinfo->code_size, p, &p);
3418         encode_value (jinfo->used_regs, p, &p);
3419         encode_value (jinfo->has_generic_jit_info, p, &p);
3420
3421         /* Exception table */
3422         if (header->num_clauses) {
3423                 for (k = 0; k < header->num_clauses; ++k) {
3424                         MonoJitExceptionInfo *ei = &jinfo->clauses [k];
3425
3426                         encode_value (ei->exvar_offset, p, &p);
3427
3428                         if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
3429                                 encode_value ((gint)((guint8*)ei->data.filter - code), p, &p);
3430
3431                         encode_value ((gint)((guint8*)ei->try_start - code), p, &p);
3432                         encode_value ((gint)((guint8*)ei->try_end - code), p, &p);
3433                         encode_value ((gint)((guint8*)ei->handler_start - code), p, &p);
3434                 }
3435         }
3436
3437         if (jinfo->has_generic_jit_info) {
3438                 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (jinfo);
3439
3440                 encode_value (gi->has_this ? 1 : 0, p, &p);
3441                 encode_value (gi->this_reg, p, &p);
3442                 encode_value (gi->this_offset, p, &p);
3443
3444                 /* 
3445                  * Need to encode jinfo->method too, since it is not equal to 'method'
3446                  * when using generic sharing.
3447                  */
3448                 encode_method_ref (acfg, jinfo->method, p, &p);
3449         }
3450
3451         g_assert (debug_info_size < buf_size);
3452
3453         encode_value (debug_info_size, p, &p);
3454         if (debug_info_size) {
3455                 memcpy (p, debug_info, debug_info_size);
3456                 p += debug_info_size;
3457                 g_free (debug_info);
3458         }
3459
3460         acfg->stats.ex_info_size += p - buf;
3461
3462         /* Emit info */
3463
3464         emit_label (acfg, symbol);
3465
3466         g_assert (p - buf < buf_size);
3467         emit_bytes (acfg, buf, p - buf);
3468         g_free (buf);
3469 }
3470
3471 static void
3472 emit_klass_info (MonoAotCompile *acfg, guint32 token)
3473 {
3474         MonoClass *klass = mono_class_get (acfg->image, token);
3475         guint8 *p, *buf;
3476         int i, buf_size;
3477         char symbol [128];
3478         gboolean no_special_static, cant_encode;
3479         gpointer iter = NULL;
3480
3481         buf_size = 10240 + (klass->vtable_size * 16);
3482         p = buf = g_malloc (buf_size);
3483
3484         g_assert (klass);
3485
3486         mono_class_init (klass);
3487
3488         mono_class_get_nested_types (klass, &iter);
3489         g_assert (klass->nested_classes_inited);
3490
3491         mono_class_setup_vtable (klass);
3492
3493         /* 
3494          * Emit all the information which is required for creating vtables so
3495          * the runtime does not need to create the MonoMethod structures which
3496          * take up a lot of space.
3497          */
3498
3499         no_special_static = !mono_class_has_special_static_fields (klass);
3500
3501         /* Check whenever we have enough info to encode the vtable */
3502         cant_encode = FALSE;
3503         for (i = 0; i < klass->vtable_size; ++i) {
3504                 MonoMethod *cm = klass->vtable [i];
3505
3506                 if (cm && mono_method_signature (cm)->is_inflated && !g_hash_table_lookup (acfg->token_info_hash, cm))
3507                         cant_encode = TRUE;
3508         }
3509
3510         if (klass->generic_container || cant_encode) {
3511                 encode_value (-1, p, &p);
3512         } else {
3513                 encode_value (klass->vtable_size, p, &p);
3514                 encode_value ((no_special_static << 7) | (klass->has_static_refs << 6) | (klass->has_references << 5) | ((klass->blittable << 4) | (klass->nested_classes ? 1 : 0) << 3) | (klass->has_cctor << 2) | (klass->has_finalize << 1) | klass->ghcimpl, p, &p);
3515                 if (klass->has_cctor)
3516                         encode_method_ref (acfg, mono_class_get_cctor (klass), p, &p);
3517                 if (klass->has_finalize)
3518                         encode_method_ref (acfg, mono_class_get_finalizer (klass), p, &p);
3519  
3520                 encode_value (klass->instance_size, p, &p);
3521                 encode_value (mono_class_data_size (klass), p, &p);
3522                 encode_value (klass->packing_size, p, &p);
3523                 encode_value (klass->min_align, p, &p);
3524
3525                 for (i = 0; i < klass->vtable_size; ++i) {
3526                         MonoMethod *cm = klass->vtable [i];
3527
3528                         if (cm)
3529                                 encode_method_ref (acfg, cm, p, &p);
3530                         else
3531                                 encode_value (0, p, &p);
3532                 }
3533         }
3534
3535         acfg->stats.class_info_size += p - buf;
3536
3537         /* Emit the info */
3538         sprintf (symbol, ".LK_I_%x", token - MONO_TOKEN_TYPE_DEF - 1);
3539         emit_label (acfg, symbol);
3540
3541         g_assert (p - buf < buf_size);
3542         emit_bytes (acfg, buf, p - buf);
3543         g_free (buf);
3544 }
3545
3546 /*
3547  * Calls made from AOTed code are routed through a table of jumps similar to the
3548  * ELF PLT (Program Linkage Table). The differences are the following:
3549  * - the ELF PLT entries make an indirect jump though the GOT so they expect the
3550  *   GOT pointer to be in EBX. We want to avoid this, so our table contains direct
3551  *   jumps. This means the jumps need to be patched when the address of the callee is
3552  *   known. Initially the PLT entries jump to code which transfers control to the
3553  *   AOT runtime through the first PLT entry.
3554  */
3555 static void
3556 emit_plt (MonoAotCompile *acfg)
3557 {
3558         char symbol [128];
3559         int i;
3560
3561         emit_line (acfg);
3562         sprintf (symbol, "plt");
3563
3564         emit_section_change (acfg, ".text", 0);
3565         emit_global (acfg, symbol, TRUE);
3566 #ifdef __i386__
3567         /* This section will be made read-write by the AOT loader */
3568         emit_alignment (acfg, PAGESIZE);
3569 #else
3570         emit_alignment (acfg, 16);
3571 #endif
3572         emit_label (acfg, symbol);
3573
3574         for (i = 0; i < acfg->plt_offset; ++i) {
3575                 char label [128];
3576 #if defined(__arm__)
3577                 guint8 buf [256];
3578                 guint8 *code;
3579 #endif
3580
3581                 sprintf (label, ".Lp_%d", i);
3582                 emit_label (acfg, label);
3583
3584                 /* 
3585                  * The first plt entry is used to transfer code to the AOT loader. 
3586                  */
3587
3588 #if defined(__i386__)
3589                 if (i == 0) {
3590                         /* It is filled up during loading by the AOT loader. */
3591                         emit_zero_bytes (acfg, 16);
3592                 } else {
3593                         /* Need to make sure this is 9 bytes long */
3594                         emit_byte (acfg, '\xe9');
3595                         emit_symbol_diff (acfg, "plt", ".", -4);
3596                         emit_int32 (acfg, acfg->plt_got_info_offsets [i]);
3597                 }
3598 #elif defined(__x86_64__)
3599                 /*
3600                  * We can't emit jumps because they are 32 bits only so they can't be patched.
3601                  * So we make indirect calls through GOT entries which are patched by the AOT 
3602                  * loader to point to .Lpd entries. 
3603                  * An x86_64 plt entry is 10 bytes long, init_plt () depends on this.
3604                  */
3605                 /* jmpq *<offset>(%rip) */
3606                 emit_byte (acfg, '\xff');
3607                 emit_byte (acfg, '\x25');
3608                 emit_symbol_diff (acfg, "got", ".", ((acfg->plt_got_offset_base + i) * sizeof (gpointer)) -4);
3609                 /* Used by mono_aot_get_plt_info_offset */
3610                 emit_int32 (acfg, acfg->plt_got_info_offsets [i]);
3611 #elif defined(__arm__)
3612                 /* FIXME:
3613                  * - optimize OP_AOTCONST implementation
3614                  * - optimize the PLT entries
3615                  * - optimize SWITCH AOT implementation
3616                  * - implement IMT support
3617                  */
3618                 code = buf;
3619 #ifdef USE_BIN_WRITER
3620                 /* We only emit 1 relocation since we implement it ourselves anyway */
3621                 emit_reloc (acfg, R_ARM_ALU_PC_G0_NC, "got", ((acfg->plt_got_offset_base + i) * sizeof (gpointer)) - 8);
3622                 /* FIXME: A 2 instruction encoding is sufficient in most cases */
3623                 ARM_ADD_REG_IMM (code, ARMREG_IP, ARMREG_PC, 0, 0);
3624                 ARM_ADD_REG_IMM (code, ARMREG_IP, ARMREG_IP, 0, 0);
3625                 ARM_LDR_IMM (code, ARMREG_PC, ARMREG_IP, 0);
3626                 emit_bytes (acfg, buf, code - buf);
3627                 /* FIXME: Get rid of this */
3628                 emit_symbol_diff (acfg, "got", ".", ((acfg->plt_got_offset_base + i) * sizeof (gpointer)));
3629                 /* Used by mono_aot_get_plt_info_offset */
3630                 emit_int32 (acfg, acfg->plt_got_info_offsets [i]);
3631 #else
3632                 ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 4);
3633                 ARM_ADD_REG_REG (code, ARMREG_IP, ARMREG_PC, ARMREG_IP);
3634                 ARM_LDR_IMM (code, ARMREG_PC, ARMREG_IP, 0);
3635                 emit_bytes (acfg, buf, code - buf);
3636                 emit_symbol_diff (acfg, "got", ".", ((acfg->plt_got_offset_base + i) * sizeof (gpointer)));
3637                 /* Used by mono_aot_get_plt_info_offset */
3638                 emit_int32 (acfg, acfg->plt_got_info_offsets [i]);
3639 #endif
3640
3641 #else
3642                 g_assert_not_reached ();
3643 #endif
3644         }
3645
3646         sprintf (symbol, "plt_end");
3647         emit_global (acfg, symbol, TRUE);
3648         emit_label (acfg, symbol);
3649 }
3650
3651 static G_GNUC_UNUSED void
3652 emit_named_code (MonoAotCompile *acfg, const char *name, guint8 *code, 
3653                                  guint32 code_size, int got_offset, MonoJumpInfo *ji)
3654 {
3655         char symbol [256];
3656         guint32 buf_size;
3657         MonoJumpInfo *patch_info;
3658         guint8 *buf, *p;
3659         GPtrArray *patches;
3660
3661         /* Emit code */
3662
3663         sprintf (symbol, "%s", name);
3664
3665         emit_section_change (acfg, ".text", 0);
3666         emit_global (acfg, symbol, TRUE);
3667         emit_alignment (acfg, 16);
3668         emit_label (acfg, symbol);
3669
3670         /* 
3671          * The code should access everything through the GOT, so we pass
3672          * TRUE here.
3673          */
3674         emit_and_reloc_code (acfg, NULL, code, code_size, ji, TRUE);
3675
3676         /* Emit info */
3677
3678         /* Sort relocations */
3679         patches = g_ptr_array_new ();
3680         for (patch_info = ji; patch_info; patch_info = patch_info->next)
3681                 g_ptr_array_add (patches, patch_info);
3682         g_ptr_array_sort (patches, compare_patches);
3683
3684         buf_size = patches->len * 128 + 128;
3685         buf = g_malloc (buf_size);
3686         p = buf;
3687
3688         encode_patch_list (acfg, patches, patches->len, got_offset, p, &p);
3689         g_assert (p - buf < buf_size);
3690
3691         sprintf (symbol, "%s_p", name);
3692
3693         emit_section_change (acfg, ".text", 0);
3694         emit_global (acfg, symbol, FALSE);
3695         emit_label (acfg, symbol);
3696                 
3697         emit_bytes (acfg, buf, p - buf);
3698 }
3699
3700 /*
3701  * When running in aot-only mode, we can't create trampolines at runtime, so we create 
3702  * a few, and save them in the AOT file. Normal trampolines embed their argument as a 
3703  * literal inside the trampoline code, we can't do that here, so instead we embed an offset
3704  * which needs to be added to the trampoline address to get the address of the GOT slot
3705  * which contains the argument value.
3706  * The generated trampolines jump to the generic trampolines using another GOT slot, which
3707  * will be setup by the AOT loader to point to the generic trampoline code of the given 
3708  * type.
3709  */
3710 static void
3711 emit_trampolines (MonoAotCompile *acfg)
3712 {
3713         char symbol [256];
3714         int i, offset;
3715 #ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
3716         int tramp_type;
3717         guint32 code_size;
3718         MonoJumpInfo *ji;
3719         guint8 *code;
3720 #endif
3721
3722         if (!acfg->aot_opts.full_aot)
3723                 return;
3724         
3725         g_assert (acfg->image->assembly);
3726
3727         /* Currently, we only emit most trampolines into the mscorlib AOT image. */
3728         if (strcmp (acfg->image->assembly->aname.name, "mscorlib") == 0) {
3729 #ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
3730                 /*
3731                  * Emit the generic trampolines.
3732                  *
3733                  * We could save some code by treating the generic trampolines as a wrapper
3734                  * method, but that approach has its own complexities, so we choose the simpler
3735                  * method.
3736                  */
3737                 for (tramp_type = 0; tramp_type < MONO_TRAMPOLINE_NUM; ++tramp_type) {
3738                         code = mono_arch_create_trampoline_code_full (tramp_type, &code_size, &ji, TRUE);
3739
3740                         /* Emit trampoline code */
3741
3742                         sprintf (symbol, "generic_trampoline_%d", tramp_type);
3743
3744                         emit_named_code (acfg, symbol, code, code_size, acfg->got_offset, ji);
3745                 }
3746
3747                 code = mono_arch_get_nullified_class_init_trampoline (&code_size);
3748                 emit_named_code (acfg, "nullified_class_init_trampoline", code, code_size, acfg->got_offset, NULL);
3749 #if defined(__x86_64__) && defined(MONO_ARCH_MONITOR_OBJECT_REG)
3750                 code = mono_arch_create_monitor_enter_trampoline_full (&code_size, &ji, TRUE);
3751                 emit_named_code (acfg, "monitor_enter_trampoline", code, code_size, acfg->got_offset, ji);
3752                 code = mono_arch_create_monitor_exit_trampoline_full (&code_size, &ji, TRUE);
3753                 emit_named_code (acfg, "monitor_exit_trampoline", code, code_size, acfg->got_offset, ji);
3754 #endif
3755
3756                 /* Emit the exception related code pieces */
3757                 code = mono_arch_get_restore_context_full (&code_size, &ji, TRUE);
3758                 emit_named_code (acfg, "restore_context", code, code_size, acfg->got_offset, ji);
3759                 code = mono_arch_get_call_filter_full (&code_size, &ji, TRUE);
3760                 emit_named_code (acfg, "call_filter", code, code_size, acfg->got_offset, ji);
3761                 code = mono_arch_get_throw_exception_full (&code_size, &ji, TRUE);
3762                 emit_named_code (acfg, "throw_exception", code, code_size, acfg->got_offset, ji);
3763                 code = mono_arch_get_rethrow_exception_full (&code_size, &ji, TRUE);
3764                 emit_named_code (acfg, "rethrow_exception", code, code_size, acfg->got_offset, ji);
3765                 code = mono_arch_get_throw_exception_by_name_full (&code_size, &ji, TRUE);
3766                 emit_named_code (acfg, "throw_exception_by_name", code, code_size, acfg->got_offset, ji);
3767                 code = mono_arch_get_throw_corlib_exception_full (&code_size, &ji, TRUE);
3768                 emit_named_code (acfg, "throw_corlib_exception", code, code_size, acfg->got_offset, ji);
3769
3770 #if defined(__x86_64__) || defined(__arm__)
3771                 for (i = 0; i < 128; ++i) {
3772                         int offset;
3773
3774                         offset = MONO_RGCTX_SLOT_MAKE_RGCTX (i);
3775                         code = mono_arch_create_rgctx_lazy_fetch_trampoline_full (offset, &code_size, &ji, TRUE);
3776                         sprintf (symbol, "rgctx_fetch_trampoline_%u", offset);
3777                         emit_named_code (acfg, symbol, code, code_size, acfg->got_offset, ji);
3778
3779                         offset = MONO_RGCTX_SLOT_MAKE_MRGCTX (i);
3780                         code = mono_arch_create_rgctx_lazy_fetch_trampoline_full (offset, &code_size, &ji, TRUE);
3781                         sprintf (symbol, "rgctx_fetch_trampoline_%u", offset);
3782                         emit_named_code (acfg, symbol, code, code_size, acfg->got_offset, ji);
3783                 }
3784 #endif
3785 #endif
3786
3787                 /*
3788                  * FIXME: Maybe we should use more specific trampolines (i.e. one class init for
3789                  * each class).
3790                  */
3791
3792                 /* Reserve some entries at the end of the GOT for our use */
3793                 acfg->num_trampoline_got_entries = acfg->num_aot_trampolines * 2;
3794
3795                 sprintf (symbol, "trampolines");
3796
3797                 emit_section_change (acfg, ".text", 0);
3798                 emit_global (acfg, symbol, TRUE);
3799                 emit_alignment (acfg, 16);
3800                 emit_label (acfg, symbol);
3801
3802                 for (i = 0; i < acfg->num_aot_trampolines; ++i) {
3803                         offset = acfg->got_offset + (i * 2);
3804
3805                         /*
3806                          * The trampolines created here are variations of the specific 
3807                          * trampolines created in mono_arch_create_specific_trampoline (). The 
3808                          * differences are:
3809                          * - the generic trampoline address is taken from a got slot.
3810                          * - the offset of the got slot where the trampoline argument is stored
3811                          *   is embedded in the instruction stream, and the generic trampoline
3812                          *   can load the argument by loading the offset, adding it to the
3813                          *   address of the trampoline to get the address of the got slot, and
3814                          *   loading the argument from the there.
3815                          */
3816 #if defined(__x86_64__)
3817                         /* This should be exactly 16 bytes long */
3818                         /* It should work together with the generic trampoline code in tramp-amd64.c */
3819                         /* call *<offset>(%rip) */
3820                         emit_byte (acfg, '\x41');
3821                         emit_byte (acfg, '\xff');
3822                         emit_byte (acfg, '\x15');
3823                         emit_symbol_diff (acfg, "got", ".", (offset * sizeof (gpointer)) - 4);
3824                         /* This should be relative to the start of the trampoline */
3825                         emit_symbol_diff (acfg, "got", ".", (offset * sizeof (gpointer)) - 4 + 19);
3826                         emit_zero_bytes (acfg, 5);
3827 #elif defined(__arm__)
3828                         {
3829                                 guint8 buf [128];
3830
3831                                 /* Generate the trampoline code */
3832                                 /* This should be exactly 28 bytes long */
3833
3834                                 code = buf;
3835                                 ARM_PUSH (code, 0x5fff);
3836                                 ARM_LDR_IMM (code, ARMREG_R1, ARMREG_PC, 8);
3837                                 /* Load the value from the GOT */
3838                                 ARM_LDR_REG_REG (code, ARMREG_R1, ARMREG_PC, ARMREG_R1);
3839                                 /* Branch to it */
3840                                 ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_PC);
3841                                 ARM_MOV_REG_REG (code, ARMREG_PC, ARMREG_R1);
3842
3843                                 g_assert (code - buf == 20);
3844
3845                                 /* Emit it */
3846                                 emit_bytes (acfg, buf, code - buf);
3847                                 emit_symbol_diff (acfg, "got", ".", (offset * sizeof (gpointer)) - 4 + 8);
3848                                 emit_symbol_diff (acfg, "got", ".", ((offset + 1) * sizeof (gpointer)) - 4 + 8);
3849                         }
3850 #else
3851                         g_assert_not_reached ();
3852 #endif
3853                 }
3854         }
3855
3856         /* Unbox trampolines */
3857
3858         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
3859                 MonoMethod *method;
3860                 guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
3861                 MonoCompile *cfg;
3862                 char call_target [256];
3863
3864                 method = mono_get_method (acfg->image, token, NULL);
3865
3866                 cfg = g_hash_table_lookup (acfg->method_to_cfg, method);
3867                 if (!cfg || !cfg->orig_method->klass->valuetype || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL))
3868                         continue;
3869
3870                 sprintf (symbol, "unbox_trampoline_%d", i);
3871
3872                 emit_section_change (acfg, ".text", 0);
3873                 emit_global (acfg, symbol, TRUE);
3874                 emit_label (acfg, symbol);
3875
3876                 sprintf (call_target, ".Lm_%x", get_method_index (acfg, cfg->orig_method));
3877
3878 #if defined(__x86_64__)
3879                 {
3880                         guint8 buf [32];
3881                         int this_reg;
3882
3883                         this_reg = mono_arch_get_this_arg_reg (mono_method_signature (cfg->orig_method), cfg->generic_sharing_context, NULL);
3884                         code = buf;
3885                         amd64_alu_reg_imm (code, X86_ADD, this_reg, sizeof (MonoObject));
3886
3887                         emit_bytes (acfg, buf, code - buf);
3888                         /* jump <method> */
3889                         emit_byte (acfg, '\xe9');
3890                         emit_symbol_diff (acfg, call_target, ".", -4);
3891                 }
3892 #elif defined(__arm__)
3893                 {
3894                         guint8 buf [128];
3895                         int this_pos = 0;
3896
3897                         code = buf;
3898
3899                         if (MONO_TYPE_ISSTRUCT (mono_method_signature (cfg->orig_method)->ret))
3900                                 this_pos = 1;
3901
3902                         ARM_ADD_REG_IMM8 (code, this_pos, this_pos, sizeof (MonoObject));
3903
3904                         emit_bytes (acfg, buf, code - buf);
3905                         /* jump to method */
3906 #if defined(USE_BIN_WRITER)
3907                         /* FIXME: */
3908                         g_assert_not_reached ();
3909 #else
3910                         fprintf (acfg->fp, "\n\tb %s\n", call_target);
3911 #endif
3912                 }
3913 #else
3914                 g_assert_not_reached ();
3915 #endif
3916         }
3917
3918         sprintf (symbol, "trampolines_info");
3919
3920         emit_section_change (acfg, ".text", 0);
3921         emit_global (acfg, symbol, TRUE);
3922         emit_alignment (acfg, PAGESIZE);
3923         emit_label (acfg, symbol);
3924
3925         emit_int32 (acfg, acfg->num_aot_trampolines);
3926         emit_int32 (acfg, acfg->got_offset);
3927
3928         acfg->trampoline_got_offset_base = acfg->got_offset;
3929 }
3930
3931 static gboolean
3932 str_begins_with (const char *str1, const char *str2)
3933 {
3934         int len = strlen (str2);
3935         return strncmp (str1, str2, len) == 0;
3936 }
3937
3938 static void
3939 mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
3940 {
3941         gchar **args, **ptr;
3942
3943         args = g_strsplit (aot_options ? aot_options : "", ",", -1);
3944         for (ptr = args; ptr && *ptr; ptr ++) {
3945                 const char *arg = *ptr;
3946
3947                 if (str_begins_with (arg, "outfile=")) {
3948                         opts->outfile = g_strdup (arg + strlen ("outfile="));
3949                 } else if (str_begins_with (arg, "save-temps")) {
3950                         opts->save_temps = TRUE;
3951                 } else if (str_begins_with (arg, "keep-temps")) {
3952                         opts->save_temps = TRUE;
3953                 } else if (str_begins_with (arg, "write-symbols")) {
3954                         opts->write_symbols = TRUE;
3955                 } else if (str_begins_with (arg, "metadata-only")) {
3956                         opts->metadata_only = TRUE;
3957                 } else if (str_begins_with (arg, "bind-to-runtime-version")) {
3958                         opts->bind_to_runtime_version = TRUE;
3959                 } else if (str_begins_with (arg, "full")) {
3960                         opts->full_aot = TRUE;
3961                         /*
3962                          * The no-dlsym option is only useful on the iphone, and even there,
3963                          * do to other limitations of the dynamic linker, it doesn't seem to
3964                          * work. So disable it for now so we don't have to support it.
3965                          */
3966                         /*
3967                 } else if (str_begins_with (arg, "no-dlsym")) {
3968                         opts->no_dlsym = TRUE;
3969                         */
3970                 } else if (str_begins_with (arg, "threads=")) {
3971                         opts->nthreads = atoi (arg + strlen ("threads="));
3972                 } else if (str_begins_with (arg, "static")) {
3973                         opts->static_link = TRUE;
3974                         opts->no_dlsym = TRUE;
3975                 } else if (str_begins_with (arg, "asmonly")) {
3976                         opts->asm_only = TRUE;
3977                 } else {
3978                         fprintf (stderr, "AOT : Unknown argument '%s'.\n", arg);
3979                         exit (1);
3980                 }
3981         }
3982
3983         g_strfreev (args);
3984 }
3985
3986 static void
3987 add_token_info_hash (gpointer key, gpointer value, gpointer user_data)
3988 {
3989         MonoMethod *method = (MonoMethod*)key;
3990         MonoJumpInfoToken *ji = (MonoJumpInfoToken*)value;
3991         MonoJumpInfoToken *new_ji = g_new0 (MonoJumpInfoToken, 1);
3992         MonoAotCompile *acfg = user_data;
3993
3994         new_ji->image = ji->image;
3995         new_ji->token = ji->token;
3996         g_hash_table_insert (acfg->token_info_hash, method, new_ji);
3997 }
3998
3999 /*
4000  * compile_method:
4001  *
4002  *   AOT compile a given method.
4003  * This function might be called by multiple threads, so it must be thread-safe.
4004  */
4005 static void
4006 compile_method (MonoAotCompile *acfg, MonoMethod *method)
4007 {
4008         MonoCompile *cfg;
4009         MonoJumpInfo *patch_info;
4010         gboolean skip;
4011         int index;
4012         MonoMethod *wrapped;
4013
4014         if (acfg->aot_opts.metadata_only)
4015                 return;
4016
4017         mono_acfg_lock (acfg);
4018         index = get_method_index (acfg, method);
4019         mono_acfg_unlock (acfg);
4020
4021         /* fixme: maybe we can also precompile wrapper methods */
4022         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
4023                 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
4024                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT)) {
4025                 //printf ("Skip (impossible): %s\n", mono_method_full_name (method, TRUE));
4026                 return;
4027         }
4028
4029         if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
4030                 return;
4031
4032         wrapped = mono_marshal_method_from_wrapper (method);
4033         if (wrapped && (wrapped->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && wrapped->is_generic)
4034                 // FIXME: The wrapper should be generic too, but it is not
4035                 return;
4036
4037         InterlockedIncrement (&acfg->stats.mcount);
4038
4039 #if 0
4040         if (method->is_generic || method->klass->generic_container) {
4041                 InterlockedIncrement (&acfg->stats.genericcount);
4042                 return;
4043         }
4044 #endif
4045
4046         if (acfg->aot_opts.full_aot)
4047                 mono_use_imt = FALSE;
4048
4049         /*
4050          * Since these methods are the only ones which are compiled with
4051          * AOT support, and they are not used by runtime startup/shutdown code,
4052          * the runtime will not see AOT methods during AOT compilation,so it
4053          * does not need to support them by creating a fake GOT etc.
4054          */
4055         cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), FALSE, TRUE, 0);
4056         if (cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) {
4057                 //printf ("F: %s\n", mono_method_full_name (method, TRUE));
4058                 InterlockedIncrement (&acfg->stats.genericcount);
4059                 return;
4060         }
4061         if (cfg->exception_type != MONO_EXCEPTION_NONE) {
4062                 /* Let the exception happen at runtime */
4063                 return;
4064         }
4065
4066         if (cfg->disable_aot) {
4067                 //printf ("Skip (other): %s\n", mono_method_full_name (method, TRUE));
4068                 InterlockedIncrement (&acfg->stats.ocount);
4069                 mono_destroy_compile (cfg);
4070                 return;
4071         }
4072
4073         /* Nullify patches which need no aot processing */
4074         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
4075                 switch (patch_info->type) {
4076                 case MONO_PATCH_INFO_LABEL:
4077                 case MONO_PATCH_INFO_BB:
4078                         patch_info->type = MONO_PATCH_INFO_NONE;
4079                         break;
4080                 default:
4081                         break;
4082                 }
4083         }
4084
4085         /* Collect method->token associations from the cfg */
4086         mono_acfg_lock (acfg);
4087         g_hash_table_foreach (cfg->token_info_hash, add_token_info_hash, acfg);
4088         mono_acfg_unlock (acfg);
4089
4090         /*
4091          * Check for absolute addresses.
4092          */
4093         skip = FALSE;
4094         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
4095                 switch (patch_info->type) {
4096                 case MONO_PATCH_INFO_ABS:
4097                         /* unable to handle this */
4098                         //printf ("Skip (abs addr):   %s %d\n", mono_method_full_name (method, TRUE), patch_info->type);
4099                         skip = TRUE;    
4100                         break;
4101                 default:
4102                         break;
4103                 }
4104         }
4105
4106         if (skip) {
4107                 InterlockedIncrement (&acfg->stats.abscount);
4108                 mono_destroy_compile (cfg);
4109                 return;
4110         }
4111
4112         /*
4113          * Check for wrapper methods we can't encode.
4114          */
4115         skip = FALSE;
4116         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
4117                 if ((patch_info->type == MONO_PATCH_INFO_METHODCONST) || (patch_info->type == MONO_PATCH_INFO_METHOD)) {
4118                         switch (patch_info->data.method->wrapper_type) {
4119                         case MONO_WRAPPER_NONE:
4120                         case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
4121                         case MONO_WRAPPER_XDOMAIN_INVOKE:
4122                         case MONO_WRAPPER_STFLD:
4123                         case MONO_WRAPPER_LDFLD:
4124                         case MONO_WRAPPER_LDFLDA:
4125                         case MONO_WRAPPER_LDFLD_REMOTE:
4126                         case MONO_WRAPPER_STFLD_REMOTE:
4127                         case MONO_WRAPPER_STELEMREF:
4128                         case MONO_WRAPPER_ISINST:
4129                         case MONO_WRAPPER_PROXY_ISINST:
4130                         case MONO_WRAPPER_ALLOC:
4131                         case MONO_WRAPPER_REMOTING_INVOKE:
4132                         case MONO_WRAPPER_STATIC_RGCTX_INVOKE:
4133                         case MONO_WRAPPER_UNKNOWN:
4134                                 break;
4135                         default:
4136                                 /* unable to handle this */
4137                                 //printf ("Skip (wrapper call):   %s %d -> %s\n", mono_method_full_name (method, TRUE), patch_info->type, mono_method_full_name (patch_info->data.method, TRUE));
4138                                 skip = TRUE;
4139                                 break;
4140                         }
4141                 } else if (patch_info->type == MONO_PATCH_INFO_RGCTX_FETCH) {
4142                         MonoJumpInfo *child = patch_info->data.rgctx_entry->data;
4143
4144                         if (child->type == MONO_PATCH_INFO_METHODCONST) {
4145                                 switch (child->data.method->wrapper_type) {
4146                                 case MONO_WRAPPER_NONE:
4147                                 case MONO_WRAPPER_STATIC_RGCTX_INVOKE:
4148                                         break;
4149                                 default:
4150                                         skip = TRUE;
4151                                 }
4152                         }
4153                 }
4154         }
4155
4156         if (skip) {
4157                 InterlockedIncrement (&acfg->stats.wrappercount);
4158                 mono_destroy_compile (cfg);
4159                 return;
4160         }
4161
4162         /* Lock for the rest of the code */
4163         mono_acfg_lock (acfg);
4164
4165         /*
4166          * Check for methods/klasses we can't encode.
4167          */
4168         skip = FALSE;
4169         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
4170                 switch (patch_info->type) {
4171                 case MONO_PATCH_INFO_METHOD:
4172                 case MONO_PATCH_INFO_METHODCONST:
4173                         if (patch_info->data.method->wrapper_type)
4174                                 break;
4175                         if (!patch_info->data.method->token) {
4176                                 /* The method is part of a constructed type like Int[,].Set (). */
4177                                 if (!g_hash_table_lookup (acfg->token_info_hash, patch_info->data.method))
4178                                         skip = TRUE;
4179                         }
4180                         break;
4181                 case MONO_PATCH_INFO_VTABLE:
4182                 case MONO_PATCH_INFO_CLASS_INIT:
4183                 case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
4184                 case MONO_PATCH_INFO_CLASS:
4185                 case MONO_PATCH_INFO_IID:
4186                 case MONO_PATCH_INFO_ADJUSTED_IID:
4187                         if (!patch_info->data.klass->type_token)
4188                                 if (!patch_info->data.klass->element_class->type_token && !(patch_info->data.klass->element_class->rank && patch_info->data.klass->element_class->element_class->type_token))
4189                                         skip = TRUE;
4190                         break;
4191                 default:
4192                         break;
4193                 }
4194         }
4195
4196         if (skip) {
4197                 acfg->stats.ocount++;
4198                 mono_destroy_compile (cfg);
4199                 mono_acfg_unlock (acfg);
4200                 return;
4201         }
4202
4203         /* Adds generic instances referenced by this method */
4204         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
4205                 switch (patch_info->type) {
4206                 case MONO_PATCH_INFO_METHOD: {
4207                         MonoMethod *m = patch_info->data.method;
4208                         if (m->is_inflated) {
4209                                 if (!(mono_class_generic_sharing_enabled (m->klass) &&
4210                                           mono_method_is_generic_sharable_impl (m, FALSE)) &&
4211                                         !method_has_type_vars (m))
4212                                         add_extra_method (acfg, m);
4213                         }
4214                         break;
4215                 }
4216                 default:
4217                         break;
4218                 }
4219         }
4220
4221         /* Determine whenever the method has GOT slots */
4222         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
4223                 switch (patch_info->type) {
4224                 case MONO_PATCH_INFO_GOT_OFFSET:
4225                 case MONO_PATCH_INFO_NONE:
4226                         break;
4227                 case MONO_PATCH_INFO_IMAGE:
4228                         /* The assembly is stored in GOT slot 0 */
4229                         if (patch_info->data.image != acfg->image)
4230                                 cfg->has_got_slots = TRUE;
4231                         break;
4232                 default:
4233                         if (!is_plt_patch (patch_info))
4234                                 cfg->has_got_slots = TRUE;
4235                         break;
4236                 }
4237         }
4238
4239         if (!cfg->has_got_slots)
4240                 InterlockedIncrement (&acfg->stats.methods_without_got_slots);
4241
4242         /* Make a copy of the patch info which is in the mempool */
4243         {
4244                 MonoJumpInfo *patches = NULL, *patches_end = NULL;
4245
4246                 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
4247                         MonoJumpInfo *new_patch_info = mono_patch_info_dup_mp (acfg->mempool, patch_info);
4248
4249                         if (!patches)
4250                                 patches = new_patch_info;
4251                         else
4252                                 patches_end->next = new_patch_info;
4253                         patches_end = new_patch_info;
4254                 }
4255                 cfg->patch_info = patches;
4256         }
4257         /* Make a copy of the unwind info */
4258         {
4259                 GSList *l, *unwind_ops;
4260                 MonoUnwindOp *op;
4261
4262                 unwind_ops = NULL;
4263                 for (l = cfg->unwind_ops; l; l = l->next) {
4264                         op = mono_mempool_alloc (acfg->mempool, sizeof (MonoUnwindOp));
4265                         memcpy (op, l->data, sizeof (MonoUnwindOp));
4266                         unwind_ops = g_slist_prepend_mempool (acfg->mempool, unwind_ops, op);
4267                 }
4268                 cfg->unwind_ops = g_slist_reverse (unwind_ops);
4269         }
4270         /* Make a copy of the argument info */
4271         {
4272                 MonoInst **args;
4273                 MonoMethodSignature *sig;
4274                 int i;
4275                 
4276                 sig = mono_method_signature (method);
4277                 args = mono_mempool_alloc (acfg->mempool, sizeof (MonoInst*) * (sig->param_count + sig->hasthis));
4278                 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
4279                         args [i] = mono_mempool_alloc (acfg->mempool, sizeof (MonoInst));
4280                         memcpy (args [i], cfg->args [i], sizeof (MonoInst));
4281                 }
4282                 cfg->args = args;
4283         }
4284
4285         /* Free some fields used by cfg to conserve memory */
4286         mono_mempool_destroy (cfg->mempool);
4287         cfg->mempool = NULL;
4288         g_free (cfg->varinfo);
4289         cfg->varinfo = NULL;
4290         g_free (cfg->vars);
4291         cfg->vars = NULL;
4292         if (cfg->rs) {
4293                 mono_regstate_free (cfg->rs);
4294                 cfg->rs = NULL;
4295         }
4296
4297         //printf ("Compile:           %s\n", mono_method_full_name (method, TRUE));
4298
4299         while (index >= acfg->cfgs_size) {
4300                 MonoCompile **new_cfgs;
4301                 int new_size;
4302
4303                 new_size = acfg->cfgs_size * 2;
4304                 new_cfgs = g_new0 (MonoCompile*, new_size);
4305                 memcpy (new_cfgs, acfg->cfgs, sizeof (MonoCompile*) * acfg->cfgs_size);
4306                 g_free (acfg->cfgs);
4307                 acfg->cfgs = new_cfgs;
4308                 acfg->cfgs_size = new_size;
4309         }
4310         acfg->cfgs [index] = cfg;
4311
4312         g_hash_table_insert (acfg->method_to_cfg, cfg->orig_method, cfg);
4313
4314         if (cfg->orig_method->wrapper_type)
4315                 g_ptr_array_add (acfg->extra_methods, cfg->orig_method);
4316
4317         mono_acfg_unlock (acfg);
4318
4319         InterlockedIncrement (&acfg->stats.ccount);
4320 }
4321  
4322 static void
4323 compile_thread_main (gpointer *user_data)
4324 {
4325         MonoDomain *domain = user_data [0];
4326         MonoAotCompile *acfg = user_data [1];
4327         GPtrArray *methods = user_data [2];
4328         int i;
4329
4330         mono_thread_attach (domain);
4331
4332         for (i = 0; i < methods->len; ++i)
4333                 compile_method (acfg, g_ptr_array_index (methods, i));
4334 }
4335
4336 static void
4337 load_profile_files (MonoAotCompile *acfg)
4338 {
4339         FILE *infile;
4340         char *tmp;
4341         int file_index, res, method_index, i;
4342         char ver [256];
4343         guint32 token;
4344         GList *unordered;
4345
4346         file_index = 0;
4347         while (TRUE) {
4348                 tmp = g_strdup_printf ("%s/.mono/aot-profile-data/%s-%s-%d", g_get_home_dir (), acfg->image->assembly_name, acfg->image->guid, file_index);
4349
4350                 if (!g_file_test (tmp, G_FILE_TEST_IS_REGULAR)) {
4351                         g_free (tmp);
4352                         break;
4353                 }
4354
4355                 infile = fopen (tmp, "r");
4356                 g_assert (infile);
4357
4358                 printf ("Using profile data file '%s'\n", tmp);
4359                 g_free (tmp);
4360
4361                 file_index ++;
4362
4363                 res = fscanf (infile, "%32s\n", ver);
4364                 if ((res != 1) || strcmp (ver, "#VER:1") != 0) {
4365                         printf ("Profile file has wrong version or invalid.\n");
4366                         fclose (infile);
4367                         continue;
4368                 }
4369
4370                 while (TRUE) {
4371                         res = fscanf (infile, "%d\n", &token);
4372                         if (res < 1)
4373                                 break;
4374
4375                         method_index = mono_metadata_token_index (token) - 1;
4376
4377                         if (!g_list_find (acfg->method_order, GUINT_TO_POINTER (method_index)))
4378                                 acfg->method_order = g_list_append (acfg->method_order, GUINT_TO_POINTER (method_index));
4379                 }
4380                 fclose (infile);
4381         }
4382
4383         /* Add missing methods */
4384         unordered = NULL;
4385         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
4386                 if (!g_list_find (acfg->method_order, GUINT_TO_POINTER (i)))
4387                         unordered = g_list_prepend (unordered, GUINT_TO_POINTER (i));
4388         }
4389         unordered = g_list_reverse (unordered);
4390         if (acfg->method_order)
4391                 g_list_last (acfg->method_order)->next = unordered;
4392         else
4393                 acfg->method_order = unordered;
4394 }
4395
4396 /**
4397  * alloc_got_slots:
4398  *
4399  *  Collect all patches which have shared GOT entries and alloc entries for them. The
4400  * rest will get entries allocated during emit_code ().
4401  */
4402 static void
4403 alloc_got_slots (MonoAotCompile *acfg)
4404 {
4405         int i;
4406         GList *l;
4407         MonoJumpInfo *ji;
4408
4409         /* Slot 0 is reserved for the address of the current assembly */
4410         ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
4411         ji->type = MONO_PATCH_INFO_IMAGE;
4412         ji->data.image = acfg->image;
4413
4414         get_shared_got_offset (acfg, ji);
4415
4416         for (l = acfg->method_order; l != NULL; l = l->next) {
4417                 i = GPOINTER_TO_UINT (l->data);
4418
4419                 if (acfg->cfgs [i]) {
4420                         MonoCompile *cfg = acfg->cfgs [i];
4421
4422                         for (ji = cfg->patch_info; ji; ji = ji->next) {
4423                                 if (is_shared_got_patch (ji))
4424                                         get_shared_got_offset (acfg, ji);
4425                         }
4426                 }
4427         }
4428 }
4429
4430 static void
4431 emit_code (MonoAotCompile *acfg)
4432 {
4433         int i;
4434         char symbol [256];
4435         GList *l;
4436
4437         sprintf (symbol, "methods");
4438         emit_section_change (acfg, ".text", 0);
4439         emit_global (acfg, symbol, TRUE);
4440         emit_alignment (acfg, 8);
4441         emit_label (acfg, symbol);
4442
4443         /* 
4444          * Emit some padding so the local symbol for the first method doesn't have the
4445          * same address as 'methods'.
4446          */
4447         emit_zero_bytes (acfg, 16);
4448
4449         for (l = acfg->method_order; l != NULL; l = l->next) {
4450                 i = GPOINTER_TO_UINT (l->data);
4451
4452                 if (acfg->cfgs [i])
4453                         emit_method_code (acfg, acfg->cfgs [i]);
4454         }
4455
4456         sprintf (symbol, "methods_end");
4457         emit_section_change (acfg, ".text", 0);
4458         emit_global (acfg, symbol, FALSE);
4459         emit_alignment (acfg, 8);
4460         emit_label (acfg, symbol);
4461
4462         sprintf (symbol, "method_offsets");
4463         emit_section_change (acfg, ".text", 1);
4464         emit_global (acfg, symbol, FALSE);
4465         emit_alignment (acfg, 8);
4466         emit_label (acfg, symbol);
4467
4468         for (i = 0; i < acfg->nmethods; ++i) {
4469                 if (acfg->cfgs [i]) {
4470                         sprintf (symbol, ".Lm_%x", i);
4471                         emit_symbol_diff (acfg, symbol, "methods", 0);
4472                 } else {
4473                         emit_int32 (acfg, 0xffffffff);
4474                 }
4475         }
4476         emit_line (acfg);
4477 }
4478
4479 static void
4480 emit_info (MonoAotCompile *acfg)
4481 {
4482         int i;
4483         char symbol [256];
4484         GList *l;
4485
4486         /* Emit method info */
4487         sprintf (symbol, "method_info");
4488         emit_section_change (acfg, ".text", 1);
4489         emit_global (acfg, symbol, FALSE);
4490         emit_alignment (acfg, 8);
4491         emit_label (acfg, symbol);
4492
4493         /* To reduce size of generated assembly code */
4494         sprintf (symbol, "mi");
4495         emit_label (acfg, symbol);
4496
4497         for (l = acfg->method_order; l != NULL; l = l->next) {
4498                 i = GPOINTER_TO_UINT (l->data);
4499
4500                 if (acfg->cfgs [i])
4501                         emit_method_info (acfg, acfg->cfgs [i]);
4502         }
4503
4504         sprintf (symbol, "method_info_offsets");
4505         emit_section_change (acfg, ".text", 1);
4506         emit_global (acfg, symbol, FALSE);
4507         emit_alignment (acfg, 8);
4508         emit_label (acfg, symbol);
4509
4510         for (i = 0; i < acfg->nmethods; ++i) {
4511                 if (acfg->cfgs [i]) {
4512                         sprintf (symbol, ".Lm_%x_p", i);
4513                         emit_symbol_diff (acfg, symbol, "mi", 0);
4514                 } else {
4515                         emit_int32 (acfg, 0);
4516                 }
4517         }
4518         emit_line (acfg);
4519 }
4520  
4521 typedef struct HashEntry {
4522     guint32 key, value, index;
4523         struct HashEntry *next;
4524 } HashEntry;
4525
4526 /*
4527  * emit_extra_methods:
4528  *
4529  * Emit methods which are not in the METHOD table, like wrappers.
4530  */
4531 static void
4532 emit_extra_methods (MonoAotCompile *acfg)
4533 {
4534         int i, table_size, buf_size;
4535         char symbol [256];
4536         guint8 *p, *buf;
4537         guint32 *info_offsets;
4538         guint32 hash;
4539         GPtrArray *table;
4540         HashEntry *entry, *new_entry;
4541         int nmethods;
4542
4543         info_offsets = g_new0 (guint32, acfg->extra_methods->len);
4544
4545         buf_size = acfg->extra_methods->len * 256 + 256;
4546         p = buf = g_malloc (buf_size);
4547
4548         /* Encode method info */
4549         nmethods = 0;
4550         /* So offsets are > 0 */
4551         *p = 0;
4552         p++;
4553         for (i = 0; i < acfg->extra_methods->len; ++i) {
4554                 MonoMethod *method = g_ptr_array_index (acfg->extra_methods, i);
4555                 MonoCompile *cfg = g_hash_table_lookup (acfg->method_to_cfg, method);
4556
4557                 if (!cfg)
4558                         continue;
4559
4560                 nmethods ++;
4561                 info_offsets [i] = p - buf;
4562
4563                 if (method->wrapper_type) {
4564                         char *name;
4565
4566                         // FIXME: Optimize disk usage
4567                         if (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE) {
4568                                 char *tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
4569                                 name = g_strdup_printf ("(wrapper runtime-invoke):%s (%s)", method->name, tmpsig);
4570                                 g_free (tmpsig);
4571                         } else {
4572                                 name = mono_method_full_name (cfg->orig_method, TRUE);
4573                         }
4574
4575                         encode_value (1, p, &p);
4576                         strcpy ((char*)p, name);
4577                         p += strlen (name ) + 1;
4578                         g_free (name);
4579                 } else {
4580                         encode_value (0, p, &p);
4581                         encode_method_ref (acfg, method, p, &p);
4582                 }
4583
4584                 g_assert ((p - buf) < buf_size);
4585         }
4586
4587         g_assert ((p - buf) < buf_size);
4588
4589         /* Emit method info */
4590         sprintf (symbol, "extra_method_info");
4591         emit_section_change (acfg, ".text", 1);
4592         emit_global (acfg, symbol, FALSE);
4593         emit_alignment (acfg, 8);
4594         emit_label (acfg, symbol);
4595
4596         emit_bytes (acfg, buf, p - buf);
4597
4598         emit_line (acfg);
4599
4600         /*
4601          * Construct a chained hash table for mapping indexes in extra_method_info to
4602          * method indexes.
4603          */
4604         table_size = g_spaced_primes_closest ((int)(nmethods * 1.5));
4605         table = g_ptr_array_sized_new (table_size);
4606         for (i = 0; i < table_size; ++i)
4607                 g_ptr_array_add (table, NULL);
4608         for (i = 0; i < acfg->extra_methods->len; ++i) {
4609                 MonoMethod *method = g_ptr_array_index (acfg->extra_methods, i);
4610                 MonoCompile *cfg = g_hash_table_lookup (acfg->method_to_cfg, method);
4611                 guint32 key, value;
4612
4613                 if (!cfg)
4614                         continue;
4615
4616                 key = info_offsets [i];
4617                 value = get_method_index (acfg, method);
4618
4619                 if (method->wrapper_type) {
4620                         hash = g_str_hash (method->name) % table_size;
4621                 } else {
4622                         // FIXME:
4623                         hash = 0 % table_size;
4624                 }
4625
4626                 /* FIXME: Allocate from the mempool */
4627                 new_entry = g_new0 (HashEntry, 1);
4628                 new_entry->key = key;
4629                 new_entry->value = value;
4630
4631                 entry = g_ptr_array_index (table, hash);
4632                 if (entry == NULL) {
4633                         new_entry->index = hash;
4634                         g_ptr_array_index (table, hash) = new_entry;
4635                 } else {
4636                         while (entry->next)
4637                                 entry = entry->next;
4638                         
4639                         entry->next = new_entry;
4640                         new_entry->index = table->len;
4641                         g_ptr_array_add (table, new_entry);
4642                 }
4643         }
4644
4645         /* Emit the table */
4646         sprintf (symbol, "extra_method_table");
4647         emit_section_change (acfg, ".text", 0);
4648         emit_global (acfg, symbol, FALSE);
4649         emit_alignment (acfg, 8);
4650         emit_label (acfg, symbol);
4651
4652         g_assert (table_size < 65000);
4653         emit_int32 (acfg, table_size);
4654         g_assert (table->len < 65000);
4655         for (i = 0; i < table->len; ++i) {
4656                 HashEntry *entry = g_ptr_array_index (table, i);
4657
4658                 if (entry == NULL) {
4659                         emit_int32 (acfg, 0);
4660                         emit_int32 (acfg, 0);
4661                         emit_int32 (acfg, 0);
4662                 } else {
4663                         g_assert (entry->key > 0);
4664                         emit_int32 (acfg, entry->key);
4665                         emit_int32 (acfg, entry->value);
4666                         if (entry->next)
4667                                 emit_int32 (acfg, entry->next->index);
4668                         else
4669                                 emit_int32 (acfg, 0);
4670                 }
4671         }
4672
4673         /* 
4674          * Emit a table reverse mapping method indexes to their index in extra_method_info.
4675          * This is used by mono_aot_find_jit_info ().
4676          */
4677         sprintf (symbol, "extra_method_info_offsets");
4678         emit_section_change (acfg, ".text", 0);
4679         emit_global (acfg, symbol, FALSE);
4680         emit_alignment (acfg, 8);
4681         emit_label (acfg, symbol);
4682
4683         emit_int32 (acfg, acfg->extra_methods->len);
4684         for (i = 0; i < acfg->extra_methods->len; ++i) {
4685                 MonoMethod *method = g_ptr_array_index (acfg->extra_methods, i);
4686
4687                 emit_int32 (acfg, get_method_index (acfg, method));
4688                 emit_int32 (acfg, info_offsets [i]);
4689         }
4690 }       
4691
4692 static void
4693 emit_method_order (MonoAotCompile *acfg)
4694 {
4695         int i, index, len;
4696         char symbol [256];
4697         GList *l;
4698
4699         sprintf (symbol, "method_order");
4700         emit_section_change (acfg, ".text", 1);
4701         emit_global (acfg, symbol, FALSE);
4702         emit_alignment (acfg, 8);
4703         emit_label (acfg, symbol);
4704
4705         /* First emit an index table */
4706         index = 0;
4707         len = 0;
4708         for (l = acfg->method_order; l != NULL; l = l->next) {
4709                 i = GPOINTER_TO_UINT (l->data);
4710
4711                 if (acfg->cfgs [i]) {
4712                         if ((index % 1024) == 0) {
4713                                 emit_int32 (acfg, i);
4714                         }
4715
4716                         index ++;
4717                 }
4718
4719                 len ++;
4720         }
4721         emit_int32 (acfg, 0xffffff);
4722
4723         /* Then emit the whole method order */
4724         for (l = acfg->method_order; l != NULL; l = l->next) {
4725                 i = GPOINTER_TO_UINT (l->data);
4726
4727                 if (acfg->cfgs [i]) {
4728                         emit_int32 (acfg, i);
4729                 }
4730         }       
4731         emit_line (acfg);
4732
4733         sprintf (symbol, "method_order_end");
4734         emit_section_change (acfg, ".text", 1);
4735         emit_global (acfg, symbol, FALSE);
4736         emit_label (acfg, symbol);
4737 }
4738
4739 static void
4740 emit_exception_info (MonoAotCompile *acfg)
4741 {
4742         int i;
4743         char symbol [256];
4744
4745         sprintf (symbol, "ex_info");
4746         emit_section_change (acfg, ".text", 1);
4747         emit_global (acfg, symbol, FALSE);
4748         emit_alignment (acfg, 8);
4749         emit_label (acfg, symbol);
4750
4751         /* To reduce size of generated assembly */
4752         sprintf (symbol, "ex");
4753         emit_label (acfg, symbol);
4754
4755         for (i = 0; i < acfg->nmethods; ++i) {
4756                 if (acfg->cfgs [i])
4757                         emit_exception_debug_info (acfg, acfg->cfgs [i]);
4758         }
4759
4760         sprintf (symbol, "ex_info_offsets");
4761         emit_section_change (acfg, ".text", 1);
4762         emit_global (acfg, symbol, FALSE);
4763         emit_alignment (acfg, 8);
4764         emit_label (acfg, symbol);
4765
4766         for (i = 0; i < acfg->nmethods; ++i) {
4767                 if (acfg->cfgs [i]) {
4768                         sprintf (symbol, ".Le_%x_p", i);
4769                         emit_symbol_diff (acfg, symbol, "ex", 0);
4770                 } else {
4771                         emit_int32 (acfg, 0);
4772                 }
4773         }
4774         emit_line (acfg);
4775 }
4776
4777 static void
4778 emit_class_info (MonoAotCompile *acfg)
4779 {
4780         int i;
4781         char symbol [256];
4782
4783         sprintf (symbol, "class_info");
4784         emit_section_change (acfg, ".text", 1);
4785         emit_global (acfg, symbol, FALSE);
4786         emit_alignment (acfg, 8);
4787         emit_label (acfg, symbol);
4788
4789         for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i)
4790                 emit_klass_info (acfg, MONO_TOKEN_TYPE_DEF | (i + 1));
4791
4792         sprintf (symbol, "class_info_offsets");
4793         emit_section_change (acfg, ".text", 1);
4794         emit_global (acfg, symbol, FALSE);
4795         emit_alignment (acfg, 8);
4796         emit_label (acfg, symbol);
4797
4798         for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
4799                 sprintf (symbol, ".LK_I_%x", i);
4800                 emit_symbol_diff (acfg, symbol, "class_info", 0);
4801         }
4802         emit_line (acfg);
4803 }
4804
4805 typedef struct ClassNameTableEntry {
4806         guint32 token, index;
4807         struct ClassNameTableEntry *next;
4808 } ClassNameTableEntry;
4809
4810 static void
4811 emit_class_name_table (MonoAotCompile *acfg)
4812 {
4813         int i, table_size;
4814         guint32 token, hash;
4815         MonoClass *klass;
4816         GPtrArray *table;
4817         char *full_name;
4818         char symbol [256];
4819         ClassNameTableEntry *entry, *new_entry;
4820
4821         /*
4822          * Construct a chained hash table for mapping class names to typedef tokens.
4823          */
4824         table_size = g_spaced_primes_closest ((int)(acfg->image->tables [MONO_TABLE_TYPEDEF].rows * 1.5));
4825         table = g_ptr_array_sized_new (table_size);
4826         for (i = 0; i < table_size; ++i)
4827                 g_ptr_array_add (table, NULL);
4828         for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
4829                 token = MONO_TOKEN_TYPE_DEF | (i + 1);
4830                 klass = mono_class_get (acfg->image, token);
4831                 full_name = mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_FULL_NAME);
4832                 hash = g_str_hash (full_name) % table_size;
4833                 g_free (full_name);
4834
4835                 /* FIXME: Allocate from the mempool */
4836                 new_entry = g_new0 (ClassNameTableEntry, 1);
4837                 new_entry->token = token;
4838
4839                 entry = g_ptr_array_index (table, hash);
4840                 if (entry == NULL) {
4841                         new_entry->index = hash;
4842                         g_ptr_array_index (table, hash) = new_entry;
4843                 } else {
4844                         while (entry->next)
4845                                 entry = entry->next;
4846                         
4847                         entry->next = new_entry;
4848                         new_entry->index = table->len;
4849                         g_ptr_array_add (table, new_entry);
4850                 }
4851         }
4852
4853         /* Emit the table */
4854         sprintf (symbol, "class_name_table");
4855         emit_section_change (acfg, ".text", 0);
4856         emit_global (acfg, symbol, FALSE);
4857         emit_alignment (acfg, 8);
4858         emit_label (acfg, symbol);
4859
4860         /* FIXME: Optimize memory usage */
4861         g_assert (table_size < 65000);
4862         emit_int16 (acfg, table_size);
4863         g_assert (table->len < 65000);
4864         for (i = 0; i < table->len; ++i) {
4865                 ClassNameTableEntry *entry = g_ptr_array_index (table, i);
4866
4867                 if (entry == NULL) {
4868                         emit_int16 (acfg, 0);
4869                         emit_int16 (acfg, 0);
4870                 } else {
4871                         emit_int16 (acfg, mono_metadata_token_index (entry->token));
4872                         if (entry->next)
4873                                 emit_int16 (acfg, entry->next->index);
4874                         else
4875                                 emit_int16 (acfg, 0);
4876                 }
4877         }
4878 }
4879
4880 static void
4881 emit_image_table (MonoAotCompile *acfg)
4882 {
4883         int i;
4884         char symbol [256];
4885
4886         /*
4887          * The image table is small but referenced in a lot of places.
4888          * So we emit it at once, and reference its elements by an index.
4889          */
4890
4891         sprintf (symbol, "mono_image_table");
4892         emit_section_change (acfg, ".text", 1);
4893         emit_global (acfg, symbol, FALSE);
4894         emit_alignment (acfg, 8);
4895         emit_label (acfg, symbol);
4896
4897         emit_int32 (acfg, acfg->image_table->len);
4898         for (i = 0; i < acfg->image_table->len; i++) {
4899                 MonoImage *image = (MonoImage*)g_ptr_array_index (acfg->image_table, i);
4900                 MonoAssemblyName *aname = &image->assembly->aname;
4901
4902                 /* FIXME: Support multi-module assemblies */
4903                 g_assert (image->assembly->image == image);
4904
4905                 emit_string (acfg, image->assembly_name);
4906                 emit_string (acfg, image->guid);
4907                 emit_string (acfg, aname->culture ? aname->culture : "");
4908                 emit_string (acfg, (const char*)aname->public_key_token);
4909
4910                 emit_alignment (acfg, 8);
4911                 emit_int32 (acfg, aname->flags);
4912                 emit_int32 (acfg, aname->major);
4913                 emit_int32 (acfg, aname->minor);
4914                 emit_int32 (acfg, aname->build);
4915                 emit_int32 (acfg, aname->revision);
4916         }
4917 }
4918
4919 static void
4920 emit_got_info (MonoAotCompile *acfg)
4921 {
4922         char symbol [256];
4923         int i, first_plt_got_patch, buf_size;
4924         guint8 *p, *buf;
4925         guint32 *got_info_offsets;
4926
4927         /* Add the patches needed by the PLT to the GOT */
4928         acfg->plt_got_offset_base = acfg->got_offset;
4929         first_plt_got_patch = acfg->shared_patches->len;
4930         for (i = 1; i < acfg->plt_offset; ++i) {
4931                 MonoJumpInfo *patch_info = g_hash_table_lookup (acfg->plt_offset_to_patch, GUINT_TO_POINTER (i));
4932
4933                 g_ptr_array_add (acfg->shared_patches, patch_info);
4934         }
4935
4936         acfg->got_offset += acfg->plt_offset;
4937
4938         /**
4939          * FIXME: 
4940          * - optimize offsets table.
4941          * - reduce number of exported symbols.
4942          * - emit info for a klass only once.
4943          * - determine when a method uses a GOT slot which is guaranteed to be already 
4944          *   initialized.
4945          * - clean up and document the code.
4946          * - use String.Empty in class libs.
4947          */
4948
4949         /* Encode info required to decode shared GOT entries */
4950         buf_size = acfg->shared_patches->len * 64;
4951         p = buf = mono_mempool_alloc (acfg->mempool, buf_size);
4952         got_info_offsets = mono_mempool_alloc (acfg->mempool, acfg->shared_patches->len * sizeof (guint32));
4953         acfg->plt_got_info_offsets = mono_mempool_alloc (acfg->mempool, acfg->plt_offset * sizeof (guint32));
4954         for (i = 0; i < acfg->shared_patches->len; ++i) {
4955                 MonoJumpInfo *ji = g_ptr_array_index (acfg->shared_patches, i);
4956
4957                 got_info_offsets [i] = p - buf;
4958                 /* No need to encode the patch type for non-PLT patches */
4959                 if (i >= first_plt_got_patch) {
4960                         acfg->plt_got_info_offsets [i - first_plt_got_patch + 1] = got_info_offsets [i];
4961                         encode_value (ji->type, p, &p);
4962                 }
4963                 encode_patch (acfg, ji, p, &p);
4964         }
4965
4966         g_assert (p - buf <= buf_size);
4967
4968         acfg->stats.got_info_size = p - buf;
4969
4970         /* Emit got_info table */
4971         sprintf (symbol, "got_info");
4972         emit_section_change (acfg, ".text", 1);
4973         emit_global (acfg, symbol, FALSE);
4974         emit_alignment (acfg, 8);
4975         emit_label (acfg, symbol);
4976
4977         emit_bytes (acfg, buf, p - buf);
4978
4979         /* Emit got_info_offsets table */
4980         sprintf (symbol, "got_info_offsets");
4981         emit_section_change (acfg, ".text", 1);
4982         emit_global (acfg, symbol, FALSE);
4983         emit_alignment (acfg, 8);
4984         emit_label (acfg, symbol);
4985
4986         for (i = 0; i < acfg->shared_patches->len; ++i)
4987                 emit_int32 (acfg, got_info_offsets [i]);
4988
4989         acfg->stats.got_info_offsets_size = acfg->shared_patches->len * 4;
4990 }
4991
4992 static void
4993 emit_got (MonoAotCompile *acfg)
4994 {
4995         char symbol [256];
4996
4997         /* Don't make GOT global so accesses to it don't need relocations */
4998         sprintf (symbol, "got");
4999         emit_section_change (acfg, ".bss", 0);
5000         emit_alignment (acfg, 8);
5001         emit_label (acfg, symbol);
5002         if ((acfg->got_offset + acfg->num_trampoline_got_entries) > 0)
5003                 emit_zero_bytes (acfg, (int)((acfg->got_offset + acfg->num_trampoline_got_entries) * sizeof (gpointer)));
5004 }
5005
5006 static void
5007 emit_globals (MonoAotCompile *acfg)
5008 {
5009         char *opts_str;
5010         char *build_info;
5011
5012         emit_string_symbol (acfg, "mono_assembly_guid" , acfg->image->guid);
5013
5014         emit_string_symbol (acfg, "mono_aot_version", MONO_AOT_FILE_VERSION);
5015
5016         opts_str = g_strdup_printf ("%d", acfg->opts);
5017         emit_string_symbol (acfg, "mono_aot_opt_flags", opts_str);
5018         g_free (opts_str);
5019
5020         emit_string_symbol (acfg, "mono_aot_full_aot", acfg->aot_opts.full_aot ? "TRUE" : "FALSE");
5021
5022         if (acfg->aot_opts.bind_to_runtime_version) {
5023                 build_info = mono_get_runtime_build_info ();
5024                 emit_string_symbol (acfg, "mono_runtime_version", build_info);
5025                 g_free (build_info);
5026         } else {
5027                 emit_string_symbol (acfg, "mono_runtime_version", "");
5028         }
5029
5030         /*
5031          * Some platforms like the iphone have no working dlsym (). To work around this,
5032          * we create an ELF ctor function which will be invoked by dlopen, and which
5033          * will call a function in the AOT loader to register the symbols used by the
5034          * image.
5035          * When static linking, we emit a global which will point to the symbol table.
5036          */
5037         if (acfg->aot_opts.no_dlsym) {
5038                 int i;
5039                 char symbol [256];
5040
5041                 if (acfg->aot_opts.static_link)
5042                         /* Emit a string holding the assembly name */
5043                         emit_string_symbol (acfg, "mono_aot_assembly_name", acfg->image->assembly->aname.name);
5044
5045                 /* Emit the names */
5046                 for (i = 0; i < acfg->globals->len; ++i) {
5047                         char *name = g_ptr_array_index (acfg->globals, i);
5048
5049                         sprintf (symbol, "name_%d", i);
5050                         emit_section_change (acfg, ".text", 1);
5051                         emit_label (acfg, symbol);
5052                         emit_string (acfg, name);
5053                 }
5054
5055                 /* Emit the globals table */
5056                 sprintf (symbol, "globals");
5057                 emit_section_change (acfg, ".data", 0);
5058                 /* This is not a global, since it is accessed by the init function */
5059                 emit_alignment (acfg, 8);
5060                 emit_label (acfg, symbol);
5061
5062                 for (i = 0; i < acfg->globals->len; ++i) {
5063                         char *name = g_ptr_array_index (acfg->globals, i);
5064
5065                         sprintf (symbol, "name_%d", i);
5066                         emit_pointer (acfg, symbol);
5067
5068                         sprintf (symbol, "%s", name);
5069                         emit_pointer (acfg, symbol);
5070                 }
5071                 /* Null terminate the table */
5072                 emit_pointer (acfg, NULL);
5073                 emit_pointer (acfg, NULL);
5074
5075                 if (acfg->aot_opts.static_link) {
5076                         char *p;
5077
5078                         /* 
5079                          * Emit a global symbol which can be passed by an embedding app to
5080                          * mono_aot_register_module ().
5081                          */
5082 #if defined(__MACH__)
5083                         sprintf (symbol, "_mono_aot_module_%s_info", acfg->image->assembly->aname.name);
5084 #else
5085                         sprintf (symbol, "mono_aot_module_%s_info", acfg->image->assembly->aname.name);
5086 #endif
5087
5088                         /* Get rid of characters which cannot occur in symbols */
5089                         p = symbol;
5090                         for (p = symbol; *p; ++p) {
5091                                 if (!(isalnum (*p) || *p == '_'))
5092                                         *p = '_';
5093                         }
5094                         acfg->static_linking_symbol = g_strdup (symbol);
5095                         emit_global_inner (acfg, symbol, FALSE);
5096                         emit_alignment (acfg, 8);
5097                         emit_label (acfg, symbol);
5098                         emit_pointer (acfg, "globals");
5099                 } else {
5100                         sprintf (symbol, "init_%s", acfg->image->assembly->aname.name);
5101                         emit_section_change (acfg, ".text", 1);
5102                         emit_alignment (acfg, 8);
5103                         emit_label (acfg, symbol);
5104 #ifdef USE_BIN_WRITER
5105                         g_assert_not_reached ();
5106 #else
5107 #ifdef __x86_64__
5108                         fprintf (acfg->fp, "leaq globals(%%rip), %%rdi\n");
5109                         fprintf (acfg->fp, "call mono_aot_register_globals@PLT\n");
5110                         fprintf (acfg->fp, "ret\n");
5111                         fprintf (acfg->fp, ".section .ctors,\"aw\",@progbits\n");
5112                         emit_alignment (acfg, 8);
5113                         emit_pointer (acfg, symbol);
5114 #elif defined(__arm__) && defined(__MACH__)
5115                                 
5116                         fprintf (acfg->fp, ".text\n");
5117                         fprintf (acfg->fp, ".align   3\n");
5118                 
5119                         fprintf (acfg->fp, "ldr r0, .L5\n");
5120                         fprintf (acfg->fp, ".LPIC0:\n");
5121                         fprintf (acfg->fp, "add r0, pc, r0\n");
5122                         fprintf (acfg->fp, "ldr r0, [r0]\n");
5123                         fprintf (acfg->fp, "b   _mono_aot_register_globals@PLT\n");
5124                         fprintf (acfg->fp, ".align 2\n");
5125
5126                         fprintf (acfg->fp, ".L5:\n");
5127                         fprintf (acfg->fp, ".long       globals_ptr-(.LPIC0+8)\n");
5128                         
5129                         fprintf (acfg->fp, ".data\n");
5130                         fprintf (acfg->fp, ".align      2\n");
5131                         fprintf (acfg->fp, "globals_ptr:\n");
5132                         fprintf (acfg->fp, ".long       globals\n");
5133                         
5134                         fprintf (acfg->fp, ".mod_init_func\n");
5135                         fprintf (acfg->fp, ".align      2\n");
5136                         fprintf (acfg->fp, ".long       %s@target1\n", symbol);
5137
5138 #elif defined(__arm__)
5139                         /* 
5140                          * Taken from gcc generated code for:
5141                          * static int i;
5142                          * void foo () { bar (&i); }
5143                          * gcc --shared -fPIC -O2
5144                          */
5145                         fprintf (acfg->fp, "ldr r3, .L5\n");
5146                         fprintf (acfg->fp, "ldr r0, .L5+4\n");
5147                         fprintf (acfg->fp, ".LPIC0:\n");
5148                         fprintf (acfg->fp, "add r3, pc, r3\n");
5149                         fprintf (acfg->fp, "add r0, r3, r0\n");
5150                         fprintf (acfg->fp, "b   mono_aot_register_globals(PLT)\n");
5151
5152                         fprintf (acfg->fp, ".L5:\n");
5153                         fprintf (acfg->fp, ".word       _GLOBAL_OFFSET_TABLE_-(.LPIC0+8)\n");
5154                         fprintf (acfg->fp, ".word       globals(GOTOFF)\n");
5155
5156                         fprintf (acfg->fp, ".section    .init_array,\"aw\",%%init_array\n");
5157                         fprintf (acfg->fp, ".align      2\n");
5158                         fprintf (acfg->fp, ".word       %s(target1)\n", symbol);
5159 #else
5160                         g_assert_not_reached ();
5161 #endif
5162 #endif
5163                 }
5164         }
5165 }
5166
5167 /*
5168  * Emit a structure containing all the information not stored elsewhere.
5169  */
5170 static void
5171 emit_file_info (MonoAotCompile *acfg)
5172 {
5173         char symbol [128];
5174
5175         sprintf (symbol, "mono_aot_file_info");
5176         emit_section_change (acfg, ".data", 0);
5177         emit_alignment (acfg, 8);
5178         emit_label (acfg, symbol);
5179         emit_global (acfg, symbol, FALSE);
5180
5181         /* The data emitted here must match MonoAotFileInfo in aot-runtime.c. */
5182         emit_int32 (acfg, acfg->plt_got_offset_base);
5183         emit_int32 (acfg, acfg->trampoline_got_offset_base);
5184         emit_int32 (acfg, acfg->num_aot_trampolines);
5185         emit_int32 (acfg, (int)(acfg->got_offset * sizeof (gpointer)));
5186         emit_int32 (acfg, acfg->plt_offset);
5187         emit_pointer (acfg, "got");
5188 }
5189
5190 /*****************************************/
5191 /*   Emitting DWARF debug information    */
5192 /*****************************************/
5193
5194 static G_GNUC_UNUSED void
5195 emit_uleb128 (MonoAotCompile *acfg, guint32 value)
5196 {
5197         do {
5198                 guint8 b = value & 0x7f;
5199                 value >>= 7;
5200                 if (value != 0) /* more bytes to come */
5201                         b |= 0x80;
5202                 emit_byte (acfg, b);
5203         } while (value);
5204 }
5205
5206 static G_GNUC_UNUSED void
5207 emit_sleb128 (MonoAotCompile *acfg, gint64 value)
5208 {
5209         gboolean more = 1;
5210         gboolean negative = (value < 0);
5211         guint32 size = 64;
5212         guint8 byte;
5213
5214         while (more) {
5215                 byte = value & 0x7f;
5216                 value >>= 7;
5217                 /* the following is unnecessary if the
5218                  * implementation of >>= uses an arithmetic rather
5219                  * than logical shift for a signed left operand
5220                  */
5221                 if (negative)
5222                         /* sign extend */
5223                         value |= - (1 <<(size - 7));
5224                 /* sign bit of byte is second high order bit (0x40) */
5225                 if ((value == 0 && !(byte & 0x40)) ||
5226                         (value == -1 && (byte & 0x40)))
5227                         more = 0;
5228                 else
5229                         byte |= 0x80;
5230                 emit_byte (acfg, byte);
5231         }
5232 }
5233
5234 static G_GNUC_UNUSED void
5235 encode_uleb128 (guint32 value, guint8 *buf, guint8 **endbuf)
5236 {
5237         guint8 *p = buf;
5238
5239         do {
5240                 guint8 b = value & 0x7f;
5241                 value >>= 7;
5242                 if (value != 0) /* more bytes to come */
5243                         b |= 0x80;
5244                 *p ++ = b;
5245         } while (value);
5246
5247         *endbuf = p;
5248 }
5249
5250 static G_GNUC_UNUSED void
5251 encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf)
5252 {
5253         gboolean more = 1;
5254         gboolean negative = (value < 0);
5255         guint32 size = 32;
5256         guint8 byte;
5257         guint8 *p = buf;
5258
5259         while (more) {
5260                 byte = value & 0x7f;
5261                 value >>= 7;
5262                 /* the following is unnecessary if the
5263                  * implementation of >>= uses an arithmetic rather
5264                  * than logical shift for a signed left operand
5265                  */
5266                 if (negative)
5267                         /* sign extend */
5268                         value |= - (1 <<(size - 7));
5269                 /* sign bit of byte is second high order bit (0x40) */
5270                 if ((value == 0 && !(byte & 0x40)) ||
5271                         (value == -1 && (byte & 0x40)))
5272                         more = 0;
5273                 else
5274                         byte |= 0x80;
5275                 *p ++= byte;
5276         }
5277
5278         *endbuf = p;
5279 }
5280
5281 static void
5282 emit_dwarf_abbrev (MonoAotCompile *acfg, int code, int tag, gboolean has_child,
5283                                    int *attrs, int attrs_len)
5284 {
5285         int i;
5286
5287         emit_uleb128 (acfg, code);
5288         emit_uleb128 (acfg, tag);
5289         emit_byte (acfg, has_child);
5290
5291         for (i = 0; i < attrs_len; i++)
5292                 emit_uleb128 (acfg, attrs [i]);
5293         emit_uleb128 (acfg, 0);
5294         emit_uleb128 (acfg, 0);
5295 }
5296
5297 #ifdef __x86_64__
5298 static int map_hw_reg_to_dwarf_reg [] = { 0, 2, 1, 3, 7, 6, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
5299 #endif
5300
5301 static int
5302 hw_reg_to_dwarf_reg (int reg)
5303 {
5304 #ifdef __x86_64__
5305         return map_hw_reg_to_dwarf_reg [reg];
5306 #else
5307         g_assert_not_reached ();
5308         return -1;
5309 #endif
5310 }
5311
5312 static void
5313 emit_cie (MonoAotCompile *acfg)
5314 {
5315 #if defined(__x86_64__)
5316         emit_section_change (acfg, ".debug_frame", 0);
5317
5318         emit_alignment (acfg, 8);
5319
5320         /* Emit a CIE */
5321         emit_symbol_diff (acfg, ".Lcie0_end", ".", -4); /* length */
5322         emit_int32 (acfg, 0xffffffff); /* CIE id */
5323         emit_byte (acfg, 3); /* version */
5324         emit_string (acfg, ""); /* augmention */
5325         emit_sleb128 (acfg, 1); /* code alignment factor */
5326 #ifdef __x86_64__
5327         emit_sleb128 (acfg, -8); /* data alignment factor */
5328         emit_uleb128 (acfg, AMD64_RIP);
5329 #else
5330         g_assert_not_reached ();
5331 #endif
5332
5333 #ifdef __x86_64__
5334         emit_byte (acfg, DW_CFA_def_cfa);
5335         emit_uleb128 (acfg, hw_reg_to_dwarf_reg (AMD64_RSP));
5336         emit_uleb128 (acfg, 8); /* offset=8 */
5337         emit_byte (acfg, DW_CFA_offset | AMD64_RIP);
5338         emit_uleb128 (acfg, 1); /* offset=-8 */
5339 #else
5340         g_assert_not_reached ();
5341 #endif
5342
5343         emit_alignment (acfg, sizeof (gpointer));
5344         emit_label (acfg, ".Lcie0_end");
5345 #endif
5346 }
5347
5348 static void
5349 emit_pointer_value (MonoAotCompile *acfg, gpointer ptr)
5350 {
5351         gssize val = (gssize)ptr;
5352         emit_bytes (acfg, (guint8*)&val, sizeof (gpointer));
5353 }
5354
5355 static void
5356 emit_fde (MonoAotCompile *acfg, int fde_index, char *start_symbol, char *end_symbol,
5357                   guint8 *code, guint32 code_size, GSList *unwind_ops)
5358 {
5359 #if defined(__x86_64__)
5360         char symbol [128];
5361         GSList *l;
5362         MonoUnwindOp *op;
5363         int loc;
5364
5365         emit_section_change (acfg, ".debug_frame", 0);
5366
5367         sprintf (symbol, ".Lfde%d_end", fde_index);
5368         emit_symbol_diff (acfg, symbol, ".", -4); /* length */
5369         emit_int32 (acfg, 0); /* CIE_pointer */
5370         if (start_symbol) {
5371                 emit_pointer (acfg, start_symbol); /* initial_location */
5372                 emit_symbol_diff (acfg, end_symbol, start_symbol, 0); /* address_range */
5373                 emit_int32 (acfg, 0);
5374         } else {
5375                 emit_pointer_value (acfg, code);
5376                 emit_int32 (acfg, code_size);
5377                 emit_int32 (acfg, 0);
5378         }
5379
5380         /* Convert the list of MonoUnwindOps to the format used by DWARF */
5381         loc = 0;
5382         l = unwind_ops;
5383 #ifdef __x86_64__
5384         /* Skip the first two ops which are in the CIE */
5385         l = l->next->next;
5386 #endif
5387         for (; l; l = l->next) {
5388                 int reg;
5389
5390                 op = l->data;
5391
5392                 /* Convert the register from the hw encoding to the dwarf encoding */
5393                 reg = hw_reg_to_dwarf_reg (op->reg);
5394
5395                 /* Emit an advance_loc if neccesary */
5396                 if (op->when > loc) {
5397                         g_assert (op->when - loc < 32);
5398                         emit_byte (acfg, DW_CFA_advance_loc | (op->when - loc));
5399                 }                       
5400
5401                 switch (op->op) {
5402                 case DW_CFA_def_cfa:
5403                         emit_byte (acfg, op->op);
5404                         emit_uleb128 (acfg, reg);
5405                         emit_uleb128 (acfg, op->val);
5406                         break;
5407                 case DW_CFA_def_cfa_offset:
5408                         emit_byte (acfg, op->op);
5409                         emit_uleb128 (acfg, op->val);
5410                         break;
5411                 case DW_CFA_def_cfa_register:
5412                         emit_byte (acfg, op->op);
5413                         emit_uleb128 (acfg, reg);
5414                         break;
5415                 case DW_CFA_offset:
5416                         emit_byte (acfg, DW_CFA_offset | reg);
5417                         emit_uleb128 (acfg, op->val / - 8);
5418                         break;
5419                 default:
5420                         g_assert_not_reached ();
5421                         break;
5422                 }
5423
5424                 loc = op->when;
5425         }
5426
5427         emit_alignment (acfg, sizeof (gpointer));
5428         sprintf (symbol, ".Lfde%d_end", fde_index);
5429         emit_label (acfg, symbol);
5430 #endif
5431 }
5432
5433 /* Abbrevations */
5434 #define AB_COMPILE_UNIT 1
5435 #define AB_SUBPROGRAM 2
5436 #define AB_PARAM 3
5437 #define AB_BASE_TYPE 4
5438 #define AB_STRUCT_TYPE 5
5439 #define AB_DATA_MEMBER 6
5440 #define AB_TYPEDEF 7
5441 #define AB_ENUM_TYPE 8
5442 #define AB_ENUMERATOR 9
5443 #define AB_NAMESPACE 10
5444
5445 static int compile_unit_attr [] = {
5446         DW_AT_producer     ,DW_FORM_string,
5447     DW_AT_name         ,DW_FORM_string,
5448     DW_AT_comp_dir     ,DW_FORM_string,
5449         DW_AT_language     ,DW_FORM_data1,
5450     DW_AT_low_pc       ,DW_FORM_addr,
5451     DW_AT_high_pc      ,DW_FORM_addr,
5452 };
5453
5454 static int subprogram_attr [] = {
5455         DW_AT_name         , DW_FORM_string,
5456     DW_AT_low_pc       , DW_FORM_addr,
5457     DW_AT_high_pc      , DW_FORM_addr,
5458         DW_AT_frame_base   , DW_FORM_block1
5459 };
5460
5461 static int param_attr [] = {
5462         DW_AT_name,     DW_FORM_string,
5463         DW_AT_type,     DW_FORM_ref4,
5464         DW_AT_location, DW_FORM_block1
5465 };
5466
5467 static int base_type_attr [] = {
5468         DW_AT_byte_size,   DW_FORM_data1,
5469         DW_AT_encoding,    DW_FORM_data1,
5470         DW_AT_name,        DW_FORM_string
5471 };
5472
5473 static int struct_type_attr [] = {
5474         DW_AT_name,        DW_FORM_string,
5475         DW_AT_byte_size,   DW_FORM_udata,
5476 };
5477
5478 static int data_member_attr [] = {
5479         DW_AT_name,        DW_FORM_string,
5480         DW_AT_type,        DW_FORM_ref4,
5481         DW_AT_data_member_location, DW_FORM_block1
5482 };
5483
5484 static int typedef_attr [] = {
5485         DW_AT_name,        DW_FORM_string,
5486         DW_AT_type,        DW_FORM_ref4
5487 };
5488
5489 static int enum_type_attr [] = {
5490         DW_AT_name,        DW_FORM_string,
5491         DW_AT_byte_size,   DW_FORM_udata,
5492         DW_AT_type,        DW_FORM_ref4,
5493 };
5494
5495 static int enumerator_attr [] = {
5496         DW_AT_name,        DW_FORM_string,
5497         DW_AT_const_value, DW_FORM_sdata,
5498 };
5499
5500 static int namespace_attr [] = {
5501         DW_AT_name,        DW_FORM_string,
5502 };
5503
5504 typedef struct DwarfBasicType {
5505         const char *die_name, *name;
5506         int type;
5507         int size;
5508         int encoding;
5509 } DwarfBasicType;
5510
5511 static DwarfBasicType basic_types [] = {
5512         { ".LDIE_I1", "sbyte", MONO_TYPE_I1, 1, DW_ATE_signed },
5513         { ".LDIE_U1", "byte", MONO_TYPE_U1, 1, DW_ATE_unsigned },
5514         { ".LDIE_I2", "short", MONO_TYPE_I2, 2, DW_ATE_signed },
5515         { ".LDIE_U2", "ushort", MONO_TYPE_U2, 2, DW_ATE_unsigned },
5516         { ".LDIE_I4", "int", MONO_TYPE_I4, 4, DW_ATE_signed },
5517         { ".LDIE_U4", "uint", MONO_TYPE_U4, 4, DW_ATE_unsigned },
5518         { ".LDIE_I8", "long", MONO_TYPE_I8, 8, DW_ATE_signed },
5519         { ".LDIE_U8", "ulong", MONO_TYPE_U8, 8, DW_ATE_unsigned },
5520         { ".LDIE_R4", "float", MONO_TYPE_R4, 4, DW_ATE_float },
5521         { ".LDIE_R8", "double", MONO_TYPE_R8, 8, DW_ATE_float },
5522         { ".LDIE_BOOLEAN", "boolean", MONO_TYPE_BOOLEAN, 1, DW_ATE_boolean },
5523         { ".LDIE_STRING", "string", MONO_TYPE_STRING, sizeof (gpointer), DW_ATE_address },
5524         { ".LDIE_OBJECT", "object", MONO_TYPE_OBJECT, sizeof (gpointer), DW_ATE_address },
5525         { ".LDIE_SZARRAY", "object", MONO_TYPE_SZARRAY, sizeof (gpointer), DW_ATE_address },
5526 };
5527
5528 static void
5529 emit_base_dwarf_info (MonoAotCompile *acfg)
5530 {
5531         char *s, *build_info;
5532         int i;
5533
5534         emit_section_change (acfg, ".debug_abbrev", 0);
5535         emit_dwarf_abbrev (acfg, AB_COMPILE_UNIT, DW_TAG_compile_unit, TRUE, 
5536                                            compile_unit_attr, G_N_ELEMENTS (compile_unit_attr));
5537         emit_dwarf_abbrev (acfg, AB_SUBPROGRAM, DW_TAG_subprogram, TRUE, 
5538                                            subprogram_attr, G_N_ELEMENTS (subprogram_attr));
5539         emit_dwarf_abbrev (acfg, AB_PARAM, DW_TAG_formal_parameter, FALSE, 
5540                                            param_attr, G_N_ELEMENTS (param_attr));
5541         emit_dwarf_abbrev (acfg, AB_BASE_TYPE, DW_TAG_base_type, FALSE, 
5542                                            base_type_attr, G_N_ELEMENTS (base_type_attr));
5543         emit_dwarf_abbrev (acfg, AB_STRUCT_TYPE, DW_TAG_class_type, TRUE, 
5544                                            struct_type_attr, G_N_ELEMENTS (struct_type_attr));
5545         emit_dwarf_abbrev (acfg, AB_DATA_MEMBER, DW_TAG_member, FALSE, 
5546                                            data_member_attr, G_N_ELEMENTS (data_member_attr));
5547         emit_dwarf_abbrev (acfg, AB_TYPEDEF, DW_TAG_typedef, FALSE, 
5548                                            typedef_attr, G_N_ELEMENTS (typedef_attr));
5549         emit_dwarf_abbrev (acfg, AB_ENUM_TYPE, DW_TAG_enumeration_type, TRUE,
5550                                            enum_type_attr, G_N_ELEMENTS (enum_type_attr));
5551         emit_dwarf_abbrev (acfg, AB_ENUMERATOR, DW_TAG_enumerator, FALSE,
5552                                            enumerator_attr, G_N_ELEMENTS (enumerator_attr));
5553         emit_dwarf_abbrev (acfg, AB_NAMESPACE, DW_TAG_namespace, TRUE,
5554                                            namespace_attr, G_N_ELEMENTS (namespace_attr));
5555         emit_byte (acfg, 0);
5556
5557         emit_section_change (acfg, ".debug_info", 0);
5558         emit_label (acfg, ".Ldebug_info_start");
5559         emit_symbol_diff (acfg, ".Ldebug_info_end", ".", -4); /* length */
5560         emit_int16 (acfg, 0x3); /* DWARF version 3 */
5561         emit_int32 (acfg, 0); /* .debug_abbrev offset */
5562         emit_byte (acfg, sizeof (gpointer)); /* address size */
5563
5564         /* Emit this into a separate section so it gets placed at the end */
5565         emit_section_change (acfg, ".debug_info", 1);
5566         emit_int32 (acfg, 0); /* close everything */
5567         emit_label (acfg, ".Ldebug_info_end");
5568         emit_section_change (acfg, ".debug_info", 0);
5569
5570         /* Compilation unit */
5571         emit_uleb128 (acfg, AB_COMPILE_UNIT);
5572         build_info = mono_get_runtime_build_info ();
5573         s = g_strdup_printf ("Mono AOT Compiler %s", build_info);
5574         emit_string (acfg, s);
5575         g_free (build_info);
5576         g_free (s);
5577         emit_string (acfg, "JITted code");
5578         emit_string (acfg, "");
5579         emit_byte (acfg, DW_LANG_C);
5580         emit_pointer_value (acfg, 0);
5581         emit_pointer_value (acfg, 0);
5582
5583         /* Base types */
5584         for (i = 0; i < G_N_ELEMENTS (basic_types); ++i) {
5585                 emit_label (acfg, basic_types [i].die_name);
5586                 emit_uleb128 (acfg, AB_BASE_TYPE);
5587                 emit_byte (acfg, basic_types [i].size);
5588                 emit_byte (acfg, basic_types [i].encoding);
5589                 emit_string (acfg, basic_types [i].name);
5590         }
5591
5592         emit_cie (acfg);
5593 }
5594
5595 /* Returns the local symbol pointing to the emitted debug info */
5596 static char*
5597 emit_class_dwarf_info (MonoAotCompile *acfg, MonoClass *klass)
5598 {
5599         char *die;
5600         char *full_name;
5601         gpointer iter;
5602         MonoClassField *field;
5603         const char *fdie;
5604         int k;
5605         gboolean emit_namespace = FALSE;
5606
5607         // FIXME: Appdomains
5608         if (!acfg->class_to_die)
5609                 acfg->class_to_die = g_hash_table_new (NULL, NULL);
5610
5611         die = g_hash_table_lookup (acfg->class_to_die, klass);
5612         if (die)
5613                 return die;
5614
5615         if (!((klass->byval_arg.type == MONO_TYPE_CLASS) || klass->enumtype))
5616                 return NULL;
5617
5618         /*
5619          * FIXME: gdb can't handle namespaces in languages it doesn't know about.
5620          */
5621         /*
5622         if (klass->name_space && klass->name_space [0] != '\0')
5623                 emit_namespace = TRUE;
5624         */
5625         if (emit_namespace) {
5626                 emit_uleb128 (acfg, AB_NAMESPACE);
5627                 emit_string (acfg, klass->name_space);
5628         }
5629
5630         full_name = g_strdup_printf ("%s%s%s", klass->name_space, klass->name_space ? "." : "", klass->name);
5631
5632         die = g_strdup_printf (".LTDIE_%d", acfg->tdie_index);
5633         emit_label (acfg, die);
5634
5635         if (klass->enumtype) {
5636                 int size = mono_class_value_size (mono_class_from_mono_type (klass->enum_basetype), NULL);
5637
5638                 emit_uleb128 (acfg, AB_ENUM_TYPE);
5639                 emit_string (acfg, full_name);
5640                 emit_uleb128 (acfg, size);
5641                 for (k = 0; k < G_N_ELEMENTS (basic_types); ++k)
5642                         if (basic_types [k].type == klass->enum_basetype->type)
5643                                 break;
5644                 g_assert (k < G_N_ELEMENTS (basic_types));
5645                 emit_symbol_diff (acfg, basic_types [k].die_name, ".Ldebug_info_start", 0);
5646
5647                 /* Emit enum values */
5648                 iter = NULL;
5649                 while ((field = mono_class_get_fields (klass, &iter))) {
5650                         const char *p;
5651                         int len;
5652                         MonoTypeEnum def_type;
5653
5654                         if (strcmp ("value__", mono_field_get_name (field)) == 0)
5655                                 continue;
5656                         if (mono_field_is_deleted (field))
5657                                 continue;
5658
5659                         emit_uleb128 (acfg, AB_ENUMERATOR);
5660                         emit_string (acfg, mono_field_get_name (field));
5661
5662                         p = mono_class_get_field_default_value (field, &def_type);
5663                         len = mono_metadata_decode_blob_size (p, &p);
5664                         switch (klass->enum_basetype->type) {
5665                         case MONO_TYPE_U1:
5666                         case MONO_TYPE_I1:
5667                                 emit_sleb128 (acfg, *p);
5668                                 break;
5669                         case MONO_TYPE_CHAR:
5670                         case MONO_TYPE_U2:
5671                         case MONO_TYPE_I2:
5672                                 emit_sleb128 (acfg, read16 (p));
5673                                 break;
5674                         case MONO_TYPE_U4:
5675                         case MONO_TYPE_I4:
5676                                 emit_sleb128 (acfg, read32 (p));
5677                                 break;
5678                         case MONO_TYPE_U8:
5679                         case MONO_TYPE_I8:
5680                                 emit_sleb128 (acfg, read64 (p));
5681                                 break;
5682                         default:
5683                                 g_assert_not_reached ();
5684                         }
5685                 }
5686         } else {
5687                 emit_uleb128 (acfg, AB_STRUCT_TYPE);
5688                 emit_string (acfg, full_name);
5689                 emit_uleb128 (acfg, klass->instance_size);
5690
5691                 /* Emit fields */
5692                 iter = NULL;
5693                 while ((field = mono_class_get_fields (klass, &iter))) {
5694                         guint8 buf [128];
5695                         guint8 *p;
5696
5697                         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
5698                                 continue;
5699
5700                         for (k = 0; k < G_N_ELEMENTS (basic_types); ++k)
5701                                 if (basic_types [k].type == field->type->type)
5702                                         break;
5703                         if (k < G_N_ELEMENTS (basic_types) && field->type->type != MONO_TYPE_SZARRAY && field->type->type != MONO_TYPE_CLASS) {
5704                                 fdie = basic_types [k].die_name;
5705
5706                                 emit_uleb128 (acfg, AB_DATA_MEMBER);
5707                                 emit_string (acfg, field->name);
5708                                 emit_symbol_diff (acfg, fdie, ".Ldebug_info_start", 0);
5709                                 /* location */
5710                                 p = buf;
5711                                 *p ++= DW_OP_plus_uconst;
5712                                 encode_uleb128 (field->offset, p, &p);
5713
5714                                 emit_byte (acfg, p - buf);
5715                                 emit_bytes (acfg, buf, p - buf);
5716                         }
5717                 }
5718         }
5719
5720         /* Type end */
5721         emit_uleb128 (acfg, 0x0);
5722
5723         /* Add a typedef, so we can reference the type without a 'struct' in gdb */
5724         emit_uleb128 (acfg, AB_TYPEDEF);
5725         emit_string (acfg, full_name);
5726         emit_symbol_diff (acfg, die, ".Ldebug_info_start", 0);
5727
5728         g_free (full_name);
5729         acfg->tdie_index ++;
5730
5731
5732         if (emit_namespace) {
5733                 /* Namespace end */
5734                 emit_uleb128 (acfg, 0x0);
5735         }
5736
5737         g_hash_table_insert (acfg->class_to_die, klass, die);
5738         return die;
5739 }
5740
5741 static void
5742 emit_method_dwarf_info (MonoAotCompile *acfg, MonoMethod *method, char *start_symbol, char *end_symbol, guint8 *code, guint32 code_size, MonoInst **args, GSList *unwind_info)
5743 {
5744         char *name;
5745         MonoMethodSignature *sig;
5746         char **names, **tdies;
5747         int i;
5748
5749         emit_section_change (acfg, ".debug_info", 0);
5750
5751         sig = mono_method_signature (method);
5752
5753         /* Parameter types */
5754         tdies = g_new0 (char *, sig->param_count + sig->hasthis);
5755         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5756                 MonoType *t;
5757
5758                 if (i == 0 && sig->hasthis) {
5759                         t = &method->klass->this_arg;
5760                 } else {
5761                         t = sig->params [i - sig->hasthis];
5762                 }
5763
5764                 emit_class_dwarf_info (acfg, mono_class_from_mono_type (t));
5765         }
5766
5767         /* Subprogram */
5768         names = g_new0 (char *, sig->param_count);
5769         mono_method_get_param_names (method, (const char **) names);
5770
5771         emit_uleb128 (acfg, AB_SUBPROGRAM);
5772         name = mono_method_full_name (method, FALSE);
5773         emit_string (acfg, name);
5774         g_free (name);
5775         if (start_symbol) {
5776                 emit_pointer_unaligned (acfg, start_symbol);
5777                 emit_pointer_unaligned (acfg, end_symbol);
5778         } else {
5779                 emit_pointer_value (acfg, code);
5780                 emit_pointer_value (acfg, code + code_size);
5781         }
5782         /* frame_base */
5783         emit_byte (acfg, 2);
5784         emit_byte (acfg, DW_OP_breg6);
5785         emit_byte (acfg, 16);
5786
5787         /* Parameters */
5788         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5789                 MonoInst *arg = args ? args [i] : NULL;
5790                 const char *tdie;
5791                 MonoType *t;
5792                 MonoClass *klass;
5793                 const char *pname;
5794                 char pname_buf [128];
5795                 int j;
5796
5797                 if (i == 0 && sig->hasthis) {
5798                         t = &mono_defaults.object_class->byval_arg;
5799                         pname = "this";
5800                 } else {
5801                         t = sig->params [i - sig->hasthis];
5802                         pname = names [i - sig->hasthis];
5803                 }
5804                 
5805                 emit_uleb128 (acfg, AB_PARAM);
5806                 /* name */
5807                 if (pname[0] == '\0') {
5808                         sprintf (pname_buf, "param%d", i - sig->hasthis);
5809                         pname = pname_buf;
5810                 }
5811                 emit_string (acfg, pname);
5812                 /* type */
5813                 klass = mono_class_from_mono_type (t);
5814                 for (j = 0; j < G_N_ELEMENTS (basic_types); ++j)
5815                         if (basic_types [j].type == t->type)
5816                                 break;
5817                 if (j < G_N_ELEMENTS (basic_types))
5818                         tdie = basic_types [j].die_name;
5819                 else {
5820                         switch (t->type) {
5821                         case MONO_TYPE_CLASS:
5822                         case MONO_TYPE_ARRAY:
5823                                 tdie = ".LDIE_OBJECT";
5824                                 break;
5825                         case MONO_TYPE_VALUETYPE:
5826                                 if (klass->enumtype)
5827                                         tdie = emit_class_dwarf_info (acfg, klass);
5828                                 else
5829                                         tdie = ".LDIE_I4";
5830                                 break;
5831                         default:
5832                                 tdie = ".LDIE_I4";
5833                                 break;
5834                         }
5835                 }
5836                 if (t->byref)
5837                         // FIXME:
5838                         tdie = ".LDIE_I4";
5839                 if (!arg || arg->flags & MONO_INST_IS_DEAD)
5840                         tdie = ".LDIE_I4";
5841                 emit_symbol_diff (acfg, tdie, ".Ldebug_info_start", 0);
5842                 /* location */
5843                 /* FIXME: This needs a location list, since the args can go from reg->stack */
5844                 if (!arg || arg->flags & MONO_INST_IS_DEAD) {
5845                         /* gdb treats this as optimized out */
5846                         emit_byte (acfg, 0);
5847                 } else if (arg->opcode == OP_REGVAR) {
5848                         emit_byte (acfg, 1);
5849                         emit_byte (acfg, DW_OP_reg0 + hw_reg_to_dwarf_reg (arg->dreg));
5850                 } else if (arg->opcode == OP_REGOFFSET) {
5851                         guint8 buf [128];
5852                         guint8 *p;
5853
5854                         p = buf;
5855                         *p ++= DW_OP_breg0 + hw_reg_to_dwarf_reg (arg->inst_basereg);
5856                         encode_sleb128 (arg->inst_offset, p, &p);
5857                         emit_byte (acfg, p - buf);
5858                         emit_bytes (acfg, buf, p - buf);
5859                 } else {
5860                         // FIXME:
5861                         emit_byte (acfg, 1);
5862                         emit_byte (acfg, DW_OP_reg0);
5863                 }
5864         }               
5865         g_free (names);
5866
5867         /* Subprogram end */
5868         emit_uleb128 (acfg, 0x0);
5869
5870         /* Emit unwind info */
5871         emit_fde (acfg, acfg->fde_index, start_symbol, end_symbol, code, code_size, unwind_info);
5872         acfg->fde_index ++;
5873 }
5874
5875 static void
5876 emit_dwarf_info (MonoAotCompile *acfg)
5877 {
5878 #if defined(USE_ELF_WRITER) && defined(__x86_64__)
5879         int i;
5880         char symbol [128], symbol2 [128];
5881
5882         emit_base_dwarf_info (acfg);
5883
5884         /* DIEs for methods */
5885         for (i = 0; i < acfg->nmethods; ++i) {
5886                 MonoCompile *cfg = acfg->cfgs [i];
5887
5888                 if (!cfg)
5889                         continue;
5890
5891                 sprintf (symbol, ".Lm_%x", i);
5892                 sprintf (symbol2, ".Lme_%x", i);
5893
5894                 emit_method_dwarf_info (acfg, cfg->method, symbol, symbol2, NULL, 0, cfg->args, cfg->unwind_ops);
5895         }
5896 #endif /* ELF_WRITER */
5897 }
5898
5899 static void
5900 acfg_free (MonoAotCompile *acfg)
5901 {
5902         int i;
5903
5904         for (i = 0; i < acfg->nmethods; ++i)
5905                 if (acfg->cfgs [i])
5906                         g_free (acfg->cfgs [i]);
5907         g_free (acfg->cfgs);
5908         g_free (acfg->static_linking_symbol);
5909         g_ptr_array_free (acfg->methods, TRUE);
5910         g_ptr_array_free (acfg->shared_patches, TRUE);
5911         g_ptr_array_free (acfg->image_table, TRUE);
5912         g_ptr_array_free (acfg->globals, TRUE);
5913         g_hash_table_destroy (acfg->method_indexes);
5914         g_hash_table_destroy (acfg->plt_offset_to_patch);
5915         g_hash_table_destroy (acfg->patch_to_plt_offset);
5916         g_hash_table_destroy (acfg->patch_to_shared_got_offset);
5917         g_hash_table_destroy (acfg->method_to_cfg);
5918         g_hash_table_destroy (acfg->token_info_hash);
5919         g_hash_table_destroy (acfg->image_hash);
5920         mono_mempool_destroy (acfg->mempool);
5921         g_free (acfg);
5922 }
5923
5924 int
5925 mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
5926 {
5927         MonoImage *image = ass->image;
5928         char symbol [256];
5929         int i, res, methods_len;
5930         MonoAotCompile *acfg;
5931         TV_DECLARE (atv);
5932         TV_DECLARE (btv);
5933
5934         printf ("Mono Ahead of Time compiler - compiling assembly %s\n", image->name);
5935
5936         acfg = g_new0 (MonoAotCompile, 1);
5937         acfg->methods = g_ptr_array_new ();
5938         acfg->method_indexes = g_hash_table_new (NULL, NULL);
5939         acfg->plt_offset_to_patch = g_hash_table_new (NULL, NULL);
5940         acfg->patch_to_plt_offset = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
5941         acfg->patch_to_shared_got_offset = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
5942         acfg->shared_patches = g_ptr_array_new ();
5943         acfg->method_to_cfg = g_hash_table_new (NULL, NULL);
5944         acfg->token_info_hash = g_hash_table_new_full (NULL, NULL, NULL, g_free);
5945         acfg->image_hash = g_hash_table_new (NULL, NULL);
5946         acfg->image_table = g_ptr_array_new ();
5947         acfg->globals = g_ptr_array_new ();
5948         acfg->image = image;
5949         acfg->opts = opts;
5950         acfg->mempool = mono_mempool_new ();
5951         acfg->extra_methods = g_ptr_array_new ();
5952         InitializeCriticalSection (&acfg->mutex);
5953 #ifdef USE_BIN_WRITER
5954         acfg->use_bin_writer = TRUE;
5955 #endif
5956
5957         memset (&acfg->aot_opts, 0, sizeof (acfg->aot_opts));
5958         acfg->aot_opts.write_symbols = TRUE;
5959
5960         mono_aot_parse_options (aot_options, &acfg->aot_opts);
5961
5962         load_profile_files (acfg);
5963
5964         emit_start (acfg);
5965
5966         acfg->num_aot_trampolines = acfg->aot_opts.full_aot ? 10240 : 0;
5967
5968         acfg->method_index = 1;
5969
5970         /* Collect methods */
5971         for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
5972                 MonoMethod *method;
5973                 guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
5974
5975                 method = mono_get_method (acfg->image, token, NULL);
5976
5977                 /* Load all methods eagerly to skip the slower lazy loading code */
5978                 mono_class_setup_methods (method->klass);
5979
5980                 if (acfg->aot_opts.full_aot && method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
5981                         /* Compile the wrapper instead */
5982                         /* We do this here instead of add_wrappers () because it is easy to do it here */
5983                         MonoMethod *wrapper = mono_marshal_get_native_wrapper (method, check_for_pending_exc, TRUE);
5984                         method = wrapper;
5985                 }
5986
5987                 /* Since we add the normal methods first, their index will be equal to their zero based token index */
5988                 add_method_with_index (acfg, method, i);
5989                 acfg->method_index ++;
5990         }
5991
5992         add_generic_instances (acfg);
5993
5994         if (acfg->aot_opts.full_aot)
5995                 add_wrappers (acfg);
5996
5997         acfg->cfgs_size = acfg->methods->len + 32;
5998         acfg->cfgs = g_new0 (MonoCompile*, acfg->cfgs_size);
5999
6000         /* PLT offset 0 is reserved for the PLT trampoline */
6001         acfg->plt_offset = 1;
6002
6003         /* Compile methods */
6004         TV_GETTIME (atv);
6005
6006         if (acfg->aot_opts.nthreads > 0) {
6007                 GPtrArray *frag;
6008                 int len, j;
6009                 GPtrArray *threads;
6010                 HANDLE handle;
6011                 gpointer *user_data;
6012                 MonoMethod **methods;
6013
6014                 methods_len = acfg->methods->len;
6015
6016                 len = acfg->methods->len / acfg->aot_opts.nthreads;
6017                 g_assert (len > 0);
6018                 /* 
6019                  * Partition the list of methods into fragments, and hand it to threads to
6020                  * process.
6021                  */
6022                 threads = g_ptr_array_new ();
6023                 /* Make a copy since acfg->methods is modified by compile_method () */
6024                 methods = g_new0 (MonoMethod*, methods_len);
6025                 //memcpy (methods, g_ptr_array_index (acfg->methods, 0), sizeof (MonoMethod*) * methods_len);
6026                 for (i = 0; i < methods_len; ++i)
6027                         methods [i] = g_ptr_array_index (acfg->methods, i);
6028                 i = 0;
6029                 while (i < methods_len) {
6030                         frag = g_ptr_array_new ();
6031                         for (j = 0; j < len; ++j) {
6032                                 if (i < methods_len) {
6033                                         g_ptr_array_add (frag, methods [i]);
6034                                         i ++;
6035                                 }
6036                         }
6037
6038                         user_data = g_new0 (gpointer, 3);
6039                         user_data [0] = mono_domain_get ();
6040                         user_data [1] = acfg;
6041                         user_data [2] = frag;
6042                         
6043                         handle = CreateThread (NULL, 0, (gpointer)compile_thread_main, user_data, 0, NULL);
6044                         g_ptr_array_add (threads, handle);
6045                 }
6046                 g_free (methods);
6047
6048                 for (i = 0; i < threads->len; ++i) {
6049                         WaitForSingleObjectEx (g_ptr_array_index (threads, i), INFINITE, FALSE);
6050                 }
6051         } else {
6052                 methods_len = 0;
6053         }
6054
6055         /* Compile methods added by compile_method () or all methods if nthreads == 0 */
6056         for (i = methods_len; i < acfg->methods->len; ++i) {
6057                 /* This can new methods to acfg->methods */
6058                 compile_method (acfg, g_ptr_array_index (acfg->methods, i));
6059         }
6060
6061         TV_GETTIME (btv);
6062  
6063         acfg->stats.jit_time = TV_ELAPSED (atv, btv);
6064
6065         TV_GETTIME (atv);
6066
6067         alloc_got_slots (acfg);
6068
6069         emit_code (acfg);
6070
6071         emit_info (acfg);
6072
6073         emit_extra_methods (acfg);
6074
6075         emit_method_order (acfg);
6076
6077         emit_trampolines (acfg);
6078
6079         emit_class_name_table (acfg);
6080
6081         emit_got_info (acfg);
6082
6083         emit_exception_info (acfg);
6084
6085         emit_class_info (acfg);
6086
6087         emit_plt (acfg);
6088
6089         emit_image_table (acfg);
6090
6091         emit_got (acfg);
6092
6093         emit_file_info (acfg);
6094
6095         emit_globals (acfg);
6096
6097         emit_dwarf_info (acfg);
6098
6099         sprintf (symbol, "mem_end");
6100         emit_section_change (acfg, ".text", 1);
6101         emit_global (acfg, symbol, FALSE);
6102         emit_alignment (acfg, 8);
6103         emit_label (acfg, symbol);
6104
6105         TV_GETTIME (btv);
6106
6107         acfg->stats.gen_time = TV_ELAPSED (atv, btv);
6108
6109         printf ("Code: %d Info: %d Ex Info: %d Class Info: %d PLT: %d GOT Info: %d GOT Info Offsets: %d GOT: %d\n", acfg->stats.code_size, acfg->stats.info_size, acfg->stats.ex_info_size, acfg->stats.class_info_size, acfg->plt_offset, acfg->stats.got_info_size, acfg->stats.got_info_offsets_size, (int)(acfg->got_offset * sizeof (gpointer)));
6110
6111         TV_GETTIME (atv);
6112         res = emit_writeout (acfg);
6113         if (res != 0) {
6114                 acfg_free (acfg);
6115                 return res;
6116         }
6117         TV_GETTIME (btv);
6118         acfg->stats.link_time = TV_ELAPSED (atv, btv);
6119
6120         printf ("Compiled %d out of %d methods (%d%%)\n", acfg->stats.ccount, acfg->stats.mcount, acfg->stats.mcount ? (acfg->stats.ccount * 100) / acfg->stats.mcount : 100);
6121         if (acfg->stats.genericcount)
6122                 printf ("%d methods are generic (%d%%)\n", acfg->stats.genericcount, acfg->stats.mcount ? (acfg->stats.genericcount * 100) / acfg->stats.mcount : 100);
6123         if (acfg->stats.abscount)
6124                 printf ("%d methods contain absolute addresses (%d%%)\n", acfg->stats.abscount, acfg->stats.mcount ? (acfg->stats.abscount * 100) / acfg->stats.mcount : 100);
6125         if (acfg->stats.wrappercount)
6126                 printf ("%d methods contain wrapper references (%d%%)\n", acfg->stats.wrappercount, acfg->stats.mcount ? (acfg->stats.wrappercount * 100) / acfg->stats.mcount : 100);
6127         if (acfg->stats.lmfcount)
6128                 printf ("%d methods contain lmf pointers (%d%%)\n", acfg->stats.lmfcount, acfg->stats.mcount ? (acfg->stats.lmfcount * 100) / acfg->stats.mcount : 100);
6129         if (acfg->stats.ocount)
6130                 printf ("%d methods have other problems (%d%%)\n", acfg->stats.ocount, acfg->stats.mcount ? (acfg->stats.ocount * 100) / acfg->stats.mcount : 100);
6131         printf ("Methods without GOT slots: %d (%d%%)\n", acfg->stats.methods_without_got_slots, acfg->stats.mcount ? (acfg->stats.methods_without_got_slots * 100) / acfg->stats.mcount : 100);
6132         printf ("Direct calls: %d (%d%%)\n", acfg->stats.direct_calls, acfg->stats.all_calls ? (acfg->stats.direct_calls * 100) / acfg->stats.all_calls : 100);
6133         printf ("JIT time: %d ms, Generation time: %d ms, Assembly+Link time: %d ms.\n", acfg->stats.jit_time / 1000, acfg->stats.gen_time / 1000, acfg->stats.link_time / 1000);
6134
6135         printf ("GOT slot distribution:\n");
6136         for (i = 0; i < MONO_PATCH_INFO_NONE; ++i)
6137                 if (acfg->stats.got_slot_types [i])
6138                         printf ("\t%s: %d\n", get_patch_name (i), acfg->stats.got_slot_types [i]);
6139
6140         acfg_free (acfg);
6141         
6142         return 0;
6143 }
6144  
6145 /*
6146  * Support for emitting debug info for JITted code.
6147  *
6148  *   This works as follows:
6149  * - the runtime writes out an xdb.s file containing DWARF debug info.
6150  * - the user calls a gdb macro
6151  * - the macro compiles and loads this shared library using add-symbol-file.
6152  *
6153  * This is based on the xdebug functionality in the Kaffe Java VM.
6154  * 
6155  * We emit assembly code instead of using the ELF writer, so we can emit debug info
6156  * incrementally as each method is JITted, and the debugger doesn't have to call
6157  * into the runtime to emit the shared library, which would cause all kinds of
6158  * complications, like threading issues, and the fact that the ELF writer's
6159  * emit_writeout () function cannot be called more than once.
6160  */
6161
6162 /* The recommended gdb macro is: */
6163 /*
6164   define xdb
6165   shell rm -f xdb.so && as --64 -o xdb.o xdb.s && ld -shared -o xdb.so xdb.o
6166   add-symbol-file xdb.so 0
6167   end
6168 */
6169
6170 static MonoAotCompile *xdebug_acfg;
6171
6172 /*
6173  * mono_save_xdebug_info:
6174  *
6175  *   Emit debugging info for METHOD into an assembly file which can be assembled
6176  * and loaded into gdb to provide debugging info for JITted code.
6177  */
6178 void
6179 mono_save_xdebug_info (MonoMethod *method, guint8 *code, guint32 code_size, MonoInst **args, GSList *unwind_info)
6180 {
6181         MonoAotCompile *acfg;
6182
6183         // FIXME: Add trampolines too
6184
6185         /* 
6186          * One time initialization.
6187          * This should be called during startup so no need for locking.
6188          */
6189         if (!xdebug_acfg) {
6190                 acfg = g_new0 (MonoAotCompile, 1);
6191                 acfg->mempool = mono_mempool_new ();
6192                 InitializeCriticalSection (&acfg->mutex);
6193                 acfg->aot_opts.asm_only = TRUE;
6194                 acfg->aot_opts.outfile = g_strdup ("xdb.s");
6195
6196                 unlink ("xdb.s");
6197
6198                 emit_start (acfg);
6199
6200                 xdebug_acfg = acfg;
6201
6202                 /* Emit something so the file has a text segment */
6203                 emit_section_change (acfg, ".text", 0);
6204                 emit_string (acfg, "");
6205
6206                 emit_base_dwarf_info (acfg);
6207         }
6208
6209         acfg = xdebug_acfg;
6210
6211         mono_acfg_lock (acfg);
6212         emit_method_dwarf_info (acfg, method, NULL, NULL, code, code_size, args, unwind_info);
6213         fflush (acfg->fp);
6214         mono_acfg_unlock (acfg);
6215 }
6216
6217 #else
6218
6219 /* AOT disabled */
6220
6221 int
6222 mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
6223 {
6224         return 0;
6225 }
6226
6227 void
6228 mono_save_xdebug_info (MonoMethod *method, guint8 *code, guint32 code_size, MonoInst **args, GSList *unwind_info)
6229 {
6230 }
6231
6232 #endif