| ... | ... | @@ -76,11 +76,29 @@ static LLVMZigDIType *to_llvm_debug_type(AstNode *type_node) { |
| 76 | 76 | return type_node->codegen_node->data.type_node.entry->di_type; |
| 77 | 77 | } |
| 78 | 78 | |
| 79 | | static bool type_is_unreachable(CodeGen *g, AstNode *type_node) { |
| 79 | static TypeTableEntry *get_type_for_type_node(CodeGen *g, AstNode *type_node) { |
| 80 | 80 | assert(type_node->type == NodeTypeType); |
| 81 | 81 | assert(type_node->codegen_node); |
| 82 | 82 | assert(type_node->codegen_node->data.type_node.entry); |
| 83 | | return type_node->codegen_node->data.type_node.entry == g->builtin_types.entry_unreachable; |
| 83 | return type_node->codegen_node->data.type_node.entry; |
| 84 | } |
| 85 | |
| 86 | static bool type_is_unreachable(CodeGen *g, AstNode *type_node) { |
| 87 | return get_type_for_type_node(g, type_node) == g->builtin_types.entry_unreachable; |
| 88 | } |
| 89 | |
| 90 | static bool is_param_decl_type_void(CodeGen *g, AstNode *param_decl_node) { |
| 91 | assert(param_decl_node->type == NodeTypeParamDecl); |
| 92 | return get_type_for_type_node(g, param_decl_node->data.param_decl.type) == g->builtin_types.entry_void; |
| 93 | } |
| 94 | |
| 95 | static int count_non_void_params(CodeGen *g, ZigList<AstNode *> *params) { |
| 96 | int result = 0; |
| 97 | for (int i = 0; i < params->length; i += 1) { |
| 98 | if (!is_param_decl_type_void(g, params->at(i))) |
| 99 | result += 1; |
| 100 | } |
| 101 | return result; |
| 84 | 102 | } |
| 85 | 103 | |
| 86 | 104 | static void add_debug_source_node(CodeGen *g, AstNode *node) { |
| ... | ... | @@ -124,15 +142,23 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) { |
| 124 | 142 | int actual_param_count = node->data.fn_call_expr.params.length; |
| 125 | 143 | assert(expected_param_count == actual_param_count); |
| 126 | 144 | |
| 127 | | LLVMValueRef *param_values = allocate<LLVMValueRef>(actual_param_count); |
| 145 | // don't really include void values |
| 146 | int gen_param_count = count_non_void_params(g, &fn_table_entry->proto_node->data.fn_proto.params); |
| 147 | LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(gen_param_count); |
| 148 | |
| 149 | int gen_param_index = 0; |
| 128 | 150 | for (int i = 0; i < actual_param_count; i += 1) { |
| 129 | 151 | AstNode *expr_node = node->data.fn_call_expr.params.at(i); |
| 130 | | param_values[i] = gen_expr(g, expr_node); |
| 152 | LLVMValueRef param_value = gen_expr(g, expr_node); |
| 153 | if (!is_param_decl_type_void(g, fn_table_entry->proto_node->data.fn_proto.params.at(i))) { |
| 154 | gen_param_values[gen_param_index] = param_value; |
| 155 | gen_param_index += 1; |
| 156 | } |
| 131 | 157 | } |
| 132 | 158 | |
| 133 | 159 | add_debug_source_node(g, node); |
| 134 | 160 | LLVMValueRef result = LLVMZigBuildCall(g->builder, fn_table_entry->fn_value, |
| 135 | | param_values, actual_param_count, fn_table_entry->calling_convention, ""); |
| 161 | gen_param_values, gen_param_count, fn_table_entry->calling_convention, ""); |
| 136 | 162 | |
| 137 | 163 | if (type_is_unreachable(g, fn_table_entry->proto_node->data.fn_proto.return_type)) { |
| 138 | 164 | return LLVMBuildUnreachable(g->builder); |
| ... | ... | @@ -590,14 +616,19 @@ static void do_code_gen(CodeGen *g) { |
| 590 | 616 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; |
| 591 | 617 | |
| 592 | 618 | LLVMTypeRef ret_type = to_llvm_type(fn_proto->return_type); |
| 593 | | LLVMTypeRef *param_types = allocate<LLVMTypeRef>(fn_proto->params.length); |
| 619 | int param_count = count_non_void_params(g, &fn_proto->params); |
| 620 | LLVMTypeRef *param_types = allocate<LLVMTypeRef>(param_count); |
| 621 | int gen_param_index = 0; |
| 594 | 622 | for (int param_decl_i = 0; param_decl_i < fn_proto->params.length; param_decl_i += 1) { |
| 595 | 623 | AstNode *param_node = fn_proto->params.at(param_decl_i); |
| 596 | 624 | assert(param_node->type == NodeTypeParamDecl); |
| 625 | if (is_param_decl_type_void(g, param_node)) |
| 626 | continue; |
| 597 | 627 | AstNode *type_node = param_node->data.param_decl.type; |
| 598 | | param_types[param_decl_i] = to_llvm_type(type_node); |
| 628 | param_types[gen_param_index] = to_llvm_type(type_node); |
| 629 | gen_param_index += 1; |
| 599 | 630 | } |
| 600 | | LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, fn_proto->params.length, 0); |
| 631 | LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, param_count, 0); |
| 601 | 632 | LLVMValueRef fn = LLVMAddFunction(g->module, buf_ptr(&fn_proto->name), function_type); |
| 602 | 633 | |
| 603 | 634 | LLVMSetLinkage(fn, fn_table_entry->internal_linkage ? LLVMInternalLinkage : LLVMExternalLinkage); |
| ... | ... | @@ -647,16 +678,20 @@ static void do_code_gen(CodeGen *g) { |
| 647 | 678 | |
| 648 | 679 | FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node; |
| 649 | 680 | assert(codegen_fn_def); |
| 650 | | int param_count = fn_proto->params.length; |
| 651 | | assert(param_count == (int)LLVMCountParams(fn)); |
| 652 | | LLVMValueRef *params = allocate<LLVMValueRef>(param_count); |
| 681 | int non_void_param_count = count_non_void_params(g, &fn_proto->params); |
| 682 | assert(non_void_param_count == (int)LLVMCountParams(fn)); |
| 683 | LLVMValueRef *params = allocate<LLVMValueRef>(non_void_param_count); |
| 653 | 684 | LLVMGetParams(fn, params); |
| 654 | 685 | |
| 655 | | for (int i = 0; i < param_count; i += 1) { |
| 686 | int non_void_index = 0; |
| 687 | for (int i = 0; i < fn_proto->params.length; i += 1) { |
| 656 | 688 | AstNode *param_decl = fn_proto->params.at(i); |
| 657 | 689 | assert(param_decl->type == NodeTypeParamDecl); |
| 690 | if (is_param_decl_type_void(g, param_decl)) |
| 691 | continue; |
| 658 | 692 | LocalVariableTableEntry *parameter_variable = fn_def_node->codegen_node->data.fn_def_node.block_context->variable_table.get(&param_decl->data.param_decl.name); |
| 659 | | parameter_variable->value_ref = params[i]; |
| 693 | parameter_variable->value_ref = params[non_void_index]; |
| 694 | non_void_index += 1; |
| 660 | 695 | } |
| 661 | 696 | |
| 662 | 697 | build_label_blocks(g, fn_def_node->data.fn_def.body); |