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