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