X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Faot-compiler.c;h=dd2780edac9e524123b6483fca0e54cb4e5ff95b;hb=56ad8f4e5dfb8198e4671f631a3103b1e8b83dd3;hp=48354b70578e4718dfc13425014d86b3caaa45f4;hpb=25b04d16d938df85b72479d1af667f8823fb6434;p=mono.git diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 48354b70578..dd2780edac9 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -8,6 +8,7 @@ * (C) 2002 Ximian, Inc. * Copyright 2003-2011 Novell, Inc * Copyright 2011 Xamarin Inc (http://www.xamarin.com) + * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ #include "config.h" @@ -40,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -152,8 +154,8 @@ typedef struct MonoAotStats { int methods_without_got_slots, direct_calls, all_calls, llvm_count; int got_slots, offsets_size; int method_categories [METHOD_CAT_NUM]; - int got_slot_types [MONO_PATCH_INFO_NONE]; - int got_slot_info_sizes [MONO_PATCH_INFO_NONE]; + int got_slot_types [MONO_PATCH_INFO_NUM]; + int got_slot_info_sizes [MONO_PATCH_INFO_NUM]; int jit_time, gen_time, link_time; } MonoAotStats; @@ -856,7 +858,331 @@ arch_init (MonoAotCompile *acfg) #ifdef TARGET_ARM64 -#include "../../../mono-extensions/mono/mini/aot-compiler-arm64.c" + +/* Load the contents of GOT_SLOT into dreg, clobbering ip0 */ +static void +arm64_emit_load_got_slot (MonoAotCompile *acfg, int dreg, int got_slot) +{ + int offset; + + g_assert (acfg->fp); + emit_unset_mode (acfg); + /* r16==ip0 */ + offset = (int)(got_slot * sizeof (gpointer)); +#ifdef TARGET_MACH + /* clang's integrated assembler */ + fprintf (acfg->fp, "adrp x16, %s@PAGE+%d\n", acfg->got_symbol, offset & 0xfffff000); + fprintf (acfg->fp, "add x16, x16, %s@PAGEOFF\n", acfg->got_symbol); + fprintf (acfg->fp, "ldr x%d, [x16, #%d]\n", dreg, offset & 0xfff); +#else + /* Linux GAS */ + fprintf (acfg->fp, "adrp x16, %s+%d\n", acfg->got_symbol, offset & 0xfffff000); + fprintf (acfg->fp, "add x16, x16, :lo12:%s\n", acfg->got_symbol); + fprintf (acfg->fp, "ldr x%d, [x16, %d]\n", dreg, offset & 0xfff); +#endif +} + +static void +arm64_emit_objc_selector_ref (MonoAotCompile *acfg, guint8 *code, int index, int *code_size) +{ + int reg; + + g_assert (acfg->fp); + emit_unset_mode (acfg); + + /* ldr rt, target */ + reg = arm_get_ldr_lit_reg (code); + + fprintf (acfg->fp, "adrp x%d, L_OBJC_SELECTOR_REFERENCES_%d@PAGE\n", reg, index); + fprintf (acfg->fp, "add x%d, x%d, L_OBJC_SELECTOR_REFERENCES_%d@PAGEOFF\n", reg, reg, index); + fprintf (acfg->fp, "ldr x%d, [x%d]\n", reg, reg); + + *code_size = 12; +} + +static void +arm64_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean external, gboolean thumb, MonoJumpInfo *ji, int *call_size) +{ + g_assert (acfg->fp); + emit_unset_mode (acfg); + if (ji && ji->relocation == MONO_R_ARM64_B) { + fprintf (acfg->fp, "b %s\n", target); + } else { + if (ji) + g_assert (ji->relocation == MONO_R_ARM64_BL); + fprintf (acfg->fp, "bl %s\n", target); + } + *call_size = 4; +} + +static void +arm64_emit_got_access (MonoAotCompile *acfg, guint8 *code, int got_slot, int *code_size) +{ + int reg; + + /* ldr rt, target */ + reg = arm_get_ldr_lit_reg (code); + arm64_emit_load_got_slot (acfg, reg, got_slot); + *code_size = 12; +} + +static void +arm64_emit_plt_entry (MonoAotCompile *acfg, const char *got_symbol, int offset, int info_offset) +{ + arm64_emit_load_got_slot (acfg, ARMREG_R16, offset / sizeof (gpointer)); + fprintf (acfg->fp, "br x16\n"); + /* Used by mono_aot_get_plt_info_offset () */ + fprintf (acfg->fp, "%s %d\n", acfg->inst_directive, info_offset); +} + +static void +arm64_emit_tramp_page_common_code (MonoAotCompile *acfg, int pagesize, int arg_reg, int *size) +{ + guint8 buf [256]; + guint8 *code; + int imm; + + /* The common code */ + code = buf; + imm = pagesize; + /* The trampoline address is in IP0 */ + arm_movzx (code, ARMREG_IP1, imm & 0xffff, 0); + arm_movkx (code, ARMREG_IP1, (imm >> 16) & 0xffff, 16); + /* Compute the data slot address */ + arm_subx (code, ARMREG_IP0, ARMREG_IP0, ARMREG_IP1); + /* Trampoline argument */ + arm_ldrx (code, arg_reg, ARMREG_IP0, 0); + /* Address */ + arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, 8); + arm_brx (code, ARMREG_IP0); + + /* Emit it */ + emit_code_bytes (acfg, buf, code - buf); + + *size = code - buf; +} + +static void +arm64_emit_tramp_page_specific_code (MonoAotCompile *acfg, int pagesize, int common_tramp_size, int specific_tramp_size) +{ + guint8 buf [256]; + guint8 *code; + int i, count; + + count = (pagesize - common_tramp_size) / specific_tramp_size; + for (i = 0; i < count; ++i) { + code = buf; + arm_adrx (code, ARMREG_IP0, code); + /* Branch to the generic code */ + arm_b (code, code - 4 - (i * specific_tramp_size) - common_tramp_size); + /* This has to be 2 pointers long */ + arm_nop (code); + arm_nop (code); + g_assert (code - buf == specific_tramp_size); + emit_code_bytes (acfg, buf, code - buf); + } +} + +static void +arm64_emit_specific_trampoline_pages (MonoAotCompile *acfg) +{ + guint8 buf [128]; + guint8 *code; + guint8 *labels [16]; + int common_tramp_size; + int specific_tramp_size = 2 * 8; + int imm, pagesize; + char symbol [128]; + + if (!acfg->aot_opts.use_trampolines_page) + return; + +#ifdef TARGET_MACH + /* Have to match the target pagesize */ + pagesize = 16384; +#else + pagesize = mono_pagesize (); +#endif + acfg->tramp_page_size = pagesize; + + /* The specific trampolines */ + sprintf (symbol, "%sspecific_trampolines_page", acfg->user_symbol_prefix); + emit_alignment (acfg, pagesize); + emit_global (acfg, symbol, TRUE); + emit_label (acfg, symbol); + + /* The common code */ + arm64_emit_tramp_page_common_code (acfg, pagesize, ARMREG_IP1, &common_tramp_size); + acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_SPECIFIC] = common_tramp_size; + + arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size); + + /* The rgctx trampolines */ + /* These are the same as the specific trampolines, but they load the argument into MONO_ARCH_RGCTX_REG */ + sprintf (symbol, "%srgctx_trampolines_page", acfg->user_symbol_prefix); + emit_alignment (acfg, pagesize); + emit_global (acfg, symbol, TRUE); + emit_label (acfg, symbol); + + /* The common code */ + arm64_emit_tramp_page_common_code (acfg, pagesize, MONO_ARCH_RGCTX_REG, &common_tramp_size); + acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_STATIC_RGCTX] = common_tramp_size; + + arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size); + + /* The gsharedvt arg trampolines */ + /* These are the same as the specific trampolines */ + sprintf (symbol, "%sgsharedvt_arg_trampolines_page", acfg->user_symbol_prefix); + emit_alignment (acfg, pagesize); + emit_global (acfg, symbol, TRUE); + emit_label (acfg, symbol); + + arm64_emit_tramp_page_common_code (acfg, pagesize, ARMREG_IP1, &common_tramp_size); + acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_GSHAREDVT_ARG] = common_tramp_size; + + arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size); + + /* The IMT trampolines */ + sprintf (symbol, "%simt_trampolines_page", acfg->user_symbol_prefix); + emit_alignment (acfg, pagesize); + emit_global (acfg, symbol, TRUE); + emit_label (acfg, symbol); + + code = buf; + imm = pagesize; + /* The trampoline address is in IP0 */ + arm_movzx (code, ARMREG_IP1, imm & 0xffff, 0); + arm_movkx (code, ARMREG_IP1, (imm >> 16) & 0xffff, 16); + /* Compute the data slot address */ + arm_subx (code, ARMREG_IP0, ARMREG_IP0, ARMREG_IP1); + /* Trampoline argument */ + arm_ldrx (code, ARMREG_IP1, ARMREG_IP0, 0); + + /* Same as arch_emit_imt_thunk () */ + labels [0] = code; + arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 0); + arm_cmpx (code, ARMREG_IP0, MONO_ARCH_RGCTX_REG); + labels [1] = code; + arm_bcc (code, ARMCOND_EQ, 0); + + /* End-of-loop check */ + labels [2] = code; + arm_cbzx (code, ARMREG_IP0, 0); + + /* Loop footer */ + arm_addx_imm (code, ARMREG_IP1, ARMREG_IP1, 2 * 8); + arm_b (code, labels [0]); + + /* Match */ + mono_arm_patch (labels [1], code, MONO_R_ARM64_BCC); + /* Load vtable slot addr */ + arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 8); + /* Load vtable slot */ + arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, 0); + arm_brx (code, ARMREG_IP0); + + /* No match */ + mono_arm_patch (labels [2], code, MONO_R_ARM64_CBZ); + /* Load fail addr */ + arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 8); + arm_brx (code, ARMREG_IP0); + + emit_code_bytes (acfg, buf, code - buf); + + common_tramp_size = code - buf; + acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT_THUNK] = common_tramp_size; + + arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size); +} + +static void +arm64_emit_specific_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size) +{ + /* Load argument from second GOT slot */ + arm64_emit_load_got_slot (acfg, ARMREG_R17, offset + 1); + /* Load generic trampoline address from first GOT slot */ + arm64_emit_load_got_slot (acfg, ARMREG_R16, offset); + fprintf (acfg->fp, "br x16\n"); + *tramp_size = 7 * 4; +} + +static void +arm64_emit_unbox_trampoline (MonoAotCompile *acfg, MonoCompile *cfg, MonoMethod *method, const char *call_target) +{ + emit_unset_mode (acfg); + fprintf (acfg->fp, "add x0, x0, %d\n", (int)(sizeof (MonoObject))); + fprintf (acfg->fp, "b %s\n", call_target); +} + +static void +arm64_emit_static_rgctx_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size) +{ + /* Similar to the specific trampolines, but use the rgctx reg instead of ip1 */ + + /* Load argument from first GOT slot */ + g_assert (MONO_ARCH_RGCTX_REG == 27); + arm64_emit_load_got_slot (acfg, ARMREG_R27, offset); + /* Load generic trampoline address from second GOT slot */ + arm64_emit_load_got_slot (acfg, ARMREG_R16, offset + 1); + fprintf (acfg->fp, "br x16\n"); + *tramp_size = 7 * 4; +} + +static void +arm64_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size) +{ + guint8 buf [128]; + guint8 *code, *labels [16]; + + /* Load parameter from GOT slot into ip1 */ + arm64_emit_load_got_slot (acfg, ARMREG_R17, offset); + + code = buf; + labels [0] = code; + arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 0); + arm_cmpx (code, ARMREG_IP0, MONO_ARCH_RGCTX_REG); + labels [1] = code; + arm_bcc (code, ARMCOND_EQ, 0); + + /* End-of-loop check */ + labels [2] = code; + arm_cbzx (code, ARMREG_IP0, 0); + + /* Loop footer */ + arm_addx_imm (code, ARMREG_IP1, ARMREG_IP1, 2 * 8); + arm_b (code, labels [0]); + + /* Match */ + mono_arm_patch (labels [1], code, MONO_R_ARM64_BCC); + /* Load vtable slot addr */ + arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 8); + /* Load vtable slot */ + arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, 0); + arm_brx (code, ARMREG_IP0); + + /* No match */ + mono_arm_patch (labels [2], code, MONO_R_ARM64_CBZ); + /* Load fail addr */ + arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 8); + arm_brx (code, ARMREG_IP0); + + emit_code_bytes (acfg, buf, code - buf); + + *tramp_size = code - buf + (3 * 4); +} + +static void +arm64_emit_gsharedvt_arg_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size) +{ + /* Similar to the specific trampolines, but the address is in the second slot */ + /* Load argument from first GOT slot */ + arm64_emit_load_got_slot (acfg, ARMREG_R17, offset); + /* Load generic trampoline address from second GOT slot */ + arm64_emit_load_got_slot (acfg, ARMREG_R16, offset + 1); + fprintf (acfg->fp, "br x16\n"); + *tramp_size = 7 * 4; +} + #endif @@ -3121,7 +3447,7 @@ is_plt_patch (MonoJumpInfo *patch_info) case MONO_PATCH_INFO_METHOD: case MONO_PATCH_INFO_INTERNAL_METHOD: case MONO_PATCH_INFO_JIT_ICALL_ADDR: - case MONO_PATCH_INFO_ICALL_ADDR: + case MONO_PATCH_INFO_ICALL_ADDR_CALL: case MONO_PATCH_INFO_RGCTX_FETCH: return TRUE; default: @@ -3609,7 +3935,7 @@ add_wrappers (MonoAotCompile *acfg) /* Assembly runtime-invoke (string, bool) [DoAssemblyResolve] */ csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2); csig->hasthis = 1; - csig->ret = &(mono_class_from_name ( + csig->ret = &(mono_class_load_from_name ( mono_defaults.corlib, "System.Reflection", "Assembly"))->byval_arg; csig->params [0] = &mono_defaults.string_class->byval_arg; csig->params [1] = &mono_defaults.boolean_class->byval_arg; @@ -3745,7 +4071,11 @@ add_wrappers (MonoAotCompile *acfg) if (method) add_method (acfg, mono_marshal_get_delegate_end_invoke (method)); - cattr = mono_custom_attrs_from_class (klass); + cattr = mono_custom_attrs_from_class_checked (klass, &error); + if (!is_ok (&error)) { + mono_error_cleanup (&error); + continue; + } if (cattr) { int j; @@ -3910,7 +4240,12 @@ add_wrappers (MonoAotCompile *acfg) * attribute named MonoPInvokeCallbackAttribute. We search for the attribute by * name to avoid defining a new assembly to contain it. */ - cattr = mono_custom_attrs_from_method (method); + cattr = mono_custom_attrs_from_method_checked (method, &error); + if (!is_ok (&error)) { + char *name = mono_method_get_full_name (method); + report_loader_error (acfg, &error, "Failed to load custom attributes from method %s due to %s\n", name, mono_error_get_message (&error)); + g_free (name); + } if (cattr) { for (j = 0; j < cattr->num_attrs; ++j) @@ -3950,8 +4285,9 @@ add_wrappers (MonoAotCompile *acfg) slen = mono_metadata_decode_value (p, &p); n = (char *)g_memdup (p, slen + 1); n [slen] = 0; - t = mono_reflection_type_from_name (n, acfg->image); + t = mono_reflection_type_from_name_checked (n, acfg->image, &error); g_assert (t); + mono_error_assert_ok (&error); g_free (n); klass = mono_class_from_mono_type (t); @@ -4156,7 +4492,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, if (!klass->generic_class && !klass->rank) return; - if (klass->exception_type) + if (mono_class_has_failure (klass)) return; if (!acfg->ginst_hash) @@ -4246,6 +4582,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, /* Add the T[]/InternalEnumerator class */ if (!strcmp (klass->name, "IEnumerable`1") || !strcmp (klass->name, "IEnumerator`1")) { + MonoError error; MonoClass *nclass; iter = NULL; @@ -4254,7 +4591,8 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, break; } g_assert (nclass); - nclass = mono_class_inflate_generic_class (nclass, mono_generic_class_get_context (klass->generic_class)); + nclass = mono_class_inflate_generic_class_checked (nclass, mono_generic_class_get_context (klass->generic_class), &error); + mono_error_assert_ok (&error); /* FIXME don't swallow the error */ add_generic_class (acfg, nclass, FALSE, "ICollection"); } @@ -4272,43 +4610,58 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, /* Add an instance of GenericComparer which is created dynamically by Comparer */ if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "Comparer`1")) { + MonoError error; MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]); - MonoClass *icomparable, *gcomparer; + MonoClass *icomparable, *gcomparer, *icomparable_inst; MonoGenericContext ctx; MonoType *args [16]; memset (&ctx, 0, sizeof (ctx)); - icomparable = mono_class_from_name (mono_defaults.corlib, "System", "IComparable`1"); - g_assert (icomparable); + icomparable = mono_class_load_from_name (mono_defaults.corlib, "System", "IComparable`1"); + args [0] = &tclass->byval_arg; ctx.class_inst = mono_metadata_get_generic_inst (1, args); - if (mono_class_is_assignable_from (mono_class_inflate_generic_class (icomparable, &ctx), tclass)) { - gcomparer = mono_class_from_name (mono_defaults.corlib, "System.Collections.Generic", "GenericComparer`1"); - g_assert (gcomparer); - add_generic_class (acfg, mono_class_inflate_generic_class (gcomparer, &ctx), FALSE, "Comparer"); + icomparable_inst = mono_class_inflate_generic_class_checked (icomparable, &ctx, &error); + mono_error_assert_ok (&error); /* FIXME don't swallow the error */ + + if (mono_class_is_assignable_from (icomparable_inst, tclass)) { + MonoClass *gcomparer_inst; + gcomparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "GenericComparer`1"); + gcomparer_inst = mono_class_inflate_generic_class_checked (gcomparer, &ctx, &error); + mono_error_assert_ok (&error); /* FIXME don't swallow the error */ + + add_generic_class (acfg, gcomparer_inst, FALSE, "Comparer"); } } /* Add an instance of GenericEqualityComparer which is created dynamically by EqualityComparer */ if (klass->image == mono_defaults.corlib && !strcmp (klass->name_space, "System.Collections.Generic") && !strcmp (klass->name, "EqualityComparer`1")) { + MonoError error; MonoClass *tclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]); - MonoClass *iface, *gcomparer; + MonoClass *iface, *gcomparer, *iface_inst; MonoGenericContext ctx; MonoType *args [16]; memset (&ctx, 0, sizeof (ctx)); - iface = mono_class_from_name (mono_defaults.corlib, "System", "IEquatable`1"); + iface = mono_class_load_from_name (mono_defaults.corlib, "System", "IEquatable`1"); g_assert (iface); args [0] = &tclass->byval_arg; ctx.class_inst = mono_metadata_get_generic_inst (1, args); - if (mono_class_is_assignable_from (mono_class_inflate_generic_class (iface, &ctx), tclass)) { - gcomparer = mono_class_from_name (mono_defaults.corlib, "System.Collections.Generic", "GenericEqualityComparer`1"); - g_assert (gcomparer); - add_generic_class (acfg, mono_class_inflate_generic_class (gcomparer, &ctx), FALSE, "EqualityComparer"); + iface_inst = mono_class_inflate_generic_class_checked (iface, &ctx, &error); + mono_error_assert_ok (&error); /* FIXME don't swallow the error */ + + if (mono_class_is_assignable_from (iface_inst, tclass)) { + MonoClass *gcomparer_inst; + MonoError error; + + gcomparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "GenericEqualityComparer`1"); + gcomparer_inst = mono_class_inflate_generic_class_checked (gcomparer, &ctx, &error); + mono_error_assert_ok (&error); /* FIXME don't swallow the error */ + add_generic_class (acfg, gcomparer_inst, FALSE, "EqualityComparer"); } } @@ -4320,13 +4673,17 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, MonoType *args [16]; if (mono_class_is_enum (tclass)) { + MonoClass *enum_comparer_inst; + MonoError error; + memset (&ctx, 0, sizeof (ctx)); args [0] = &tclass->byval_arg; ctx.class_inst = mono_metadata_get_generic_inst (1, args); - enum_comparer = mono_class_from_name (mono_defaults.corlib, "System.Collections.Generic", "EnumEqualityComparer`1"); - g_assert (enum_comparer); - add_generic_class (acfg, mono_class_inflate_generic_class (enum_comparer, &ctx), FALSE, "EqualityComparer"); + enum_comparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "EnumEqualityComparer`1"); + enum_comparer_inst = mono_class_inflate_generic_class_checked (enum_comparer, &ctx, &error); + mono_error_assert_ok (&error); /* FIXME don't swallow the error */ + add_generic_class (acfg, enum_comparer_inst, FALSE, "EqualityComparer"); } } @@ -4338,13 +4695,17 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, MonoType *args [16]; if (mono_class_is_enum (tclass)) { + MonoClass *comparer_inst; + MonoError error; + memset (&ctx, 0, sizeof (ctx)); args [0] = &tclass->byval_arg; ctx.class_inst = mono_metadata_get_generic_inst (1, args); - comparer = mono_class_from_name (mono_defaults.corlib, "System.Collections.Generic", "ObjectComparer`1"); - g_assert (comparer); - add_generic_class (acfg, mono_class_inflate_generic_class (comparer, &ctx), FALSE, "Comparer"); + comparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "ObjectComparer`1"); + comparer_inst = mono_class_inflate_generic_class_checked (comparer, &ctx, &error); + mono_error_assert_ok (&error); /* FIXME don't swallow the error */ + add_generic_class (acfg, comparer_inst, FALSE, "Comparer"); } } } @@ -4362,15 +4723,20 @@ add_instances_of (MonoAotCompile *acfg, MonoClass *klass, MonoType **insts, int memset (&ctx, 0, sizeof (ctx)); for (i = 0; i < ninsts; ++i) { + MonoError error; + MonoClass *generic_inst; args [0] = insts [i]; ctx.class_inst = mono_metadata_get_generic_inst (1, args); - add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx), force, ""); + generic_inst = mono_class_inflate_generic_class_checked (klass, &ctx, &error); + mono_error_assert_ok (&error); /* FIXME don't swallow the error */ + add_generic_class (acfg, generic_inst, force, ""); } } static void add_types_from_method_header (MonoAotCompile *acfg, MonoMethod *method) { + MonoError error; MonoMethodHeader *header; MonoMethodSignature *sig; int j, depth; @@ -4385,14 +4751,14 @@ add_types_from_method_header (MonoAotCompile *acfg, MonoMethod *method) add_generic_class_with_depth (acfg, mono_class_from_mono_type (sig->params [j]), depth + 1, "arg"); } - header = mono_method_get_header (method); + header = mono_method_get_header_checked (method, &error); if (header) { for (j = 0; j < header->num_locals; ++j) if (header->locals [j]->type == MONO_TYPE_GENERICINST) add_generic_class_with_depth (acfg, mono_class_from_mono_type (header->locals [j]), depth + 1, "local"); } else { - mono_loader_clear_error (); + mono_error_cleanup (&error); /* FIXME report the error */ } } @@ -4561,10 +4927,10 @@ add_generic_instances (MonoAotCompile *acfg) insts [ninsts ++] = &mono_defaults.boolean_class->byval_arg; /* Add GenericComparer instances for primitive types for Enum.ToString () */ - klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "GenericComparer`1"); + klass = mono_class_try_load_from_name (acfg->image, "System.Collections.Generic", "GenericComparer`1"); if (klass) add_instances_of (acfg, klass, insts, ninsts, TRUE); - klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "GenericEqualityComparer`1"); + klass = mono_class_try_load_from_name (acfg->image, "System.Collections.Generic", "GenericEqualityComparer`1"); if (klass) add_instances_of (acfg, klass, insts, ninsts, TRUE); @@ -4579,24 +4945,20 @@ add_generic_instances (MonoAotCompile *acfg) insts [ninsts ++] = &mono_defaults.uint32_class->byval_arg; insts [ninsts ++] = &mono_defaults.uint16_class->byval_arg; insts [ninsts ++] = &mono_defaults.byte_class->byval_arg; - enum_comparer = mono_class_from_name (mono_defaults.corlib, "System.Collections.Generic", "EnumEqualityComparer`1"); - g_assert (enum_comparer); + enum_comparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "EnumEqualityComparer`1"); add_instances_of (acfg, enum_comparer, insts, ninsts, FALSE); ninsts = 0; insts [ninsts ++] = &mono_defaults.int16_class->byval_arg; - enum_comparer = mono_class_from_name (mono_defaults.corlib, "System.Collections.Generic", "ShortEnumEqualityComparer`1"); - g_assert (enum_comparer); + enum_comparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "ShortEnumEqualityComparer`1"); add_instances_of (acfg, enum_comparer, insts, ninsts, FALSE); ninsts = 0; insts [ninsts ++] = &mono_defaults.sbyte_class->byval_arg; - enum_comparer = mono_class_from_name (mono_defaults.corlib, "System.Collections.Generic", "SByteEnumEqualityComparer`1"); - g_assert (enum_comparer); + enum_comparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "SByteEnumEqualityComparer`1"); add_instances_of (acfg, enum_comparer, insts, ninsts, FALSE); - enum_comparer = mono_class_from_name (mono_defaults.corlib, "System.Collections.Generic", "LongEnumEqualityComparer`1"); - g_assert (enum_comparer); + enum_comparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "LongEnumEqualityComparer`1"); ninsts = 0; insts [ninsts ++] = &mono_defaults.int64_class->byval_arg; insts [ninsts ++] = &mono_defaults.uint64_class->byval_arg; @@ -4605,13 +4967,15 @@ add_generic_instances (MonoAotCompile *acfg) /* Add instances of the array generic interfaces for primitive types */ /* This will add instances of the InternalArray_ helper methods in Array too */ - klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "ICollection`1"); + klass = mono_class_try_load_from_name (acfg->image, "System.Collections.Generic", "ICollection`1"); if (klass) add_instances_of (acfg, klass, insts, ninsts, TRUE); - klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "IList`1"); + + klass = mono_class_try_load_from_name (acfg->image, "System.Collections.Generic", "IList`1"); if (klass) add_instances_of (acfg, klass, insts, ninsts, TRUE); - klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "IEnumerable`1"); + + klass = mono_class_try_load_from_name (acfg->image, "System.Collections.Generic", "IEnumerable`1"); if (klass) add_instances_of (acfg, klass, insts, ninsts, TRUE); @@ -4642,7 +5006,7 @@ add_generic_instances (MonoAotCompile *acfg) MonoGenericContext ctx; MonoType *args [16]; MonoMethod *m; - MonoClass *interlocked_klass = mono_class_from_name (mono_defaults.corlib, "System.Threading", "Interlocked"); + MonoClass *interlocked_klass = mono_class_load_from_name (mono_defaults.corlib, "System.Threading", "Interlocked"); gpointer iter = NULL; while ((m = mono_class_get_methods (interlocked_klass, &iter))) { @@ -4662,7 +5026,7 @@ add_generic_instances (MonoAotCompile *acfg) MonoGenericContext ctx; MonoType *args [16]; MonoMethod *m; - MonoClass *volatile_klass = mono_class_from_name (mono_defaults.corlib, "System.Threading", "Volatile"); + MonoClass *volatile_klass = mono_class_try_load_from_name (mono_defaults.corlib, "System.Threading", "Volatile"); gpointer iter = NULL; if (volatile_klass) { @@ -4743,10 +5107,10 @@ is_direct_callable (MonoAotCompile *acfg, MonoMethod *method, MonoJumpInfo *patc if (direct_callable) return TRUE; } - } else if ((patch_info->type == MONO_PATCH_INFO_ICALL_ADDR && patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) { + } else if ((patch_info->type == MONO_PATCH_INFO_ICALL_ADDR_CALL && patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) { if (acfg->aot_opts.direct_pinvoke) return TRUE; - } else if (patch_info->type == MONO_PATCH_INFO_ICALL_ADDR) { + } else if (patch_info->type == MONO_PATCH_INFO_ICALL_ADDR_CALL) { if (acfg->aot_opts.direct_icalls) return TRUE; return FALSE; @@ -4927,7 +5291,7 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui GPtrArray *patches; MonoJumpInfo *patch_info; MonoDebugSourceLocation **locs = NULL; - gboolean skip; + gboolean skip, prologue_end = FALSE; #ifdef MONO_ARCH_AOT_SUPPORTED gboolean direct_call, external_call; guint32 got_slot; @@ -4962,10 +5326,16 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui if (locs && locs [i]) { MonoDebugSourceLocation *loc = locs [i]; int findex; + const char *options; findex = get_file_index (acfg, loc->source_file); emit_unset_mode (acfg); - fprintf (acfg->fp, ".loc %d %d 0\n", findex, loc->row); + if (!prologue_end) + options = " prologue_end"; + else + options = ""; + prologue_end = TRUE; + fprintf (acfg->fp, ".loc %d %d 0%s\n", findex, loc->row, options); mono_debug_symfile_free_location (loc); } @@ -5029,7 +5399,7 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui } acfg->stats.all_calls ++; - } else if (patch_info->type == MONO_PATCH_INFO_ICALL_ADDR) { + } else if (patch_info->type == MONO_PATCH_INFO_ICALL_ADDR_CALL) { if (!got_only && is_direct_callable (acfg, method, patch_info)) { if (!(patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) direct_pinvoke = mono_lookup_icall_symbol (patch_info->data.method); @@ -5343,6 +5713,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint case MONO_PATCH_INFO_METHOD: case MONO_PATCH_INFO_METHOD_JUMP: case MONO_PATCH_INFO_ICALL_ADDR: + case MONO_PATCH_INFO_ICALL_ADDR_CALL: case MONO_PATCH_INFO_METHOD_RGCTX: case MONO_PATCH_INFO_METHOD_CODE_SLOT: encode_method_ref (acfg, patch_info->data.method, p, &p); @@ -5383,9 +5754,8 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint MonoClass *ex_class; ex_class = - mono_class_from_name (mono_defaults.exception_class->image, + mono_class_load_from_name (mono_defaults.exception_class->image, "System", (const char *)patch_info->data.target); - g_assert (ex_class); encode_klass_ref (acfg, ex_class, p, &p); break; } @@ -5565,11 +5935,13 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg) buf_size = (patches->len < 1000) ? 40960 : 40960 + (patches->len * 64); p = buf = (guint8 *)g_malloc (buf_size); - if (mono_class_get_cctor (method->klass)) + if (mono_class_get_cctor (method->klass)) { + encode_value (1, p, &p); encode_klass_ref (acfg, method->klass, p, &p); - else + } else { /* Not needed when loading the method */ encode_value (0, p, &p); + } g_assert (!(cfg->opt & MONO_OPT_SHARED)); @@ -6017,7 +6389,8 @@ get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cac case MONO_PATCH_INFO_RGCTX_FETCH: debug_sym = g_strdup_printf ("%s_rgctx_fetch_%d", prefix, acfg->label_generator ++); break; - case MONO_PATCH_INFO_ICALL_ADDR: { + case MONO_PATCH_INFO_ICALL_ADDR: + case MONO_PATCH_INFO_ICALL_ADDR_CALL: { char *s = get_debug_sym (ji->data.method, "", cache); debug_sym = g_strdup_printf ("%s_icall_native_%s", prefix, s); @@ -6628,6 +7001,15 @@ wrap_path (gchar * path) return clean; } +// Duplicate a char range and add it to a ptrarray, but only if it is nonempty +static void +ptr_array_add_range_if_nonempty(GPtrArray *args, gchar const *start, gchar const *end) +{ + ptrdiff_t len = end-start; + if (len > 0) + g_ptr_array_add (args, g_strndup (start, len)); +} + static GPtrArray * mono_aot_split_options (const char *aot_options) { @@ -6683,6 +7065,7 @@ mono_aot_split_options (const char *aot_options) next: aot_options++; + restart: // If the next character is end of string, then process the last option. if (*(aot_options) == '\0') { end_of_string = TRUE; @@ -6691,11 +7074,11 @@ mono_aot_split_options (const char *aot_options) continue; new_opt: - g_ptr_array_add (args, g_strndup (opt_start, aot_options - opt_start)); + ptr_array_add_range_if_nonempty (args, opt_start, aot_options); opt_start = ++aot_options; if (end_of_string) break; - goto next; + goto restart; // Check for null and continue loop } return args; @@ -7105,6 +7488,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) gboolean skip; int index, depth; MonoMethod *wrapped; + GTimer *jit_timer; JitFlags flags; if (acfg->aot_opts.metadata_only) @@ -7159,7 +7543,11 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) flags = (JitFlags)(flags | JIT_FLAG_LLVM_ONLY | JIT_FLAG_EXPLICIT_NULL_CHECKS); if (acfg->aot_opts.no_direct_calls) flags = (JitFlags)(flags | JIT_FLAG_NO_DIRECT_ICALLS); + + jit_timer = mono_time_track_start (); cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), flags, 0, index); + mono_time_track_end (&mono_jit_stats.jit_time, jit_timer); + mono_loader_clear_error (); if (cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) { @@ -7407,6 +7795,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) } /* Make a copy of the argument/local info */ { + MonoError error; MonoInst **args, **locals; MonoMethodSignature *sig; MonoMethodHeader *header; @@ -7420,7 +7809,8 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) } cfg->args = args; - header = mono_method_get_header (method); + header = mono_method_get_header_checked (method, &error); + mono_error_assert_ok (&error); /* FIXME don't swallow the error */ locals = (MonoInst **)mono_mempool_alloc (acfg->mempool, sizeof (MonoInst*) * header->num_locals); for (i = 0; i < header->num_locals; ++i) { locals [i] = (MonoInst *)mono_mempool_alloc (acfg->mempool, sizeof (MonoInst)); @@ -7458,6 +7848,8 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) g_hash_table_insert (acfg->method_to_cfg, cfg->orig_method, cfg); + mono_update_jit_stats (cfg); + /* if (cfg->orig_method->wrapper_type) g_ptr_array_add (acfg->extra_methods, cfg->orig_method); @@ -7788,7 +8180,7 @@ mono_aot_get_direct_call_symbol (MonoJumpInfoType type, gconstpointer data) if (type == MONO_PATCH_INFO_JIT_ICALL_ADDR) { /* Call to a C function implementing a jit icall */ sym = mono_lookup_jit_icall_symbol ((const char *)data); - } else if (type == MONO_PATCH_INFO_ICALL_ADDR) { + } else if (type == MONO_PATCH_INFO_ICALL_ADDR_CALL) { MonoMethod *method = (MonoMethod *)data; if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) sym = mono_lookup_icall_symbol (method); @@ -7818,7 +8210,7 @@ mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data) if (type == MONO_PATCH_INFO_JIT_ICALL_ADDR) { /* Call to a C function implementing a jit icall */ sym = mono_lookup_jit_icall_symbol ((const char *)data); - } else if (type == MONO_PATCH_INFO_ICALL_ADDR) { + } else if (type == MONO_PATCH_INFO_ICALL_ADDR_CALL) { MonoMethod *method = (MonoMethod *)data; if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) sym = mono_lookup_icall_symbol (method); @@ -7920,7 +8312,6 @@ emit_llvm_file (MonoAotCompile *acfg) * then removing tailcallelim + the global opts. * strip-dead-prototypes deletes unused intrinsics definitions. */ - //opts = g_strdup ("-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -domfrontier -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -iv-users -indvars -loop-deletion -loop-simplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -simplifycfg -domtree -verify"); /* The dse pass is disabled because of #13734 and #17616 */ /* * The dse bug is in DeadStoreElimination.cpp:isOverwrite (): @@ -7936,7 +8327,11 @@ emit_llvm_file (MonoAotCompile *acfg) // FIXME: This doesn't work yet opts = g_strdup (""); else +#if LLVM_API_VERSION > 100 + opts = g_strdup ("-O2"); +#else opts = g_strdup ("-targetlibinfo -no-aa -basicaa -notti -instcombine -simplifycfg -inline-cost -inline -sroa -domtree -early-cse -lazy-value-info -correlated-propagation -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -indvars -loop-idiom -loop-deletion -loop-unroll -memdep -gvn -memdep -memcpyopt -sccp -instcombine -lazy-value-info -correlated-propagation -domtree -memdep -adce -simplifycfg -instcombine -strip-dead-prototypes -domtree -verify"); +#endif command = g_strdup_printf ("\"%sopt\" -f %s -o \"%s\" \"%s\"", acfg->aot_opts.llvm_path, opts, optbc, tempbc); aot_printf (acfg, "Executing opt: %s\n", command); if (execute_system (command) != 0) @@ -7971,6 +8366,10 @@ emit_llvm_file (MonoAotCompile *acfg) g_string_append_printf (acfg->llc_args, " -mono-eh-frame-symbol=%s%s", acfg->user_symbol_prefix, acfg->llvm_eh_frame_symbol); +#if LLVM_API_VERSION > 100 + g_string_append_printf (acfg->llc_args, " -disable-tail-calls"); +#endif + #if defined(TARGET_MACH) && defined(TARGET_ARM) /* ios requires PIC code now */ g_string_append_printf (acfg->llc_args, " -relocation-model=pic"); @@ -8608,7 +9007,6 @@ emit_exception_info (MonoAotCompile *acfg) if (seq_points_to_file) { char *seq_points_aot_file = acfg->aot_opts.gen_seq_points_file_path ? acfg->aot_opts.gen_seq_points_file_path : g_strdup_printf("%s%s", acfg->image->name, SEQ_POINT_AOT_EXT); - printf("%s\n", seq_points_aot_file); mono_seq_point_data_write (&sp_data, seq_points_aot_file); mono_seq_point_data_free (&sp_data); g_free (seq_points_aot_file); @@ -9487,7 +9885,6 @@ compile_asm (MonoAotCompile *acfg) #define AS_OPTIONS "--64" #elif defined(TARGET_POWERPC64) #define AS_OPTIONS "-a64 -mppc64" -#define LD_OPTIONS "-m elf64ppc" #elif defined(sparc) && SIZEOF_VOID_P == 8 #define AS_OPTIONS "-xarch=v9" #elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__) @@ -9508,22 +9905,30 @@ compile_asm (MonoAotCompile *acfg) #define AS_NAME "as" #endif -#ifndef LD_OPTIONS -#define LD_OPTIONS "" -#endif - #if defined(sparc) -#define LD_NAME "ld -shared -G" +#define LD_NAME "ld" +#define LD_OPTIONS "-shared -G" #elif defined(__ppc__) && defined(TARGET_MACH) -#define LD_NAME "gcc -dynamiclib" +#define LD_NAME "gcc" +#define LD_OPTIONS "-dynamiclib" #elif defined(TARGET_AMD64) && defined(TARGET_MACH) -#define LD_NAME "clang --shared" +#define LD_NAME "clang" +#define LD_OPTIONS "--shared" #elif defined(TARGET_WIN32) && !defined(TARGET_ANDROID) -#define LD_NAME "gcc -shared --dll" +#define LD_NAME "gcc" +#define LD_OPTIONS "-shared" #elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__) -#define LD_NAME "clang -m32 -dynamiclib" +#define LD_NAME "clang" +#define LD_OPTIONS "-m32 -dynamiclib" #elif defined(TARGET_ARM) && !defined(TARGET_ANDROID) -#define LD_NAME "gcc --shared" +#define LD_NAME "gcc" +#define LD_OPTIONS "--shared" +#elif defined(TARGET_POWERPC64) +#define LD_OPTIONS "-m elf64ppc" +#endif + +#ifndef LD_OPTIONS +#define LD_OPTIONS "" #endif if (acfg->aot_opts.asm_only) { @@ -9599,10 +10004,11 @@ compile_asm (MonoAotCompile *acfg) ld_flags = g_strdup_printf ("%s %s", ld_flags, "-lstdc++"); #ifdef LD_NAME - command = g_strdup_printf ("%s -o %s %s %s %s", LD_NAME, + command = g_strdup_printf ("%s%s %s -o %s %s %s %s", tool_prefix, LD_NAME, LD_OPTIONS, wrap_path (tmp_outfile_name), wrap_path (llvm_ofile), wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags); #else + // Default (linux) command = g_strdup_printf ("\"%sld\" %s -shared -o %s %s %s %s", tool_prefix, LD_OPTIONS, wrap_path (tmp_outfile_name), wrap_path (llvm_ofile), wrap_path (g_strdup_printf ("%s.o", acfg->tmpfname)), ld_flags); @@ -10007,11 +10413,11 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) memset (&acfg->aot_opts, 0, sizeof (acfg->aot_opts)); acfg->aot_opts.write_symbols = TRUE; - acfg->aot_opts.ntrampolines = 1024; - acfg->aot_opts.nrgctx_trampolines = 1024; - acfg->aot_opts.nimt_trampolines = 128; + acfg->aot_opts.ntrampolines = 4096; + acfg->aot_opts.nrgctx_trampolines = 4096; + acfg->aot_opts.nimt_trampolines = 512; acfg->aot_opts.nrgctx_fetch_trampolines = 128; - acfg->aot_opts.ngsharedvt_arg_trampolines = 128; + acfg->aot_opts.ngsharedvt_arg_trampolines = 512; acfg->aot_opts.llvm_path = g_strdup (""); acfg->aot_opts.temp_path = g_strdup (""); #ifdef MONOTOUCH @@ -10035,7 +10441,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) //acfg->aot_opts.print_skipped_methods = TRUE; -#if !defined(ENABLE_GSHAREDVT) +#if !defined(MONO_ARCH_GSHAREDVT_SUPPORTED) if (opts & MONO_OPT_GSHAREDVT) { aot_printerrf (acfg, "-O=gsharedvt not supported on this platform.\n"); return 1; @@ -10050,13 +10456,13 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) #endif if (acfg->aot_opts.llvm_only) { -#ifndef ENABLE_GSHAREDVT - aot_printerrf (acfg, "--aot=llvmonly requires a runtime compiled with --enable-gsharedvt.\n"); +#ifndef MONO_ARCH_GSHAREDVT_SUPPORTED + aot_printerrf (acfg, "--aot=llvmonly requires a runtime that supports gsharedvt.\n"); return 1; #endif } -#if defined(ENABLE_GSHAREDVT) && defined(MONO_ARCH_GSHAREDVT_SUPPORTED) +#if defined(MONO_ARCH_GSHAREDVT_SUPPORTED) acfg->opts |= MONO_OPT_GSHAREDVT; opts |= MONO_OPT_GSHAREDVT; #endif @@ -10272,13 +10678,11 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) } } - if (acfg->aot_opts.dwarf_debug && acfg->aot_opts.asm_only && acfg->aot_opts.gnu_asm) { + if (acfg->aot_opts.dwarf_debug && acfg->aot_opts.gnu_asm) { /* * CLANG supports GAS .file/.loc directives, so emit line number information this way - * FIXME: CLANG only emits line number info for .loc directives followed by assembly, not - * .byte directives. */ - //acfg->gas_line_numbers = TRUE; + acfg->gas_line_numbers = TRUE; } if ((!acfg->aot_opts.nodebug || acfg->aot_opts.dwarf_debug) && acfg->has_jitted_code) { @@ -10286,7 +10690,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) aot_printerrf (acfg, "The dwarf AOT option requires the --debug option.\n"); return 1; } - acfg->dwarf = mono_dwarf_writer_create (acfg->w, NULL, 0, FALSE, !acfg->gas_line_numbers); + acfg->dwarf = mono_dwarf_writer_create (acfg->w, NULL, 0, !acfg->gas_line_numbers); } if (acfg->w) @@ -10419,7 +10823,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) int i; aot_printf (acfg, "GOT slot distribution:\n"); - for (i = 0; i < MONO_PATCH_INFO_NONE; ++i) + for (i = 0; i < MONO_PATCH_INFO_NUM; ++i) if (acfg->stats.got_slot_types [i]) aot_printf (acfg, "\t%s: %d (%d)\n", get_patch_name (i), acfg->stats.got_slot_types [i], acfg->stats.got_slot_info_sizes [i]); aot_printf (acfg, "\nMethod stats:\n");