2 * aot.c: mono Ahead of Time compiler
5 * Dietmar Maurer (dietmar@ximian.com)
7 * (C) 2002 Ximian, Inc.
11 #include <sys/types.h>
15 #ifndef PLATFORM_WIN32
21 #include <limits.h> /* for PAGESIZE */
26 #include <mono/metadata/tabledefs.h>
27 #include <mono/metadata/class.h>
28 #include <mono/metadata/object.h>
29 #include <mono/metadata/tokentype.h>
30 #include <mono/metadata/appdomain.h>
31 #include <mono/metadata/debug-helpers.h>
32 #include <mono/metadata/assembly.h>
33 #include <mono/os/gc_wrapper.h>
37 #define ENCODE_TYPE_POS(t,l) (((t) << 24) | (l))
38 #define DECODE_TYPE(v) ((v) >> 24)
39 #define DECODE_POS(v) ((v) & 0xffffff)
42 #define SHARED_EXT ".dll"
44 #define SHARED_EXT ".so"
47 typedef struct MonoAotMethodInfo {
49 MonoJumpInfo *patch_info;
52 typedef struct MonoAotModuleInfo {
53 /* Optimization flags used to compile the module */
55 /* Maps MonoMethods to MonoAotMethodInfos */
56 MonoGHashTable *methods;
59 static MonoGHashTable *aot_modules;
61 static CRITICAL_SECTION aot_mutex;
64 decode_class_info (gpointer *data)
69 image = mono_image_loaded_by_guid ((char *)data [1]);
73 return mono_class_get (image, (guint32)data [0]);
75 klass = decode_class_info (data [3]);
76 return mono_array_class_get (klass, (guint32)data [2]);
83 load_aot_module (MonoAssembly *assembly, gpointer user_data)
86 MonoAotModuleInfo *info;
87 gboolean usable = TRUE;
88 char *saved_guid = NULL;
89 char *aot_version = NULL;
90 char *opt_flags = NULL;
92 aot_name = g_strdup_printf ("%s.so", assembly->image->name);
94 assembly->aot_module = g_module_open (aot_name, G_MODULE_BIND_LAZY);
96 if (!assembly->aot_module)
99 g_module_symbol (assembly->aot_module, "mono_assembly_guid", (gpointer *) &saved_guid);
100 g_module_symbol (assembly->aot_module, "mono_aot_version", (gpointer *) &aot_version);
101 g_module_symbol (assembly->aot_module, "mono_aot_opt_flags", (gpointer *)&opt_flags);
103 if (!aot_version || strcmp (aot_version, MONO_AOT_FILE_VERSION)) {
104 printf ("AOT module %s has wrong file format version (expected %s got %s)\n", aot_name, MONO_AOT_FILE_VERSION, aot_version);
108 if (!saved_guid || strcmp (assembly->image->guid, saved_guid)) {
109 printf ("AOT module %s has a different GUID than the corresponding assembly.\n", aot_name);
115 g_module_close (assembly->aot_module);
116 assembly->aot_module = NULL;
121 * It seems that MonoGHashTables are in the GC heap, so structures
122 * containing them must be in the GC heap as well :(
125 info = GC_MALLOC (sizeof (MonoAotModuleInfo));
127 info = g_new0 (MonoAotModuleInfo, 1);
129 info->methods = mono_g_hash_table_new (NULL, NULL);
130 sscanf (opt_flags, "%d", &info->opts);
132 EnterCriticalSection (&aot_mutex);
133 mono_g_hash_table_insert (aot_modules, assembly, info);
134 LeaveCriticalSection (&aot_mutex);
136 printf ("Loaded AOT Module for %s.\n", assembly->image->name);
142 InitializeCriticalSection (&aot_mutex);
144 aot_modules = mono_g_hash_table_new (NULL, NULL);
146 mono_install_assembly_load_hook (load_aot_module, NULL);
150 mono_aot_get_method_inner (MonoDomain *domain, MonoMethod *method)
152 MonoClass *klass = method->klass;
153 MonoAssembly *ass = klass->image->assembly;
154 MonoJumpInfo *patch_info = NULL;
155 GModule *module = ass->aot_module;
156 char *method_label, *info_label;
159 guint code_len, used_int_regs, used_strings;
160 MonoAotModuleInfo *aot_module;
161 MonoAotMethodInfo *minfo;
170 aot_module = (MonoAotModuleInfo*)mono_g_hash_table_lookup (aot_modules, ass);
172 g_assert (klass->inited);
174 minfo = mono_g_hash_table_lookup (aot_module->methods, method);
178 jinfo = mono_mempool_alloc0 (domain->mp, sizeof (MonoJitInfo));
179 memcpy (jinfo, minfo->info, sizeof (MonoJitInfo));
181 /* This method was already loaded in another appdomain */
182 if (aot_module->opts & MONO_OPT_SHARED)
183 /* Use the same method in the new appdomain */
186 /* Create a copy of the original method and apply relocations */
188 code = mono_mempool_alloc (domain->code_mp, minfo->info->code_size);
189 memcpy (code, minfo->info->code_start, minfo->info->code_size);
191 //printf ("REUSE METHOD: %s %p - %p.\n", mono_method_full_name (method, TRUE), code, (char*)code + code_len);
193 /* Do this outside the lock to avoid deadlocks */
194 LeaveCriticalSection (&aot_mutex);
195 mono_arch_patch_code (method, domain, code, minfo->patch_info);
196 EnterCriticalSection (&aot_mutex);
198 jinfo->code_start = code;
201 mono_jit_info_table_add (domain, jinfo);
202 return jinfo->code_start;
205 method_label = g_strdup_printf ("method_%08X", method->token);
207 if (!g_module_symbol (module, method_label, (gpointer *)&code)) {
208 g_free (method_label);
212 info_label = g_strdup_printf ("%s_patch_info", method_label);
213 if (!g_module_symbol (module, info_label, (gpointer *)&info)) {
214 g_free (method_label);
220 static int count = 0;
224 if (getenv ("MONO_LASTAOT")) {
225 if (count > atoi(getenv ("MONO_LASTAOT"))) {
229 if (count == atoi(getenv ("MONO_LASTAOT")))
230 printf ("LAST AOT METHOD: %s.%s.%s.\n", klass->name_space, klass->name, method->name);
234 code_len = GPOINTER_TO_UINT (*((gpointer **)info));
236 used_int_regs = GPOINTER_TO_UINT (*((gpointer **)info));
238 used_strings = GPOINTER_TO_UINT (*((gpointer **)info));
241 //printf ("FOUND AOT compiled code for %s %p - %p %p\n", mono_method_full_name (method, TRUE), code, code + code_len, info);
243 for (i = 0; i < used_strings; i++) {
244 guint token = GPOINTER_TO_UINT (*((gpointer **)info));
246 mono_ldstr (mono_root_domain, klass->image, mono_metadata_token_index (token));
250 minfo = GC_MALLOC (sizeof (MonoAotMethodInfo));
252 minfo = g_new0 (MonoAotMethodInfo, 1);
256 MonoMemPool *mp = mono_mempool_new ();
264 MonoJumpInfo *ji = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfo));
265 gpointer *data = *((gpointer **)info);
267 ji->type = DECODE_TYPE (GPOINTER_TO_UINT (*info));
268 ji->ip.i = DECODE_POS (GPOINTER_TO_UINT (*info));
271 case MONO_PATCH_INFO_CLASS:
272 ji->data.klass = decode_class_info (data);
273 g_assert (ji->data.klass);
274 mono_class_init (ji->data.klass);
276 case MONO_PATCH_INFO_VTABLE:
277 ji->data.klass = decode_class_info (data);
278 g_assert (ji->data.klass);
279 mono_class_init (ji->data.klass);
281 case MONO_PATCH_INFO_IMAGE:
282 ji->data.image = mono_image_loaded_by_guid ((char *)data);
283 g_assert (ji->data.image);
285 case MONO_PATCH_INFO_METHOD:
286 case MONO_PATCH_INFO_METHODCONST:
287 image = mono_image_loaded_by_guid ((char *)data [1]);
289 ji->data.method = mono_get_method (image, (guint32)data [0], NULL);
290 g_assert (ji->data.method);
291 mono_class_init (ji->data.method->klass);
293 case MONO_PATCH_INFO_FIELD:
294 case MONO_PATCH_INFO_SFLDA:
295 image = mono_image_loaded_by_guid ((char *)data [1]);
297 ji->data.field = mono_field_from_token (image, (guint32)data [0], NULL);
298 mono_class_init (ji->data.field->parent);
299 g_assert (ji->data.field);
301 case MONO_PATCH_INFO_INTERNAL_METHOD:
302 ji->data.name = (char *)data;
303 g_assert (ji->data.name);
305 case MONO_PATCH_INFO_SWITCH:
306 ji->table_size = (int)data [0];
307 table = g_new (gpointer, ji->table_size);
308 ji->data.target = table;
309 for (i = 0; i < ji->table_size; i++) {
310 table [i] = data [i + 1];
313 case MONO_PATCH_INFO_R4:
314 case MONO_PATCH_INFO_R8:
315 ji->data.target = data;
317 case MONO_PATCH_INFO_LDSTR:
318 case MONO_PATCH_INFO_LDTOKEN:
319 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
320 ji->data.target = *data;
322 case MONO_PATCH_INFO_EXC_NAME:
323 ji->data.klass = decode_class_info (data);
324 g_assert (ji->data.klass);
325 mono_class_init (ji->data.klass);
326 ji->data.name = ji->data.klass->name;
328 case MONO_PATCH_INFO_METHOD_REL:
329 ji->data.offset = (int)data [0];
332 g_warning ("unhandled type %d", ji->type);
333 g_assert_not_reached ();
337 ji->next = patch_info;
341 #ifndef PLATFORM_WIN32
342 /* disable write protection */
343 page_start = (char *) (((int) (code)) & ~ (PAGESIZE - 1));
344 pages = (code + code_len - page_start + PAGESIZE - 1) / PAGESIZE;
345 err = mprotect (page_start, pages * PAGESIZE, PROT_READ | PROT_WRITE | PROT_EXEC);
350 g_assert (VirtualProtect (code, code_len, PAGE_EXECUTE_READWRITE, &oldp) != 0);
354 /* Do this outside the lock to avoid deadlocks */
355 LeaveCriticalSection (&aot_mutex);
356 mono_arch_patch_code (method, domain, code, patch_info);
357 EnterCriticalSection (&aot_mutex);
359 if (aot_module->opts & MONO_OPT_SHARED)
360 /* No need to cache this */
361 mono_mempool_destroy (mp);
363 minfo->patch_info = patch_info;
367 g_free (method_label);
371 info = mono_mempool_alloc0 (domain->mp, sizeof (MonoJitInfo));
372 info->code_size = code_len;
373 info->used_regs = used_int_regs;
374 info->method = method;
375 info->code_start = code;
376 info->domain_neutral = (aot_module->opts & MONO_OPT_SHARED) != 0;
377 mono_jit_info_table_add (domain, info);
380 mono_g_hash_table_insert (aot_module->methods, method, minfo);
382 mono_jit_stats.methods_aot++;
388 mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
392 EnterCriticalSection (&aot_mutex);
393 res = mono_aot_get_method_inner (domain, method);
394 LeaveCriticalSection (&aot_mutex);
400 write_data_symbol (FILE *fp, const char *name, guint8 *buf, int size, int align)
404 fprintf (fp, ".globl %s\n", name);
405 fprintf (fp, ".data\n\t.align %d\n", align);
406 fprintf (fp, "\t.type %s,@object\n", name);
407 fprintf (fp, "\t.size %s,%d\n", name, size);
408 fprintf (fp, "%s:\n", name);
409 for (i = 0; i < size; i++) {
410 fprintf (fp, ".byte %d\n", buf [i]);
417 write_string_symbol (FILE *fp, const char *name, const char *value)
419 fprintf (fp, ".globl %s\n", name);
420 fprintf (fp, ".data\n");
421 fprintf (fp, "%s:\n", name);
422 fprintf (fp, "\t.string \"%s\"\n", value);
426 mono_get_field_token (MonoClassField *field)
428 MonoClass *klass = field->parent;
431 for (i = 0; i < klass->field.count; ++i) {
432 if (field == &klass->fields [i])
433 return MONO_TOKEN_FIELD_DEF | (klass->field.first + 1 + i);
436 g_assert_not_reached ();
441 cond_emit_image_label (FILE *tmpfp, GHashTable *image_hash, MonoImage *image)
445 if ((label = g_hash_table_lookup (image_hash, image)))
448 label = g_strdup_printf ("image_patch_info_%p", image);
449 fprintf (tmpfp, "%s:\n", label);
450 fprintf (tmpfp, "\t.string \"%s\"\n", image->guid);
452 g_hash_table_insert (image_hash, image, label);
458 cond_emit_icall_label (FILE *tmpfp, GHashTable *hash, const char *icall_name)
462 if ((label = g_hash_table_lookup (hash, icall_name)))
465 label = g_strdup_printf ("icall_patch_info_%s", icall_name);
466 fprintf (tmpfp, "%s:\n", label);
467 fprintf (tmpfp, "\t.string \"%s\"\n", icall_name);
469 g_hash_table_insert (hash, (gpointer)icall_name, label);
475 cond_emit_method_label (FILE *tmpfp, GHashTable *hash, MonoJumpInfo *patch_info)
477 MonoMethod *method = patch_info->data.method;
480 if ((l1 = g_hash_table_lookup (hash, method)))
483 l2 = cond_emit_image_label (tmpfp, hash, method->klass->image);
484 fprintf (tmpfp, "\t.align %d\n", sizeof (gpointer));
485 l1 = g_strdup_printf ("method_patch_info_%08x_%p", method->token, method);
486 fprintf (tmpfp, "%s:\n", l1);
487 fprintf (tmpfp, "\t.long 0x%08x\n", method->token);
488 g_assert (method->token);
489 fprintf (tmpfp, "\t.long %s\n", l2);
491 g_hash_table_insert (hash, method, l1);
497 cond_emit_klass_label (FILE *tmpfp, GHashTable *hash, MonoClass *klass)
499 char *l1, *l2, *el = NULL;
501 if ((l1 = g_hash_table_lookup (hash, klass)))
504 if (!klass->type_token) {
505 g_assert (klass->rank > 0);
506 el = cond_emit_klass_label (tmpfp, hash, klass->element_class);
509 l2 = cond_emit_image_label (tmpfp, hash, klass->image);
510 fprintf (tmpfp, "\t.align %d\n", sizeof (gpointer));
511 l1 = g_strdup_printf ("klass_patch_info_%08x_%p", klass->type_token, klass);
512 fprintf (tmpfp, "%s:\n", l1);
513 fprintf (tmpfp, "\t.long 0x%08x\n", klass->type_token);
514 fprintf (tmpfp, "\t.long %s\n", l2);
517 fprintf (tmpfp, "\t.long %d\n", klass->rank);
518 fprintf (tmpfp, "\t.long %s\n", el);
521 g_hash_table_insert (hash, klass, l1);
527 cond_emit_field_label (FILE *tmpfp, GHashTable *hash, MonoJumpInfo *patch_info)
529 MonoClassField *field = patch_info->data.field;
533 if ((l1 = g_hash_table_lookup (hash, field)))
536 l2 = cond_emit_image_label (tmpfp, hash, field->parent->image);
537 fprintf (tmpfp, "\t.align %d\n", sizeof (gpointer));
538 token = mono_get_field_token (field);
539 l1 = g_strdup_printf ("klass_patch_info_%08x_%p", token, field);
540 fprintf (tmpfp, "%s:\n", l1);
541 fprintf (tmpfp, "\t.long 0x%08x\n", token);
543 fprintf (tmpfp, "\t.long %s\n", l2);
545 g_hash_table_insert (hash, field, l1);
551 mono_compile_assembly (MonoAssembly *ass, guint32 opts)
554 MonoImage *image = ass->image;
557 char *com, *tmpfname, *opts_str;
560 guint8 *code, *mname;
561 int ccount = 0, mcount = 0, lmfcount = 0, ecount = 0, abscount = 0, wrappercount = 0, ocount = 0;
562 GHashTable *ref_hash;
563 int func_alignment = 16;
565 printf ("Mono AOT compiler - compiling assembly %s\n", image->name);
567 i = g_file_open_tmp ("mono_aot_XXXXXX", &tmpfname, NULL);
568 tmpfp = fdopen (i, "w+");
571 ref_hash = g_hash_table_new (NULL, NULL);
573 write_string_symbol (tmpfp, "mono_assembly_guid" , image->guid);
575 write_string_symbol (tmpfp, "mono_aot_version", MONO_AOT_FILE_VERSION);
577 opts_str = g_strdup_printf ("%d", opts);
578 write_string_symbol (tmpfp, "mono_aot_opt_flags", opts_str);
581 for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
582 MonoJumpInfo *patch_info;
584 guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
585 method = mono_get_method (image, token, NULL);
587 /* fixme: maybe we can also precompile wrapper methods */
588 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
589 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
590 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
591 (method->flags & METHOD_ATTRIBUTE_ABSTRACT)) {
592 //printf ("Skip (impossible): %s\n", mono_method_full_name (method, TRUE));
598 /* fixme: we need to patch the IP for the LMF in that case */
599 if (method->save_lmf) {
600 //printf ("Skip (needs lmf): %s\n", mono_method_full_name (method, TRUE));
605 /* fixme: add methods with exception tables */
606 if (((MonoMethodNormal *)method)->header->num_clauses) {
607 //printf ("Skip (exceptions): %s\n", mono_method_full_name (method, TRUE));
612 //printf ("START: %s\n", mono_method_full_name (method, TRUE));
613 //mono_compile_method (method);
615 cfg = mini_method_compile (method, opts, mono_root_domain, 0);
618 if (cfg->disable_aot) {
624 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
625 if (patch_info->type == MONO_PATCH_INFO_ABS) {
626 /* unable to handle this */
627 //printf ("Skip (abs addr): %s %d\n", mono_method_full_name (method, TRUE), patch_info->type);
639 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
640 if ((patch_info->type == MONO_PATCH_INFO_METHOD ||
641 patch_info->type == MONO_PATCH_INFO_METHODCONST) &&
642 patch_info->data.method->wrapper_type) {
643 /* unable to handle this */
644 //printf ("Skip (wrapper call): %s %d\n", mono_method_full_name (method, TRUE), patch_info->type);
655 //printf ("Compile: %s\n", mono_method_full_name (method, TRUE));
657 code = cfg->native_code;
659 fprintf (tmpfp, ".text\n");
660 mname = g_strdup_printf ("method_%08X", token);
661 fprintf (tmpfp, "\t.align %d\n", func_alignment);
662 fprintf (tmpfp, ".globl %s\n", mname);
663 fprintf (tmpfp, "\t.type %s,@function\n", mname);
664 fprintf (tmpfp, "%s:\n", mname);
666 for (j = 0; j < cfg->code_len; j++)
667 fprintf (tmpfp, ".byte %d\n", (unsigned int) code [j]);
669 fprintf (tmpfp, ".data\n");
672 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
673 switch (patch_info->type) {
674 case MONO_PATCH_INFO_LABEL:
675 case MONO_PATCH_INFO_BB:
676 /* relative jumps are no problem, there is no need to handle then here */
678 case MONO_PATCH_INFO_SWITCH: {
679 gpointer *table = (gpointer *)patch_info->data.target;
682 fprintf (tmpfp, "\t.align %d\n", sizeof (gpointer));
683 fprintf (tmpfp, "%s_patch_info_%d:\n", mname, j);
684 fprintf (tmpfp, "\t.long %d\n", patch_info->table_size);
686 for (k = 0; k < patch_info->table_size; k++) {
687 fprintf (tmpfp, "\t.long %d\n", (int)table [k]);
692 case MONO_PATCH_INFO_INTERNAL_METHOD:
693 patch_info->data.name = cond_emit_icall_label (tmpfp, ref_hash, patch_info->data.name);
696 case MONO_PATCH_INFO_METHODCONST:
697 case MONO_PATCH_INFO_METHOD:
698 patch_info->data.name = cond_emit_method_label (tmpfp, ref_hash, patch_info);
701 case MONO_PATCH_INFO_FIELD:
702 patch_info->data.name = cond_emit_field_label (tmpfp, ref_hash, patch_info);
705 case MONO_PATCH_INFO_CLASS:
706 patch_info->data.name = cond_emit_klass_label (tmpfp, ref_hash, patch_info->data.klass);
709 case MONO_PATCH_INFO_IMAGE:
710 patch_info->data.name = cond_emit_image_label (tmpfp, ref_hash, patch_info->data.image);
713 case MONO_PATCH_INFO_EXC_NAME: {
717 mono_class_from_name (mono_defaults.exception_class->image,
718 "System", patch_info->data.target);
720 patch_info->data.name = cond_emit_klass_label (tmpfp, ref_hash, ex_class);
724 case MONO_PATCH_INFO_R4:
725 fprintf (tmpfp, "\t.align 8\n");
726 fprintf (tmpfp, "%s_patch_info_%d:\n", mname, j);
727 fprintf (tmpfp, "\t.long 0x%08x\n", *((guint32 *)patch_info->data.target));
731 case MONO_PATCH_INFO_R8:
732 fprintf (tmpfp, "\t.align 8\n");
733 fprintf (tmpfp, "%s_patch_info_%d:\n", mname, j);
734 fprintf (tmpfp, "\t.long 0x%08x\n", *((guint32 *)patch_info->data.target));
735 fprintf (tmpfp, "\t.long 0x%08x\n", *((guint32 *)patch_info->data.target + 1));
739 case MONO_PATCH_INFO_METHOD_REL:
740 fprintf (tmpfp, "\t.align %d\n", sizeof (gpointer));
741 fprintf (tmpfp, "%s_patch_info_%d:\n", mname, j);
742 fprintf (tmpfp, "\t.long 0x%08x\n", patch_info->data.offset);
745 case MONO_PATCH_INFO_VTABLE:
746 patch_info->data.name = cond_emit_klass_label (tmpfp, ref_hash, patch_info->data.klass);
749 case MONO_PATCH_INFO_SFLDA:
750 patch_info->data.name = cond_emit_field_label (tmpfp, ref_hash, patch_info);
753 case MONO_PATCH_INFO_LDSTR:
754 case MONO_PATCH_INFO_LDTOKEN:
755 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
756 fprintf (tmpfp, "\t.align 8\n");
757 fprintf (tmpfp, "%s_patch_info_%d:\n", mname, j);
758 fprintf (tmpfp, "\t.long 0x%08x\n", patch_info->data.token);
762 g_warning ("unable to handle jump info %d", patch_info->type);
763 g_assert_not_reached ();
767 fprintf (tmpfp, ".globl %s_patch_info\n", mname);
768 fprintf (tmpfp, "\t.align %d\n", sizeof (gpointer));
769 fprintf (tmpfp, "%s_patch_info:\n", mname);
771 fprintf (tmpfp, "\t.long %d\n", cfg->code_len);
772 fprintf (tmpfp, "\t.long %d\n", cfg->used_int_regs);
774 fprintf (tmpfp, "\t.long %d\n", g_list_length (cfg->ldstr_list));
775 for (l = cfg->ldstr_list; l; l = l->next) {
776 fprintf (tmpfp, "\t.long 0x%08lx\n", (long)l->data);
781 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
782 switch (patch_info->type) {
783 case MONO_PATCH_INFO_METHODCONST:
784 case MONO_PATCH_INFO_METHOD:
785 case MONO_PATCH_INFO_CLASS:
786 case MONO_PATCH_INFO_FIELD:
787 case MONO_PATCH_INFO_INTERNAL_METHOD:
788 case MONO_PATCH_INFO_IMAGE:
789 case MONO_PATCH_INFO_VTABLE:
790 case MONO_PATCH_INFO_SFLDA:
791 case MONO_PATCH_INFO_EXC_NAME:
792 fprintf (tmpfp, "\t.long %s\n", patch_info->data.name);
793 fprintf (tmpfp, "\t.long 0x%08x\n", ENCODE_TYPE_POS (patch_info->type, patch_info->ip.i));
796 case MONO_PATCH_INFO_SWITCH:
797 case MONO_PATCH_INFO_R4:
798 case MONO_PATCH_INFO_R8:
799 case MONO_PATCH_INFO_METHOD_REL:
800 case MONO_PATCH_INFO_LDSTR:
801 case MONO_PATCH_INFO_LDTOKEN:
802 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
803 fprintf (tmpfp, "\t.long %s_patch_info_%d\n", mname, j);
804 fprintf (tmpfp, "\t.long 0x%08x\n", ENCODE_TYPE_POS (patch_info->type, patch_info->ip.i));
807 case MONO_PATCH_INFO_LABEL:
808 case MONO_PATCH_INFO_BB:
811 g_warning ("unable to handle jump info %d", patch_info->type);
812 g_assert_not_reached ();
817 /* NULL terminated array */
818 fprintf (tmpfp, "\t.long 0\n");
820 /* fixme: save the rest of the required infos */
823 mono_destroy_compile (cfg);
830 com = g_strdup_printf ("as %s -o %s.o", tmpfname, tmpfname);
831 printf ("Executing the native assembler: %s\n", com);
834 com = g_strdup_printf ("ld -shared -o %s%s %s.o", image->name, SHARED_EXT, tmpfname);
835 printf ("Executing the native linker: %s\n", com);
838 com = g_strdup_printf ("%s.o", tmpfname);
841 /*com = g_strdup_printf ("strip --strip-unneeded %s%s", image->name, SHARED_EXT);
842 printf ("Stripping the binary: %s\n", com);
846 printf ("Compiled %d out of %d methods (%d%%)\n", ccount, mcount, (ccount*100)/mcount);
847 printf ("%d methods contain exception tables (%d%%)\n", ecount, (ecount*100)/mcount);
848 printf ("%d methods contain absolute addresses (%d%%)\n", abscount, (abscount*100)/mcount);
849 printf ("%d methods contain wrapper references (%d%%)\n", wrappercount, (wrappercount*100)/mcount);
850 printf ("%d methods contain lmf pointers (%d%%)\n", lmfcount, (lmfcount*100)/mcount);
851 printf ("%d methods have other problems (%d%%)\n", ocount, (ocount*100)/mcount);