authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-06 01:13:47-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-06 01:18:39-07:00
log34a7e6fdb362cb7be1067b7d1fc110eb2f323c51
tree7f424a8a2d04f7b76d9a4d5f4dc65948b33d732d
parentec33e5a638b816ab0ba1e4dd3f9433dbb71d7e53

codegen: return respects unconditional defer

See #110

4 files changed, 29 insertions(+), 20 deletions(-)

src/all_types.hpp-9
...@@ -1159,14 +1159,6 @@ struct ErrorTableEntry {...@@ -1159,14 +1159,6 @@ struct ErrorTableEntry {
1159 AstNode *decl_node;1159 AstNode *decl_node;
1160};1160};
11611161
1162enum BlockExitPath {
1163 BlockExitPathFallthrough,
1164 BlockExitPathReturn,
1165 BlockExitPathGoto,
1166
1167 BlockExitPathCount,
1168};
1169
1170struct BlockContext {1162struct BlockContext {
1171 // One of: NodeTypeFnDef, NodeTypeBlock, NodeTypeRoot, NodeTypeDefer, NodeTypeVariableDeclaration1163 // One of: NodeTypeFnDef, NodeTypeBlock, NodeTypeRoot, NodeTypeDefer, NodeTypeVariableDeclaration
1172 AstNode *node;1164 AstNode *node;
...@@ -1186,7 +1178,6 @@ struct BlockContext {...@@ -1186,7 +1178,6 @@ struct BlockContext {
11861178
1187 LLVMZigDIScope *di_scope;1179 LLVMZigDIScope *di_scope;
1188 Buf *c_import_buf;1180 Buf *c_import_buf;
1189 bool block_exit_paths[BlockExitPathCount];
1190};1181};
11911182
1192enum CIntType {1183enum CIntType {
src/analyze.cpp-3
...@@ -4545,9 +4545,6 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import,...@@ -4545,9 +4545,6 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import,
4545 normalize_parent_ptrs(node);4545 normalize_parent_ptrs(node);
4546 }4546 }
45474547
4548 // TODO follow the blocks to their parents, loop over all of them, set them all to true
4549 context->block_exit_paths[BlockExitPathReturn] = true;
4550
4551 TypeTableEntry *expected_return_type = get_return_type(context);4548 TypeTableEntry *expected_return_type = get_return_type(context);
45524549
4553 switch (node->data.return_expr.kind) {4550 switch (node->data.return_expr.kind) {
src/codegen.cpp+16-8
...@@ -1593,7 +1593,19 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {...@@ -1593,7 +1593,19 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {
1593 return phi;1593 return phi;
1594}1594}
15951595
1596static void gen_defers_for_block(CodeGen *g, BlockContext *inner_block, BlockContext *outer_block) {
1597 while (inner_block != outer_block) {
1598 if (inner_block->node->type == NodeTypeDefer) {
1599 gen_expr(g, inner_block->node->data.defer.expr);
1600 }
1601 inner_block = inner_block->parent;
1602 }
1603}
1604
1596static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef value) {1605static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef value) {
1606 gen_defers_for_block(g, source_node->block_context,
1607 source_node->block_context->fn_entry->fn_def_node->block_context);
1608
1597 TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;1609 TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
1598 if (handle_is_ptr(return_type)) {1610 if (handle_is_ptr(return_type)) {
1599 assert(g->cur_ret_ptr);1611 assert(g->cur_ret_ptr);
...@@ -1615,7 +1627,9 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {...@@ -1615,7 +1627,9 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
16151627
1616 switch (node->data.return_expr.kind) {1628 switch (node->data.return_expr.kind) {
1617 case ReturnKindUnconditional:1629 case ReturnKindUnconditional:
1618 return gen_return(g, node, value);1630 {
1631 return gen_return(g, node, value);
1632 }
1619 case ReturnKindError:1633 case ReturnKindError:
1620 {1634 {
1621 assert(value_type->id == TypeTableEntryIdErrorUnion);1635 assert(value_type->id == TypeTableEntryIdErrorUnion);
...@@ -1820,13 +1834,7 @@ static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *i...@@ -1820,13 +1834,7 @@ static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *i
1820 return nullptr;1834 return nullptr;
1821 }1835 }
18221836
1823 BlockContext *block_context = block_node->data.block.nested_block;1837 gen_defers_for_block(g, block_node->data.block.nested_block, block_node->data.block.child_block);
1824 while (block_context != block_node->data.block.child_block) {
1825 if (block_context->node->type == NodeTypeDefer) {
1826 gen_expr(g, block_context->node->data.defer.expr);
1827 }
1828 block_context = block_context->parent;
1829 }
18301838
1831 if (implicit_return_type) {1839 if (implicit_return_type) {
1832 return gen_return(g, block_node, return_value);1840 return gen_return(g, block_node, return_value);
test/run_tests.cpp+13
...@@ -1532,6 +1532,19 @@ pub fn main(args: [][]u8) -> %void {...@@ -1532,6 +1532,19 @@ pub fn main(args: [][]u8) -> %void {
1532}1532}
1533 )SOURCE", "before\nafter\ndefer3\ndefer2\ndefer1\n");1533 )SOURCE", "before\nafter\ndefer3\ndefer2\ndefer1\n");
15341534
1535
1536 add_simple_case("defer with return", R"SOURCE(
1537import "std.zig";
1538pub fn main(args: [][]u8) -> %void {
1539 %%stdout.printf("before\n");
1540 defer %%stdout.printf("defer1\n");
1541 defer %%stdout.printf("defer2\n");
1542 if (args.len == 1) return;
1543 defer %%stdout.printf("defer3\n");
1544 %%stdout.printf("after\n");
1545}
1546 )SOURCE", "before\ndefer2\ndefer1\n");
1547
1535}1548}
15361549
15371550