From c5b94fae57c2a127e4100d132075a3329f89b95d Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 17 Jun 2010 00:28:24 +0000 Subject: [PATCH] 2010-06-17 Zoltan Varga * mini-llvm.c (emit_cond_system_exception): Pass the ip of to throw_corlib_trampoline using a block address if using the LLVM mono branch. * exceptions-amd64.c (mono_arch_exceptions_init): Add new LLVM throw corlib exception trampolines. svn path=/trunk/mono/; revision=159044 --- mono/mini/ChangeLog | 8 ++++ mono/mini/exceptions-amd64.c | 45 +++++++++++++++------ mono/mini/mini-amd64.h | 2 +- mono/mini/mini-llvm.c | 77 ++++++++++++++++++++---------------- 4 files changed, 87 insertions(+), 45 deletions(-) diff --git a/mono/mini/ChangeLog b/mono/mini/ChangeLog index a5fd3b77dd5..50332073cba 100755 --- a/mono/mini/ChangeLog +++ b/mono/mini/ChangeLog @@ -1,3 +1,11 @@ +2010-06-17 Zoltan Varga + + * mini-llvm.c (emit_cond_system_exception): Pass the ip of to throw_corlib_trampoline + using a block address if using the LLVM mono branch. + + * exceptions-amd64.c (mono_arch_exceptions_init): Add new LLVM throw corlib exception + trampolines. + 2010-06-15 Zoltan Varga * mini-ppc.c (mono_arch_get_cie_program): Define this for powerpc too. diff --git a/mono/mini/exceptions-amd64.c b/mono/mini/exceptions-amd64.c index 4002c8c20c8..006d59063b7 100644 --- a/mono/mini/exceptions-amd64.c +++ b/mono/mini/exceptions-amd64.c @@ -358,7 +358,7 @@ mono_amd64_throw_corlib_exception (guint64 dummy1, guint64 dummy2, guint64 dummy guint64 rbx, guint64 rbp, guint64 r12, guint64 r13, guint64 r14, guint64 r15, guint64 rdi, guint64 rsi, guint64 rax, guint64 rcx, guint64 rdx, - gint32 pc_offset) + gint64 pc_offset) { guint32 ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index; MonoException *ex; @@ -367,6 +367,9 @@ mono_amd64_throw_corlib_exception (guint64 dummy1, guint64 dummy2, guint64 dummy rip -= pc_offset; + /* Negate the ip adjustment done in mono_amd64_throw_exception () */ + rip += 1; + mono_amd64_throw_exception (dummy1, dummy2, dummy3, dummy4, dummy5, dummy6, (MonoObject*)ex, rip, rsp, rbx, rbp, r12, r13, r14, r15, rdi, rsi, rax, rcx, rdx, FALSE); } @@ -377,7 +380,7 @@ mono_amd64_throw_corlib_exception (guint64 dummy1, guint64 dummy2, guint64 dummy * mono_amd64_throw_corlib_exception. */ static gpointer -get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, gboolean aot) +get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, gboolean llvm_abs, gboolean aot) { guint8* start; guint8 *code; @@ -393,10 +396,18 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g amd64_mov_reg_reg (code, AMD64_R11, AMD64_RSP, 8); /* reverse order */ - if (corlib) + if (corlib) { amd64_push_reg (code, AMD64_ARG_REG2); - else + if (llvm_abs) + /* + * The caller is LLVM code which passes the absolute address not a pc offset, + * so compensate by passing 0 as 'rip' and passing the negated abs address as + * the pc offset. + */ + amd64_neg_membase (code, X86_ESP, 0); + } else { amd64_push_imm (code, rethrow); + } amd64_push_reg (code, AMD64_RDX); amd64_push_reg (code, AMD64_RCX); amd64_push_reg (code, AMD64_RAX); @@ -414,7 +425,10 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g amd64_push_reg (code, AMD64_RAX); /* IP */ - amd64_push_membase (code, AMD64_R11, 0); + if (llvm_abs) + amd64_push_imm (code, 0); + else + amd64_push_membase (code, AMD64_R11, 0); if (corlib) /* exc type token */ @@ -436,7 +450,7 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g #endif if (aot) { - ji = mono_patch_info_list_prepend (ji, code - start, MONO_PATCH_INFO_JIT_ICALL_ADDR, corlib ? "mono_amd64_throw_corlib_exception" : "mono_amd64_throw_exception"); + ji = mono_patch_info_list_prepend (ji, code - start, MONO_PATCH_INFO_JIT_ICALL_ADDR, corlib ? (llvm_abs ? "mono_amd64_throw_corlib_exception_abs" : "mono_amd64_throw_corlib_exception") : "mono_amd64_throw_exception"); amd64_mov_reg_membase (code, AMD64_R11, AMD64_RIP, 0, 8); } else { amd64_mov_reg_imm (code, AMD64_R11, corlib ? (gpointer)mono_amd64_throw_corlib_exception : (gpointer)mono_amd64_throw_exception); @@ -448,11 +462,11 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g g_assert ((code - start) < 64); - mono_save_trampoline_xdebug_info (corlib ? "throw_corlib_exception_trampoline" + mono_save_trampoline_xdebug_info (corlib ? (llvm_abs ? "throw_corlib_exception_trampoline_llvm_abs" : "throw_corlib_exception_trampoline") : "throw_exception_trampoline", start, code - start, unwind_ops); if (info) - *info = mono_tramp_info_create (g_strdup_printf (corlib ? "throw_corlib_exception" : (rethrow ? "rethrow_exception" : "throw_exception")), start, code - start, ji, unwind_ops); + *info = mono_tramp_info_create (g_strdup_printf (corlib ? (llvm_abs ? "throw_corlib_exception_llvm_abs" : "throw_corlib_exception") : (rethrow ? "rethrow_exception" : "throw_exception")), start, code - start, ji, unwind_ops); return start; } @@ -468,13 +482,13 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g gpointer mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot) { - return get_throw_trampoline (info, FALSE, FALSE, aot); + return get_throw_trampoline (info, FALSE, FALSE, FALSE, aot); } gpointer mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) { - return get_throw_trampoline (info, TRUE, FALSE, aot); + return get_throw_trampoline (info, TRUE, FALSE, FALSE, aot); } /** @@ -490,7 +504,7 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot) gpointer mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot) { - return get_throw_trampoline (info, FALSE, TRUE, aot); + return get_throw_trampoline (info, FALSE, TRUE, FALSE, aot); } /* @@ -1075,12 +1089,21 @@ mono_arch_notify_pending_exc (void) void mono_arch_exceptions_init (void) { + guint8 *tramp; + if (mono_aot_only) { throw_pending_exception = mono_aot_get_trampoline ("throw_pending_exception"); } else { /* Call this to avoid initialization races */ throw_pending_exception = mono_arch_get_throw_pending_exception (NULL, FALSE); } + + /* LLVM needs different throw trampolines */ + tramp = get_throw_trampoline (NULL, FALSE, TRUE, FALSE, FALSE); + mono_register_jit_icall (tramp, "mono_arch_llvm_throw_corlib_exception", NULL, TRUE); + + tramp = get_throw_trampoline (NULL, FALSE, TRUE, TRUE, FALSE); + mono_register_jit_icall (tramp, "mono_arch_llvm_throw_corlib_exception_abs", NULL, TRUE); } #ifdef TARGET_WIN32 diff --git a/mono/mini/mini-amd64.h b/mono/mini/mini-amd64.h index b0f815753dc..798b40caf1d 100644 --- a/mono/mini/mini-amd64.h +++ b/mono/mini/mini-amd64.h @@ -426,7 +426,7 @@ mono_amd64_throw_corlib_exception (guint64 dummy1, guint64 dummy2, guint64 dummy guint64 rbx, guint64 rbp, guint64 r12, guint64 r13, guint64 r14, guint64 r15, guint64 rdi, guint64 rsi, guint64 rax, guint64 rcx, guint64 rdx, - gint32 pc_offset) MONO_INTERNAL; + gint64 pc_offset) MONO_INTERNAL; guint64 mono_amd64_get_original_ip (void) MONO_INTERNAL; diff --git a/mono/mini/mini-llvm.c b/mono/mini/mini-llvm.c index f34ea5bf882..3798dc4ac47 100644 --- a/mono/mini/mini-llvm.c +++ b/mono/mini/mini-llvm.c @@ -131,6 +131,12 @@ llvm_ins_info[] = { #define TRACE_FAILURE(msg) #endif +#ifdef TARGET_X86 +#define IS_TARGET_X86 1 +#else +#define IS_TARGET_X86 0 +#endif + #define LLVM_FAILURE(ctx, reason) do { \ TRACE_FAILURE (reason); \ (ctx)->cfg->exception_message = g_strdup (reason); \ @@ -1038,11 +1044,6 @@ get_plt_entry (EmitContext *ctx, LLVMTypeRef llvm_sig, MonoJumpInfoType type, gc return callee; } -static void -emit_cond_throw_pos (EmitContext *ctx) -{ -} - static int get_handler_clause (MonoCompile *cfg, MonoBasicBlock *bb) { @@ -1209,7 +1210,7 @@ emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *ex LLVMBuilderRef builder; MonoClass *exc_class; LLVMValueRef args [2]; - + ex_bb = gen_bb (ctx, "EX_BB"); noex_bb = gen_bb (ctx, "NOEX_BB"); @@ -1225,48 +1226,61 @@ emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *ex if (!ctx->lmodule->throw_corlib_exception) { LLVMValueRef callee; LLVMTypeRef sig; + const char *icall_name; MonoMethodSignature *throw_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 2); throw_sig->ret = &mono_defaults.void_class->byval_arg; throw_sig->params [0] = &mono_defaults.int32_class->byval_arg; - throw_sig->params [1] = &mono_defaults.int32_class->byval_arg; + if (IS_LLVM_MONO_BRANCH) { + icall_name = "mono_arch_llvm_throw_corlib_exception_abs"; + throw_sig->params [1] = &mono_defaults.int_class->byval_arg; + } else { + icall_name = "mono_arch_llvm_throw_corlib_exception"; + throw_sig->params [1] = &mono_defaults.int32_class->byval_arg; + } sig = sig_to_llvm_sig (ctx, throw_sig); if (ctx->cfg->compile_aot) { - callee = get_plt_entry (ctx, sig, MONO_PATCH_INFO_INTERNAL_METHOD, "mono_arch_throw_corlib_exception"); + callee = get_plt_entry (ctx, sig, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name); } else { - callee = LLVMAddFunction (ctx->module, "throw_corlib_exception", sig_to_llvm_sig (ctx, throw_sig)); + callee = LLVMAddFunction (ctx->module, "llvm_throw_corlib_exception", sig_to_llvm_sig (ctx, throw_sig)); -#ifdef TARGET_X86 - /* - * LLVM generated code doesn't push the arguments, so we need another - * throw trampoline. + /* + * Differences between the LLVM/non-LLVM throw corlib exception trampoline: + * - On x86, LLVM generated code doesn't push the arguments + * - When using the LLVM mono branch, the trampoline takes the throw address as an + * arguments, not a pc offset. */ - LLVMAddGlobalMapping (ee, callee, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, "mono_arch_llvm_throw_corlib_exception")); -#else - LLVMAddGlobalMapping (ee, callee, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, "mono_arch_throw_corlib_exception")); -#endif + LLVMAddGlobalMapping (ee, callee, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name)); } mono_memory_barrier (); ctx->lmodule->throw_corlib_exception = callee; } -#ifdef TARGET_X86 - args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token - MONO_TOKEN_TYPE_DEF, FALSE); -#else - args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token, FALSE); -#endif + if (IS_TARGET_X86) + args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token - MONO_TOKEN_TYPE_DEF, FALSE); + else + args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token, FALSE); - /* - * FIXME: The offset is 0, this is only a problem if the code is inside a clause, - * otherwise only the line numbers in stack traces are incorrect. - */ - if (bb->region != -1) - LLVM_FAILURE (ctx, "system-ex-in-region"); + if (IS_LLVM_MONO_BRANCH) { + /* + * The LLVM mono branch contains changes so a block address can be passed as an + * argument to a call. + */ + args [1] = LLVMBuildPtrToInt (builder, LLVMBlockAddress (ctx->lmethod, ex_bb), IntPtrType (), ""); + emit_call (ctx, bb, &builder, ctx->lmodule->throw_corlib_exception, args, 2); + } else { + /* + * FIXME: The offset is 0, this is only a problem if the code is inside a clause, + * otherwise only the line numbers in stack traces are incorrect. + */ + if (bb->region != -1 && !IS_LLVM_MONO_BRANCH) + LLVM_FAILURE (ctx, "system-ex-in-region"); - args [1] = LLVMConstInt (LLVMInt32Type (), 0, FALSE); - emit_call (ctx, bb, &builder, ctx->lmodule->throw_corlib_exception, args, 2); + args [1] = LLVMConstInt (LLVMInt32Type (), 0, FALSE); + emit_call (ctx, bb, &builder, ctx->lmodule->throw_corlib_exception, args, 2); + } LLVMBuildUnreachable (builder); @@ -2227,7 +2241,6 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) /* Add stores for volatile variables */ emit_volatile_store (ctx, ins->next->dreg); } else if (MONO_IS_COND_EXC (ins->next)) { - //emit_cond_throw_pos (ctx); emit_cond_system_exception (ctx, bb, ins->next->inst_p1, cmp); CHECK_FAILURE (ctx); builder = ctx->builder; @@ -3063,8 +3076,6 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) { LLVMValueRef args [2], val, ovf, func; - emit_cond_throw_pos (ctx); - args [0] = convert (ctx, lhs, op_to_llvm_type (ins->opcode)); args [1] = convert (ctx, rhs, op_to_llvm_type (ins->opcode)); func = LLVMGetNamedFunction (module, ovf_op_to_intrins (ins->opcode)); -- 2.25.1