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