aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2016-08-23 15:05:26 -0700
committerAndrew Kelley <superjoe30@gmail.com>2016-08-29 22:14:09 -0700
commit1f7ec741fa5b1d9ba3826e06a8a8a0feec58876f (patch)
treeb74ec329f2e7e128087282adedcd37752b7cceaf /src/codegen.cpp
parent6149f7318986214a34b09347f28ba48b2a614fef (diff)
downloadzig-1f7ec741fa5b1d9ba3826e06a8a8a0feec58876f.tar.gz
zig-1f7ec741fa5b1d9ba3826e06a8a8a0feec58876f.zip
implement `?return` expression
Diffstat (limited to 'src/codegen.cpp')
-rw-r--r--src/codegen.cpp40
1 files changed, 39 insertions, 1 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 3b954da4f6..12ba5378ac 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -2497,7 +2497,45 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
}
}
case ReturnKindMaybe:
- zig_panic("TODO");
+ {
+ assert(value_type->id == TypeTableEntryIdMaybe);
+ TypeTableEntry *child_type = value_type->data.maybe.child_type;
+
+ LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeRetReturn");
+ LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeRetContinue");
+
+ set_debug_source_node(g, node);
+ LLVMValueRef maybe_val_ptr = LLVMBuildStructGEP(g->builder, value, 1, "");
+ LLVMValueRef is_non_null = LLVMBuildLoad(g->builder, maybe_val_ptr, "");
+
+ LLVMValueRef zero = LLVMConstNull(LLVMInt1Type());
+ LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntNE, is_non_null, zero, "");
+ LLVMBuildCondBr(g->builder, cond_val, continue_block, return_block);
+
+ LLVMPositionBuilderAtEnd(g->builder, return_block);
+ TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
+ assert(return_type->id == TypeTableEntryIdMaybe);
+ if (handle_is_ptr(return_type)) {
+ assert(g->cur_ret_ptr);
+
+ set_debug_source_node(g, node);
+ LLVMValueRef maybe_bit_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, 1, "");
+ LLVMBuildStore(g->builder, zero, maybe_bit_ptr);
+ LLVMBuildRetVoid(g->builder);
+ } else {
+ LLVMValueRef ret_zero_value = LLVMConstNull(return_type->type_ref);
+ gen_return(g, node, ret_zero_value, ReturnKnowledgeKnownNull);
+ }
+
+ LLVMPositionBuilderAtEnd(g->builder, continue_block);
+ if (type_has_bits(child_type)) {
+ set_debug_source_node(g, node);
+ LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, value, 0, "");
+ return get_handle_value(g, node, val_ptr, child_type);
+ } else {
+ return nullptr;
+ }
+ }
}
zig_unreachable();
}