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