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