Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[llvm] Generate code at the start of exception clauses to branch to t…

…he proper nesting clause so the EH code can branch to the innermost landing pad in the future. This is needed because LLVM always expects the innermost landing pad to be called.
commit f9bdc96a15a6e9516c14d98fa8874955799f1648 1 parent b387b3b
@vargaz vargaz authored
View
1  mono/mini/mini-amd64.h
@@ -233,6 +233,7 @@ typedef struct {
#define MONO_CONTEXT_SET_LLVM_EXC_REG(ctx, exc) do { (ctx)->rax = (gsize)exc; } while (0)
+#define MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG(ctx, sel) do { (ctx)->rdx = (gsize)(sel); } while (0)
#define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf)
View
10 mono/mini/mini-exceptions.c
@@ -1494,6 +1494,11 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, gpointer obj, gint3
*((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
}
+#ifdef MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG
+ if (ji->from_llvm)
+ MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG (ctx, i);
+#endif
+
mono_debugger_agent_begin_exception_filter (mono_ex, ctx, &initial_ctx);
filtered = call_filter (ctx, ei->data.filter);
mono_debugger_agent_end_exception_filter (mono_ex, ctx, &initial_ctx);
@@ -1789,6 +1794,11 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume,
}
}
+#ifdef MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG
+ if (ji->from_llvm)
+ MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG (ctx, i);
+#endif
+
if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
/*
* Filter clauses should only be run in the
View
65 mono/mini/mini-llvm.c
@@ -2465,6 +2465,7 @@ emit_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef builder
BBInfo *bblocks = ctx->bblocks;
LLVMTypeRef i8ptr;
LLVMValueRef personality;
+ LLVMValueRef landing_pad;
LLVMBasicBlockRef target_bb;
MonoInst *exvar;
static gint32 mapping_inited;
@@ -2473,6 +2474,7 @@ emit_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef builder
MonoClass **ti;
LLVMValueRef type_info;
int clause_index;
+ GSList *l;
// <resultval> = landingpad <somety> personality <type> <pers_fn> <clause>+
@@ -2526,7 +2528,6 @@ emit_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef builder
{
LLVMTypeRef members [2], ret_type;
- LLVMValueRef landing_pad;
members [0] = i8ptr;
members [1] = LLVMInt32Type ();
@@ -2548,11 +2549,69 @@ emit_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef builder
}
}
+#ifdef MONO_CONTEXT_SET_LLVM_EH_SELECTOR_REG
+ /*
+ * LLVM throw sites are associated with a one landing pad, and LLVM generated
+ * code expects control to be transferred to this landing pad even in the
+ * presence of nested clauses. The landing pad needs to branch to the landing
+ * pads belonging to nested clauses based on the selector value returned by
+ * the landing pad instruction, which is passed to the landing pad in a
+ * register by the EH code.
+ */
+ /* Store the exception object into the eh variable of nested clauses. */
+ for (l = ctx->nested_in [clause_index]; l; l = l->next) {
+ int nesting_clause_index = GPOINTER_TO_INT (l->data);
+ MonoBasicBlock *handler_bb;
+
+ handler_bb = g_hash_table_lookup (ctx->clause_to_handler, GINT_TO_POINTER (nesting_clause_index));
+ g_assert (handler_bb);
+
+ if (handler_bb->in_scount == 1) {
+ LLVMValueRef ex_obj = LLVMBuildExtractValue (builder, landing_pad, 0, "ex_obj");
+ MonoInst *var;
+ int vreg;
+
+ exvar = handler_bb->in_stack [0];
+ vreg = exvar->dreg;
+
+ /*
+ * Can't assign to exvar directly, because of SSA, so store into
+ * the location where the (volatile) exvar is stored.
+ */
+
+ /* From emit_volatile_store () */
+ var = get_vreg_to_inst (ctx->cfg, vreg);
+
+ g_assert (var && var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT));
+ g_assert (ctx->addresses [vreg]);
+ LLVMBuildStore (ctx->builder, convert (ctx, ex_obj, type_to_llvm_type (ctx, var->inst_vtype)), ctx->addresses [vreg]);
+ }
+ }
+
+ target_bb = bblocks [bb->block_num].call_handler_target_bb;
+ g_assert (target_bb);
+#endif
+
+ /*
+ * Branch to the correct landing pad
+ */
+ LLVMValueRef ex_selector = LLVMBuildExtractValue (builder, landing_pad, 1, "ex_selector");
+ LLVMValueRef switch_ins = LLVMBuildSwitch (builder, ex_selector, target_bb, 0);
+
+ for (l = ctx->nested_in [clause_index]; l; l = l->next) {
+ int nesting_clause_index = GPOINTER_TO_INT (l->data);
+ MonoBasicBlock *handler_bb;
+
+ handler_bb = g_hash_table_lookup (ctx->clause_to_handler, GINT_TO_POINTER (nesting_clause_index));
+ g_assert (handler_bb);
+
+ g_assert (ctx->bblocks [handler_bb->block_num].call_handler_target_bb);
+ LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), nesting_clause_index, FALSE), ctx->bblocks [handler_bb->block_num].call_handler_target_bb);
+ }
+
/* Start a new bblock which CALL_HANDLER can branch to */
target_bb = bblocks [bb->block_num].call_handler_target_bb;
if (target_bb) {
- LLVMBuildBr (builder, target_bb);
-
ctx->builder = builder = create_builder (ctx);
LLVMPositionBuilderAtEnd (ctx->builder, target_bb);
Please sign in to comment.
Something went wrong with that request. Please try again.