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