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