Fri Aug 18 19:38:28 CEST 2006 Paolo Molaro <lupus@ximian.com>
[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 #include "config.h"
12 #include <sys/types.h>
13 #include <unistd.h>
14 #include <fcntl.h>
15 #include <string.h>
16 #ifndef PLATFORM_WIN32
17 #include <sys/mman.h>
18 #else
19 #include <winsock2.h>
20 #include <windows.h>
21 #endif
22
23 #include <errno.h>
24 #include <sys/stat.h>
25 #include <limits.h>    /* for PAGESIZE */
26 #ifndef PAGESIZE
27 #define PAGESIZE 4096
28 #endif
29
30 #include <mono/metadata/tabledefs.h>
31 #include <mono/metadata/class.h>
32 #include <mono/metadata/object.h>
33 #include <mono/metadata/tokentype.h>
34 #include <mono/metadata/appdomain.h>
35 #include <mono/metadata/debug-helpers.h>
36 #include <mono/metadata/assembly.h>
37 #include <mono/metadata/metadata-internals.h>
38 #include <mono/metadata/marshal.h>
39 #include <mono/utils/mono-logger.h>
40 #include "mono/utils/mono-compiler.h"
41
42 #include "mini.h"
43
44 #ifndef DISABLE_AOT
45
46 #ifdef PLATFORM_WIN32
47 #define SHARED_EXT ".dll"
48 #elif defined(__ppc__) && defined(__MACH__)
49 #define SHARED_EXT ".dylib"
50 #else
51 #define SHARED_EXT ".so"
52 #endif
53
54 #if defined(sparc) || defined(__ppc__)
55 #define AS_STRING_DIRECTIVE ".asciz"
56 #else
57 /* GNU as */
58 #define AS_STRING_DIRECTIVE ".string"
59 #endif
60
61 #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
62 #define ROUND_DOWN(VALUE,SIZE)  ((VALUE) & ~((SIZE) - 1))
63
64 typedef struct MonoAotOptions {
65         char *outfile;
66         gboolean save_temps;
67         gboolean write_symbols;
68 } MonoAotOptions;
69
70 typedef struct MonoAotStats {
71         int ccount, mcount, lmfcount, abscount, wrappercount, ocount;
72         int code_size, info_size, ex_info_size, got_size, class_info_size, got_info_size, got_info_offsets_size;
73         int methods_without_got_slots, direct_calls, all_calls;
74         int got_slots;
75         int got_slot_types [MONO_PATCH_INFO_NONE];
76 } MonoAotStats;
77
78 /* emit mode */
79 enum {
80         EMIT_NONE,
81         EMIT_BYTE,
82         EMIT_LONG
83 };
84
85 typedef struct MonoAotCompile {
86         MonoImage *image;
87         MonoCompile **cfgs;
88         GHashTable *patch_to_plt_offset;
89         GHashTable *plt_offset_to_patch;
90         GHashTable *patch_to_shared_got_offset;
91         GPtrArray *shared_patches;
92         GHashTable *image_hash;
93         GHashTable *method_to_cfg;
94         GPtrArray *image_table;
95         GList *method_order;
96         guint32 got_offset, plt_offset;
97         guint32 *method_got_offsets;
98         gboolean *has_got_slots;
99         MonoAotOptions aot_opts;
100         guint32 nmethods;
101         guint32 opts;
102         MonoMemPool *mempool;
103         MonoAotStats stats;
104         FILE *fp;
105         char *tmpfname;
106         int mode; /* emit mode */
107         int col_count; /* bytes emitted per .byte line */
108 } MonoAotCompile;
109
110 /* Keep in synch with MonoJumpInfoType */
111 static const char* patch_types [] = {
112         "bb",
113         "abs",
114         "label",
115         "method",
116         "method_jump",
117         "method_rel",
118         "methodconst",
119         "internal_method",
120         "switch",
121         "exc",
122         "exc_name",
123         "class",
124         "image",
125         "field",
126         "vtable",
127         "class_init",
128         "sflda",
129         "ldstr",
130         "ldtoken",
131         "type_from_handle",
132         "r4",
133         "r8",
134         "ip",
135         "iid",
136         "adjusted_iid",
137         "bb_ovf",
138         "exc_ovf",
139         "wrapper",
140         "got_offset",
141         "declsec",
142         "none"
143 };
144
145 static gboolean 
146 is_got_patch (MonoJumpInfoType patch_type)
147 {
148 #ifdef __x86_64__
149         return TRUE;
150 #elif defined(__i386__)
151         return TRUE;
152 #else
153         return FALSE;
154 #endif
155 }
156
157 #if defined(__ppc__) && defined(__MACH__)
158 static int
159 ilog2(register int value)
160 {
161         int count = -1;
162         while (value & ~0xf) count += 4, value >>= 4;
163         while (value) count++, value >>= 1;
164         return count;
165 }
166 #endif
167
168 static void
169 emit_start (MonoAotCompile *acfg)
170 {
171         int i = g_file_open_tmp ("mono_aot_XXXXXX", &acfg->tmpfname, NULL);
172         acfg->fp = fdopen (i, "w+");
173         g_assert (acfg->fp);
174 }
175
176 static void
177 emit_unset_mode (MonoAotCompile *acfg)
178 {
179         if (acfg->mode == EMIT_NONE)
180                 return;
181         fprintf (acfg->fp, "\n");
182         acfg->mode = EMIT_NONE;
183 }
184
185 static void
186 emit_section_change (MonoAotCompile *acfg, const char *section_name, int subsection_index)
187 {
188         emit_unset_mode (acfg);
189 #if defined(PLATFORM_WIN32)
190         fprintf (acfg->fp, ".section %s\n", section_name);
191 #elif defined(sparc)
192         /* For solaris as, GNU as should accept the same */
193         fprintf (acfg->fp, ".section \"%s\"\n", section_name);
194 #elif defined(__ppc__) && defined(__MACH__)
195         /* This needs to be made more precise on mach. */
196         fprintf (acfg->fp, "%s\n", subsection_index == 0 ? ".text" : ".data");
197 #else
198         fprintf (acfg->fp, "%s %d\n", section_name, subsection_index);
199 #endif
200 }
201
202 static void
203 emit_symbol_type (MonoAotCompile *acfg, const char *name, gboolean func)
204 {
205         const char *stype;
206
207         if (func)
208                 stype = "function";
209         else
210                 stype = "object";
211
212         emit_unset_mode (acfg);
213 #if defined(sparc)
214         fprintf (acfg->fp, "\t.type %s,#%s\n", name, stype);
215 #elif defined(PLATFORM_WIN32)
216
217 #elif !(defined(__ppc__) && defined(__MACH__))
218         fprintf (acfg->fp, "\t.type %s,@%s\n", name, stype);
219 #elif defined(__x86_64__) || defined(__i386__)
220         fprintf (acfg->fp, "\t.type %s,@%s\n", name, stype);
221 #endif
222 }
223
224 static void
225 emit_global (MonoAotCompile *acfg, const char *name, gboolean func)
226 {
227         emit_unset_mode (acfg);
228 #if  (defined(__ppc__) && defined(__MACH__)) || defined(PLATFORM_WIN32)
229     // mach-o always uses a '_' prefix.
230         fprintf (acfg->fp, "\t.globl _%s\n", name);
231 #else
232         fprintf (acfg->fp, "\t.globl %s\n", name);
233 #endif
234
235         emit_symbol_type (acfg, name, func);
236 }
237
238 static void
239 emit_label (MonoAotCompile *acfg, const char *name)
240 {
241         emit_unset_mode (acfg);
242 #if (defined(__ppc__) && defined(__MACH__)) || defined(PLATFORM_WIN32)
243     // mach-o always uses a '_' prefix.
244         fprintf (acfg->fp, "_%s:\n", name);
245 #else
246         fprintf (acfg->fp, "%s:\n", name);
247 #endif
248
249 #if defined(PLATFORM_WIN32)
250         /* Emit a normal label too */
251         fprintf (acfg->fp, "%s:\n", name);
252 #endif
253 }
254
255 static void
256 emit_string (MonoAotCompile *acfg, const char *value)
257 {
258         emit_unset_mode (acfg);
259         fprintf (acfg->fp, "\t%s \"%s\"\n", AS_STRING_DIRECTIVE, value);
260 }
261
262 static void
263 emit_line (MonoAotCompile *acfg)
264 {
265         emit_unset_mode (acfg);
266         fprintf (acfg->fp, "\n");
267 }
268
269 static void
270 emit_string_symbol (MonoAotCompile *acfg, const char *name, const char *value)
271 {
272         emit_unset_mode (acfg);
273         emit_section_change (acfg, ".text", 1);
274         emit_global (acfg, name, FALSE);
275         emit_label (acfg, name);
276         emit_string (acfg, value);
277 }
278
279 static void 
280 emit_alignment (MonoAotCompile *acfg, int size)
281 {
282         emit_unset_mode (acfg);
283 #if defined(__ppc__) && defined(__MACH__)
284         // the mach-o assembler specifies alignments as powers of 2.
285         fprintf (acfg->fp, "\t.align %d\t; ilog2\n", ilog2(size));
286 #elif defined(__powerpc__)
287         /* ignore on linux/ppc */
288 #else
289         fprintf (acfg->fp, "\t.align %d\n", size);
290 #endif
291 }
292
293 static void
294 emit_pointer (MonoAotCompile *acfg, const char *target)
295 {
296         emit_unset_mode (acfg);
297         emit_alignment (acfg, sizeof (gpointer));
298 #if defined(__x86_64__)
299         fprintf (acfg->fp, "\t.quad %s\n", target);
300 #elif defined(sparc) && SIZEOF_VOID_P == 8
301         fprintf (acfg->fp, "\t.xword %s\n", target);
302 #else
303         fprintf (acfg->fp, "\t.long %s\n", target);
304 #endif
305 }
306
307 static void
308 emit_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
309 {
310         int i;
311         if (acfg->mode != EMIT_BYTE) {
312                 acfg->mode = EMIT_BYTE;
313                 acfg->col_count = 0;
314         }
315         for (i = 0; i < size; ++i, ++acfg->col_count) {
316                 if ((acfg->col_count % 32) == 0)
317                         fprintf (acfg->fp, "\n\t.byte ");
318                 else
319                         fprintf (acfg->fp, ", ");
320                 fprintf (acfg->fp, "0x%x", buf [i]);
321         }
322 }
323
324 static void
325 emit_int32 (MonoAotCompile *acfg, int value)
326 {
327         if (acfg->mode != EMIT_LONG) {
328                 acfg->mode = EMIT_LONG;
329                 acfg->col_count = 0;
330         }
331         if ((acfg->col_count++ % 8) == 0)
332                 fprintf (acfg->fp, "\n\t.long ");
333         else
334                 fprintf (acfg->fp, ", ");
335         fprintf (acfg->fp, "%d", value);
336 }
337
338 static void
339 emit_symbol_diff (MonoAotCompile *acfg, const char *end, const char* start, int offset)
340 {
341         if (acfg->mode != EMIT_LONG) {
342                 acfg->mode = EMIT_LONG;
343                 acfg->col_count = 0;
344         }
345         if ((acfg->col_count++ % 8) == 0)
346                 fprintf (acfg->fp, "\n\t.long ");
347         else
348                 fprintf (acfg->fp, ", ");
349         if (offset)
350                 fprintf (acfg->fp, "%s - %s %c %d", end, start, offset < 0? ' ': '+', offset);
351         else
352                 fprintf (acfg->fp, "%s - %s", end, start);
353 }
354
355 static void
356 emit_zero_bytes (MonoAotCompile *acfg, int num)
357 {
358         emit_unset_mode (acfg);
359         fprintf (acfg->fp, "\t.skip %d\n", num);
360 }
361
362 static void
363 emit_writeout (MonoAotCompile *acfg)
364 {
365         char *command, *objfile;
366         char *outfile_name, *tmp_outfile_name;
367
368         fclose (acfg->fp);
369
370 #if defined(__x86_64__)
371 #define AS_OPTIONS "--64"
372 #elif defined(sparc) && SIZEOF_VOID_P == 8
373 #define AS_OPTIONS "-xarch=v9"
374 #else
375 #define AS_OPTIONS ""
376 #endif
377         command = g_strdup_printf ("as %s %s -o %s.o", AS_OPTIONS, acfg->tmpfname, acfg->tmpfname);
378         printf ("Executing the native assembler: %s\n", command);
379         if (system (command) != 0) {
380                 g_free (command);
381                 return;
382         }
383
384         g_free (command);
385
386         if (acfg->aot_opts.outfile)
387                 outfile_name = g_strdup_printf ("%s", acfg->aot_opts.outfile);
388         else
389                 outfile_name = g_strdup_printf ("%s%s", acfg->image->name, SHARED_EXT);
390
391         tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
392
393 #if defined(sparc)
394         command = g_strdup_printf ("ld -shared -G -o %s %s.o", outfile_name, acfg->tmpfname);
395 #elif defined(__ppc__) && defined(__MACH__)
396         command = g_strdup_printf ("gcc -dynamiclib -o %s %s.o", outfile_name, acfg->tmpfname);
397 #elif defined(PLATFORM_WIN32)
398         command = g_strdup_printf ("gcc -shared --dll -mno-cygwin -o %s %s.o", outfile_name, acfg->tmpfname);
399 #else
400         command = g_strdup_printf ("ld -shared -o %s %s.o", outfile_name, acfg->tmpfname);
401 #endif
402         printf ("Executing the native linker: %s\n", command);
403         if (system (command) != 0) {
404                 g_free (tmp_outfile_name);
405                 g_free (outfile_name);
406                 g_free (command);
407                 return;
408         }
409
410         g_free (command);
411         objfile = g_strdup_printf ("%s.o", acfg->tmpfname);
412         unlink (objfile);
413         g_free (objfile);
414         /*com = g_strdup_printf ("strip --strip-unneeded %s%s", acfg->image->name, SHARED_EXT);
415         printf ("Stripping the binary: %s\n", com);
416         system (com);
417         g_free (com);*/
418
419         rename (tmp_outfile_name, outfile_name);
420
421         g_free (tmp_outfile_name);
422         g_free (outfile_name);
423
424         if (acfg->aot_opts.save_temps)
425                 printf ("Retained input file.\n");
426         else
427                 unlink (acfg->tmpfname);
428
429 }
430
431 static void
432 emit_byte (MonoAotCompile *acfg, guint8 val)
433 {
434         emit_bytes (acfg, &val, 1);
435 }
436
437 static guint32
438 mono_get_field_token (MonoClassField *field) 
439 {
440         MonoClass *klass = field->parent;
441         int i;
442
443         for (i = 0; i < klass->field.count; ++i) {
444                 if (field == &klass->fields [i])
445                         return MONO_TOKEN_FIELD_DEF | (klass->field.first + 1 + i);
446         }
447
448         g_assert_not_reached ();
449         return 0;
450 }
451
452 static inline void
453 encode_value (gint32 value, guint8 *buf, guint8 **endbuf)
454 {
455         guint8 *p = buf;
456
457         //printf ("ENCODE: %d 0x%x.\n", value, value);
458
459         /* 
460          * Same encoding as the one used in the metadata, extended to handle values
461          * greater than 0x1fffffff.
462          */
463         if ((value >= 0) && (value <= 127))
464                 *p++ = value;
465         else if ((value >= 0) && (value <= 16383)) {
466                 p [0] = 0x80 | (value >> 8);
467                 p [1] = value & 0xff;
468                 p += 2;
469         } else if ((value >= 0) && (value <= 0x1fffffff)) {
470                 p [0] = (value >> 24) | 0xc0;
471                 p [1] = (value >> 16) & 0xff;
472                 p [2] = (value >> 8) & 0xff;
473                 p [3] = value & 0xff;
474                 p += 4;
475         }
476         else {
477                 p [0] = 0xff;
478                 p [1] = (value >> 24) & 0xff;
479                 p [2] = (value >> 16) & 0xff;
480                 p [3] = (value >> 8) & 0xff;
481                 p [4] = value & 0xff;
482                 p += 5;
483         }
484         if (endbuf)
485                 *endbuf = p;
486 }
487
488 static guint32
489 get_image_index (MonoAotCompile *cfg, MonoImage *image)
490 {
491         guint32 index;
492
493         index = GPOINTER_TO_UINT (g_hash_table_lookup (cfg->image_hash, image));
494         if (index)
495                 return index - 1;
496         else {
497                 index = g_hash_table_size (cfg->image_hash);
498                 g_hash_table_insert (cfg->image_hash, image, GUINT_TO_POINTER (index + 1));
499                 g_ptr_array_add (cfg->image_table, image);
500                 return index;
501         }
502 }
503
504 static void
505 encode_klass_info (MonoAotCompile *cfg, MonoClass *klass, guint8 *buf, guint8 **endbuf)
506 {
507         if (!klass->type_token) {
508                 /* Array class */
509                 g_assert (klass->rank > 0);
510                 g_assert (klass->element_class->type_token);
511                 encode_value (MONO_TOKEN_TYPE_DEF, buf, &buf);
512                 encode_value (get_image_index (cfg, klass->image), buf, &buf);
513                 g_assert (mono_metadata_token_code (klass->element_class->type_token) == MONO_TOKEN_TYPE_DEF);
514                 encode_value (klass->element_class->type_token - MONO_TOKEN_TYPE_DEF, buf, &buf);
515                 encode_value (klass->rank, buf, &buf);
516         }
517         else {
518                 g_assert (mono_metadata_token_code (klass->type_token) == MONO_TOKEN_TYPE_DEF);
519                 encode_value (klass->type_token - MONO_TOKEN_TYPE_DEF, buf, &buf);
520                 encode_value (get_image_index (cfg, klass->image), buf, &buf);
521         }
522         *endbuf = buf;
523 }
524
525 static void
526 encode_field_info (MonoAotCompile *cfg, MonoClassField *field, guint8 *buf, guint8 **endbuf)
527 {
528         guint32 token = mono_get_field_token (field);
529
530         encode_klass_info (cfg, field->parent, buf, &buf);
531         g_assert (mono_metadata_token_code (token) == MONO_TOKEN_FIELD_DEF);
532         encode_value (token - MONO_TOKEN_FIELD_DEF, buf, &buf);
533         *endbuf = buf;
534 }
535
536 static void
537 encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 **endbuf)
538 {
539         guint32 image_index = get_image_index (acfg, method->klass->image);
540         guint32 token = method->token;
541         g_assert (image_index < 256);
542         g_assert (mono_metadata_token_table (token) == MONO_TABLE_METHOD);
543
544         encode_value ((image_index << 24) + (mono_metadata_token_index (token)), buf, &buf);
545         *endbuf = buf;
546 }
547
548 static gint
549 compare_patches (gconstpointer a, gconstpointer b)
550 {
551         int i, j;
552
553         i = (*(MonoJumpInfo**)a)->ip.i;
554         j = (*(MonoJumpInfo**)b)->ip.i;
555
556         if (i < j)
557                 return -1;
558         else
559                 if (i > j)
560                         return 1;
561         else
562                 return 0;
563 }
564
565 static int
566 get_plt_index (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
567 {
568         int res = -1;
569         int idx;
570
571         switch (patch_info->type) {
572         case MONO_PATCH_INFO_METHOD:
573         case MONO_PATCH_INFO_WRAPPER:
574         case MONO_PATCH_INFO_INTERNAL_METHOD:
575         case MONO_PATCH_INFO_CLASS_INIT: {
576                 MonoJumpInfo *new_ji = mono_patch_info_dup_mp (acfg->mempool, patch_info);
577                 gpointer patch_id = NULL;
578
579                 /* First check for an existing patch */
580                 switch (patch_info->type) {
581                 case MONO_PATCH_INFO_METHOD:
582                         patch_id = patch_info->data.method;
583                         break;
584                 case MONO_PATCH_INFO_INTERNAL_METHOD:
585                         patch_id = (gpointer)patch_info->data.name;
586                         break;
587                 case MONO_PATCH_INFO_CLASS_INIT:
588                         patch_id = patch_info->data.klass;
589                         break;
590                 case MONO_PATCH_INFO_WRAPPER:
591                         /* A bit ugly, but works */
592                         g_assert (patch_info->data.method->wrapper_type < sizeof (MonoMethod));
593                         patch_id = (gpointer)(((guint8*)patch_info->data.method) + patch_info->data.method->wrapper_type);
594                         break;
595                 default:
596                         g_assert_not_reached ();
597                 }
598
599                 if (patch_id) {
600                         idx = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->patch_to_plt_offset, patch_id));
601                         if (idx)
602                                 res = idx;
603                         else
604                                 g_hash_table_insert (acfg->patch_to_plt_offset, patch_id, GUINT_TO_POINTER (acfg->plt_offset));
605                 }
606
607                 if (res == -1) {
608                         res = acfg->plt_offset;
609                         g_hash_table_insert (acfg->plt_offset_to_patch, GUINT_TO_POINTER (acfg->plt_offset), new_ji);
610                         acfg->plt_offset ++;
611                 }
612
613                 /* Nullify the patch */
614                 patch_info->type = MONO_PATCH_INFO_NONE;
615
616                 return res;
617         }
618         default:
619                 return -1;
620         }
621 }
622
623 /**
624  * get_got_offset:
625  *
626  *   Returns the offset of the GOT slot where the runtime object resulting from resolving
627  * JI could be found if it exists, otherwise allocates a new one.
628  */
629 static guint32
630 get_got_offset (MonoAotCompile *acfg, MonoJumpInfo *ji)
631 {
632         guint32 got_offset;
633
634         got_offset = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->patch_to_shared_got_offset, ji));
635         if (got_offset)
636                 return got_offset - 1;
637
638         got_offset = acfg->got_offset;
639         acfg->got_offset ++;
640
641         acfg->stats.got_slots ++;
642         acfg->stats.got_slot_types [ji->type] ++;
643
644         return got_offset;
645 }
646
647 static guint32
648 get_shared_got_offset (MonoAotCompile *acfg, MonoJumpInfo *ji)
649 {
650         MonoJumpInfo *copy;
651         guint32 got_offset;
652
653         if (!g_hash_table_lookup (acfg->patch_to_shared_got_offset, ji)) {
654                 got_offset = get_got_offset (acfg, ji);
655                 copy = mono_patch_info_dup_mp (acfg->mempool, ji);
656                 g_hash_table_insert (acfg->patch_to_shared_got_offset, copy, GUINT_TO_POINTER (got_offset + 1));
657                 g_ptr_array_add (acfg->shared_patches, copy);
658         }
659
660         return get_got_offset (acfg, ji);
661 }
662
663 static void
664 emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg)
665 {
666         MonoMethod *method;
667         int i, pindex, method_index;
668         guint8 *code;
669         char *symbol;
670         int func_alignment = 16;
671         GPtrArray *patches;
672         MonoJumpInfo *patch_info;
673         MonoMethodHeader *header;
674         gboolean skip;
675         guint32 got_slot;
676
677         method = cfg->method;
678         code = cfg->native_code;
679         header = mono_method_get_header (method);
680
681         method_index = mono_metadata_token_index (method->token);
682
683         /* Make the labels local */
684         symbol = g_strdup_printf (".Lm_%x", method_index);
685
686         emit_alignment (acfg, func_alignment);
687         emit_label (acfg, symbol);
688         if (acfg->aot_opts.write_symbols)
689                 emit_global (acfg, symbol, TRUE);
690
691         if (cfg->verbose_level > 0)
692                 g_print ("Method %s emitted as %s\n", mono_method_full_name (method, TRUE), symbol);
693
694         acfg->stats.code_size += cfg->code_len;
695
696         /* Collect and sort relocations */
697         patches = g_ptr_array_new ();
698         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next)
699                 g_ptr_array_add (patches, patch_info);
700         g_ptr_array_sort (patches, compare_patches);
701
702         acfg->method_got_offsets [method_index] = acfg->got_offset;
703         for (i = 0; i < cfg->code_len; i++) {
704                 patch_info = NULL;
705                 for (pindex = 0; pindex < patches->len; ++pindex) {
706                         patch_info = g_ptr_array_index (patches, pindex);
707                         if (patch_info->ip.i == i)
708                                 break;
709                 }
710
711 #ifdef MONO_ARCH_HAVE_PIC_AOT
712
713                 skip = FALSE;
714                 if (patch_info && (pindex < patches->len)) {
715                         switch (patch_info->type) {
716                         case MONO_PATCH_INFO_LABEL:
717                         case MONO_PATCH_INFO_BB:
718                         case MONO_PATCH_INFO_NONE:
719                                 break;
720                         case MONO_PATCH_INFO_GOT_OFFSET: {
721                                 guint32 offset = mono_arch_get_patch_offset (code + i);
722                                 emit_bytes (acfg, code + i, offset);
723                                 emit_symbol_diff (acfg, "got", ".", offset);
724
725                                 i += offset + 4 - 1;
726                                 skip = TRUE;
727                                 break;
728                         }
729                         default: {
730                                 int plt_index;
731                                 char *direct_call_target;
732
733                                 if (!is_got_patch (patch_info->type))
734                                         break;
735
736                                 /*
737                                  * If this patch is a call, try emitting a direct call instead of
738                                  * through a PLT entry. This is possible if the called method is in
739                                  * the same assembly and requires no initialization.
740                                  */
741                                 direct_call_target = NULL;
742                                 if ((patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == cfg->method->klass->image)) {
743                                         MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
744                                         if (callee_cfg) {
745                                                 guint32 callee_idx = mono_metadata_token_index (callee_cfg->method->token);
746                                                 if (!acfg->has_got_slots [callee_idx] && (callee_cfg->method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)) {
747                                                         //printf ("DIRECT: %s %s\n", mono_method_full_name (cfg->method, TRUE), mono_method_full_name (callee_cfg->method, TRUE));
748                                                         direct_call_target = g_strdup_printf (".Lm_%x", mono_metadata_token_index (callee_cfg->method->token));
749                                                         patch_info->type = MONO_PATCH_INFO_NONE;
750                                                         acfg->stats.direct_calls ++;
751                                                 }
752                                         }
753
754                                         acfg->stats.all_calls ++;
755                                 }
756
757                                 if (!direct_call_target) {
758                                         plt_index = get_plt_index (acfg, patch_info);
759                                         if (plt_index != -1) {
760                                                 /* This patch has a PLT entry, so we must emit a call to the PLT entry */
761                                                 direct_call_target = g_strdup_printf (".Lp_%d", plt_index);
762                                         }
763                                 }
764
765                                 if (direct_call_target) {
766 #if defined(__i386__) || defined(__x86_64__)
767                                         g_assert (code [i] == 0xe8);
768                                         /* Need to make sure this is exactly 5 bytes long */
769                                         emit_byte (acfg, '\xe8');
770                                         emit_symbol_diff (acfg, direct_call_target, ".", -4);
771                                         i += 4;
772 #else
773                                         g_assert_not_reached ();
774 #endif
775                                 } else {
776                                         got_slot = get_got_offset (acfg, patch_info);
777
778                                         emit_bytes (acfg, code + i, mono_arch_get_patch_offset (code + i));
779 #ifdef __x86_64__
780                                         emit_symbol_diff (acfg, "got", ".", (unsigned int) ((got_slot * sizeof (gpointer)) - 4));
781 #elif defined(__i386__)
782                                         emit_int32 (acfg, (unsigned int) ((got_slot * sizeof (gpointer))));
783 #endif
784                                         
785                                         i += mono_arch_get_patch_offset (code + i) + 4 - 1;
786                                 }
787                                 skip = TRUE;
788                         }
789                         }
790                 }
791 #endif /* MONO_ARCH_HAVE_PIC_AOT */
792
793                 if (!skip)
794                         emit_bytes (acfg, code + i, 1);
795         }
796         emit_line (acfg);
797 }
798
799 /**
800  * encode_patch:
801  *
802  *  Encode PATCH_INFO into its disk representation. If SHARED is true, encode some types
803  * of patches by allocating a GOT entry for them, and encode the GOT offset instead.
804  */
805 static void
806 encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint8 **endbuf, gboolean shared)
807 {
808         guint8 *p = buf;
809
810         switch (patch_info->type) {
811         case MONO_PATCH_INFO_NONE:
812                 break;
813         case MONO_PATCH_INFO_IMAGE:
814                 encode_value (get_image_index (acfg, patch_info->data.image), p, &p);
815                 break;
816         case MONO_PATCH_INFO_METHOD_REL:
817                 encode_value ((gint)patch_info->data.offset, p, &p);
818                 break;
819         case MONO_PATCH_INFO_SWITCH: {
820                 gpointer *table = (gpointer *)patch_info->data.table->table;
821                 int k;
822
823                 encode_value (patch_info->data.table->table_size, p, &p);
824                 for (k = 0; k < patch_info->data.table->table_size; k++)
825                         encode_value ((int)(gssize)table [k], p, &p);
826                 break;
827         }
828         case MONO_PATCH_INFO_METHODCONST:
829         case MONO_PATCH_INFO_METHOD:
830         case MONO_PATCH_INFO_METHOD_JUMP:
831                 encode_method_ref (acfg, patch_info->data.method, p, &p);
832                 break;
833         case MONO_PATCH_INFO_INTERNAL_METHOD: {
834                 guint32 len = strlen (patch_info->data.name);
835
836                 encode_value (len, p, &p);
837
838                 memcpy (p, patch_info->data.name, len);
839                 p += len;
840                 *p++ = '\0';
841                 break;
842         }
843         case MONO_PATCH_INFO_LDSTR: {
844                 guint32 image_index = get_image_index (acfg, patch_info->data.token->image);
845                 guint32 token = patch_info->data.token->token;
846                 g_assert (mono_metadata_token_code (token) == MONO_TOKEN_STRING);
847                 /* 
848                  * An optimization would be to emit shared code for ldstr 
849                  * statements followed by a throw.
850                  */
851                 encode_value (image_index, p, &p);
852                 encode_value (patch_info->data.token->token - MONO_TOKEN_STRING, p, &p);
853                 break;
854         }
855         case MONO_PATCH_INFO_DECLSEC:
856         case MONO_PATCH_INFO_LDTOKEN:
857         case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
858                 if (shared) {
859                         guint32 offset = get_got_offset (acfg, patch_info);
860                         encode_value (offset, p, &p);
861                 } else {
862                         encode_value (get_image_index (acfg, patch_info->data.token->image), p, &p);
863                         encode_value (patch_info->data.token->token, p, &p);
864                 }
865                 break;
866         case MONO_PATCH_INFO_EXC_NAME: {
867                 MonoClass *ex_class;
868
869                 ex_class =
870                         mono_class_from_name (mono_defaults.exception_class->image,
871                                                                   "System", patch_info->data.target);
872                 g_assert (ex_class);
873                 encode_klass_info (acfg, ex_class, p, &p);
874                 break;
875         }
876         case MONO_PATCH_INFO_R4:
877                 encode_value (*((guint32 *)patch_info->data.target), p, &p);
878                 break;
879         case MONO_PATCH_INFO_R8:
880                 encode_value (*((guint32 *)patch_info->data.target), p, &p);
881                 encode_value (*(((guint32 *)patch_info->data.target) + 1), p, &p);
882                 break;
883         case MONO_PATCH_INFO_VTABLE:
884         case MONO_PATCH_INFO_CLASS:
885         case MONO_PATCH_INFO_IID:
886         case MONO_PATCH_INFO_ADJUSTED_IID:
887                 if (shared) {
888                         guint32 offset = get_got_offset (acfg, patch_info);
889                         encode_value (offset, p, &p);
890                 } else {
891                         encode_klass_info (acfg, patch_info->data.klass, p, &p);
892                 }
893                 break;
894         case MONO_PATCH_INFO_CLASS_INIT:
895                 encode_klass_info (acfg, patch_info->data.klass, p, &p);
896                 break;
897         case MONO_PATCH_INFO_FIELD:
898         case MONO_PATCH_INFO_SFLDA:
899                 if (shared) {
900                         guint32 offset = get_got_offset (acfg, patch_info);
901                         encode_value (offset, p, &p);
902                 } else {
903                         encode_field_info (acfg, patch_info->data.field, p, &p);
904                 }
905                 break;
906         case MONO_PATCH_INFO_WRAPPER: {
907                 encode_value (patch_info->data.method->wrapper_type, p, &p);
908
909                 switch (patch_info->data.method->wrapper_type) {
910                 case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK: {
911                         MonoMethod *m;
912                         guint32 image_index;
913                         guint32 token;
914
915                         m = mono_marshal_method_from_wrapper (patch_info->data.method);
916                         image_index = get_image_index (acfg, m->klass->image);
917                         token = m->token;
918                         g_assert (image_index < 256);
919                         g_assert (mono_metadata_token_table (token) == MONO_TABLE_METHOD);
920
921                         encode_value ((image_index << 24) + (mono_metadata_token_index (token)), p, &p);
922                         break;
923                 }
924                 case MONO_WRAPPER_PROXY_ISINST:
925                 case MONO_WRAPPER_LDFLD:
926                 case MONO_WRAPPER_LDFLDA:
927                 case MONO_WRAPPER_STFLD:
928                 case MONO_WRAPPER_LDFLD_REMOTE:
929                 case MONO_WRAPPER_STFLD_REMOTE:
930                 case MONO_WRAPPER_ISINST: {
931                         MonoClass *proxy_class = (MonoClass*)mono_marshal_method_from_wrapper (patch_info->data.method);
932                         encode_klass_info (acfg, proxy_class, p, &p);
933                         break;
934                 }
935                 case MONO_WRAPPER_STELEMREF:
936                         break;
937                 default:
938                         g_assert_not_reached ();
939                 }
940                 break;
941         }
942         default:
943                 g_warning ("unable to handle jump info %d", patch_info->type);
944                 g_assert_not_reached ();
945         }
946
947         *endbuf = p;
948 }
949
950 static void
951 emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
952 {
953         MonoMethod *method;
954         GList *l;
955         int j, pindex, buf_size, n_patches;
956         guint8 *code;
957         char *symbol;
958         GPtrArray *patches;
959         MonoJumpInfo *patch_info;
960         MonoMethodHeader *header;
961         guint32 last_offset, method_idx;
962         guint8 *p, *buf;
963         guint32 first_got_offset;
964
965         method = cfg->method;
966         code = cfg->native_code;
967         header = mono_method_get_header (method);
968
969         method_idx = mono_metadata_token_index (method->token);
970
971         /* Make the labels local */
972         symbol = g_strdup_printf (".Lm_%x_p", method_idx);
973
974         /* Sort relocations */
975         patches = g_ptr_array_new ();
976         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next)
977                 g_ptr_array_add (patches, patch_info);
978         g_ptr_array_sort (patches, compare_patches);
979
980         first_got_offset = acfg->method_got_offsets [mono_metadata_token_index (cfg->method->token)];
981
982         /**********************/
983         /* Encode method info */
984         /**********************/
985
986         buf_size = (patches->len < 1000) ? 40960 : 40960 + (patches->len * 64);
987         p = buf = g_malloc (buf_size);
988
989         if (mono_class_get_cctor (method->klass))
990                 encode_klass_info (acfg, method->klass, p, &p);
991         else
992                 /* Not needed when loading the method */
993                 encode_value (0, p, &p);
994
995         /* String table */
996         if (cfg->opt & MONO_OPT_SHARED) {
997                 encode_value (g_list_length (cfg->ldstr_list), p, &p);
998                 for (l = cfg->ldstr_list; l; l = l->next) {
999                         encode_value ((long)l->data, p, &p);
1000                 }
1001         }
1002         else
1003                 /* Used only in shared mode */
1004                 g_assert (!cfg->ldstr_list);
1005
1006         n_patches = 0;
1007         for (pindex = 0; pindex < patches->len; ++pindex) {
1008                 patch_info = g_ptr_array_index (patches, pindex);
1009                 
1010                 if ((patch_info->type == MONO_PATCH_INFO_LABEL) ||
1011                         (patch_info->type == MONO_PATCH_INFO_BB) ||
1012                         (patch_info->type == MONO_PATCH_INFO_GOT_OFFSET) ||
1013                         (patch_info->type == MONO_PATCH_INFO_NONE)) {
1014                         patch_info->type = MONO_PATCH_INFO_NONE;
1015                         /* Nothing to do */
1016                         continue;
1017                 }
1018
1019                 if ((patch_info->type == MONO_PATCH_INFO_IMAGE) && (patch_info->data.image == acfg->image)) {
1020                         /* Stored in a GOT slot initialized at module load time */
1021                         patch_info->type = MONO_PATCH_INFO_NONE;
1022                         continue;
1023                 }
1024
1025                 n_patches ++;
1026         }
1027
1028         if (n_patches)
1029                 g_assert (acfg->has_got_slots [method_idx]);
1030
1031         encode_value (n_patches, p, &p);
1032
1033         if (n_patches)
1034                 encode_value (first_got_offset, p, &p);
1035
1036         /* First encode the type+position table */
1037         last_offset = 0;
1038         j = 0;
1039         for (pindex = 0; pindex < patches->len; ++pindex) {
1040                 guint32 offset;
1041                 patch_info = g_ptr_array_index (patches, pindex);
1042                 
1043                 if (patch_info->type == MONO_PATCH_INFO_NONE)
1044                         /* Nothing to do */
1045                         continue;
1046
1047                 j ++;
1048                 //printf ("T: %d O: %d.\n", patch_info->type, patch_info->ip.i);
1049                 offset = patch_info->ip.i - last_offset;
1050                 last_offset = patch_info->ip.i;
1051
1052                 /* Only the type is needed */
1053                 *p = patch_info->type;
1054                 p++;
1055         }
1056
1057         /*
1058         if (n_patches) {
1059                 printf ("%s:\n", mono_method_full_name (cfg->method, TRUE));
1060                 for (pindex = 0; pindex < patches->len; ++pindex) {
1061                         patch_info = g_ptr_array_index (patches, pindex);
1062                         if (patch_info->type != MONO_PATCH_INFO_NONE) {
1063                                 printf ("\t%s", patch_types [patch_info->type]);
1064                                 if (patch_info->type == MONO_PATCH_INFO_VTABLE)
1065                                         printf (": %s\n", patch_info->data.klass->name);
1066                                 else
1067                                         printf ("\n");
1068                         }
1069                 }
1070         }
1071         */
1072
1073         /* Then encode the other info */
1074         for (pindex = 0; pindex < patches->len; ++pindex) {
1075                 patch_info = g_ptr_array_index (patches, pindex);
1076
1077                 encode_patch (acfg, patch_info, p, &p, TRUE);
1078         }
1079
1080         acfg->stats.info_size += p - buf;
1081
1082         /* Emit method info */
1083
1084         emit_label (acfg, symbol);
1085
1086         g_assert (p - buf < buf_size);
1087         emit_bytes (acfg, buf, p - buf);
1088         g_free (buf);
1089
1090         g_free (symbol);
1091 }
1092
1093 static void
1094 emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg)
1095 {
1096         MonoMethod *method;
1097         int k, buf_size;
1098         guint32 debug_info_size;
1099         guint8 *code;
1100         char *symbol;
1101         MonoMethodHeader *header;
1102         guint8 *p, *buf, *debug_info;
1103
1104         method = cfg->method;
1105         code = cfg->native_code;
1106         header = mono_method_get_header (method);
1107
1108         /* Make the labels local */
1109         symbol = g_strdup_printf (".Le_%x_p", mono_metadata_token_index (method->token));
1110
1111         buf_size = header->num_clauses * 256 + 128;
1112         p = buf = g_malloc (buf_size);
1113
1114         encode_value (cfg->code_len, p, &p);
1115         encode_value (cfg->used_int_regs, p, &p);
1116
1117         /* Exception table */
1118         if (header->num_clauses) {
1119                 MonoJitInfo *jinfo = cfg->jit_info;
1120
1121                 for (k = 0; k < header->num_clauses; ++k) {
1122                         MonoJitExceptionInfo *ei = &jinfo->clauses [k];
1123
1124                         encode_value (ei->exvar_offset, p, &p);
1125
1126                         if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
1127                                 encode_value ((gint)((guint8*)ei->data.filter - code), p, &p);
1128
1129                         encode_value ((gint)((guint8*)ei->try_start - code), p, &p);
1130                         encode_value ((gint)((guint8*)ei->try_end - code), p, &p);
1131                         encode_value ((gint)((guint8*)ei->handler_start - code), p, &p);
1132                 }
1133         }
1134
1135         mono_debug_serialize_debug_info (cfg, &debug_info, &debug_info_size);
1136
1137         encode_value (debug_info_size, p, &p);
1138         if (debug_info_size) {
1139                 memcpy (p, debug_info, debug_info_size);
1140                 p += debug_info_size;
1141                 g_free (debug_info);
1142         }
1143
1144         acfg->stats.ex_info_size += p - buf;
1145
1146         /* Emit info */
1147
1148         emit_label (acfg, symbol);
1149
1150         g_assert (p - buf < buf_size);
1151         emit_bytes (acfg, buf, p - buf);
1152         g_free (buf);
1153
1154         g_free (symbol);
1155 }
1156
1157 static void
1158 emit_klass_info (MonoAotCompile *acfg, guint32 token)
1159 {
1160         MonoClass *klass = mono_class_get (acfg->image, token);
1161         guint8 *p, *buf;
1162         int i, buf_size;
1163         char *label;
1164         gboolean no_special_static;
1165
1166         buf_size = 10240;
1167         p = buf = g_malloc (buf_size);
1168
1169         g_assert (klass);
1170
1171         mono_class_init (klass);
1172
1173         /* 
1174          * Emit all the information which is required for creating vtables so
1175          * the runtime does not need to create the MonoMethod structures which
1176          * take up a lot of space.
1177          */
1178
1179         no_special_static = !mono_class_has_special_static_fields (klass);
1180
1181         if (1) {
1182                 encode_value (klass->vtable_size, p, &p);
1183                 encode_value ((no_special_static << 7) | (klass->has_static_refs << 6) | (klass->has_references << 5) | ((klass->blittable << 4) | (klass->nested_classes ? 1 : 0) << 3) | (klass->has_cctor << 2) | (klass->has_finalize << 1) | klass->ghcimpl, p, &p);
1184                 if (klass->has_cctor)
1185                         encode_method_ref (acfg, mono_class_get_cctor (klass), p, &p);
1186                 if (klass->has_finalize)
1187                         encode_method_ref (acfg, mono_class_get_finalizer (klass), p, &p);
1188  
1189                 encode_value (klass->instance_size, p, &p);
1190                 encode_value (klass->class_size, p, &p);
1191                 encode_value (klass->packing_size, p, &p);
1192                 encode_value (klass->min_align, p, &p);
1193
1194                 for (i = 0; i < klass->vtable_size; ++i) {
1195                         MonoMethod *cm = klass->vtable [i];
1196
1197                         if (cm)
1198                                 encode_method_ref (acfg, cm, p, &p);
1199                         else
1200                                 encode_value (0, p, &p);
1201                 }
1202         }
1203
1204         acfg->stats.class_info_size += p - buf;
1205
1206         /* Emit the info */
1207         label = g_strdup_printf (".LK_I_%x", token - MONO_TOKEN_TYPE_DEF - 1);
1208         emit_label (acfg, label);
1209
1210         g_assert (p - buf < buf_size);
1211         emit_bytes (acfg, buf, p - buf);
1212         g_free (buf);
1213 }
1214
1215 /*
1216  * Calls made from AOTed code are routed through a table of jumps similar to the
1217  * ELF PLT (Program Linkage Table). The differences are the following:
1218  * - the ELF PLT entries make an indirect jump though the GOT so they expect the
1219  *   GOT pointer to be in EBX. We want to avoid this, so our table contains direct
1220  *   jumps. This means the jumps need to be patched when the address of the callee is
1221  *   known. Initially the PLT entries jump to code which transfer control to the
1222  *   AOT runtime through the first PLT entry.
1223  */
1224 static void
1225 emit_plt (MonoAotCompile *acfg)
1226 {
1227         char *symbol;
1228         int i, buf_size;
1229         guint8 *p, *buf;
1230         guint32 *plt_info_offsets;
1231
1232         /*
1233          * Encode info need to resolve PLT entries.
1234          */
1235         buf_size = acfg->plt_offset * 128;
1236         p = buf = g_malloc (buf_size);
1237
1238         plt_info_offsets = g_new0 (guint32, acfg->plt_offset);
1239
1240         for (i = 1; i < acfg->plt_offset; ++i) {
1241                 MonoJumpInfo *patch_info = g_hash_table_lookup (acfg->plt_offset_to_patch, GUINT_TO_POINTER (i));
1242
1243                 plt_info_offsets [i] = p - buf;
1244                 encode_value (patch_info->type, p, &p);
1245                 encode_patch (acfg, patch_info, p, &p, FALSE);
1246         }
1247
1248         emit_line (acfg);
1249         symbol = g_strdup_printf ("plt");
1250
1251         /* This section will be made read-write by the AOT loader */
1252         emit_section_change (acfg, ".text", 0);
1253         emit_global (acfg, symbol, TRUE);
1254         emit_alignment (acfg, PAGESIZE);
1255         emit_label (acfg, symbol);
1256
1257         /* 
1258          * The first plt entry is used to transfer code to the AOT loader. 
1259          */
1260         emit_label (acfg, ".Lp_0");
1261 #if defined(__i386__)
1262         /* It is filled up during loading by the AOT loader. */
1263         emit_zero_bytes (acfg, 16);
1264 #elif defined(__x86_64__)
1265         /* This should be exactly 16 bytes long */
1266         /* jmpq *<offset>(%rip) */
1267         emit_byte (acfg, '\xff');
1268         emit_byte (acfg, '\x25');
1269         emit_symbol_diff (acfg, "plt_jump_table", ".", -4);
1270         emit_zero_bytes (acfg, 10);
1271 #else
1272         g_assert_not_reached ();
1273 #endif
1274
1275         for (i = 1; i < acfg->plt_offset; ++i) {
1276                 char *label;
1277
1278                 label = g_strdup_printf (".Lp_%d", i);
1279                 emit_label (acfg, label);
1280                 g_free (label);
1281 #if defined(__i386__)
1282                 /* Need to make sure this is 5 bytes long */
1283                 emit_byte (acfg, '\xe9');
1284                 label = g_strdup_printf (".Lpd_%d", i);
1285                 emit_symbol_diff (acfg, label, ".", -4);
1286                 g_free (label);
1287 #elif defined(__x86_64__)
1288                 /*
1289                  * We can't emit jumps because they are 32 bits only so they can't be patched.
1290                  * So we emit a jump table instead whose entries are patched by the AOT loader to
1291                  * point to .Lpd entries. ELF stores these in the GOT too, but we don't, since
1292                  * methods with GOT entries can't be called directly.
1293                  * We also emit the default PLT code here since the PLT code will not be patched.
1294                  * An x86_64 plt entry is 16 bytes long, init_plt () depends on this.
1295                  */
1296                 /* jmpq *<offset>(%rip) */
1297                 emit_byte (acfg, '\xff');
1298                 emit_byte (acfg, '\x25');
1299                 emit_symbol_diff (acfg, "plt_jump_table", ".", (i * sizeof (gpointer)) -4);
1300                 /* mov <plt info offset>, %eax */
1301                 emit_byte (acfg, '\xb8');
1302                 emit_int32 (acfg, plt_info_offsets [i]);
1303                 /* jmp .Lp_0 */
1304                 emit_byte (acfg, '\xe9');
1305                 emit_symbol_diff (acfg, ".Lp_0", ".", -4);
1306 #else
1307                 g_assert_not_reached ();
1308 #endif
1309         }
1310
1311         symbol = g_strdup_printf ("plt_end");
1312         emit_global (acfg, symbol, TRUE);
1313         emit_label (acfg, symbol);
1314
1315         /* 
1316          * Emit the default targets for the PLT entries separately since these will not
1317          * be modified at runtime.
1318          */
1319         for (i = 1; i < acfg->plt_offset; ++i) {
1320                 char *label;
1321
1322                 label = g_strdup_printf (".Lpd_%d", i);
1323                 emit_label (acfg, label);
1324                 g_free (label);
1325
1326                 /* Put the offset into the register expected by mono_aot_plt_trampoline */
1327 #if defined(__i386__)
1328                 /* movl $const, %eax */
1329                 emit_byte (acfg, '\xb8');
1330                 emit_int32 (acfg, plt_info_offsets [i]);
1331                 /* jmp .Lp_0 */
1332                 emit_byte (acfg, '\xe9');
1333                 emit_symbol_diff (acfg, ".Lp_0", ".", -4);
1334 #elif defined(__x86_64__)
1335                 /* Emitted along with the PLT entries since they will not be patched */
1336 #else
1337                 g_assert_not_reached ();
1338 #endif
1339         }
1340
1341         /* Emit PLT info */
1342         symbol = g_strdup_printf ("plt_info");
1343         emit_global (acfg, symbol, FALSE);
1344         emit_label (acfg, symbol);
1345
1346         g_assert (p - buf < buf_size);
1347         emit_bytes (acfg, buf, p - buf);
1348         g_free (buf);
1349
1350         symbol = g_strdup_printf ("plt_jump_table_addr");
1351         emit_section_change (acfg, ".data", 0);
1352         emit_global (acfg, symbol, FALSE);
1353         emit_alignment (acfg, 8);
1354         emit_label (acfg, symbol);
1355         emit_pointer (acfg, "plt_jump_table");
1356
1357         symbol = g_strdup_printf ("plt_jump_table_size");
1358         emit_section_change (acfg, ".data", 0);
1359         emit_global (acfg, symbol, FALSE);
1360         emit_alignment (acfg, 8);
1361         emit_label (acfg, symbol);
1362         emit_symbol_diff (acfg, "plt_jump_table_end", "plt_jump_table", 0);
1363
1364         /* Don't make this a global so accesses don't need relocations */
1365         symbol = g_strdup_printf ("plt_jump_table");
1366         emit_section_change (acfg, ".bss", 0);
1367         emit_label (acfg, symbol);
1368
1369 #ifdef __x86_64__
1370         emit_zero_bytes (acfg, (int)(acfg->plt_offset * sizeof (gpointer)));
1371 #endif  
1372
1373         symbol = g_strdup_printf ("plt_jump_table_end");
1374         emit_label (acfg, symbol);
1375 }
1376
1377 static gboolean
1378 str_begins_with (const char *str1, const char *str2)
1379 {
1380         int len = strlen (str2);
1381         return strncmp (str1, str2, len) == 0;
1382 }
1383
1384 static void
1385 mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
1386 {
1387         gchar **args, **ptr;
1388
1389         memset (opts, 0, sizeof (*opts));
1390
1391         args = g_strsplit (aot_options ? aot_options : "", ",", -1);
1392         for (ptr = args; ptr && *ptr; ptr ++) {
1393                 const char *arg = *ptr;
1394
1395                 if (str_begins_with (arg, "outfile=")) {
1396                         opts->outfile = g_strdup (arg + strlen ("outfile="));
1397                 } else if (str_begins_with (arg, "save-temps")) {
1398                         opts->save_temps = TRUE;
1399                 } else if (str_begins_with (arg, "keep-temps")) {
1400                         opts->save_temps = TRUE;
1401                 } else if (str_begins_with (arg, "write-symbols")) {
1402                         opts->write_symbols = TRUE;
1403                 } else {
1404                         fprintf (stderr, "AOT : Unknown argument '%s'.\n", arg);
1405                         exit (1);
1406                 }
1407         }
1408 }
1409
1410 static void
1411 compile_method (MonoAotCompile *acfg, int index)
1412 {
1413         MonoCompile *cfg;
1414         MonoMethod *method;
1415         MonoJumpInfo *patch_info;
1416         gboolean skip;
1417         guint32 token = MONO_TOKEN_METHOD_DEF | (index + 1);
1418         guint32 method_idx;
1419
1420         method = mono_get_method (acfg->image, token, NULL);
1421
1422         method_idx = mono_metadata_token_index (method->token); 
1423                 
1424         /* fixme: maybe we can also precompile wrapper methods */
1425         if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
1426                 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
1427                 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
1428                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT)) {
1429                 //printf ("Skip (impossible): %s\n", mono_method_full_name (method, TRUE));
1430                 return;
1431         }
1432
1433         acfg->stats.mcount++;
1434
1435         /* fixme: we need to patch the IP for the LMF in that case */
1436         if (method->save_lmf) {
1437                 //printf ("Skip (needs lmf):  %s\n", mono_method_full_name (method, TRUE));
1438                 acfg->stats.lmfcount++;
1439                 return;
1440         }
1441
1442         /*
1443          * Since these methods are the only ones which are compiled with
1444          * AOT support, and they are not used by runtime startup/shutdown code,
1445          * the runtime will not see AOT methods during AOT compilation,so it
1446          * does not need to support them by creating a fake GOT etc.
1447          */
1448         cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), FALSE, TRUE, 0);
1449         if (cfg->exception_type != MONO_EXCEPTION_NONE) {
1450                 /* Let the exception happen at runtime */
1451                 return;
1452         }
1453
1454         if (cfg->disable_aot) {
1455                 //printf ("Skip (other): %s\n", mono_method_full_name (method, TRUE));
1456                 acfg->stats.ocount++;
1457                 mono_destroy_compile (cfg);
1458                 return;
1459         }
1460
1461         skip = FALSE;
1462         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
1463                 if (patch_info->type == MONO_PATCH_INFO_ABS) {
1464                         /* unable to handle this */
1465                         //printf ("Skip (abs addr):   %s %d\n", mono_method_full_name (method, TRUE), patch_info->type);
1466                         skip = TRUE;    
1467                         break;
1468                 }
1469         }
1470
1471         if (skip) {
1472                 acfg->stats.abscount++;
1473                 mono_destroy_compile (cfg);
1474                 return;
1475         }
1476
1477         /* some wrappers are very common */
1478         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
1479                 if (patch_info->type == MONO_PATCH_INFO_METHODCONST) {
1480                         switch (patch_info->data.method->wrapper_type) {
1481                         case MONO_WRAPPER_PROXY_ISINST:
1482                                 patch_info->type = MONO_PATCH_INFO_WRAPPER;
1483                         }
1484                 }
1485
1486                 if (patch_info->type == MONO_PATCH_INFO_METHOD) {
1487                         switch (patch_info->data.method->wrapper_type) {
1488                         case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
1489                         case MONO_WRAPPER_STFLD:
1490                         case MONO_WRAPPER_LDFLD:
1491                         case MONO_WRAPPER_LDFLDA:
1492                         case MONO_WRAPPER_LDFLD_REMOTE:
1493                         case MONO_WRAPPER_STFLD_REMOTE:
1494                         case MONO_WRAPPER_STELEMREF:
1495                         case MONO_WRAPPER_ISINST:
1496                         case MONO_WRAPPER_PROXY_ISINST:
1497                                 patch_info->type = MONO_PATCH_INFO_WRAPPER;
1498                                 break;
1499                         }
1500                 }
1501         }
1502
1503         skip = FALSE;
1504         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
1505                 switch (patch_info->type) {
1506                 case MONO_PATCH_INFO_METHOD:
1507                 case MONO_PATCH_INFO_METHODCONST:
1508                         if (patch_info->data.method->wrapper_type) {
1509                                 /* unable to handle this */
1510                                 //printf ("Skip (wrapper call):   %s %d -> %s\n", mono_method_full_name (method, TRUE), patch_info->type, mono_method_full_name (patch_info->data.method, TRUE));
1511                                 skip = TRUE;
1512                                 break;
1513                         }
1514                         if (!patch_info->data.method->token)
1515                                 /*
1516                                  * The method is part of a constructed type like Int[,].Set (). It doesn't
1517                                  * have a token, and we can't make one, since the parent type is part of
1518                                  * assembly which contains the element type, and not the assembly which
1519                                  * referenced this type.
1520                                  */
1521                                 skip = TRUE;
1522                         break;
1523                 case MONO_PATCH_INFO_VTABLE:
1524                 case MONO_PATCH_INFO_CLASS_INIT:
1525                 case MONO_PATCH_INFO_CLASS:
1526                 case MONO_PATCH_INFO_IID:
1527                 case MONO_PATCH_INFO_ADJUSTED_IID:
1528                         if (!patch_info->data.klass->type_token)
1529                                 if (!patch_info->data.klass->element_class->type_token)
1530                                         skip = TRUE;
1531                         break;
1532                 default:
1533                         break;
1534                 }
1535         }
1536
1537         if (skip) {
1538                 acfg->stats.wrappercount++;
1539                 mono_destroy_compile (cfg);
1540                 return;
1541         }
1542
1543         /* Determine whenever the method has GOT slots */
1544         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
1545                 switch (patch_info->type) {
1546                 case MONO_PATCH_INFO_LABEL:
1547                 case MONO_PATCH_INFO_BB:
1548                 case MONO_PATCH_INFO_GOT_OFFSET:
1549                 case MONO_PATCH_INFO_NONE:
1550                 case MONO_PATCH_INFO_METHOD:
1551                 case MONO_PATCH_INFO_INTERNAL_METHOD:
1552                 case MONO_PATCH_INFO_WRAPPER:
1553                         break;
1554                 case MONO_PATCH_INFO_IMAGE:
1555                         if (patch_info->data.image == acfg->image)
1556                                 /* Stored in GOT slot 0 */
1557                                 break;
1558                         /* Fall through */
1559                 default:
1560                         acfg->has_got_slots [method_idx] = TRUE;
1561                         break;
1562                 }
1563         }
1564
1565         if (!acfg->has_got_slots [method_idx])
1566                 acfg->stats.methods_without_got_slots ++;
1567
1568         /* Make a copy of the patch info which is in the mempool */
1569         {
1570                 MonoJumpInfo *patches = NULL, *patches_end = NULL;
1571
1572                 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
1573                         MonoJumpInfo *new_patch_info = mono_patch_info_dup_mp (acfg->mempool, patch_info);
1574
1575                         if (!patches)
1576                                 patches = new_patch_info;
1577                         else
1578                                 patches_end->next = new_patch_info;
1579                         patches_end = new_patch_info;
1580                 }
1581                 cfg->patch_info = patches;
1582         }
1583
1584         /* Free some fields used by cfg to conserve memory */
1585         mono_mempool_destroy (cfg->mempool);
1586         cfg->mempool = NULL;
1587         g_free (cfg->varinfo);
1588         cfg->varinfo = NULL;
1589         g_free (cfg->vars);
1590         cfg->vars = NULL;
1591         if (cfg->rs) {
1592                 mono_regstate_free (cfg->rs);
1593                 cfg->rs = NULL;
1594         }
1595
1596         //printf ("Compile:           %s\n", mono_method_full_name (method, TRUE));
1597
1598         acfg->cfgs [index] = cfg;
1599
1600         g_hash_table_insert (acfg->method_to_cfg, cfg->method, cfg);
1601
1602         acfg->stats.ccount++;
1603 }
1604
1605 static void
1606 load_profile_files (MonoAotCompile *acfg)
1607 {
1608         FILE *infile;
1609         char *tmp;
1610         int file_index, res, method_index, i;
1611         char ver [256];
1612         guint32 token;
1613
1614         file_index = 0;
1615         while (TRUE) {
1616                 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);
1617
1618                 if (!g_file_test (tmp, G_FILE_TEST_IS_REGULAR))
1619                         break;
1620
1621                 infile = fopen (tmp, "r");
1622                 g_assert (infile);
1623
1624                 printf ("Using profile data file '%s'\n", tmp);
1625
1626                 file_index ++;
1627
1628                 res = fscanf (infile, "%32s\n", ver);
1629                 if ((res != 1) || strcmp (ver, "#VER:1") != 0) {
1630                         printf ("Profile file has wrong version or invalid.\n");
1631                         continue;
1632                 }
1633
1634                 while (TRUE) {
1635                         res = fscanf (infile, "%d\n", &token);
1636                         if (res < 1)
1637                                 break;
1638
1639                         method_index = mono_metadata_token_index (token) - 1;
1640
1641                         if (!g_list_find (acfg->method_order, GUINT_TO_POINTER (method_index)))
1642                                 acfg->method_order = g_list_append (acfg->method_order, GUINT_TO_POINTER (method_index));
1643                 }
1644         }
1645
1646         /* Add missing methods */
1647         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
1648                 if (!g_list_find (acfg->method_order, GUINT_TO_POINTER (i)))
1649                         acfg->method_order = g_list_append (acfg->method_order, GUINT_TO_POINTER (i));
1650         }               
1651 }
1652
1653 /**
1654  * alloc_got_slots:
1655  *
1656  *  Collect all patches which have shared GOT entries and alloc entries for them. The
1657  * rest will get entries allocated during emit_code ().
1658  */
1659 static void
1660 alloc_got_slots (MonoAotCompile *acfg)
1661 {
1662         int i;
1663         GList *l;
1664         MonoJumpInfo *ji;
1665
1666         /* Slot 0 is reserved for the address of the current assembly */
1667         ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
1668         ji->type = MONO_PATCH_INFO_IMAGE;
1669         ji->data.image = acfg->image;
1670
1671         get_shared_got_offset (acfg, ji);
1672
1673         for (l = acfg->method_order; l != NULL; l = l->next) {
1674                 i = GPOINTER_TO_UINT (l->data);
1675
1676                 if (acfg->cfgs [i]) {
1677                         MonoCompile *cfg = acfg->cfgs [i];
1678
1679                         for (ji = cfg->patch_info; ji; ji = ji->next) {
1680                                 switch (ji->type) {
1681                                 case MONO_PATCH_INFO_VTABLE:
1682                                 case MONO_PATCH_INFO_CLASS:
1683                                 case MONO_PATCH_INFO_IID:
1684                                 case MONO_PATCH_INFO_ADJUSTED_IID:
1685                                 case MONO_PATCH_INFO_FIELD:
1686                                 case MONO_PATCH_INFO_SFLDA:
1687                                 case MONO_PATCH_INFO_DECLSEC:
1688                                 case MONO_PATCH_INFO_LDTOKEN:
1689                                 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
1690                                         get_shared_got_offset (acfg, ji);
1691                                         break;
1692                                 default:
1693                                         break;
1694                                 }
1695                         }
1696                 }
1697         }
1698 }
1699
1700 static void
1701 emit_code (MonoAotCompile *acfg)
1702 {
1703         int i;
1704         char *symbol;
1705         GList *l;
1706
1707         symbol = g_strdup_printf ("methods");
1708         emit_section_change (acfg, ".text", 0);
1709         emit_global (acfg, symbol, TRUE);
1710         emit_alignment (acfg, 8);
1711         emit_label (acfg, symbol);
1712
1713         for (l = acfg->method_order; l != NULL; l = l->next) {
1714                 i = GPOINTER_TO_UINT (l->data);
1715
1716                 if (acfg->cfgs [i])
1717                         emit_method_code (acfg, acfg->cfgs [i]);
1718         }
1719
1720         symbol = g_strdup_printf ("methods_end");
1721         emit_section_change (acfg, ".text", 0);
1722         emit_global (acfg, symbol, FALSE);
1723         emit_alignment (acfg, 8);
1724         emit_label (acfg, symbol);
1725
1726         symbol = g_strdup_printf ("method_offsets");
1727         emit_section_change (acfg, ".text", 1);
1728         emit_global (acfg, symbol, FALSE);
1729         emit_alignment (acfg, 8);
1730         emit_label (acfg, symbol);
1731
1732         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
1733                 if (acfg->cfgs [i]) {
1734                         symbol = g_strdup_printf (".Lm_%x", i + 1);
1735                         emit_symbol_diff (acfg, symbol, "methods", 0);
1736                 } else {
1737                         emit_int32 (acfg, 0xffffffff);
1738                 }
1739         }
1740         emit_line (acfg);
1741 }
1742
1743 static void
1744 emit_info (MonoAotCompile *acfg)
1745 {
1746         int i;
1747         char *symbol;
1748         GList *l;
1749
1750         /* Emit method info */
1751         symbol = g_strdup_printf ("method_info");
1752         emit_section_change (acfg, ".text", 1);
1753         emit_global (acfg, symbol, FALSE);
1754         emit_alignment (acfg, 8);
1755         emit_label (acfg, symbol);
1756
1757         /* To reduce size of generated assembly code */
1758         symbol = g_strdup_printf ("mi");
1759         emit_label (acfg, symbol);
1760
1761         for (l = acfg->method_order; l != NULL; l = l->next) {
1762                 i = GPOINTER_TO_UINT (l->data);
1763
1764                 if (acfg->cfgs [i])
1765                         emit_method_info (acfg, acfg->cfgs [i]);
1766         }
1767
1768         symbol = g_strdup_printf ("method_info_offsets");
1769         emit_section_change (acfg, ".text", 1);
1770         emit_global (acfg, symbol, FALSE);
1771         emit_alignment (acfg, 8);
1772         emit_label (acfg, symbol);
1773
1774         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
1775                 if (acfg->cfgs [i]) {
1776                         symbol = g_strdup_printf (".Lm_%x_p", i + 1);
1777                         emit_symbol_diff (acfg, symbol, "mi", 0);
1778                 } else {
1779                         emit_int32 (acfg, 0);
1780                 }
1781         }
1782         emit_line (acfg);
1783 }
1784
1785 static void
1786 emit_method_order (MonoAotCompile *acfg)
1787 {
1788         int i, index, len;
1789         char *symbol;
1790         GList *l;
1791
1792         symbol = g_strdup_printf ("method_order");
1793         emit_section_change (acfg, ".text", 1);
1794         emit_global (acfg, symbol, FALSE);
1795         emit_alignment (acfg, 8);
1796         emit_label (acfg, symbol);
1797
1798         /* First emit an index table */
1799         index = 0;
1800         len = 0;
1801         for (l = acfg->method_order; l != NULL; l = l->next) {
1802                 i = GPOINTER_TO_UINT (l->data);
1803
1804                 if (acfg->cfgs [i]) {
1805                         if ((index % 1024) == 0) {
1806                                 emit_int32 (acfg, i);
1807                         }
1808
1809                         index ++;
1810                 }
1811
1812                 len ++;
1813         }
1814         emit_int32 (acfg, 0xffffff);
1815
1816         /* Then emit the whole method order */
1817         for (l = acfg->method_order; l != NULL; l = l->next) {
1818                 i = GPOINTER_TO_UINT (l->data);
1819
1820                 if (acfg->cfgs [i]) {
1821                         emit_int32 (acfg, i);
1822                 }
1823         }       
1824         emit_line (acfg);
1825
1826         symbol = g_strdup_printf ("method_order_end");
1827         emit_section_change (acfg, ".text", 1);
1828         emit_global (acfg, symbol, FALSE);
1829         emit_label (acfg, symbol);
1830 }
1831
1832 static void
1833 emit_exception_info (MonoAotCompile *acfg)
1834 {
1835         int i;
1836         char *symbol;
1837
1838         symbol = g_strdup_printf ("ex_info");
1839         emit_section_change (acfg, ".text", 1);
1840         emit_global (acfg, symbol, FALSE);
1841         emit_alignment (acfg, 8);
1842         emit_label (acfg, symbol);
1843
1844         /* To reduce size of generate assembly */
1845         symbol = g_strdup_printf ("ex");
1846         emit_label (acfg, symbol);
1847
1848         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
1849                 if (acfg->cfgs [i])
1850                         emit_exception_debug_info (acfg, acfg->cfgs [i]);
1851         }
1852
1853         symbol = g_strdup_printf ("ex_info_offsets");
1854         emit_section_change (acfg, ".text", 1);
1855         emit_global (acfg, symbol, FALSE);
1856         emit_alignment (acfg, 8);
1857         emit_label (acfg, symbol);
1858
1859         for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
1860                 if (acfg->cfgs [i]) {
1861                         symbol = g_strdup_printf (".Le_%x_p", i + 1);
1862                         emit_symbol_diff (acfg, symbol, "ex", 0);
1863                 } else {
1864                         emit_int32 (acfg, 0);
1865                 }
1866         }
1867         emit_line (acfg);
1868 }
1869
1870 static void
1871 emit_class_info (MonoAotCompile *acfg)
1872 {
1873         int i;
1874         char *symbol;
1875
1876         symbol = g_strdup_printf ("class_info");
1877         emit_section_change (acfg, ".text", 1);
1878         emit_global (acfg, symbol, FALSE);
1879         emit_alignment (acfg, 8);
1880         emit_label (acfg, symbol);
1881
1882         for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i)
1883                 emit_klass_info (acfg, MONO_TOKEN_TYPE_DEF | (i + 1));
1884
1885         symbol = g_strdup_printf ("class_info_offsets");
1886         emit_section_change (acfg, ".text", 1);
1887         emit_global (acfg, symbol, FALSE);
1888         emit_alignment (acfg, 8);
1889         emit_label (acfg, symbol);
1890
1891         for (i = 0; i < acfg->image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
1892                 symbol = g_strdup_printf (".LK_I_%x", i);
1893                 emit_symbol_diff (acfg, symbol, "class_info", 0);
1894         }
1895         emit_line (acfg);
1896 }
1897
1898 static void
1899 emit_image_table (MonoAotCompile *acfg)
1900 {
1901         int i;
1902         char *symbol;
1903
1904         /*
1905          * The image table is small but referenced in a lot of places.
1906          * So we emit it at once, and reference its elements by an index.
1907          */
1908
1909         symbol = g_strdup_printf ("mono_image_table");
1910         emit_section_change (acfg, ".text", 1);
1911         emit_global (acfg, symbol, FALSE);
1912         emit_alignment (acfg, 8);
1913         emit_label (acfg, symbol);
1914         emit_int32 (acfg, acfg->image_table->len);
1915         for (i = 0; i < acfg->image_table->len; i++) {
1916                 MonoImage *image = (MonoImage*)g_ptr_array_index (acfg->image_table, i);
1917                 MonoAssemblyName *aname = &image->assembly->aname;
1918
1919                 /* FIXME: Support multi-module assemblies */
1920                 g_assert (image->assembly->image == image);
1921
1922                 emit_string (acfg, image->assembly_name);
1923                 emit_string (acfg, image->guid);
1924                 emit_string (acfg, aname->culture ? aname->culture : "");
1925                 emit_string (acfg, (const char*)aname->public_key_token);
1926
1927                 emit_alignment (acfg, 8);
1928                 emit_int32 (acfg, aname->flags);
1929                 emit_int32 (acfg, aname->major);
1930                 emit_int32 (acfg, aname->minor);
1931                 emit_int32 (acfg, aname->build);
1932                 emit_int32 (acfg, aname->revision);
1933         }
1934 }
1935
1936 static void
1937 emit_got_info (MonoAotCompile *acfg)
1938 {
1939         char *symbol;
1940         int i, buf_size;
1941         guint8 *p, *buf;
1942         guint32 *got_info_offsets;
1943
1944         /**
1945          * FIXME: 
1946          * - optimize offsets table.
1947          * - reduce number of exported symbols.
1948          * - emit info for a klass only once.
1949          * - determine when a method uses a GOT slot which is guaranteed to be already 
1950          *   initialized.
1951          * - clean up and document the code.
1952          * - use String.Empty in class libs.
1953          */
1954
1955         /* Encode info required to decode shared GOT entries */
1956         buf_size = acfg->shared_patches->len * 64;
1957         p = buf = mono_mempool_alloc (acfg->mempool, buf_size);
1958         got_info_offsets = mono_mempool_alloc (acfg->mempool, acfg->shared_patches->len * sizeof (guint32));
1959         for (i = 0; i < acfg->shared_patches->len; ++i) {
1960                 MonoJumpInfo *ji = g_ptr_array_index (acfg->shared_patches, i);
1961
1962                 /* No need to encode the patch type */
1963                 got_info_offsets [i] = p - buf;
1964                 encode_patch (acfg, ji, p, &p, FALSE);
1965         }
1966
1967         g_assert (p - buf <= buf_size);
1968
1969         acfg->stats.got_info_size = p - buf;
1970
1971         /* Emit got_info table */
1972         symbol = g_strdup_printf ("got_info");
1973         emit_section_change (acfg, ".text", 1);
1974         emit_global (acfg, symbol, FALSE);
1975         emit_alignment (acfg, 8);
1976         emit_label (acfg, symbol);
1977
1978         emit_bytes (acfg, buf, p - buf);
1979
1980         /* Emit got_info_offsets table */
1981         symbol = g_strdup_printf ("got_info_offsets");
1982         emit_section_change (acfg, ".text", 1);
1983         emit_global (acfg, symbol, FALSE);
1984         emit_alignment (acfg, 8);
1985         emit_label (acfg, symbol);
1986
1987         for (i = 0; i < acfg->shared_patches->len; ++i)
1988                 emit_int32 (acfg, got_info_offsets [i]);
1989
1990         acfg->stats.got_info_offsets_size = acfg->shared_patches->len * 4;
1991 }
1992
1993 static void
1994 emit_got (MonoAotCompile *acfg)
1995 {
1996         char *symbol;
1997
1998         /* Don't make GOT global so accesses to it don't need relocations */
1999         symbol = g_strdup_printf ("got");
2000         emit_section_change (acfg, ".bss", 1);
2001         emit_alignment (acfg, 8);
2002         emit_label (acfg, symbol);
2003         if (acfg->got_offset > 0)
2004                 emit_zero_bytes (acfg, (int)(acfg->got_offset * sizeof (gpointer)));
2005
2006         symbol = g_strdup_printf ("got_addr");
2007         emit_section_change (acfg, ".data", 1);
2008         emit_global (acfg, symbol, FALSE);
2009         emit_alignment (acfg, 8);
2010         emit_label (acfg, symbol);
2011         emit_pointer (acfg, "got");
2012
2013         symbol = g_strdup_printf ("got_size");
2014         emit_section_change (acfg, ".data", 1);
2015         emit_global (acfg, symbol, FALSE);
2016         emit_alignment (acfg, 8);
2017         emit_label (acfg, symbol);
2018         emit_int32 (acfg, (int)(acfg->got_offset * sizeof (gpointer)));
2019 }
2020
2021 static void
2022 emit_globals (MonoAotCompile *acfg)
2023 {
2024         char *opts_str;
2025
2026         emit_string_symbol (acfg, "mono_assembly_guid" , acfg->image->guid);
2027
2028         emit_string_symbol (acfg, "mono_aot_version", MONO_AOT_FILE_VERSION);
2029
2030         opts_str = g_strdup_printf ("%d", acfg->opts);
2031         emit_string_symbol (acfg, "mono_aot_opt_flags", opts_str);
2032         g_free (opts_str);
2033 }
2034
2035 int
2036 mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
2037 {
2038         MonoImage *image = ass->image;
2039         char *symbol;
2040         int i;
2041         MonoAotCompile *acfg;
2042         MonoCompile **cfgs;
2043
2044         printf ("Mono Ahead of Time compiler - compiling assembly %s\n", image->name);
2045
2046         acfg = g_new0 (MonoAotCompile, 1);
2047         acfg->plt_offset_to_patch = g_hash_table_new (NULL, NULL);
2048         acfg->patch_to_plt_offset = g_hash_table_new (NULL, NULL);
2049         acfg->patch_to_shared_got_offset = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
2050         acfg->shared_patches = g_ptr_array_new ();
2051         acfg->method_to_cfg = g_hash_table_new (NULL, NULL);
2052         acfg->image_hash = g_hash_table_new (NULL, NULL);
2053         acfg->image_table = g_ptr_array_new ();
2054         acfg->image = image;
2055         acfg->opts = opts;
2056         acfg->mempool = mono_mempool_new ();
2057
2058         mono_aot_parse_options (aot_options, &acfg->aot_opts);
2059
2060         load_profile_files (acfg);
2061
2062         emit_start (acfg);
2063
2064         cfgs = g_new0 (MonoCompile*, image->tables [MONO_TABLE_METHOD].rows + 32);
2065         acfg->cfgs = cfgs;
2066         acfg->nmethods = image->tables [MONO_TABLE_METHOD].rows;
2067         acfg->method_got_offsets = g_new0 (guint32, image->tables [MONO_TABLE_METHOD].rows + 32);
2068         acfg->has_got_slots = g_new0 (gboolean, image->tables [MONO_TABLE_METHOD].rows + 32);
2069
2070         /* PLT offset 0 is reserved for the PLT trampoline */
2071         acfg->plt_offset = 1;
2072
2073         /* Compile methods */
2074         for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i)
2075                 compile_method (acfg, i);
2076
2077         alloc_got_slots (acfg);
2078
2079         emit_code (acfg);
2080
2081         emit_info (acfg);
2082
2083         emit_method_order (acfg);
2084
2085         emit_got_info (acfg);
2086
2087         emit_exception_info (acfg);
2088
2089         emit_class_info (acfg);
2090
2091         emit_plt (acfg);
2092
2093         emit_image_table (acfg);
2094
2095         emit_got (acfg);
2096
2097         emit_globals (acfg);
2098
2099         symbol = g_strdup_printf ("mem_end");
2100         emit_section_change (acfg, ".text", 1);
2101         emit_global (acfg, symbol, FALSE);
2102         emit_alignment (acfg, 8);
2103         emit_label (acfg, symbol);
2104
2105         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)));
2106
2107         emit_writeout (acfg);
2108
2109         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);
2110         printf ("%d methods contain absolute addresses (%d%%)\n", acfg->stats.abscount, acfg->stats.mcount ? (acfg->stats.abscount * 100) / acfg->stats.mcount : 100);
2111         printf ("%d methods contain wrapper references (%d%%)\n", acfg->stats.wrappercount, acfg->stats.mcount ? (acfg->stats.wrappercount * 100) / acfg->stats.mcount : 100);
2112         printf ("%d methods contain lmf pointers (%d%%)\n", acfg->stats.lmfcount, acfg->stats.mcount ? (acfg->stats.lmfcount * 100) / acfg->stats.mcount : 100);
2113         printf ("%d methods have other problems (%d%%)\n", acfg->stats.ocount, acfg->stats.mcount ? (acfg->stats.ocount * 100) / acfg->stats.mcount : 100);
2114         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);
2115         printf ("Direct calls: %d (%d%%)\n", acfg->stats.direct_calls, acfg->stats.all_calls ? (acfg->stats.direct_calls * 100) / acfg->stats.all_calls : 100);
2116
2117         printf ("GOT slot distribution:\n");
2118         for (i = 0; i < MONO_PATCH_INFO_NONE; ++i)
2119                 if (acfg->stats.got_slot_types [i])
2120                         printf ("\t%s: %d\n", patch_types [i], acfg->stats.got_slot_types [i]);
2121
2122         return 0;
2123 }
2124
2125 #else
2126
2127 /* AOT disabled */
2128
2129 int
2130 mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
2131 {
2132         return 0;
2133 }
2134
2135 #endif