X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Faot-compiler.c;h=58d9bea5d9175e66f733004e136e42e018e6ccb1;hb=c2d511e567dd2d535056dc79b745f88b4fb64afa;hp=987c463270544770a2179a0deb723f255ebfaf5c;hpb=9fb25285a3f87354dc66d82cf4a989013212f229;p=mono.git diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 987c4632705..58d9bea5d91 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -99,6 +99,7 @@ typedef struct MonoAotOptions { int nthreads; int ntrampolines; gboolean print_skipped_methods; + char *tool_prefix; } MonoAotOptions; typedef struct MonoAotStats { @@ -422,7 +423,7 @@ encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf) /* ARCHITECTURE SPECIFIC CODE */ -#if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM) +#if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM) || defined(TARGET_POWERPC) #define EMIT_DWARF_INFO 1 #endif @@ -1001,15 +1002,15 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size) /* The IMT method is in v5 */ - /* Only IP is available, but we need at least two free registers */ - ARM_PUSH1 (code, ARMREG_R1); + /* Need at least two free registers, plus a slot for storing the pc */ + ARM_PUSH (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_R2)); labels [0] = code; /* Load the parameter from the GOT */ - ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0); - ARM_LDR_REG_REG (code, ARMREG_IP, ARMREG_PC, ARMREG_IP); + ARM_LDR_IMM (code, ARMREG_R0, ARMREG_PC, 0); + ARM_LDR_REG_REG (code, ARMREG_R0, ARMREG_PC, ARMREG_R0); labels [1] = code; - ARM_LDR_IMM (code, ARMREG_R1, ARMREG_IP, 0); + ARM_LDR_IMM (code, ARMREG_R1, ARMREG_R0, 0); ARM_CMP_REG_REG (code, ARMREG_R1, ARMREG_V5); labels [2] = code; ARM_B_COND (code, ARMCOND_EQ, 0); @@ -1020,16 +1021,19 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size) ARM_B_COND (code, ARMCOND_EQ, 0); /* Loop footer */ - ARM_ADD_REG_IMM8 (code, ARMREG_IP, ARMREG_IP, sizeof (gpointer) * 2); + ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_R0, sizeof (gpointer) * 2); labels [4] = code; ARM_B (code, 0); arm_patch (labels [4], labels [1]); /* Match */ arm_patch (labels [2], code); - ARM_POP1 (code, ARMREG_R1); - ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, 4); - ARM_LDR_IMM (code, ARMREG_PC, ARMREG_IP, 0); + ARM_LDR_IMM (code, ARMREG_R0, ARMREG_R0, 4); + ARM_LDR_IMM (code, ARMREG_R0, ARMREG_R0, 0); + /* Save it to the third stack slot */ + ARM_STR_IMM (code, ARMREG_R0, ARMREG_SP, 8); + /* Restore the registers and branch */ + ARM_POP (code, (1 << ARMREG_R0)|(1 << ARMREG_R1)|(1 << ARMREG_PC)); /* No match */ arm_patch (labels [3], code); @@ -1037,7 +1041,7 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size) /* Fixup offset */ code2 = labels [0]; - ARM_LDR_IMM (code2, ARMREG_IP, ARMREG_PC, (code - (labels [0] + 8))); + ARM_LDR_IMM (code2, ARMREG_R0, ARMREG_PC, (code - (labels [0] + 8))); emit_bytes (acfg, buf, code - buf); emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) + (code - (labels [0] + 8)) - 4); @@ -1050,14 +1054,14 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size) code = buf; /* Load the mscorlib got address */ - ppc_load_reg (code, ppc_r11, sizeof (gpointer), ppc_r30); + ppc_ldptr (code, ppc_r11, sizeof (gpointer), ppc_r30); /* Load the parameter from the GOT */ ppc_load (code, ppc_r0, offset * sizeof (gpointer)); - ppc_load_reg_indexed (code, ppc_r11, ppc_r11, ppc_r0); + ppc_ldptr_indexed (code, ppc_r11, ppc_r11, ppc_r0); /* Load and check key */ labels [1] = code; - ppc_load_reg (code, ppc_r0, 0, ppc_r11); + ppc_ldptr (code, ppc_r0, 0, ppc_r11); ppc_cmp (code, 0, sizeof (gpointer) == 8 ? 1 : 0, ppc_r0, MONO_ARCH_IMT_REG); labels [2] = code; ppc_bc (code, PPC_BR_TRUE, PPC_BR_EQ, 0); @@ -1075,10 +1079,10 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size) /* Match */ mono_ppc_patch (labels [2], code); - ppc_load_reg (code, ppc_r11, sizeof (gpointer), ppc_r11); + ppc_ldptr (code, ppc_r11, sizeof (gpointer), ppc_r11); /* r11 now contains the value of the vtable slot */ /* this is not a function descriptor on ppc64 */ - ppc_load_reg (code, ppc_r11, 0, ppc_r11); + ppc_ldptr (code, ppc_r11, 0, ppc_r11); ppc_mtctr (code, ppc_r11); ppc_bcctr (code, PPC_BR_ALWAYS, 0); @@ -1109,6 +1113,12 @@ arch_get_cie_program (void) mono_add_unwind_op_def_cfa (l, (guint8*)NULL, (guint8*)NULL, AMD64_RSP, 8); mono_add_unwind_op_offset (l, (guint8*)NULL, (guint8*)NULL, AMD64_RIP, -8); + return l; +#elif defined(TARGET_POWERPC) + GSList *l = NULL; + + mono_add_unwind_op_def_cfa (l, (guint8*)NULL, (guint8*)NULL, ppc_r1, 0); + return l; #else return NULL; @@ -1700,7 +1710,7 @@ static void add_wrappers (MonoAotCompile *acfg) { MonoMethod *method, *m; - int i, j, nallocators; + int i, j; MonoMethodSignature *sig, *csig; guint32 token; @@ -1746,8 +1756,11 @@ add_wrappers (MonoAotCompile *acfg) } if (strcmp (acfg->image->assembly->aname.name, "mscorlib") == 0) { +#ifdef MONO_ARCH_HAVE_TLS_GET MonoMethodDesc *desc; MonoMethod *orig_method; + int nallocators; +#endif /* Runtime invoke wrappers */ @@ -2026,6 +2039,14 @@ add_generic_class (MonoAotCompile *acfg, MonoClass *klass) add_extra_method (acfg, method); } + if (klass->delegate) { + method = mono_get_delegate_invoke (klass); + + method = mono_marshal_get_delegate_invoke (method, NULL); + + add_method (acfg, method); + } + /* * For ICollection, where T is a vtype, add instances of the helper methods * in Array, since a T[] could be cast to ICollection. @@ -2067,6 +2088,18 @@ add_generic_class (MonoAotCompile *acfg, MonoClass *klass) } } +static void +add_array_wrappers (MonoAotCompile *acfg, MonoClass *klass) +{ + int i; + + mono_class_setup_methods (klass); + for (i = 0; i < klass->method.count; ++i) { + if (klass->methods [i]->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) + add_extra_method (acfg, klass->methods [i]); + } +} + /* * add_generic_instances: * @@ -2135,6 +2168,157 @@ add_generic_instances (MonoAotCompile *acfg) add_generic_class (acfg, mono_class_from_mono_type (header->locals [j])); } } + + if (acfg->image == mono_defaults.corlib) { + /* Add GenericComparer instances for primitive types for Enum.ToString () */ + MonoClass *klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "GenericComparer`1"); + + if (klass) { + MonoGenericContext ctx; + MonoType *args [16]; + + memset (&ctx, 0, sizeof (ctx)); + + args [0] = &mono_defaults.byte_class->byval_arg; + ctx.class_inst = mono_metadata_get_generic_inst (1, args); + add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx)); + + args [0] = &mono_defaults.sbyte_class->byval_arg; + ctx.class_inst = mono_metadata_get_generic_inst (1, args); + add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx)); + + args [0] = &mono_defaults.int16_class->byval_arg; + ctx.class_inst = mono_metadata_get_generic_inst (1, args); + add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx)); + + args [0] = &mono_defaults.uint16_class->byval_arg; + ctx.class_inst = mono_metadata_get_generic_inst (1, args); + add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx)); + + args [0] = &mono_defaults.int32_class->byval_arg; + ctx.class_inst = mono_metadata_get_generic_inst (1, args); + add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx)); + + args [0] = &mono_defaults.uint32_class->byval_arg; + ctx.class_inst = mono_metadata_get_generic_inst (1, args); + add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx)); + + args [0] = &mono_defaults.int64_class->byval_arg; + ctx.class_inst = mono_metadata_get_generic_inst (1, args); + add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx)); + + args [0] = &mono_defaults.uint64_class->byval_arg; + ctx.class_inst = mono_metadata_get_generic_inst (1, args); + add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx)); + } + + /* Add GenericEqualityComparer instances for primitive types */ + klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "GenericEqualityComparer`1"); + + if (klass) { + MonoGenericContext ctx; + MonoType *args [16]; + + memset (&ctx, 0, sizeof (ctx)); + + args [0] = &mono_defaults.byte_class->byval_arg; + ctx.class_inst = mono_metadata_get_generic_inst (1, args); + add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx)); + + args [0] = &mono_defaults.sbyte_class->byval_arg; + ctx.class_inst = mono_metadata_get_generic_inst (1, args); + add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx)); + + args [0] = &mono_defaults.int16_class->byval_arg; + ctx.class_inst = mono_metadata_get_generic_inst (1, args); + add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx)); + + args [0] = &mono_defaults.uint16_class->byval_arg; + ctx.class_inst = mono_metadata_get_generic_inst (1, args); + add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx)); + + args [0] = &mono_defaults.int32_class->byval_arg; + ctx.class_inst = mono_metadata_get_generic_inst (1, args); + add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx)); + + args [0] = &mono_defaults.uint32_class->byval_arg; + ctx.class_inst = mono_metadata_get_generic_inst (1, args); + add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx)); + + args [0] = &mono_defaults.int64_class->byval_arg; + ctx.class_inst = mono_metadata_get_generic_inst (1, args); + add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx)); + + args [0] = &mono_defaults.uint64_class->byval_arg; + ctx.class_inst = mono_metadata_get_generic_inst (1, args); + add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx)); + } + + /* Emit the array wrapper methods for arrays of primitive types */ + add_array_wrappers (acfg, mono_array_class_get (mono_defaults.byte_class, 1)); + add_array_wrappers (acfg, mono_array_class_get (mono_defaults.sbyte_class, 1)); + add_array_wrappers (acfg, mono_array_class_get (mono_defaults.int16_class, 1)); + add_array_wrappers (acfg, mono_array_class_get (mono_defaults.uint16_class, 1)); + add_array_wrappers (acfg, mono_array_class_get (mono_defaults.int32_class, 1)); + add_array_wrappers (acfg, mono_array_class_get (mono_defaults.uint32_class, 1)); + add_array_wrappers (acfg, mono_array_class_get (mono_defaults.int64_class, 1)); + add_array_wrappers (acfg, mono_array_class_get (mono_defaults.single_class, 1)); + add_array_wrappers (acfg, mono_array_class_get (mono_defaults.double_class, 1)); + /* These are not handled by generic sharing */ + add_array_wrappers (acfg, mono_array_class_get (mono_defaults.object_class, 1)); + add_array_wrappers (acfg, mono_array_class_get (mono_defaults.string_class, 1)); + + /* Add instances of Array.GetGenericValueImpl */ + { + MonoGenericContext ctx; + MonoType *args [16]; + MonoMethod *method; + + memset (&ctx, 0, sizeof (ctx)); + + /* + * managed-to-native wrappers are not shared, so have to generate + * these for ref types too. + */ + klass = mono_array_class_get (mono_defaults.int_class, 1)->parent; + method = mono_class_get_method_from_name (klass, "GetGenericValueImpl", 2); + + if (method) { + /* String */ + args [0] = &mono_defaults.string_class->byval_arg; + ctx.method_inst = mono_metadata_get_generic_inst (1, args); + add_extra_method (acfg, mono_marshal_get_native_wrapper (mono_class_inflate_generic_method (method, &ctx), TRUE, TRUE)); + } + } + } +} + +/* + * is_direct_callable: + * + * Return whenever the method identified by JI is directly callable without + * going through the PLT. + */ +static gboolean +is_direct_callable (MonoAotCompile *acfg, MonoMethod *method, MonoJumpInfo *patch_info) +{ + if ((patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == acfg->image)) { + MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method); + if (callee_cfg) { + gboolean direct_callable = TRUE; + + if (direct_callable && !(!callee_cfg->has_got_slots && (callee_cfg->method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT))) + direct_callable = FALSE; + if ((callee_cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) && (!method || method->wrapper_type != MONO_WRAPPER_SYNCHRONIZED)) + // FIXME: Maybe call the wrapper directly ? + direct_callable = FALSE; + + if (direct_callable) + return TRUE; + } + } + + return FALSE; } /* @@ -2201,23 +2385,14 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui * the same assembly and requires no initialization. */ direct_call = FALSE; - if (!got_only && (patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == method->klass->image)) { - MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method); - if (callee_cfg) { - gboolean direct_callable = TRUE; - - if (direct_callable && !(!callee_cfg->has_got_slots && (callee_cfg->method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT))) - direct_callable = FALSE; - if ((callee_cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) && method->wrapper_type != MONO_WRAPPER_SYNCHRONIZED) - // FIXME: Maybe call the wrapper directly ? - direct_callable = FALSE; - if (direct_callable) { - //printf ("DIRECT: %s %s\n", method ? mono_method_full_name (method, TRUE) : "", mono_method_full_name (callee_cfg->method, TRUE)); - direct_call = TRUE; - sprintf (direct_call_target, "%sm_%x", acfg->temp_prefix, get_method_index (acfg, callee_cfg->orig_method)); - patch_info->type = MONO_PATCH_INFO_NONE; - acfg->stats.direct_calls ++; - } + if ((patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == acfg->image)) { + if (!got_only && is_direct_callable (acfg, method, patch_info)) { + MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method); + //printf ("DIRECT: %s %s\n", method ? mono_method_full_name (method, TRUE) : "", mono_method_full_name (callee_cfg->method, TRUE)); + direct_call = TRUE; + sprintf (direct_call_target, "%sm_%x", acfg->temp_prefix, get_method_index (acfg, callee_cfg->orig_method)); + patch_info->type = MONO_PATCH_INFO_NONE; + acfg->stats.direct_calls ++; } acfg->stats.all_calls ++; @@ -2274,6 +2449,21 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui } } +/* + * sanitize_symbol: + * + * Modify SYMBOL so it only includes characters permissible in symbols. + */ +static void +sanitize_symbol (char *symbol) +{ + int i, len = strlen (symbol); + + for (i = 0; i < len; ++i) + if (!isalnum (symbol [i]) && (symbol [i] != '_')) + symbol [i] = '_'; +} + static char* get_debug_sym (MonoMethod *method, const char *prefix, GHashTable *cache) { @@ -2702,7 +2892,7 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg) use_unwind_ops = cfg->unwind_ops != NULL; #endif - flags = (jinfo->has_generic_jit_info ? 1 : 0) | (use_unwind_ops ? 2 : 0); + flags = (jinfo->has_generic_jit_info ? 1 : 0) | (use_unwind_ops ? 2 : 0) | (header->num_clauses ? 4 : 0); encode_value (jinfo->code_size, p, &p); encode_value (flags, p, &p); @@ -2723,19 +2913,28 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg) } /* Exception table */ - if (header->num_clauses) { - for (k = 0; k < header->num_clauses; ++k) { - MonoJitExceptionInfo *ei = &jinfo->clauses [k]; + if (jinfo->num_clauses) + encode_value (jinfo->num_clauses, p, &p); - encode_value (ei->exvar_offset, p, &p); + for (k = 0; k < jinfo->num_clauses; ++k) { + MonoJitExceptionInfo *ei = &jinfo->clauses [k]; - if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) - encode_value ((gint)((guint8*)ei->data.filter - code), p, &p); + encode_value (ei->exvar_offset, p, &p); - encode_value ((gint)((guint8*)ei->try_start - code), p, &p); - encode_value ((gint)((guint8*)ei->try_end - code), p, &p); - encode_value ((gint)((guint8*)ei->handler_start - code), p, &p); + if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) + encode_value ((gint)((guint8*)ei->data.filter - code), p, &p); + else { + if (ei->data.catch_class) { + encode_value (1, p, &p); + encode_klass_ref (acfg, ei->data.catch_class, p, &p); + } else { + encode_value (0, p, &p); + } } + + encode_value ((gint)((guint8*)ei->try_start - code), p, &p); + encode_value ((gint)((guint8*)ei->try_end - code), p, &p); + encode_value ((gint)((guint8*)ei->handler_start - code), p, &p); } if (jinfo->has_generic_jit_info) { @@ -2887,13 +3086,45 @@ emit_plt (MonoAotCompile *acfg) emit_label (acfg, label); if (acfg->aot_opts.write_symbols) { - MonoJumpInfo *patch_info = g_hash_table_lookup (acfg->plt_offset_to_patch, GUINT_TO_POINTER (i)); + MonoJumpInfo *ji = g_hash_table_lookup (acfg->plt_offset_to_patch, GUINT_TO_POINTER (i)); + char *debug_sym = NULL; - if (patch_info && patch_info->type == MONO_PATCH_INFO_METHOD) { - char *debug_sym = get_debug_sym (patch_info->data.method, "plt_", cache); + if (ji) { + switch (ji->type) { + case MONO_PATCH_INFO_METHOD: + debug_sym = get_debug_sym (ji->data.method, "plt_", cache); + break; + case MONO_PATCH_INFO_INTERNAL_METHOD: + debug_sym = g_strdup_printf ("plt__jit_icall_%s", ji->data.name); + break; + case MONO_PATCH_INFO_CLASS_INIT: + debug_sym = g_strdup_printf ("plt__class_init_%s", mono_type_get_name (&ji->data.klass->byval_arg)); + sanitize_symbol (debug_sym); + break; + case MONO_PATCH_INFO_RGCTX_FETCH: + debug_sym = g_strdup_printf ("plt__rgctx_fetch_%d", acfg->label_generator ++); + break; + case MONO_PATCH_INFO_ICALL_ADDR: { + char *s = get_debug_sym (ji->data.method, "", cache); + + debug_sym = g_strdup_printf ("plt__icall_native_%s", s); + g_free (s); + break; + } + case MONO_PATCH_INFO_JIT_ICALL_ADDR: + debug_sym = g_strdup_printf ("plt__jit_icall_native_%s", ji->data.name); + break; + case MONO_PATCH_INFO_GENERIC_CLASS_INIT: + debug_sym = g_strdup_printf ("plt__generic_class_init"); + break; + default: + break; + } - emit_local_symbol (acfg, debug_sym, NULL, TRUE); - emit_label (acfg, debug_sym); + if (debug_sym) { + emit_local_symbol (acfg, debug_sym, NULL, TRUE); + emit_label (acfg, debug_sym); + } } } @@ -3215,6 +3446,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts) opts->nodebug = TRUE; } else if (str_begins_with (arg, "ntrampolines=")) { opts->ntrampolines = atoi (arg + strlen ("ntrampolines=")); + } else if (str_begins_with (arg, "tool-prefix=")) { + opts->tool_prefix = g_strdup (arg + strlen ("tool-prefix=")); } else { fprintf (stderr, "AOT : Unknown argument '%s'.\n", arg); exit (1); @@ -3473,6 +3706,13 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) } break; } + case MONO_PATCH_INFO_VTABLE: { + MonoClass *klass = patch_info->data.klass; + + if (klass->generic_class && !mono_generic_context_is_sharable (&klass->generic_class->context, FALSE)) + add_generic_class (acfg, klass); + break; + } default: break; } @@ -4487,7 +4727,7 @@ emit_got (MonoAotCompile *acfg) char symbol [256]; /* Don't make GOT global so accesses to it don't need relocations */ - sprintf (symbol, acfg->got_symbol); + sprintf (symbol, "%s", acfg->got_symbol); emit_section_change (acfg, ".bss", 0); emit_alignment (acfg, 8); emit_local_symbol (acfg, symbol, "got_end", FALSE); @@ -4626,6 +4866,7 @@ emit_file_info (MonoAotCompile *acfg) emit_int32 (acfg, acfg->plt_got_offset_base); emit_int32 (acfg, (int)(acfg->got_offset * sizeof (gpointer))); emit_int32 (acfg, acfg->plt_offset); + emit_int32 (acfg, acfg->nmethods); for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i) emit_int32 (acfg, acfg->num_trampolines [i]); @@ -4762,6 +5003,7 @@ compile_asm (MonoAotCompile *acfg) { char *command, *objfile; char *outfile_name, *tmp_outfile_name; + const char *tool_prefix = acfg->aot_opts.tool_prefix ? acfg->aot_opts.tool_prefix : ""; #if defined(TARGET_AMD64) #define AS_OPTIONS "--64" @@ -4793,7 +5035,7 @@ compile_asm (MonoAotCompile *acfg) } else { objfile = g_strdup_printf ("%s.o", acfg->tmpfname); } - command = g_strdup_printf ("as %s %s -o %s", AS_OPTIONS, acfg->tmpfname, objfile); + command = g_strdup_printf ("%sas %s %s -o %s", tool_prefix, AS_OPTIONS, acfg->tmpfname, objfile); printf ("Executing the native assembler: %s\n", command); if (system (command) != 0) { g_free (command); @@ -4824,7 +5066,7 @@ compile_asm (MonoAotCompile *acfg) #elif defined(PLATFORM_WIN32) command = g_strdup_printf ("gcc -shared --dll -mno-cygwin -o %s %s.o", tmp_outfile_name, acfg->tmpfname); #else - command = g_strdup_printf ("ld %s -shared -o %s %s.o", LD_OPTIONS, tmp_outfile_name, acfg->tmpfname); + command = g_strdup_printf ("%sld %s -shared -o %s %s.o", tool_prefix, LD_OPTIONS, tmp_outfile_name, acfg->tmpfname); #endif printf ("Executing the native linker: %s\n", command); if (system (command) != 0) { @@ -4847,7 +5089,7 @@ compile_asm (MonoAotCompile *acfg) * gas generates 'mapping symbols' each time code and data is mixed, which * happens a lot in emit_and_reloc_code (), so we need to get rid of them. */ - command = g_strdup_printf ("strip --strip-symbol=\\$a --strip-symbol=\\$d %s", tmp_outfile_name); + command = g_strdup_printf ("%sstrip --strip-symbol=\\$a --strip-symbol=\\$d %s", tool_prefix, tmp_outfile_name); printf ("Stripping the binary: %s\n", command); if (system (command) != 0) { g_free (tmp_outfile_name); @@ -4977,11 +5219,14 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options) acfg->plt_symbol = g_strdup_printf ("mono_aot_%s_plt", acfg->image->assembly->aname.name); /* Get rid of characters which cannot occur in symbols */ - p = acfg->got_symbol; for (p = acfg->got_symbol; *p; ++p) { if (!(isalnum (*p) || *p == '_')) *p = '_'; } + for (p = acfg->plt_symbol; *p; ++p) { + if (!(isalnum (*p) || *p == '_')) + *p = '_'; + } acfg->method_index = 1;