authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-07 15:22:21-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-07 15:22:21-04:00
logec8d8a9774c01945dbd2c9ddf4e0f5d77e7ebbb9
tree930ef60700cefa7c8c9da1273c5a1a85968debe5
parent0e8b65c537c897786803e452bd054948b4b57bfe
signature Commit is signed but in an unrecognized format.

hook up while on error unions with result locations

```zig export fn entry() void { var c: anyerror!i32 = 1234; var x = while (c) |y| break foo() else |e| bar(); } ``` ```llvm define void @entry() #2 !dbg !39 { Entry: %c = alloca { i16, i32 }, align 4 %x = alloca %Foo, align 4 %0 = bitcast { i16, i32 }* %c to i8*, !dbg !56 call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %0, i8* align 4 bitcast ({ i16, i32 }* @0 to i8*), i64 8, i1 false), !dbg !56 call void @llvm.dbg.declare(metadata { i16, i32 }* %c, metadata !43, metadata !DIExpression()), !dbg !56 br label %WhileCond, !dbg !57 WhileCond: ; preds = %Entry %1 = getelementptr inbounds { i16, i32 }, { i16, i32 }* %c, i32 0, i32 0, !dbg !58 %2 = load i16, i16* %1, align 2, !dbg !58 %3 = icmp ne i16 %2, 0, !dbg !58 br i1 %3, label %WhileElse, label %WhileBody, !dbg !58 WhileBody: ; preds = %WhileCond %4 = getelementptr inbounds { i16, i32 }, { i16, i32 }* %c, i32 0, i32 1, !dbg !57 call void @llvm.dbg.declare(metadata i32* %4, metadata !50, metadata !DIExpression()), !dbg !57 call fastcc void @foo(%Foo* sret %x), !dbg !59 br label %WhileEnd, !dbg !60 WhileElse: ; preds = %WhileCond %5 = getelementptr inbounds { i16, i32 }, { i16, i32 }* %c, i32 0, i32 0, !dbg !61 call void @llvm.dbg.declare(metadata i16* %5, metadata !51, metadata !DIExpression()), !dbg !61 call fastcc void @bar(%Foo* sret %x), !dbg !61 br label %WhileEnd, !dbg !57 WhileEnd: ; preds = %WhileElse, %WhileBody call void @llvm.dbg.declare(metadata %Foo* %x, metadata !52, metadata !DIExpression()), !dbg !62 ret void, !dbg !63 } ```

2 files changed, 51 insertions(+), 54 deletions(-)

src/all_types.hpp+7-5
...@@ -2041,18 +2041,25 @@ struct ScopeCImport {...@@ -2041,18 +2041,25 @@ struct ScopeCImport {
2041 Buf buf;2041 Buf buf;
2042};2042};
20432043
2044enum LVal {
2045 LValNone,
2046 LValPtr,
2047};
2048
2044// This scope is created for a loop such as for or while in order to2049// This scope is created for a loop such as for or while in order to
2045// make break and continue statements work.2050// make break and continue statements work.
2046// NodeTypeForExpr or NodeTypeWhileExpr2051// NodeTypeForExpr or NodeTypeWhileExpr
2047struct ScopeLoop {2052struct ScopeLoop {
2048 Scope base;2053 Scope base;
20492054
2055 LVal lval;
2050 Buf *name;2056 Buf *name;
2051 IrBasicBlock *break_block;2057 IrBasicBlock *break_block;
2052 IrBasicBlock *continue_block;2058 IrBasicBlock *continue_block;
2053 IrInstruction *is_comptime;2059 IrInstruction *is_comptime;
2054 ZigList<IrInstruction *> *incoming_values;2060 ZigList<IrInstruction *> *incoming_values;
2055 ZigList<IrBasicBlock *> *incoming_blocks;2061 ZigList<IrBasicBlock *> *incoming_blocks;
2062 ResultLoc *result_loc;
2056};2063};
20572064
2058// This scope blocks certain things from working such as comptime continue2065// This scope blocks certain things from working such as comptime continue
...@@ -2143,11 +2150,6 @@ struct IrBasicBlock {...@@ -2143,11 +2150,6 @@ struct IrBasicBlock {
2143 IrInstruction *must_be_comptime_source_instr;2150 IrInstruction *must_be_comptime_source_instr;
2144};2151};
21452152
2146enum LVal {
2147 LValNone,
2148 LValPtr,
2149};
2150
2151// These instructions are in transition to having "pass 1" instructions2153// These instructions are in transition to having "pass 1" instructions
2152// and "pass 2" instructions. The pass 1 instructions are suffixed with Src2154// and "pass 2" instructions. The pass 1 instructions are suffixed with Src
2153// and pass 2 are suffixed with Gen.2155// and pass 2 are suffixed with Gen.
src/ir.cpp+44-49
...@@ -5290,6 +5290,26 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node...@@ -5290,6 +5290,26 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
5290 return ir_lval_wrap(irb, scope, fn_call, lval, result_loc);5290 return ir_lval_wrap(irb, scope, fn_call, lval, result_loc);
5291}5291}
52925292
5293static ResultLocPeerParent *create_binary_result_peers(IrInstruction *cond_br_inst,
5294 IrBasicBlock *else_block, IrBasicBlock *endif_block, ResultLoc *parent)
5295{
5296 ResultLocPeerParent *peer_parent = allocate<ResultLocPeerParent>(1);
5297 peer_parent->base.id = ResultLocIdPeerParent;
5298 peer_parent->base.source_instruction = cond_br_inst;
5299 peer_parent->parent = parent;
5300 peer_parent->peer_count = 2;
5301 peer_parent->peers = allocate<ResultLocPeer>(2);
5302 peer_parent->peers[0].base.id = ResultLocIdPeer;
5303 peer_parent->peers[0].base.source_instruction = cond_br_inst;
5304 peer_parent->peers[0].parent = peer_parent;
5305 peer_parent->peers[0].next_bb = else_block;
5306 peer_parent->peers[1].base.id = ResultLocIdPeer;
5307 peer_parent->peers[1].base.source_instruction = cond_br_inst;
5308 peer_parent->peers[1].parent = peer_parent;
5309 peer_parent->peers[1].next_bb = endif_block;
5310 return peer_parent;
5311}
5312
5293static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,5313static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
5294 ResultLoc *result_loc)5314 ResultLoc *result_loc)
5295{5315{
...@@ -5316,20 +5336,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -5316,20 +5336,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
5316 IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, condition->source_node, condition,5336 IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, condition->source_node, condition,
5317 then_block, else_block, is_comptime);5337 then_block, else_block, is_comptime);
53185338
5319 ResultLocPeerParent *peer_parent = allocate<ResultLocPeerParent>(1);5339 ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, endif_block, result_loc);
5320 peer_parent->base.id = ResultLocIdPeerParent;
5321 peer_parent->base.source_instruction = cond_br_inst;
5322 peer_parent->parent = result_loc;
5323 peer_parent->peer_count = 2;
5324 peer_parent->peers = allocate<ResultLocPeer>(2);
5325 peer_parent->peers[0].base.id = ResultLocIdPeer;
5326 peer_parent->peers[0].base.source_instruction = cond_br_inst;
5327 peer_parent->peers[0].parent = peer_parent;
5328 peer_parent->peers[0].next_bb = else_block;
5329 peer_parent->peers[1].base.id = ResultLocIdPeer;
5330 peer_parent->peers[1].base.source_instruction = cond_br_inst;
5331 peer_parent->peers[1].parent = peer_parent;
5332 peer_parent->peers[1].next_bb = endif_block;
53335340
5334 ir_set_cursor_at_end_and_append_block(irb, then_block);5341 ir_set_cursor_at_end_and_append_block(irb, then_block);
53355342
...@@ -5676,7 +5683,9 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5676,7 +5683,9 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
5676 return ir_build_var_decl_src(irb, scope, node, var, align_value, alloca);5683 return ir_build_var_decl_src(irb, scope, node, var, align_value, alloca);
5677}5684}
56785685
5679static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) {5686static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
5687 ResultLoc *result_loc)
5688{
5680 assert(node->type == NodeTypeWhileExpr);5689 assert(node->type == NodeTypeWhileExpr);
56815690
5682 AstNode *continue_expr_node = node->data.while_expr.continue_expr;5691 AstNode *continue_expr_node = node->data.while_expr.continue_expr;
...@@ -5719,11 +5728,16 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5719,11 +5728,16 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5719 IrInstruction *is_err = ir_build_test_err(irb, scope, node->data.while_expr.condition, err_val);5728 IrInstruction *is_err = ir_build_test_err(irb, scope, node->data.while_expr.condition, err_val);
5720 IrBasicBlock *after_cond_block = irb->current_basic_block;5729 IrBasicBlock *after_cond_block = irb->current_basic_block;
5721 IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));5730 IrInstruction *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node));
5731 IrInstruction *cond_br_inst;
5722 if (!instr_is_unreachable(is_err)) {5732 if (!instr_is_unreachable(is_err)) {
5723 ir_mark_gen(ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_err,5733 cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_err,
5724 else_block, body_block, is_comptime));5734 else_block, body_block, is_comptime);
5735 } else {
5736 cond_br_inst = is_err; // for the purposes of the source instruction to create_binary_result_peers
5725 }5737 }
57265738
5739 ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, end_block, result_loc);
5740
5727 ir_set_cursor_at_end_and_append_block(irb, body_block);5741 ir_set_cursor_at_end_and_append_block(irb, body_block);
5728 if (var_symbol) {5742 if (var_symbol) {
5729 IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, payload_scope, symbol_node,5743 IrInstruction *payload_ptr = ir_build_unwrap_err_payload(irb, payload_scope, symbol_node,
...@@ -5742,7 +5756,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5742,7 +5756,12 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5742 loop_scope->is_comptime = is_comptime;5756 loop_scope->is_comptime = is_comptime;
5743 loop_scope->incoming_blocks = &incoming_blocks;5757 loop_scope->incoming_blocks = &incoming_blocks;
5744 loop_scope->incoming_values = &incoming_values;5758 loop_scope->incoming_values = &incoming_values;
5759 loop_scope->lval = lval;
5760 loop_scope->result_loc = &peer_parent->peers[0].base;
57455761
5762 // Note the body block of the loop is not the place that lval and result_loc are used -
5763 // it's actually in break statements, handled similarly to return statements.
5764 // That is why we set those values in loop_scope above and not in this ir_gen_node call.
5746 IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base);5765 IrInstruction *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base);
5747 if (body_result == irb->codegen->invalid_instruction)5766 if (body_result == irb->codegen->invalid_instruction)
5748 return body_result;5767 return body_result;
...@@ -5774,7 +5793,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5774,7 +5793,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5774 IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);5793 IrInstruction *err_ptr = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);
5775 ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, err_ptr);5794 ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, err_ptr);
57765795
5777 IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope);5796 IrInstruction *else_result = ir_gen_node_extra(irb, else_node, err_scope, lval, &peer_parent->peers[1].base);
5778 if (else_result == irb->codegen->invalid_instruction)5797 if (else_result == irb->codegen->invalid_instruction)
5779 return else_result;5798 return else_result;
5780 if (!instr_is_unreachable(else_result))5799 if (!instr_is_unreachable(else_result))
...@@ -5789,7 +5808,8 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5789,7 +5808,8 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5789 incoming_values.append(void_else_result);5808 incoming_values.append(void_else_result);
5790 }5809 }
57915810
5792 return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);5811 IrInstruction *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);
5812 return ir_expr_wrap(irb, scope, phi, result_loc);
5793 } else if (var_symbol != nullptr) {5813 } else if (var_symbol != nullptr) {
5794 ir_set_cursor_at_end_and_append_block(irb, cond_block);5814 ir_set_cursor_at_end_and_append_block(irb, cond_block);
5795 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);5815 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
...@@ -6370,20 +6390,7 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN...@@ -6370,20 +6390,7 @@ static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstN
6370 IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, is_non_null,6390 IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, is_non_null,
6371 then_block, else_block, is_comptime);6391 then_block, else_block, is_comptime);
63726392
6373 ResultLocPeerParent *peer_parent = allocate<ResultLocPeerParent>(1);6393 ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, endif_block, result_loc);
6374 peer_parent->base.id = ResultLocIdPeerParent;
6375 peer_parent->base.source_instruction = cond_br_inst;
6376 peer_parent->parent = result_loc;
6377 peer_parent->peer_count = 2;
6378 peer_parent->peers = allocate<ResultLocPeer>(2);
6379 peer_parent->peers[0].base.id = ResultLocIdPeer;
6380 peer_parent->peers[0].base.source_instruction = cond_br_inst;
6381 peer_parent->peers[0].parent = peer_parent;
6382 peer_parent->peers[0].next_bb = else_block;
6383 peer_parent->peers[1].base.id = ResultLocIdPeer;
6384 peer_parent->peers[1].base.source_instruction = cond_br_inst;
6385 peer_parent->peers[1].parent = peer_parent;
6386 peer_parent->peers[1].next_bb = endif_block;
63876394
6388 ir_set_cursor_at_end_and_append_block(irb, then_block);6395 ir_set_cursor_at_end_and_append_block(irb, then_block);
63896396
...@@ -6463,20 +6470,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -6463,20 +6470,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
6463 IrInstruction *is_comptime = force_comptime ? ir_build_const_bool(irb, scope, node, true) : ir_build_test_comptime(irb, scope, node, is_err);6470 IrInstruction *is_comptime = force_comptime ? ir_build_const_bool(irb, scope, node, true) : ir_build_test_comptime(irb, scope, node, is_err);
6464 IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime);6471 IrInstruction *cond_br_inst = ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime);
64656472
6466 ResultLocPeerParent *peer_parent = allocate<ResultLocPeerParent>(1);6473 ResultLocPeerParent *peer_parent = create_binary_result_peers(cond_br_inst, else_block, endif_block, result_loc);
6467 peer_parent->base.id = ResultLocIdPeerParent;
6468 peer_parent->base.source_instruction = cond_br_inst;
6469 peer_parent->parent = result_loc;
6470 peer_parent->peer_count = 2;
6471 peer_parent->peers = allocate<ResultLocPeer>(2);
6472 peer_parent->peers[0].base.id = ResultLocIdPeer;
6473 peer_parent->peers[0].base.source_instruction = cond_br_inst;
6474 peer_parent->peers[0].parent = peer_parent;
6475 peer_parent->peers[0].next_bb = else_block;
6476 peer_parent->peers[1].base.id = ResultLocIdPeer;
6477 peer_parent->peers[1].base.source_instruction = cond_br_inst;
6478 peer_parent->peers[1].parent = peer_parent;
6479 peer_parent->peers[1].next_bb = endif_block;
64806474
6481 ir_set_cursor_at_end_and_append_block(irb, ok_block);6475 ir_set_cursor_at_end_and_append_block(irb, ok_block);
64826476
...@@ -6926,7 +6920,8 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode *...@@ -6926,7 +6920,8 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *break_scope, AstNode *
69266920
6927 IrInstruction *result_value;6921 IrInstruction *result_value;
6928 if (node->data.break_expr.expr) {6922 if (node->data.break_expr.expr) {
6929 result_value = ir_gen_node(irb, node->data.break_expr.expr, break_scope);6923 result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope,
6924 loop_scope->lval, loop_scope->result_loc);
6930 if (result_value == irb->codegen->invalid_instruction)6925 if (result_value == irb->codegen->invalid_instruction)
6931 return irb->codegen->invalid_instruction;6926 return irb->codegen->invalid_instruction;
6932 } else {6927 } else {
...@@ -7845,7 +7840,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -7845,7 +7840,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
7845 case NodeTypeVariableDeclaration:7840 case NodeTypeVariableDeclaration:
7846 return ir_lval_wrap(irb, scope, ir_gen_var_decl(irb, scope, node), lval, result_loc);7841 return ir_lval_wrap(irb, scope, ir_gen_var_decl(irb, scope, node), lval, result_loc);
7847 case NodeTypeWhileExpr:7842 case NodeTypeWhileExpr:
7848 return ir_lval_wrap(irb, scope, ir_gen_while_expr(irb, scope, node), lval, result_loc);7843 return ir_gen_while_expr(irb, scope, node, lval, result_loc);
7849 case NodeTypeForExpr:7844 case NodeTypeForExpr:
7850 return ir_lval_wrap(irb, scope, ir_gen_for_expr(irb, scope, node), lval, result_loc);7845 return ir_lval_wrap(irb, scope, ir_gen_for_expr(irb, scope, node), lval, result_loc);
7851 case NodeTypeArrayAccessExpr:7846 case NodeTypeArrayAccessExpr: