aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-06-15 19:19:13 -0400
committerAndrew Kelley <andrew@ziglang.org>2019-06-15 19:19:13 -0400
commit9564c05cd5641095d48baf982a372f00bdf02659 (patch)
tree695ceb61c44021f4a04608e20f4be7f007830586 /src/ir.cpp
parent6bf193af192ffaf3465958a243ec8fc8941cfe4d (diff)
downloadzig-9564c05cd5641095d48baf982a372f00bdf02659.tar.gz
zig-9564c05cd5641095d48baf982a372f00bdf02659.zip
better result location handling of inline loops
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp111
1 files changed, 89 insertions, 22 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index b6f45a5325..d48c013caf 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -166,6 +166,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg);
static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing);
+static void ir_assert(bool ok, IrInstruction *source_instruction);
static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var);
static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op);
static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval, ResultLoc *result_loc);
@@ -904,6 +905,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionResolveResult *)
return IrInstructionIdResolveResult;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionResetResult *) {
+ return IrInstructionIdResetResult;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionResultPtr *) {
return IrInstructionIdResultPtr;
}
@@ -2865,6 +2870,15 @@ static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstN
return &instruction->base;
}
+static IrInstruction *ir_build_reset_result(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ ResultLoc *result_loc)
+{
+ IrInstructionResetResult *instruction = ir_build_instruction<IrInstructionResetResult>(irb, scope, source_node);
+ instruction->result_loc = result_loc;
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_result_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
ResultLoc *result_loc, IrInstruction *result)
{
@@ -3540,6 +3554,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
{
ResultLocReturn *result_loc_ret = allocate<ResultLocReturn>(1);
result_loc_ret->base.id = ResultLocIdReturn;
+ ir_build_reset_result(irb, scope, node, &result_loc_ret->base);
IrInstruction *return_value;
if (expr_node) {
@@ -3929,7 +3944,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod
return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr);
}
-static ResultLocPeerParent *create_binary_result_peers(IrInstruction *cond_br_inst,
+static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst,
IrBasicBlock *else_block, IrBasicBlock *endif_block, ResultLoc *parent, IrInstruction *is_comptime)
{
ResultLocPeerParent *peer_parent = allocate<ResultLocPeerParent>(1);
@@ -3948,6 +3963,13 @@ static ResultLocPeerParent *create_binary_result_peers(IrInstruction *cond_br_in
peer_parent->peers[1].base.source_instruction = cond_br_inst;
peer_parent->peers[1].parent = peer_parent;
peer_parent->peers[1].next_bb = endif_block;
+
+ IrInstruction *popped_inst = irb->current_basic_block->instruction_list.pop();
+ ir_assert(popped_inst == cond_br_inst, cond_br_inst);
+
+ ir_build_reset_result(irb, cond_br_inst->scope, cond_br_inst->source_node, &peer_parent->base);
+ irb->current_basic_block->instruction_list.append(popped_inst);
+
return peer_parent;
}
@@ -3978,8 +4000,8 @@ static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode
IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "OptionalEnd");
IrInstruction *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_non_null, ok_block, null_block, is_comptime);
- ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, ok_block, end_block, result_loc,
- is_comptime);
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, ok_block, end_block,
+ result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, null_block);
IrInstruction *null_result = ir_gen_node_extra(irb, op2_node, parent_scope, lval, &peer_parent->peers[0].base);
@@ -5006,6 +5028,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
ir_ref_instruction(dest_type, irb->current_basic_block);
result_loc_bit_cast->parent = result_loc;
+ ir_build_reset_result(irb, scope, node, &result_loc_bit_cast->base);
+
AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
IrInstruction *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone,
&result_loc_bit_cast->base);
@@ -5494,8 +5518,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, condition->source_node, condition,
then_block, else_block, is_comptime);
-
- ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, endif_block,
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block,
result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, then_block);
@@ -5832,11 +5855,14 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
zig_unreachable();
}
-static ResultLocVar *create_var_result_loc(IrInstruction *alloca, ZigVar *var) {
+static ResultLocVar *ir_build_var_result_loc(IrBuilder *irb, IrInstruction *alloca, ZigVar *var) {
ResultLocVar *result_loc_var = allocate<ResultLocVar>(1);
result_loc_var->base.id = ResultLocIdVar;
result_loc_var->base.source_instruction = alloca;
result_loc_var->var = var;
+
+ ir_build_reset_result(irb, alloca->scope, alloca->source_node, &result_loc_var->base);
+
return result_loc_var;
}
@@ -5844,7 +5870,7 @@ static void build_decl_var_and_init(IrBuilder *irb, Scope *scope, AstNode *sourc
IrInstruction *init, const char *name_hint, IrInstruction *is_comptime)
{
IrInstruction *alloca = ir_build_alloca_src(irb, scope, source_node, nullptr, name_hint, is_comptime);
- ResultLocVar *var_result_loc = create_var_result_loc(alloca, var);
+ ResultLocVar *var_result_loc = ir_build_var_result_loc(irb, alloca, var);
ir_build_end_expr(irb, scope, source_node, init, &var_result_loc->base);
ir_build_var_decl_src(irb, scope, source_node, var, nullptr, alloca);
}
@@ -5907,7 +5933,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
buf_ptr(variable_declaration->symbol), is_comptime);
// Create a result location for the initialization expression.
- ResultLocVar *result_loc_var = create_var_result_loc(alloca, var);
+ ResultLocVar *result_loc_var = ir_build_var_result_loc(irb, alloca, var);
ResultLoc *init_result_loc = (type_instruction == nullptr) ? &result_loc_var->base : nullptr;
Scope *init_scope = is_comptime_scalar ?
@@ -5983,10 +6009,11 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
else_block, body_block, is_comptime);
cond_br_inst->is_gen = true;
} else {
- cond_br_inst = is_err; // for the purposes of the source instruction to create_binary_result_peers
+ // for the purposes of the source instruction to ir_build_binary_result_peers
+ cond_br_inst = irb->current_basic_block->instruction_list.last();
}
- ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, end_block,
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block,
result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, body_block);
@@ -6085,10 +6112,11 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
body_block, else_block, is_comptime);
cond_br_inst->is_gen = true;
} else {
- cond_br_inst = is_non_null; // for the purposes of source instruction for create_binary_result_peers
+ // for the purposes of the source instruction to ir_build_binary_result_peers
+ cond_br_inst = irb->current_basic_block->instruction_list.last();
}
- ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, end_block,
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block,
result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, body_block);
@@ -6168,10 +6196,11 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
body_block, else_block, is_comptime);
cond_br_inst->is_gen = true;
} else {
- cond_br_inst = cond_val; // for the source instruction arg to create_binary_result_peers
+ // for the purposes of the source instruction to ir_build_binary_result_peers
+ cond_br_inst = irb->current_basic_block->instruction_list.last();
}
- ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, end_block,
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block,
result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, body_block);
@@ -6303,8 +6332,8 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
IrInstruction *cond_br_inst = ir_mark_gen(ir_build_cond_br(irb, parent_scope, node, cond,
body_block, else_block, is_comptime));
- ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, end_block, result_loc,
- is_comptime);
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, end_block,
+ result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, body_block);
IrInstruction *elem_ptr = ir_build_elem_ptr(irb, parent_scope, node, array_val_ptr, index_val, false,
@@ -6683,7 +6712,7 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, is_non_null,
then_block, else_block, is_comptime);
- ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, endif_block,
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block,
result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, then_block);
@@ -6765,7 +6794,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
IrInstruction *is_comptime = force_comptime ? ir_build_const_bool(irb, scope, node, true) : ir_build_test_comptime(irb, scope, node, is_err);
IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime);
- ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, endif_block,
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block,
result_loc, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, ok_block);
@@ -7093,6 +7122,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
IrInstruction *switch_prongs_void = ir_build_check_switch_prongs(irb, scope, node, target_value,
check_ranges.items, check_ranges.length, else_prong != nullptr);
+ ir_build_reset_result(irb, scope, node, &peer_parent->base);
+
IrInstruction *br_instruction;
if (cases.length == 0) {
br_instruction = ir_build_br(irb, scope, node, else_block, is_comptime);
@@ -7377,7 +7408,7 @@ static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode
IrBasicBlock *end_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrEnd");
IrInstruction *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_err, err_block, ok_block, is_comptime);
- ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, ok_block, end_block, result_loc,
+ ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, ok_block, end_block, result_loc,
is_comptime);
ir_set_cursor_at_end_and_append_block(irb, err_block);
@@ -8268,6 +8299,7 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *sc
// Create a result location indicating there is none - but if one gets created
// it will be properly distributed.
result_loc = no_result_loc();
+ ir_build_reset_result(irb, scope, node, result_loc);
}
IrInstruction *result = ir_gen_node_raw(irb, node, scope, lval, result_loc);
irb->exec->invalid = irb->exec->invalid || (result == irb->codegen->invalid_instruction);
@@ -8521,10 +8553,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
// non-allocating. Basically coroutines are not supported right now until they are reworked.
args[3] = ir_build_const_usize(irb, scope, node, 1); // new_size
args[4] = ir_build_const_usize(irb, scope, node, 1); // new_align
- ResultLocNone *result_loc_none = allocate<ResultLocNone>(1);
- result_loc_none->base.id = ResultLocIdNone;
ir_build_call_src(irb, scope, node, nullptr, shrink_fn, arg_count, args, false, FnInlineAuto, false, nullptr,
- nullptr, &result_loc_none->base);
+ nullptr, no_result_loc());
IrBasicBlock *resume_block = ir_create_basic_block(irb, scope, "Resume");
ir_build_cond_br(irb, scope, node, resume_awaiter, resume_block, irb->exec->coro_suspend_block, const_bool_false);
@@ -15082,6 +15112,40 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn
return ir_resolve_result(ira, &instruction->base, instruction->result_loc, implicit_elem_type, nullptr);
}
+static void ir_reset_result(ResultLoc *result_loc) {
+ result_loc->written = false;
+ result_loc->resolved_loc = nullptr;
+ result_loc->gen_instruction = nullptr;
+ result_loc->implicit_elem_type = nullptr;
+ // TODO handle result_loc->scope_elide =
+ switch (result_loc->id) {
+ case ResultLocIdInvalid:
+ zig_unreachable();
+ case ResultLocIdPeerParent: {
+ ResultLocPeerParent *peer_parent = reinterpret_cast<ResultLocPeerParent *>(result_loc);
+ peer_parent->skipped = false;
+ peer_parent->done_resuming = false;
+ peer_parent->resolved_type = nullptr;
+ for (size_t i = 0; i < peer_parent->peer_count; i += 1) {
+ ir_reset_result(&peer_parent->peers[i].base);
+ }
+ break;
+ }
+ case ResultLocIdPeer:
+ case ResultLocIdNone:
+ case ResultLocIdVar:
+ case ResultLocIdReturn:
+ case ResultLocIdInstruction:
+ case ResultLocIdBitCast:
+ break;
+ }
+}
+
+static IrInstruction *ir_analyze_instruction_reset_result(IrAnalyze *ira, IrInstructionResetResult *instruction) {
+ ir_reset_result(instruction->result_loc);
+ return ir_const_void(ira, &instruction->base);
+}
+
static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, ZigFn *fn_entry,
ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count,
IrInstruction *async_allocator_inst)
@@ -24594,6 +24658,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
return ir_analyze_instruction_implicit_cast(ira, (IrInstructionImplicitCast *)instruction);
case IrInstructionIdResolveResult:
return ir_analyze_instruction_resolve_result(ira, (IrInstructionResolveResult *)instruction);
+ case IrInstructionIdResetResult:
+ return ir_analyze_instruction_reset_result(ira, (IrInstructionResetResult *)instruction);
case IrInstructionIdResultPtr:
return ir_analyze_instruction_result_ptr(ira, (IrInstructionResultPtr *)instruction);
case IrInstructionIdOpaqueType:
@@ -24818,6 +24884,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdSliceGen:
case IrInstructionIdOptionalWrap:
case IrInstructionIdVectorToArray:
+ case IrInstructionIdResetResult:
return true;
case IrInstructionIdPhi: