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