diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2016-08-23 15:05:26 -0700 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2016-08-29 22:14:09 -0700 |
| commit | 1f7ec741fa5b1d9ba3826e06a8a8a0feec58876f (patch) | |
| tree | b74ec329f2e7e128087282adedcd37752b7cceaf /src/codegen.cpp | |
| parent | 6149f7318986214a34b09347f28ba48b2a614fef (diff) | |
| download | zig-1f7ec741fa5b1d9ba3826e06a8a8a0feec58876f.tar.gz zig-1f7ec741fa5b1d9ba3826e06a8a8a0feec58876f.zip | |
implement `?return` expression
Diffstat (limited to 'src/codegen.cpp')
| -rw-r--r-- | src/codegen.cpp | 40 |
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(); } |
