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