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