aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2016-02-06 01:13:47 -0700
committerAndrew Kelley <superjoe30@gmail.com>2016-02-06 01:18:39 -0700
commit34a7e6fdb362cb7be1067b7d1fc110eb2f323c51 (patch)
tree7f424a8a2d04f7b76d9a4d5f4dc65948b33d732d /src
parentec33e5a638b816ab0ba1e4dd3f9433dbb71d7e53 (diff)
downloadzig-34a7e6fdb362cb7be1067b7d1fc110eb2f323c51.tar.gz
zig-34a7e6fdb362cb7be1067b7d1fc110eb2f323c51.zip
codegen: return respects unconditional defer
See #110
Diffstat (limited to 'src')
-rw-r--r--src/all_types.hpp9
-rw-r--r--src/analyze.cpp3
-rw-r--r--src/codegen.cpp24
3 files changed, 16 insertions, 20 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp
index d627b36c37..9b5fc79575 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1159,14 +1159,6 @@ struct ErrorTableEntry {
AstNode *decl_node;
};
-enum BlockExitPath {
- BlockExitPathFallthrough,
- BlockExitPathReturn,
- BlockExitPathGoto,
-
- BlockExitPathCount,
-};
-
struct BlockContext {
// One of: NodeTypeFnDef, NodeTypeBlock, NodeTypeRoot, NodeTypeDefer, NodeTypeVariableDeclaration
AstNode *node;
@@ -1186,7 +1178,6 @@ struct BlockContext {
LLVMZigDIScope *di_scope;
Buf *c_import_buf;
- bool block_exit_paths[BlockExitPathCount];
};
enum CIntType {
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 1bf0ca06ec..03e5ad1899 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -4545,9 +4545,6 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import,
normalize_parent_ptrs(node);
}
- // TODO follow the blocks to their parents, loop over all of them, set them all to true
- context->block_exit_paths[BlockExitPathReturn] = true;
-
TypeTableEntry *expected_return_type = get_return_type(context);
switch (node->data.return_expr.kind) {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 2be63327fb..4cab9fa13d 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -1593,7 +1593,19 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {
return phi;
}
+static void gen_defers_for_block(CodeGen *g, BlockContext *inner_block, BlockContext *outer_block) {
+ while (inner_block != outer_block) {
+ if (inner_block->node->type == NodeTypeDefer) {
+ gen_expr(g, inner_block->node->data.defer.expr);
+ }
+ inner_block = inner_block->parent;
+ }
+}
+
static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef value) {
+ gen_defers_for_block(g, source_node->block_context,
+ source_node->block_context->fn_entry->fn_def_node->block_context);
+
TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
if (handle_is_ptr(return_type)) {
assert(g->cur_ret_ptr);
@@ -1615,7 +1627,9 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
switch (node->data.return_expr.kind) {
case ReturnKindUnconditional:
- return gen_return(g, node, value);
+ {
+ return gen_return(g, node, value);
+ }
case ReturnKindError:
{
assert(value_type->id == TypeTableEntryIdErrorUnion);
@@ -1820,13 +1834,7 @@ static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *i
return nullptr;
}
- BlockContext *block_context = block_node->data.block.nested_block;
- while (block_context != block_node->data.block.child_block) {
- if (block_context->node->type == NodeTypeDefer) {
- gen_expr(g, block_context->node->data.defer.expr);
- }
- block_context = block_context->parent;
- }
+ gen_defers_for_block(g, block_node->data.block.nested_block, block_node->data.block.child_block);
if (implicit_return_type) {
return gen_return(g, block_node, return_value);