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