2010-02-07 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_get_wrapper_info (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                         AllocatorWrapperInfo *info = mono_marshal_get_wrapper_info (method);
1630
1631                         g_assert (info->alloc_type != -1);
1632                         encode_value (info->alloc_type, p, &p);
1633                         break;
1634                 }
1635                 case MONO_WRAPPER_STELEMREF:
1636                         break;
1637                 case MONO_WRAPPER_UNKNOWN:
1638                         if (strcmp (method->name, "FastMonitorEnter") == 0)
1639                                 encode_value (MONO_AOT_WRAPPER_MONO_ENTER, p, &p);
1640                         else if (strcmp (method->name, "FastMonitorExit") == 0)
1641                                 encode_value (MONO_AOT_WRAPPER_MONO_EXIT, p, &p);
1642                         else
1643                                 g_assert_not_reached ();
1644                         break;
1645                 case MONO_WRAPPER_SYNCHRONIZED:
1646                 case MONO_WRAPPER_MANAGED_TO_NATIVE:
1647                 case MONO_WRAPPER_RUNTIME_INVOKE: {
1648                         MonoMethod *m;
1649
1650                         m = mono_marshal_method_from_wrapper (method);
1651                         g_assert (m);
1652                         g_assert (m != method);
1653                         encode_method_ref (acfg, m, p, &p);
1654                         break;
1655                 }
1656                 case MONO_WRAPPER_MANAGED_TO_MANAGED:
1657                         if (!strcmp (method->name, "ElementAddr")) {
1658                                 ElementAddrWrapperInfo *info = mono_marshal_get_wrapper_info (method);
1659
1660                                 g_assert (info);
1661                                 encode_value (MONO_AOT_WRAPPER_ELEMENT_ADDR, p, &p);
1662                                 encode_value (info->rank, p, &p);
1663                                 encode_value (info->elem_size, p, &p);
1664                         } else {
1665                                 g_assert_not_reached ();
1666                         }
1667                         break;
1668                 default:
1669                         g_assert_not_reached ();
1670                 }
1671         } else if (mono_method_signature (method)->is_inflated) {
1672                 /* 
1673                  * This is a generic method, find the original token which referenced it and
1674                  * encode that.
1675                  * Obtain the token from information recorded by the JIT.
1676                  */
1677                 ji = g_hash_table_lookup (acfg->token_info_hash, method);
1678                 if (ji) {
1679                         image_index = get_image_index (acfg, ji->image);
1680                         g_assert (image_index < MAX_IMAGE_INDEX);
1681                         token = ji->token;
1682
1683                         encode_value ((MONO_AOT_METHODREF_METHODSPEC << 24), p, &p);
1684                         encode_value (image_index, p, &p);
1685                         encode_value (token, p, &p);
1686                 } else {
1687                         MonoMethod *declaring;
1688                         MonoGenericContext *context = mono_method_get_context (method);
1689
1690                         g_assert (method->is_inflated);
1691                         declaring = ((MonoMethodInflated*)method)->declaring;
1692
1693                         /*
1694                          * This might be a non-generic method of a generic instance, which 
1695                          * doesn't have a token since the reference is generated by the JIT 
1696                          * like Nullable:Box/Unbox, or by generic sharing.
1697                          */
1698
1699                         encode_value ((MONO_AOT_METHODREF_GINST << 24), p, &p);
1700                         /* Encode the klass */
1701                         encode_klass_ref (acfg, method->klass, p, &p);
1702                         /* Encode the method */
1703                         image_index = get_image_index (acfg, method->klass->image);
1704                         g_assert (image_index < MAX_IMAGE_INDEX);
1705                         g_assert (declaring->token);
1706                         token = declaring->token;
1707                         g_assert (mono_metadata_token_table (token) == MONO_TABLE_METHOD);
1708                         encode_value (image_index, p, &p);
1709                         encode_value (token, p, &p);
1710                         encode_generic_context (acfg, context, p, &p);
1711                 }
1712         } else if (token == 0) {
1713                 /* This might be a method of a constructed type like int[,].Set */
1714                 /* Obtain the token from information recorded by the JIT */
1715                 ji = g_hash_table_lookup (acfg->token_info_hash, method);
1716                 if (ji) {
1717                         image_index = get_image_index (acfg, ji->image);
1718                         g_assert (image_index < MAX_IMAGE_INDEX);
1719                         token = ji->token;
1720
1721                         encode_value ((MONO_AOT_METHODREF_METHODSPEC << 24), p, &p);
1722                         encode_value (image_index, p, &p);
1723                         encode_value (token, p, &p);
1724                 } else {
1725                         /* Array methods */
1726                         g_assert (method->klass->rank);
1727
1728                         /* Encode directly */
1729                         encode_value ((MONO_AOT_METHODREF_ARRAY << 24), p, &p);
1730                         encode_klass_ref (acfg, method->klass, p, &p);
1731                         if (!strcmp (method->name, ".ctor") && mono_method_signature (method)->param_count == method->klass->rank)
1732                                 encode_value (0, p, &p);
1733                         else if (!strcmp (method->name, ".ctor") && mono_method_signature (method)->param_count == method->klass->rank * 2)
1734                                 encode_value (1, p, &p);
1735                         else if (!strcmp (method->name, "Get"))
1736                                 encode_value (2, p, &p);
1737                         else if (!strcmp (method->name, "Address"))
1738                                 encode_value (3, p, &p);
1739                         else if (!strcmp (method->name, "Set"))
1740                                 encode_value (4, p, &p);
1741                         else
1742                                 g_assert_not_reached ();
1743                 }
1744         } else {
1745                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_METHOD);
1746                 encode_value ((image_index << 24) | mono_metadata_token_index (token), p, &p);
1747         }
1748         *endbuf = p;
1749 }
1750
1751 static gint
1752 compare_patches (gconstpointer a, gconstpointer b)
1753 {
1754         int i, j;
1755
1756         i = (*(MonoJumpInfo**)a)->ip.i;
1757         j = (*(MonoJumpInfo**)b)->ip.i;
1758
1759         if (i < j)
1760                 return -1;
1761         else
1762                 if (i > j)
1763                         return 1;
1764         else
1765                 return 0;
1766 }
1767
1768 /*
1769  * is_plt_patch:
1770  *
1771  *   Return whenever PATCH_INFO refers to a direct call, and thus requires a
1772  * PLT entry.
1773  */
1774 static inline gboolean
1775 is_plt_patch (MonoJumpInfo *patch_info)
1776 {
1777         switch (patch_info->type) {
1778         case MONO_PATCH_INFO_METHOD:
1779         case MONO_PATCH_INFO_INTERNAL_METHOD:
1780         case MONO_PATCH_INFO_JIT_ICALL_ADDR:
1781         case MONO_PATCH_INFO_ICALL_ADDR:
1782         case MONO_PATCH_INFO_CLASS_INIT:
1783         case MONO_PATCH_INFO_RGCTX_FETCH:
1784         case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
1785         case MONO_PATCH_INFO_MONITOR_ENTER:
1786         case MONO_PATCH_INFO_MONITOR_EXIT:
1787         case MONO_PATCH_INFO_LLVM_IMT_TRAMPOLINE:
1788                 return TRUE;
1789         default:
1790                 return FALSE;
1791         }
1792 }
1793
1794 static int
1795 get_plt_offset (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
1796 {
1797         int res = -1;
1798
1799         if (is_plt_patch (patch_info)) {
1800                 int idx = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->patch_to_plt_offset, patch_info));
1801
1802                 // FIXME: This breaks the calculation of final_got_size         
1803                 if (!acfg->llvm && patch_info->type == MONO_PATCH_INFO_METHOD && (patch_info->data.method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)) {
1804                         /* 
1805                          * Allocate a separate PLT slot for each such patch, since some plt
1806                          * entries will refer to the method itself, and some will refer to the
1807                          * wrapper.
1808                          */
1809                         idx = 0;
1810                 }
1811
1812                 if (idx) {
1813                         res = idx;
1814                 } else {
1815                         MonoJumpInfo *new_ji = mono_patch_info_dup_mp (acfg->mempool, patch_info);
1816
1817                         g_assert (!acfg->final_got_size);
1818
1819                         res = acfg->plt_offset;
1820                         g_hash_table_insert (acfg->plt_offset_to_patch, GUINT_TO_POINTER (res), new_ji);
1821                         g_hash_table_insert (acfg->patch_to_plt_offset, new_ji, GUINT_TO_POINTER (res));
1822                         acfg->plt_offset ++;
1823                 }
1824         }
1825
1826         return res;
1827 }
1828
1829 /**
1830  * get_got_offset:
1831  *
1832  *   Returns the offset of the GOT slot where the runtime object resulting from resolving
1833  * JI could be found if it exists, otherwise allocates a new one.
1834  */
1835 static guint32
1836 get_got_offset (MonoAotCompile *acfg, MonoJumpInfo *ji)
1837 {
1838         guint32 got_offset;
1839
1840         got_offset = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->patch_to_got_offset_by_type [ji->type], ji));
1841         if (got_offset)
1842                 return got_offset - 1;
1843
1844         got_offset = acfg->got_offset;
1845         acfg->got_offset ++;
1846
1847         if (acfg->final_got_size)
1848                 g_assert (got_offset < acfg->final_got_size);
1849
1850         acfg->stats.got_slots ++;
1851         acfg->stats.got_slot_types [ji->type] ++;
1852
1853         g_hash_table_insert (acfg->patch_to_got_offset, ji, GUINT_TO_POINTER (got_offset + 1));
1854         g_hash_table_insert (acfg->patch_to_got_offset_by_type [ji->type], ji, GUINT_TO_POINTER (got_offset + 1));
1855         g_ptr_array_add (acfg->got_patches, ji);
1856
1857         return got_offset;
1858 }
1859
1860 /* Add a method to the list of methods which need to be emitted */
1861 static void
1862 add_method_with_index (MonoAotCompile *acfg, MonoMethod *method, int index, gboolean extra)
1863 {
1864         g_assert (method);
1865         if (!g_hash_table_lookup (acfg->method_indexes, method)) {
1866                 g_ptr_array_add (acfg->methods, method);
1867                 g_hash_table_insert (acfg->method_indexes, method, GUINT_TO_POINTER (index + 1));
1868                 acfg->nmethods = acfg->methods->len + 1;
1869         }
1870
1871         if (method->wrapper_type || extra)
1872                 g_ptr_array_add (acfg->extra_methods, method);
1873 }
1874
1875 static guint32
1876 get_method_index (MonoAotCompile *acfg, MonoMethod *method)
1877 {
1878         int index = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_indexes, method));
1879         
1880         g_assert (index);
1881
1882         return index - 1;
1883 }
1884
1885 static int
1886 add_method_full (MonoAotCompile *acfg, MonoMethod *method, gboolean extra, int depth)
1887 {
1888         int index;
1889
1890         index = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_indexes, method));
1891         if (index)
1892                 return index - 1;
1893
1894         index = acfg->method_index;
1895         add_method_with_index (acfg, method, index, extra);
1896
1897         /* FIXME: Fix quadratic behavior */
1898         acfg->method_order = g_list_append (acfg->method_order, GUINT_TO_POINTER (index));
1899
1900         g_hash_table_insert (acfg->method_depth, method, GUINT_TO_POINTER (depth));
1901
1902         acfg->method_index ++;
1903
1904         return index;
1905 }
1906
1907 static int
1908 add_method (MonoAotCompile *acfg, MonoMethod *method)
1909 {
1910         return add_method_full (acfg, method, FALSE, 0);
1911 }
1912
1913 static void
1914 add_extra_method (MonoAotCompile *acfg, MonoMethod *method)
1915 {
1916         add_method_full (acfg, method, TRUE, 0);
1917 }
1918
1919 static void
1920 add_extra_method_with_depth (MonoAotCompile *acfg, MonoMethod *method, int depth)
1921 {
1922         add_method_full (acfg, method, TRUE, depth);
1923 }
1924
1925 static void
1926 add_jit_icall_wrapper (gpointer key, gpointer value, gpointer user_data)
1927 {
1928         MonoAotCompile *acfg = user_data;
1929         MonoJitICallInfo *callinfo = value;
1930         MonoMethod *wrapper;
1931         char *name;
1932
1933         if (!callinfo->sig)
1934                 return;
1935
1936         name = g_strdup_printf ("__icall_wrapper_%s", callinfo->name);
1937         wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, check_for_pending_exc);
1938         g_free (name);
1939
1940         add_method (acfg, wrapper);
1941 }
1942
1943 static MonoMethod*
1944 get_runtime_invoke_sig (MonoMethodSignature *sig)
1945 {
1946         MonoMethodBuilder *mb;
1947         MonoMethod *m;
1948
1949         mb = mono_mb_new (mono_defaults.object_class, "FOO", MONO_WRAPPER_NONE);
1950         m = mono_mb_create_method (mb, sig, 16);
1951         return mono_marshal_get_runtime_invoke (m, FALSE);
1952 }
1953
1954 static gboolean
1955 can_marshal_struct (MonoClass *klass)
1956 {
1957         MonoClassField *field;
1958         gboolean can_marshal = TRUE;
1959         gpointer iter = NULL;
1960
1961         if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1962                 return FALSE;
1963
1964         /* Only allow a few field types to avoid asserts in the marshalling code */
1965         while ((field = mono_class_get_fields (klass, &iter))) {
1966                 if ((field->type->attrs & FIELD_ATTRIBUTE_STATIC))
1967                         continue;
1968
1969                 switch (field->type->type) {
1970                 case MONO_TYPE_I4:
1971                 case MONO_TYPE_U4:
1972                 case MONO_TYPE_I1:
1973                 case MONO_TYPE_U1:
1974                 case MONO_TYPE_BOOLEAN:
1975                 case MONO_TYPE_I2:
1976                 case MONO_TYPE_U2:
1977                 case MONO_TYPE_CHAR:
1978                 case MONO_TYPE_I8:
1979                 case MONO_TYPE_U8:
1980                 case MONO_TYPE_I:
1981                 case MONO_TYPE_U:
1982                 case MONO_TYPE_PTR:
1983                 case MONO_TYPE_R4:
1984                 case MONO_TYPE_R8:
1985                 case MONO_TYPE_STRING:
1986                         break;
1987                 case MONO_TYPE_VALUETYPE:
1988                         if (!mono_class_from_mono_type (field->type)->enumtype && !can_marshal_struct (mono_class_from_mono_type (field->type)))
1989                                 can_marshal = FALSE;
1990                         break;
1991                 default:
1992                         can_marshal = FALSE;
1993                         break;
1994                 }
1995         }
1996
1997         /* Special cases */
1998         /* Its hard to compute whenever these can be marshalled or not */
1999         if (!strcmp (klass->name_space, "System.Net.NetworkInformation.MacOsStructs"))
2000                 return TRUE;
2001
2002         return can_marshal;
2003 }
2004
2005 static void
2006 add_wrappers (MonoAotCompile *acfg)
2007 {
2008         MonoMethod *method, *m;
2009         int i, j;
2010         MonoMethodSignature *sig, *csig;
2011         guint32 token;
2012
2013         /* 
2014          * FIXME: Instead of AOTing all the wrappers, it might be better to redesign them
2015          * so there is only one wrapper of a given type, or inlining their contents into their
2016          * callers.
2017          */
2018
2019         /* 
2020          * FIXME: This depends on the fact that different wrappers have different 
2021          * names.
2022          */
2023
2024         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
2025                 MonoMethod *method;
2026                 guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
2027                 gboolean skip = FALSE;
2028
2029                 method = mono_get_method (acfg->image, token, NULL);
2030
2031                 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
2032                         (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
2033                         (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
2034                         skip = TRUE;
2035
2036                 if (method->is_generic || method->klass->generic_container)
2037                         skip = TRUE;
2038
2039                 /* Skip methods which can not be handled by get_runtime_invoke () */
2040                 sig = mono_method_signature (method);
2041                 if ((sig->ret->type == MONO_TYPE_PTR) ||
2042                         (sig->ret->type == MONO_TYPE_TYPEDBYREF))
2043                         skip = TRUE;
2044
2045                 for (j = 0; j < sig->param_count; j++) {
2046                         if (sig->params [j]->type == MONO_TYPE_TYPEDBYREF)
2047                                 skip = TRUE;
2048                 }
2049
2050 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
2051                 if (!method->klass->contextbound) {
2052                         MonoDynCallInfo *info = mono_arch_dyn_call_prepare (sig);
2053                         gboolean has_nullable = FALSE;
2054
2055                         for (j = 0; j < sig->param_count; j++) {
2056                                 if (sig->params [j]->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (sig->params [j])))
2057                                         has_nullable = TRUE;
2058                         }
2059
2060                         if (info && !has_nullable) {
2061                                 /* Supported by the dynamic runtime-invoke wrapper */
2062                                 skip = TRUE;
2063                                 g_free (info);
2064                         }
2065                 }
2066 #endif
2067
2068                 if (!skip) {
2069                         //printf ("%s\n", mono_method_full_name (method, TRUE));
2070                         add_method (acfg, mono_marshal_get_runtime_invoke (method, FALSE));
2071                 }
2072         }
2073
2074         if (strcmp (acfg->image->assembly->aname.name, "mscorlib") == 0) {
2075 #ifdef MONO_ARCH_HAVE_TLS_GET
2076                 MonoMethodDesc *desc;
2077                 MonoMethod *orig_method;
2078                 int nallocators;
2079 #endif
2080
2081                 /* Runtime invoke wrappers */
2082
2083                 /* void runtime-invoke () [.cctor] */
2084                 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
2085                 csig->ret = &mono_defaults.void_class->byval_arg;
2086                 add_method (acfg, get_runtime_invoke_sig (csig));
2087
2088                 /* void runtime-invoke () [Finalize] */
2089                 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
2090                 csig->hasthis = 1;
2091                 csig->ret = &mono_defaults.void_class->byval_arg;
2092                 add_method (acfg, get_runtime_invoke_sig (csig));
2093
2094                 /* void runtime-invoke (string) [exception ctor] */
2095                 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
2096                 csig->hasthis = 1;
2097                 csig->ret = &mono_defaults.void_class->byval_arg;
2098                 csig->params [0] = &mono_defaults.string_class->byval_arg;
2099                 add_method (acfg, get_runtime_invoke_sig (csig));
2100
2101                 /* void runtime-invoke (string, string) [exception ctor] */
2102                 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
2103                 csig->hasthis = 1;
2104                 csig->ret = &mono_defaults.void_class->byval_arg;
2105                 csig->params [0] = &mono_defaults.string_class->byval_arg;
2106                 csig->params [1] = &mono_defaults.string_class->byval_arg;
2107                 add_method (acfg, get_runtime_invoke_sig (csig));
2108
2109                 /* string runtime-invoke () [Exception.ToString ()] */
2110                 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 0);
2111                 csig->hasthis = 1;
2112                 csig->ret = &mono_defaults.string_class->byval_arg;
2113                 add_method (acfg, get_runtime_invoke_sig (csig));
2114
2115                 /* void runtime-invoke (string, Exception) [exception ctor] */
2116                 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
2117                 csig->hasthis = 1;
2118                 csig->ret = &mono_defaults.void_class->byval_arg;
2119                 csig->params [0] = &mono_defaults.string_class->byval_arg;
2120                 csig->params [1] = &mono_defaults.exception_class->byval_arg;
2121                 add_method (acfg, get_runtime_invoke_sig (csig));
2122
2123                 /* Assembly runtime-invoke (string, bool) [DoAssemblyResolve] */
2124                 csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
2125                 csig->hasthis = 1;
2126                 csig->ret = &(mono_class_from_name (
2127                                                                                         mono_defaults.corlib, "System.Reflection", "Assembly"))->byval_arg;
2128                 csig->params [0] = &mono_defaults.string_class->byval_arg;
2129                 csig->params [1] = &mono_defaults.boolean_class->byval_arg;
2130                 add_method (acfg, get_runtime_invoke_sig (csig));
2131
2132                 /* runtime-invoke used by finalizers */
2133                 add_method (acfg, mono_marshal_get_runtime_invoke (mono_class_get_method_from_name_flags (mono_defaults.object_class, "Finalize", 0, 0), TRUE));
2134
2135                 /* This is used by mono_runtime_capture_context () */
2136                 method = mono_get_context_capture_method ();
2137                 if (method)
2138                         add_method (acfg, mono_marshal_get_runtime_invoke (method, FALSE));
2139
2140 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
2141                 add_method (acfg, mono_marshal_get_runtime_invoke_dynamic ());
2142 #endif
2143
2144                 /* JIT icall wrappers */
2145                 /* FIXME: locking */
2146                 g_hash_table_foreach (mono_get_jit_icall_info (), add_jit_icall_wrapper, acfg);
2147
2148                 /* stelemref */
2149                 add_method (acfg, mono_marshal_get_stelemref ());
2150
2151 #ifdef MONO_ARCH_HAVE_TLS_GET
2152                 /* Managed Allocators */
2153                 nallocators = mono_gc_get_managed_allocator_types ();
2154                 for (i = 0; i < nallocators; ++i) {
2155                         m = mono_gc_get_managed_allocator_by_type (i);
2156                         if (m)
2157                                 add_method (acfg, m);
2158                 }
2159
2160                 /* Monitor Enter/Exit */
2161                 desc = mono_method_desc_new ("Monitor:Enter", FALSE);
2162                 orig_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
2163                 g_assert (orig_method);
2164                 mono_method_desc_free (desc);
2165                 method = mono_monitor_get_fast_path (orig_method);
2166                 if (method)
2167                         add_method (acfg, method);
2168
2169                 desc = mono_method_desc_new ("Monitor:Exit", FALSE);
2170                 orig_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
2171                 g_assert (orig_method);
2172                 mono_method_desc_free (desc);
2173                 method = mono_monitor_get_fast_path (orig_method);
2174                 if (method)
2175                         add_method (acfg, method);
2176 #endif
2177         }
2178
2179         /* 
2180          * remoting-invoke-with-check wrappers are very frequent, so avoid emitting them,
2181          * we use the original method instead at runtime.
2182          * Since full-aot doesn't support remoting, this is not a problem.
2183          */
2184 #if 0
2185         /* remoting-invoke wrappers */
2186         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
2187                 MonoMethodSignature *sig;
2188                 
2189                 token = MONO_TOKEN_METHOD_DEF | (i + 1);
2190                 method = mono_get_method (acfg->image, token, NULL);
2191
2192                 sig = mono_method_signature (method);
2193
2194                 if (sig->hasthis && (method->klass->marshalbyref || method->klass == mono_defaults.object_class)) {
2195                         m = mono_marshal_get_remoting_invoke_with_check (method);
2196
2197                         add_method (acfg, m);
2198                 }
2199         }
2200 #endif
2201
2202         /* delegate-invoke wrappers */
2203         for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
2204                 MonoClass *klass;
2205                 
2206                 token = MONO_TOKEN_TYPE_DEF | (i + 1);
2207                 klass = mono_class_get (acfg->image, token);
2208
2209                 if (klass->delegate && klass != mono_defaults.delegate_class && klass != mono_defaults.multicastdelegate_class && !klass->generic_container) {
2210                         method = mono_get_delegate_invoke (klass);
2211
2212                         m = mono_marshal_get_delegate_invoke (method, NULL);
2213
2214                         add_method (acfg, m);
2215
2216                         method = mono_class_get_method_from_name_flags (klass, "BeginInvoke", -1, 0);
2217                         add_method (acfg, mono_marshal_get_delegate_begin_invoke (method));
2218
2219                         method = mono_class_get_method_from_name_flags (klass, "EndInvoke", -1, 0);
2220                         add_method (acfg, mono_marshal_get_delegate_end_invoke (method));
2221                 }
2222         }
2223
2224         /* Synchronized wrappers */
2225         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
2226                 token = MONO_TOKEN_METHOD_DEF | (i + 1);
2227                 method = mono_get_method (acfg->image, token, NULL);
2228
2229                 if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED && !method->is_generic)
2230                         add_method (acfg, mono_marshal_get_synchronized_wrapper (method));
2231         }
2232
2233         /* pinvoke wrappers */
2234         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
2235                 MonoMethod *method;
2236                 guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
2237
2238                 method = mono_get_method (acfg->image, token, NULL);
2239
2240                 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
2241                         (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
2242                         add_method (acfg, mono_marshal_get_native_wrapper (method, TRUE, TRUE));
2243                 }
2244         }
2245  
2246         /* native-to-managed wrappers */
2247         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
2248                 MonoMethod *method;
2249                 guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
2250                 MonoCustomAttrInfo *cattr;
2251                 int j;
2252
2253                 method = mono_get_method (acfg->image, token, NULL);
2254
2255                 /* 
2256                  * Only generate native-to-managed wrappers for methods which have an
2257                  * attribute named MonoPInvokeCallbackAttribute. We search for the attribute by
2258                  * name to avoid defining a new assembly to contain it.
2259                  */
2260                 cattr = mono_custom_attrs_from_method (method);
2261
2262                 if (cattr) {
2263                         for (j = 0; j < cattr->num_attrs; ++j)
2264                                 if (cattr->attrs [j].ctor && !strcmp (cattr->attrs [j].ctor->klass->name, "MonoPInvokeCallbackAttribute"))
2265                                         break;
2266                         if (j < cattr->num_attrs) {
2267                                 MonoCustomAttrEntry *e = &cattr->attrs [j];
2268                                 MonoMethodSignature *sig = mono_method_signature (e->ctor);
2269                                 const char *p = (const char*)e->data;
2270                                 int slen;
2271                                 char *n;
2272                                 MonoType *t;
2273                                 MonoClass *klass;
2274
2275                                 g_assert (method->flags & METHOD_ATTRIBUTE_STATIC);
2276
2277                                 g_assert (sig->param_count == 1);
2278                                 g_assert (sig->params [0]->type == MONO_TYPE_CLASS && !strcmp (mono_class_from_mono_type (sig->params [0])->name, "Type"));
2279
2280                                 /* 
2281                                  * Decode the cattr manually since we can't create objects
2282                                  * during aot compilation.
2283                                  */
2284                                         
2285                                 /* Skip prolog */
2286                                 p += 2;
2287
2288                                 /* From load_cattr_value () in reflection.c */
2289                                 slen = mono_metadata_decode_value (p, &p);
2290                                 n = g_memdup (p, slen + 1);
2291                                 n [slen] = 0;
2292                                 t = mono_reflection_type_from_name (n, acfg->image);
2293                                 g_assert (t);
2294                                 g_free (n);
2295
2296                                 klass = mono_class_from_mono_type (t);
2297                                 g_assert (klass->parent == mono_defaults.multicastdelegate_class);
2298
2299                                 add_method (acfg, mono_marshal_get_managed_wrapper (method, klass, NULL));
2300                         }
2301                 }
2302
2303                 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
2304                         (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
2305                         add_method (acfg, mono_marshal_get_native_wrapper (method, TRUE, TRUE));
2306                 }
2307         }
2308
2309         /* StructureToPtr/PtrToStructure wrappers */
2310         for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
2311                 MonoClass *klass;
2312                 
2313                 token = MONO_TOKEN_TYPE_DEF | (i + 1);
2314                 klass = mono_class_get (acfg->image, token);
2315
2316                 if (klass->valuetype && !klass->generic_container && can_marshal_struct (klass)) {
2317                         add_method (acfg, mono_marshal_get_struct_to_ptr (klass));
2318                         add_method (acfg, mono_marshal_get_ptr_to_struct (klass));
2319                 }
2320         }
2321 }
2322
2323 static gboolean
2324 has_type_vars (MonoClass *klass)
2325 {
2326         if ((klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
2327                 return TRUE;
2328         if (klass->rank)
2329                 return has_type_vars (klass->element_class);
2330         if (klass->generic_class) {
2331                 MonoGenericContext *context = &klass->generic_class->context;
2332                 if (context->class_inst) {
2333                         int i;
2334
2335                         for (i = 0; i < context->class_inst->type_argc; ++i)
2336                                 if (has_type_vars (mono_class_from_mono_type (context->class_inst->type_argv [i])))
2337                                         return TRUE;
2338                 }
2339         }
2340         return FALSE;
2341 }
2342
2343 static gboolean
2344 method_has_type_vars (MonoMethod *method)
2345 {
2346         if (has_type_vars (method->klass))
2347                 return TRUE;
2348
2349         if (method->is_inflated) {
2350                 MonoGenericContext *context = mono_method_get_context (method);
2351                 if (context->method_inst) {
2352                         int i;
2353
2354                         for (i = 0; i < context->method_inst->type_argc; ++i)
2355                                 if (has_type_vars (mono_class_from_mono_type (context->method_inst->type_argv [i])))
2356                                         return TRUE;
2357                 }
2358         }
2359         return FALSE;
2360 }
2361
2362 /*
2363  * add_generic_class:
2364  *
2365  *   Add all methods of a generic class.
2366  */
2367 static void
2368 add_generic_class (MonoAotCompile *acfg, MonoClass *klass)
2369 {
2370         MonoMethod *method;
2371         gpointer iter;
2372
2373         mono_class_init (klass);
2374
2375         if (klass->generic_class && klass->generic_class->context.class_inst->is_open)
2376                 return;
2377
2378         if (has_type_vars (klass))
2379                 return;
2380
2381         if (!klass->generic_class && !klass->rank)
2382                 return;
2383
2384         iter = NULL;
2385         while ((method = mono_class_get_methods (klass, &iter))) {
2386                 if (mono_method_is_generic_sharable_impl (method, FALSE))
2387                         /* Already added */
2388                         continue;
2389
2390                 if (method->is_generic)
2391                         /* FIXME: */
2392                         continue;
2393
2394                 /*
2395                  * FIXME: Instances which are referenced by these methods are not added,
2396                  * for example Array.Resize<int> for List<int>.Add ().
2397                  */
2398                 add_extra_method (acfg, method);
2399         }
2400
2401         if (klass->delegate) {
2402                 method = mono_get_delegate_invoke (klass);
2403
2404                 method = mono_marshal_get_delegate_invoke (method, NULL);
2405
2406                 add_method (acfg, method);
2407         }
2408
2409         /* 
2410          * For ICollection<T>, add instances of the helper methods
2411          * in Array, since a T[] could be cast to ICollection<T>.
2412          */
2413         if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") &&
2414                 (!strcmp(klass->name, "ICollection`1") || !strcmp (klass->name, "IEnumerable`1") || !strcmp (klass->name, "IList`1") || !strcmp (klass->name, "IEnumerator`1"))) {
2415                 MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
2416                 MonoClass *array_class = mono_bounded_array_class_get (tclass, 1, FALSE);
2417                 gpointer iter;
2418                 char *name_prefix;
2419
2420                 if (!strcmp (klass->name, "IEnumerator`1"))
2421                         name_prefix = g_strdup_printf ("%s.%s", klass->name_space, "IEnumerable`1");
2422                 else
2423                         name_prefix = g_strdup_printf ("%s.%s", klass->name_space, klass->name);
2424
2425                 /* Add the T[]/InternalEnumerator class */
2426                 if (!strcmp (klass->name, "IEnumerable`1") || !strcmp (klass->name, "IEnumerator`1")) {
2427                         MonoClass *nclass;
2428
2429                         iter = NULL;
2430                         while ((nclass = mono_class_get_nested_types (array_class->parent, &iter))) {
2431                                 if (!strcmp (nclass->name, "InternalEnumerator`1"))
2432                                         break;
2433                         }
2434                         g_assert (nclass);
2435                         nclass = mono_class_inflate_generic_class (nclass, mono_generic_class_get_context (klass->generic_class));
2436                         add_generic_class (acfg, nclass);
2437                 }
2438
2439                 iter = NULL;
2440                 while ((method = mono_class_get_methods (array_class, &iter))) {
2441                         if (strstr (method->name, name_prefix)) {
2442                                 MonoMethod *m = mono_aot_get_array_helper_from_wrapper (method);
2443                                 add_extra_method (acfg, m);
2444                         }
2445                 }
2446
2447                 g_free (name_prefix);
2448         }
2449
2450         /* Add an instance of GenericComparer<T> which is created dynamically by Comparer<T> */
2451         if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "Comparer`1")) {
2452                 MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
2453                 MonoClass *icomparable, *gcomparer;
2454                 MonoGenericContext ctx;
2455                 MonoType *args [16];
2456
2457                 memset (&ctx, 0, sizeof (ctx));
2458
2459                 icomparable = mono_class_from_name (mono_defaults.corlib, "System", "IComparable`1");
2460                 g_assert (icomparable);
2461                 args [0] = &tclass->byval_arg;
2462                 ctx.class_inst = mono_metadata_get_generic_inst (1, args);
2463
2464                 if (mono_class_is_assignable_from (mono_class_inflate_generic_class (icomparable, &ctx), tclass)) {
2465                         gcomparer = mono_class_from_name (mono_defaults.corlib, "System.Collections.Generic", "GenericComparer`1");
2466                         g_assert (gcomparer);
2467                         add_generic_class (acfg, mono_class_inflate_generic_class (gcomparer, &ctx));
2468                 }
2469         }
2470 }
2471
2472 static void
2473 add_instances_of (MonoAotCompile *acfg, MonoClass *klass, MonoType **insts, int ninsts)
2474 {
2475         int i;
2476         MonoGenericContext ctx;
2477         MonoType *args [16];
2478
2479         memset (&ctx, 0, sizeof (ctx));
2480
2481         for (i = 0; i < ninsts; ++i) {
2482                 args [0] = insts [i];
2483                 ctx.class_inst = mono_metadata_get_generic_inst (1, args);
2484                 add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
2485         }
2486 }
2487
2488 /*
2489  * add_generic_instances:
2490  *
2491  *   Add instances referenced by the METHODSPEC/TYPESPEC table.
2492  */
2493 static void
2494 add_generic_instances (MonoAotCompile *acfg)
2495 {
2496         int i;
2497         guint32 token;
2498         MonoMethod *method;
2499         MonoMethodHeader *header;
2500         MonoMethodSignature *sig;
2501         MonoGenericContext *context;
2502
2503         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHODSPEC].rows; ++i) {
2504                 token = MONO_TOKEN_METHOD_SPEC | (i + 1);
2505                 method = mono_get_method (acfg->image, token, NULL);
2506
2507                 context = mono_method_get_context (method);
2508                 if (context && ((context->class_inst && context->class_inst->is_open) ||
2509                                                 (context->method_inst && context->method_inst->is_open)))
2510                         continue;
2511
2512                 if (method->klass->image != acfg->image)
2513                         continue;
2514
2515                 if (mono_method_is_generic_sharable_impl (method, FALSE))
2516                         /* Already added */
2517                         continue;
2518
2519                 add_extra_method (acfg, method);
2520         }
2521
2522         for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPESPEC].rows; ++i) {
2523                 MonoClass *klass;
2524
2525                 token = MONO_TOKEN_TYPE_SPEC | (i + 1);
2526
2527                 klass = mono_class_get (acfg->image, token);
2528                 if (!klass || klass->rank)
2529                         continue;
2530
2531                 add_generic_class (acfg, klass);
2532         }
2533
2534         /* Add types of args/locals */
2535         for (i = 0; i < acfg->methods->len; ++i) {
2536                 int j;
2537
2538                 method = g_ptr_array_index (acfg->methods, i);
2539
2540                 sig = mono_method_signature (method);
2541
2542                 if (sig) {
2543                         for (j = 0; j < sig->param_count; ++j)
2544                                 if (sig->params [j]->type == MONO_TYPE_GENERICINST)
2545                                         add_generic_class (acfg, mono_class_from_mono_type (sig->params [j]));
2546                 }
2547
2548                 header = mono_method_get_header (method);
2549
2550                 if (header) {
2551                         for (j = 0; j < header->num_locals; ++j)
2552                                 if (header->locals [j]->type == MONO_TYPE_GENERICINST)
2553                                         add_generic_class (acfg, mono_class_from_mono_type (header->locals [j]));
2554                 }
2555         }
2556
2557         if (acfg->image == mono_defaults.corlib) {
2558                 MonoClass *klass;
2559                 MonoType *insts [256];
2560                 int ninsts = 0;
2561
2562                 insts [ninsts ++] = &mono_defaults.byte_class->byval_arg;
2563                 insts [ninsts ++] = &mono_defaults.sbyte_class->byval_arg;
2564                 insts [ninsts ++] = &mono_defaults.int16_class->byval_arg;
2565                 insts [ninsts ++] = &mono_defaults.uint16_class->byval_arg;
2566                 insts [ninsts ++] = &mono_defaults.int32_class->byval_arg;
2567                 insts [ninsts ++] = &mono_defaults.uint32_class->byval_arg;
2568                 insts [ninsts ++] = &mono_defaults.int64_class->byval_arg;
2569                 insts [ninsts ++] = &mono_defaults.uint64_class->byval_arg;
2570                 insts [ninsts ++] = &mono_defaults.single_class->byval_arg;
2571                 insts [ninsts ++] = &mono_defaults.double_class->byval_arg;
2572                 insts [ninsts ++] = &mono_defaults.char_class->byval_arg;
2573                 insts [ninsts ++] = &mono_defaults.boolean_class->byval_arg;
2574
2575                 /* Add GenericComparer<T> instances for primitive types for Enum.ToString () */
2576                 klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "GenericComparer`1");
2577                 if (klass)
2578                         add_instances_of (acfg, klass, insts, ninsts);
2579                 klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "GenericEqualityComparer`1");
2580                 if (klass)
2581                         add_instances_of (acfg, klass, insts, ninsts);
2582
2583                 /* Add instances of the array generic interfaces for primitive types */
2584                 /* This will add instances of the InternalArray_ helper methods in Array too */
2585                 klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "ICollection`1");
2586                 if (klass)
2587                         add_instances_of (acfg, klass, insts, ninsts);
2588                 klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "IList`1");
2589                 if (klass)
2590                         add_instances_of (acfg, klass, insts, ninsts);
2591                 klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "IEnumerable`1");
2592                 if (klass)
2593                         add_instances_of (acfg, klass, insts, ninsts);
2594
2595                 /* 
2596                  * Add a managed-to-native wrapper of Array.GetGenericValueImpl<object>, which is
2597                  * used for all instances of GetGenericValueImpl by the AOT runtime.
2598                  */
2599                 {
2600                         MonoGenericContext ctx;
2601                         MonoType *args [16];
2602                         MonoMethod *get_method;
2603                         MonoClass *array_klass = mono_array_class_get (mono_defaults.object_class, 1)->parent;
2604
2605                         get_method = mono_class_get_method_from_name (array_klass, "GetGenericValueImpl", 2);
2606
2607                         if (get_method) {
2608                                 memset (&ctx, 0, sizeof (ctx));
2609                                 args [0] = &mono_defaults.object_class->byval_arg;
2610                                 ctx.method_inst = mono_metadata_get_generic_inst (1, args);
2611                                 add_extra_method (acfg, mono_marshal_get_native_wrapper (mono_class_inflate_generic_method (get_method, &ctx), TRUE, TRUE));
2612                         }
2613                 }
2614         }
2615 }
2616
2617 /*
2618  * is_direct_callable:
2619  *
2620  *   Return whenever the method identified by JI is directly callable without 
2621  * going through the PLT.
2622  */
2623 static gboolean
2624 is_direct_callable (MonoAotCompile *acfg, MonoMethod *method, MonoJumpInfo *patch_info)
2625 {
2626         if ((patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == acfg->image)) {
2627                 MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
2628                 if (callee_cfg) {
2629                         gboolean direct_callable = TRUE;
2630
2631                         if (direct_callable && !(!callee_cfg->has_got_slots && (callee_cfg->method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)))
2632                                 direct_callable = FALSE;
2633                         if ((callee_cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) && (!method || method->wrapper_type != MONO_WRAPPER_SYNCHRONIZED))
2634                                 // FIXME: Maybe call the wrapper directly ?
2635                                 direct_callable = FALSE;
2636
2637                         if (direct_callable)
2638                                 return TRUE;
2639                 }
2640         }
2641
2642         return FALSE;
2643 }
2644
2645 /*
2646  * emit_and_reloc_code:
2647  *
2648  *   Emit the native code in CODE, handling relocations along the way. If GOT_ONLY
2649  * is true, calls are made through the GOT too. This is used for emitting trampolines
2650  * in full-aot mode, since calls made from trampolines couldn't go through the PLT,
2651  * since trampolines are needed to make PTL work.
2652  */
2653 static void
2654 emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, guint32 code_len, MonoJumpInfo *relocs, gboolean got_only)
2655 {
2656         int i, pindex, start_index, method_index;
2657         GPtrArray *patches;
2658         MonoJumpInfo *patch_info;
2659         MonoMethodHeader *header;
2660         gboolean skip, direct_call;
2661         guint32 got_slot;
2662         char direct_call_target [128];
2663
2664         if (method) {
2665                 header = mono_method_get_header (method);
2666
2667                 method_index = get_method_index (acfg, method);
2668         }
2669
2670         /* Collect and sort relocations */
2671         patches = g_ptr_array_new ();
2672         for (patch_info = relocs; patch_info; patch_info = patch_info->next)
2673                 g_ptr_array_add (patches, patch_info);
2674         g_ptr_array_sort (patches, compare_patches);
2675
2676         start_index = 0;
2677         for (i = 0; i < code_len; i++) {
2678                 patch_info = NULL;
2679                 for (pindex = start_index; pindex < patches->len; ++pindex) {
2680                         patch_info = g_ptr_array_index (patches, pindex);
2681                         if (patch_info->ip.i >= i)
2682                                 break;
2683                 }
2684
2685 #ifdef MONO_ARCH_AOT_SUPPORTED
2686                 skip = FALSE;
2687                 if (patch_info && (patch_info->ip.i == i) && (pindex < patches->len)) {
2688                         start_index = pindex;
2689
2690                         switch (patch_info->type) {
2691                         case MONO_PATCH_INFO_NONE:
2692                                 break;
2693                         case MONO_PATCH_INFO_GOT_OFFSET: {
2694                                 int code_size;
2695  
2696                                 arch_emit_got_offset (acfg, code + i, &code_size);
2697                                 i += code_size - 1;
2698                                 skip = TRUE;
2699                                 patch_info->type = MONO_PATCH_INFO_NONE;
2700                                 break;
2701                         }
2702                         default: {
2703                                 /*
2704                                  * If this patch is a call, try emitting a direct call instead of
2705                                  * through a PLT entry. This is possible if the called method is in
2706                                  * the same assembly and requires no initialization.
2707                                  */
2708                                 direct_call = FALSE;
2709                                 if ((patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == acfg->image)) {
2710                                         if (!got_only && is_direct_callable (acfg, method, patch_info)) {
2711                                                 MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
2712                                                 //printf ("DIRECT: %s %s\n", method ? mono_method_full_name (method, TRUE) : "", mono_method_full_name (callee_cfg->method, TRUE));
2713                                                 direct_call = TRUE;
2714                                                 sprintf (direct_call_target, callee_cfg->asm_symbol);
2715                                                 patch_info->type = MONO_PATCH_INFO_NONE;
2716                                                 acfg->stats.direct_calls ++;
2717                                         }
2718
2719                                         acfg->stats.all_calls ++;
2720                                 }
2721
2722                                 if (!got_only && !direct_call) {
2723                                         int plt_offset = get_plt_offset (acfg, patch_info);
2724                                         if (plt_offset != -1) {
2725                                                 /* This patch has a PLT entry, so we must emit a call to the PLT entry */
2726                                                 direct_call = TRUE;
2727                                                 sprintf (direct_call_target, "%s%sp_%d", acfg->llvm_label_prefix, acfg->temp_prefix, plt_offset);
2728                 
2729                                                 /* Nullify the patch */
2730                                                 patch_info->type = MONO_PATCH_INFO_NONE;
2731                                         }
2732                                 }
2733
2734                                 if (direct_call) {
2735                                         int call_size;
2736
2737                                         arch_emit_direct_call (acfg, direct_call_target, &call_size);
2738                                         i += call_size - 1;
2739                                 } else {
2740                                         int code_size;
2741
2742                                         got_slot = get_got_offset (acfg, patch_info);
2743
2744                                         arch_emit_got_access (acfg, code + i, got_slot, &code_size);
2745                                         i += code_size - 1;
2746                                 }
2747                                 skip = TRUE;
2748                         }
2749                         }
2750                 }
2751 #endif /* MONO_ARCH_AOT_SUPPORTED */
2752
2753                 if (!skip) {
2754                         /* Find next patch */
2755                         patch_info = NULL;
2756                         for (pindex = start_index; pindex < patches->len; ++pindex) {
2757                                 patch_info = g_ptr_array_index (patches, pindex);
2758                                 if (patch_info->ip.i >= i)
2759                                         break;
2760                         }
2761
2762                         /* Try to emit multiple bytes at once */
2763                         if (pindex < patches->len && patch_info->ip.i > i) {
2764                                 emit_bytes (acfg, code + i, patch_info->ip.i - i);
2765                                 i = patch_info->ip.i - 1;
2766                         } else {
2767                                 emit_bytes (acfg, code + i, 1);
2768                         }
2769                 }
2770         }
2771 }
2772
2773 /*
2774  * sanitize_symbol:
2775  *
2776  *   Modify SYMBOL so it only includes characters permissible in symbols.
2777  */
2778 static void
2779 sanitize_symbol (char *symbol)
2780 {
2781         int i, len = strlen (symbol);
2782
2783         for (i = 0; i < len; ++i)
2784                 if (!isalnum (symbol [i]) && (symbol [i] != '_'))
2785                         symbol [i] = '_';
2786 }
2787
2788 static char*
2789 get_debug_sym (MonoMethod *method, const char *prefix, GHashTable *cache)
2790 {
2791         char *name1, *name2, *cached;
2792         int i, j, len, count;
2793                 
2794         name1 = mono_method_full_name (method, TRUE);
2795         len = strlen (name1);
2796         name2 = malloc (strlen (prefix) + len + 16);
2797         memcpy (name2, prefix, strlen (prefix));
2798         j = strlen (prefix);
2799         for (i = 0; i < len; ++i) {
2800                 if (isalnum (name1 [i])) {
2801                         name2 [j ++] = name1 [i];
2802                 } else if (name1 [i] == ' ' && name1 [i + 1] == '(' && name1 [i + 2] == ')') {
2803                         i += 2;
2804                 } else if (name1 [i] == ',' && name1 [i + 1] == ' ') {
2805                         name2 [j ++] = '_';
2806                         i++;
2807                 } else if (name1 [i] == '(' || name1 [i] == ')' || name1 [i] == '>') {
2808                 } else
2809                         name2 [j ++] = '_';
2810         }
2811         name2 [j] = '\0';
2812
2813         g_free (name1);
2814
2815         count = 0;
2816         while (g_hash_table_lookup (cache, name2)) {
2817                 sprintf (name2 + j, "_%d", count);
2818                 count ++;
2819         }
2820
2821         cached = g_strdup (name2);
2822         g_hash_table_insert (cache, cached, cached);
2823
2824         return name2;
2825 }
2826
2827 static void
2828 emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg)
2829 {
2830         MonoMethod *method;
2831         int method_index;
2832         guint8 *code;
2833         char *debug_sym = NULL;
2834         char symbol [128];
2835         int func_alignment = AOT_FUNC_ALIGNMENT;
2836         MonoMethodHeader *header;
2837
2838         method = cfg->orig_method;
2839         code = cfg->native_code;
2840         header = mono_method_get_header (method);
2841
2842         method_index = get_method_index (acfg, method);
2843
2844         /* Emit unbox trampoline */
2845         if (acfg->aot_opts.full_aot && cfg->orig_method->klass->valuetype && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
2846                 char call_target [256];
2847
2848                 if (!method->wrapper_type && !method->is_inflated) {
2849                         g_assert (method->token);
2850                         sprintf (symbol, "ut_%d", mono_metadata_token_index (method->token) - 1);
2851                 } else {
2852                         sprintf (symbol, "ut_e_%d", get_method_index (acfg, method));
2853                 }
2854
2855                 emit_section_change (acfg, ".text", 0);
2856                 emit_global (acfg, symbol, TRUE);
2857                 emit_label (acfg, symbol);
2858
2859                 sprintf (call_target, "%s", cfg->asm_symbol);
2860
2861                 arch_emit_unbox_trampoline (acfg, cfg->orig_method, cfg->generic_sharing_context, call_target);
2862         }
2863
2864         /* Make the labels local */
2865         sprintf (symbol, "%s", cfg->asm_symbol);
2866
2867         emit_section_change (acfg, ".text", 0);
2868         emit_alignment (acfg, func_alignment);
2869         emit_label (acfg, symbol);
2870
2871         if (acfg->aot_opts.write_symbols) {
2872                 /* 
2873                  * Write a C style symbol for every method, this has two uses:
2874                  * - it works on platforms where the dwarf debugging info is not
2875                  *   yet supported.
2876                  * - it allows the setting of breakpoints of aot-ed methods.
2877                  */
2878                 debug_sym = get_debug_sym (method, "", acfg->method_label_hash);
2879
2880                 sprintf (symbol, "%sme_%x", acfg->temp_prefix, method_index);
2881                 emit_local_symbol (acfg, debug_sym, symbol, TRUE);
2882                 emit_label (acfg, debug_sym);
2883         }
2884
2885         if (cfg->verbose_level > 0)
2886                 g_print ("Method %s emitted as %s\n", mono_method_full_name (method, TRUE), symbol);
2887
2888         acfg->stats.code_size += cfg->code_len;
2889
2890         acfg->cfgs [method_index]->got_offset = acfg->got_offset;
2891
2892         emit_and_reloc_code (acfg, method, code, cfg->code_len, cfg->patch_info, FALSE);
2893
2894         emit_line (acfg);
2895
2896         if (acfg->aot_opts.write_symbols) {
2897                 emit_symbol_size (acfg, debug_sym, ".");
2898                 g_free (debug_sym);
2899         }
2900
2901         sprintf (symbol, "%sme_%x", acfg->temp_prefix, method_index);
2902         emit_label (acfg, symbol);
2903 }
2904
2905 /**
2906  * encode_patch:
2907  *
2908  *  Encode PATCH_INFO into its disk representation.
2909  */
2910 static void
2911 encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint8 **endbuf)
2912 {
2913         guint8 *p = buf;
2914
2915         switch (patch_info->type) {
2916         case MONO_PATCH_INFO_NONE:
2917                 break;
2918         case MONO_PATCH_INFO_IMAGE:
2919                 encode_value (get_image_index (acfg, patch_info->data.image), p, &p);
2920                 break;
2921         case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
2922                 break;
2923         case MONO_PATCH_INFO_METHOD_REL:
2924                 encode_value ((gint)patch_info->data.offset, p, &p);
2925                 break;
2926         case MONO_PATCH_INFO_SWITCH: {
2927                 gpointer *table = (gpointer *)patch_info->data.table->table;
2928                 int k;
2929
2930                 encode_value (patch_info->data.table->table_size, p, &p);
2931                 for (k = 0; k < patch_info->data.table->table_size; k++)
2932                         encode_value ((int)(gssize)table [k], p, &p);
2933                 break;
2934         }
2935         case MONO_PATCH_INFO_METHODCONST:
2936         case MONO_PATCH_INFO_METHOD:
2937         case MONO_PATCH_INFO_METHOD_JUMP:
2938         case MONO_PATCH_INFO_ICALL_ADDR:
2939         case MONO_PATCH_INFO_METHOD_RGCTX:
2940                 encode_method_ref (acfg, patch_info->data.method, p, &p);
2941                 break;
2942         case MONO_PATCH_INFO_INTERNAL_METHOD:
2943         case MONO_PATCH_INFO_JIT_ICALL_ADDR: {
2944                 guint32 len = strlen (patch_info->data.name);
2945
2946                 encode_value (len, p, &p);
2947
2948                 memcpy (p, patch_info->data.name, len);
2949                 p += len;
2950                 *p++ = '\0';
2951                 break;
2952         }
2953         case MONO_PATCH_INFO_LDSTR: {
2954                 guint32 image_index = get_image_index (acfg, patch_info->data.token->image);
2955                 guint32 token = patch_info->data.token->token;
2956                 g_assert (mono_metadata_token_code (token) == MONO_TOKEN_STRING);
2957                 encode_value (image_index, p, &p);
2958                 encode_value (patch_info->data.token->token - MONO_TOKEN_STRING, p, &p);
2959                 break;
2960         }
2961         case MONO_PATCH_INFO_RVA:
2962         case MONO_PATCH_INFO_DECLSEC:
2963         case MONO_PATCH_INFO_LDTOKEN:
2964         case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
2965                 encode_value (get_image_index (acfg, patch_info->data.token->image), p, &p);
2966                 encode_value (patch_info->data.token->token, p, &p);
2967                 encode_value (patch_info->data.token->has_context, p, &p);
2968                 if (patch_info->data.token->has_context)
2969                         encode_generic_context (acfg, &patch_info->data.token->context, p, &p);
2970                 break;
2971         case MONO_PATCH_INFO_EXC_NAME: {
2972                 MonoClass *ex_class;
2973
2974                 ex_class =
2975                         mono_class_from_name (mono_defaults.exception_class->image,
2976                                                                   "System", patch_info->data.target);
2977                 g_assert (ex_class);
2978                 encode_klass_ref (acfg, ex_class, p, &p);
2979                 break;
2980         }
2981         case MONO_PATCH_INFO_R4:
2982                 encode_value (*((guint32 *)patch_info->data.target), p, &p);
2983                 break;
2984         case MONO_PATCH_INFO_R8:
2985                 encode_value (((guint32 *)patch_info->data.target) [MINI_LS_WORD_IDX], p, &p);
2986                 encode_value (((guint32 *)patch_info->data.target) [MINI_MS_WORD_IDX], p, &p);
2987                 break;
2988         case MONO_PATCH_INFO_VTABLE:
2989         case MONO_PATCH_INFO_CLASS:
2990         case MONO_PATCH_INFO_IID:
2991         case MONO_PATCH_INFO_ADJUSTED_IID:
2992                 encode_klass_ref (acfg, patch_info->data.klass, p, &p);
2993                 break;
2994         case MONO_PATCH_INFO_CLASS_INIT:
2995         case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
2996                 encode_klass_ref (acfg, patch_info->data.klass, p, &p);
2997                 break;
2998         case MONO_PATCH_INFO_FIELD:
2999         case MONO_PATCH_INFO_SFLDA:
3000                 encode_field_info (acfg, patch_info->data.field, p, &p);
3001                 break;
3002         case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
3003                 break;
3004         case MONO_PATCH_INFO_RGCTX_FETCH: {
3005                 MonoJumpInfoRgctxEntry *entry = patch_info->data.rgctx_entry;
3006
3007                 encode_method_ref (acfg, entry->method, p, &p);
3008                 encode_value (entry->in_mrgctx, p, &p);
3009                 encode_value (entry->info_type, p, &p);
3010                 encode_value (entry->data->type, p, &p);
3011                 encode_patch (acfg, entry->data, p, &p);
3012                 break;
3013         }
3014         case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
3015         case MONO_PATCH_INFO_MONITOR_ENTER:
3016         case MONO_PATCH_INFO_MONITOR_EXIT:
3017         case MONO_PATCH_INFO_SEQ_POINT_INFO:
3018                 break;
3019         case MONO_PATCH_INFO_LLVM_IMT_TRAMPOLINE:
3020                 encode_method_ref (acfg, patch_info->data.imt_tramp->method, p, &p);
3021                 encode_value (patch_info->data.imt_tramp->vt_offset, p, &p);
3022                 break;
3023         default:
3024                 g_warning ("unable to handle jump info %d", patch_info->type);
3025                 g_assert_not_reached ();
3026         }
3027
3028         *endbuf = p;
3029 }
3030
3031 static void
3032 encode_patch_list (MonoAotCompile *acfg, GPtrArray *patches, int n_patches, int first_got_offset, guint8 *buf, guint8 **endbuf)
3033 {
3034         guint8 *p = buf;
3035         guint32 pindex, offset;
3036         MonoJumpInfo *patch_info;
3037
3038         encode_value (n_patches, p, &p);
3039
3040         for (pindex = 0; pindex < patches->len; ++pindex) {
3041                 patch_info = g_ptr_array_index (patches, pindex);
3042
3043                 if (patch_info->type == MONO_PATCH_INFO_NONE || patch_info->type == MONO_PATCH_INFO_BB)
3044                         /* Nothing to do */
3045                         continue;
3046
3047                 offset = get_got_offset (acfg, patch_info);
3048                 encode_value (offset, p, &p);
3049         }
3050
3051         *endbuf = p;
3052 }
3053
3054 static void
3055 emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
3056 {
3057         MonoMethod *method;
3058         GList *l;
3059         int pindex, buf_size, n_patches;
3060         guint8 *code;
3061         GPtrArray *patches;
3062         MonoJumpInfo *patch_info;
3063         MonoMethodHeader *header;
3064         guint32 method_index;
3065         guint8 *p, *buf;
3066         guint32 first_got_offset;
3067
3068         method = cfg->orig_method;
3069         code = cfg->native_code;
3070         header = mono_method_get_header (method);
3071
3072         method_index = get_method_index (acfg, method);
3073
3074         /* Sort relocations */
3075         patches = g_ptr_array_new ();
3076         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next)
3077                 g_ptr_array_add (patches, patch_info);
3078         g_ptr_array_sort (patches, compare_patches);
3079
3080         first_got_offset = acfg->cfgs [method_index]->got_offset;
3081
3082         /**********************/
3083         /* Encode method info */
3084         /**********************/
3085
3086         buf_size = (patches->len < 1000) ? 40960 : 40960 + (patches->len * 64);
3087         p = buf = g_malloc (buf_size);
3088
3089         if (mono_class_get_cctor (method->klass))
3090                 encode_klass_ref (acfg, method->klass, p, &p);
3091         else
3092                 /* Not needed when loading the method */
3093                 encode_value (0, p, &p);
3094
3095         /* String table */
3096         if (cfg->opt & MONO_OPT_SHARED) {
3097                 encode_value (g_list_length (cfg->ldstr_list), p, &p);
3098                 for (l = cfg->ldstr_list; l; l = l->next) {
3099                         encode_value ((long)l->data, p, &p);
3100                 }
3101         }
3102         else
3103                 /* Used only in shared mode */
3104                 g_assert (!cfg->ldstr_list);
3105
3106         n_patches = 0;
3107         for (pindex = 0; pindex < patches->len; ++pindex) {
3108                 patch_info = g_ptr_array_index (patches, pindex);
3109                 
3110                 if ((patch_info->type == MONO_PATCH_INFO_GOT_OFFSET) ||
3111                         (patch_info->type == MONO_PATCH_INFO_NONE)) {
3112                         patch_info->type = MONO_PATCH_INFO_NONE;
3113                         /* Nothing to do */
3114                         continue;
3115                 }
3116
3117                 if ((patch_info->type == MONO_PATCH_INFO_IMAGE) && (patch_info->data.image == acfg->image)) {
3118                         /* Stored in a GOT slot initialized at module load time */
3119                         patch_info->type = MONO_PATCH_INFO_NONE;
3120                         continue;
3121                 }
3122
3123                 if (is_plt_patch (patch_info)) {
3124                         /* Calls are made through the PLT */
3125                         patch_info->type = MONO_PATCH_INFO_NONE;
3126                         continue;
3127                 }
3128
3129                 n_patches ++;
3130         }
3131
3132         if (n_patches)
3133                 g_assert (cfg->has_got_slots);
3134
3135         encode_patch_list (acfg, patches, n_patches, first_got_offset, p, &p);
3136
3137         acfg->stats.info_size += p - buf;
3138
3139         g_assert (p - buf < buf_size);
3140
3141         cfg->method_info_offset = add_to_blob (acfg, buf, p - buf);
3142         g_free (buf);
3143 }
3144
3145 static guint32
3146 get_unwind_info_offset (MonoAotCompile *acfg, guint8 *encoded, guint32 encoded_len)
3147 {
3148         guint32 cache_index;
3149         guint32 offset;
3150
3151         /* Reuse the unwind module to canonize and store unwind info entries */
3152         cache_index = mono_cache_unwind_info (encoded, encoded_len);
3153
3154         /* Use +/- 1 to distinguish 0s from missing entries */
3155         offset = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->unwind_info_offsets, GUINT_TO_POINTER (cache_index + 1)));
3156         if (offset)
3157                 return offset - 1;
3158         else {
3159                 guint8 buf [16];
3160                 guint8 *p;
3161
3162                 /* 
3163                  * It would be easier to use assembler symbols, but the caller needs an
3164                  * offset now.
3165                  */
3166                 offset = acfg->unwind_info_offset;
3167                 g_hash_table_insert (acfg->unwind_info_offsets, GUINT_TO_POINTER (cache_index + 1), GUINT_TO_POINTER (offset + 1));
3168                 g_ptr_array_add (acfg->unwind_ops, GUINT_TO_POINTER (cache_index));
3169
3170                 p = buf;
3171                 encode_value (encoded_len, p, &p);
3172
3173                 acfg->unwind_info_offset += encoded_len + (p - buf);
3174                 return offset;
3175         }
3176 }
3177
3178 static void
3179 emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
3180 {
3181         MonoMethod *method;
3182         int i, k, buf_size, method_index;
3183         guint32 debug_info_size;
3184         guint8 *code;
3185         MonoMethodHeader *header;
3186         guint8 *p, *buf, *debug_info;
3187         MonoJitInfo *jinfo = cfg->jit_info;
3188         guint32 flags;
3189         gboolean use_unwind_ops = FALSE;
3190         MonoSeqPointInfo *seq_points;
3191
3192         method = cfg->orig_method;
3193         code = cfg->native_code;
3194         header = mono_method_get_header (method);
3195
3196         method_index = get_method_index (acfg, method);
3197
3198         if (!acfg->aot_opts.nodebug) {
3199                 mono_debug_serialize_debug_info (cfg, &debug_info, &debug_info_size);
3200         } else {
3201                 debug_info = NULL;
3202                 debug_info_size = 0;
3203         }
3204
3205         seq_points = cfg->seq_point_info;
3206
3207         buf_size = header->num_clauses * 256 + debug_info_size + 1024 + (seq_points ? (seq_points->len * 64) : 0);
3208         p = buf = g_malloc (buf_size);
3209
3210 #ifdef MONO_ARCH_HAVE_XP_UNWIND
3211         use_unwind_ops = cfg->unwind_ops != NULL;
3212 #endif
3213
3214         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);
3215
3216         encode_value (flags, p, &p);
3217
3218         if (use_unwind_ops) {
3219                 guint32 encoded_len;
3220                 guint8 *encoded;
3221
3222                 /* 
3223                  * This is a duplicate of the data in the .debug_frame section, but that
3224                  * section cannot be accessed using the dl interface.
3225                  */
3226                 encoded = mono_unwind_ops_encode (cfg->unwind_ops, &encoded_len);
3227                 encode_value (get_unwind_info_offset (acfg, encoded, encoded_len), p, &p);
3228                 g_free (encoded);
3229         } else {
3230                 encode_value (jinfo->used_regs, p, &p);
3231         }
3232
3233         /* Exception table */
3234         if (jinfo->num_clauses)
3235                 encode_value (jinfo->num_clauses, p, &p);
3236
3237         for (k = 0; k < jinfo->num_clauses; ++k) {
3238                 MonoJitExceptionInfo *ei = &jinfo->clauses [k];
3239
3240                 encode_value (ei->flags, p, &p);
3241                 encode_value (ei->exvar_offset, p, &p);
3242
3243                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
3244                         encode_value ((gint)((guint8*)ei->data.filter - code), p, &p);
3245                 else {
3246                         if (ei->data.catch_class) {
3247                                 encode_value (1, p, &p);
3248                                 encode_klass_ref (acfg, ei->data.catch_class, p, &p);
3249                         } else {
3250                                 encode_value (0, p, &p);
3251                         }
3252                 }
3253
3254                 encode_value ((gint)((guint8*)ei->try_start - code), p, &p);
3255                 encode_value ((gint)((guint8*)ei->try_end - code), p, &p);
3256                 encode_value ((gint)((guint8*)ei->handler_start - code), p, &p);
3257         }
3258
3259         if (jinfo->has_generic_jit_info) {
3260                 MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (jinfo);
3261
3262                 encode_value (gi->has_this ? 1 : 0, p, &p);
3263                 encode_value (gi->this_reg, p, &p);
3264                 encode_value (gi->this_offset, p, &p);
3265
3266                 /* 
3267                  * Need to encode jinfo->method too, since it is not equal to 'method'
3268                  * when using generic sharing.
3269                  */
3270                 encode_method_ref (acfg, jinfo->method, p, &p);
3271         }
3272
3273         if (seq_points) {
3274                 int il_offset, native_offset, last_il_offset, last_native_offset, j;
3275
3276                 encode_value (seq_points->len, p, &p);
3277                 last_il_offset = last_native_offset = 0;
3278                 for (i = 0; i < seq_points->len; ++i) {
3279                         SeqPoint *sp = &seq_points->seq_points [i];
3280                         il_offset = sp->il_offset;
3281                         native_offset = sp->native_offset;
3282                         encode_value (il_offset - last_il_offset, p, &p);
3283                         encode_value (native_offset - last_native_offset, p, &p);
3284                         last_il_offset = il_offset;
3285                         last_native_offset = native_offset;
3286
3287                         encode_value (sp->next_len, p, &p);
3288                         for (j = 0; j < sp->next_len; ++j)
3289                                 encode_value (sp->next [j], p, &p);
3290                 }
3291         }
3292                 
3293
3294         g_assert (debug_info_size < buf_size);
3295
3296         encode_value (debug_info_size, p, &p);
3297         if (debug_info_size) {
3298                 memcpy (p, debug_info, debug_info_size);
3299                 p += debug_info_size;
3300                 g_free (debug_info);
3301         }
3302
3303         acfg->stats.ex_info_size += p - buf;
3304
3305         g_assert (p - buf < buf_size);
3306
3307         /* Emit info */
3308         cfg->ex_info_offset = add_to_blob (acfg, buf, p - buf);
3309         g_free (buf);
3310 }
3311
3312 static guint32
3313 emit_klass_info (MonoAotCompile *acfg, guint32 token)
3314 {
3315         MonoClass *klass = mono_class_get (acfg->image, token);
3316         guint8 *p, *buf;
3317         int i, buf_size, res;
3318         gboolean no_special_static, cant_encode;
3319         gpointer iter = NULL;
3320
3321         buf_size = 10240 + (klass->vtable_size * 16);
3322         p = buf = g_malloc (buf_size);
3323
3324         g_assert (klass);
3325
3326         mono_class_init (klass);
3327
3328         mono_class_get_nested_types (klass, &iter);
3329         g_assert (klass->nested_classes_inited);
3330
3331         mono_class_setup_vtable (klass);
3332
3333         /* 
3334          * Emit all the information which is required for creating vtables so
3335          * the runtime does not need to create the MonoMethod structures which
3336          * take up a lot of space.
3337          */
3338
3339         no_special_static = !mono_class_has_special_static_fields (klass);
3340
3341         /* Check whenever we have enough info to encode the vtable */
3342         cant_encode = FALSE;
3343         for (i = 0; i < klass->vtable_size; ++i) {
3344                 MonoMethod *cm = klass->vtable [i];
3345
3346                 if (cm && mono_method_signature (cm)->is_inflated && !g_hash_table_lookup (acfg->token_info_hash, cm))
3347                         cant_encode = TRUE;
3348         }
3349
3350         if (klass->generic_container || cant_encode) {
3351                 encode_value (-1, p, &p);
3352         } else {
3353                 encode_value (klass->vtable_size, p, &p);
3354                 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);
3355                 if (klass->has_cctor)
3356                         encode_method_ref (acfg, mono_class_get_cctor (klass), p, &p);
3357                 if (klass->has_finalize)
3358                         encode_method_ref (acfg, mono_class_get_finalizer (klass), p, &p);
3359  
3360                 encode_value (klass->instance_size, p, &p);
3361                 encode_value (mono_class_data_size (klass), p, &p);
3362                 encode_value (klass->packing_size, p, &p);
3363                 encode_value (klass->min_align, p, &p);
3364
3365                 for (i = 0; i < klass->vtable_size; ++i) {
3366                         MonoMethod *cm = klass->vtable [i];
3367
3368                         if (cm)
3369                                 encode_method_ref (acfg, cm, p, &p);
3370                         else
3371                                 encode_value (0, p, &p);
3372                 }
3373         }
3374
3375         acfg->stats.class_info_size += p - buf;
3376
3377         g_assert (p - buf < buf_size);
3378         res = add_to_blob (acfg, buf, p - buf);
3379         g_free (buf);
3380
3381         return res;
3382 }
3383
3384 /*
3385  * Calls made from AOTed code are routed through a table of jumps similar to the
3386  * ELF PLT (Program Linkage Table). The differences are the following:
3387  * - the ELF PLT entries make an indirect jump though the GOT so they expect the
3388  *   GOT pointer to be in EBX. We want to avoid this, so our table contains direct
3389  *   jumps. This means the jumps need to be patched when the address of the callee is
3390  *   known. Initially the PLT entries jump to code which transfers control to the
3391  *   AOT runtime through the first PLT entry.
3392  */
3393 static void
3394 emit_plt (MonoAotCompile *acfg)
3395 {
3396         char symbol [128];
3397         int i;
3398         GHashTable *cache;
3399
3400         cache = g_hash_table_new (g_str_hash, g_str_equal);
3401
3402         emit_line (acfg);
3403         sprintf (symbol, "plt");
3404
3405         emit_section_change (acfg, ".text", 0);
3406         emit_global (acfg, symbol, TRUE);
3407 #ifdef TARGET_X86
3408         /* This section will be made read-write by the AOT loader */
3409         emit_alignment (acfg, mono_pagesize ());
3410 #else
3411         emit_alignment (acfg, 16);
3412 #endif
3413         emit_label (acfg, symbol);
3414         emit_label (acfg, acfg->plt_symbol);
3415
3416         for (i = 0; i < acfg->plt_offset; ++i) {
3417                 char label [128];
3418                 char *debug_sym = NULL;
3419                 MonoJumpInfo *ji;
3420
3421                 sprintf (label, "%s%sp_%d", acfg->llvm_label_prefix, acfg->temp_prefix, i);
3422
3423                 if (acfg->llvm) {
3424                         /*
3425                          * If the target is directly callable, alias the plt symbol to point to
3426                          * the method code.
3427                          * FIXME: Use this to simplify emit_and_reloc_code ().
3428                          * FIXME: Avoid the got slot.
3429                          * FIXME: Add support to the binary writer.
3430                          */
3431                         ji = g_hash_table_lookup (acfg->plt_offset_to_patch, GUINT_TO_POINTER (i));
3432                         if (ji && is_direct_callable (acfg, NULL, ji) && !acfg->use_bin_writer) {
3433                                 MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, ji->data.method);
3434                                 fprintf (acfg->fp, "\n.set %s, %s\n", label, callee_cfg->asm_symbol);
3435                                 continue;
3436                         }
3437                 }
3438
3439                 emit_label (acfg, label);
3440
3441                 if (acfg->aot_opts.write_symbols) {
3442                         MonoJumpInfo *ji = g_hash_table_lookup (acfg->plt_offset_to_patch, GUINT_TO_POINTER (i));
3443
3444                         if (ji) {
3445                                 switch (ji->type) {
3446                                 case MONO_PATCH_INFO_METHOD:
3447                                         debug_sym = get_debug_sym (ji->data.method, "plt_", cache);
3448                                         break;
3449                                 case MONO_PATCH_INFO_INTERNAL_METHOD:
3450                                         debug_sym = g_strdup_printf ("plt__jit_icall_%s", ji->data.name);
3451                                         break;
3452                                 case MONO_PATCH_INFO_CLASS_INIT:
3453                                         debug_sym = g_strdup_printf ("plt__class_init_%s", mono_type_get_name (&ji->data.klass->byval_arg));
3454                                         sanitize_symbol (debug_sym);
3455                                         break;
3456                                 case MONO_PATCH_INFO_RGCTX_FETCH:
3457                                         debug_sym = g_strdup_printf ("plt__rgctx_fetch_%d", acfg->label_generator ++);
3458                                         break;
3459                                 case MONO_PATCH_INFO_ICALL_ADDR: {
3460                                         char *s = get_debug_sym (ji->data.method, "", cache);
3461                                         
3462                                         debug_sym = g_strdup_printf ("plt__icall_native_%s", s);
3463                                         g_free (s);
3464                                         break;
3465                                 }
3466                                 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
3467                                         debug_sym = g_strdup_printf ("plt__jit_icall_native_%s", ji->data.name);
3468                                         break;
3469                                 case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
3470                                         debug_sym = g_strdup_printf ("plt__generic_class_init");
3471                                         break;
3472                                 default:
3473                                         break;
3474                                 }
3475
3476                                 if (debug_sym) {
3477                                         emit_local_symbol (acfg, debug_sym, NULL, TRUE);
3478                                         emit_label (acfg, debug_sym);
3479                                 }
3480                         }
3481                 }
3482
3483                 /* 
3484                  * The first plt entry is used to transfer code to the AOT loader. 
3485                  */
3486                 arch_emit_plt_entry (acfg, i);
3487
3488                 if (debug_sym) {
3489                         emit_symbol_size (acfg, debug_sym, ".");
3490                         g_free (debug_sym);
3491                 }
3492         }
3493
3494         emit_symbol_size (acfg, acfg->plt_symbol, ".");
3495
3496         sprintf (symbol, "plt_end");
3497         emit_global (acfg, symbol, TRUE);
3498         emit_label (acfg, symbol);
3499
3500         g_hash_table_destroy (cache);
3501 }
3502
3503 static G_GNUC_UNUSED void
3504 emit_trampoline (MonoAotCompile *acfg, const char *name, guint8 *code, 
3505                                  guint32 code_size, int got_offset, MonoJumpInfo *ji, GSList *unwind_ops)
3506 {
3507         char start_symbol [256];
3508         char symbol [256];
3509         guint32 buf_size, info_offset;
3510         MonoJumpInfo *patch_info;
3511         guint8 *buf, *p;
3512         GPtrArray *patches;
3513
3514         /* Emit code */
3515
3516         sprintf (start_symbol, "%s", name);
3517
3518         emit_section_change (acfg, ".text", 0);
3519         emit_global (acfg, start_symbol, TRUE);
3520         emit_alignment (acfg, 16);
3521         emit_label (acfg, start_symbol);
3522
3523         sprintf (symbol, "%snamed_%s", acfg->temp_prefix, name);
3524         emit_label (acfg, symbol);
3525
3526         /* 
3527          * The code should access everything through the GOT, so we pass
3528          * TRUE here.
3529          */
3530         emit_and_reloc_code (acfg, NULL, code, code_size, ji, TRUE);
3531
3532         emit_symbol_size (acfg, start_symbol, ".");
3533
3534         /* Emit info */
3535
3536         /* Sort relocations */
3537         patches = g_ptr_array_new ();
3538         for (patch_info = ji; patch_info; patch_info = patch_info->next)
3539                 if (patch_info->type != MONO_PATCH_INFO_NONE)
3540                         g_ptr_array_add (patches, patch_info);
3541         g_ptr_array_sort (patches, compare_patches);
3542
3543         buf_size = patches->len * 128 + 128;
3544         buf = g_malloc (buf_size);
3545         p = buf;
3546
3547         encode_patch_list (acfg, patches, patches->len, got_offset, p, &p);
3548         g_assert (p - buf < buf_size);
3549
3550         sprintf (symbol, "%s_p", name);
3551
3552         info_offset = add_to_blob (acfg, buf, p - buf);
3553
3554         emit_section_change (acfg, ".text", 0);
3555         emit_global (acfg, symbol, FALSE);
3556         emit_label (acfg, symbol);
3557
3558         emit_int32 (acfg, info_offset);
3559
3560         /* Emit debug info */
3561         if (unwind_ops) {
3562                 char symbol2 [256];
3563
3564                 sprintf (symbol, "%s", name);
3565                 sprintf (symbol2, "%snamed_%s", acfg->temp_prefix, name);
3566
3567                 if (acfg->dwarf)
3568                         mono_dwarf_writer_emit_trampoline (acfg->dwarf, symbol, symbol2, NULL, NULL, code_size, unwind_ops);
3569         }
3570 }
3571
3572 static void
3573 emit_trampolines (MonoAotCompile *acfg)
3574 {
3575         char symbol [256];
3576         int i, tramp_got_offset;
3577         MonoAotTrampoline ntype;
3578 #ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
3579         int tramp_type;
3580         guint32 code_size;
3581         MonoJumpInfo *ji;
3582         guint8 *code;
3583         GSList *unwind_ops;
3584 #endif
3585
3586         if (!acfg->aot_opts.full_aot)
3587                 return;
3588         
3589         g_assert (acfg->image->assembly);
3590
3591         /* Currently, we emit most trampolines into the mscorlib AOT image. */
3592         if (strcmp (acfg->image->assembly->aname.name, "mscorlib") == 0) {
3593 #ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
3594                 /*
3595                  * Emit the generic trampolines.
3596                  *
3597                  * We could save some code by treating the generic trampolines as a wrapper
3598                  * method, but that approach has its own complexities, so we choose the simpler
3599                  * method.
3600                  */
3601                 for (tramp_type = 0; tramp_type < MONO_TRAMPOLINE_NUM; ++tramp_type) {
3602                         code = mono_arch_create_trampoline_code_full (tramp_type, &code_size, &ji, &unwind_ops, TRUE);
3603
3604                         /* Emit trampoline code */
3605
3606                         sprintf (symbol, "generic_trampoline_%d", tramp_type);
3607
3608                         emit_trampoline (acfg, symbol, code, code_size, acfg->got_offset, ji, unwind_ops);
3609                 }
3610
3611                 code = mono_arch_get_nullified_class_init_trampoline (&code_size);
3612                 emit_trampoline (acfg, "nullified_class_init_trampoline", code, code_size, acfg->got_offset, NULL, NULL);
3613 #if defined(TARGET_AMD64) && defined(MONO_ARCH_MONITOR_OBJECT_REG)
3614                 code = mono_arch_create_monitor_enter_trampoline_full (&code_size, &ji, TRUE);
3615                 emit_trampoline (acfg, "monitor_enter_trampoline", code, code_size, acfg->got_offset, ji, NULL);
3616                 code = mono_arch_create_monitor_exit_trampoline_full (&code_size, &ji, TRUE);
3617                 emit_trampoline (acfg, "monitor_exit_trampoline", code, code_size, acfg->got_offset, ji, NULL);
3618 #endif
3619
3620                 code = mono_arch_create_generic_class_init_trampoline_full (&code_size, &ji, TRUE);
3621                 emit_trampoline (acfg, "generic_class_init_trampoline", code, code_size, acfg->got_offset, ji, NULL);
3622
3623                 /* Emit the exception related code pieces */
3624                 code = mono_arch_get_restore_context_full (&code_size, &ji, TRUE);
3625                 emit_trampoline (acfg, "restore_context", code, code_size, acfg->got_offset, ji, NULL);
3626                 code = mono_arch_get_call_filter_full (&code_size, &ji, TRUE);
3627                 emit_trampoline (acfg, "call_filter", code, code_size, acfg->got_offset, ji, NULL);
3628                 code = mono_arch_get_throw_exception_full (&code_size, &ji, TRUE);
3629                 emit_trampoline (acfg, "throw_exception", code, code_size, acfg->got_offset, ji, NULL);
3630                 code = mono_arch_get_rethrow_exception_full (&code_size, &ji, TRUE);
3631                 emit_trampoline (acfg, "rethrow_exception", code, code_size, acfg->got_offset, ji, NULL);
3632 #ifdef MONO_ARCH_HAVE_THROW_EXCEPTION_BY_NAME
3633                 code = mono_arch_get_throw_exception_by_name_full (&code_size, &ji, TRUE);
3634                 emit_trampoline (acfg, "throw_exception_by_name", code, code_size, acfg->got_offset, ji, NULL);
3635 #endif
3636                 code = mono_arch_get_throw_corlib_exception_full (&code_size, &ji, TRUE);
3637                 emit_trampoline (acfg, "throw_corlib_exception", code, code_size, acfg->got_offset, ji, NULL);
3638
3639 #if defined(TARGET_AMD64)
3640                 code = mono_arch_get_throw_pending_exception_full (&code_size, &ji, TRUE);
3641                 emit_trampoline (acfg, "throw_pending_exception", code, code_size, acfg->got_offset, ji, NULL);
3642 #endif
3643
3644                 for (i = 0; i < 128; ++i) {
3645                         int offset;
3646
3647                         offset = MONO_RGCTX_SLOT_MAKE_RGCTX (i);
3648                         code = mono_arch_create_rgctx_lazy_fetch_trampoline_full (offset, &code_size, &ji, TRUE);
3649                         sprintf (symbol, "rgctx_fetch_trampoline_%u", offset);
3650                         emit_trampoline (acfg, symbol, code, code_size, acfg->got_offset, ji, NULL);
3651
3652                         offset = MONO_RGCTX_SLOT_MAKE_MRGCTX (i);
3653                         code = mono_arch_create_rgctx_lazy_fetch_trampoline_full (offset, &code_size, &ji, TRUE);
3654                         sprintf (symbol, "rgctx_fetch_trampoline_%u", offset);
3655                         emit_trampoline (acfg, symbol, code, code_size, acfg->got_offset, ji, NULL);
3656                 }
3657
3658                 {
3659                         GSList *l;
3660
3661                         /* delegate_invoke_impl trampolines */
3662                         l = mono_arch_get_delegate_invoke_impls ();
3663                         while (l) {
3664                                 MonoAotTrampInfo *info = l->data;
3665
3666                                 emit_trampoline (acfg, info->name, info->code, info->code_size, acfg->got_offset, NULL, NULL);
3667                                 l = l->next;
3668                         }
3669                 }
3670
3671 #endif /* #ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES */
3672
3673                 /* Emit trampolines which are numerous */
3674
3675                 /*
3676                  * These include the following:
3677                  * - specific trampolines
3678                  * - static rgctx invoke trampolines
3679                  * - imt thunks
3680                  * These trampolines have the same code, they are parameterized by GOT 
3681                  * slots. 
3682                  * They are defined in this file, in the arch_... routines instead of
3683                  * in tramp-<ARCH>.c, since it is easier to do it this way.
3684                  */
3685
3686                 /*
3687                  * When running in aot-only mode, we can't create specific trampolines at 
3688                  * runtime, so we create a few, and save them in the AOT file. 
3689                  * Normal trampolines embed their argument as a literal inside the 
3690                  * trampoline code, we can't do that here, so instead we embed an offset
3691                  * which needs to be added to the trampoline address to get the address of
3692                  * the GOT slot which contains the argument value.
3693                  * The generated trampolines jump to the generic trampolines using another
3694                  * GOT slot, which will be setup by the AOT loader to point to the 
3695                  * generic trampoline code of the given type.
3696                  */
3697
3698                 /*
3699                  * FIXME: Maybe we should use more specific trampolines (i.e. one class init for
3700                  * each class).
3701                  */
3702
3703                 emit_section_change (acfg, ".text", 0);
3704
3705                 tramp_got_offset = acfg->got_offset;
3706
3707                 for (ntype = 0; ntype < MONO_AOT_TRAMP_NUM; ++ntype) {
3708                         switch (ntype) {
3709                         case MONO_AOT_TRAMP_SPECIFIC:
3710                                 sprintf (symbol, "specific_trampolines");
3711                                 break;
3712                         case MONO_AOT_TRAMP_STATIC_RGCTX:
3713                                 sprintf (symbol, "static_rgctx_trampolines");
3714                                 break;
3715                         case MONO_AOT_TRAMP_IMT_THUNK:
3716                                 sprintf (symbol, "imt_thunks");
3717                                 break;
3718                         default:
3719                                 g_assert_not_reached ();
3720                         }
3721
3722                         emit_global (acfg, symbol, TRUE);
3723                         emit_alignment (acfg, 16);
3724                         emit_label (acfg, symbol);
3725
3726                         acfg->trampoline_got_offset_base [ntype] = tramp_got_offset;
3727
3728                         for (i = 0; i < acfg->num_trampolines [ntype]; ++i) {
3729                                 int tramp_size = 0;
3730
3731                                 switch (ntype) {
3732                                 case MONO_AOT_TRAMP_SPECIFIC:
3733                                         arch_emit_specific_trampoline (acfg, tramp_got_offset, &tramp_size);
3734                                         tramp_got_offset += 2;
3735                                 break;
3736                                 case MONO_AOT_TRAMP_STATIC_RGCTX:
3737                                         arch_emit_static_rgctx_trampoline (acfg, tramp_got_offset, &tramp_size);                                
3738                                         tramp_got_offset += 2;
3739                                         break;
3740                                 case MONO_AOT_TRAMP_IMT_THUNK:
3741                                         arch_emit_imt_thunk (acfg, tramp_got_offset, &tramp_size);
3742                                         tramp_got_offset += 1;
3743                                         break;
3744                                 default:
3745                                         g_assert_not_reached ();
3746                                 }
3747
3748                                 if (!acfg->trampoline_size [ntype]) {
3749                                         g_assert (tramp_size);
3750                                         acfg->trampoline_size [ntype] = tramp_size;
3751                                 }
3752                         }
3753                 }
3754
3755                 /* Reserve some entries at the end of the GOT for our use */
3756                 acfg->num_trampoline_got_entries = tramp_got_offset - acfg->got_offset;
3757         }
3758
3759         acfg->got_offset += acfg->num_trampoline_got_entries;
3760 }
3761
3762 static gboolean
3763 str_begins_with (const char *str1, const char *str2)
3764 {
3765         int len = strlen (str2);
3766         return strncmp (str1, str2, len) == 0;
3767 }
3768
3769 static void
3770 mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
3771 {
3772         gchar **args, **ptr;
3773
3774         args = g_strsplit (aot_options ? aot_options : "", ",", -1);
3775         for (ptr = args; ptr && *ptr; ptr ++) {
3776                 const char *arg = *ptr;
3777
3778                 if (str_begins_with (arg, "outfile=")) {
3779                         opts->outfile = g_strdup (arg + strlen ("outfile="));
3780                 } else if (str_begins_with (arg, "save-temps")) {
3781                         opts->save_temps = TRUE;
3782                 } else if (str_begins_with (arg, "keep-temps")) {
3783                         opts->save_temps = TRUE;
3784                 } else if (str_begins_with (arg, "write-symbols")) {
3785                         opts->write_symbols = TRUE;
3786                 } else if (str_begins_with (arg, "metadata-only")) {
3787                         opts->metadata_only = TRUE;
3788                 } else if (str_begins_with (arg, "bind-to-runtime-version")) {
3789                         opts->bind_to_runtime_version = TRUE;
3790                 } else if (str_begins_with (arg, "full")) {
3791                         opts->full_aot = TRUE;
3792                 } else if (str_begins_with (arg, "threads=")) {
3793                         opts->nthreads = atoi (arg + strlen ("threads="));
3794                 } else if (str_begins_with (arg, "static")) {
3795                         opts->static_link = TRUE;
3796                         opts->no_dlsym = TRUE;
3797                 } else if (str_begins_with (arg, "asmonly")) {
3798                         opts->asm_only = TRUE;
3799                 } else if (str_begins_with (arg, "asmwriter")) {
3800                         opts->asm_writer = TRUE;
3801                 } else if (str_begins_with (arg, "nodebug")) {
3802                         opts->nodebug = TRUE;
3803                 } else if (str_begins_with (arg, "ntrampolines=")) {
3804                         opts->ntrampolines = atoi (arg + strlen ("ntrampolines="));
3805                 } else if (str_begins_with (arg, "nrgctx-trampolines=")) {
3806                         opts->nrgctx_trampolines = atoi (arg + strlen ("nrgctx-trampolines="));
3807                 } else if (str_begins_with (arg, "autoreg")) {
3808                         opts->autoreg = TRUE;
3809                 } else if (str_begins_with (arg, "tool-prefix=")) {
3810                         opts->tool_prefix = g_strdup (arg + strlen ("tool-prefix="));
3811                 } else if (str_begins_with (arg, "soft-debug")) {
3812                         opts->soft_debug = TRUE;
3813                 } else if (str_begins_with (arg, "print-skipped")) {
3814                         opts->print_skipped_methods = TRUE;
3815                 } else if (str_begins_with (arg, "stats")) {
3816                         opts->stats = TRUE;
3817                 } else {
3818                         fprintf (stderr, "AOT : Unknown argument '%s'.\n", arg);
3819                         exit (1);
3820                 }
3821         }
3822
3823         g_strfreev (args);
3824 }
3825
3826 static void
3827 add_token_info_hash (gpointer key, gpointer value, gpointer user_data)
3828 {
3829         MonoMethod *method = (MonoMethod*)key;
3830         MonoJumpInfoToken *ji = (MonoJumpInfoToken*)value;
3831         MonoJumpInfoToken *new_ji = g_new0 (MonoJumpInfoToken, 1);
3832         MonoAotCompile *acfg = user_data;
3833
3834         new_ji->image = ji->image;
3835         new_ji->token = ji->token;
3836         g_hash_table_insert (acfg->token_info_hash, method, new_ji);
3837 }
3838
3839 static gboolean
3840 can_encode_class (MonoAotCompile *acfg, MonoClass *klass)
3841 {
3842         if (klass->type_token)
3843                 return TRUE;
3844         if ((klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
3845                 return TRUE;
3846         if (klass->rank)
3847                 return can_encode_class (acfg, klass->element_class);
3848         return FALSE;
3849 }
3850
3851 static gboolean
3852 can_encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
3853 {
3854         switch (patch_info->type) {
3855         case MONO_PATCH_INFO_METHOD:
3856         case MONO_PATCH_INFO_METHODCONST: {
3857                 MonoMethod *method = patch_info->data.method;
3858
3859                 if (method->wrapper_type) {
3860                         switch (method->wrapper_type) {
3861                         case MONO_WRAPPER_NONE:
3862                         case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
3863                         case MONO_WRAPPER_XDOMAIN_INVOKE:
3864                         case MONO_WRAPPER_STFLD:
3865                         case MONO_WRAPPER_LDFLD:
3866                         case MONO_WRAPPER_LDFLDA:
3867                         case MONO_WRAPPER_LDFLD_REMOTE:
3868                         case MONO_WRAPPER_STFLD_REMOTE:
3869                         case MONO_WRAPPER_STELEMREF:
3870                         case MONO_WRAPPER_ISINST:
3871                         case MONO_WRAPPER_PROXY_ISINST:
3872                         case MONO_WRAPPER_ALLOC:
3873                         case MONO_WRAPPER_REMOTING_INVOKE:
3874                         case MONO_WRAPPER_UNKNOWN:
3875                                 break;
3876                         case MONO_WRAPPER_MANAGED_TO_MANAGED:
3877                                 if (!strcmp (method->name, "ElementAddr"))
3878                                         return TRUE;
3879                                 else
3880                                         return FALSE;
3881                         default:
3882                                 //printf ("Skip (wrapper call): %d -> %s\n", patch_info->type, mono_method_full_name (patch_info->data.method, TRUE));
3883                                 return FALSE;
3884                         }
3885                 } else {
3886                         if (!method->token) {
3887                                 /* The method is part of a constructed type like Int[,].Set (). */
3888                                 if (!g_hash_table_lookup (acfg->token_info_hash, method)) {
3889                                         if (method->klass->rank)
3890                                                 return TRUE;
3891                                         return FALSE;
3892                                 }
3893                         }
3894                 }
3895                 break;
3896         }
3897         case MONO_PATCH_INFO_VTABLE:
3898         case MONO_PATCH_INFO_CLASS_INIT:
3899         case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
3900         case MONO_PATCH_INFO_CLASS:
3901         case MONO_PATCH_INFO_IID:
3902         case MONO_PATCH_INFO_ADJUSTED_IID:
3903                 if (!can_encode_class (acfg, patch_info->data.klass)) {
3904                         //printf ("Skip: %s\n", mono_type_full_name (&patch_info->data.klass->byval_arg));
3905                         return FALSE;
3906                 }
3907                 break;
3908         case MONO_PATCH_INFO_RGCTX_FETCH: {
3909                 MonoJumpInfoRgctxEntry *entry = patch_info->data.rgctx_entry;
3910
3911                 if (!can_encode_patch (acfg, entry->data))
3912                         return FALSE;
3913                 break;
3914         }
3915         default:
3916                 break;
3917         }
3918
3919         return TRUE;
3920 }
3921
3922 static void
3923 add_generic_class (MonoAotCompile *acfg, MonoClass *klass);
3924
3925 /*
3926  * compile_method:
3927  *
3928  *   AOT compile a given method.
3929  * This function might be called by multiple threads, so it must be thread-safe.
3930  */
3931 static void
3932 compile_method (MonoAotCompile *acfg, MonoMethod *method)
3933 {
3934         MonoCompile *cfg;
3935         MonoJumpInfo *patch_info;
3936         gboolean skip;
3937         int index, depth;
3938         MonoMethod *wrapped;
3939
3940         if (acfg->aot_opts.metadata_only)
3941                 return;
3942
3943         mono_acfg_lock (acfg);
3944         index = get_method_index (acfg, method);
3945         mono_acfg_unlock (acfg);
3946
3947         /* fixme: maybe we can also precompile wrapper methods */
3948         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
3949                 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
3950                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT)) {
3951                 //printf ("Skip (impossible): %s\n", mono_method_full_name (method, TRUE));
3952                 return;
3953         }
3954
3955         if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
3956                 return;
3957
3958         wrapped = mono_marshal_method_from_wrapper (method);
3959         if (wrapped && (wrapped->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && wrapped->is_generic)
3960                 // FIXME: The wrapper should be generic too, but it is not
3961                 return;
3962
3963         InterlockedIncrement (&acfg->stats.mcount);
3964
3965 #if 0
3966         if (method->is_generic || method->klass->generic_container) {
3967                 InterlockedIncrement (&acfg->stats.genericcount);
3968                 return;
3969         }
3970 #endif
3971
3972         //acfg->aot_opts.print_skipped_methods = TRUE;
3973
3974         /*
3975          * Since these methods are the only ones which are compiled with
3976          * AOT support, and they are not used by runtime startup/shutdown code,
3977          * the runtime will not see AOT methods during AOT compilation,so it
3978          * does not need to support them by creating a fake GOT etc.
3979          */
3980         cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), FALSE, TRUE, 0);
3981         if (cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) {
3982                 //printf ("F: %s\n", mono_method_full_name (method, TRUE));
3983                 InterlockedIncrement (&acfg->stats.genericcount);
3984                 return;
3985         }
3986         if (cfg->exception_type != MONO_EXCEPTION_NONE) {
3987                 /* Let the exception happen at runtime */
3988                 return;
3989         }
3990
3991         if (cfg->disable_aot) {
3992                 if (acfg->aot_opts.print_skipped_methods)
3993                         printf ("Skip (disabled): %s\n", mono_method_full_name (method, TRUE));
3994                 InterlockedIncrement (&acfg->stats.ocount);
3995                 mono_destroy_compile (cfg);
3996                 return;
3997         }
3998
3999         /* Nullify patches which need no aot processing */
4000         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
4001                 switch (patch_info->type) {
4002                 case MONO_PATCH_INFO_LABEL:
4003                 case MONO_PATCH_INFO_BB:
4004                         patch_info->type = MONO_PATCH_INFO_NONE;
4005                         break;
4006                 default:
4007                         break;
4008                 }
4009         }
4010
4011         /* Collect method->token associations from the cfg */
4012         mono_acfg_lock (acfg);
4013         g_hash_table_foreach (cfg->token_info_hash, add_token_info_hash, acfg);
4014         mono_acfg_unlock (acfg);
4015
4016         /*
4017          * Check for absolute addresses.
4018          */
4019         skip = FALSE;
4020         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
4021                 switch (patch_info->type) {
4022                 case MONO_PATCH_INFO_ABS:
4023                         /* unable to handle this */
4024                         skip = TRUE;    
4025                         break;
4026                 default:
4027                         break;
4028                 }
4029         }
4030
4031         if (skip) {
4032                 if (acfg->aot_opts.print_skipped_methods)
4033                         printf ("Skip (abs call): %s\n", mono_method_full_name (method, TRUE));
4034                 InterlockedIncrement (&acfg->stats.abscount);
4035                 mono_destroy_compile (cfg);
4036                 return;
4037         }
4038
4039         /* Lock for the rest of the code */
4040         mono_acfg_lock (acfg);
4041
4042         /*
4043          * Check for methods/klasses we can't encode.
4044          */
4045         skip = FALSE;
4046         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
4047                 if (!can_encode_patch (acfg, patch_info))
4048                         skip = TRUE;
4049         }
4050
4051         if (skip) {
4052                 if (acfg->aot_opts.print_skipped_methods)
4053                         printf ("Skip (patches): %s\n", mono_method_full_name (method, TRUE));
4054                 acfg->stats.ocount++;
4055                 mono_destroy_compile (cfg);
4056                 mono_acfg_unlock (acfg);
4057                 return;
4058         }
4059
4060         /* Adds generic instances referenced by this method */
4061         /* 
4062          * The depth is used to avoid infinite loops when generic virtual recursion is 
4063          * encountered.
4064          */
4065         depth = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_depth, method));
4066         if (depth < 32) {
4067                 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
4068                         switch (patch_info->type) {
4069                         case MONO_PATCH_INFO_METHOD: {
4070                                 MonoMethod *m = patch_info->data.method;
4071                                 if (m->is_inflated) {
4072                                         if (!(mono_class_generic_sharing_enabled (m->klass) &&
4073                                                   mono_method_is_generic_sharable_impl (m, FALSE)) &&
4074                                                 !method_has_type_vars (m)) {
4075                                                 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
4076                                                         if (acfg->aot_opts.full_aot)
4077                                                                 add_extra_method_with_depth (acfg, mono_marshal_get_native_wrapper (m, TRUE, TRUE), depth + 1);
4078                                                 } else {
4079                                                         add_extra_method_with_depth (acfg, m, depth + 1);
4080                                                 }
4081                                         }
4082                                         add_generic_class (acfg, m->klass);
4083                                 }
4084                                 if (m->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED && !strcmp (m->name, "ElementAddr"))
4085                                         add_extra_method_with_depth (acfg, m, depth + 1);
4086                                 break;
4087                         }
4088                         case MONO_PATCH_INFO_VTABLE: {
4089                                 MonoClass *klass = patch_info->data.klass;
4090
4091                                 if (klass->generic_class && !mono_generic_context_is_sharable (&klass->generic_class->context, FALSE))
4092                                         add_generic_class (acfg, klass);
4093                                 break;
4094                         }
4095                         default:
4096                                 break;
4097                         }
4098                 }
4099         }
4100
4101         /* Determine whenever the method has GOT slots */
4102         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
4103                 switch (patch_info->type) {
4104                 case MONO_PATCH_INFO_GOT_OFFSET:
4105                 case MONO_PATCH_INFO_NONE:
4106                         break;
4107                 case MONO_PATCH_INFO_IMAGE:
4108                         /* The assembly is stored in GOT slot 0 */
4109                         if (patch_info->data.image != acfg->image)
4110                                 cfg->has_got_slots = TRUE;
4111                         break;
4112                 default:
4113                         if (!is_plt_patch (patch_info))
4114                                 cfg->has_got_slots = TRUE;
4115                         break;
4116                 }
4117         }
4118
4119         if (!cfg->has_got_slots)
4120                 InterlockedIncrement (&acfg->stats.methods_without_got_slots);
4121
4122         /* 
4123          * FIXME: Instead of this mess, allocate the patches from the aot mempool.
4124          */
4125         /* Make a copy of the patch info which is in the mempool */
4126         {
4127                 MonoJumpInfo *patches = NULL, *patches_end = NULL;
4128
4129                 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
4130                         MonoJumpInfo *new_patch_info = mono_patch_info_dup_mp (acfg->mempool, patch_info);
4131
4132                         if (!patches)
4133                                 patches = new_patch_info;
4134                         else
4135                                 patches_end->next = new_patch_info;
4136                         patches_end = new_patch_info;
4137                 }
4138                 cfg->patch_info = patches;
4139         }
4140         /* Make a copy of the unwind info */
4141         {
4142                 GSList *l, *unwind_ops;
4143                 MonoUnwindOp *op;
4144
4145                 unwind_ops = NULL;
4146                 for (l = cfg->unwind_ops; l; l = l->next) {
4147                         op = mono_mempool_alloc (acfg->mempool, sizeof (MonoUnwindOp));
4148                         memcpy (op, l->data, sizeof (MonoUnwindOp));
4149                         unwind_ops = g_slist_prepend_mempool (acfg->mempool, unwind_ops, op);
4150                 }
4151                 cfg->unwind_ops = g_slist_reverse (unwind_ops);
4152         }
4153         /* Make a copy of the argument/local info */
4154         {
4155                 MonoInst **args, **locals;
4156                 MonoMethodSignature *sig;
4157                 MonoMethodHeader *header;
4158                 int i;
4159                 
4160                 sig = mono_method_signature (method);
4161                 args = mono_mempool_alloc (acfg->mempool, sizeof (MonoInst*) * (sig->param_count + sig->hasthis));
4162                 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
4163                         args [i] = mono_mempool_alloc (acfg->mempool, sizeof (MonoInst));
4164                         memcpy (args [i], cfg->args [i], sizeof (MonoInst));
4165                 }
4166                 cfg->args = args;
4167
4168                 header = mono_method_get_header (method);
4169                 locals = mono_mempool_alloc (acfg->mempool, sizeof (MonoInst*) * header->num_locals);
4170                 for (i = 0; i < header->num_locals; ++i) {
4171                         locals [i] = mono_mempool_alloc (acfg->mempool, sizeof (MonoInst));
4172                         memcpy (locals [i], cfg->locals [i], sizeof (MonoInst));
4173                 }
4174                 cfg->locals = locals;
4175         }
4176
4177         /* Free some fields used by cfg to conserve memory */
4178         mono_mempool_destroy (cfg->mempool);
4179         cfg->mempool = NULL;
4180         g_free (cfg->varinfo);
4181         cfg->varinfo = NULL;
4182         g_free (cfg->vars);
4183         cfg->vars = NULL;
4184         if (cfg->rs) {
4185                 mono_regstate_free (cfg->rs);
4186                 cfg->rs = NULL;
4187         }
4188
4189         //printf ("Compile:           %s\n", mono_method_full_name (method, TRUE));
4190
4191         while (index >= acfg->cfgs_size) {
4192                 MonoCompile **new_cfgs;
4193                 int new_size;
4194
4195                 new_size = acfg->cfgs_size * 2;
4196                 new_cfgs = g_new0 (MonoCompile*, new_size);
4197                 memcpy (new_cfgs, acfg->cfgs, sizeof (MonoCompile*) * acfg->cfgs_size);
4198                 g_free (acfg->cfgs);
4199                 acfg->cfgs = new_cfgs;
4200                 acfg->cfgs_size = new_size;
4201         }
4202         acfg->cfgs [index] = cfg;
4203
4204         g_hash_table_insert (acfg->method_to_cfg, cfg->orig_method, cfg);
4205
4206         /*
4207         if (cfg->orig_method->wrapper_type)
4208                 g_ptr_array_add (acfg->extra_methods, cfg->orig_method);
4209         */
4210
4211         mono_acfg_unlock (acfg);
4212
4213         InterlockedIncrement (&acfg->stats.ccount);
4214 }
4215  
4216 static void
4217 compile_thread_main (gpointer *user_data)
4218 {
4219         MonoDomain *domain = user_data [0];
4220         MonoAotCompile *acfg = user_data [1];
4221         GPtrArray *methods = user_data [2];
4222         int i;
4223
4224         mono_thread_attach (domain);
4225
4226         for (i = 0; i < methods->len; ++i)
4227                 compile_method (acfg, g_ptr_array_index (methods, i));
4228 }
4229
4230 static void
4231 load_profile_files (MonoAotCompile *acfg)
4232 {
4233         FILE *infile;
4234         char *tmp;
4235         int file_index, res, method_index, i;
4236         char ver [256];
4237         guint32 token;
4238         GList *unordered;
4239
4240         file_index = 0;
4241         while (TRUE) {
4242                 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);
4243
4244                 if (!g_file_test (tmp, G_FILE_TEST_IS_REGULAR)) {
4245                         g_free (tmp);
4246                         break;
4247                 }
4248
4249                 infile = fopen (tmp, "r");
4250                 g_assert (infile);
4251
4252                 printf ("Using profile data file '%s'\n", tmp);
4253                 g_free (tmp);
4254
4255                 file_index ++;
4256
4257                 res = fscanf (infile, "%32s\n", ver);
4258                 if ((res != 1) || strcmp (ver, "#VER:1") != 0) {
4259                         printf ("Profile file has wrong version or invalid.\n");
4260                         fclose (infile);
4261                         continue;
4262                 }
4263
4264                 while (TRUE) {
4265                         res = fscanf (infile, "%d\n", &token);
4266                         if (res < 1)
4267                                 break;
4268
4269                         method_index = mono_metadata_token_index (token) - 1;
4270
4271                         if (!g_list_find (acfg->method_order, GUINT_TO_POINTER (method_index)))
4272                                 acfg->method_order = g_list_append (acfg->method_order, GUINT_TO_POINTER (method_index));
4273                 }
4274                 fclose (infile);
4275         }
4276
4277         /* Add missing methods */
4278         unordered = NULL;
4279         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
4280                 if (!g_list_find (acfg->method_order, GUINT_TO_POINTER (i)))
4281                         unordered = g_list_prepend (unordered, GUINT_TO_POINTER (i));
4282         }
4283         unordered = g_list_reverse (unordered);
4284         if (acfg->method_order)
4285                 g_list_last (acfg->method_order)->next = unordered;
4286         else
4287                 acfg->method_order = unordered;
4288 }
4289  
4290 /* Used by the LLVM backend */
4291 guint32
4292 mono_aot_get_got_offset (MonoJumpInfo *ji)
4293 {
4294         return get_got_offset (llvm_acfg, ji);
4295 }
4296
4297 char*
4298 mono_aot_get_method_name (MonoCompile *cfg)
4299 {
4300         guint32 method_index = get_method_index (llvm_acfg, cfg->orig_method);
4301
4302         return g_strdup_printf ("m_%x", method_index);
4303 }
4304
4305 char*
4306 mono_aot_get_method_debug_name (MonoCompile *cfg)
4307 {
4308         return get_debug_sym (cfg->orig_method, "", llvm_acfg->method_label_hash);
4309 }
4310
4311 char*
4312 mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data)
4313 {
4314         MonoJumpInfo *ji = mono_mempool_alloc (llvm_acfg->mempool, sizeof (MonoJumpInfo));
4315         int offset;
4316
4317         ji->type = type;
4318         ji->data.target = data;
4319
4320         if (!can_encode_patch (llvm_acfg, ji))
4321                 return NULL;
4322
4323         offset = get_plt_offset (llvm_acfg, ji);
4324
4325         return g_strdup_printf ("%sp_%d", llvm_acfg->temp_prefix, offset);
4326 }
4327
4328 MonoJumpInfo*
4329 mono_aot_patch_info_dup (MonoJumpInfo* ji)
4330 {
4331         MonoJumpInfo *res;
4332
4333         mono_acfg_lock (llvm_acfg);
4334         res = mono_patch_info_dup_mp (llvm_acfg->mempool, ji);
4335         mono_acfg_unlock (llvm_acfg);
4336
4337         return res;
4338 }
4339
4340 #ifdef ENABLE_LLVM
4341
4342 /*
4343  * emit_llvm_file:
4344  *
4345  *   Emit the LLVM code into an LLVM bytecode file, and compile it using the LLVM
4346  * tools.
4347  */
4348 static void
4349 emit_llvm_file (MonoAotCompile *acfg)
4350 {
4351         char *command, *opts;
4352         int i;
4353         MonoJumpInfo *patch_info;
4354         char *llc_target_args;
4355
4356         /*
4357          * When using LLVM, we let llvm emit the got since the LLVM IL needs to refer
4358          * to it.
4359          */
4360
4361         /* Compute the final size of the got */
4362         for (i = 0; i < acfg->nmethods; ++i) {
4363                 if (acfg->cfgs [i]) {
4364                         for (patch_info = acfg->cfgs [i]->patch_info; patch_info; patch_info = patch_info->next) {
4365                                 if (patch_info->type != MONO_PATCH_INFO_NONE) {
4366                                         if (!is_plt_patch (patch_info))
4367                                                 get_got_offset (acfg, patch_info);
4368                                         else
4369                                                 get_plt_offset (acfg, patch_info);
4370                                 }
4371                         }
4372                 }
4373         }
4374
4375         acfg->final_got_size = acfg->got_offset + acfg->plt_offset;
4376
4377         if (acfg->aot_opts.full_aot) {
4378                 int ntype;
4379
4380                 /* 
4381                  * Need to add the got entries used by the trampolines.
4382                  * This is only a conservative approximation.
4383                  */
4384                 if (strcmp (acfg->image->assembly->aname.name, "mscorlib") == 0) {
4385                         /* For the generic + rgctx trampolines */
4386                         acfg->final_got_size += 200;
4387                         /* For the specific trampolines */
4388                         for (ntype = 0; ntype < MONO_AOT_TRAMP_NUM; ++ntype)
4389                                 acfg->final_got_size += acfg->num_trampolines [ntype] * 2;
4390                 }
4391         }
4392
4393
4394         mono_llvm_emit_aot_module ("temp.bc", acfg->final_got_size);
4395
4396         /*
4397          * FIXME: Experiment with adding optimizations, the -std-compile-opts set takes
4398          * a lot of time, and doesn't seem to save much space.
4399          * The following optimizations cannot be enabled:
4400          * - 'tailcallelim'
4401          * The opt list below was produced by taking the output of:
4402          * llvm-as < /dev/null | opt -O2 -disable-output -debug-pass=Arguments
4403          * then removing tailcallelim + the global opts, and adding a second gvn.
4404          */
4405         opts = g_strdup ("-instcombine -simplifycfg");
4406         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");
4407 #if 1
4408         command = g_strdup_printf ("opt -f %s -o temp.opt.bc temp.bc", opts);
4409         printf ("Executing opt: %s\n", command);
4410         if (system (command) != 0) {
4411                 exit (1);
4412         }
4413 #endif
4414         g_free (opts);
4415
4416         llc_target_args = g_strdup (LLC_TARGET_ARGS);
4417
4418         command = g_strdup_printf ("llc %s -f -relocation-model=pic -unwind-tables -o %s temp.opt.bc", llc_target_args, acfg->tmpfname);
4419         g_free (llc_target_args);
4420
4421         printf ("Executing llc: %s\n", command);
4422
4423         if (system (command) != 0) {
4424                 exit (1);
4425         }
4426 }
4427 #endif
4428
4429 static void
4430 emit_code (MonoAotCompile *acfg)
4431 {
4432         int i;
4433         char symbol [256];
4434         char end_symbol [256];
4435         GList *l;
4436
4437 #if defined(TARGET_POWERPC64)
4438         sprintf (symbol, ".Lgot_addr");
4439         emit_section_change (acfg, ".text", 0);
4440         emit_alignment (acfg, 8);
4441         emit_label (acfg, symbol);
4442         emit_pointer (acfg, acfg->got_symbol);
4443 #endif
4444
4445         /* 
4446          * This global symbol is used to compute the address of each method using the
4447          * code_offsets array. It is also used to compute the memory ranges occupied by
4448          * AOT code, so it must be equal to the address of the first emitted method.
4449          */
4450         sprintf (symbol, "methods");
4451         emit_section_change (acfg, ".text", 0);
4452         emit_global (acfg, symbol, TRUE);
4453         emit_alignment (acfg, 8);
4454         if (acfg->llvm) {
4455                 for (i = 0; i < acfg->nmethods; ++i) {
4456                         if (acfg->cfgs [i] && acfg->cfgs [i]->compile_llvm) {
4457                                 fprintf (acfg->fp, "\n.set methods, %s\n", acfg->cfgs [i]->asm_symbol); 
4458                                 break;
4459                         }
4460                 }
4461                 if (i == acfg->nmethods)
4462                         /* No LLVM compiled methods */
4463                         emit_label (acfg, symbol);
4464         } else {
4465                 emit_label (acfg, symbol);
4466         }
4467
4468         /* 
4469          * Emit some padding so the local symbol for the first method doesn't have the
4470          * same address as 'methods'.
4471          */
4472         emit_zero_bytes (acfg, 16);
4473
4474         for (l = acfg->method_order; l != NULL; l = l->next) {
4475                 i = GPOINTER_TO_UINT (l->data);
4476
4477                 if (acfg->cfgs [i]) {
4478                         if (acfg->cfgs [i]->compile_llvm)
4479                                 acfg->stats.llvm_count ++;
4480                         else
4481                                 emit_method_code (acfg, acfg->cfgs [i]);
4482                 }
4483         }
4484
4485         sprintf (symbol, "methods_end");
4486         emit_section_change (acfg, ".text", 0);
4487         emit_global (acfg, symbol, FALSE);
4488         emit_alignment (acfg, 8);
4489         emit_label (acfg, symbol);
4490
4491         sprintf (symbol, "code_offsets");
4492         emit_section_change (acfg, ".text", 1);
4493         emit_global (acfg, symbol, FALSE);
4494         emit_alignment (acfg, 8);
4495         emit_label (acfg, symbol);
4496
4497         acfg->stats.offsets_size += acfg->nmethods * 4;
4498
4499         sprintf (end_symbol, "%smethods", acfg->llvm_label_prefix);
4500         for (i = 0; i < acfg->nmethods; ++i) {
4501                 if (acfg->cfgs [i]) {
4502                         emit_symbol_diff (acfg, acfg->cfgs [i]->asm_symbol, end_symbol, 0);
4503                 } else {
4504                         emit_int32 (acfg, 0xffffffff);
4505                 }
4506         }
4507         emit_line (acfg);
4508 }
4509
4510 static void
4511 emit_info (MonoAotCompile *acfg)
4512 {
4513         int i;
4514         char symbol [256];
4515         GList *l;
4516         gint32 *offsets;
4517
4518         offsets = g_new0 (gint32, acfg->nmethods);
4519
4520         for (l = acfg->method_order; l != NULL; l = l->next) {
4521                 i = GPOINTER_TO_UINT (l->data);
4522
4523                 if (acfg->cfgs [i]) {
4524                         emit_method_info (acfg, acfg->cfgs [i]);
4525                         offsets [i] = acfg->cfgs [i]->method_info_offset;
4526                 } else {
4527                         offsets [i] = 0;
4528                 }
4529         }
4530
4531         sprintf (symbol, "method_info_offsets");
4532         emit_section_change (acfg, ".text", 1);
4533         emit_global (acfg, symbol, FALSE);
4534         emit_alignment (acfg, 8);
4535         emit_label (acfg, symbol);
4536
4537         acfg->stats.offsets_size += emit_offset_table (acfg, acfg->nmethods, 10, offsets);
4538
4539         g_free (offsets);
4540 }
4541
4542 #endif /* #if !defined(DISABLE_AOT) && !defined(DISABLE_JIT) */
4543
4544 #define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
4545 #define mix(a,b,c) { \
4546         a -= c;  a ^= rot(c, 4);  c += b; \
4547         b -= a;  b ^= rot(a, 6);  a += c; \
4548         c -= b;  c ^= rot(b, 8);  b += a; \
4549         a -= c;  a ^= rot(c,16);  c += b; \
4550         b -= a;  b ^= rot(a,19);  a += c; \
4551         c -= b;  c ^= rot(b, 4);  b += a; \
4552 }
4553 #define final(a,b,c) { \
4554         c ^= b; c -= rot(b,14); \
4555         a ^= c; a -= rot(c,11); \
4556         b ^= a; b -= rot(a,25); \
4557         c ^= b; c -= rot(b,16); \
4558         a ^= c; a -= rot(c,4);  \
4559         b ^= a; b -= rot(a,14); \
4560         c ^= b; c -= rot(b,24); \
4561 }
4562
4563 static guint
4564 mono_aot_type_hash (MonoType *t1)
4565 {
4566         guint hash = t1->type;
4567
4568         hash |= t1->byref << 6; /* do not collide with t1->type values */
4569         switch (t1->type) {
4570         case MONO_TYPE_VALUETYPE:
4571         case MONO_TYPE_CLASS:
4572         case MONO_TYPE_SZARRAY:
4573                 /* check if the distribution is good enough */
4574                 return ((hash << 5) - hash) ^ mono_metadata_str_hash (t1->data.klass->name);
4575         case MONO_TYPE_PTR:
4576                 return ((hash << 5) - hash) ^ mono_metadata_type_hash (t1->data.type);
4577         case MONO_TYPE_ARRAY:
4578                 return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
4579         case MONO_TYPE_GENERICINST:
4580                 return ((hash << 5) - hash) ^ 0;
4581         }
4582         return hash;
4583 }
4584
4585 /*
4586  * mono_aot_method_hash:
4587  *
4588  *   Return a hash code for methods which only depends on metadata.
4589  */
4590 guint32
4591 mono_aot_method_hash (MonoMethod *method)
4592 {
4593         MonoMethodSignature *sig;
4594         MonoClass *klass;
4595         int i;
4596         int hashes_count;
4597         guint32 *hashes_start, *hashes;
4598         guint32 a, b, c;
4599
4600         /* Similar to the hash in mono_method_get_imt_slot () */
4601
4602         sig = mono_method_signature (method);
4603
4604         hashes_count = sig->param_count + 5;
4605         hashes_start = malloc (hashes_count * sizeof (guint32));
4606         hashes = hashes_start;
4607
4608         /* Some wrappers are assigned to random classes */
4609         if (!method->wrapper_type || method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
4610                 klass = method->klass;
4611         else
4612                 klass = mono_defaults.object_class;
4613
4614         if (!method->wrapper_type) {
4615                 char *full_name = mono_type_full_name (&klass->byval_arg);
4616
4617                 hashes [0] = mono_metadata_str_hash (full_name);
4618                 hashes [1] = 0;
4619                 g_free (full_name);
4620         } else {
4621                 hashes [0] = mono_metadata_str_hash (klass->name);
4622                 hashes [1] = mono_metadata_str_hash (klass->name_space);
4623         }
4624         if (method->wrapper_type == MONO_WRAPPER_STFLD || method->wrapper_type == MONO_WRAPPER_LDFLD || method->wrapper_type == MONO_WRAPPER_LDFLDA)
4625                 /* The method name includes a stringified pointer */
4626                 hashes [2] = 0;
4627         else
4628                 hashes [2] = mono_metadata_str_hash (method->name);
4629         hashes [3] = method->wrapper_type;
4630         hashes [4] = mono_aot_type_hash (sig->ret);
4631         for (i = 0; i < sig->param_count; i++) {
4632                 hashes [5 + i] = mono_aot_type_hash (sig->params [i]);
4633         }
4634         
4635         /* Setup internal state */
4636         a = b = c = 0xdeadbeef + (((guint32)hashes_count)<<2);
4637
4638         /* Handle most of the hashes */
4639         while (hashes_count > 3) {
4640                 a += hashes [0];
4641                 b += hashes [1];
4642                 c += hashes [2];
4643                 mix (a,b,c);
4644                 hashes_count -= 3;
4645                 hashes += 3;
4646         }
4647
4648         /* Handle the last 3 hashes (all the case statements fall through) */
4649         switch (hashes_count) { 
4650         case 3 : c += hashes [2];
4651         case 2 : b += hashes [1];
4652         case 1 : a += hashes [0];
4653                 final (a,b,c);
4654         case 0: /* nothing left to add */
4655                 break;
4656         }
4657         
4658         free (hashes_start);
4659         
4660         return c;
4661 }
4662 #undef rot
4663 #undef mix
4664 #undef final
4665
4666 /*
4667  * mono_aot_wrapper_name:
4668  *
4669  *   Return a string which uniqely identifies the given wrapper method.
4670  */
4671 char*
4672 mono_aot_wrapper_name (MonoMethod *method)
4673 {
4674         char *name, *tmpsig, *klass_desc;
4675
4676         tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
4677
4678         switch (method->wrapper_type) {
4679         case MONO_WRAPPER_RUNTIME_INVOKE:
4680                 if (!strcmp (method->name, "runtime_invoke_dynamic"))
4681                         name = g_strdup_printf ("(wrapper runtime-invoke-dynamic)");
4682                 else
4683                         name = g_strdup_printf ("%s (%s)", method->name, tmpsig);
4684                 break;
4685         default:
4686                 klass_desc = mono_type_full_name (&method->klass->byval_arg);
4687                 name = g_strdup_printf ("%s:%s (%s)", klass_desc, method->name, tmpsig);
4688                 g_free (klass_desc);
4689                 break;
4690         }
4691
4692         g_free (tmpsig);
4693
4694         return name;
4695 }
4696
4697 /*
4698  * mono_aot_get_array_helper_from_wrapper;
4699  *
4700  * Get the helper method in Array called by an array wrapper method.
4701  */
4702 MonoMethod*
4703 mono_aot_get_array_helper_from_wrapper (MonoMethod *method)
4704 {
4705         MonoMethod *m;
4706         const char *prefix;
4707         MonoGenericContext ctx;
4708         MonoType *args [16];
4709         char *mname, *iname, *s, *s2, *helper_name = NULL;
4710
4711         prefix = "System.Collections.Generic";
4712         s = g_strdup_printf ("%s", method->name + strlen (prefix) + 1);
4713         s2 = strstr (s, "`1.");
4714         g_assert (s2);
4715         s2 [0] = '\0';
4716         iname = s;
4717         mname = s2 + 3;
4718
4719         //printf ("X: %s %s\n", iname, mname);
4720
4721         if (!strcmp (iname, "IList"))
4722                 helper_name = g_strdup_printf ("InternalArray__%s", mname);
4723         else
4724                 helper_name = g_strdup_printf ("InternalArray__%s_%s", iname, mname);
4725         m = mono_class_get_method_from_name (mono_defaults.array_class, helper_name, mono_method_signature (method)->param_count);
4726         g_assert (m);
4727         g_free (helper_name);
4728         g_free (s);
4729
4730         if (m->is_generic) {
4731                 memset (&ctx, 0, sizeof (ctx));
4732                 args [0] = &method->klass->element_class->byval_arg;
4733                 ctx.method_inst = mono_metadata_get_generic_inst (1, args);
4734                 m = mono_class_inflate_generic_method (m, &ctx);
4735         }
4736
4737         return m;
4738 }
4739
4740 /*
4741  * mono_aot_tramp_info_create:
4742  *
4743  *   Create a MonoAotTrampInfo structure from the arguments.
4744  */
4745 MonoAotTrampInfo*
4746 mono_aot_tramp_info_create (const char *name, guint8 *code, guint32 code_size)
4747 {
4748         MonoAotTrampInfo *info = g_new0 (MonoAotTrampInfo, 1);
4749
4750         info->name = (char*)name;
4751         info->code = code;
4752         info->code_size = code_size;
4753
4754         return info;
4755 }
4756
4757 #if !defined(DISABLE_AOT) && !defined(DISABLE_JIT)
4758
4759 typedef struct HashEntry {
4760     guint32 key, value, index;
4761         struct HashEntry *next;
4762 } HashEntry;
4763
4764 /*
4765  * emit_extra_methods:
4766  *
4767  * Emit methods which are not in the METHOD table, like wrappers.
4768  */
4769 static void
4770 emit_extra_methods (MonoAotCompile *acfg)
4771 {
4772         int i, table_size, buf_size;
4773         char symbol [256];
4774         guint8 *p, *buf;
4775         guint32 *info_offsets;
4776         guint32 hash;
4777         GPtrArray *table;
4778         HashEntry *entry, *new_entry;
4779         int nmethods, max_chain_length;
4780         int *chain_lengths;
4781
4782         info_offsets = g_new0 (guint32, acfg->extra_methods->len);
4783
4784         /* Emit method info */
4785         nmethods = 0;
4786         for (i = 0; i < acfg->extra_methods->len; ++i) {
4787                 MonoMethod *method = g_ptr_array_index (acfg->extra_methods, i);
4788                 MonoCompile *cfg = g_hash_table_lookup (acfg->method_to_cfg, method);
4789                 char *name;
4790
4791                 if (!cfg)
4792                         continue;
4793
4794                 buf_size = 512;
4795                 p = buf = g_malloc (buf_size);
4796
4797                 nmethods ++;
4798
4799                 name = NULL;
4800                 if (method->wrapper_type) {
4801                         /* 
4802                          * We encode some wrappers using their name, since encoding them
4803                          * directly would be difficult. This also avoids creating the wrapper
4804                          * methods at runtime, since they are not needed anyway.
4805                          */
4806                         switch (method->wrapper_type) {
4807                         case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
4808                         case MONO_WRAPPER_SYNCHRONIZED:
4809                                 /* encode_method_ref () can handle these */
4810                                 break;
4811                         case MONO_WRAPPER_RUNTIME_INVOKE:
4812                                 if (mono_marshal_method_from_wrapper (method) != method && !strstr (method->name, "virtual"))
4813                                         /* Direct wrapper, encode normally */
4814                                         break;
4815                                 /* Fall through */
4816                         default:
4817                                 name = mono_aot_wrapper_name (method);
4818                                 break;
4819                         }
4820                 }
4821
4822                 if (name) {
4823                         encode_value (1, p, &p);
4824                         encode_value (method->wrapper_type, p, &p);
4825                         strcpy ((char*)p, name);
4826                         p += strlen (name ) + 1;
4827                         g_free (name);
4828                 } else {
4829                         encode_value (0, p, &p);
4830                         encode_method_ref (acfg, method, p, &p);
4831                 }
4832
4833                 g_assert ((p - buf) < buf_size);
4834
4835                 info_offsets [i] = add_to_blob (acfg, buf, p - buf);
4836                 g_free (buf);
4837         }
4838
4839         /*
4840          * Construct a chained hash table for mapping indexes in extra_method_info to
4841          * method indexes.
4842          */
4843         table_size = g_spaced_primes_closest ((int)(nmethods * 1.5));
4844         table = g_ptr_array_sized_new (table_size);
4845         for (i = 0; i < table_size; ++i)
4846                 g_ptr_array_add (table, NULL);
4847         chain_lengths = g_new0 (int, table_size);
4848         max_chain_length = 0;
4849         for (i = 0; i < acfg->extra_methods->len; ++i) {
4850                 MonoMethod *method = g_ptr_array_index (acfg->extra_methods, i);
4851                 MonoCompile *cfg = g_hash_table_lookup (acfg->method_to_cfg, method);
4852                 guint32 key, value;
4853
4854                 if (!cfg)
4855                         continue;
4856
4857                 key = info_offsets [i];
4858                 value = get_method_index (acfg, method);
4859
4860                 hash = mono_aot_method_hash (method) % table_size;
4861
4862                 chain_lengths [hash] ++;
4863                 max_chain_length = MAX (max_chain_length, chain_lengths [hash]);
4864
4865                 new_entry = mono_mempool_alloc0 (acfg->mempool, sizeof (HashEntry));
4866                 new_entry->key = key;
4867                 new_entry->value = value;
4868
4869                 entry = g_ptr_array_index (table, hash);
4870                 if (entry == NULL) {
4871                         new_entry->index = hash;
4872                         g_ptr_array_index (table, hash) = new_entry;
4873                 } else {
4874                         while (entry->next)
4875                                 entry = entry->next;
4876                         
4877                         entry->next = new_entry;
4878                         new_entry->index = table->len;
4879                         g_ptr_array_add (table, new_entry);
4880                 }
4881         }
4882
4883         //printf ("MAX: %d\n", max_chain_length);
4884
4885         /* Emit the table */
4886         sprintf (symbol, "extra_method_table");
4887         emit_section_change (acfg, ".text", 0);
4888         emit_global (acfg, symbol, FALSE);
4889         emit_alignment (acfg, 8);
4890         emit_label (acfg, symbol);
4891
4892         emit_int32 (acfg, table_size);
4893         for (i = 0; i < table->len; ++i) {
4894                 HashEntry *entry = g_ptr_array_index (table, i);
4895
4896                 if (entry == NULL) {
4897                         emit_int32 (acfg, 0);
4898                         emit_int32 (acfg, 0);
4899                         emit_int32 (acfg, 0);
4900                 } else {
4901                         //g_assert (entry->key > 0);
4902                         emit_int32 (acfg, entry->key);
4903                         emit_int32 (acfg, entry->value);
4904                         if (entry->next)
4905                                 emit_int32 (acfg, entry->next->index);
4906                         else
4907                                 emit_int32 (acfg, 0);
4908                 }
4909         }
4910
4911         /* 
4912          * Emit a table reverse mapping method indexes to their index in extra_method_info.
4913          * This is used by mono_aot_find_jit_info ().
4914          */
4915         sprintf (symbol, "extra_method_info_offsets");
4916         emit_section_change (acfg, ".text", 0);
4917         emit_global (acfg, symbol, FALSE);
4918         emit_alignment (acfg, 8);
4919         emit_label (acfg, symbol);
4920
4921         emit_int32 (acfg, acfg->extra_methods->len);
4922         for (i = 0; i < acfg->extra_methods->len; ++i) {
4923                 MonoMethod *method = g_ptr_array_index (acfg->extra_methods, i);
4924
4925                 emit_int32 (acfg, get_method_index (acfg, method));
4926                 emit_int32 (acfg, info_offsets [i]);
4927         }
4928 }       
4929
4930 static void
4931 emit_exception_info (MonoAotCompile *acfg)
4932 {
4933         int i;
4934         char symbol [256];
4935         gint32 *offsets;
4936
4937         offsets = g_new0 (gint32, acfg->nmethods);
4938         for (i = 0; i < acfg->nmethods; ++i) {
4939                 if (acfg->cfgs [i]) {
4940                         emit_exception_debug_info (acfg, acfg->cfgs [i]);
4941                         offsets [i] = acfg->cfgs [i]->ex_info_offset;
4942                 } else {
4943                         offsets [i] = 0;
4944                 }
4945         }
4946
4947         sprintf (symbol, "ex_info_offsets");
4948         emit_section_change (acfg, ".text", 1);
4949         emit_global (acfg, symbol, FALSE);
4950         emit_alignment (acfg, 8);
4951         emit_label (acfg, symbol);
4952
4953         acfg->stats.offsets_size += emit_offset_table (acfg, acfg->nmethods, 10, offsets);
4954         g_free (offsets);
4955 }
4956
4957 static void
4958 emit_unwind_info (MonoAotCompile *acfg)
4959 {
4960         int i;
4961         char symbol [128];
4962
4963         /* 
4964          * The unwind info contains a lot of duplicates so we emit each unique
4965          * entry once, and only store the offset from the start of the table in the
4966          * exception info.
4967          */
4968
4969         sprintf (symbol, "unwind_info");
4970         emit_section_change (acfg, ".text", 1);
4971         emit_alignment (acfg, 8);
4972         emit_label (acfg, symbol);
4973         emit_global (acfg, symbol, FALSE);
4974
4975         for (i = 0; i < acfg->unwind_ops->len; ++i) {
4976                 guint32 index = GPOINTER_TO_UINT (g_ptr_array_index (acfg->unwind_ops, i));
4977                 guint8 *unwind_info;
4978                 guint32 unwind_info_len;
4979                 guint8 buf [16];
4980                 guint8 *p;
4981
4982                 unwind_info = mono_get_cached_unwind_info (index, &unwind_info_len);
4983
4984                 p = buf;
4985                 encode_value (unwind_info_len, p, &p);
4986                 emit_bytes (acfg, buf, p - buf);
4987                 emit_bytes (acfg, unwind_info, unwind_info_len);
4988
4989                 acfg->stats.unwind_info_size += (p - buf) + unwind_info_len;
4990         }
4991 }
4992
4993 static void
4994 emit_class_info (MonoAotCompile *acfg)
4995 {
4996         int i;
4997         char symbol [256];
4998         gint32 *offsets;
4999
5000         offsets = g_new0 (gint32, acfg->image->tables [MONO_TABLE_TYPEDEF].rows);
5001         for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i)
5002                 offsets [i] = emit_klass_info (acfg, MONO_TOKEN_TYPE_DEF | (i + 1));
5003
5004         sprintf (symbol, "class_info_offsets");
5005         emit_section_change (acfg, ".text", 1);
5006         emit_global (acfg, symbol, FALSE);
5007         emit_alignment (acfg, 8);
5008         emit_label (acfg, symbol);
5009
5010         acfg->stats.offsets_size += emit_offset_table (acfg, acfg->image->tables [MONO_TABLE_TYPEDEF].rows, 10, offsets);
5011         g_free (offsets);
5012 }
5013
5014 typedef struct ClassNameTableEntry {
5015         guint32 token, index;
5016         struct ClassNameTableEntry *next;
5017 } ClassNameTableEntry;
5018
5019 static void
5020 emit_class_name_table (MonoAotCompile *acfg)
5021 {
5022         int i, table_size;
5023         guint32 token, hash;
5024         MonoClass *klass;
5025         GPtrArray *table;
5026         char *full_name;
5027         char symbol [256];
5028         ClassNameTableEntry *entry, *new_entry;
5029
5030         /*
5031          * Construct a chained hash table for mapping class names to typedef tokens.
5032          */
5033         table_size = g_spaced_primes_closest ((int)(acfg->image->tables [MONO_TABLE_TYPEDEF].rows * 1.5));
5034         table = g_ptr_array_sized_new (table_size);
5035         for (i = 0; i < table_size; ++i)
5036                 g_ptr_array_add (table, NULL);
5037         for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
5038                 token = MONO_TOKEN_TYPE_DEF | (i + 1);
5039                 klass = mono_class_get (acfg->image, token);
5040                 full_name = mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_FULL_NAME);
5041                 hash = mono_metadata_str_hash (full_name) % table_size;
5042                 g_free (full_name);
5043
5044                 /* FIXME: Allocate from the mempool */
5045                 new_entry = g_new0 (ClassNameTableEntry, 1);
5046                 new_entry->token = token;
5047
5048                 entry = g_ptr_array_index (table, hash);
5049                 if (entry == NULL) {
5050                         new_entry->index = hash;
5051                         g_ptr_array_index (table, hash) = new_entry;
5052                 } else {
5053                         while (entry->next)
5054                                 entry = entry->next;
5055                         
5056                         entry->next = new_entry;
5057                         new_entry->index = table->len;
5058                         g_ptr_array_add (table, new_entry);
5059                 }
5060         }
5061
5062         /* Emit the table */
5063         sprintf (symbol, "class_name_table");
5064         emit_section_change (acfg, ".text", 0);
5065         emit_global (acfg, symbol, FALSE);
5066         emit_alignment (acfg, 8);
5067         emit_label (acfg, symbol);
5068
5069         /* FIXME: Optimize memory usage */
5070         g_assert (table_size < 65000);
5071         emit_int16 (acfg, table_size);
5072         g_assert (table->len < 65000);
5073         for (i = 0; i < table->len; ++i) {
5074                 ClassNameTableEntry *entry = g_ptr_array_index (table, i);
5075
5076                 if (entry == NULL) {
5077                         emit_int16 (acfg, 0);
5078                         emit_int16 (acfg, 0);
5079                 } else {
5080                         emit_int16 (acfg, mono_metadata_token_index (entry->token));
5081                         if (entry->next)
5082                                 emit_int16 (acfg, entry->next->index);
5083                         else
5084                                 emit_int16 (acfg, 0);
5085                 }
5086         }
5087 }
5088
5089 static void
5090 emit_image_table (MonoAotCompile *acfg)
5091 {
5092         int i;
5093         char symbol [256];
5094
5095         /*
5096          * The image table is small but referenced in a lot of places.
5097          * So we emit it at once, and reference its elements by an index.
5098          */
5099
5100         sprintf (symbol, "mono_image_table");
5101         emit_section_change (acfg, ".text", 1);
5102         emit_global (acfg, symbol, FALSE);
5103         emit_alignment (acfg, 8);
5104         emit_label (acfg, symbol);
5105
5106         emit_int32 (acfg, acfg->image_table->len);
5107         for (i = 0; i < acfg->image_table->len; i++) {
5108                 MonoImage *image = (MonoImage*)g_ptr_array_index (acfg->image_table, i);
5109                 MonoAssemblyName *aname = &image->assembly->aname;
5110
5111                 /* FIXME: Support multi-module assemblies */
5112                 g_assert (image->assembly->image == image);
5113
5114                 emit_string (acfg, image->assembly_name);
5115                 emit_string (acfg, image->guid);
5116                 emit_string (acfg, aname->culture ? aname->culture : "");
5117                 emit_string (acfg, (const char*)aname->public_key_token);
5118
5119                 emit_alignment (acfg, 8);
5120                 emit_int32 (acfg, aname->flags);
5121                 emit_int32 (acfg, aname->major);
5122                 emit_int32 (acfg, aname->minor);
5123                 emit_int32 (acfg, aname->build);
5124                 emit_int32 (acfg, aname->revision);
5125         }
5126 }
5127
5128 static void
5129 emit_got_info (MonoAotCompile *acfg)
5130 {
5131         char symbol [256];
5132         int i, first_plt_got_patch, buf_size;
5133         guint8 *p, *buf;
5134         guint32 *got_info_offsets;
5135
5136         /* Add the patches needed by the PLT to the GOT */
5137         acfg->plt_got_offset_base = acfg->got_offset;
5138         first_plt_got_patch = acfg->got_patches->len;
5139         for (i = 1; i < acfg->plt_offset; ++i) {
5140                 MonoJumpInfo *patch_info = g_hash_table_lookup (acfg->plt_offset_to_patch, GUINT_TO_POINTER (i));
5141
5142                 g_ptr_array_add (acfg->got_patches, patch_info);
5143         }
5144
5145         acfg->got_offset += acfg->plt_offset;
5146
5147         /**
5148          * FIXME: 
5149          * - optimize offsets table.
5150          * - reduce number of exported symbols.
5151          * - emit info for a klass only once.
5152          * - determine when a method uses a GOT slot which is guaranteed to be already 
5153          *   initialized.
5154          * - clean up and document the code.
5155          * - use String.Empty in class libs.
5156          */
5157
5158         /* Encode info required to decode shared GOT entries */
5159         buf_size = acfg->got_patches->len * 64;
5160         p = buf = mono_mempool_alloc (acfg->mempool, buf_size);
5161         got_info_offsets = mono_mempool_alloc (acfg->mempool, acfg->got_patches->len * sizeof (guint32));
5162         acfg->plt_got_info_offsets = mono_mempool_alloc (acfg->mempool, acfg->plt_offset * sizeof (guint32));
5163         /* Unused */
5164         if (acfg->plt_offset)
5165                 acfg->plt_got_info_offsets [0] = 0;
5166         for (i = 0; i < acfg->got_patches->len; ++i) {
5167                 MonoJumpInfo *ji = g_ptr_array_index (acfg->got_patches, i);
5168
5169                 p = buf;
5170
5171                 encode_value (ji->type, p, &p);
5172                 encode_patch (acfg, ji, p, &p);
5173
5174                 g_assert (p - buf <= buf_size);
5175                 got_info_offsets [i] = add_to_blob (acfg, buf, p - buf);
5176
5177                 if (i >= first_plt_got_patch)
5178                         acfg->plt_got_info_offsets [i - first_plt_got_patch + 1] = got_info_offsets [i];
5179                 acfg->stats.got_info_size += p - buf;
5180         }
5181
5182         /* Emit got_info_offsets table */
5183         sprintf (symbol, "got_info_offsets");
5184         emit_section_change (acfg, ".text", 1);
5185         emit_global (acfg, symbol, FALSE);
5186         emit_alignment (acfg, 8);
5187         emit_label (acfg, symbol);
5188
5189         /* No need to emit offsets for the got plt entries, the plt embeds them directly */
5190         acfg->stats.offsets_size += emit_offset_table (acfg, first_plt_got_patch, 10, (gint32*)got_info_offsets);
5191 }
5192
5193 static void
5194 emit_got (MonoAotCompile *acfg)
5195 {
5196         char symbol [256];
5197
5198         if (!acfg->llvm) {
5199                 /* Don't make GOT global so accesses to it don't need relocations */
5200                 sprintf (symbol, "%s", acfg->got_symbol);
5201                 emit_section_change (acfg, ".bss", 0);
5202                 emit_alignment (acfg, 8);
5203                 emit_local_symbol (acfg, symbol, "got_end", FALSE);
5204                 emit_label (acfg, symbol);
5205                 if (acfg->got_offset > 0)
5206                         emit_zero_bytes (acfg, (int)(acfg->got_offset * sizeof (gpointer)));
5207
5208                 sprintf (symbol, "got_end");
5209                 emit_label (acfg, symbol);
5210         }
5211
5212         sprintf (symbol, "mono_aot_got_addr");
5213         emit_section_change (acfg, ".data", 0);
5214         emit_global (acfg, symbol, FALSE);
5215         emit_alignment (acfg, 8);
5216         emit_label (acfg, symbol);
5217         emit_pointer (acfg, acfg->got_symbol);
5218 }
5219
5220 typedef struct GlobalsTableEntry {
5221         guint32 value, index;
5222         struct GlobalsTableEntry *next;
5223 } GlobalsTableEntry;
5224
5225 static void
5226 emit_globals_table (MonoAotCompile *acfg)
5227 {
5228         int i, table_size;
5229         guint32 hash;
5230         GPtrArray *table;
5231         char symbol [256];
5232         GlobalsTableEntry *entry, *new_entry;
5233
5234         /*
5235          * Construct a chained hash table for mapping global names to their index in
5236          * the globals table.
5237          */
5238         table_size = g_spaced_primes_closest ((int)(acfg->globals->len * 1.5));
5239         table = g_ptr_array_sized_new (table_size);
5240         for (i = 0; i < table_size; ++i)
5241                 g_ptr_array_add (table, NULL);
5242         for (i = 0; i < acfg->globals->len; ++i) {
5243                 char *name = g_ptr_array_index (acfg->globals, i);
5244
5245                 hash = mono_metadata_str_hash (name) % table_size;
5246
5247                 /* FIXME: Allocate from the mempool */
5248                 new_entry = g_new0 (GlobalsTableEntry, 1);
5249                 new_entry->value = i;
5250
5251                 entry = g_ptr_array_index (table, hash);
5252                 if (entry == NULL) {
5253                         new_entry->index = hash;
5254                         g_ptr_array_index (table, hash) = new_entry;
5255                 } else {
5256                         while (entry->next)
5257                                 entry = entry->next;
5258                         
5259                         entry->next = new_entry;
5260                         new_entry->index = table->len;
5261                         g_ptr_array_add (table, new_entry);
5262                 }
5263         }
5264
5265         /* Emit the table */
5266         sprintf (symbol, ".Lglobals_hash");
5267         emit_section_change (acfg, ".text", 0);
5268         emit_alignment (acfg, 8);
5269         emit_label (acfg, symbol);
5270
5271         /* FIXME: Optimize memory usage */
5272         g_assert (table_size < 65000);
5273         emit_int16 (acfg, table_size);
5274         for (i = 0; i < table->len; ++i) {
5275                 GlobalsTableEntry *entry = g_ptr_array_index (table, i);
5276
5277                 if (entry == NULL) {
5278                         emit_int16 (acfg, 0);
5279                         emit_int16 (acfg, 0);
5280                 } else {
5281                         emit_int16 (acfg, entry->value + 1);
5282                         if (entry->next)
5283                                 emit_int16 (acfg, entry->next->index);
5284                         else
5285                                 emit_int16 (acfg, 0);
5286                 }
5287         }
5288
5289         /* Emit the names */
5290         for (i = 0; i < acfg->globals->len; ++i) {
5291                 char *name = g_ptr_array_index (acfg->globals, i);
5292
5293                 sprintf (symbol, "name_%d", i);
5294                 emit_section_change (acfg, ".text", 1);
5295                 emit_label (acfg, symbol);
5296                 emit_string (acfg, name);
5297         }
5298
5299         /* Emit the globals table */
5300         sprintf (symbol, ".Lglobals");
5301         emit_section_change (acfg, ".data", 0);
5302         /* This is not a global, since it is accessed by the init function */
5303         emit_alignment (acfg, 8);
5304         emit_label (acfg, symbol);
5305
5306         sprintf (symbol, "%sglobals_hash", acfg->temp_prefix);
5307         emit_pointer (acfg, symbol);
5308
5309         for (i = 0; i < acfg->globals->len; ++i) {
5310                 char *name = g_ptr_array_index (acfg->globals, i);
5311
5312                 sprintf (symbol, "name_%d", i);
5313                 emit_pointer (acfg, symbol);
5314
5315                 sprintf (symbol, "%s", name);
5316                 emit_pointer (acfg, symbol);
5317         }
5318         /* Null terminate the table */
5319         emit_int32 (acfg, 0);
5320         emit_int32 (acfg, 0);
5321 }
5322
5323 static void
5324 emit_globals (MonoAotCompile *acfg)
5325 {
5326         char *build_info;
5327
5328         emit_string_symbol (acfg, "mono_assembly_guid" , acfg->image->guid);
5329
5330         emit_string_symbol (acfg, "mono_aot_version", MONO_AOT_FILE_VERSION);
5331
5332         if (acfg->aot_opts.bind_to_runtime_version) {
5333                 build_info = mono_get_runtime_build_info ();
5334                 emit_string_symbol (acfg, "mono_runtime_version", build_info);
5335                 g_free (build_info);
5336         } else {
5337                 emit_string_symbol (acfg, "mono_runtime_version", "");
5338         }
5339
5340         /* 
5341          * When static linking, we emit a global which will point to the symbol table.
5342          */
5343         if (acfg->aot_opts.static_link) {
5344                 char symbol [256];
5345                 char *p;
5346
5347                 /* Emit a string holding the assembly name */
5348                 emit_string_symbol (acfg, "mono_aot_assembly_name", acfg->image->assembly->aname.name);
5349
5350                 emit_globals_table (acfg);
5351
5352                 /* 
5353                  * Emit a global symbol which can be passed by an embedding app to
5354                  * mono_aot_register_module ().
5355                  */
5356 #if defined(__MACH__)
5357                 sprintf (symbol, "_mono_aot_module_%s_info", acfg->image->assembly->aname.name);
5358 #else
5359                 sprintf (symbol, "mono_aot_module_%s_info", acfg->image->assembly->aname.name);
5360 #endif
5361
5362                 /* Get rid of characters which cannot occur in symbols */
5363                 p = symbol;
5364                 for (p = symbol; *p; ++p) {
5365                         if (!(isalnum (*p) || *p == '_'))
5366                                 *p = '_';
5367                 }
5368                 acfg->static_linking_symbol = g_strdup (symbol);
5369                 emit_global_inner (acfg, symbol, FALSE);
5370                 emit_alignment (acfg, 8);
5371                 emit_label (acfg, symbol);
5372                 sprintf (symbol, "%sglobals", acfg->temp_prefix);
5373                 emit_pointer (acfg, symbol);
5374         }
5375 }
5376
5377 static void
5378 emit_autoreg (MonoAotCompile *acfg)
5379 {
5380         char *symbol;
5381
5382         /*
5383          * Emit a function into the .ctor section which will be called by the ELF
5384          * loader to register this module with the runtime.
5385          */
5386         if (! (!acfg->use_bin_writer && acfg->aot_opts.static_link && acfg->aot_opts.autoreg))
5387                 return;
5388
5389         symbol = g_strdup_printf ("_%s_autoreg", acfg->static_linking_symbol);
5390
5391         arch_emit_autoreg (acfg, symbol);
5392
5393         g_free (symbol);
5394 }       
5395
5396 static void
5397 emit_mem_end (MonoAotCompile *acfg)
5398 {
5399         char symbol [128];
5400
5401         sprintf (symbol, "mem_end");
5402         emit_section_change (acfg, ".text", 1);
5403         emit_global (acfg, symbol, FALSE);
5404         emit_alignment (acfg, 8);
5405         emit_label (acfg, symbol);
5406 }
5407
5408 /*
5409  * Emit a structure containing all the information not stored elsewhere.
5410  */
5411 static void
5412 emit_file_info (MonoAotCompile *acfg)
5413 {
5414         char symbol [128];
5415         int i;
5416
5417         sprintf (symbol, "mono_aot_file_info");
5418         emit_section_change (acfg, ".data", 0);
5419         emit_alignment (acfg, 8);
5420         emit_label (acfg, symbol);
5421         emit_global (acfg, symbol, FALSE);
5422
5423         /* The data emitted here must match MonoAotFileInfo in aot-runtime.c. */
5424         emit_int32 (acfg, acfg->plt_got_offset_base);
5425         emit_int32 (acfg, (int)(acfg->got_offset * sizeof (gpointer)));
5426         emit_int32 (acfg, acfg->plt_offset);
5427         emit_int32 (acfg, acfg->nmethods);
5428         emit_int32 (acfg, acfg->flags);
5429         emit_int32 (acfg, acfg->opts);
5430
5431         for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
5432                 emit_int32 (acfg, acfg->num_trampolines [i]);
5433         for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
5434                 emit_int32 (acfg, acfg->trampoline_got_offset_base [i]);
5435         for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
5436                 emit_int32 (acfg, acfg->trampoline_size [i]);
5437 }
5438
5439 static void
5440 emit_blob (MonoAotCompile *acfg)
5441 {
5442         char symbol [128];
5443
5444         sprintf (symbol, "blob");
5445         emit_section_change (acfg, ".text", 1);
5446         emit_global (acfg, symbol, FALSE);
5447         emit_alignment (acfg, 8);
5448         emit_label (acfg, symbol);
5449
5450         emit_bytes (acfg, (guint8*)acfg->blob.data, acfg->blob.index);
5451 }
5452
5453 static void
5454 emit_dwarf_info (MonoAotCompile *acfg)
5455 {
5456 #ifdef EMIT_DWARF_INFO
5457         int i;
5458         char symbol [128], symbol2 [128];
5459
5460         /* DIEs for methods */
5461         for (i = 0; i < acfg->nmethods; ++i) {
5462                 MonoCompile *cfg = acfg->cfgs [i];
5463
5464                 if (!cfg)
5465                         continue;
5466
5467                 // FIXME: LLVM doesn't define .Lme_...
5468                 if (cfg->compile_llvm)
5469                         continue;
5470
5471                 sprintf (symbol, "%s", cfg->asm_symbol);
5472                 sprintf (symbol2, "%sme_%x", acfg->temp_prefix, i);
5473
5474                 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 ()));
5475         }
5476 #endif
5477 }
5478
5479 static void
5480 collect_methods (MonoAotCompile *acfg)
5481 {
5482         int i;
5483         MonoImage *image = acfg->image;
5484
5485         /* Collect methods */
5486         for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
5487                 MonoMethod *method;
5488                 guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
5489
5490                 method = mono_get_method (acfg->image, token, NULL);
5491
5492                 if (!method) {
5493                         printf ("Failed to load method 0x%x from '%s'.\n", token, image->name);
5494                         exit (1);
5495                 }
5496                         
5497                 /* Load all methods eagerly to skip the slower lazy loading code */
5498                 mono_class_setup_methods (method->klass);
5499
5500                 if (acfg->aot_opts.full_aot && method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
5501                         /* Compile the wrapper instead */
5502                         /* We do this here instead of add_wrappers () because it is easy to do it here */
5503                         MonoMethod *wrapper = mono_marshal_get_native_wrapper (method, check_for_pending_exc, TRUE);
5504                         method = wrapper;
5505                 }
5506
5507                 /* FIXME: Some mscorlib methods don't have debug info */
5508                 /*
5509                 if (acfg->aot_opts.soft_debug && !method->wrapper_type) {
5510                         if (!((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5511                                   (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
5512                                   (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5513                                   (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))) {
5514                                 if (!mono_debug_lookup_method (method)) {
5515                                         fprintf (stderr, "Method %s has no debug info, probably the .mdb file for the assembly is missing.\n", mono_method_full_name (method, TRUE));
5516                                         exit (1);
5517                                 }
5518                         }
5519                 }
5520                 */
5521
5522                 /* Since we add the normal methods first, their index will be equal to their zero based token index */
5523                 add_method_with_index (acfg, method, i, FALSE);
5524                 acfg->method_index ++;
5525         }
5526
5527         add_generic_instances (acfg);
5528
5529         if (acfg->aot_opts.full_aot)
5530                 add_wrappers (acfg);
5531 }
5532
5533 static void
5534 compile_methods (MonoAotCompile *acfg)
5535 {
5536         int i, methods_len;
5537
5538         if (acfg->aot_opts.nthreads > 0) {
5539                 GPtrArray *frag;
5540                 int len, j;
5541                 GPtrArray *threads;
5542                 HANDLE handle;
5543                 gpointer *user_data;
5544                 MonoMethod **methods;
5545
5546                 methods_len = acfg->methods->len;
5547
5548                 len = acfg->methods->len / acfg->aot_opts.nthreads;
5549                 g_assert (len > 0);
5550                 /* 
5551                  * Partition the list of methods into fragments, and hand it to threads to
5552                  * process.
5553                  */
5554                 threads = g_ptr_array_new ();
5555                 /* Make a copy since acfg->methods is modified by compile_method () */
5556                 methods = g_new0 (MonoMethod*, methods_len);
5557                 //memcpy (methods, g_ptr_array_index (acfg->methods, 0), sizeof (MonoMethod*) * methods_len);
5558                 for (i = 0; i < methods_len; ++i)
5559                         methods [i] = g_ptr_array_index (acfg->methods, i);
5560                 i = 0;
5561                 while (i < methods_len) {
5562                         frag = g_ptr_array_new ();
5563                         for (j = 0; j < len; ++j) {
5564                                 if (i < methods_len) {
5565                                         g_ptr_array_add (frag, methods [i]);
5566                                         i ++;
5567                                 }
5568                         }
5569
5570                         user_data = g_new0 (gpointer, 3);
5571                         user_data [0] = mono_domain_get ();
5572                         user_data [1] = acfg;
5573                         user_data [2] = frag;
5574                         
5575                         handle = mono_create_thread (NULL, 0, (gpointer)compile_thread_main, user_data, 0, NULL);
5576                         g_ptr_array_add (threads, handle);
5577                 }
5578                 g_free (methods);
5579
5580                 for (i = 0; i < threads->len; ++i) {
5581                         WaitForSingleObjectEx (g_ptr_array_index (threads, i), INFINITE, FALSE);
5582                 }
5583         } else {
5584                 methods_len = 0;
5585         }
5586
5587         /* Compile methods added by compile_method () or all methods if nthreads == 0 */
5588         for (i = methods_len; i < acfg->methods->len; ++i) {
5589                 /* This can new methods to acfg->methods */
5590                 compile_method (acfg, g_ptr_array_index (acfg->methods, i));
5591         }
5592 }
5593
5594 static int
5595 compile_asm (MonoAotCompile *acfg)
5596 {
5597         char *command, *objfile;
5598         char *outfile_name, *tmp_outfile_name;
5599         const char *tool_prefix = acfg->aot_opts.tool_prefix ? acfg->aot_opts.tool_prefix : "";
5600
5601 #if defined(TARGET_AMD64)
5602 #define AS_OPTIONS "--64"
5603 #elif defined(TARGET_POWERPC64)
5604 #define AS_OPTIONS "-a64 -mppc64"
5605 #define LD_OPTIONS "-m elf64ppc"
5606 #elif defined(sparc) && SIZEOF_VOID_P == 8
5607 #define AS_OPTIONS "-xarch=v9"
5608 #else
5609 #define AS_OPTIONS ""
5610 #endif
5611
5612 #ifndef LD_OPTIONS
5613 #define LD_OPTIONS ""
5614 #endif
5615
5616 #ifdef ENABLE_LLVM
5617 #define EH_LD_OPTIONS "--eh-frame-hdr"
5618 #else
5619 #define EH_LD_OPTIONS ""
5620 #endif
5621
5622         if (acfg->aot_opts.asm_only) {
5623                 printf ("Output file: '%s'.\n", acfg->tmpfname);
5624                 if (acfg->aot_opts.static_link)
5625                         printf ("Linking symbol: '%s'.\n", acfg->static_linking_symbol);
5626                 return 0;
5627         }
5628
5629         if (acfg->aot_opts.static_link) {
5630                 if (acfg->aot_opts.outfile)
5631                         objfile = g_strdup_printf ("%s", acfg->aot_opts.outfile);
5632                 else
5633                         objfile = g_strdup_printf ("%s.o", acfg->image->name);
5634         } else {
5635                 objfile = g_strdup_printf ("%s.o", acfg->tmpfname);
5636         }
5637         command = g_strdup_printf ("%sas %s %s -o %s", tool_prefix, AS_OPTIONS, acfg->tmpfname, objfile);
5638         printf ("Executing the native assembler: %s\n", command);
5639         if (system (command) != 0) {
5640                 g_free (command);
5641                 g_free (objfile);
5642                 return 1;
5643         }
5644
5645         g_free (command);
5646
5647         if (acfg->aot_opts.static_link) {
5648                 printf ("Output file: '%s'.\n", objfile);
5649                 printf ("Linking symbol: '%s'.\n", acfg->static_linking_symbol);
5650                 g_free (objfile);
5651                 return 0;
5652         }
5653
5654         if (acfg->aot_opts.outfile)
5655                 outfile_name = g_strdup_printf ("%s", acfg->aot_opts.outfile);
5656         else
5657                 outfile_name = g_strdup_printf ("%s%s", acfg->image->name, SHARED_EXT);
5658
5659         tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
5660
5661 #if defined(sparc)
5662         command = g_strdup_printf ("ld -shared -G -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
5663 #elif defined(__ppc__) && defined(__MACH__)
5664         command = g_strdup_printf ("gcc -dynamiclib -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
5665 #elif defined(HOST_WIN32)
5666         command = g_strdup_printf ("gcc -shared --dll -mno-cygwin -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
5667 #else
5668         command = g_strdup_printf ("%sld %s %s -shared -o %s %s.o", tool_prefix, EH_LD_OPTIONS, LD_OPTIONS, tmp_outfile_name, acfg->tmpfname);
5669 #endif
5670         printf ("Executing the native linker: %s\n", command);
5671         if (system (command) != 0) {
5672                 g_free (tmp_outfile_name);
5673                 g_free (outfile_name);
5674                 g_free (command);
5675                 g_free (objfile);
5676                 return 1;
5677         }
5678
5679         g_free (command);
5680         unlink (objfile);
5681         /*com = g_strdup_printf ("strip --strip-unneeded %s%s", acfg->image->name, SHARED_EXT);
5682         printf ("Stripping the binary: %s\n", com);
5683         system (com);
5684         g_free (com);*/
5685
5686 #if defined(TARGET_ARM) && !defined(__MACH__)
5687         /* 
5688          * gas generates 'mapping symbols' each time code and data is mixed, which 
5689          * happens a lot in emit_and_reloc_code (), so we need to get rid of them.
5690          */
5691         command = g_strdup_printf ("%sstrip --strip-symbol=\\$a --strip-symbol=\\$d %s", tool_prefix, tmp_outfile_name);
5692         printf ("Stripping the binary: %s\n", command);
5693         if (system (command) != 0) {
5694                 g_free (tmp_outfile_name);
5695                 g_free (outfile_name);
5696                 g_free (command);
5697                 g_free (objfile);
5698                 return 1;
5699         }
5700 #endif
5701
5702         rename (tmp_outfile_name, outfile_name);
5703
5704         g_free (tmp_outfile_name);
5705         g_free (outfile_name);
5706         g_free (objfile);
5707
5708         if (acfg->aot_opts.save_temps)
5709                 printf ("Retained input file.\n");
5710         else
5711                 unlink (acfg->tmpfname);
5712
5713         return 0;
5714 }
5715
5716 static MonoAotCompile*
5717 acfg_create (MonoAssembly *ass, guint32 opts)
5718 {
5719         MonoImage *image = ass->image;
5720         MonoAotCompile *acfg;
5721         int i;
5722
5723         acfg = g_new0 (MonoAotCompile, 1);
5724         acfg->methods = g_ptr_array_new ();
5725         acfg->method_indexes = g_hash_table_new (NULL, NULL);
5726         acfg->method_depth = g_hash_table_new (NULL, NULL);
5727         acfg->plt_offset_to_patch = g_hash_table_new (NULL, NULL);
5728         acfg->patch_to_plt_offset = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
5729         acfg->patch_to_got_offset = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
5730         acfg->patch_to_got_offset_by_type = g_new0 (GHashTable*, MONO_PATCH_INFO_NUM);
5731         for (i = 0; i < MONO_PATCH_INFO_NUM; ++i)
5732                 acfg->patch_to_got_offset_by_type [i] = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
5733         acfg->got_patches = g_ptr_array_new ();
5734         acfg->method_to_cfg = g_hash_table_new (NULL, NULL);
5735         acfg->token_info_hash = g_hash_table_new_full (NULL, NULL, NULL, g_free);
5736         acfg->image_hash = g_hash_table_new (NULL, NULL);
5737         acfg->image_table = g_ptr_array_new ();
5738         acfg->globals = g_ptr_array_new ();
5739         acfg->image = image;
5740         acfg->opts = opts;
5741         acfg->mempool = mono_mempool_new ();
5742         acfg->extra_methods = g_ptr_array_new ();
5743         acfg->unwind_info_offsets = g_hash_table_new (NULL, NULL);
5744         acfg->unwind_ops = g_ptr_array_new ();
5745         acfg->method_label_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
5746         InitializeCriticalSection (&acfg->mutex);
5747
5748         return acfg;
5749 }
5750
5751 static void
5752 acfg_free (MonoAotCompile *acfg)
5753 {
5754         int i;
5755
5756         img_writer_destroy (acfg->w);
5757         for (i = 0; i < acfg->nmethods; ++i)
5758                 if (acfg->cfgs [i])
5759                         g_free (acfg->cfgs [i]);
5760         g_free (acfg->cfgs);
5761         g_free (acfg->static_linking_symbol);
5762         g_free (acfg->got_symbol);
5763         g_free (acfg->plt_symbol);
5764         g_ptr_array_free (acfg->methods, TRUE);
5765         g_ptr_array_free (acfg->got_patches, TRUE);
5766         g_ptr_array_free (acfg->image_table, TRUE);
5767         g_ptr_array_free (acfg->globals, TRUE);
5768         g_ptr_array_free (acfg->unwind_ops, TRUE);
5769         g_hash_table_destroy (acfg->method_indexes);
5770         g_hash_table_destroy (acfg->method_depth);
5771         g_hash_table_destroy (acfg->plt_offset_to_patch);
5772         g_hash_table_destroy (acfg->patch_to_plt_offset);
5773         g_hash_table_destroy (acfg->patch_to_got_offset);
5774         g_hash_table_destroy (acfg->method_to_cfg);
5775         g_hash_table_destroy (acfg->token_info_hash);
5776         g_hash_table_destroy (acfg->image_hash);
5777         g_hash_table_destroy (acfg->unwind_info_offsets);
5778         g_hash_table_destroy (acfg->method_label_hash);
5779         for (i = 0; i < MONO_PATCH_INFO_NUM; ++i)
5780                 g_hash_table_destroy (acfg->patch_to_got_offset_by_type [i]);
5781         g_free (acfg->patch_to_got_offset_by_type);
5782         mono_mempool_destroy (acfg->mempool);
5783         g_free (acfg);
5784 }
5785
5786 int
5787 mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
5788 {
5789         MonoImage *image = ass->image;
5790         int i, res;
5791         MonoAotCompile *acfg;
5792         char *outfile_name, *tmp_outfile_name, *p;
5793         TV_DECLARE (atv);
5794         TV_DECLARE (btv);
5795
5796         printf ("Mono Ahead of Time compiler - compiling assembly %s\n", image->name);
5797
5798         acfg = acfg_create (ass, opts);
5799
5800         memset (&acfg->aot_opts, 0, sizeof (acfg->aot_opts));
5801         acfg->aot_opts.write_symbols = TRUE;
5802         acfg->aot_opts.ntrampolines = 1024;
5803         acfg->aot_opts.nrgctx_trampolines = 1024;
5804
5805         mono_aot_parse_options (aot_options, &acfg->aot_opts);
5806
5807         if (acfg->aot_opts.static_link)
5808                 acfg->aot_opts.autoreg = TRUE;
5809
5810         //acfg->aot_opts.print_skipped_methods = TRUE;
5811
5812 #ifndef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
5813         if (acfg->aot_opts.full_aot) {
5814                 printf ("--aot=full is not supported on this platform.\n");
5815                 return 1;
5816         }
5817 #endif
5818
5819         if (acfg->aot_opts.static_link)
5820                 acfg->aot_opts.asm_writer = TRUE;
5821
5822         if (acfg->aot_opts.soft_debug) {
5823                 MonoDebugOptions *opt = mini_get_debug_options ();
5824
5825                 opt->mdb_optimizations = TRUE;
5826                 opt->gen_seq_points = TRUE;
5827
5828                 if (mono_debug_format == MONO_DEBUG_FORMAT_NONE) {
5829                         fprintf (stderr, "The soft-debug AOT option requires the --debug option.\n");
5830                         return 1;
5831                 }
5832         }
5833
5834 #ifdef ENABLE_LLVM
5835         acfg->llvm = TRUE;
5836         acfg->aot_opts.asm_writer = TRUE;
5837         acfg->flags |= MONO_AOT_FILE_FLAG_WITH_LLVM;
5838 #endif
5839
5840         if (acfg->aot_opts.full_aot)
5841                 acfg->flags |= MONO_AOT_FILE_FLAG_FULL_AOT;
5842
5843         load_profile_files (acfg);
5844
5845         acfg->num_trampolines [MONO_AOT_TRAMP_SPECIFIC] = acfg->aot_opts.full_aot ? acfg->aot_opts.ntrampolines : 0;
5846 #ifdef MONO_ARCH_HAVE_STATIC_RGCTX_TRAMPOLINE
5847         acfg->num_trampolines [MONO_AOT_TRAMP_STATIC_RGCTX] = acfg->aot_opts.full_aot ? acfg->aot_opts.nrgctx_trampolines : 0;
5848 #endif
5849         acfg->num_trampolines [MONO_AOT_TRAMP_IMT_THUNK] = acfg->aot_opts.full_aot ? 128 : 0;
5850
5851         acfg->got_symbol_base = g_strdup_printf ("mono_aot_%s_got", acfg->image->assembly->aname.name);
5852         acfg->plt_symbol = g_strdup_printf ("mono_aot_%s_plt", acfg->image->assembly->aname.name);
5853
5854         /* Get rid of characters which cannot occur in symbols */
5855         for (p = acfg->got_symbol_base; *p; ++p) {
5856                 if (!(isalnum (*p) || *p == '_'))
5857                         *p = '_';
5858         }
5859         for (p = acfg->plt_symbol; *p; ++p) {
5860                 if (!(isalnum (*p) || *p == '_'))
5861                         *p = '_';
5862         }
5863
5864         acfg->temp_prefix = img_writer_get_temp_label_prefix (NULL);
5865
5866         acfg->method_index = 1;
5867
5868         collect_methods (acfg);
5869
5870         acfg->cfgs_size = acfg->methods->len + 32;
5871         acfg->cfgs = g_new0 (MonoCompile*, acfg->cfgs_size);
5872
5873         /* PLT offset 0 is reserved for the PLT trampoline */
5874         acfg->plt_offset = 1;
5875
5876 #ifdef ENABLE_LLVM
5877         llvm_acfg = acfg;
5878         mono_llvm_create_aot_module (acfg->got_symbol_base);
5879 #endif
5880
5881         /* GOT offset 0 is reserved for the address of the current assembly */
5882         {
5883                 MonoJumpInfo *ji;
5884
5885                 ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
5886                 ji->type = MONO_PATCH_INFO_IMAGE;
5887                 ji->data.image = acfg->image;
5888
5889                 get_got_offset (acfg, ji);
5890
5891                 /* Slot 1 is reserved for the mscorlib got addr */
5892                 ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
5893                 ji->type = MONO_PATCH_INFO_MSCORLIB_GOT_ADDR;
5894                 get_got_offset (acfg, ji);
5895         }
5896
5897         TV_GETTIME (atv);
5898
5899         compile_methods (acfg);
5900
5901         TV_GETTIME (btv);
5902
5903         acfg->stats.jit_time = TV_ELAPSED (atv, btv);
5904
5905         TV_GETTIME (atv);
5906
5907 #ifdef ENABLE_LLVM
5908         if (acfg->llvm) {
5909                 if (acfg->aot_opts.asm_only) {
5910                         if (acfg->aot_opts.outfile)
5911                                 acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
5912                         else
5913                                 acfg->tmpfname = g_strdup_printf ("%s.s", acfg->image->name);
5914                 } else {
5915                         acfg->tmpfname = g_strdup ("temp.s");
5916                 }
5917         }
5918
5919         emit_llvm_file (acfg);
5920 #endif
5921
5922         if (!acfg->aot_opts.asm_only && !acfg->aot_opts.asm_writer && bin_writer_supported ()) {
5923                 if (acfg->aot_opts.outfile)
5924                         outfile_name = g_strdup_printf ("%s", acfg->aot_opts.outfile);
5925                 else
5926                         outfile_name = g_strdup_printf ("%s%s", acfg->image->name, SHARED_EXT);
5927
5928                 /* 
5929                  * Can't use g_file_open_tmp () as it will be deleted at exit, and
5930                  * it might be in another file system so the rename () won't work.
5931                  */
5932                 tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
5933
5934                 acfg->fp = fopen (tmp_outfile_name, "w");
5935                 if (!acfg->fp) {
5936                         printf ("Unable to create temporary file '%s': %s\n", tmp_outfile_name, strerror (errno));
5937                         return 1;
5938                 }
5939
5940                 acfg->w = img_writer_create (acfg->fp, TRUE);
5941                 acfg->use_bin_writer = TRUE;
5942         } else {
5943                 if (acfg->llvm) {
5944                         /* Append to the .s file created by llvm */
5945                         /* FIXME: Use multiple files instead */
5946                         acfg->fp = fopen (acfg->tmpfname, "a+");
5947                 } else {
5948                         if (acfg->aot_opts.asm_only) {
5949                                 if (acfg->aot_opts.outfile)
5950                                         acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
5951                                 else
5952                                         acfg->tmpfname = g_strdup_printf ("%s.s", acfg->image->name);
5953                                 acfg->fp = fopen (acfg->tmpfname, "w+");
5954                         } else {
5955                                 int i = g_file_open_tmp ("mono_aot_XXXXXX", &acfg->tmpfname, NULL);
5956                                 acfg->fp = fdopen (i, "w+");
5957                         }
5958                         g_assert (acfg->fp);
5959                 }
5960                 acfg->w = img_writer_create (acfg->fp, FALSE);
5961                 
5962                 tmp_outfile_name = NULL;
5963                 outfile_name = NULL;
5964         }
5965
5966         /*
5967          * The prefix LLVM likes to put in front of symbol names on darwin.
5968          * The mach-os specs require this for globals, but LLVM puts them in front of all
5969          * symbols. We need to handle this, since we need to refer to LLVM generated
5970          * symbols.
5971          */
5972         acfg->llvm_label_prefix = "";
5973         if (acfg->llvm)
5974                 acfg->llvm_label_prefix = LLVM_LABEL_PREFIX;
5975
5976         acfg->got_symbol = g_strdup_printf ("%s%s", acfg->llvm_label_prefix, acfg->got_symbol_base);
5977
5978         /* Compute symbols for methods */
5979         for (i = 0; i < acfg->nmethods; ++i) {
5980                 if (acfg->cfgs [i]) {
5981                         MonoCompile *cfg = acfg->cfgs [i];
5982                         int method_index = get_method_index (acfg, cfg->orig_method);
5983
5984                         cfg->asm_symbol = g_strdup_printf ("%s%sm_%x", acfg->temp_prefix, LLVM_LABEL_PREFIX, method_index);
5985                 }
5986         }
5987
5988         if (!acfg->aot_opts.nodebug)
5989                 acfg->dwarf = mono_dwarf_writer_create (acfg->w, NULL, 0, FALSE);
5990
5991         img_writer_emit_start (acfg->w);
5992
5993         if (acfg->dwarf)
5994                 mono_dwarf_writer_emit_base_info (acfg->dwarf, mono_arch_get_cie_program ());
5995
5996         emit_code (acfg);
5997
5998         emit_info (acfg);
5999
6000         emit_extra_methods (acfg);
6001
6002         emit_trampolines (acfg);
6003
6004         emit_class_name_table (acfg);
6005
6006         emit_got_info (acfg);
6007
6008         emit_exception_info (acfg);
6009
6010         emit_unwind_info (acfg);
6011
6012         emit_class_info (acfg);
6013
6014         emit_plt (acfg);
6015
6016         emit_image_table (acfg);
6017
6018         emit_got (acfg);
6019
6020         emit_file_info (acfg);
6021
6022         emit_blob (acfg);
6023
6024         emit_globals (acfg);
6025
6026         emit_autoreg (acfg);
6027
6028         if (acfg->dwarf) {
6029                 emit_dwarf_info (acfg);
6030                 mono_dwarf_writer_close (acfg->dwarf);
6031         }
6032
6033         emit_mem_end (acfg);
6034
6035         TV_GETTIME (btv);
6036
6037         acfg->stats.gen_time = TV_ELAPSED (atv, btv);
6038
6039         if (acfg->llvm)
6040                 g_assert (acfg->got_offset <= acfg->final_got_size);
6041
6042         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);
6043
6044         TV_GETTIME (atv);
6045         res = img_writer_emit_writeout (acfg->w);
6046         if (res != 0) {
6047                 acfg_free (acfg);
6048                 return res;
6049         }
6050         if (acfg->use_bin_writer) {
6051                 int err = rename (tmp_outfile_name, outfile_name);
6052
6053                 if (err) {
6054                         printf ("Unable to rename '%s' to '%s': %s\n", tmp_outfile_name, outfile_name, strerror (errno));
6055                         return 1;
6056                 }
6057         } else {
6058                 res = compile_asm (acfg);
6059                 if (res != 0) {
6060                         acfg_free (acfg);
6061                         return res;
6062                 }
6063         }
6064         TV_GETTIME (btv);
6065         acfg->stats.link_time = TV_ELAPSED (atv, btv);
6066
6067         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);
6068         if (acfg->stats.genericcount)
6069                 printf ("%d methods are generic (%d%%)\n", acfg->stats.genericcount, acfg->stats.mcount ? (acfg->stats.genericcount * 100) / acfg->stats.mcount : 100);
6070         if (acfg->stats.abscount)
6071                 printf ("%d methods contain absolute addresses (%d%%)\n", acfg->stats.abscount, acfg->stats.mcount ? (acfg->stats.abscount * 100) / acfg->stats.mcount : 100);
6072         if (acfg->stats.lmfcount)
6073                 printf ("%d methods contain lmf pointers (%d%%)\n", acfg->stats.lmfcount, acfg->stats.mcount ? (acfg->stats.lmfcount * 100) / acfg->stats.mcount : 100);
6074         if (acfg->stats.ocount)
6075                 printf ("%d methods have other problems (%d%%)\n", acfg->stats.ocount, acfg->stats.mcount ? (acfg->stats.ocount * 100) / acfg->stats.mcount : 100);
6076         if (acfg->llvm)
6077                 printf ("Methods compiled with LLVM: %d (%d%%)\n", acfg->stats.llvm_count, acfg->stats.mcount ? (acfg->stats.llvm_count * 100) / acfg->stats.mcount : 100);
6078         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);
6079         printf ("Direct calls: %d (%d%%)\n", acfg->stats.direct_calls, acfg->stats.all_calls ? (acfg->stats.direct_calls * 100) / acfg->stats.all_calls : 100);
6080
6081         if (acfg->aot_opts.stats) {
6082                 int i;
6083
6084                 printf ("GOT slot distribution:\n");
6085                 for (i = 0; i < MONO_PATCH_INFO_NONE; ++i)
6086                         if (acfg->stats.got_slot_types [i])
6087                                 printf ("\t%s: %d\n", get_patch_name (i), acfg->stats.got_slot_types [i]);
6088         }
6089
6090         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);
6091
6092         acfg_free (acfg);
6093         
6094         return 0;
6095 }
6096
6097 #else
6098
6099 /* AOT disabled */
6100
6101 int
6102 mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
6103 {
6104         return 0;
6105 }
6106
6107 #endif