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