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