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