parent
ec33e5a638
commit
34a7e6fdb3
|
@ -1159,14 +1159,6 @@ struct ErrorTableEntry {
|
||||||
AstNode *decl_node;
|
AstNode *decl_node;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BlockExitPath {
|
|
||||||
BlockExitPathFallthrough,
|
|
||||||
BlockExitPathReturn,
|
|
||||||
BlockExitPathGoto,
|
|
||||||
|
|
||||||
BlockExitPathCount,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BlockContext {
|
struct BlockContext {
|
||||||
// One of: NodeTypeFnDef, NodeTypeBlock, NodeTypeRoot, NodeTypeDefer, NodeTypeVariableDeclaration
|
// One of: NodeTypeFnDef, NodeTypeBlock, NodeTypeRoot, NodeTypeDefer, NodeTypeVariableDeclaration
|
||||||
AstNode *node;
|
AstNode *node;
|
||||||
|
@ -1186,7 +1178,6 @@ struct BlockContext {
|
||||||
|
|
||||||
LLVMZigDIScope *di_scope;
|
LLVMZigDIScope *di_scope;
|
||||||
Buf *c_import_buf;
|
Buf *c_import_buf;
|
||||||
bool block_exit_paths[BlockExitPathCount];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CIntType {
|
enum CIntType {
|
||||||
|
|
|
@ -4545,9 +4545,6 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import,
|
||||||
normalize_parent_ptrs(node);
|
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);
|
TypeTableEntry *expected_return_type = get_return_type(context);
|
||||||
|
|
||||||
switch (node->data.return_expr.kind) {
|
switch (node->data.return_expr.kind) {
|
||||||
|
|
|
@ -1593,7 +1593,19 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {
|
||||||
return phi;
|
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) {
|
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;
|
TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
|
||||||
if (handle_is_ptr(return_type)) {
|
if (handle_is_ptr(return_type)) {
|
||||||
assert(g->cur_ret_ptr);
|
assert(g->cur_ret_ptr);
|
||||||
|
@ -1615,7 +1627,9 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
|
||||||
|
|
||||||
switch (node->data.return_expr.kind) {
|
switch (node->data.return_expr.kind) {
|
||||||
case ReturnKindUnconditional:
|
case ReturnKindUnconditional:
|
||||||
return gen_return(g, node, value);
|
{
|
||||||
|
return gen_return(g, node, value);
|
||||||
|
}
|
||||||
case ReturnKindError:
|
case ReturnKindError:
|
||||||
{
|
{
|
||||||
assert(value_type->id == TypeTableEntryIdErrorUnion);
|
assert(value_type->id == TypeTableEntryIdErrorUnion);
|
||||||
|
@ -1820,13 +1834,7 @@ static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *i
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockContext *block_context = block_node->data.block.nested_block;
|
gen_defers_for_block(g, block_node->data.block.nested_block, block_node->data.block.child_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (implicit_return_type) {
|
if (implicit_return_type) {
|
||||||
return gen_return(g, block_node, return_value);
|
return gen_return(g, block_node, return_value);
|
||||||
|
|
|
@ -1532,6 +1532,19 @@ pub fn main(args: [][]u8) -> %void {
|
||||||
}
|
}
|
||||||
)SOURCE", "before\nafter\ndefer3\ndefer2\ndefer1\n");
|
)SOURCE", "before\nafter\ndefer3\ndefer2\ndefer1\n");
|
||||||
|
|
||||||
|
|
||||||
|
add_simple_case("defer with return", R"SOURCE(
|
||||||
|
import "std.zig";
|
||||||
|
pub fn main(args: [][]u8) -> %void {
|
||||||
|
%%stdout.printf("before\n");
|
||||||
|
defer %%stdout.printf("defer1\n");
|
||||||
|
defer %%stdout.printf("defer2\n");
|
||||||
|
if (args.len == 1) return;
|
||||||
|
defer %%stdout.printf("defer3\n");
|
||||||
|
%%stdout.printf("after\n");
|
||||||
|
}
|
||||||
|
)SOURCE", "before\ndefer2\ndefer1\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue