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 {...@@ -1996,6 +1996,11 @@ struct ScopeDecls {
1996 bool any_imports_failed;1996 bool any_imports_failed;
1997};1997};
19981998
1999enum LVal {
2000 LValNone,
2001 LValPtr,
2002};
2003
1999// This scope comes from a block expression in user code.2004// This scope comes from a block expression in user code.
2000// NodeTypeBlock2005// NodeTypeBlock
2001struct ScopeBlock {2006struct ScopeBlock {
...@@ -2004,12 +2009,14 @@ struct ScopeBlock {...@@ -2004,12 +2009,14 @@ struct ScopeBlock {
2004 Buf *name;2009 Buf *name;
2005 IrBasicBlock *end_block;2010 IrBasicBlock *end_block;
2006 IrInstruction *is_comptime;2011 IrInstruction *is_comptime;
2012 ResultLocPeerParent *peer_parent;
2007 ZigList<IrInstruction *> *incoming_values;2013 ZigList<IrInstruction *> *incoming_values;
2008 ZigList<IrBasicBlock *> *incoming_blocks;2014 ZigList<IrBasicBlock *> *incoming_blocks;
20092015
2010 AstNode *safety_set_node;2016 AstNode *safety_set_node;
2011 AstNode *fast_math_set_node;2017 AstNode *fast_math_set_node;
20122018
2019 LVal lval;
2013 bool safety_off;2020 bool safety_off;
2014 bool fast_math_on;2021 bool fast_math_on;
2015};2022};
...@@ -2047,11 +2054,6 @@ struct ScopeCImport {...@@ -2047,11 +2054,6 @@ struct ScopeCImport {
2047 Buf buf;2054 Buf buf;
2048};2055};
20492056
2050enum LVal {
2051 LValNone,
2052 LValPtr,
2053};
2054
2055// This scope is created for a loop such as for or while in order to2057// This scope is created for a loop such as for or while in order to
2056// make break and continue statements work.2058// make break and continue statements work.
2057// NodeTypeForExpr or NodeTypeWhileExpr2059// 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...@@ -3759,7 +3759,17 @@ static ZigVar *ir_create_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *n
3759 return var;3759 return var;
3760}3760}
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{
3763 assert(block_node->type == NodeTypeBlock);3773 assert(block_node->type == NodeTypeBlock);
37643774
3765 ZigList<IrInstruction *> incoming_values = {0};3775 ZigList<IrInstruction *> incoming_values = {0};
...@@ -3777,15 +3787,24 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3777,15 +3787,24 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
37773787
3778 if (block_node->data.block.statements.length == 0) {3788 if (block_node->data.block.statements.length == 0) {
3779 // {}3789 // {}
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);
3781 }3791 }
37823792
3783 if (block_node->data.block.name != nullptr) {3793 if (block_node->data.block.name != nullptr) {
3794 scope_block->lval = lval;
3784 scope_block->incoming_blocks = &incoming_blocks;3795 scope_block->incoming_blocks = &incoming_blocks;
3785 scope_block->incoming_values = &incoming_values;3796 scope_block->incoming_values = &incoming_values;
3786 scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd");3797 scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd");
3787 scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node,3798 scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node,
3788 ir_should_inline(irb->exec, parent_scope));3799 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);
3789 }3808 }
37903809
3791 bool is_continuation_unreachable = false;3810 bool is_continuation_unreachable = false;
...@@ -3821,23 +3840,41 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3821,23 +3840,41 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
3821 return noreturn_return_value;3840 return noreturn_return_value;
3822 }3841 }
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 }
3824 ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block);3846 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,3847 IrInstruction *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length,
3826 incoming_blocks.items, incoming_values.items, nullptr);3848 incoming_blocks.items, incoming_values.items, scope_block->peer_parent);
3849 return ir_expr_wrap(irb, parent_scope, phi, result_loc);
3827 } else {3850 } else {
3828 incoming_blocks.append(irb->current_basic_block);3851 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);
3830 }3865 }
38313866
3832 if (block_node->data.block.name != nullptr) {3867 if (block_node->data.block.name != nullptr) {
3833 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);3868 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);
3834 ir_mark_gen(ir_build_br(irb, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime));3869 ir_mark_gen(ir_build_br(irb, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime));
3835 ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block);3870 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,3871 IrInstruction *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length,
3837 incoming_blocks.items, incoming_values.items, nullptr);3872 incoming_blocks.items, incoming_values.items, scope_block->peer_parent);
3873 return ir_expr_wrap(irb, parent_scope, phi, result_loc);
3838 } else {3874 } else {
3839 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);3875 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);
3841 }3878 }
3842}3879}
38433880
...@@ -3964,14 +4001,6 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -3964,14 +4001,6 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod
3964 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr);4001 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr);
3965}4002}
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
3975static ResultLocPeerParent *ir_build_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst,4004static ResultLocPeerParent *ir_build_result_peers(IrBuilder *irb, IrInstruction *cond_br_inst,
3976 IrBasicBlock *end_block, ResultLoc *parent, IrInstruction *is_comptime)4005 IrBasicBlock *end_block, ResultLoc *parent, IrInstruction *is_comptime)
3977{4006{
...@@ -7216,7 +7245,11 @@ static IrInstruction *ir_gen_return_from_block(IrBuilder *irb, Scope *break_scop...@@ -7216,7 +7245,11 @@ static IrInstruction *ir_gen_return_from_block(IrBuilder *irb, Scope *break_scop
72167245
7217 IrInstruction *result_value;7246 IrInstruction *result_value;
7218 if (node->data.break_expr.expr) {7247 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);
7220 if (result_value == irb->codegen->invalid_instruction)7253 if (result_value == irb->codegen->invalid_instruction)
7221 return irb->codegen->invalid_instruction;7254 return irb->codegen->invalid_instruction;
7222 } else {7255 } else {
...@@ -8193,7 +8226,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -8193,7 +8226,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
8193 case NodeTypeTestDecl:8226 case NodeTypeTestDecl:
8194 zig_unreachable();8227 zig_unreachable();
8195 case NodeTypeBlock:8228 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);
8197 case NodeTypeGroupedExpr:8230 case NodeTypeGroupedExpr:
8198 return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval, result_loc);8231 return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval, result_loc);
8199 case NodeTypeBinOpExpr:8232 case NodeTypeBinOpExpr:
...@@ -15066,6 +15099,21 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe...@@ -15066,6 +15099,21 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
15066 ResultLocPeer *result_peer = reinterpret_cast<ResultLocPeer *>(result_loc);15099 ResultLocPeer *result_peer = reinterpret_cast<ResultLocPeer *>(result_loc);
15067 ResultLocPeerParent *peer_parent = result_peer->parent;15100 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
15069 bool is_comptime;15117 bool is_comptime;
15070 if (!ir_resolve_comptime(ira, peer_parent->is_comptime->child, &is_comptime))15118 if (!ir_resolve_comptime(ira, peer_parent->is_comptime->child, &is_comptime))
15071 return ira->codegen->invalid_instruction;15119 return ira->codegen->invalid_instruction;
...@@ -16670,7 +16718,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh...@@ -16670,7 +16718,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
1667016718
16671 ResultLocPeerParent *peer_parent = phi_instruction->peer_parent;16719 ResultLocPeerParent *peer_parent = phi_instruction->peer_parent;
16672 if (peer_parent != nullptr && !peer_parent->skipped && !peer_parent->done_resuming &&16720 if (peer_parent != nullptr && !peer_parent->skipped && !peer_parent->done_resuming &&
16673 peer_parent->peers.length != 0)16721 peer_parent->peers.length >= 2)
16674 {16722 {
16675 if (peer_parent->resolved_type == nullptr) {16723 if (peer_parent->resolved_type == nullptr) {
16676 IrInstruction **instructions = allocate<IrInstruction *>(peer_parent->peers.length);16724 IrInstruction **instructions = allocate<IrInstruction *>(peer_parent->peers.length);