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