authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-04-23 12:21:47-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-04-23 12:21:47-07:00
log55b28ab0301237b8c9e39db4160036a42544f836
tree83ff05b5b2715b90ee1167758d609574f8bff6ca
parentda406cb11287e2961ad5aaa6ca857efd57fb9d03

fix returning empty struct from function

closes #142

3 files changed, 33 insertions(+), 15 deletions(-)

src/analyze.cpp+3-4
...@@ -623,7 +623,6 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {...@@ -623,7 +623,6 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
623 buf_appendf(&fn_type->name, " -> %s", buf_ptr(&fn_type_id->return_type->name));623 buf_appendf(&fn_type->name, " -> %s", buf_ptr(&fn_type_id->return_type->name));
624 }624 }
625625
626
627 // next, loop over the parameters again and compute debug information626 // next, loop over the parameters again and compute debug information
628 // and codegen information627 // and codegen information
629 bool first_arg_return = handle_is_ptr(fn_type_id->return_type);628 bool first_arg_return = handle_is_ptr(fn_type_id->return_type);
...@@ -634,15 +633,15 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {...@@ -634,15 +633,15 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
634 param_di_types[0] = fn_type_id->return_type->di_type;633 param_di_types[0] = fn_type_id->return_type->di_type;
635 int gen_param_index = 0;634 int gen_param_index = 0;
636 TypeTableEntry *gen_return_type;635 TypeTableEntry *gen_return_type;
637 if (first_arg_return) {636 if (!type_has_bits(fn_type_id->return_type)) {
637 gen_return_type = g->builtin_types.entry_void;
638 } else if (first_arg_return) {
638 TypeTableEntry *gen_type = get_pointer_to_type(g, fn_type_id->return_type, false);639 TypeTableEntry *gen_type = get_pointer_to_type(g, fn_type_id->return_type, false);
639 gen_param_types[gen_param_index] = gen_type->type_ref;640 gen_param_types[gen_param_index] = gen_type->type_ref;
640 gen_param_index += 1;641 gen_param_index += 1;
641 // after the gen_param_index += 1 because 0 is the return type642 // after the gen_param_index += 1 because 0 is the return type
642 param_di_types[gen_param_index] = gen_type->di_type;643 param_di_types[gen_param_index] = gen_type->di_type;
643 gen_return_type = g->builtin_types.entry_void;644 gen_return_type = g->builtin_types.entry_void;
644 } else if (!type_has_bits(fn_type_id->return_type)) {
645 gen_return_type = g->builtin_types.entry_void;
646 } else {645 } else {
647 gen_return_type = fn_type_id->return_type;646 gen_return_type = fn_type_id->return_type;
648 }647 }
src/codegen.cpp+15-11
...@@ -788,8 +788,10 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -788,8 +788,10 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
788788
789 TypeTableEntry *src_return_type = fn_type->data.fn.fn_type_id.return_type;789 TypeTableEntry *src_return_type = fn_type->data.fn.fn_type_id.return_type;
790790
791 bool ret_has_bits = type_has_bits(src_return_type);
792
791 int fn_call_param_count = node->data.fn_call_expr.params.length;793 int fn_call_param_count = node->data.fn_call_expr.params.length;
792 bool first_arg_ret = handle_is_ptr(src_return_type);794 bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type);
793 int actual_param_count = fn_call_param_count + (struct_type ? 1 : 0) + (first_arg_ret ? 1 : 0);795 int actual_param_count = fn_call_param_count + (struct_type ? 1 : 0) + (first_arg_ret ? 1 : 0);
794 bool is_var_args = fn_type->data.fn.fn_type_id.is_var_args;796 bool is_var_args = fn_type->data.fn.fn_type_id.is_var_args;
795797
...@@ -824,10 +826,10 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -824,10 +826,10 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
824826
825 if (src_return_type->id == TypeTableEntryIdUnreachable) {827 if (src_return_type->id == TypeTableEntryIdUnreachable) {
826 return LLVMBuildUnreachable(g->builder);828 return LLVMBuildUnreachable(g->builder);
829 } else if (!ret_has_bits) {
830 return nullptr;
827 } else if (first_arg_ret) {831 } else if (first_arg_ret) {
828 return node->data.fn_call_expr.tmp_ptr;832 return node->data.fn_call_expr.tmp_ptr;
829 } else if (!type_has_bits(src_return_type)) {
830 return nullptr;
831 } else {833 } else {
832 return result;834 return result;
833 }835 }
...@@ -1568,6 +1570,9 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b...@@ -1568,6 +1570,9 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b
1568 LLVMValueRef target_ref, LLVMValueRef value,1570 LLVMValueRef target_ref, LLVMValueRef value,
1569 TypeTableEntry *op1_type, TypeTableEntry *op2_type)1571 TypeTableEntry *op1_type, TypeTableEntry *op2_type)
1570{1572{
1573 if (!type_has_bits(op1_type)) {
1574 return nullptr;
1575 }
1571 if (handle_is_ptr(op1_type)) {1576 if (handle_is_ptr(op1_type)) {
1572 assert(op1_type == op2_type);1577 assert(op1_type == op2_type);
1573 assert(bin_op == BinOpTypeAssign);1578 assert(bin_op == BinOpTypeAssign);
...@@ -1584,7 +1589,8 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b...@@ -1584,7 +1589,8 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b
1584 }1589 }
15851590
1586 add_debug_source_node(g, source_node);1591 add_debug_source_node(g, source_node);
1587 return LLVMBuildStore(g->builder, value, target_ref);1592 LLVMBuildStore(g->builder, value, target_ref);
1593 return nullptr;
1588}1594}
15891595
1590static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) {1596static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) {
...@@ -1600,11 +1606,8 @@ static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) {...@@ -1600,11 +1606,8 @@ static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) {
16001606
1601 LLVMValueRef value = gen_expr(g, node->data.bin_op_expr.op2);1607 LLVMValueRef value = gen_expr(g, node->data.bin_op_expr.op2);
16021608
1603 if (!type_has_bits(op1_type)) {1609 gen_assign_raw(g, node, node->data.bin_op_expr.bin_op, target_ref, value, op1_type, op2_type);
1604 return nullptr;1610 return nullptr;
1605 }
1606
1607 return gen_assign_raw(g, node, node->data.bin_op_expr.bin_op, target_ref, value, op1_type, op2_type);
1608}1611}
16091612
1610static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef maybe_struct_ref) {1613static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef maybe_struct_ref) {
...@@ -1846,11 +1849,12 @@ static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef va...@@ -1846,11 +1849,12 @@ static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef va
1846 assert(g->cur_ret_ptr);1849 assert(g->cur_ret_ptr);
1847 gen_assign_raw(g, source_node, BinOpTypeAssign, g->cur_ret_ptr, value, return_type, return_type);1850 gen_assign_raw(g, source_node, BinOpTypeAssign, g->cur_ret_ptr, value, return_type, return_type);
1848 add_debug_source_node(g, source_node);1851 add_debug_source_node(g, source_node);
1849 return LLVMBuildRetVoid(g->builder);1852 LLVMBuildRetVoid(g->builder);
1850 } else {1853 } else {
1851 add_debug_source_node(g, source_node);1854 add_debug_source_node(g, source_node);
1852 return LLVMBuildRet(g->builder, value);1855 LLVMBuildRet(g->builder, value);
1853 }1856 }
1857 return nullptr;
1854}1858}
18551859
1856static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {1860static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
test/self_hosted.zig+15
...@@ -1299,3 +1299,18 @@ struct EmptyStruct {...@@ -1299,3 +1299,18 @@ struct EmptyStruct {
12991299
1300#attribute("test")1300#attribute("test")
1301fn @"weird function name"() { }1301fn @"weird function name"() { }
1302
1303
1304#attribute("test")
1305fn return_empty_struct_from_fn() {
1306 test_return_empty_struct_from_fn();
1307 test_return_empty_struct_from_fn_noeval();
1308}
1309struct EmptyStruct2 {}
1310fn test_return_empty_struct_from_fn() -> EmptyStruct2 {
1311 EmptyStruct2 {}
1312}
1313#static_eval_enable(false)
1314fn test_return_empty_struct_from_fn_noeval() -> EmptyStruct2 {
1315 EmptyStruct2 {}
1316}