| author | |
| committer | |
| log | 34a7e6fdb362cb7be1067b7d1fc110eb2f323c51 |
| tree | 7f424a8a2d04f7b76d9a4d5f4dc65948b33d732d |
| parent | ec33e5a638b816ab0ba1e4dd3f9433dbb71d7e53 |
See #1104 files changed, 29 insertions(+), 20 deletions(-)
src/all_types.hpp-9| ... | ... | @@ -1159,14 +1159,6 @@ struct ErrorTableEntry { |
| 1159 | 1159 | AstNode *decl_node; |
| 1160 | 1160 | }; |
| 1161 | 1161 | |
| 1162 | enum BlockExitPath { | |
| 1163 | BlockExitPathFallthrough, | |
| 1164 | BlockExitPathReturn, | |
| 1165 | BlockExitPathGoto, | |
| 1166 | ||
| 1167 | BlockExitPathCount, | |
| 1168 | }; | |
| 1169 | ||
| 1170 | 1162 | struct BlockContext { |
| 1171 | 1163 | // One of: NodeTypeFnDef, NodeTypeBlock, NodeTypeRoot, NodeTypeDefer, NodeTypeVariableDeclaration |
| 1172 | 1164 | AstNode *node; |
| ... | ... | @@ -1186,7 +1178,6 @@ struct BlockContext { |
| 1186 | 1178 | |
| 1187 | 1179 | LLVMZigDIScope *di_scope; |
| 1188 | 1180 | Buf *c_import_buf; |
| 1189 | bool block_exit_paths[BlockExitPathCount]; | |
| 1190 | 1181 | }; |
| 1191 | 1182 | |
| 1192 | 1183 | enum CIntType { |
src/analyze.cpp-3| ... | ... | @@ -4545,9 +4545,6 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, |
| 4545 | 4545 | normalize_parent_ptrs(node); |
| 4546 | 4546 | } |
| 4547 | 4547 | |
| 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 | 4548 | TypeTableEntry *expected_return_type = get_return_type(context); |
| 4552 | 4549 | |
| 4553 | 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 | 1593 | return phi; |
| 1594 | 1594 | } |
| 1595 | 1595 | |
| 1596 | static 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 | ||
| 1596 | 1605 | static 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 | 1609 | TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type; |
| 1598 | 1610 | if (handle_is_ptr(return_type)) { |
| 1599 | 1611 | assert(g->cur_ret_ptr); |
| ... | ... | @@ -1615,7 +1627,9 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) { |
| 1615 | 1627 | |
| 1616 | 1628 | switch (node->data.return_expr.kind) { |
| 1617 | 1629 | case ReturnKindUnconditional: |
| 1618 | return gen_return(g, node, value); | |
| 1630 | { | |
| 1631 | return gen_return(g, node, value); | |
| 1632 | } | |
| 1619 | 1633 | case ReturnKindError: |
| 1620 | 1634 | { |
| 1621 | 1635 | assert(value_type->id == TypeTableEntryIdErrorUnion); |
| ... | ... | @@ -1820,13 +1834,7 @@ static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *i |
| 1820 | 1834 | return nullptr; |
| 1821 | 1835 | } |
| 1822 | 1836 | |
| 1823 | BlockContext *block_context = block_node->data.block.nested_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 | } | |
| 1837 | gen_defers_for_block(g, block_node->data.block.nested_block, block_node->data.block.child_block); | |
| 1830 | 1838 | |
| 1831 | 1839 | if (implicit_return_type) { |
| 1832 | 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 | 1532 | } |
| 1533 | 1533 | )SOURCE", "before\nafter\ndefer3\ndefer2\ndefer1\n"); |
| 1534 | 1534 | |
| 1535 | ||
| 1536 | add_simple_case("defer with return", R"SOURCE( | |
| 1537 | import "std.zig"; | |
| 1538 | pub 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 | } |
| 1536 | 1549 | |
| 1537 | 1550 |