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