diff options
Diffstat (limited to 'src/codegen.cpp')
| -rw-r--r-- | src/codegen.cpp | 48 |
1 files changed, 45 insertions, 3 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp index 11e4903ded..023a714819 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2864,6 +2864,48 @@ static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrIn return instruction->var->value_ref; } +static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) { + LLVMValueRef fn_val = ir_llvm_value(g, instruction->fn); + TypeTableEntry *fn_type = instruction->fn->type_entry; + TypeTableEntry *src_return_type = fn_type->data.fn.fn_type_id.return_type; + bool ret_has_bits = type_has_bits(src_return_type); + size_t fn_call_param_count = instruction->arg_count; + bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type); + size_t actual_param_count = fn_call_param_count + (first_arg_ret ? 1 : 0); + bool is_var_args = fn_type->data.fn.fn_type_id.is_var_args; + LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count); + size_t gen_param_index = 0; + if (first_arg_ret) { + zig_panic("TODO"); + //gen_param_values[gen_param_index] = node->data.fn_call_expr.tmp_ptr; + //gen_param_index += 1; + } + for (size_t call_i = 0; call_i < fn_call_param_count; call_i += 1) { + IrInstruction *param_instruction = instruction->args[call_i]; + LLVMValueRef param_value = ir_llvm_value(g, param_instruction); + assert(param_value); + TypeTableEntry *param_type = param_instruction->type_entry; + if (is_var_args || type_has_bits(param_type)) { + gen_param_values[gen_param_index] = param_value; + gen_param_index += 1; + } + } + + LLVMValueRef result = ZigLLVMBuildCall(g->builder, fn_val, + gen_param_values, gen_param_index, fn_type->data.fn.calling_convention, ""); + + if (src_return_type->id == TypeTableEntryIdUnreachable) { + return LLVMBuildUnreachable(g->builder); + } else if (!ret_has_bits) { + return nullptr; + } else if (first_arg_ret) { + zig_panic("TODO"); + //return node->data.fn_call_expr.tmp_ptr; + } else { + return result; + } +} + static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) { set_debug_source_node(g, instruction->source_node); @@ -2891,10 +2933,11 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, return ir_render_load_ptr(g, executable, (IrInstructionLoadPtr *)instruction); case IrInstructionIdVarPtr: return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction); + case IrInstructionIdCall: + return ir_render_call(g, executable, (IrInstructionCall *)instruction); case IrInstructionIdSwitchBr: case IrInstructionIdPhi: case IrInstructionIdStorePtr: - case IrInstructionIdCall: case IrInstructionIdBuiltinCall: case IrInstructionIdContainerInitList: case IrInstructionIdContainerInitFields: @@ -2911,8 +2954,7 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) { assert(executable->basic_block_list.length > 0); for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) { IrBasicBlock *current_block = executable->basic_block_list.at(block_i); - if (current_block->ref_count == 0) - continue; + assert(current_block->ref_count > 0); assert(current_block->llvm_block); LLVMPositionBuilderAtEnd(g->builder, current_block->llvm_block); for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) { |
