Skip to content

Commit

Permalink
[llvm] Generate code at the start of exception clauses to branch to t…
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
vargaz committed Mar 30, 2015
1 parent b387b3b commit f9bdc96
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 3 deletions.
1 change: 1 addition & 0 deletions mono/mini/mini-amd64.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
10 changes: 10 additions & 0 deletions mono/mini/mini-exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down
65 changes: 62 additions & 3 deletions mono/mini/mini-llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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>+

Expand Down Expand Up @@ -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 ();
Expand All @@ -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);

Expand Down

0 comments on commit f9bdc96

Please sign in to comment.