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