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