2008-08-29 Geoff Norton <gnorton@novell.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 #include <fcntl.h>
33 #include <string.h>
34 #ifndef PLATFORM_WIN32
35 #include <sys/mman.h>
36 #else
37 #include <winsock2.h>
38 #include <windows.h>
39 #endif
40
41 #include <errno.h>
42 #include <sys/stat.h>
43 #include <limits.h>    /* for PAGESIZE */
44 #ifndef PAGESIZE
45 #define PAGESIZE 4096
46 #endif
47
48 #include <mono/metadata/tabledefs.h>
49 #include <mono/metadata/class.h>
50 #include <mono/metadata/object.h>
51 #include <mono/metadata/tokentype.h>
52 #include <mono/metadata/appdomain.h>
53 #include <mono/metadata/debug-helpers.h>
54 #include <mono/metadata/assembly.h>
55 #include <mono/metadata/metadata-internals.h>
56 #include <mono/metadata/marshal.h>
57 #include <mono/metadata/gc-internal.h>
58 #include <mono/metadata/method-builder.h>
59 #include <mono/utils/mono-logger.h>
60 #include "mono/utils/mono-compiler.h"
61
62 #include "mini.h"
63 #include "version.h"
64
65 #ifndef DISABLE_AOT
66
67 #ifdef PLATFORM_WIN32
68 #define SHARED_EXT ".dll"
69 #elif defined(__ppc__) && defined(__MACH__)
70 #define SHARED_EXT ".dylib"
71 #else
72 #define SHARED_EXT ".so"
73 #endif
74
75 #if defined(sparc) || defined(__ppc__) || defined(__MACH__)
76 #define AS_STRING_DIRECTIVE ".asciz"
77 #else
78 /* GNU as */
79 #define AS_STRING_DIRECTIVE ".string"
80 #endif
81
82
83 // __MACH__
84 // .byte generates 1 byte per expression.
85 // .short generates 2 bytes per expression.
86 // .long generates 4 bytes per expression.
87 // .quad generates 8 bytes per expression.
88
89 #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
90 #define ROUND_DOWN(VALUE,SIZE)  ((VALUE) & ~((SIZE) - 1))
91
92 typedef struct MonoAotOptions {
93         char *outfile;
94         gboolean save_temps;
95         gboolean write_symbols;
96         gboolean metadata_only;
97         gboolean bind_to_runtime_version;
98         gboolean full_aot;
99         gboolean no_dlsym;
100         gboolean static_link;
101         gboolean asm_only;
102 } MonoAotOptions;
103
104 typedef struct MonoAotStats {
105         int ccount, mcount, lmfcount, abscount, wrappercount, gcount, ocount, genericcount;
106         int code_size, info_size, ex_info_size, got_size, class_info_size, got_info_size, got_info_offsets_size;
107         int methods_without_got_slots, direct_calls, all_calls;
108         int got_slots;
109         int got_slot_types [MONO_PATCH_INFO_NONE];
110 } MonoAotStats;
111
112 /*#define USE_ELF_WRITER 1*/
113
114 #if defined(USE_ELF_WRITER)
115 #define USE_BIN_WRITER 1
116 #endif
117
118 #ifdef USE_BIN_WRITER
119
120 typedef struct _BinSymbol BinSymbol;
121 typedef struct _BinReloc BinReloc;
122 typedef struct _BinSection BinSection;
123
124 #else
125
126 /* emit mode */
127 enum {
128         EMIT_NONE,
129         EMIT_BYTE,
130         EMIT_WORD,
131         EMIT_LONG
132 };
133
134 #endif
135
136 typedef struct MonoAotCompile {
137         MonoImage *image;
138         GPtrArray *methods;
139         GHashTable *method_indexes;
140         MonoCompile **cfgs;
141         GHashTable *patch_to_plt_offset;
142         GHashTable *plt_offset_to_patch;
143         GHashTable *patch_to_shared_got_offset;
144         GPtrArray *shared_patches;
145         GHashTable *image_hash;
146         GHashTable *method_to_cfg;
147         GHashTable *token_info_hash;
148         GPtrArray *image_table;
149         GPtrArray *globals;
150         GList *method_order;
151         /* Number of trampolines emitted into the AOT file */
152         guint32 num_aot_trampolines;
153         guint32 got_offset, plt_offset;
154         /* Number of GOT entries reserved for trampolines */
155         guint32 num_trampoline_got_entries;
156         guint32 *method_got_offsets;
157         MonoAotOptions aot_opts;
158         guint32 nmethods;
159         guint32 opts;
160         MonoMemPool *mempool;
161         MonoAotStats stats;
162         int method_index;
163         char *static_linking_symbol;
164 #ifdef USE_BIN_WRITER
165         BinSymbol *symbols;
166         BinSection *sections;
167         BinSection *cur_section;
168         BinReloc *relocations;
169         GHashTable *labels;
170         int num_relocs;
171 #else
172         FILE *fp;
173         char *tmpfname;
174         int mode; /* emit mode */
175         int col_count; /* bytes emitted per .byte line */
176 #endif
177 } MonoAotCompile;
178
179 #ifdef HAVE_ARRAY_ELEM_INIT
180 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
181 #define MSGSTRFIELD1(line) str##line
182 static const struct msgstr_t {
183 #define PATCH_INFO(a,b) char MSGSTRFIELD(__LINE__) [sizeof (b)];
184 #include "patch-info.h"
185 #undef PATCH_INFO
186 } opstr = {
187 #define PATCH_INFO(a,b) b,
188 #include "patch-info.h"
189 #undef PATCH_INFO
190 };
191 static const gint16 opidx [] = {
192 #define PATCH_INFO(a,b) [MONO_PATCH_INFO_ ## a] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
193 #include "patch-info.h"
194 #undef PATCH_INFO
195 };
196
197 static const char*
198 get_patch_name (int info)
199 {
200         return (const char*)&opstr + opidx [info];
201 }
202
203 #else
204 #define PATCH_INFO(a,b) b,
205 static const char* const
206 patch_types [MONO_PATCH_INFO_NUM + 1] = {
207 #include "patch-info.h"
208         NULL
209 };
210
211 static const char*
212 get_patch_name (int info)
213 {
214         return patch_types [info];
215 }
216
217 #endif
218
219 static void
220 emit_global (MonoAotCompile *acfg, const char *name, gboolean func);
221
222 static gboolean 
223 is_got_patch (MonoJumpInfoType patch_type)
224 {
225         return TRUE;
226 }
227
228 static G_GNUC_UNUSED int
229 ilog2(register int value)
230 {
231         int count = -1;
232         while (value & ~0xf) count += 4, value >>= 4;
233         while (value) count++, value >>= 1;
234         return count;
235 }
236
237 #ifdef USE_BIN_WRITER
238
239 typedef struct _BinLabel BinLabel;
240 struct _BinLabel {
241         char *name;
242         BinSection *section;
243         int offset;
244 };
245
246 struct _BinReloc {
247         BinReloc *next;
248         char *val1;
249         char *val2;
250         BinSection *val2_section;
251         int val2_offset;
252         int offset;
253         BinSection *section;
254         int section_offset;
255 };
256
257 struct _BinSymbol {
258         BinSymbol *next;
259         char *name;
260         BinSection *section;
261         int offset;
262         gboolean is_function;
263         gboolean is_global;
264 };
265
266 struct _BinSection {
267         BinSection *next;
268         BinSection *parent;
269         char *name;
270         int subsection;
271         guint8 *data;
272         int data_len;
273         int cur_offset;
274         int file_offset;
275         int virt_offset;
276         int shidx;
277 };
278
279 static void
280 emit_start (MonoAotCompile *acfg)
281 {
282         acfg->labels = g_hash_table_new (g_str_hash, g_str_equal);
283 }
284
285 static void
286 emit_section_change (MonoAotCompile *acfg, const char *section_name, int subsection_index)
287 {
288         BinSection *section;
289
290         if (acfg->cur_section && acfg->cur_section->subsection == subsection_index
291                         && strcmp (acfg->cur_section->name, section_name) == 0)
292                 return;
293         for (section = acfg->sections; section; section = section->next) {
294                 if (section->subsection == subsection_index && strcmp (section->name, section_name) == 0) {
295                         acfg->cur_section = section;
296                         return;
297                 }
298         }
299         if (!section) {
300                 section = g_new0 (BinSection, 1);
301                 section->name = g_strdup (section_name);
302                 section->subsection = subsection_index;
303                 section->next = acfg->sections;
304                 acfg->sections = section;
305                 acfg->cur_section = section;
306         }
307 }
308
309 static void
310 emit_global_inner (MonoAotCompile *acfg, const char *name, gboolean func)
311 {
312         BinSymbol *symbol = g_new0 (BinSymbol, 1);
313         symbol->name = g_strdup (name);
314         symbol->is_function = func;
315         symbol->is_global = TRUE;
316         symbol->section = acfg->cur_section;
317         /* FIXME: we align after this call... */
318         symbol->offset = symbol->section->cur_offset;
319         symbol->next = acfg->symbols;
320         acfg->symbols = symbol;
321 }
322
323 static void
324 emit_label (MonoAotCompile *acfg, const char *name)
325 {
326         BinLabel *label = g_new0 (BinLabel, 1);
327         label->name = g_strdup (name);
328         label->section = acfg->cur_section;
329         label->offset = acfg->cur_section->cur_offset;
330         g_hash_table_insert (acfg->labels, label->name, label);
331 }
332
333 static void
334 emit_ensure_buffer (BinSection *section, int size)
335 {
336         int new_offset = section->cur_offset + size;
337         if (new_offset >= section->data_len) {
338                 int new_size = section->data_len? section->data_len * 2: 256;
339                 guint8 *data;
340                 while (new_size <= new_offset)
341                         new_size *= 2;
342                 data = g_malloc0 (new_size);
343                 memcpy (data, section->data, section->data_len);
344                 g_free (section->data);
345                 section->data = data;
346                 section->data_len = new_size;
347         }
348 }
349
350 static void
351 emit_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
352 {
353         emit_ensure_buffer (acfg->cur_section, size);
354         memcpy (acfg->cur_section->data + acfg->cur_section->cur_offset, buf, size);
355         acfg->cur_section->cur_offset += size;
356 }
357
358 static void
359 emit_string (MonoAotCompile *acfg, const char *value)
360 {
361         int size = strlen (value) + 1;
362         emit_bytes (acfg, (const guint8*)value, size);
363 }
364
365 static void
366 emit_line (MonoAotCompile *acfg)
367 {
368         /* Nothing to do in binary writer */
369 }
370
371 static void
372 emit_string_symbol (MonoAotCompile *acfg, const char *name, const char *value)
373 {
374         emit_section_change (acfg, ".text", 1);
375         emit_global (acfg, name, FALSE);
376         emit_label (acfg, name);
377         emit_string (acfg, value);
378 }
379
380 static void 
381 emit_alignment (MonoAotCompile *acfg, int size)
382 {
383         int offset = acfg->cur_section->cur_offset;
384         int add;
385         offset += (size - 1);
386         offset &= ~(size - 1);
387         add = offset - acfg->cur_section->cur_offset;
388         if (add) {
389                 emit_ensure_buffer (acfg->cur_section, add);
390                 acfg->cur_section->cur_offset += add;
391         }
392 }
393
394 static void
395 emit_pointer (MonoAotCompile *acfg, const char *target)
396 {
397         BinReloc *reloc;
398
399         if (!target)
400                 // FIXME:
401                 g_assert_not_reached ();
402         emit_alignment (acfg, sizeof (gpointer));
403         reloc = g_new0 (BinReloc, 1);
404         reloc->val1 = g_strdup (target);
405         reloc->section = acfg->cur_section;
406         reloc->section_offset = acfg->cur_section->cur_offset;
407         reloc->next = acfg->relocations;
408         acfg->relocations = reloc;
409         if (strcmp (reloc->section->name, ".data") == 0) {
410                 acfg->num_relocs++;
411                 g_print ("reloc: %s at %d\n", target, acfg->cur_section->cur_offset);
412         }
413         acfg->cur_section->cur_offset += sizeof (gpointer);
414 }
415
416 static void
417 emit_int16 (MonoAotCompile *acfg, int value)
418 {
419         guint8 *data;
420         emit_ensure_buffer (acfg->cur_section, 2);
421         data = acfg->cur_section->data + acfg->cur_section->cur_offset;
422         acfg->cur_section->cur_offset += 2;
423         /* FIXME: little endian */
424         data [0] = value;
425         data [1] = value >> 8;
426 }
427
428 static void
429 emit_int32 (MonoAotCompile *acfg, int value)
430 {
431         guint8 *data;
432         emit_ensure_buffer (acfg->cur_section, 4);
433         data = acfg->cur_section->data + acfg->cur_section->cur_offset;
434         acfg->cur_section->cur_offset += 4;
435         /* FIXME: little endian */
436         data [0] = value;
437         data [1] = value >> 8;
438         data [2] = value >> 16;
439         data [3] = value >> 24;
440 }
441
442 static void
443 emit_symbol_diff (MonoAotCompile *acfg, const char *end, const char* start, int offset)
444 {
445         BinReloc *reloc;
446         reloc = g_new0 (BinReloc, 1);
447         reloc->val1 = g_strdup (end);
448         if (strcmp (start, ".") == 0) {
449                 reloc->val2_section = acfg->cur_section;
450                 reloc->val2_offset = acfg->cur_section->cur_offset;
451         } else {
452                 reloc->val2 = g_strdup (start);
453         }
454         reloc->offset = offset;
455         reloc->section = acfg->cur_section;
456         reloc->section_offset = acfg->cur_section->cur_offset;
457         reloc->next = acfg->relocations;
458         acfg->relocations = reloc;
459         acfg->cur_section->cur_offset += 4;
460         /*if (strcmp (reloc->section->name, ".data") == 0) {
461                 acfg->num_relocs++;
462                 g_print ("reloc: %s - %s + %d at %d\n", end, start, offset, acfg->cur_section->cur_offset - 4);
463         }*/
464 }
465
466 static void
467 emit_zero_bytes (MonoAotCompile *acfg, int num)
468 {
469         emit_ensure_buffer (acfg->cur_section, num);
470         acfg->cur_section->cur_offset += num;
471 }
472
473 #ifdef USE_ELF_WRITER
474 enum {
475         SYM_LOCAL = 0 << 4,
476         SYM_GLOBAL = 1 << 4,
477         SYM_OBJECT = 1,
478         SYM_FUNC = 2,
479         SYM_SECTION = 3
480 };
481
482 enum {
483         SECT_NULL,
484         SECT_HASH,
485         SECT_DYNSYM,
486         SECT_DYNSTR,
487         SECT_REL_DYN,
488         SECT_TEXT,
489         SECT_DYNAMIC,
490         SECT_GOT_PLT,
491         SECT_DATA,
492         SECT_BSS,
493         SECT_SHSTRTAB,
494         SECT_SYMTAB,
495         SECT_STRTAB,
496         SECT_NUM
497 };
498
499 enum {
500         DYN_HASH = 4,
501         DYN_STRTAB = 5,
502         DYN_SYMTAB = 6,
503         DYN_STRSZ = 10,
504         DYN_SYMENT = 11,
505         DYN_REL = 17,
506         DYN_RELSZ = 18,
507         DYN_RELENT = 19,
508         DYN_RELCOUNT = 0x6ffffffa
509 };
510
511 static const char* section_names [] = {
512         "",
513         ".hash",
514         ".dynsym",
515         ".dynstr",
516         ".rel.dyn",
517         ".text",
518         ".dynamic",
519         ".got.plt",
520         ".data",
521         ".bss",
522         ".shstrtab",
523         ".symtab",
524         ".strtab"
525 };
526
527 static const guint8 section_type [] = {
528         0, 5, 11, 3, 9, 1,
529         6, 1, 1, 8, 3, 2, 3
530 };
531
532 static const guint8 section_link [] = {
533         0, 2, 3, 0, 2, 0, 3, 0, 0, 0, 0, 12, 0
534 };
535
536 static const guint8 section_esize [] = {
537         0, 4, 16, 0, 8, 0, 8, 4, 0, 0, 0, 16, 0
538 };
539
540 static const guint8 section_flags [] = {
541         0, 2, 2, 2, 2, 6, 3, 3, 3, 3, 0, 0, 0
542 };
543
544 static const guint16 section_align [] = {
545         0, 4, 4, 1, 4, 4096, 4, 4, 8, 8, 1, 4, 1
546 };
547
548 struct ElfHeader {
549         guint8  e_ident [16];
550         guint16 e_type;
551         guint16 e_machine;
552         guint32 e_version;
553         gsize   e_entry;
554         gsize   e_phoff;
555         gsize   e_shoff;
556         guint32 e_flags;
557         guint16 e_ehsize;
558         guint16 e_phentsize;
559         guint16 e_phnum;
560         guint16 e_shentsize;
561         guint16 e_shnum;
562         guint16 e_shstrndx;
563 };
564
565 struct ElfSectHeader {
566         guint32 sh_name;
567         guint32 sh_type;
568         gsize   sh_flags;
569         gsize   sh_addr;
570         gsize   sh_offset;
571         gsize   sh_size;
572         guint32 sh_link;
573         guint32 sh_info;
574         gsize   sh_addralign;
575         gsize   sh_entsize;
576 };
577
578 #if SIZEOF_VOID_P == 4
579
580 struct ElfProgHeader {
581         guint32 p_type;
582         guint32 p_offset;
583         guint32 p_vaddr;
584         guint32 p_paddr;
585         guint32 p_filesz;
586         guint32 p_memsz;
587         guint32 p_flags;
588         guint32 p_align;
589 };
590
591 typedef struct {
592         guint32 st_name;
593         guint32 st_value;
594         guint32 st_size;
595         guint8  st_info;
596         guint8  st_other;
597         guint16 st_shndx;
598 } ElfSymbol;
599
600 typedef struct {
601         guint32 addr;
602         guint32 value;
603 } ElfReloc;
604
605 typedef struct {
606         guint32 d_tag;
607         guint32 d_val;
608 } ElfDynamic;
609
610 #else
611
612 struct ElfProgHeader {
613         guint32 p_type;
614         guint32 p_flags;
615         guint64 p_offset;
616         guint64 p_vaddr;
617         guint64 p_paddr;
618         guint64 p_filesz;
619         guint64 p_memsz;
620         guint64 p_align;
621 };
622
623 typedef struct {
624         guint32 st_name;
625         guint8  st_info;
626         guint8  st_other;
627         guint16 st_shndx;
628         guint64 st_value;
629         guint64 st_size;
630 } ElfSymbol;
631
632 typedef struct {
633         guint64 addr;
634         guint64 value;
635 } ElfReloc;
636
637 typedef struct {
638         guint64 addr;
639         guint64 value;
640         guint64 addend;
641 } ElfRelocA;
642
643 typedef struct {
644         guint64 d_tag;
645         guint64 d_val;
646 } ElfDynamic;
647
648 #endif
649
650 typedef struct {
651         GString *data;
652         GHashTable *hash;
653 } ElfStrTable;
654
655 static int
656 str_table_add (ElfStrTable *table, const char* value)
657 {
658         int idx;
659         if (!table->data) {
660                 table->data = g_string_new_len ("", 1);
661                 table->hash = g_hash_table_new (g_str_hash, g_str_equal);
662         }
663         idx = GPOINTER_TO_UINT (g_hash_table_lookup (table->hash, value));
664         if (idx)
665                 return idx;
666         idx = table->data->len;
667         g_string_append (table->data, value);
668         g_string_append_c (table->data, 0);
669         g_hash_table_insert (table->hash, (void*)value, GUINT_TO_POINTER (idx));
670         return idx;
671 }
672
673 static void
674 append_subsection (MonoAotCompile *acfg, struct ElfSectHeader *sheaders, BinSection *sect, BinSection *add)
675 {
676         int offset = sect->cur_offset;
677         /*offset += (sheaders [sect->shidx].sh_addralign - 1);
678         offset &= ~(sheaders [sect->shidx].sh_addralign - 1);*/
679         offset += (8 - 1);
680         offset &= ~(8 - 1);
681         emit_ensure_buffer (sect, offset);
682         g_print ("section %s aligned to %d from %d\n", sect->name, offset, sect->cur_offset);
683         sect->cur_offset = offset;
684
685         emit_ensure_buffer (sect, add->cur_offset);
686         memcpy (sect->data + sect->cur_offset, add->data, add->cur_offset);
687         add->parent = sect;
688         sect->cur_offset += add->cur_offset;
689         add->cur_offset = offset; /* it becomes the offset in the parent section */
690         g_print ("subsection %d of %s added at offset %d (align: %d)\n", add->subsection, sect->name, add->cur_offset, sheaders [sect->shidx].sh_addralign);
691         add->data = NULL;
692         add->data_len = 0;
693 }
694
695 /* merge the subsections */
696 static int
697 collect_sections (MonoAotCompile *acfg, struct ElfSectHeader *sheaders, BinSection **out, int num)
698 {
699         int i, j, maxs, num_sections;
700         BinSection *sect;
701
702         num_sections = 0;
703         maxs = 0;
704         for (sect = acfg->sections; sect; sect = sect->next) {
705                 if (sect->subsection == 0) {
706                         out [num_sections++] = sect;
707                         g_assert (num_sections < num);
708                         if (strcmp (sect->name, ".text") == 0) {
709                                 sect->shidx = SECT_TEXT;
710                         } else if (strcmp (sect->name, ".data") == 0) {
711                                 sect->shidx = SECT_DATA;
712                         } else if (strcmp (sect->name, ".bss") == 0) {
713                                 sect->shidx = SECT_BSS;
714                         }
715                 }
716                 maxs = MAX (maxs, sect->subsection);
717         }
718         for (i = 0; i < num_sections; i++) {
719                 for (j = 1; j <= maxs; ++j) {
720                         for (sect = acfg->sections; sect; sect = sect->next) {
721                                 if (sect->subsection == j && strcmp (out [i]->name, sect->name) == 0) {
722                                         append_subsection (acfg, sheaders, out [i], sect);
723                                 }
724                         }
725                 }
726         }
727         return num_sections;
728 }
729
730 static unsigned long
731 elf_hash (const unsigned char *name)
732 {
733         unsigned long h = 0, g;
734         while (*name) {
735                 h = (h << 4) + *name++;
736                 if ((g = h & 0xf0000000))
737                         h ^= g >> 24;
738                 h &= ~g;
739         }
740         return h;
741 }
742
743 #define NUM_BUCKETS 17
744
745 static int*
746 build_hash (MonoAotCompile *acfg, int num_sections, ElfStrTable *dynstr)
747 {
748         int *data;
749         int num_symbols = 1 + num_sections + 3;
750         BinSymbol *symbol;
751
752         for (symbol = acfg->symbols; symbol; symbol = symbol->next) {
753                 if (!symbol->is_global)
754                         continue;
755                 num_symbols++;
756                 str_table_add (dynstr, symbol->name);
757                 /*g_print ("adding sym: %s\n", symbol->name);*/
758         }
759         str_table_add (dynstr, "__bss_start");
760         str_table_add (dynstr, "_edata");
761         str_table_add (dynstr, "_end");
762
763         data = g_new0 (int, num_symbols + 2 + NUM_BUCKETS);
764         data [0] = NUM_BUCKETS;
765         data [1] = num_symbols;
766
767         return data;
768 }
769
770 static gsize
771 get_label_addr (MonoAotCompile *acfg, const char *name)
772 {
773         int offset;
774         BinLabel *lab;
775         BinSection *section;
776         gsize value;
777
778         lab = g_hash_table_lookup (acfg->labels, name);
779         section = lab->section;
780         offset = lab->offset;
781         if (section->parent) {
782                 value = section->parent->file_offset + section->cur_offset + offset;
783         } else {
784                 value = section->file_offset + offset;
785         }
786         return value;
787 }
788
789 static ElfSymbol*
790 collect_syms (MonoAotCompile *acfg, int *hash, ElfStrTable *strtab, struct ElfSectHeader *sheaders, int *num_syms)
791 {
792         ElfSymbol *symbols;
793         BinSymbol *symbol;
794         BinSection *section;
795         int i;
796         int *bucket;
797         int *chain;
798         unsigned long hashc;
799
800         if (hash)
801                 symbols = g_new0 (ElfSymbol, hash [1]);
802         else
803                 symbols = g_new0 (ElfSymbol, *num_syms + SECT_NUM + 10); /* FIXME */
804
805         /* the first symbol is undef, all zeroes */
806         i = 1;
807         if (sheaders) {
808                 int j;
809                 for (j = 1; j < SECT_NUM; ++j) {
810                         symbols [i].st_info = SYM_LOCAL | SYM_SECTION;
811                         symbols [i].st_shndx = j;
812                         symbols [i].st_value = sheaders [j].sh_addr;
813                         ++i;
814                 }
815         } else {
816                 for (section = acfg->sections; section; section = section->next) {
817                         if (section->parent)
818                                 continue;
819                         symbols [i].st_info = SYM_LOCAL | SYM_SECTION;
820                         if (strcmp (section->name, ".text") == 0) {
821                                 symbols [i].st_shndx = SECT_TEXT;
822                                 section->shidx = SECT_TEXT;
823                                 section->file_offset = 4096;
824                                 symbols [i].st_value = section->file_offset;
825                         } else if (strcmp (section->name, ".data") == 0) {
826                                 symbols [i].st_shndx = SECT_DATA;
827                                 section->shidx = SECT_DATA;
828                                 section->file_offset = 4096 + 28; /* FIXME */
829                                 symbols [i].st_value = section->file_offset;
830                         } else if (strcmp (section->name, ".bss") == 0) {
831                                 symbols [i].st_shndx = SECT_BSS;
832                                 section->shidx = SECT_BSS;
833                                 section->file_offset = 4096 + 28 + 8; /* FIXME */
834                                 symbols [i].st_value = section->file_offset;
835                         }
836                         ++i;
837                 }
838         }
839         for (symbol = acfg->symbols; symbol; symbol = symbol->next) {
840                 int offset;
841                 BinLabel *lab;
842                 if (!symbol->is_global)
843                         continue;
844                 symbols [i].st_info = (symbol->is_function? SYM_FUNC : SYM_OBJECT) | SYM_GLOBAL;
845                 symbols [i].st_name = str_table_add (strtab, symbol->name);
846                 /*g_print ("sym name %s tabled to %d\n", symbol->name, symbols [i].st_name);*/
847                 section = symbol->section;
848                 symbols [i].st_shndx = section->parent? section->parent->shidx: section->shidx;
849                 lab = g_hash_table_lookup (acfg->labels, symbol->name);
850                 offset = lab->offset;
851                 if (section->parent) {
852                         symbols [i].st_value = section->parent->file_offset + section->cur_offset + offset;
853                 } else {
854                         symbols [i].st_value = section->file_offset + offset;
855                 }
856                 ++i;
857         }
858         /* add special symbols */
859         symbols [i].st_name = str_table_add (strtab, "__bss_start");
860         symbols [i].st_shndx = 0xfff1;
861         symbols [i].st_info = SYM_GLOBAL;
862         ++i;
863         symbols [i].st_name = str_table_add (strtab, "_edata");
864         symbols [i].st_shndx = 0xfff1;
865         symbols [i].st_info = SYM_GLOBAL;
866         ++i;
867         symbols [i].st_name = str_table_add (strtab, "_end");
868         symbols [i].st_shndx = 0xfff1;
869         symbols [i].st_info = SYM_GLOBAL;
870         ++i;
871
872         if (num_syms)
873                 *num_syms = i;
874
875         /* add to hash table */
876         if (hash) {
877                 bucket = hash + 2;
878                 chain = hash + 2 + hash [0];
879                 for (i = 0; i < hash [1]; ++i) {
880                         int slot;
881                         /*g_print ("checking %d '%s' (sym %d)\n", symbols [i].st_name, strtab->data->str + symbols [i].st_name, i);*/
882                         if (!symbols [i].st_name)
883                                 continue;
884                         hashc = elf_hash ((guint8*)strtab->data->str + symbols [i].st_name);
885                         slot = hashc % hash [0];
886                         /*g_print ("hashing '%s' at slot %d (sym %d)\n", strtab->data->str + symbols [i].st_name, slot, i);*/
887                         if (bucket [slot]) {
888                                 chain [i] = bucket [slot];
889                                 bucket [slot] = i;
890                         } else {
891                                 bucket [slot] = i;
892                         }
893                 }
894         }
895         return symbols;
896 }
897
898 static void
899 reloc_symbols (MonoAotCompile *acfg, ElfSymbol *symbols, struct ElfSectHeader *sheaders, ElfStrTable *strtab, gboolean dynamic)
900 {
901         BinSection *section;
902         BinSymbol *symbol;
903         int i;
904
905         i = 1;
906         if (dynamic) {
907                 for (section = acfg->sections; section; section = section->next) {
908                         if (section->parent)
909                                 continue;
910                         symbols [i].st_value = sheaders [section->shidx].sh_addr;
911                         ++i;
912                 }
913         } else {
914                 for (i = 1; i < SECT_NUM; ++i) {
915                         symbols [i].st_value = sheaders [i].sh_addr;
916                 }
917         }
918         for (symbol = acfg->symbols; symbol; symbol = symbol->next) {
919                 int offset;
920                 BinLabel *lab;
921                 if (dynamic && !symbol->is_global)
922                         continue;
923                 section = symbol->section;
924                 lab = g_hash_table_lookup (acfg->labels, symbol->name);
925                 offset = lab->offset;
926                 if (section->parent) {
927                         symbols [i].st_value = sheaders [section->parent->shidx].sh_addr + section->cur_offset + offset;
928                 } else {
929                         symbols [i].st_value = sheaders [section->shidx].sh_addr + offset;
930                 }
931                 ++i;
932         }
933         /* __bss_start */
934         symbols [i].st_value = sheaders [SECT_BSS].sh_addr;
935         ++i;
936         /* _edata */
937         symbols [i].st_value = sheaders [SECT_DATA].sh_addr + sheaders [SECT_DATA].sh_size;
938         ++i;
939         /* _end */
940         symbols [i].st_value = sheaders [SECT_BSS].sh_addr + sheaders [SECT_BSS].sh_size;
941         ++i;
942 }
943
944 static ElfReloc*
945 resolve_relocations (MonoAotCompile *acfg)
946 {
947         BinReloc *reloc;
948         guint8 *data;
949         gsize end_val, start_val;
950         ElfReloc *rr;
951         int i;
952         gsize vaddr;
953
954         rr = g_new0 (ElfReloc, acfg->num_relocs);
955         i = 0;
956
957         for (reloc = acfg->relocations; reloc; reloc = reloc->next) {
958                 end_val = get_label_addr (acfg, reloc->val1);
959                 if (reloc->val2) {
960                         start_val = get_label_addr (acfg, reloc->val2);
961                 } else if (reloc->val2_section) {
962                         start_val = reloc->val2_offset;
963                         if (reloc->val2_section->parent)
964                                 start_val += reloc->val2_section->parent->file_offset + reloc->val2_section->cur_offset;
965                         else
966                                 start_val += reloc->val2_section->file_offset;
967                 } else {
968                         start_val = 0;
969                 }
970                 end_val = end_val - start_val + reloc->offset;
971                 if (reloc->section->parent) {
972                         data = reloc->section->parent->data;
973                         data += reloc->section->cur_offset;
974                         data += reloc->section_offset;
975                         vaddr = reloc->section->parent->file_offset;
976                         vaddr += reloc->section->cur_offset;
977                         vaddr += reloc->section_offset;
978                 } else {
979                         data = reloc->section->data;
980                         data += reloc->section_offset;
981                         vaddr = reloc->section->file_offset;
982                         vaddr += reloc->section_offset;
983                 }
984                 /* FIXME: little endian */
985                 data [0] = end_val;
986                 data [1] = end_val >> 8;
987                 data [2] = end_val >> 16;
988                 data [3] = end_val >> 24;
989                 if (start_val == 0) {
990                         rr [i].addr = vaddr;
991                         rr [i].value = 8; /* FIXME: 386_RELATIVE */
992                         ++i;
993                         g_assert (i <= acfg->num_relocs);
994                 }
995         }
996         return rr;
997 }
998
999 static int
1000 emit_writeout (MonoAotCompile *acfg)
1001 {
1002         char *outfile_name, *tmp_outfile_name;
1003         FILE *file;
1004         struct ElfHeader header;
1005         struct ElfProgHeader progh [3];
1006         struct ElfSectHeader secth [SECT_NUM];
1007         ElfReloc *relocs;
1008         ElfStrTable str_table = {NULL, NULL};
1009         ElfStrTable sh_str_table = {NULL, NULL};
1010         ElfStrTable dyn_str_table = {NULL, NULL};
1011         BinSection* sections [6];
1012         BinSection *text_section = NULL, *data_section = NULL, *bss_section = NULL;
1013         ElfSymbol *dynsym;
1014         ElfSymbol *symtab;
1015         ElfDynamic dynamic [14];
1016         int *hash;
1017         int i, num_sections, file_offset, virt_offset, size, num_symtab;
1018         int num_local_syms;
1019
1020         g_assert (!acfg->aot_opts.asm_only);
1021
1022         if (acfg->aot_opts.outfile)
1023                 outfile_name = g_strdup_printf ("%s", acfg->aot_opts.outfile);
1024         else
1025                 outfile_name = g_strdup_printf ("%s%s", acfg->image->name, SHARED_EXT);
1026
1027         tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
1028
1029         unlink (tmp_outfile_name);
1030         file = fopen (tmp_outfile_name, "w");
1031         g_assert (file);
1032
1033         /* Section headers */
1034         memset (&secth, 0, sizeof (secth));
1035         memset (&dynamic, 0, sizeof (dynamic));
1036         memset (&header, 0, sizeof (header));
1037
1038         for (i = 1; i < SECT_NUM; ++i) {
1039                 secth [i].sh_name = str_table_add (&sh_str_table, section_names [i]);
1040                 secth [i].sh_type = section_type [i];
1041                 secth [i].sh_link = section_link [i];
1042                 secth [i].sh_addralign = section_align [i];
1043                 secth [i].sh_flags = section_flags [i];
1044                 secth [i].sh_entsize = section_esize [i];
1045         }
1046         secth [SECT_DYNSYM].sh_info = 4;
1047         secth [SECT_SYMTAB].sh_info = 20;
1048
1049         num_sections = collect_sections (acfg, secth, sections, 6);
1050         hash = build_hash (acfg, num_sections, &dyn_str_table);
1051         num_symtab = hash [1]; /* FIXME */
1052         g_print ("num_sections: %d\n", num_sections);
1053         g_print ("dynsym: %d, dynstr size: %d\n", hash [1], dyn_str_table.data->len);
1054         for (i = 0; i < num_sections; ++i) {
1055                 g_print ("section %s, size: %d, %x\n", sections [i]->name, sections [i]->cur_offset, sections [i]->cur_offset);
1056         }
1057
1058         /* at this point we know where in the file the first segment sections go */
1059         dynsym = collect_syms (acfg, hash, &dyn_str_table, NULL, NULL);
1060         num_local_syms = hash [1];
1061         symtab = collect_syms (acfg, NULL, &str_table, secth, &num_local_syms);
1062
1063         for (i = 0; i < num_sections; ++i) {
1064                 if (sections [i]->shidx == SECT_TEXT) {
1065                         text_section = sections [i];
1066                 } else if (sections [i]->shidx == SECT_DATA) {
1067                         data_section = sections [i];
1068                 } else if (sections [i]->shidx == SECT_BSS) {
1069                         bss_section = sections [i];
1070                 }
1071         }
1072
1073         file_offset = virt_offset = sizeof (header) + sizeof (progh);
1074         secth [SECT_HASH].sh_addr = secth [SECT_HASH].sh_offset = file_offset;
1075         size = sizeof (int) * (2 + hash [0] + hash [1]);
1076         virt_offset = (file_offset += size);
1077         secth [SECT_HASH].sh_size = size;
1078         secth [SECT_DYNSYM].sh_addr = secth [SECT_DYNSYM].sh_offset = file_offset;
1079         size = sizeof (ElfSymbol) * hash [1];
1080         virt_offset = (file_offset += size);
1081         secth [SECT_DYNSYM].sh_size = size;
1082         secth [SECT_DYNSTR].sh_addr = secth [SECT_DYNSTR].sh_offset = file_offset;
1083         size = dyn_str_table.data->len;
1084         virt_offset = (file_offset += size);
1085         secth [SECT_DYNSTR].sh_size = size;
1086         file_offset += 4-1;
1087         file_offset &= ~(4-1);
1088         secth [SECT_REL_DYN].sh_addr = secth [SECT_REL_DYN].sh_offset = file_offset;
1089         size = sizeof (ElfReloc) * acfg->num_relocs;
1090         secth [SECT_REL_DYN].sh_size = size;
1091         virt_offset = (file_offset += size);
1092         secth [SECT_REL_DYN].sh_size = size;
1093         file_offset += 4096-1;
1094         file_offset &= ~(4096-1);
1095         virt_offset = file_offset;
1096         secth [SECT_TEXT].sh_addr = secth [SECT_TEXT].sh_offset = file_offset;
1097         size = text_section->cur_offset;
1098         secth [SECT_TEXT].sh_size = size;
1099         file_offset += size;
1100         file_offset += 4-1;
1101         file_offset &= ~(4-1);
1102         virt_offset = file_offset;
1103         /* .dynamic, .got.plt, .data, .bss here */
1104         secth [SECT_DYNAMIC].sh_addr = virt_offset;
1105         secth [SECT_DYNAMIC].sh_offset = file_offset;
1106         size = sizeof (dynamic);
1107         secth [SECT_DYNAMIC].sh_size = size;
1108         size += 4-1;
1109         size &= ~(4-1);
1110         file_offset += size;
1111         virt_offset += size;
1112         secth [SECT_GOT_PLT].sh_addr = virt_offset;
1113         secth [SECT_GOT_PLT].sh_offset = file_offset;
1114         size = 12;
1115         secth [SECT_GOT_PLT].sh_size = size;
1116         size += 8-1;
1117         size &= ~(8-1);
1118         file_offset += size;
1119         virt_offset += size;
1120         secth [SECT_DATA].sh_addr = virt_offset;
1121         secth [SECT_DATA].sh_offset = file_offset;
1122         size = data_section->cur_offset;
1123         secth [SECT_DATA].sh_size = size;
1124         size += 8-1;
1125         size &= ~(8-1);
1126         file_offset += size;
1127         virt_offset += size;
1128         secth [SECT_BSS].sh_addr = virt_offset;
1129         secth [SECT_BSS].sh_offset = file_offset;
1130         size = bss_section->cur_offset;
1131         secth [SECT_BSS].sh_size = size;
1132
1133         /* virtual doesn't matter anymore */
1134         secth [SECT_SHSTRTAB].sh_offset = file_offset;
1135         size = sh_str_table.data->len;
1136         secth [SECT_SHSTRTAB].sh_size = size;
1137         size += 4-1;
1138         size &= ~(4-1);
1139         file_offset += size;
1140         secth [SECT_SYMTAB].sh_offset = file_offset;
1141         size = sizeof (ElfSymbol) * num_local_syms;
1142         secth [SECT_SYMTAB].sh_size = size;
1143         file_offset += size;
1144         secth [SECT_STRTAB].sh_offset = file_offset;
1145         size = str_table.data->len;
1146         secth [SECT_STRTAB].sh_size = size;
1147         file_offset += size;
1148         file_offset += 4-1;
1149         file_offset &= ~(4-1);
1150
1151         text_section->file_offset = secth [SECT_TEXT].sh_offset;
1152         data_section->file_offset = secth [SECT_DATA].sh_offset;
1153         bss_section->file_offset = secth [SECT_BSS].sh_offset;
1154
1155         header.e_ident [0] = 0x7f; header.e_ident [1] = 'E';
1156         header.e_ident [2] = 'L'; header.e_ident [3] = 'F';
1157         header.e_ident [4] = SIZEOF_VOID_P == 4? 1: 2;
1158         header.e_ident [5] = 1; /* FIXME: little endian, bigendian is 2 */
1159         header.e_ident [6] = 1; /* version */
1160         header.e_ident [7] = 0; /* FIXME: */
1161         header.e_ident [8] = 0; /* FIXME: */
1162         for (i = 9; i < 16; ++i)
1163                 header.e_ident [i] = 0;
1164
1165         header.e_type = 3; /* shared library */
1166         header.e_machine = 3; /* FIXME: 386 */
1167         header.e_version = 1; /* FIXME:  */
1168
1169         header.e_phoff = sizeof (header);
1170         header.e_ehsize = sizeof (header);
1171         header.e_phentsize = sizeof (struct ElfProgHeader);
1172         header.e_phnum = 3;
1173         header.e_entry = secth [SECT_TEXT].sh_addr;
1174         header.e_shstrndx = 10;
1175         header.e_shentsize = sizeof (struct ElfSectHeader);
1176         header.e_shnum = SECT_NUM;
1177         header.e_shoff = file_offset;
1178
1179         /* dynamic data */
1180         i = 0;
1181         dynamic [i].d_tag = DYN_HASH;
1182         dynamic [i].d_val = secth [SECT_HASH].sh_offset;
1183         ++i;
1184         dynamic [i].d_tag = DYN_STRTAB;
1185         dynamic [i].d_val = secth [SECT_DYNSTR].sh_offset;
1186         ++i;
1187         dynamic [i].d_tag = DYN_SYMTAB;
1188         dynamic [i].d_val = secth [SECT_DYNSYM].sh_offset;
1189         ++i;
1190         dynamic [i].d_tag = DYN_STRSZ;
1191         dynamic [i].d_val = dyn_str_table.data->len;
1192         ++i;
1193         dynamic [i].d_tag = DYN_SYMENT;
1194         dynamic [i].d_val = sizeof (ElfSymbol);
1195         ++i;
1196         dynamic [i].d_tag = DYN_REL;
1197         dynamic [i].d_val = secth [SECT_REL_DYN].sh_offset;
1198         ++i;
1199         dynamic [i].d_tag = DYN_RELSZ;
1200         dynamic [i].d_val = secth [SECT_REL_DYN].sh_size;
1201         ++i;
1202         dynamic [i].d_tag = DYN_RELENT;
1203         dynamic [i].d_val = sizeof (ElfReloc);
1204         ++i;
1205         dynamic [i].d_tag = DYN_RELCOUNT;
1206         dynamic [i].d_val = acfg->num_relocs;
1207         ++i;
1208
1209         /* Program header */
1210         memset (&progh, 0, sizeof (progh));
1211         progh [0].p_type = 1; /* LOAD */
1212         progh [0].p_filesz = progh [0].p_memsz = secth [SECT_DYNAMIC].sh_offset;
1213         progh [0].p_align = 4096;
1214         progh [0].p_flags = 5;
1215
1216         progh [1].p_type = 1;
1217         progh [1].p_offset = secth [SECT_DYNAMIC].sh_offset;
1218         progh [1].p_vaddr = progh [1].p_paddr = secth [SECT_DYNAMIC].sh_addr;
1219         progh [1].p_filesz = secth [SECT_BSS].sh_offset  - secth [SECT_DYNAMIC].sh_offset;
1220         progh [1].p_memsz = secth [SECT_BSS].sh_addr + secth [SECT_BSS].sh_size - secth [SECT_DYNAMIC].sh_addr;
1221         progh [1].p_align = 4096;
1222         progh [1].p_flags = 6;
1223
1224         progh [2].p_type = 2; /* DYNAMIC */
1225         progh [2].p_offset = secth [SECT_DYNAMIC].sh_offset;
1226         progh [2].p_vaddr = progh [2].p_paddr = secth [SECT_DYNAMIC].sh_addr;
1227         progh [2].p_filesz = progh [2].p_memsz = secth [SECT_DYNAMIC].sh_size;
1228         progh [2].p_align = 4;
1229         progh [2].p_flags = 6;
1230
1231         reloc_symbols (acfg, dynsym, secth, &dyn_str_table, TRUE);
1232         reloc_symbols (acfg, symtab, secth, &str_table, FALSE);
1233         relocs = resolve_relocations (acfg);
1234
1235         fwrite (&header, sizeof (header), 1, file);
1236         fwrite (&progh, sizeof (progh), 1, file);
1237         fwrite (hash, sizeof (int) * (hash [0] + hash [1] + 2), 1, file);
1238         fwrite (dynsym, sizeof (ElfSymbol) * hash [1], 1, file);
1239         fwrite (dyn_str_table.data->str, dyn_str_table.data->len, 1, file);
1240         /* .rel.dyn */
1241         fseek (file, secth [SECT_REL_DYN].sh_offset, SEEK_SET);
1242         fwrite (relocs, sizeof (ElfReloc), acfg->num_relocs, file);
1243
1244         fseek (file, secth [SECT_TEXT].sh_offset, SEEK_SET);
1245         /* write .text, .data, .bss sections */
1246         fwrite (text_section->data, text_section->cur_offset, 1, file);
1247
1248         /* .dynamic */
1249         fwrite (dynamic, sizeof (dynamic), 1, file);
1250         /* .got.plt */
1251         size = secth [SECT_DYNAMIC].sh_addr;
1252         fwrite (&size, sizeof (size), 1, file);
1253         fseek (file, secth [SECT_DATA].sh_offset, SEEK_SET);
1254         fwrite (data_section->data, data_section->cur_offset, 1, file);
1255
1256         fseek (file, secth [SECT_SHSTRTAB].sh_offset, SEEK_SET);
1257         fwrite (sh_str_table.data->str, sh_str_table.data->len, 1, file);
1258         fseek (file, secth [SECT_SYMTAB].sh_offset, SEEK_SET);
1259         fwrite (symtab, sizeof (ElfSymbol) * num_local_syms, 1, file);
1260         fseek (file, secth [SECT_STRTAB].sh_offset, SEEK_SET);
1261         fwrite (str_table.data->str, str_table.data->len, 1, file);
1262         /*g_print ("file_offset %d vs %d\n", file_offset, ftell (file));*/
1263         /*g_assert (file_offset >= ftell (file));*/
1264         fseek (file, file_offset, SEEK_SET);
1265         fwrite (&secth, sizeof (secth), 1, file);
1266         fclose (file);
1267         rename (tmp_outfile_name, outfile_name);
1268
1269         g_free (tmp_outfile_name);
1270         g_free (outfile_name);
1271
1272         return 0;
1273 }
1274
1275 #endif /* USE_ELF_WRITER */
1276
1277 #else
1278
1279 static void
1280 emit_start (MonoAotCompile *acfg)
1281 {
1282         if (acfg->aot_opts.asm_only) {
1283                 if (acfg->aot_opts.outfile)
1284                         acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
1285                 else
1286                         acfg->tmpfname = g_strdup_printf ("%s.s", acfg->image->name);
1287                 acfg->fp = fopen (acfg->tmpfname, "w+");
1288         } else {
1289                 int i = g_file_open_tmp ("mono_aot_XXXXXX", &acfg->tmpfname, NULL);
1290                 acfg->fp = fdopen (i, "w+");
1291         }
1292         g_assert (acfg->fp);
1293 }
1294
1295 static void
1296 emit_unset_mode (MonoAotCompile *acfg)
1297 {
1298         if (acfg->mode == EMIT_NONE)
1299                 return;
1300         fprintf (acfg->fp, "\n");
1301         acfg->mode = EMIT_NONE;
1302 }
1303
1304 static void
1305 emit_section_change (MonoAotCompile *acfg, const char *section_name, int subsection_index)
1306 {
1307         emit_unset_mode (acfg);
1308 #if defined(PLATFORM_WIN32)
1309         fprintf (acfg->fp, ".section %s\n", section_name);
1310 #elif defined(__MACH__)
1311         /* This needs to be made more precise on mach. */
1312         fprintf (acfg->fp, "%s\n", subsection_index == 0 ? ".text" : ".data");
1313 #elif defined(sparc) || defined(__arm__)
1314         /* For solaris as, GNU as should accept the same */
1315         fprintf (acfg->fp, ".section \"%s\"\n", section_name);
1316 #else
1317         fprintf (acfg->fp, "%s %d\n", section_name, subsection_index);
1318 #endif
1319 }
1320
1321 static void
1322 emit_symbol_type (MonoAotCompile *acfg, const char *name, gboolean func)
1323 {
1324         const char *stype;
1325
1326         if (func)
1327                 stype = "function";
1328         else
1329                 stype = "object";
1330
1331         emit_unset_mode (acfg);
1332 #if defined(__MACH__)
1333
1334 #elif defined(sparc) || defined(__arm__)
1335         fprintf (acfg->fp, "\t.type %s,#%s\n", name, stype);
1336 #elif defined(PLATFORM_WIN32)
1337
1338 #elif defined(__x86_64__) || defined(__i386__)
1339         fprintf (acfg->fp, "\t.type %s,@%s\n", name, stype);
1340 #else
1341         fprintf (acfg->fp, "\t.type %s,@%s\n", name, stype);
1342 #endif
1343 }
1344
1345 static void
1346 emit_global_inner (MonoAotCompile *acfg, const char *name, gboolean func)
1347 {
1348         emit_unset_mode (acfg);
1349 #if  (defined(__ppc__) && defined(__MACH__)) || defined(PLATFORM_WIN32)
1350     // mach-o always uses a '_' prefix.
1351         fprintf (acfg->fp, "\t.globl _%s\n", name);
1352 #else
1353         fprintf (acfg->fp, "\t.globl %s\n", name);
1354 #endif
1355
1356         emit_symbol_type (acfg, name, func);
1357 }
1358
1359 static void
1360 emit_label (MonoAotCompile *acfg, const char *name)
1361 {
1362         emit_unset_mode (acfg);
1363 #if (defined(__ppc__) && defined(__MACH__)) || defined(PLATFORM_WIN32)
1364     // mach-o always uses a '_' prefix.
1365         fprintf (acfg->fp, "_%s:\n", name);
1366 #else
1367         fprintf (acfg->fp, "%s:\n", name);
1368 #endif
1369
1370 #if defined(PLATFORM_WIN32)
1371         /* Emit a normal label too */
1372         fprintf (acfg->fp, "%s:\n", name);
1373 #endif
1374 }
1375
1376 static void
1377 emit_string (MonoAotCompile *acfg, const char *value)
1378 {
1379         emit_unset_mode (acfg);
1380         fprintf (acfg->fp, "\t%s \"%s\"\n", AS_STRING_DIRECTIVE, value);
1381 }
1382
1383 static void
1384 emit_line (MonoAotCompile *acfg)
1385 {
1386         emit_unset_mode (acfg);
1387         fprintf (acfg->fp, "\n");
1388 }
1389
1390 static void
1391 emit_string_symbol (MonoAotCompile *acfg, const char *name, const char *value)
1392 {
1393         emit_unset_mode (acfg);
1394         emit_section_change (acfg, ".text", 1);
1395         emit_global (acfg, name, FALSE);
1396         emit_label (acfg, name);
1397         emit_string (acfg, value);
1398 }
1399
1400 static void 
1401 emit_alignment (MonoAotCompile *acfg, int size)
1402 {
1403         emit_unset_mode (acfg);
1404 #if defined(__arm__)
1405         fprintf (acfg->fp, "\t.align %d\n", ilog2 (size));
1406 #elif defined(__ppc__) && defined(__MACH__)
1407         // the mach-o assembler specifies alignments as powers of 2.
1408         fprintf (acfg->fp, "\t.align %d\t; ilog2\n", ilog2(size));
1409 #elif defined(__powerpc__)
1410         /* ignore on linux/ppc */
1411 #else
1412         fprintf (acfg->fp, "\t.align %d\n", size);
1413 #endif
1414 }
1415
1416 static void
1417 emit_pointer (MonoAotCompile *acfg, const char *target)
1418 {
1419         emit_unset_mode (acfg);
1420         emit_alignment (acfg, sizeof (gpointer));
1421 #if defined(__x86_64__)
1422         fprintf (acfg->fp, "\t.quad %s\n", target ? target : "0");
1423 #elif defined(sparc) && SIZEOF_VOID_P == 8
1424         fprintf (acfg->fp, "\t.xword %s\n", target ? target : "0");
1425 #else
1426         fprintf (acfg->fp, "\t.long %s\n", target ? target : "0");
1427 #endif
1428 }
1429
1430 static void
1431 emit_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
1432 {
1433         int i;
1434         if (acfg->mode != EMIT_BYTE) {
1435                 acfg->mode = EMIT_BYTE;
1436                 acfg->col_count = 0;
1437         }
1438         for (i = 0; i < size; ++i, ++acfg->col_count) {
1439                 if ((acfg->col_count % 32) == 0)
1440                         fprintf (acfg->fp, "\n\t.byte ");
1441                 else
1442                         fprintf (acfg->fp, ",");
1443                 fprintf (acfg->fp, "0x%x", buf [i]);
1444         }
1445 }
1446
1447 static inline void
1448 emit_int16 (MonoAotCompile *acfg, int value)
1449 {
1450         if (acfg->mode != EMIT_WORD) {
1451                 acfg->mode = EMIT_WORD;
1452                 acfg->col_count = 0;
1453         }
1454         if ((acfg->col_count++ % 8) == 0)
1455 #if defined(__MACH__)
1456                 fprintf (acfg->fp, "\n\t.short ");
1457 #elif defined(__arm__)
1458                 /* FIXME: Use .hword on other archs as well */
1459                 fprintf (acfg->fp, "\n\t.hword ");
1460 #else
1461                 fprintf (acfg->fp, "\n\t.word ");
1462 #endif
1463         else
1464                 fprintf (acfg->fp, ", ");
1465         fprintf (acfg->fp, "%d", value);
1466 }
1467
1468 static inline void
1469 emit_int32 (MonoAotCompile *acfg, int value)
1470 {
1471         if (acfg->mode != EMIT_LONG) {
1472                 acfg->mode = EMIT_LONG;
1473                 acfg->col_count = 0;
1474         }
1475         if ((acfg->col_count++ % 8) == 0)
1476                 fprintf (acfg->fp, "\n\t.long ");
1477         else
1478                 fprintf (acfg->fp, ",");
1479         fprintf (acfg->fp, "%d", value);
1480 }
1481
1482 static void
1483 emit_symbol_diff (MonoAotCompile *acfg, const char *end, const char* start, int offset)
1484 {
1485         if (acfg->mode != EMIT_LONG) {
1486                 acfg->mode = EMIT_LONG;
1487                 acfg->col_count = 0;
1488         }
1489         if ((acfg->col_count++ % 8) == 0)
1490                 fprintf (acfg->fp, "\n\t.long ");
1491         else
1492                 fprintf (acfg->fp, ",");
1493         if (offset > 0)
1494                 fprintf (acfg->fp, "%s - %s + %d", end, start, offset);
1495         else if (offset < 0)
1496                 fprintf (acfg->fp, "%s - %s %d", end, start, offset);
1497         else
1498                 fprintf (acfg->fp, "%s - %s", end, start);
1499 }
1500
1501 static void
1502 emit_zero_bytes (MonoAotCompile *acfg, int num)
1503 {
1504         emit_unset_mode (acfg);
1505 #if defined(__MACH__)
1506         fprintf (acfg->fp, "\t.space %d\n", num);
1507 #else
1508         fprintf (acfg->fp, "\t.skip %d\n", num);
1509 #endif
1510 }
1511
1512 static int
1513 emit_writeout (MonoAotCompile *acfg)
1514 {
1515         char *command, *objfile;
1516         char *outfile_name, *tmp_outfile_name;
1517
1518         fclose (acfg->fp);
1519
1520 #if defined(__x86_64__)
1521 #define AS_OPTIONS "--64"
1522 #elif defined(sparc) && SIZEOF_VOID_P == 8
1523 #define AS_OPTIONS "-xarch=v9"
1524 #else
1525 #define AS_OPTIONS ""
1526 #endif
1527
1528         if (acfg->aot_opts.asm_only) {
1529                 printf ("Output file: '%s'.\n", acfg->tmpfname);
1530                 if (acfg->aot_opts.static_link)
1531                         printf ("Linking symbol: '%s'.\n", acfg->static_linking_symbol);
1532                 return 0;
1533         }
1534
1535         if (acfg->aot_opts.static_link) {
1536                 if (acfg->aot_opts.outfile)
1537                         objfile = g_strdup_printf ("%s", acfg->aot_opts.outfile);
1538                 else
1539                         objfile = g_strdup_printf ("%s.o", acfg->image->name);
1540         } else {
1541                 objfile = g_strdup_printf ("%s.o", acfg->tmpfname);
1542         }
1543         command = g_strdup_printf ("as %s %s -o %s", AS_OPTIONS, acfg->tmpfname, objfile);
1544         printf ("Executing the native assembler: %s\n", command);
1545         if (system (command) != 0) {
1546                 g_free (command);
1547                 g_free (objfile);
1548                 return 1;
1549         }
1550
1551         g_free (command);
1552
1553         if (acfg->aot_opts.static_link) {
1554                 printf ("Output file: '%s'.\n", objfile);
1555                 printf ("Linking symbol: '%s'.\n", acfg->static_linking_symbol);
1556                 g_free (objfile);
1557                 return 0;
1558         }
1559
1560         if (acfg->aot_opts.outfile)
1561                 outfile_name = g_strdup_printf ("%s", acfg->aot_opts.outfile);
1562         else
1563                 outfile_name = g_strdup_printf ("%s%s", acfg->image->name, SHARED_EXT);
1564
1565         tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
1566
1567 #if defined(sparc)
1568         command = g_strdup_printf ("ld -shared -G -o %s %s.o", outfile_name, acfg->tmpfname);
1569 #elif defined(__ppc__) && defined(__MACH__)
1570         command = g_strdup_printf ("gcc -dynamiclib -o %s %s.o", outfile_name, acfg->tmpfname);
1571 #elif defined(PLATFORM_WIN32)
1572         command = g_strdup_printf ("gcc -shared --dll -mno-cygwin -o %s %s.o", outfile_name, acfg->tmpfname);
1573 #else
1574         if (acfg->aot_opts.no_dlsym) {
1575                 /* 
1576                  * Need to link using gcc so our ctor function gets called.
1577                  */
1578                 command = g_strdup_printf ("gcc -shared -o %s %s.o", outfile_name, acfg->tmpfname);
1579         } else {
1580                 command = g_strdup_printf ("ld -shared -o %s %s.o", outfile_name, acfg->tmpfname);
1581         }
1582 #endif
1583         printf ("Executing the native linker: %s\n", command);
1584         if (system (command) != 0) {
1585                 g_free (tmp_outfile_name);
1586                 g_free (outfile_name);
1587                 g_free (command);
1588                 g_free (objfile);
1589                 return 1;
1590         }
1591
1592         g_free (command);
1593         unlink (objfile);
1594         /*com = g_strdup_printf ("strip --strip-unneeded %s%s", acfg->image->name, SHARED_EXT);
1595         printf ("Stripping the binary: %s\n", com);
1596         system (com);
1597         g_free (com);*/
1598
1599         rename (tmp_outfile_name, outfile_name);
1600
1601         g_free (tmp_outfile_name);
1602         g_free (outfile_name);
1603         g_free (objfile);
1604
1605         if (acfg->aot_opts.save_temps)
1606                 printf ("Retained input file.\n");
1607         else
1608                 unlink (acfg->tmpfname);
1609
1610         return 0;
1611 }
1612
1613 #endif /* ASM_WRITER */
1614
1615 static void
1616 emit_global (MonoAotCompile *acfg, const char *name, gboolean func)
1617 {
1618         if (acfg->aot_opts.no_dlsym) {
1619                 g_ptr_array_add (acfg->globals, g_strdup (name));
1620         } else {
1621                 emit_global_inner (acfg, name, func);
1622         }
1623 }
1624
1625 static void
1626 emit_byte (MonoAotCompile *acfg, guint8 val)
1627 {
1628         emit_bytes (acfg, &val, 1);
1629 }
1630
1631 static guint32
1632 mono_get_field_token (MonoClassField *field) 
1633 {
1634         MonoClass *klass = field->parent;
1635         int i;
1636
1637         for (i = 0; i < klass->field.count; ++i) {
1638                 if (field == &klass->fields [i])
1639                         return MONO_TOKEN_FIELD_DEF | (klass->field.first + 1 + i);
1640         }
1641
1642         g_assert_not_reached ();
1643         return 0;
1644 }
1645
1646 static inline void
1647 encode_value (gint32 value, guint8 *buf, guint8 **endbuf)
1648 {
1649         guint8 *p = buf;
1650
1651         //printf ("ENCODE: %d 0x%x.\n", value, value);
1652
1653         /* 
1654          * Same encoding as the one used in the metadata, extended to handle values
1655          * greater than 0x1fffffff.
1656          */
1657         if ((value >= 0) && (value <= 127))
1658                 *p++ = value;
1659         else if ((value >= 0) && (value <= 16383)) {
1660                 p [0] = 0x80 | (value >> 8);
1661                 p [1] = value & 0xff;
1662                 p += 2;
1663         } else if ((value >= 0) && (value <= 0x1fffffff)) {
1664                 p [0] = (value >> 24) | 0xc0;
1665                 p [1] = (value >> 16) & 0xff;
1666                 p [2] = (value >> 8) & 0xff;
1667                 p [3] = value & 0xff;
1668                 p += 4;
1669         }
1670         else {
1671                 p [0] = 0xff;
1672                 p [1] = (value >> 24) & 0xff;
1673                 p [2] = (value >> 16) & 0xff;
1674                 p [3] = (value >> 8) & 0xff;
1675                 p [4] = value & 0xff;
1676                 p += 5;
1677         }
1678         if (endbuf)
1679                 *endbuf = p;
1680 }
1681
1682 static guint32
1683 get_image_index (MonoAotCompile *cfg, MonoImage *image)
1684 {
1685         guint32 index;
1686
1687         index = GPOINTER_TO_UINT (g_hash_table_lookup (cfg->image_hash, image));
1688         if (index)
1689                 return index - 1;
1690         else {
1691                 index = g_hash_table_size (cfg->image_hash);
1692                 g_hash_table_insert (cfg->image_hash, image, GUINT_TO_POINTER (index + 1));
1693                 g_ptr_array_add (cfg->image_table, image);
1694                 return index;
1695         }
1696 }
1697
1698 static guint32
1699 find_typespec_for_class (MonoAotCompile *acfg, MonoClass *klass)
1700 {
1701         int i;
1702         MonoClass *k = NULL;
1703
1704         /* FIXME: Search referenced images as well */
1705         for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows; ++i) {
1706                 k = mono_class_get_full (acfg->image, MONO_TOKEN_TYPE_SPEC | (i + 1), NULL);
1707                 if (k == klass)
1708                         break;
1709         }
1710
1711         if (i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows)
1712                 return MONO_TOKEN_TYPE_SPEC | (i + 1);
1713         else
1714                 return 0;
1715 }
1716
1717 static void
1718 encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 **endbuf);
1719
1720 /*
1721  * encode_klass_ref:
1722  *
1723  *   Encode a reference to KLASS. We use our home-grown encoding instead of the
1724  * standard metadata encoding.
1725  */
1726 static void
1727 encode_klass_ref (MonoAotCompile *acfg, MonoClass *klass, guint8 *buf, guint8 **endbuf)
1728 {
1729         guint8 *p = buf;
1730
1731         if (klass->generic_class) {
1732                 guint32 token;
1733                 g_assert (klass->type_token);
1734
1735                 /* Find a typespec for a class if possible */
1736                 token = find_typespec_for_class (acfg, klass);
1737                 if (token) {
1738                         encode_value (token, p, &p);
1739                         encode_value (get_image_index (acfg, acfg->image), p, &p);
1740                 } else {
1741                         MonoClass *gclass = klass->generic_class->container_class;
1742                         MonoGenericInst *inst = klass->generic_class->context.class_inst;
1743                         int i;
1744
1745                         /* Encode it ourselves */
1746                         /* Marker */
1747                         encode_value (MONO_TOKEN_TYPE_SPEC, p, &p);
1748                         encode_value (MONO_TYPE_GENERICINST, p, &p);
1749                         encode_klass_ref (acfg, gclass, p, &p);
1750                         encode_value (inst->type_argc, p, &p);
1751                         for (i = 0; i < inst->type_argc; ++i)
1752                                 encode_klass_ref (acfg, mono_class_from_mono_type (inst->type_argv [i]), p, &p);
1753                 }
1754         } else if (klass->type_token) {
1755                 g_assert (mono_metadata_token_code (klass->type_token) == MONO_TOKEN_TYPE_DEF);
1756                 encode_value (klass->type_token - MONO_TOKEN_TYPE_DEF, p, &p);
1757                 encode_value (get_image_index (acfg, klass->image), p, &p);
1758         } else if ((klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR)) {
1759                 MonoGenericParam *param = klass->byval_arg.data.generic_param;
1760
1761                 /* Marker */
1762                 encode_value (MONO_TOKEN_TYPE_SPEC, p, &p);
1763                 encode_value (klass->byval_arg.type, p, &p);
1764
1765                 encode_value (param->num, p, &p);
1766                 
1767                 g_assert (param->owner);
1768                 encode_value (param->owner->is_method, p, &p);
1769                 if (param->owner->is_method)
1770                         encode_method_ref (acfg, param->owner->owner.method, p, &p);
1771                 else
1772                         encode_klass_ref (acfg, param->owner->owner.klass, p, &p);
1773         } else {
1774                 /* Array class */
1775                 g_assert (klass->rank > 0);
1776                 encode_value (MONO_TOKEN_TYPE_DEF, p, &p);
1777                 encode_value (get_image_index (acfg, klass->image), p, &p);
1778                 encode_value (klass->rank, p, &p);
1779                 encode_klass_ref (acfg, klass->element_class, p, &p);
1780         }
1781         *endbuf = p;
1782 }
1783
1784 static void
1785 encode_field_info (MonoAotCompile *cfg, MonoClassField *field, guint8 *buf, guint8 **endbuf)
1786 {
1787         guint32 token = mono_get_field_token (field);
1788         guint8 *p = buf;
1789
1790         encode_klass_ref (cfg, field->parent, p, &p);
1791         g_assert (mono_metadata_token_code (token) == MONO_TOKEN_FIELD_DEF);
1792         encode_value (token - MONO_TOKEN_FIELD_DEF, p, &p);
1793         *endbuf = p;
1794 }
1795
1796 #define MAX_IMAGE_INDEX 250
1797
1798 static void
1799 encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 **endbuf)
1800 {
1801         guint32 image_index = get_image_index (acfg, method->klass->image);
1802         guint32 token = method->token;
1803         MonoJumpInfoToken *ji;
1804         guint8 *p = buf;
1805
1806         g_assert (image_index < MAX_IMAGE_INDEX);
1807
1808         if (method->wrapper_type) {
1809                 /* Marker */
1810                 encode_value ((253 << 24), p, &p);
1811
1812                 encode_value (method->wrapper_type, p, &p);
1813
1814                 switch (method->wrapper_type) {
1815                 case MONO_WRAPPER_REMOTING_INVOKE:
1816                 case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
1817                 case MONO_WRAPPER_XDOMAIN_INVOKE: {
1818                         MonoMethod *m;
1819
1820                         m = mono_marshal_method_from_wrapper (method);
1821                         g_assert (m);
1822                         encode_method_ref (acfg, m, p, &p);
1823                         break;
1824                 }
1825                 case MONO_WRAPPER_PROXY_ISINST:
1826                 case MONO_WRAPPER_LDFLD:
1827                 case MONO_WRAPPER_LDFLDA:
1828                 case MONO_WRAPPER_STFLD:
1829                 case MONO_WRAPPER_ISINST: {
1830                         MonoClass *proxy_class = (MonoClass*)mono_marshal_method_from_wrapper (method);
1831                         encode_klass_ref (acfg, proxy_class, p, &p);
1832                         break;
1833                 }
1834                 case MONO_WRAPPER_LDFLD_REMOTE:
1835                 case MONO_WRAPPER_STFLD_REMOTE:
1836                         break;
1837                 case MONO_WRAPPER_ALLOC: {
1838                         int alloc_type = mono_gc_get_managed_allocator_type (method);
1839                         g_assert (alloc_type != -1);
1840                         encode_value (alloc_type, p, &p);
1841                         break;
1842                 }
1843                 case MONO_WRAPPER_STELEMREF:
1844                         break;
1845                 case MONO_WRAPPER_STATIC_RGCTX_INVOKE: {
1846                         MonoMethod *m;
1847
1848                         m = mono_marshal_method_from_wrapper (method);
1849                         g_assert (m);
1850                         encode_method_ref (acfg, m, p, &p);
1851                         break;
1852                 }
1853                 default:
1854                         g_assert_not_reached ();
1855                 }
1856         } else if (mono_method_signature (method)->is_inflated) {
1857                 /* 
1858                  * This is a generic method, find the original token which referenced it and
1859                  * encode that.
1860                  * Obtain the token from information recorded by the JIT.
1861                  */
1862                 ji = g_hash_table_lookup (acfg->token_info_hash, method);
1863                 if (ji) {
1864                         image_index = get_image_index (acfg, ji->image);
1865                         g_assert (image_index < MAX_IMAGE_INDEX);
1866                         token = ji->token;
1867
1868                         /* Marker */
1869                         encode_value ((255 << 24), p, &p);
1870                         encode_value (image_index, p, &p);
1871                         encode_value (token, p, &p);
1872                 } else {
1873                         MonoMethod *declaring;
1874                         MonoGenericContext *context = mono_method_get_context (method);
1875                         MonoGenericInst *inst;
1876                         int i;
1877
1878                         g_assert (method->is_inflated);
1879                         declaring = ((MonoMethodInflated*)method)->declaring;
1880
1881                         /*
1882                          * This might be a non-generic method of a generic instance, which 
1883                          * doesn't have a token since the reference is generated by the JIT 
1884                          * like Nullable:Box/Unbox, or by generic sharing.
1885                          */
1886
1887                         /* Marker */
1888                         encode_value ((254 << 24), p, &p);
1889                         /* Encode the klass */
1890                         encode_klass_ref (acfg, method->klass, p, &p);
1891                         /* Encode the method */
1892                         image_index = get_image_index (acfg, method->klass->image);
1893                         g_assert (image_index < MAX_IMAGE_INDEX);
1894                         g_assert (declaring->token);
1895                         token = declaring->token;
1896                         g_assert (mono_metadata_token_table (token) == MONO_TABLE_METHOD);
1897                         encode_value (image_index, p, &p);
1898                         encode_value (token, p, &p);
1899
1900                         /* Encode the context */
1901                         inst = context->class_inst;
1902                         encode_value (inst ? 1 : 0, p, &p);
1903                         if (inst) {
1904                                 encode_value (inst->type_argc, p, &p);
1905                                 for (i = 0; i < inst->type_argc; ++i)
1906                                         encode_klass_ref (acfg, mono_class_from_mono_type (inst->type_argv [i]), p, &p);
1907                         }
1908                         inst = context->method_inst;
1909                         encode_value (inst ? 1 : 0, p, &p);
1910                         if (inst) {
1911                                 encode_value (inst->type_argc, p, &p);
1912                                 for (i = 0; i < inst->type_argc; ++i)
1913                                         encode_klass_ref (acfg, mono_class_from_mono_type (inst->type_argv [i]), p, &p);
1914                         }
1915                 }
1916         } else if (token == 0) {
1917                 /* This might be a method of a constructed type like int[,].Set */
1918                 /* Obtain the token from information recorded by the JIT */
1919                 ji = g_hash_table_lookup (acfg->token_info_hash, method);
1920                 g_assert (ji);
1921                 image_index = get_image_index (acfg, ji->image);
1922                 g_assert (image_index < MAX_IMAGE_INDEX);
1923                 token = ji->token;
1924
1925                 /* Marker */
1926                 encode_value ((255 << 24), p, &p);
1927                 encode_value (image_index, p, &p);
1928                 encode_value (token, p, &p);
1929         } else {
1930                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_METHOD);
1931                 encode_value ((image_index << 24) | mono_metadata_token_index (token), p, &p);
1932         }
1933         *endbuf = p;
1934 }
1935
1936 static gint
1937 compare_patches (gconstpointer a, gconstpointer b)
1938 {
1939         int i, j;
1940
1941         i = (*(MonoJumpInfo**)a)->ip.i;
1942         j = (*(MonoJumpInfo**)b)->ip.i;
1943
1944         if (i < j)
1945                 return -1;
1946         else
1947                 if (i > j)
1948                         return 1;
1949         else
1950                 return 0;
1951 }
1952
1953 /*
1954  * is_plt_patch:
1955  *
1956  *   Return whenever PATCH_INFO refers to a direct call, and thus requires a
1957  * PLT entry.
1958  */
1959 static inline gboolean
1960 is_plt_patch (MonoJumpInfo *patch_info)
1961 {
1962         switch (patch_info->type) {
1963         case MONO_PATCH_INFO_METHOD:
1964         case MONO_PATCH_INFO_INTERNAL_METHOD:
1965         case MONO_PATCH_INFO_JIT_ICALL_ADDR:
1966         case MONO_PATCH_INFO_CLASS_INIT:
1967         case MONO_PATCH_INFO_RGCTX_FETCH:
1968         case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
1969                 return TRUE;
1970         default:
1971                 return FALSE;
1972         }
1973 }
1974
1975 /*
1976  * is_shared_got_patch:
1977  *
1978  *   Return whenever PATCH_INFO refers to a patch which needs a shared GOT
1979  * entry.
1980  * Keep it in sync with the version in aot-runtime.c.
1981  */
1982 static inline gboolean
1983 is_shared_got_patch (MonoJumpInfo *patch_info)
1984 {
1985         switch (patch_info->type) {
1986         case MONO_PATCH_INFO_VTABLE:
1987         case MONO_PATCH_INFO_CLASS:
1988         case MONO_PATCH_INFO_IID:
1989         case MONO_PATCH_INFO_ADJUSTED_IID:
1990         case MONO_PATCH_INFO_FIELD:
1991         case MONO_PATCH_INFO_SFLDA:
1992         case MONO_PATCH_INFO_DECLSEC:
1993         case MONO_PATCH_INFO_LDTOKEN:
1994         case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
1995         case MONO_PATCH_INFO_RVA:
1996         case MONO_PATCH_INFO_METHODCONST:
1997                 return TRUE;
1998         default:
1999                 return FALSE;
2000         }
2001 }
2002
2003 static int
2004 get_plt_offset (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
2005 {
2006         int res = -1;
2007
2008         if (is_plt_patch (patch_info)) {
2009                 int idx = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->patch_to_plt_offset, patch_info));
2010
2011                 if (idx) {
2012                         res = idx;
2013                 } else {
2014                         MonoJumpInfo *new_ji = mono_patch_info_dup_mp (acfg->mempool, patch_info);
2015
2016                         res = acfg->plt_offset;
2017                         g_hash_table_insert (acfg->plt_offset_to_patch, GUINT_TO_POINTER (res), new_ji);
2018                         g_hash_table_insert (acfg->patch_to_plt_offset, new_ji, GUINT_TO_POINTER (res));
2019                         acfg->plt_offset ++;
2020                 }
2021         }
2022
2023         return res;
2024 }
2025
2026 /**
2027  * get_got_offset:
2028  *
2029  *   Returns the offset of the GOT slot where the runtime object resulting from resolving
2030  * JI could be found if it exists, otherwise allocates a new one.
2031  */
2032 static guint32
2033 get_got_offset (MonoAotCompile *acfg, MonoJumpInfo *ji)
2034 {
2035         guint32 got_offset;
2036
2037         got_offset = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->patch_to_shared_got_offset, ji));
2038         if (got_offset)
2039                 return got_offset - 1;
2040
2041         got_offset = acfg->got_offset;
2042         acfg->got_offset ++;
2043
2044         acfg->stats.got_slots ++;
2045         acfg->stats.got_slot_types [ji->type] ++;
2046
2047         return got_offset;
2048 }
2049
2050 static guint32
2051 get_shared_got_offset (MonoAotCompile *acfg, MonoJumpInfo *ji)
2052 {
2053         MonoJumpInfo *copy;
2054         guint32 got_offset;
2055
2056         if (!g_hash_table_lookup (acfg->patch_to_shared_got_offset, ji)) {
2057                 got_offset = get_got_offset (acfg, ji);
2058                 copy = mono_patch_info_dup_mp (acfg->mempool, ji);
2059                 g_hash_table_insert (acfg->patch_to_shared_got_offset, copy, GUINT_TO_POINTER (got_offset + 1));
2060                 g_ptr_array_add (acfg->shared_patches, copy);
2061         }
2062
2063         return get_got_offset (acfg, ji);
2064 }
2065
2066 /* Add a method to the list of methods which need to be emitted */
2067 static void
2068 add_method_with_index (MonoAotCompile *acfg, MonoMethod *method, int index)
2069 {
2070         if (!g_hash_table_lookup (acfg->method_indexes, method)) {
2071                 g_ptr_array_add (acfg->methods, method);
2072                 g_hash_table_insert (acfg->method_indexes, method, GUINT_TO_POINTER (index + 1));
2073         }
2074 }
2075
2076 static guint32
2077 get_method_index (MonoAotCompile *acfg, MonoMethod *method)
2078 {
2079         int index = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_indexes, method));
2080         
2081         g_assert (index);
2082
2083         return index - 1;
2084 }
2085
2086 static int
2087 add_method (MonoAotCompile *acfg, MonoMethod *method)
2088 {
2089         int index;
2090
2091         index = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_indexes, method));
2092         if (index)
2093                 return index - 1;
2094
2095         index = acfg->method_index;
2096         add_method_with_index (acfg, method, index);
2097
2098         /* FIXME: Fix quadratic behavior */
2099         acfg->method_order = g_list_append (acfg->method_order, GUINT_TO_POINTER (index));
2100
2101         acfg->method_index ++;
2102
2103         return index;
2104 }
2105
2106 static void
2107 add_jit_icall_wrapper (gpointer key, gpointer value, gpointer user_data)
2108 {
2109         MonoAotCompile *acfg = user_data;
2110         MonoJitICallInfo *callinfo = value;
2111         MonoMethod *wrapper;
2112         char *name;
2113
2114         if (!callinfo->sig)
2115                 return;
2116
2117         name = g_strdup_printf ("__icall_wrapper_%s", callinfo->name);
2118         wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, check_for_pending_exc);
2119         g_free (name);
2120
2121         add_method (acfg, wrapper);
2122 }
2123
2124 static MonoMethod*
2125 get_runtime_invoke_sig (MonoMethodSignature *sig)
2126 {
2127         MonoMethodBuilder *mb;
2128         MonoMethod *m;
2129
2130         mb = mono_mb_new (mono_defaults.object_class, "FOO", MONO_WRAPPER_NONE);
2131         m = mono_mb_create_method (mb, sig, 16);
2132         return mono_marshal_get_runtime_invoke (m);
2133 }
2134
2135 static void
2136 add_wrappers (MonoAotCompile *acfg)
2137 {
2138         MonoMethod *method, *m;
2139         int i, j, nallocators;
2140         MonoMethodSignature *sig, *csig;
2141         guint32 token;
2142
2143         /* 
2144          * FIXME: Instead of AOTing all the wrappers, it might be better to redesign them
2145          * so there is only one wrapper of a given type, or inlining their contents into their
2146          * callers.
2147          */
2148
2149         /* 
2150          * FIXME: This depends on the fact that different wrappers have different 
2151          * names.
2152          */
2153
2154         /* FIXME: Collect these automatically */
2155
2156         /* Runtime invoke wrappers */
2157
2158         /* void runtime-invoke () [.cctor] */
2159         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
2160         csig->ret = &mono_defaults.void_class->byval_arg;
2161         add_method (acfg, get_runtime_invoke_sig (csig));
2162
2163         /* void runtime-invoke () [Finalize] */
2164         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
2165         csig->hasthis = 1;
2166         csig->ret = &mono_defaults.void_class->byval_arg;
2167         add_method (acfg, get_runtime_invoke_sig (csig));
2168
2169         /* void runtime-invoke (string) [exception ctor] */
2170         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
2171         csig->hasthis = 1;
2172         csig->ret = &mono_defaults.void_class->byval_arg;
2173         csig->params [0] = &mono_defaults.string_class->byval_arg;
2174         add_method (acfg, get_runtime_invoke_sig (csig));
2175
2176         /* void runtime-invoke (string, string) [exception ctor] */
2177         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
2178         csig->hasthis = 1;
2179         csig->ret = &mono_defaults.void_class->byval_arg;
2180         csig->params [0] = &mono_defaults.string_class->byval_arg;
2181         csig->params [1] = &mono_defaults.string_class->byval_arg;
2182         add_method (acfg, get_runtime_invoke_sig (csig));
2183
2184         /* string runtime-invoke () [Exception.ToString ()] */
2185         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
2186         csig->hasthis = 1;
2187         csig->ret = &mono_defaults.string_class->byval_arg;
2188         add_method (acfg, get_runtime_invoke_sig (csig));
2189
2190         /* void runtime-invoke (string, Exception) [exception ctor] */
2191         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
2192         csig->hasthis = 1;
2193         csig->ret = &mono_defaults.void_class->byval_arg;
2194         csig->params [0] = &mono_defaults.string_class->byval_arg;
2195         csig->params [1] = &mono_defaults.exception_class->byval_arg;
2196         add_method (acfg, get_runtime_invoke_sig (csig));
2197
2198         /* Assembly runtime-invoke (string, bool) [DoAssemblyResolve] */
2199         csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
2200         csig->hasthis = 1;
2201         csig->ret = &(mono_class_from_name (
2202                                                                                 mono_defaults.corlib, "System.Reflection", "Assembly"))->byval_arg;
2203         csig->params [0] = &mono_defaults.string_class->byval_arg;
2204         csig->params [1] = &mono_defaults.boolean_class->byval_arg;
2205         add_method (acfg, get_runtime_invoke_sig (csig));
2206
2207         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
2208                 MonoMethod *method;
2209                 guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
2210                 gboolean skip = FALSE;
2211
2212                 method = mono_get_method (acfg->image, token, NULL);
2213
2214                 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
2215                         (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
2216                         (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
2217                         skip = TRUE;
2218
2219                 /* Skip methods which can not be handled by get_runtime_invoke () */
2220                 sig = mono_method_signature (method);
2221                 if ((sig->ret->type == MONO_TYPE_PTR) ||
2222                         (sig->ret->type == MONO_TYPE_TYPEDBYREF))
2223                         skip = TRUE;
2224
2225                 for (j = 0; j < sig->param_count; j++) {
2226                         if (sig->params [j]->type == MONO_TYPE_TYPEDBYREF)
2227                                 skip = TRUE;
2228                 }
2229
2230                 if (!skip)
2231                         add_method (acfg, mono_marshal_get_runtime_invoke (method));
2232         }
2233
2234         if (strcmp (acfg->image->assembly->aname.name, "mscorlib") == 0) {
2235                 /* JIT icall wrappers */
2236                 /* FIXME: locking */
2237                 g_hash_table_foreach (mono_get_jit_icall_info (), add_jit_icall_wrapper, acfg);
2238
2239                 /* Managed Allocators */
2240                 nallocators = mono_gc_get_managed_allocator_types ();
2241                 for (i = 0; i < nallocators; ++i) {
2242                         m = mono_gc_get_managed_allocator_by_type (i);
2243                         if (m)
2244                                 add_method (acfg, m);
2245                 }
2246
2247                 /* stelemref */
2248                 add_method (acfg, mono_marshal_get_stelemref ());
2249         }
2250
2251         /* remoting-invoke wrappers */
2252         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
2253                 MonoMethodSignature *sig;
2254                 
2255                 token = MONO_TOKEN_METHOD_DEF | (i + 1);
2256                 method = mono_get_method (acfg->image, token, NULL);
2257
2258                 sig = mono_method_signature (method);
2259
2260                 if (sig->hasthis && (method->klass->marshalbyref || method->klass == mono_defaults.object_class) && 
2261                         !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
2262                         m = mono_marshal_get_remoting_invoke_with_check (method);
2263
2264                         add_method (acfg, m);
2265                 }
2266         }
2267
2268 #if 0
2269         /* static rgctx wrappers */
2270         /* FIXME: Each wrapper belongs to a given instantiation of a generic method */
2271         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
2272                 token = MONO_TOKEN_METHOD_DEF | (i + 1);
2273                 method = mono_get_method (acfg->image, token, NULL);
2274
2275                 if (((method->flags & METHOD_ATTRIBUTE_STATIC) ||
2276                          (method->is_inflated && mono_method_get_context (method)->method_inst)) &&
2277                         mono_class_generic_sharing_enabled (method->klass) &&
2278                         mono_method_is_generic_sharable_impl (method, FALSE)) {
2279                         m = mono_marshal_get_static_rgctx_invoke (method);
2280                         add_method (acfg, m);
2281                 }
2282         }
2283 #endif
2284 }
2285
2286 static void
2287 emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, guint32 code_len, MonoJumpInfo *relocs, gboolean got_only)
2288 {
2289         int i, pindex, start_index, method_index;
2290         GPtrArray *patches;
2291         MonoJumpInfo *patch_info;
2292         MonoMethodHeader *header;
2293         gboolean skip;
2294         guint32 got_slot;
2295
2296         if (method) {
2297                 header = mono_method_get_header (method);
2298
2299                 method_index = get_method_index (acfg, method);
2300         }
2301
2302         /* Collect and sort relocations */
2303         patches = g_ptr_array_new ();
2304         for (patch_info = relocs; patch_info; patch_info = patch_info->next)
2305                 g_ptr_array_add (patches, patch_info);
2306         g_ptr_array_sort (patches, compare_patches);
2307
2308         start_index = 0;
2309         for (i = 0; i < code_len; i++) {
2310                 patch_info = NULL;
2311                 for (pindex = start_index; pindex < patches->len; ++pindex) {
2312                         patch_info = g_ptr_array_index (patches, pindex);
2313                         if (patch_info->ip.i >= i)
2314                                 break;
2315                 }
2316
2317 #ifdef MONO_ARCH_AOT_SUPPORTED
2318                 skip = FALSE;
2319                 if (patch_info && (patch_info->ip.i == i) && (pindex < patches->len)) {
2320                         start_index = pindex;
2321
2322                         switch (patch_info->type) {
2323                         case MONO_PATCH_INFO_NONE:
2324                                 break;
2325                         case MONO_PATCH_INFO_GOT_OFFSET: {
2326                                 guint32 offset = mono_arch_get_patch_offset (code + i);
2327                                 emit_bytes (acfg, code + i, offset);
2328                                 emit_symbol_diff (acfg, "got", ".", offset);
2329
2330                                 i += offset + 4 - 1;
2331                                 skip = TRUE;
2332                                 break;
2333                         }
2334                         default: {
2335                                 char *direct_call_target;
2336
2337                                 if (!is_got_patch (patch_info->type))
2338                                         break;
2339
2340                                 /*
2341                                  * If this patch is a call, try emitting a direct call instead of
2342                                  * through a PLT entry. This is possible if the called method is in
2343                                  * the same assembly and requires no initialization.
2344                                  */
2345                                 direct_call_target = NULL;
2346                                 if (!got_only && (patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == method->klass->image)) {
2347                                         MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
2348                                         if (callee_cfg) {
2349                                                 if (!callee_cfg->has_got_slots && (callee_cfg->method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)) {
2350                                                         //printf ("DIRECT: %s %s\n", mono_method_full_name (cfg->method, TRUE), mono_method_full_name (callee_cfg->method, TRUE));
2351                                                         direct_call_target = g_strdup_printf (".Lm_%x", get_method_index (acfg, callee_cfg->orig_method));
2352                                                         patch_info->type = MONO_PATCH_INFO_NONE;
2353                                                         acfg->stats.direct_calls ++;
2354                                                 }
2355                                         }
2356
2357                                         acfg->stats.all_calls ++;
2358                                 }
2359
2360                                 if (!got_only && !direct_call_target) {
2361                                         int plt_offset = get_plt_offset (acfg, patch_info);
2362                                         if (plt_offset != -1) {
2363                                                 /* This patch has a PLT entry, so we must emit a call to the PLT entry */
2364                                                 direct_call_target = g_strdup_printf (".Lp_%d", plt_offset);
2365                 
2366                                                 /* Nullify the patch */
2367                                                 patch_info->type = MONO_PATCH_INFO_NONE;
2368                                         }
2369                                 }
2370
2371                                 if (direct_call_target) {
2372 #if defined(__i386__) || defined(__x86_64__)
2373                                         g_assert (code [i] == 0xe8);
2374                                         /* Need to make sure this is exactly 5 bytes long */
2375                                         emit_byte (acfg, '\xe8');
2376                                         emit_symbol_diff (acfg, direct_call_target, ".", -4);
2377                                         i += 4;
2378 #elif defined(__arm__)
2379 #ifdef USE_BIN_WRITER
2380                                         /* FIXME: Can't encode this using the current symbol writer functions */
2381                                         g_assert_not_reached ();
2382 #else
2383                                         emit_unset_mode (acfg);
2384                                         fprintf (acfg->fp, "bl %s\n", direct_call_target);
2385                                         i += 4 - 1;
2386 #endif
2387 #endif
2388
2389                                         g_free (direct_call_target);
2390                                 } else {
2391                                         got_slot = get_got_offset (acfg, patch_info);
2392
2393                                         emit_bytes (acfg, code + i, mono_arch_get_patch_offset (code + i));
2394 #ifdef __x86_64__
2395                                         emit_symbol_diff (acfg, "got", ".", (unsigned int) ((got_slot * sizeof (gpointer)) - 4));
2396 #elif defined(__i386__)
2397                                         emit_int32 (acfg, (unsigned int) ((got_slot * sizeof (gpointer))));
2398 #elif defined(__arm__)
2399                                         emit_symbol_diff (acfg, "got", ".", (unsigned int) ((got_slot * sizeof (gpointer))) - 12);
2400 #else
2401                                         g_assert_not_reached ();
2402 #endif
2403                                         
2404                                         i += mono_arch_get_patch_offset (code + i) + 4 - 1;
2405                                 }
2406                                 skip = TRUE;
2407                         }
2408                         }
2409                 }
2410 #endif /* MONO_ARCH_AOT_SUPPORTED */
2411
2412                 if (!skip)
2413                         emit_bytes (acfg, code + i, 1);
2414         }
2415 }
2416
2417 static void
2418 emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg)
2419 {
2420         MonoMethod *method;
2421         int method_index;
2422         guint8 *code;
2423         char *symbol;
2424         int func_alignment = 16;
2425         MonoMethodHeader *header;
2426
2427         method = cfg->orig_method;
2428         code = cfg->native_code;
2429         header = mono_method_get_header (method);
2430
2431         method_index = get_method_index (acfg, method);
2432
2433         /* Make the labels local */
2434         symbol = g_strdup_printf (".Lm_%x", method_index);
2435
2436         emit_alignment (acfg, func_alignment);
2437         emit_label (acfg, symbol);
2438         if (acfg->aot_opts.write_symbols)
2439                 emit_global (acfg, symbol, TRUE);
2440
2441         if (cfg->verbose_level > 0)
2442                 g_print ("Method %s emitted as %s\n", mono_method_full_name (method, TRUE), symbol);
2443         g_free (symbol);
2444
2445         acfg->stats.code_size += cfg->code_len;
2446
2447         acfg->method_got_offsets [method_index] = acfg->got_offset;
2448
2449         emit_and_reloc_code (acfg, method, code, cfg->code_len, cfg->patch_info, FALSE);
2450
2451         emit_line (acfg);
2452 }
2453
2454 /**
2455  * encode_patch:
2456  *
2457  *  Encode PATCH_INFO into its disk representation.
2458  */
2459 static void
2460 encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint8 **endbuf)
2461 {
2462         guint8 *p = buf;
2463
2464         switch (patch_info->type) {
2465         case MONO_PATCH_INFO_NONE:
2466                 break;
2467         case MONO_PATCH_INFO_IMAGE:
2468                 encode_value (get_image_index (acfg, patch_info->data.image), p, &p);
2469                 break;
2470         case MONO_PATCH_INFO_METHOD_REL:
2471                 encode_value ((gint)patch_info->data.offset, p, &p);
2472                 break;
2473         case MONO_PATCH_INFO_SWITCH: {
2474                 gpointer *table = (gpointer *)patch_info->data.table->table;
2475                 int k;
2476
2477                 encode_value (patch_info->data.table->table_size, p, &p);
2478                 for (k = 0; k < patch_info->data.table->table_size; k++)
2479                         encode_value ((int)(gssize)table [k], p, &p);
2480                 break;
2481         }
2482         case MONO_PATCH_INFO_METHODCONST:
2483         case MONO_PATCH_INFO_METHOD:
2484         case MONO_PATCH_INFO_METHOD_JUMP:
2485         case MONO_PATCH_INFO_ICALL_ADDR:
2486         case MONO_PATCH_INFO_METHOD_RGCTX:
2487                 encode_method_ref (acfg, patch_info->data.method, p, &p);
2488                 break;
2489         case MONO_PATCH_INFO_INTERNAL_METHOD:
2490         case MONO_PATCH_INFO_JIT_ICALL_ADDR: {
2491                 guint32 len = strlen (patch_info->data.name);
2492
2493                 encode_value (len, p, &p);
2494
2495                 memcpy (p, patch_info->data.name, len);
2496                 p += len;
2497                 *p++ = '\0';
2498                 break;
2499         }
2500         case MONO_PATCH_INFO_LDSTR: {
2501                 guint32 image_index = get_image_index (acfg, patch_info->data.token->image);
2502                 guint32 token = patch_info->data.token->token;
2503                 g_assert (mono_metadata_token_code (token) == MONO_TOKEN_STRING);
2504                 encode_value (image_index, p, &p);
2505                 encode_value (patch_info->data.token->token - MONO_TOKEN_STRING, p, &p);
2506                 break;
2507         }
2508         case MONO_PATCH_INFO_RVA:
2509         case MONO_PATCH_INFO_DECLSEC:
2510         case MONO_PATCH_INFO_LDTOKEN:
2511         case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
2512                 encode_value (get_image_index (acfg, patch_info->data.token->image), p, &p);
2513                 encode_value (patch_info->data.token->token, p, &p);
2514                 break;
2515         case MONO_PATCH_INFO_EXC_NAME: {
2516                 MonoClass *ex_class;
2517
2518                 ex_class =
2519                         mono_class_from_name (mono_defaults.exception_class->image,
2520                                                                   "System", patch_info->data.target);
2521                 g_assert (ex_class);
2522                 encode_klass_ref (acfg, ex_class, p, &p);
2523                 break;
2524         }
2525         case MONO_PATCH_INFO_R4:
2526                 encode_value (*((guint32 *)patch_info->data.target), p, &p);
2527                 break;
2528         case MONO_PATCH_INFO_R8:
2529                 encode_value (*((guint32 *)patch_info->data.target), p, &p);
2530                 encode_value (*(((guint32 *)patch_info->data.target) + 1), p, &p);
2531                 break;
2532         case MONO_PATCH_INFO_VTABLE:
2533         case MONO_PATCH_INFO_CLASS:
2534         case MONO_PATCH_INFO_IID:
2535         case MONO_PATCH_INFO_ADJUSTED_IID:
2536                 encode_klass_ref (acfg, patch_info->data.klass, p, &p);
2537                 break;
2538         case MONO_PATCH_INFO_CLASS_INIT:
2539         case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
2540                 encode_klass_ref (acfg, patch_info->data.klass, p, &p);
2541                 break;
2542         case MONO_PATCH_INFO_FIELD:
2543         case MONO_PATCH_INFO_SFLDA:
2544                 encode_field_info (acfg, patch_info->data.field, p, &p);
2545                 break;
2546         case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
2547                 break;
2548         case MONO_PATCH_INFO_RGCTX_FETCH: {
2549                 MonoJumpInfoRgctxEntry *entry = patch_info->data.rgctx_entry;
2550
2551                 encode_method_ref (acfg, entry->method, p, &p);
2552                 encode_value (entry->in_mrgctx, p, &p);
2553                 encode_value (entry->info_type, p, &p);
2554                 encode_value (entry->data->type, p, &p);
2555                 encode_patch (acfg, entry->data, p, &p);
2556                 break;
2557         }
2558         case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
2559                 break;
2560         default:
2561                 g_warning ("unable to handle jump info %d", patch_info->type);
2562                 g_assert_not_reached ();
2563         }
2564
2565         *endbuf = p;
2566 }
2567
2568 static void
2569 encode_patch_list (MonoAotCompile *acfg, GPtrArray *patches, int n_patches, int first_got_offset, guint8 *buf, guint8 **endbuf)
2570 {
2571         guint8 *p = buf;
2572         guint32 last_offset, j, pindex;
2573         MonoJumpInfo *patch_info;
2574
2575         encode_value (n_patches, p, &p);
2576
2577         if (n_patches)
2578                 encode_value (first_got_offset, p, &p);
2579
2580         /* First encode the type+position table */
2581         last_offset = 0;
2582         j = 0;
2583         for (pindex = 0; pindex < patches->len; ++pindex) {
2584                 guint32 offset;
2585                 patch_info = g_ptr_array_index (patches, pindex);
2586                 
2587                 if (patch_info->type == MONO_PATCH_INFO_NONE)
2588                         /* Nothing to do */
2589                         continue;
2590
2591                 j ++;
2592                 //printf ("T: %d O: %d.\n", patch_info->type, patch_info->ip.i);
2593                 offset = patch_info->ip.i - last_offset;
2594                 last_offset = patch_info->ip.i;
2595
2596                 /* Only the type is needed */
2597                 *p = patch_info->type;
2598                 p++;
2599         }
2600
2601         /* Then encode the other info */
2602         for (pindex = 0; pindex < patches->len; ++pindex) {
2603                 patch_info = g_ptr_array_index (patches, pindex);
2604
2605                 if (is_shared_got_patch (patch_info)) {
2606                         guint32 offset = get_got_offset (acfg, patch_info);
2607                         encode_value (offset, p, &p);
2608                 } else {
2609                         encode_patch (acfg, patch_info, p, &p);
2610                 }
2611         }
2612
2613         *endbuf = p;
2614 }
2615
2616 static void
2617 emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
2618 {
2619         MonoMethod *method;
2620         GList *l;
2621         int pindex, buf_size, n_patches;
2622         guint8 *code;
2623         char *symbol;
2624         GPtrArray *patches;
2625         MonoJumpInfo *patch_info;
2626         MonoMethodHeader *header;
2627         guint32 method_index;
2628         guint8 *p, *buf;
2629         guint32 first_got_offset;
2630
2631         method = cfg->orig_method;
2632         code = cfg->native_code;
2633         header = mono_method_get_header (method);
2634
2635         method_index = get_method_index (acfg, method);
2636
2637         /* Make the labels local */
2638         symbol = g_strdup_printf (".Lm_%x_p", method_index);
2639
2640         /* Sort relocations */
2641         patches = g_ptr_array_new ();
2642         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next)
2643                 g_ptr_array_add (patches, patch_info);
2644         g_ptr_array_sort (patches, compare_patches);
2645
2646         first_got_offset = acfg->method_got_offsets [method_index];
2647
2648         /**********************/
2649         /* Encode method info */
2650         /**********************/
2651
2652         buf_size = (patches->len < 1000) ? 40960 : 40960 + (patches->len * 64);
2653         p = buf = g_malloc (buf_size);
2654
2655         if (mono_class_get_cctor (method->klass))
2656                 encode_klass_ref (acfg, method->klass, p, &p);
2657         else
2658                 /* Not needed when loading the method */
2659                 encode_value (0, p, &p);
2660
2661         /* String table */
2662         if (cfg->opt & MONO_OPT_SHARED) {
2663                 encode_value (g_list_length (cfg->ldstr_list), p, &p);
2664                 for (l = cfg->ldstr_list; l; l = l->next) {
2665                         encode_value ((long)l->data, p, &p);
2666                 }
2667         }
2668         else
2669                 /* Used only in shared mode */
2670                 g_assert (!cfg->ldstr_list);
2671
2672         n_patches = 0;
2673         for (pindex = 0; pindex < patches->len; ++pindex) {
2674                 patch_info = g_ptr_array_index (patches, pindex);
2675                 
2676                 if ((patch_info->type == MONO_PATCH_INFO_GOT_OFFSET) ||
2677                         (patch_info->type == MONO_PATCH_INFO_NONE)) {
2678                         patch_info->type = MONO_PATCH_INFO_NONE;
2679                         /* Nothing to do */
2680                         continue;
2681                 }
2682
2683                 if ((patch_info->type == MONO_PATCH_INFO_IMAGE) && (patch_info->data.image == acfg->image)) {
2684                         /* Stored in a GOT slot initialized at module load time */
2685                         patch_info->type = MONO_PATCH_INFO_NONE;
2686                         continue;
2687                 }
2688
2689                 if (is_plt_patch (patch_info)) {
2690                         /* Calls are made through the PLT */
2691                         patch_info->type = MONO_PATCH_INFO_NONE;
2692                         continue;
2693                 }
2694
2695                 n_patches ++;
2696         }
2697
2698         if (n_patches)
2699                 g_assert (cfg->has_got_slots);
2700
2701         encode_patch_list (acfg, patches, n_patches, first_got_offset, p, &p);
2702
2703         acfg->stats.info_size += p - buf;
2704
2705         /* Emit method info */
2706
2707         emit_label (acfg, symbol);
2708         g_free (symbol);
2709
2710         g_assert (p - buf < buf_size);
2711         emit_bytes (acfg, buf, p - buf);
2712         g_free (buf);
2713 }
2714
2715 static void
2716 emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
2717 {
2718         MonoMethod *method;
2719         int k, buf_size, method_index;
2720         guint32 debug_info_size;
2721         guint8 *code;
2722         char *symbol;
2723         MonoMethodHeader *header;
2724         guint8 *p, *buf, *debug_info;
2725         MonoJitInfo *jinfo = cfg->jit_info;
2726
2727         method = cfg->orig_method;
2728         code = cfg->native_code;
2729         header = mono_method_get_header (method);
2730
2731         method_index = get_method_index (acfg, method);
2732
2733         /* Make the labels local */
2734         symbol = g_strdup_printf (".Le_%x_p", method_index);
2735
2736         mono_debug_serialize_debug_info (cfg, &debug_info, &debug_info_size);
2737
2738         buf_size = header->num_clauses * 256 + debug_info_size + 128;
2739         p = buf = g_malloc (buf_size);
2740
2741         encode_value (cfg->code_len, p, &p);
2742         encode_value (cfg->used_int_regs, p, &p);
2743         encode_value (jinfo->has_generic_jit_info, p, &p);
2744
2745         /* Exception table */
2746         if (header->num_clauses) {
2747                 for (k = 0; k < header->num_clauses; ++k) {
2748                         MonoJitExceptionInfo *ei = &jinfo->clauses [k];
2749
2750                         encode_value (ei->exvar_offset, p, &p);
2751
2752                         if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
2753                                 encode_value ((gint)((guint8*)ei->data.filter - code), p, &p);
2754
2755                         encode_value ((gint)((guint8*)ei->try_start - code), p, &p);
2756                         encode_value ((gint)((guint8*)ei->try_end - code), p, &p);
2757                         encode_value ((gint)((guint8*)ei->handler_start - code), p, &p);
2758                 }
2759         }
2760
2761         if (jinfo->has_generic_jit_info) {
2762                 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (jinfo);
2763
2764                 encode_value (gi->has_this ? 1 : 0, p, &p);
2765                 encode_value (gi->this_reg, p, &p);
2766                 encode_value (gi->this_offset, p, &p);
2767
2768                 /* 
2769                  * Need to encode jinfo->method too, since it is not equal to 'method'
2770                  * when using generic sharing.
2771                  */
2772                 encode_method_ref (acfg, jinfo->method, p, &p);
2773         }
2774
2775         g_assert (debug_info_size < buf_size);
2776
2777         encode_value (debug_info_size, p, &p);
2778         if (debug_info_size) {
2779                 memcpy (p, debug_info, debug_info_size);
2780                 p += debug_info_size;
2781                 g_free (debug_info);
2782         }
2783
2784         acfg->stats.ex_info_size += p - buf;
2785
2786         /* Emit info */
2787
2788         emit_label (acfg, symbol);
2789         g_free (symbol);
2790
2791         g_assert (p - buf < buf_size);
2792         emit_bytes (acfg, buf, p - buf);
2793         g_free (buf);
2794 }
2795
2796 static void
2797 emit_klass_info (MonoAotCompile *acfg, guint32 token)
2798 {
2799         MonoClass *klass = mono_class_get (acfg->image, token);
2800         guint8 *p, *buf;
2801         int i, buf_size;
2802         char *symbol;
2803         gboolean no_special_static, cant_encode;
2804         gpointer iter = NULL;
2805
2806         buf_size = 10240 + (klass->vtable_size * 16);
2807         p = buf = g_malloc (buf_size);
2808
2809         g_assert (klass);
2810
2811         mono_class_init (klass);
2812
2813         mono_class_get_nested_types (klass, &iter);
2814         g_assert (klass->nested_classes_inited);
2815
2816         mono_class_setup_vtable (klass);
2817
2818         /* 
2819          * Emit all the information which is required for creating vtables so
2820          * the runtime does not need to create the MonoMethod structures which
2821          * take up a lot of space.
2822          */
2823
2824         no_special_static = !mono_class_has_special_static_fields (klass);
2825
2826         /* Check whenever we have enough info to encode the vtable */
2827         cant_encode = FALSE;
2828         for (i = 0; i < klass->vtable_size; ++i) {
2829                 MonoMethod *cm = klass->vtable [i];
2830
2831                 if (cm && mono_method_signature (cm)->is_inflated && !g_hash_table_lookup (acfg->token_info_hash, cm))
2832                         cant_encode = TRUE;
2833         }
2834
2835         if (klass->generic_container || cant_encode) {
2836                 encode_value (-1, p, &p);
2837         } else {
2838                 encode_value (klass->vtable_size, p, &p);
2839                 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);
2840                 if (klass->has_cctor)
2841                         encode_method_ref (acfg, mono_class_get_cctor (klass), p, &p);
2842                 if (klass->has_finalize)
2843                         encode_method_ref (acfg, mono_class_get_finalizer (klass), p, &p);
2844  
2845                 encode_value (klass->instance_size, p, &p);
2846                 encode_value (mono_class_data_size (klass), p, &p);
2847                 encode_value (klass->packing_size, p, &p);
2848                 encode_value (klass->min_align, p, &p);
2849
2850                 for (i = 0; i < klass->vtable_size; ++i) {
2851                         MonoMethod *cm = klass->vtable [i];
2852
2853                         if (cm)
2854                                 encode_method_ref (acfg, cm, p, &p);
2855                         else
2856                                 encode_value (0, p, &p);
2857                 }
2858         }
2859
2860         acfg->stats.class_info_size += p - buf;
2861
2862         /* Emit the info */
2863         symbol = g_strdup_printf (".LK_I_%x", token - MONO_TOKEN_TYPE_DEF - 1);
2864         emit_label (acfg, symbol);
2865         g_free (symbol);
2866
2867         g_assert (p - buf < buf_size);
2868         emit_bytes (acfg, buf, p - buf);
2869         g_free (buf);
2870 }
2871
2872 /*
2873  * Calls made from AOTed code are routed through a table of jumps similar to the
2874  * ELF PLT (Program Linkage Table). The differences are the following:
2875  * - the ELF PLT entries make an indirect jump though the GOT so they expect the
2876  *   GOT pointer to be in EBX. We want to avoid this, so our table contains direct
2877  *   jumps. This means the jumps need to be patched when the address of the callee is
2878  *   known. Initially the PLT entries jump to code which transfers control to the
2879  *   AOT runtime through the first PLT entry.
2880  */
2881 static void
2882 emit_plt (MonoAotCompile *acfg)
2883 {
2884         char *symbol;
2885         int i, buf_size;
2886         guint8 *p, *buf;
2887         guint32 *plt_info_offsets;
2888
2889         /*
2890          * Encode info need to resolve PLT entries.
2891          */
2892         buf_size = acfg->plt_offset * 128;
2893         p = buf = g_malloc (buf_size);
2894
2895         plt_info_offsets = g_new0 (guint32, acfg->plt_offset);
2896
2897         for (i = 1; i < acfg->plt_offset; ++i) {
2898                 MonoJumpInfo *patch_info = g_hash_table_lookup (acfg->plt_offset_to_patch, GUINT_TO_POINTER (i));
2899
2900                 plt_info_offsets [i] = p - buf;
2901                 encode_value (patch_info->type, p, &p);
2902                 encode_patch (acfg, patch_info, p, &p);
2903         }
2904
2905         emit_line (acfg);
2906         symbol = g_strdup_printf ("plt");
2907
2908         /* This section will be made read-write by the AOT loader */
2909         emit_section_change (acfg, ".text", 0);
2910         emit_global (acfg, symbol, TRUE);
2911         emit_alignment (acfg, PAGESIZE);
2912         emit_label (acfg, symbol);
2913         g_free (symbol);
2914
2915 #if defined(USE_BIN_WRITER) && defined(__arm__)
2916         /* FIXME: */
2917         g_assert_not_reached ();
2918 #endif
2919
2920         for (i = 0; i < acfg->plt_offset; ++i) {
2921                 char *label;
2922
2923                 label = g_strdup_printf (".Lp_%d", i);
2924                 emit_label (acfg, label);
2925                 g_free (label);
2926
2927                 /* 
2928                  * The first plt entry is used to transfer code to the AOT loader. 
2929                  */
2930
2931 #if defined(__i386__)
2932                 if (i == 0) {
2933                         /* It is filled up during loading by the AOT loader. */
2934                         emit_zero_bytes (acfg, 16);
2935                 } else {
2936                         /* Need to make sure this is 9 bytes long */
2937                         emit_byte (acfg, '\xe9');
2938                         emit_symbol_diff (acfg, "plt", ".", -4);
2939                         emit_int32 (acfg, plt_info_offsets [i]);
2940                 }
2941 #elif defined(__x86_64__)
2942                 /*
2943                  * We can't emit jumps because they are 32 bits only so they can't be patched.
2944                  * So we emit a jump table instead whose entries are patched by the AOT loader to
2945                  * point to .Lpd entries. ELF stores these in the GOT too, but we don't, since
2946                  * methods with GOT entries can't be called directly.
2947                  * We also emit the default PLT code here since the PLT code will not be patched.
2948                  * An x86_64 plt entry is 10 bytes long, init_plt () depends on this.
2949                  */
2950                 /* jmpq *<offset>(%rip) */
2951                 emit_byte (acfg, '\xff');
2952                 emit_byte (acfg, '\x25');
2953                 emit_symbol_diff (acfg, "plt_jump_table", ".", (i * sizeof (gpointer)) -4);
2954                 /* Used by mono_aot_get_plt_info_offset */
2955                 emit_int32 (acfg, plt_info_offsets [i]);
2956 #elif defined(__arm__)
2957                 /* FIXME:
2958                  * - optimize OP_AOTCONST implementation
2959                  * - optimize the PLT entries
2960                  * - optimize SWITCH AOT implementation
2961                  * - implement IMT support
2962                  */
2963                 emit_unset_mode (acfg);
2964                 fprintf (acfg->fp, "\tldr ip, [pc, #4]\n");
2965                 fprintf (acfg->fp, "\tadd ip, pc, ip\n");
2966                 fprintf (acfg->fp, "\tldr pc, [ip, #0]\n");
2967                 emit_symbol_diff (acfg, "plt_jump_table", ".", 0);
2968                 /* Used by mono_aot_get_plt_info_offset */
2969     #if defined(__MACH__)
2970                 fprintf (acfg->fp, "\n\t.long %d\n", plt_info_offsets [i]);
2971     #else
2972                 fprintf (acfg->fp, "\n\t.word %d\n", plt_info_offsets [i]);
2973     #endif
2974
2975 #else
2976                 g_assert_not_reached ();
2977 #endif
2978         }
2979
2980         g_free (plt_info_offsets);
2981
2982         symbol = g_strdup_printf ("plt_end");
2983         emit_global (acfg, symbol, TRUE);
2984         emit_label (acfg, symbol);
2985         g_free (symbol);
2986
2987         /* Emit PLT info */
2988         symbol = g_strdup_printf ("plt_info");
2989         emit_global (acfg, symbol, FALSE);
2990         emit_label (acfg, symbol);
2991         g_free (symbol);
2992
2993         g_assert (p - buf < buf_size);
2994         emit_bytes (acfg, buf, p - buf);
2995         g_free (buf);
2996
2997         symbol = g_strdup_printf ("plt_jump_table_addr");
2998         emit_section_change (acfg, ".data", 0);
2999         emit_global (acfg, symbol, FALSE);
3000         emit_alignment (acfg, 8);
3001         emit_label (acfg, symbol);
3002         emit_pointer (acfg, "plt_jump_table");
3003         g_free (symbol);
3004
3005         symbol = g_strdup_printf ("plt_jump_table_size");
3006         emit_section_change (acfg, ".data", 0);
3007         emit_global (acfg, symbol, FALSE);
3008         emit_alignment (acfg, 8);
3009         emit_label (acfg, symbol);
3010         emit_symbol_diff (acfg, "plt_jump_table_end", "plt_jump_table", 0);
3011         g_free (symbol);
3012
3013         /* Don't make this a global so accesses don't need relocations */
3014         symbol = g_strdup_printf ("plt_jump_table");
3015         emit_section_change (acfg, ".bss", 0);
3016         emit_label (acfg, symbol);
3017         g_free (symbol);
3018
3019 #if defined(__x86_64__) || defined(__arm__)
3020         emit_zero_bytes (acfg, (int)(acfg->plt_offset * sizeof (gpointer)));
3021 #endif  
3022
3023         symbol = g_strdup_printf ("plt_jump_table_end");
3024         emit_label (acfg, symbol);
3025         g_free (symbol);
3026 }
3027
3028 static G_GNUC_UNUSED void
3029 emit_named_code (MonoAotCompile *acfg, const char *name, guint8 *code, 
3030                                  guint32 code_size, int got_offset, MonoJumpInfo *ji)
3031 {
3032         char *symbol;
3033         guint32 buf_size;
3034         MonoJumpInfo *patch_info;
3035         guint8 *buf, *p;
3036         GPtrArray *patches;
3037
3038         /* Emit code */
3039
3040         symbol = g_strdup_printf ("%s", name);
3041
3042         emit_section_change (acfg, ".text", 0);
3043         emit_global (acfg, symbol, TRUE);
3044         emit_alignment (acfg, 16);
3045         emit_label (acfg, symbol);
3046         g_free (symbol);
3047
3048         /* 
3049          * The code should access everything through the GOT, so we pass
3050          * TRUE here.
3051          */
3052         emit_and_reloc_code (acfg, NULL, code, code_size, ji, TRUE);
3053
3054         /* Emit info */
3055
3056         /* Sort relocations */
3057         patches = g_ptr_array_new ();
3058         for (patch_info = ji; patch_info; patch_info = patch_info->next)
3059                 g_ptr_array_add (patches, patch_info);
3060         g_ptr_array_sort (patches, compare_patches);
3061
3062         buf_size = patches->len * 128 + 128;
3063         buf = g_malloc (buf_size);
3064         p = buf;
3065
3066         encode_patch_list (acfg, patches, patches->len, got_offset, p, &p);
3067         g_assert (p - buf < buf_size);
3068
3069         symbol = g_strdup_printf ("%s_p", name);
3070
3071         emit_section_change (acfg, ".text", 0);
3072         emit_global (acfg, symbol, FALSE);
3073         emit_label (acfg, symbol);
3074         g_free (symbol);
3075                 
3076         emit_bytes (acfg, buf, p - buf);
3077 }
3078
3079 /*
3080  * When running in aot-only mode, we can't create trampolines at runtime, so we create 
3081  * a few, and save them in the AOT file. Normal trampolines embed their argument as a 
3082  * literal inside the trampoline code, we can't do that here, so instead we embed an offset
3083  * which needs to be added to the trampoline address to get the address of the GOT slot
3084  * which contains the argument value.
3085  * The generated trampolines jump to the generic trampolines using another GOT slot, which
3086  * will be setup by the AOT loader to point to the generic trampoline code of the given 
3087  * type.
3088  */
3089 static void
3090 emit_trampolines (MonoAotCompile *acfg)
3091 {
3092         char *symbol;
3093         int i, offset;
3094 #ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
3095         int tramp_type;
3096         guint32 code_size;
3097         MonoJumpInfo *ji;
3098         guint8 *code;
3099 #endif
3100
3101         if (!acfg->aot_opts.full_aot)
3102                 return;
3103         
3104         g_assert (acfg->image->assembly);
3105
3106         /* Currently, we only emit most trampolines into the mscorlib AOT image. */
3107         if (strcmp (acfg->image->assembly->aname.name, "mscorlib") == 0) {
3108 #ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
3109                 /*
3110                  * Emit the generic trampolines.
3111                  *
3112                  * We could save some code by treating the generic trampolines as a wrapper
3113                  * method, but that approach has its own complexities, so we choose the simpler
3114                  * method.
3115                  */
3116                 for (tramp_type = 0; tramp_type < MONO_TRAMPOLINE_NUM; ++tramp_type) {
3117                         code = mono_arch_create_trampoline_code_full (tramp_type, &code_size, &ji, TRUE);
3118
3119                         /* Emit trampoline code */
3120
3121                         symbol = g_strdup_printf ("generic_trampoline_%d", tramp_type);
3122
3123                         emit_named_code (acfg, symbol, code, code_size, acfg->got_offset, ji);
3124
3125                         g_free (symbol);
3126                 }
3127
3128                 code = mono_arch_get_nullified_class_init_trampoline (&code_size);
3129                 emit_named_code (acfg, "nullified_class_init_trampoline", code, code_size, acfg->got_offset, NULL);
3130
3131                 /* Emit the exception related code pieces */
3132                 code = mono_arch_get_restore_context_full (&code_size, &ji, TRUE);
3133                 emit_named_code (acfg, "restore_context", code, code_size, acfg->got_offset, ji);
3134                 code = mono_arch_get_call_filter_full (&code_size, &ji, TRUE);
3135                 emit_named_code (acfg, "call_filter", code, code_size, acfg->got_offset, ji);
3136                 code = mono_arch_get_throw_exception_full (&code_size, &ji, TRUE);
3137                 emit_named_code (acfg, "throw_exception", code, code_size, acfg->got_offset, ji);
3138                 code = mono_arch_get_rethrow_exception_full (&code_size, &ji, TRUE);
3139                 emit_named_code (acfg, "rethrow_exception", code, code_size, acfg->got_offset, ji);
3140                 code = mono_arch_get_throw_exception_by_name_full (&code_size, &ji, TRUE);
3141                 emit_named_code (acfg, "throw_exception_by_name", code, code_size, acfg->got_offset, ji);
3142                 code = mono_arch_get_throw_corlib_exception_full (&code_size, &ji, TRUE);
3143                 emit_named_code (acfg, "throw_corlib_exception", code, code_size, acfg->got_offset, ji);
3144
3145 #ifdef __x86_64__
3146                 for (i = 0; i < 128; ++i) {
3147                         int offset;
3148
3149                         offset = MONO_RGCTX_SLOT_MAKE_RGCTX (i);
3150                         code = mono_arch_create_rgctx_lazy_fetch_trampoline_full (offset, &code_size, &ji, TRUE);
3151                         symbol = g_strdup_printf ("rgctx_fetch_trampoline_%u", offset);
3152                         emit_named_code (acfg, symbol, code, code_size, acfg->got_offset, ji);
3153                         g_free (symbol);
3154
3155                         offset = MONO_RGCTX_SLOT_MAKE_MRGCTX (i);
3156                         code = mono_arch_create_rgctx_lazy_fetch_trampoline_full (offset, &code_size, &ji, TRUE);
3157                         symbol = g_strdup_printf ("rgctx_fetch_trampoline_%u", offset);
3158                         emit_named_code (acfg, symbol, code, code_size, acfg->got_offset, ji);
3159                         g_free (symbol);
3160                 }
3161 #endif
3162 #endif
3163
3164                 /*
3165                  * FIXME: Maybe we should use more specific trampolines (i.e. one class init for
3166                  * each class).
3167                  */
3168
3169                 /* Reserve some entries at the end of the GOT for our use */
3170                 acfg->num_trampoline_got_entries = acfg->num_aot_trampolines * 2;
3171
3172                 symbol = g_strdup_printf ("trampolines");
3173
3174                 emit_section_change (acfg, ".text", 0);
3175                 emit_global (acfg, symbol, TRUE);
3176                 emit_alignment (acfg, 16);
3177                 emit_label (acfg, symbol);
3178
3179                 for (i = 0; i < acfg->num_aot_trampolines; ++i) {
3180                         offset = acfg->got_offset + (i * 2);
3181
3182                         /*
3183                          * The trampolines created here are variations of the specific 
3184                          * trampolines created in mono_arch_create_specific_trampoline (). The 
3185                          * differences are:
3186                          * - the generic trampoline address is taken from a got slot.
3187                          * - the offset of the got slot where the trampoline argument is stored
3188                          *   is embedded in the instruction stream, and the generic trampoline
3189                          *   can load the argument by loading the offset, adding it to the
3190                          *   address of the trampoline to get the address of the got slot, and
3191                          *   loading the argument from the there.
3192                          */
3193 #if defined(__x86_64__)
3194                         /* This should be exactly 16 bytes long */
3195                         /* It should work together with the generic trampoline code in tramp-amd64.c */
3196                         /* call *<offset>(%rip) */
3197                         emit_byte (acfg, '\x41');
3198                         emit_byte (acfg, '\xff');
3199                         emit_byte (acfg, '\x15');
3200                         emit_symbol_diff (acfg, "got", ".", (offset * sizeof (gpointer)) - 4);
3201                         /* This should be relative to the start of the trampoline */
3202                         emit_symbol_diff (acfg, "got", ".", (offset * sizeof (gpointer)) - 4 + 19);
3203                         emit_zero_bytes (acfg, 5);
3204 #elif defined(__arm__)
3205                         {
3206                                 guint8 buf [128];
3207
3208                                 /* Generate the trampoline code */
3209                                 /* This should be exactly 28 bytes long */
3210
3211                                 code = buf;
3212                                 ARM_PUSH (code, 0x5fff);
3213                                 ARM_LDR_IMM (code, ARMREG_R1, ARMREG_PC, 8);
3214                                 /* Load the value from the GOT */
3215                                 ARM_LDR_REG_REG (code, ARMREG_R1, ARMREG_PC, ARMREG_R1);
3216                                 /* Branch to it */
3217                                 ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_PC);
3218                                 ARM_MOV_REG_REG (code, ARMREG_PC, ARMREG_R1);
3219
3220                                 g_assert (code - buf == 20);
3221
3222                                 /* Emit it */
3223                                 emit_bytes (acfg, buf, code - buf);
3224                                 emit_symbol_diff (acfg, "got", ".", (offset * sizeof (gpointer)) - 4 + 8);
3225                                 emit_symbol_diff (acfg, "got", ".", ((offset + 1) * sizeof (gpointer)) - 4 + 8);
3226                         }
3227 #else
3228                         g_assert_not_reached ();
3229 #endif
3230                 }
3231         }
3232
3233         /* Unbox trampolines */
3234
3235         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
3236                 MonoMethod *method;
3237                 guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
3238                 MonoCompile *cfg;
3239                 char *call_target;
3240
3241                 method = mono_get_method (acfg->image, token, NULL);
3242
3243                 cfg = g_hash_table_lookup (acfg->method_to_cfg, method);
3244                 if (!cfg || !cfg->orig_method->klass->valuetype || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL))
3245                         continue;
3246
3247                 symbol = g_strdup_printf ("unbox_trampoline_%d", i);
3248
3249                 emit_section_change (acfg, ".text", 0);
3250                 emit_global (acfg, symbol, TRUE);
3251                 emit_label (acfg, symbol);
3252
3253                 call_target = g_strdup_printf (".Lm_%x", get_method_index (acfg, cfg->orig_method));
3254
3255 #if defined(__x86_64__)
3256                 {
3257                         guint8 buf [32];
3258                         int this_reg;
3259
3260                         this_reg = mono_arch_get_this_arg_reg (mono_method_signature (cfg->orig_method), cfg->generic_sharing_context, NULL);
3261                         code = buf;
3262                         amd64_alu_reg_imm (code, X86_ADD, this_reg, sizeof (MonoObject));
3263
3264                         emit_bytes (acfg, buf, code - buf);
3265                         /* jump <method> */
3266                         emit_byte (acfg, '\xe9');
3267                         emit_symbol_diff (acfg, call_target, ".", -4);
3268                 }
3269 #elif defined(__arm__)
3270                 {
3271                         guint8 buf [128];
3272                         int this_pos = 0;
3273
3274                         code = buf;
3275
3276                         if (MONO_TYPE_ISSTRUCT (mono_method_signature (cfg->orig_method)->ret))
3277                                 this_pos = 1;
3278
3279                         ARM_ADD_REG_IMM8 (code, this_pos, this_pos, sizeof (MonoObject));
3280
3281                         emit_bytes (acfg, buf, code - buf);
3282                         /* jump to method */
3283 #if defined(USE_BIN_WRITER)
3284                         /* FIXME: */
3285                         g_assert_not_reached ();
3286 #endif
3287                         fprintf (acfg->fp, "\n\tb %s\n", call_target);
3288                 }
3289 #else
3290                 g_assert_not_reached ();
3291 #endif
3292         }
3293
3294         symbol = g_strdup_printf ("trampolines_info");
3295
3296         emit_section_change (acfg, ".text", 0);
3297         emit_global (acfg, symbol, TRUE);
3298         emit_alignment (acfg, PAGESIZE);
3299         emit_label (acfg, symbol);
3300
3301         emit_int32 (acfg, acfg->num_aot_trampolines);
3302         emit_int32 (acfg, acfg->got_offset);
3303 }
3304
3305 static gboolean
3306 str_begins_with (const char *str1, const char *str2)
3307 {
3308         int len = strlen (str2);
3309         return strncmp (str1, str2, len) == 0;
3310 }
3311
3312 static void
3313 mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
3314 {
3315         gchar **args, **ptr;
3316
3317         memset (opts, 0, sizeof (*opts));
3318
3319         args = g_strsplit (aot_options ? aot_options : "", ",", -1);
3320         for (ptr = args; ptr && *ptr; ptr ++) {
3321                 const char *arg = *ptr;
3322
3323                 if (str_begins_with (arg, "outfile=")) {
3324                         opts->outfile = g_strdup (arg + strlen ("outfile="));
3325                 } else if (str_begins_with (arg, "save-temps")) {
3326                         opts->save_temps = TRUE;
3327                 } else if (str_begins_with (arg, "keep-temps")) {
3328                         opts->save_temps = TRUE;
3329                 } else if (str_begins_with (arg, "write-symbols")) {
3330                         opts->write_symbols = TRUE;
3331                 } else if (str_begins_with (arg, "metadata-only")) {
3332                         opts->metadata_only = TRUE;
3333                 } else if (str_begins_with (arg, "bind-to-runtime-version")) {
3334                         opts->bind_to_runtime_version = TRUE;
3335                 } else if (str_begins_with (arg, "full")) {
3336                         opts->full_aot = TRUE;
3337                         /*
3338                          * The no-dlsym option is only useful on the iphone, and even there,
3339                          * do to other limitations of the dynamic linker, it doesn't seem to
3340                          * work. So disable it for now so we don't have to support it.
3341                          */
3342                         /*
3343                 } else if (str_begins_with (arg, "no-dlsym")) {
3344                         opts->no_dlsym = TRUE;
3345                         */
3346                 } else if (str_begins_with (arg, "static")) {
3347                         opts->static_link = TRUE;
3348                         opts->no_dlsym = TRUE;
3349                 } else if (str_begins_with (arg, "asmonly")) {
3350                         opts->asm_only = TRUE;
3351                 } else {
3352                         fprintf (stderr, "AOT : Unknown argument '%s'.\n", arg);
3353                         exit (1);
3354                 }
3355         }
3356
3357         g_strfreev (args);
3358 }
3359
3360 static void
3361 add_token_info_hash (gpointer key, gpointer value, gpointer user_data)
3362 {
3363         MonoMethod *method = (MonoMethod*)key;
3364         MonoJumpInfoToken *ji = (MonoJumpInfoToken*)value;
3365         MonoJumpInfoToken *new_ji = g_new0 (MonoJumpInfoToken, 1);
3366         MonoAotCompile *acfg = user_data;
3367
3368         new_ji->image = ji->image;
3369         new_ji->token = ji->token;
3370         g_hash_table_insert (acfg->token_info_hash, method, new_ji);
3371 }
3372
3373 static void
3374 compile_method (MonoAotCompile *acfg, MonoMethod *method)
3375 {
3376         MonoCompile *cfg;
3377         MonoJumpInfo *patch_info;
3378         gboolean skip;
3379         int index;
3380         MonoMethod *wrapped;
3381
3382         if (acfg->aot_opts.metadata_only)
3383                 return;
3384
3385         index = get_method_index (acfg, method);
3386
3387         /* fixme: maybe we can also precompile wrapper methods */
3388         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
3389                 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
3390                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT)) {
3391                 //printf ("Skip (impossible): %s\n", mono_method_full_name (method, TRUE));
3392                 return;
3393         }
3394
3395         if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
3396                 return;
3397
3398         wrapped = mono_marshal_method_from_wrapper (method);
3399         if (wrapped && (wrapped->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && wrapped->is_generic)
3400                 // FIXME: The wrapper should be generic too, but it is not
3401                 return;
3402
3403         acfg->stats.mcount++;
3404
3405         if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) {
3406                 /* 
3407                  * FIXME: Enabling this causes virtual-sync.exe to fail, since the trampoline
3408                  * code can't determine that it needs to insert a sync wrapper in the AOT case.
3409                  */
3410                 return;
3411         }
3412
3413         /*
3414          * FIXME: This does not work currently, because 
3415          * mono_metadata_generic_context_hash () uses inst->id which is different at
3416          * AOT time and runtime, causing the IMT slot of methods to change.
3417          */
3418 #if 1
3419         if (method->is_generic || method->klass->generic_container) {
3420                 acfg->stats.genericcount ++;
3421                 return;
3422         }
3423 #endif
3424
3425         if (acfg->aot_opts.full_aot)
3426                 mono_use_imt = FALSE;
3427
3428         /*
3429          * Since these methods are the only ones which are compiled with
3430          * AOT support, and they are not used by runtime startup/shutdown code,
3431          * the runtime will not see AOT methods during AOT compilation,so it
3432          * does not need to support them by creating a fake GOT etc.
3433          */
3434         cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), FALSE, TRUE, 0);
3435         if (cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) {
3436                 //printf ("F: %s\n", mono_method_full_name (method, TRUE));
3437                 acfg->stats.genericcount ++;
3438                 return;
3439         }
3440         if (cfg->exception_type != MONO_EXCEPTION_NONE) {
3441                 /* Let the exception happen at runtime */
3442                 return;
3443         }
3444
3445         if (cfg->disable_aot) {
3446                 //printf ("Skip (other): %s\n", mono_method_full_name (method, TRUE));
3447                 acfg->stats.ocount++;
3448                 mono_destroy_compile (cfg);
3449                 return;
3450         }
3451
3452         /* Nullify patches which need no aot processing */
3453         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
3454                 switch (patch_info->type) {
3455                 case MONO_PATCH_INFO_LABEL:
3456                 case MONO_PATCH_INFO_BB:
3457                         patch_info->type = MONO_PATCH_INFO_NONE;
3458                         break;
3459                 default:
3460                         break;
3461                 }
3462         }
3463
3464         /* Collect method->token associations from the cfg */
3465         g_hash_table_foreach (cfg->token_info_hash, add_token_info_hash, acfg);
3466
3467         /*
3468          * Check for absolute addresses.
3469          */
3470         skip = FALSE;
3471         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
3472                 switch (patch_info->type) {
3473                 case MONO_PATCH_INFO_ABS:
3474                         /* unable to handle this */
3475                         //printf ("Skip (abs addr):   %s %d\n", mono_method_full_name (method, TRUE), patch_info->type);
3476                         skip = TRUE;    
3477                         break;
3478                 default:
3479                         break;
3480                 }
3481         }
3482
3483         if (skip) {
3484                 acfg->stats.abscount++;
3485                 mono_destroy_compile (cfg);
3486                 return;
3487         }
3488
3489         /*
3490          * Check for wrapper methods we can't encode.
3491          */
3492         skip = FALSE;
3493         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
3494                 if ((patch_info->type == MONO_PATCH_INFO_METHODCONST) || (patch_info->type == MONO_PATCH_INFO_METHOD)) {
3495                         switch (patch_info->data.method->wrapper_type) {
3496                         case MONO_WRAPPER_NONE:
3497                         case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
3498                         case MONO_WRAPPER_XDOMAIN_INVOKE:
3499                         case MONO_WRAPPER_STFLD:
3500                         case MONO_WRAPPER_LDFLD:
3501                         case MONO_WRAPPER_LDFLDA:
3502                         case MONO_WRAPPER_LDFLD_REMOTE:
3503                         case MONO_WRAPPER_STFLD_REMOTE:
3504                         case MONO_WRAPPER_STELEMREF:
3505                         case MONO_WRAPPER_ISINST:
3506                         case MONO_WRAPPER_PROXY_ISINST:
3507                         case MONO_WRAPPER_ALLOC:
3508                         case MONO_WRAPPER_REMOTING_INVOKE:
3509                         case MONO_WRAPPER_STATIC_RGCTX_INVOKE:
3510                                 break;
3511                         default:
3512                                 /* unable to handle this */
3513                                 //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));
3514                                 skip = TRUE;
3515                                 break;
3516                         }
3517                 } else if (patch_info->type == MONO_PATCH_INFO_RGCTX_FETCH) {
3518                         MonoJumpInfo *child = patch_info->data.rgctx_entry->data;
3519
3520                         if (child->type == MONO_PATCH_INFO_METHODCONST) {
3521                                 switch (child->data.method->wrapper_type) {
3522                                 case MONO_WRAPPER_NONE:
3523                                 case MONO_WRAPPER_STATIC_RGCTX_INVOKE:
3524                                         break;
3525                                 default:
3526                                         skip = TRUE;
3527                                 }
3528                         }
3529                 }
3530         }
3531
3532         if (skip) {
3533                 acfg->stats.wrappercount++;
3534                 mono_destroy_compile (cfg);
3535                 return;
3536         }
3537
3538         /*
3539          * Check for methods/klasses we can't encode.
3540          */
3541         skip = FALSE;
3542         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
3543                 switch (patch_info->type) {
3544                 case MONO_PATCH_INFO_METHOD:
3545                 case MONO_PATCH_INFO_METHODCONST:
3546                         if (patch_info->data.method->wrapper_type)
3547                                 break;
3548                         if (!patch_info->data.method->token) {
3549                                 /* The method is part of a constructed type like Int[,].Set (). */
3550                                 if (!g_hash_table_lookup (acfg->token_info_hash, patch_info->data.method))
3551                                         skip = TRUE;
3552                         }
3553                         if (patch_info->data.method->is_inflated && !g_hash_table_lookup (acfg->token_info_hash, patch_info->data.method)) {
3554                                 /* 
3555                                  * encode_method_ref () can handle this method if it is not generic
3556                                  * and its class can be encoded.
3557                                  */
3558                                 if (!g_hash_table_lookup (acfg->token_info_hash, patch_info->data.method->klass) || mono_method_get_context (patch_info->data.method)->method_inst) {
3559                                         /* FIXME: Can't encode these */
3560                                         //printf ("Skip (can't encode):   %s %d -> %s\n", mono_method_full_name (method, TRUE), patch_info->type, mono_method_full_name (patch_info->data.method, TRUE));
3561                                         skip = TRUE;
3562                                 }
3563                         }
3564                         break;
3565                 case MONO_PATCH_INFO_VTABLE:
3566                 case MONO_PATCH_INFO_CLASS_INIT:
3567                 case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
3568                 case MONO_PATCH_INFO_CLASS:
3569                 case MONO_PATCH_INFO_IID:
3570                 case MONO_PATCH_INFO_ADJUSTED_IID:
3571                         if (!patch_info->data.klass->type_token)
3572                                 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))
3573                                         skip = TRUE;
3574                         break;
3575                 default:
3576                         break;
3577                 }
3578         }
3579
3580         if (skip) {
3581                 acfg->stats.ocount++;
3582                 mono_destroy_compile (cfg);
3583                 return;
3584         }
3585
3586         /* Determine whenever the method has GOT slots */
3587         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
3588                 switch (patch_info->type) {
3589                 case MONO_PATCH_INFO_GOT_OFFSET:
3590                 case MONO_PATCH_INFO_NONE:
3591                         break;
3592                 case MONO_PATCH_INFO_IMAGE:
3593                         /* The assembly is stored in GOT slot 0 */
3594                         if (patch_info->data.image != acfg->image)
3595                                 cfg->has_got_slots = TRUE;
3596                         break;
3597                 default:
3598                         if (!is_plt_patch (patch_info))
3599                                 cfg->has_got_slots = TRUE;
3600                         break;
3601                 }
3602         }
3603
3604         if (!cfg->has_got_slots)
3605                 acfg->stats.methods_without_got_slots ++;
3606
3607         /* Make a copy of the patch info which is in the mempool */
3608         {
3609                 MonoJumpInfo *patches = NULL, *patches_end = NULL;
3610
3611                 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
3612                         MonoJumpInfo *new_patch_info = mono_patch_info_dup_mp (acfg->mempool, patch_info);
3613
3614                         if (!patches)
3615                                 patches = new_patch_info;
3616                         else
3617                                 patches_end->next = new_patch_info;
3618                         patches_end = new_patch_info;
3619                 }
3620                 cfg->patch_info = patches;
3621         }
3622
3623         /* Free some fields used by cfg to conserve memory */
3624         mono_mempool_destroy (cfg->mempool);
3625         cfg->mempool = NULL;
3626         g_free (cfg->varinfo);
3627         cfg->varinfo = NULL;
3628         g_free (cfg->vars);
3629         cfg->vars = NULL;
3630         if (cfg->rs) {
3631                 mono_regstate_free (cfg->rs);
3632                 cfg->rs = NULL;
3633         }
3634
3635         //printf ("Compile:           %s\n", mono_method_full_name (method, TRUE));
3636
3637         acfg->cfgs [index] = cfg;
3638
3639         g_hash_table_insert (acfg->method_to_cfg, cfg->orig_method, cfg);
3640
3641         acfg->stats.ccount++;
3642 }
3643
3644 static void
3645 load_profile_files (MonoAotCompile *acfg)
3646 {
3647         FILE *infile;
3648         char *tmp;
3649         int file_index, res, method_index, i;
3650         char ver [256];
3651         guint32 token;
3652         GList *unordered;
3653
3654         file_index = 0;
3655         while (TRUE) {
3656                 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);
3657
3658                 if (!g_file_test (tmp, G_FILE_TEST_IS_REGULAR)) {
3659                         g_free (tmp);
3660                         break;
3661                 }
3662
3663                 infile = fopen (tmp, "r");
3664                 g_assert (infile);
3665
3666                 printf ("Using profile data file '%s'\n", tmp);
3667                 g_free (tmp);
3668
3669                 file_index ++;
3670
3671                 res = fscanf (infile, "%32s\n", ver);
3672                 if ((res != 1) || strcmp (ver, "#VER:1") != 0) {
3673                         printf ("Profile file has wrong version or invalid.\n");
3674                         fclose (infile);
3675                         continue;
3676                 }
3677
3678                 while (TRUE) {
3679                         res = fscanf (infile, "%d\n", &token);
3680                         if (res < 1)
3681                                 break;
3682
3683                         method_index = mono_metadata_token_index (token) - 1;
3684
3685                         if (!g_list_find (acfg->method_order, GUINT_TO_POINTER (method_index)))
3686                                 acfg->method_order = g_list_append (acfg->method_order, GUINT_TO_POINTER (method_index));
3687                 }
3688                 fclose (infile);
3689         }
3690
3691         /* Add missing methods */
3692         unordered = NULL;
3693         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
3694                 if (!g_list_find (acfg->method_order, GUINT_TO_POINTER (i)))
3695                         unordered = g_list_prepend (unordered, GUINT_TO_POINTER (i));
3696         }
3697         unordered = g_list_reverse (unordered);
3698         if (acfg->method_order)
3699                 g_list_last (acfg->method_order)->next = unordered;
3700         else
3701                 acfg->method_order = unordered;
3702 }
3703
3704 /**
3705  * alloc_got_slots:
3706  *
3707  *  Collect all patches which have shared GOT entries and alloc entries for them. The
3708  * rest will get entries allocated during emit_code ().
3709  */
3710 static void
3711 alloc_got_slots (MonoAotCompile *acfg)
3712 {
3713         int i;
3714         GList *l;
3715         MonoJumpInfo *ji;
3716
3717         /* Slot 0 is reserved for the address of the current assembly */
3718         ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
3719         ji->type = MONO_PATCH_INFO_IMAGE;
3720         ji->data.image = acfg->image;
3721
3722         get_shared_got_offset (acfg, ji);
3723
3724         for (l = acfg->method_order; l != NULL; l = l->next) {
3725                 i = GPOINTER_TO_UINT (l->data);
3726
3727                 if (acfg->cfgs [i]) {
3728                         MonoCompile *cfg = acfg->cfgs [i];
3729
3730                         for (ji = cfg->patch_info; ji; ji = ji->next) {
3731                                 if (is_shared_got_patch (ji))
3732                                         get_shared_got_offset (acfg, ji);
3733                         }
3734                 }
3735         }
3736 }
3737
3738 static void
3739 emit_code (MonoAotCompile *acfg)
3740 {
3741         int i;
3742         char *symbol;
3743         GList *l;
3744
3745         symbol = g_strdup_printf ("methods");
3746         emit_section_change (acfg, ".text", 0);
3747         emit_global (acfg, symbol, TRUE);
3748         emit_alignment (acfg, 8);
3749         emit_label (acfg, symbol);
3750         g_free (symbol);
3751
3752         for (l = acfg->method_order; l != NULL; l = l->next) {
3753                 i = GPOINTER_TO_UINT (l->data);
3754
3755                 if (acfg->cfgs [i])
3756                         emit_method_code (acfg, acfg->cfgs [i]);
3757         }
3758
3759         symbol = g_strdup_printf ("methods_end");
3760         emit_section_change (acfg, ".text", 0);
3761         emit_global (acfg, symbol, FALSE);
3762         emit_alignment (acfg, 8);
3763         emit_label (acfg, symbol);
3764         g_free (symbol);
3765
3766         symbol = g_strdup_printf ("method_offsets");
3767         emit_section_change (acfg, ".text", 1);
3768         emit_global (acfg, symbol, FALSE);
3769         emit_alignment (acfg, 8);
3770         emit_label (acfg, symbol);
3771         g_free (symbol);
3772
3773         for (i = 0; i < acfg->nmethods; ++i) {
3774                 if (acfg->cfgs [i]) {
3775                         symbol = g_strdup_printf (".Lm_%x", i);
3776                         emit_symbol_diff (acfg, symbol, "methods", 0);
3777                         g_free (symbol);
3778                 } else {
3779                         emit_int32 (acfg, 0xffffffff);
3780                 }
3781         }
3782         emit_line (acfg);
3783 }
3784
3785 static void
3786 emit_info (MonoAotCompile *acfg)
3787 {
3788         int i;
3789         char *symbol;
3790         GList *l;
3791
3792         /* Emit method info */
3793         symbol = g_strdup_printf ("method_info");
3794         emit_section_change (acfg, ".text", 1);
3795         emit_global (acfg, symbol, FALSE);
3796         emit_alignment (acfg, 8);
3797         emit_label (acfg, symbol);
3798         g_free (symbol);
3799
3800         /* To reduce size of generated assembly code */
3801         symbol = g_strdup_printf ("mi");
3802         emit_label (acfg, symbol);
3803         g_free (symbol);
3804
3805         for (l = acfg->method_order; l != NULL; l = l->next) {
3806                 i = GPOINTER_TO_UINT (l->data);
3807
3808                 if (acfg->cfgs [i])
3809                         emit_method_info (acfg, acfg->cfgs [i]);
3810         }
3811
3812         symbol = g_strdup_printf ("method_info_offsets");
3813         emit_section_change (acfg, ".text", 1);
3814         emit_global (acfg, symbol, FALSE);
3815         emit_alignment (acfg, 8);
3816         emit_label (acfg, symbol);
3817         g_free (symbol);
3818
3819         for (i = 0; i < acfg->nmethods; ++i) {
3820                 if (acfg->cfgs [i]) {
3821                         symbol = g_strdup_printf (".Lm_%x_p", i);
3822                         emit_symbol_diff (acfg, symbol, "mi", 0);
3823                         g_free (symbol);
3824                 } else {
3825                         emit_int32 (acfg, 0);
3826                 }
3827         }
3828         emit_line (acfg);
3829 }
3830
3831 static void
3832 emit_wrapper_info (MonoAotCompile *acfg)
3833 {
3834         int i, index;
3835         char *symbol;
3836         char *name;
3837
3838         /* Emit method info */
3839         symbol = g_strdup_printf ("wrapper_info");
3840         emit_section_change (acfg, ".text", 1);
3841         emit_global (acfg, symbol, FALSE);
3842         emit_alignment (acfg, 8);
3843         emit_label (acfg, symbol);
3844         g_free (symbol);
3845
3846         if (!acfg->aot_opts.full_aot)
3847                 return;
3848
3849         for (i = 0; i < acfg->nmethods; ++i) {
3850                 MonoCompile *cfg = acfg->cfgs [i];
3851
3852                 if (!cfg || !cfg->orig_method->wrapper_type)
3853                         continue;
3854
3855                 index = get_method_index (acfg, cfg->orig_method);
3856
3857                 // FIXME: Optimize disk usage and lookup speed
3858                 name = mono_method_full_name (cfg->orig_method, TRUE);
3859                 emit_string (acfg, name);
3860                 emit_alignment (acfg, 4);
3861                 emit_int32 (acfg, index);
3862         }
3863
3864         emit_byte (acfg, 0);
3865
3866         emit_line (acfg);
3867 }       
3868
3869 static void
3870 emit_method_order (MonoAotCompile *acfg)
3871 {
3872         int i, index, len;
3873         char *symbol;
3874         GList *l;
3875
3876         symbol = g_strdup_printf ("method_order");
3877         emit_section_change (acfg, ".text", 1);
3878         emit_global (acfg, symbol, FALSE);
3879         emit_alignment (acfg, 8);
3880         emit_label (acfg, symbol);
3881         g_free (symbol);
3882
3883         /* First emit an index table */
3884         index = 0;
3885         len = 0;
3886         for (l = acfg->method_order; l != NULL; l = l->next) {
3887                 i = GPOINTER_TO_UINT (l->data);
3888
3889                 if (acfg->cfgs [i]) {
3890                         if ((index % 1024) == 0) {
3891                                 emit_int32 (acfg, i);
3892                         }
3893
3894                         index ++;
3895                 }
3896
3897                 len ++;
3898         }
3899         emit_int32 (acfg, 0xffffff);
3900
3901         /* Then emit the whole method order */
3902         for (l = acfg->method_order; l != NULL; l = l->next) {
3903                 i = GPOINTER_TO_UINT (l->data);
3904
3905                 if (acfg->cfgs [i]) {
3906                         emit_int32 (acfg, i);
3907                 }
3908         }       
3909         emit_line (acfg);
3910
3911         symbol = g_strdup_printf ("method_order_end");
3912         emit_section_change (acfg, ".text", 1);
3913         emit_global (acfg, symbol, FALSE);
3914         emit_label (acfg, symbol);
3915         g_free (symbol);
3916 }
3917
3918 static void
3919 emit_exception_info (MonoAotCompile *acfg)
3920 {
3921         int i;
3922         char *symbol;
3923
3924         symbol = g_strdup_printf ("ex_info");
3925         emit_section_change (acfg, ".text", 1);
3926         emit_global (acfg, symbol, FALSE);
3927         emit_alignment (acfg, 8);
3928         emit_label (acfg, symbol);
3929         g_free (symbol);
3930
3931         /* To reduce size of generated assembly */
3932         symbol = g_strdup_printf ("ex");
3933         emit_label (acfg, symbol);
3934         g_free (symbol);
3935
3936         for (i = 0; i < acfg->nmethods; ++i) {
3937                 if (acfg->cfgs [i])
3938                         emit_exception_debug_info (acfg, acfg->cfgs [i]);
3939         }
3940
3941         symbol = g_strdup_printf ("ex_info_offsets");
3942         emit_section_change (acfg, ".text", 1);
3943         emit_global (acfg, symbol, FALSE);
3944         emit_alignment (acfg, 8);
3945         emit_label (acfg, symbol);
3946         g_free (symbol);
3947
3948         for (i = 0; i < acfg->nmethods; ++i) {
3949                 if (acfg->cfgs [i]) {
3950                         symbol = g_strdup_printf (".Le_%x_p", i);
3951                         emit_symbol_diff (acfg, symbol, "ex", 0);
3952                         g_free (symbol);
3953                 } else {
3954                         emit_int32 (acfg, 0);
3955                 }
3956         }
3957         emit_line (acfg);
3958 }
3959
3960 static void
3961 emit_class_info (MonoAotCompile *acfg)
3962 {
3963         int i;
3964         char *symbol;
3965
3966         symbol = g_strdup_printf ("class_info");
3967         emit_section_change (acfg, ".text", 1);
3968         emit_global (acfg, symbol, FALSE);
3969         emit_alignment (acfg, 8);
3970         emit_label (acfg, symbol);
3971         g_free (symbol);
3972
3973         for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i)
3974                 emit_klass_info (acfg, MONO_TOKEN_TYPE_DEF | (i + 1));
3975
3976         symbol = g_strdup_printf ("class_info_offsets");
3977         emit_section_change (acfg, ".text", 1);
3978         emit_global (acfg, symbol, FALSE);
3979         emit_alignment (acfg, 8);
3980         emit_label (acfg, symbol);
3981         g_free (symbol);
3982
3983         for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
3984                 symbol = g_strdup_printf (".LK_I_%x", i);
3985                 emit_symbol_diff (acfg, symbol, "class_info", 0);
3986                 g_free (symbol);
3987         }
3988         emit_line (acfg);
3989 }
3990
3991 typedef struct ClassNameTableEntry {
3992         guint32 token, index;
3993         struct ClassNameTableEntry *next;
3994 } ClassNameTableEntry;
3995
3996 static void
3997 emit_class_name_table (MonoAotCompile *acfg)
3998 {
3999         int i, table_size;
4000         guint32 token, hash;
4001         MonoClass *klass;
4002         GPtrArray *table;
4003         char *full_name;
4004         char *symbol;
4005         ClassNameTableEntry *entry, *new_entry;
4006
4007         /*
4008          * Construct a chained hash table for mapping class names to typedef tokens.
4009          */
4010         table_size = g_spaced_primes_closest ((int)(acfg->image->tables [MONO_TABLE_TYPEDEF].rows * 1.5));
4011         table = g_ptr_array_sized_new (table_size);
4012         for (i = 0; i < table_size; ++i)
4013                 g_ptr_array_add (table, NULL);
4014         for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
4015                 token = MONO_TOKEN_TYPE_DEF | (i + 1);
4016                 klass = mono_class_get (acfg->image, token);
4017                 full_name = mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_FULL_NAME);
4018                 hash = g_str_hash (full_name) % table_size;
4019                 g_free (full_name);
4020
4021                 /* FIXME: Allocate from the mempool */
4022                 new_entry = g_new0 (ClassNameTableEntry, 1);
4023                 new_entry->token = token;
4024
4025                 entry = g_ptr_array_index (table, hash);
4026                 if (entry == NULL) {
4027                         new_entry->index = hash;
4028                         g_ptr_array_index (table, hash) = new_entry;
4029                 } else {
4030                         while (entry->next)
4031                                 entry = entry->next;
4032                         
4033                         entry->next = new_entry;
4034                         new_entry->index = table->len;
4035                         g_ptr_array_add (table, new_entry);
4036                 }
4037         }
4038
4039         /* Emit the table */
4040         symbol = g_strdup_printf ("class_name_table");
4041         emit_section_change (acfg, ".text", 0);
4042         emit_global (acfg, symbol, FALSE);
4043         emit_alignment (acfg, 8);
4044         emit_label (acfg, symbol);
4045         g_free (symbol);
4046
4047         /* FIXME: Optimize memory usage */
4048         g_assert (table_size < 65000);
4049         emit_int16 (acfg, table_size);
4050         g_assert (table->len < 65000);
4051         for (i = 0; i < table->len; ++i) {
4052                 ClassNameTableEntry *entry = g_ptr_array_index (table, i);
4053
4054                 if (entry == NULL) {
4055                         emit_int16 (acfg, 0);
4056                         emit_int16 (acfg, 0);
4057                 } else {
4058                         emit_int16 (acfg, mono_metadata_token_index (entry->token));
4059                         if (entry->next)
4060                                 emit_int16 (acfg, entry->next->index);
4061                         else
4062                                 emit_int16 (acfg, 0);
4063                 }
4064         }
4065 }
4066
4067 static void
4068 emit_image_table (MonoAotCompile *acfg)
4069 {
4070         int i;
4071         char *symbol;
4072
4073         /*
4074          * The image table is small but referenced in a lot of places.
4075          * So we emit it at once, and reference its elements by an index.
4076          */
4077
4078         symbol = g_strdup_printf ("mono_image_table");
4079         emit_section_change (acfg, ".text", 1);
4080         emit_global (acfg, symbol, FALSE);
4081         emit_alignment (acfg, 8);
4082         emit_label (acfg, symbol);
4083         g_free (symbol);
4084
4085         emit_int32 (acfg, acfg->image_table->len);
4086         for (i = 0; i < acfg->image_table->len; i++) {
4087                 MonoImage *image = (MonoImage*)g_ptr_array_index (acfg->image_table, i);
4088                 MonoAssemblyName *aname = &image->assembly->aname;
4089
4090                 /* FIXME: Support multi-module assemblies */
4091                 g_assert (image->assembly->image == image);
4092
4093                 emit_string (acfg, image->assembly_name);
4094                 emit_string (acfg, image->guid);
4095                 emit_string (acfg, aname->culture ? aname->culture : "");
4096                 emit_string (acfg, (const char*)aname->public_key_token);
4097
4098                 emit_alignment (acfg, 8);
4099                 emit_int32 (acfg, aname->flags);
4100                 emit_int32 (acfg, aname->major);
4101                 emit_int32 (acfg, aname->minor);
4102                 emit_int32 (acfg, aname->build);
4103                 emit_int32 (acfg, aname->revision);
4104         }
4105 }
4106
4107 static void
4108 emit_got_info (MonoAotCompile *acfg)
4109 {
4110         char *symbol;
4111         int i, buf_size;
4112         guint8 *p, *buf;
4113         guint32 *got_info_offsets;
4114
4115         /**
4116          * FIXME: 
4117          * - optimize offsets table.
4118          * - reduce number of exported symbols.
4119          * - emit info for a klass only once.
4120          * - determine when a method uses a GOT slot which is guaranteed to be already 
4121          *   initialized.
4122          * - clean up and document the code.
4123          * - use String.Empty in class libs.
4124          */
4125
4126         /* Encode info required to decode shared GOT entries */
4127         buf_size = acfg->shared_patches->len * 64;
4128         p = buf = mono_mempool_alloc (acfg->mempool, buf_size);
4129         got_info_offsets = mono_mempool_alloc (acfg->mempool, acfg->shared_patches->len * sizeof (guint32));
4130         for (i = 0; i < acfg->shared_patches->len; ++i) {
4131                 MonoJumpInfo *ji = g_ptr_array_index (acfg->shared_patches, i);
4132
4133                 /* No need to encode the patch type */
4134                 got_info_offsets [i] = p - buf;
4135                 encode_patch (acfg, ji, p, &p);
4136         }
4137
4138         g_assert (p - buf <= buf_size);
4139
4140         acfg->stats.got_info_size = p - buf;
4141
4142         /* Emit got_info table */
4143         symbol = g_strdup_printf ("got_info");
4144         emit_section_change (acfg, ".text", 1);
4145         emit_global (acfg, symbol, FALSE);
4146         emit_alignment (acfg, 8);
4147         emit_label (acfg, symbol);
4148         g_free (symbol);
4149
4150         emit_bytes (acfg, buf, p - buf);
4151
4152         /* Emit got_info_offsets table */
4153         symbol = g_strdup_printf ("got_info_offsets");
4154         emit_section_change (acfg, ".text", 1);
4155         emit_global (acfg, symbol, FALSE);
4156         emit_alignment (acfg, 8);
4157         emit_label (acfg, symbol);
4158         g_free (symbol);
4159
4160         for (i = 0; i < acfg->shared_patches->len; ++i)
4161                 emit_int32 (acfg, got_info_offsets [i]);
4162
4163         acfg->stats.got_info_offsets_size = acfg->shared_patches->len * 4;
4164 }
4165
4166 static void
4167 emit_got (MonoAotCompile *acfg)
4168 {
4169         char *symbol;
4170
4171         /* Don't make GOT global so accesses to it don't need relocations */
4172         symbol = g_strdup_printf ("got");
4173         emit_section_change (acfg, ".bss", 1);
4174         emit_alignment (acfg, 8);
4175         emit_label (acfg, symbol);
4176         if ((acfg->got_offset + acfg->num_trampoline_got_entries) > 0)
4177                 emit_zero_bytes (acfg, (int)((acfg->got_offset + acfg->num_trampoline_got_entries) * sizeof (gpointer)));
4178         g_free (symbol);
4179
4180         symbol = g_strdup_printf ("got_addr");
4181         emit_section_change (acfg, ".data", 1);
4182         emit_global (acfg, symbol, FALSE);
4183         emit_alignment (acfg, 8);
4184         emit_label (acfg, symbol);
4185         emit_pointer (acfg, "got");
4186         g_free (symbol);
4187
4188         symbol = g_strdup_printf ("got_size");
4189         emit_section_change (acfg, ".data", 1);
4190         emit_global (acfg, symbol, FALSE);
4191         emit_alignment (acfg, 8);
4192         emit_label (acfg, symbol);
4193         emit_int32 (acfg, (int)(acfg->got_offset * sizeof (gpointer)));
4194         g_free (symbol);
4195 }
4196
4197 static void
4198 emit_globals (MonoAotCompile *acfg)
4199 {
4200         char *opts_str;
4201
4202         emit_string_symbol (acfg, "mono_assembly_guid" , acfg->image->guid);
4203
4204         emit_string_symbol (acfg, "mono_aot_version", MONO_AOT_FILE_VERSION);
4205
4206         opts_str = g_strdup_printf ("%d", acfg->opts);
4207         emit_string_symbol (acfg, "mono_aot_opt_flags", opts_str);
4208         g_free (opts_str);
4209
4210         emit_string_symbol (acfg, "mono_aot_full_aot", acfg->aot_opts.full_aot ? "TRUE" : "FALSE");
4211
4212         if (acfg->aot_opts.bind_to_runtime_version)
4213                 emit_string_symbol (acfg, "mono_runtime_version", FULL_VERSION);
4214         else
4215                 emit_string_symbol (acfg, "mono_runtime_version", "");
4216
4217         /*
4218          * Some platforms like the iphone have no working dlsym (). To work around this,
4219          * we create an ELF ctor function which will be invoked by dlopen, and which
4220          * will call a function in the AOT loader to register the symbols used by the
4221          * image.
4222          * When static linking, we emit a global which will point to the symbol table.
4223          */
4224         if (acfg->aot_opts.no_dlsym) {
4225                 int i;
4226                 char *symbol;
4227
4228                 if (acfg->aot_opts.static_link)
4229                         /* Emit a string holding the assembly name */
4230                         emit_string_symbol (acfg, "mono_aot_assembly_name", acfg->image->assembly->aname.name);
4231
4232                 /* Emit the names */
4233                 for (i = 0; i < acfg->globals->len; ++i) {
4234                         char *name = g_ptr_array_index (acfg->globals, i);
4235
4236                         symbol = g_strdup_printf ("name_%d", i);
4237                         emit_section_change (acfg, ".text", 1);
4238                         emit_label (acfg, symbol);
4239                         emit_string (acfg, name);
4240                         g_free (symbol);
4241                 }
4242
4243                 /* Emit the globals table */
4244                 symbol = g_strdup_printf ("globals");
4245                 emit_section_change (acfg, ".data", 0);
4246                 /* This is not a global, since it is accessed by the init function */
4247                 emit_alignment (acfg, 8);
4248                 emit_label (acfg, symbol);
4249
4250                 for (i = 0; i < acfg->globals->len; ++i) {
4251                         char *name = g_ptr_array_index (acfg->globals, i);
4252
4253                         symbol = g_strdup_printf ("name_%d", i);
4254                         emit_pointer (acfg, symbol);
4255                         g_free (symbol);
4256
4257                         symbol = g_strdup_printf ("%s", name);
4258                         emit_pointer (acfg, symbol);
4259                         g_free (symbol);
4260                 }
4261                 /* Null terminate the table */
4262                 emit_pointer (acfg, NULL);
4263                 emit_pointer (acfg, NULL);
4264
4265                 if (acfg->aot_opts.static_link) {
4266                         /* 
4267                          * Emit a global symbol which can be passed by an embedding app to
4268                          * mono_aot_register_module ().
4269                          */
4270 #if defined(__MACH__)
4271                         symbol = g_strdup_printf ("_mono_aot_module_%s_info", acfg->image->assembly->aname.name);
4272 #else
4273                         symbol = g_strdup_printf ("mono_aot_module_%s_info", acfg->image->assembly->aname.name);
4274 #endif
4275                         acfg->static_linking_symbol = g_strdup (symbol);
4276                         emit_global_inner (acfg, symbol, FALSE);
4277                         emit_alignment (acfg, 8);
4278                         emit_label (acfg, symbol);
4279                         emit_pointer (acfg, "globals");
4280                 } else {
4281                         symbol = g_strdup_printf ("init_%s", acfg->image->assembly->aname.name);
4282                         emit_section_change (acfg, ".text", 1);
4283                         emit_alignment (acfg, 8);
4284                         emit_label (acfg, symbol);
4285 #ifdef USE_BIN_WRITER
4286                         g_assert_not_reached ();
4287 #else
4288 #ifdef __x86_64__
4289                         fprintf (acfg->fp, "leaq globals(%%rip), %%rdi\n");
4290                         fprintf (acfg->fp, "call mono_aot_register_globals@PLT\n");
4291                         fprintf (acfg->fp, "ret\n");
4292                         fprintf (acfg->fp, ".section .ctors,\"aw\",@progbits\n");
4293                         emit_alignment (acfg, 8);
4294                         emit_pointer (acfg, symbol);
4295 #elif defined(__arm__) && defined(__MACH__)
4296                                 
4297                         fprintf (acfg->fp, ".text\n");
4298                         fprintf (acfg->fp, ".align   3\n");
4299                 
4300                         fprintf (acfg->fp, "ldr r0, .L5\n");
4301                         fprintf (acfg->fp, ".LPIC0:\n");
4302                         fprintf (acfg->fp, "add r0, pc, r0\n");
4303                         fprintf (acfg->fp, "ldr r0, [r0]\n");
4304                         fprintf (acfg->fp, "b   _mono_aot_register_globals@PLT\n");
4305                         fprintf (acfg->fp, ".align 2\n");
4306
4307                         fprintf (acfg->fp, ".L5:\n");
4308                         fprintf (acfg->fp, ".long       globals_ptr-(.LPIC0+8)\n");
4309                         
4310                         fprintf (acfg->fp, ".data\n");
4311                         fprintf (acfg->fp, ".align      2\n");
4312                         fprintf (acfg->fp, "globals_ptr:\n");
4313                         fprintf (acfg->fp, ".long       globals\n");
4314                         
4315                         fprintf (acfg->fp, ".mod_init_func\n");
4316                         fprintf (acfg->fp, ".align      2\n");
4317                         fprintf (acfg->fp, ".long       %s@target1\n", symbol);
4318
4319 #elif defined(__arm__)
4320                         /* 
4321                          * Taken from gcc generated code for:
4322                          * static int i;
4323                          * void foo () { bar (&i); }
4324                          * gcc --shared -fPIC -O2
4325                          */
4326                         fprintf (acfg->fp, "ldr r3, .L5\n");
4327                         fprintf (acfg->fp, "ldr r0, .L5+4\n");
4328                         fprintf (acfg->fp, ".LPIC0:\n");
4329                         fprintf (acfg->fp, "add r3, pc, r3\n");
4330                         fprintf (acfg->fp, "add r0, r3, r0\n");
4331                         fprintf (acfg->fp, "b   mono_aot_register_globals(PLT)\n");
4332
4333                         fprintf (acfg->fp, ".L5:\n");
4334                         fprintf (acfg->fp, ".word       _GLOBAL_OFFSET_TABLE_-(.LPIC0+8)\n");
4335                         fprintf (acfg->fp, ".word       globals(GOTOFF)\n");
4336
4337                         fprintf (acfg->fp, ".section    .init_array,\"aw\",%%init_array\n");
4338                         fprintf (acfg->fp, ".align      2\n");
4339                         fprintf (acfg->fp, ".word       %s(target1)\n", symbol);
4340 #else
4341                         g_assert_not_reached ();
4342 #endif
4343 #endif
4344                         g_free (symbol);
4345                 }
4346         }
4347 }
4348
4349 static void
4350 acfg_free (MonoAotCompile *acfg)
4351 {
4352         int i;
4353
4354         for (i = 0; i < acfg->nmethods; ++i)
4355                 if (acfg->cfgs [i])
4356                         g_free (acfg->cfgs [i]);
4357         g_free (acfg->cfgs);
4358         g_free (acfg->method_got_offsets);
4359         g_free (acfg->static_linking_symbol);
4360         g_ptr_array_free (acfg->methods, TRUE);
4361         g_ptr_array_free (acfg->shared_patches, TRUE);
4362         g_ptr_array_free (acfg->image_table, TRUE);
4363         g_ptr_array_free (acfg->globals, TRUE);
4364         g_hash_table_destroy (acfg->method_indexes);
4365         g_hash_table_destroy (acfg->plt_offset_to_patch);
4366         g_hash_table_destroy (acfg->patch_to_plt_offset);
4367         g_hash_table_destroy (acfg->patch_to_shared_got_offset);
4368         g_hash_table_destroy (acfg->method_to_cfg);
4369         g_hash_table_destroy (acfg->token_info_hash);
4370         g_hash_table_destroy (acfg->image_hash);
4371         mono_mempool_destroy (acfg->mempool);
4372         g_free (acfg);
4373 }
4374
4375 int
4376 mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
4377 {
4378         MonoImage *image = ass->image;
4379         char *symbol;
4380         int i, res;
4381         MonoAotCompile *acfg;
4382
4383         printf ("Mono Ahead of Time compiler - compiling assembly %s\n", image->name);
4384
4385         acfg = g_new0 (MonoAotCompile, 1);
4386         acfg->methods = g_ptr_array_new ();
4387         acfg->method_indexes = g_hash_table_new (NULL, NULL);
4388         acfg->plt_offset_to_patch = g_hash_table_new (NULL, NULL);
4389         acfg->patch_to_plt_offset = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
4390         acfg->patch_to_shared_got_offset = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
4391         acfg->shared_patches = g_ptr_array_new ();
4392         acfg->method_to_cfg = g_hash_table_new (NULL, NULL);
4393         acfg->token_info_hash = g_hash_table_new_full (NULL, NULL, NULL, g_free);
4394         acfg->image_hash = g_hash_table_new (NULL, NULL);
4395         acfg->image_table = g_ptr_array_new ();
4396         acfg->globals = g_ptr_array_new ();
4397         acfg->image = image;
4398         acfg->opts = opts;
4399         acfg->mempool = mono_mempool_new ();
4400
4401         mono_aot_parse_options (aot_options, &acfg->aot_opts);
4402
4403         load_profile_files (acfg);
4404
4405         emit_start (acfg);
4406
4407         acfg->num_aot_trampolines = acfg->aot_opts.full_aot ? 10240 : 0;
4408
4409         acfg->method_index = 1;
4410
4411         /* Collect methods */
4412         for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
4413                 MonoMethod *method;
4414                 guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
4415
4416                 method = mono_get_method (acfg->image, token, NULL);
4417
4418                 if (acfg->aot_opts.full_aot && method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
4419                         /* Compile the wrapper instead */
4420                         /* We do this here instead of add_wrappers () because it is easy to do it here */
4421                         MonoMethod *wrapper = mono_marshal_get_native_wrapper (method, check_for_pending_exc, TRUE);
4422                         method = wrapper;
4423                 }
4424
4425                 /* Since we add the normal methods first, their index will be equal to their zero based token index */
4426                 add_method_with_index (acfg, method, i);
4427                 acfg->method_index ++;
4428         }
4429
4430         if (acfg->aot_opts.full_aot)
4431                 add_wrappers (acfg);
4432
4433         acfg->nmethods = acfg->methods->len + 1;
4434         acfg->cfgs = g_new0 (MonoCompile*, acfg->nmethods + 32);
4435         acfg->method_got_offsets = g_new0 (guint32, acfg->nmethods + 32);
4436
4437         /* PLT offset 0 is reserved for the PLT trampoline */
4438         acfg->plt_offset = 1;
4439
4440         /* Compile methods */
4441         for (i = 0; i < acfg->methods->len; ++i) {
4442                 compile_method (acfg, g_ptr_array_index (acfg->methods, i));
4443         }
4444
4445         alloc_got_slots (acfg);
4446
4447         emit_code (acfg);
4448
4449         emit_info (acfg);
4450
4451         emit_wrapper_info (acfg);
4452
4453         emit_method_order (acfg);
4454
4455         emit_trampolines (acfg);
4456
4457         emit_class_name_table (acfg);
4458
4459         emit_got_info (acfg);
4460
4461         emit_exception_info (acfg);
4462
4463         emit_class_info (acfg);
4464
4465         emit_plt (acfg);
4466
4467         emit_image_table (acfg);
4468
4469         emit_got (acfg);
4470
4471         emit_globals (acfg);
4472
4473         symbol = g_strdup_printf ("mem_end");
4474         emit_section_change (acfg, ".text", 1);
4475         emit_global (acfg, symbol, FALSE);
4476         emit_alignment (acfg, 8);
4477         emit_label (acfg, symbol);
4478         g_free (symbol);
4479
4480         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)));
4481
4482         res = emit_writeout (acfg);
4483         if (res != 0) {
4484                 acfg_free (acfg);
4485                 return res;
4486         }
4487
4488         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);
4489         if (acfg->stats.genericcount)
4490                 printf ("%d methods are generic (%d%%)\n", acfg->stats.genericcount, acfg->stats.mcount ? (acfg->stats.genericcount * 100) / acfg->stats.mcount : 100);
4491         if (acfg->stats.abscount)
4492                 printf ("%d methods contain absolute addresses (%d%%)\n", acfg->stats.abscount, acfg->stats.mcount ? (acfg->stats.abscount * 100) / acfg->stats.mcount : 100);
4493         if (acfg->stats.wrappercount)
4494                 printf ("%d methods contain wrapper references (%d%%)\n", acfg->stats.wrappercount, acfg->stats.mcount ? (acfg->stats.wrappercount * 100) / acfg->stats.mcount : 100);
4495         if (acfg->stats.lmfcount)
4496                 printf ("%d methods contain lmf pointers (%d%%)\n", acfg->stats.lmfcount, acfg->stats.mcount ? (acfg->stats.lmfcount * 100) / acfg->stats.mcount : 100);
4497         if (acfg->stats.ocount)
4498                 printf ("%d methods have other problems (%d%%)\n", acfg->stats.ocount, acfg->stats.mcount ? (acfg->stats.ocount * 100) / acfg->stats.mcount : 100);
4499         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);
4500         printf ("Direct calls: %d (%d%%)\n", acfg->stats.direct_calls, acfg->stats.all_calls ? (acfg->stats.direct_calls * 100) / acfg->stats.all_calls : 100);
4501
4502         printf ("GOT slot distribution:\n");
4503         for (i = 0; i < MONO_PATCH_INFO_NONE; ++i)
4504                 if (acfg->stats.got_slot_types [i])
4505                         printf ("\t%s: %d\n", get_patch_name (i), acfg->stats.got_slot_types [i]);
4506
4507         acfg_free (acfg);
4508         
4509         return 0;
4510 }
4511
4512 #else
4513
4514 /* AOT disabled */
4515
4516 int
4517 mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
4518 {
4519         return 0;
4520 }
4521
4522 #endif