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