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