implement ?return expression

This commit is contained in:
Andrew Kelley
2016-08-23 15:05:26 -07:00
parent 6149f73189
commit 1f7ec741fa
5 changed files with 102 additions and 3 deletions
+28 -1
View File
@@ -6271,7 +6271,34 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import,
}
}
case ReturnKindMaybe:
zig_panic("TODO");
{
TypeTableEntry *expected_maybe_type;
if (expected_type) {
expected_maybe_type = get_maybe_type(g, expected_type);
} else {
expected_maybe_type = nullptr;
}
TypeTableEntry *resolved_type = analyze_expression(g, import, context, expected_maybe_type,
node->data.return_expr.expr);
if (resolved_type->id == TypeTableEntryIdInvalid) {
return resolved_type;
} else if (resolved_type->id == TypeTableEntryIdMaybe) {
TypeTableEntry *return_type = context->fn_entry->type_entry->data.fn.fn_type_id.return_type;
if (return_type->id != TypeTableEntryIdMaybe) {
ErrorMsg *msg = add_node_error(g, node,
buf_sprintf("?return statement in function with return type '%s'",
buf_ptr(&return_type->name)));
AstNode *return_type_node = context->fn_entry->fn_def_node->data.fn_def.fn_proto->data.fn_proto.return_type;
add_error_note(g, msg, return_type_node, buf_sprintf("function return type here"));
}
return resolved_type->data.maybe.child_type;
} else {
add_node_error(g, node->data.return_expr.expr,
buf_sprintf("expected maybe type, got '%s'", buf_ptr(&resolved_type->name)));
return g->builtin_types.entry_invalid;
}
}
}
zig_unreachable();
}
+39 -1
View File
@@ -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();
}