authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-21 13:16:55-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-21 13:16:55-04:00
log4299cd4446f00ae68edd0c3b5273c83d38a6a253
tree4e10fced65df3ee7f69cd3475724c74ee66932a8
parent4f21dc8a80d7b190d1812a668eaf570d377d95bf
signature Commit is signed but in an unrecognized format.

blocks have result location semantics


2 files changed, 74 insertions(+), 24 deletions(-)

src/all_types.hpp+7-5
......@@ -1996,6 +1996,11 @@ struct ScopeDecls {
19961996 bool any_imports_failed;
19971997};
19981998
1999enum LVal {
2000 LValNone,
2001 LValPtr,
2002};
2003
19992004// This scope comes from a block expression in user code.
20002005// NodeTypeBlock
20012006struct ScopeBlock {
......@@ -2004,12 +2009,14 @@ struct ScopeBlock {
20042009 Buf *name;
20052010 IrBasicBlock *end_block;
20062011 IrInstruction *is_comptime;
2012 ResultLocPeerParent *peer_parent;
20072013 ZigList<IrInstruction *> *incoming_values;
20082014 ZigList<IrBasicBlock *> *incoming_blocks;
20092015
20102016 AstNode *safety_set_node;
20112017 AstNode *fast_math_set_node;
20122018
2019 LVal lval;
20132020 bool safety_off;
20142021 bool fast_math_on;
20152022};
......@@ -2047,11 +2054,6 @@ struct ScopeCImport {
20472054 Buf buf;
20482055};
20492056
2050enum LVal {
2051 LValNone,
2052 LValPtr,
2053};
2054
20552057// This scope is created for a loop such as for or while in order to
20562058// make break and continue statements work.
20572059// NodeTypeForExpr or NodeTypeWhileExpr
src/ir.cpp+67-19
......@@ -3759,7 +3759,17 @@ static ZigVar *ir_create_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *n
37593759 return var;
37603760}
37613761
3762static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode *block_node) {
3762static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) {
3763 ResultLocPeer *result = allocate<ResultLocPeer>(1);
3764 result->base.id = ResultLocIdPeer;
3765 result->base.source_instruction = peer_parent->base.source_instruction;
3766 result->parent = peer_parent;
3767 return result;
3768}
3769
3770static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode *block_node, LVal lval,
3771 ResultLoc *result_loc)
3772{
37633773 assert(block_node->type == NodeTypeBlock);
37643774
37653775 ZigList<IrInstruction *> incoming_values = {0};
......@@ -3777,15 +3787,24 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
37773787
37783788 if (block_node->data.block.statements.length == 0) {
37793789 // {}
3780 return ir_build_const_void(irb, child_scope, block_node);
3790 return ir_lval_wrap(irb, parent_scope, ir_build_const_void(irb, child_scope, block_node), lval, result_loc);
37813791 }
37823792
37833793 if (block_node->data.block.name != nullptr) {
3794 scope_block->lval = lval;
37843795 scope_block->incoming_blocks = &incoming_blocks;
37853796 scope_block->incoming_values = &incoming_values;
37863797 scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd");
37873798 scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node,
37883799 ir_should_inline(irb->exec, parent_scope));
3800
3801 scope_block->peer_parent = allocate<ResultLocPeerParent>(1);
3802 scope_block->peer_parent->base.id = ResultLocIdPeerParent;
3803 scope_block->peer_parent->base.source_instruction = scope_block->is_comptime;
3804 scope_block->peer_parent->end_bb = scope_block->end_block;
3805 scope_block->peer_parent->is_comptime = scope_block->is_comptime;
3806 scope_block->peer_parent->parent = result_loc;
3807 ir_build_reset_result(irb, parent_scope, block_node, &scope_block->peer_parent->base);
37893808 }
37903809
37913810 bool is_continuation_unreachable = false;
......@@ -3821,23 +3840,41 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
38213840 return noreturn_return_value;
38223841 }
38233842
3843 if (scope_block->peer_parent != nullptr && scope_block->peer_parent->peers.length != 0) {
3844 scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block;
3845 }
38243846 ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block);
3825 return ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length,
3826 incoming_blocks.items, incoming_values.items, nullptr);
3847 IrInstruction *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length,
3848 incoming_blocks.items, incoming_values.items, scope_block->peer_parent);
3849 return ir_expr_wrap(irb, parent_scope, phi, result_loc);
38273850 } else {
38283851 incoming_blocks.append(irb->current_basic_block);
3829 incoming_values.append(ir_mark_gen(ir_build_const_void(irb, parent_scope, block_node)));
3852 IrInstruction *else_expr_result = ir_mark_gen(ir_build_const_void(irb, parent_scope, block_node));
3853
3854 if (scope_block->peer_parent != nullptr) {
3855 ResultLocPeer *peer_result = create_peer_result(scope_block->peer_parent);
3856 scope_block->peer_parent->peers.append(peer_result);
3857 ir_build_end_expr(irb, parent_scope, block_node, else_expr_result, &peer_result->base);
3858
3859 if (scope_block->peer_parent->peers.length != 0) {
3860 scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block;
3861 }
3862 }
3863
3864 incoming_values.append(else_expr_result);
38303865 }
38313866
38323867 if (block_node->data.block.name != nullptr) {
38333868 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);
38343869 ir_mark_gen(ir_build_br(irb, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime));
38353870 ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block);
3836 return ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length,
3837 incoming_blocks.items, incoming_values.items, nullptr);
3871 IrInstruction *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length,
3872 incoming_blocks.items, incoming_values.items, scope_block->peer_parent);
3873 return ir_expr_wrap(irb, parent_scope, phi, result_loc);
38383874 } else {
38393875 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);
3840 return ir_mark_gen(ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)));
3876 IrInstruction *void_inst = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node));
3877 return ir_lval_wrap(irb, parent_scope, void_inst, lval, result_loc);
38413878 }
38423879}
38433880
......@@ -3964,14 +4001,6 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod
39644001 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr);
39654002}
39664003
3967static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) {
3968 ResultLocPeer *result = allocate<ResultLocPeer>(1);
3969 result->base.id = ResultLocIdPeer;
3970 result->base.source_instruction = peer_parent->base.source_instruction;
3971 result->parent = peer_parent;
3972 return result;
3973}
3974
39754004static ResultLocPeerParent *ir_build_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst,
39764005 IrBasicBlock *end_block, ResultLoc *parent, IrInstruction *is_comptime)
39774006{
......@@ -7216,7 +7245,11 @@ static IrInstruction *ir_gen_return_from_block(IrBuilder *irb, Scope *break_scop
72167245
72177246 IrInstruction *result_value;
72187247 if (node->data.break_expr.expr) {
7219 result_value = ir_gen_node(irb, node->data.break_expr.expr, break_scope);
7248 ResultLocPeer *peer_result = create_peer_result(block_scope->peer_parent);
7249 block_scope->peer_parent->peers.append(peer_result);
7250
7251 result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope, block_scope->lval,
7252 &peer_result->base);
72207253 if (result_value == irb->codegen->invalid_instruction)
72217254 return irb->codegen->invalid_instruction;
72227255 } else {
......@@ -8193,7 +8226,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
81938226 case NodeTypeTestDecl:
81948227 zig_unreachable();
81958228 case NodeTypeBlock:
8196 return ir_lval_wrap(irb, scope, ir_gen_block(irb, scope, node), lval, result_loc);
8229 return ir_gen_block(irb, scope, node, lval, result_loc);
81978230 case NodeTypeGroupedExpr:
81988231 return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval, result_loc);
81998232 case NodeTypeBinOpExpr:
......@@ -15066,6 +15099,21 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
1506615099 ResultLocPeer *result_peer = reinterpret_cast<ResultLocPeer *>(result_loc);
1506715100 ResultLocPeerParent *peer_parent = result_peer->parent;
1506815101
15102 if (peer_parent->peers.length == 1) {
15103 IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent,
15104 value_type, value, false, non_null_comptime);
15105 result_peer->suspend_pos.basic_block_index = SIZE_MAX;
15106 result_peer->suspend_pos.instruction_index = SIZE_MAX;
15107 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
15108 parent_result_loc->value.type->id == ZigTypeIdUnreachable)
15109 {
15110 return parent_result_loc;
15111 }
15112 result_loc->written = true;
15113 result_loc->resolved_loc = parent_result_loc;
15114 return result_loc->resolved_loc;
15115 }
15116
1506915117 bool is_comptime;
1507015118 if (!ir_resolve_comptime(ira, peer_parent->is_comptime->child, &is_comptime))
1507115119 return ira->codegen->invalid_instruction;
......@@ -16670,7 +16718,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
1667016718
1667116719 ResultLocPeerParent *peer_parent = phi_instruction->peer_parent;
1667216720 if (peer_parent != nullptr && !peer_parent->skipped && !peer_parent->done_resuming &&
16673 peer_parent->peers.length != 0)
16721 peer_parent->peers.length >= 2)
1667416722 {
1667516723 if (peer_parent->resolved_type == nullptr) {
1667616724 IrInstruction **instructions = allocate<IrInstruction *>(peer_parent->peers.length);