| ... | @@ -3111,6 +3111,51 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) { | ... | @@ -3111,6 +3111,51 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) { |
| 3111 | LLVMAddCallSiteAttribute(call_instr, 1, sret_attr); | 3111 | LLVMAddCallSiteAttribute(call_instr, 1, sret_attr); |
| 3112 | } | 3112 | } |
| 3113 | | 3113 | |
| | 3114 | ATTRIBUTE_NORETURN |
| | 3115 | static void report_errors_and_exit(CodeGen *g) { |
| | 3116 | assert(g->errors.length != 0); |
| | 3117 | for (size_t i = 0; i < g->errors.length; i += 1) { |
| | 3118 | ErrorMsg *err = g->errors.at(i); |
| | 3119 | print_err_msg(err, g->err_color); |
| | 3120 | } |
| | 3121 | exit(1); |
| | 3122 | } |
| | 3123 | |
| | 3124 | static void report_errors_and_maybe_exit(CodeGen *g) { |
| | 3125 | if (g->errors.length != 0) { |
| | 3126 | report_errors_and_exit(g); |
| | 3127 | } |
| | 3128 | } |
| | 3129 | |
| | 3130 | ATTRIBUTE_NORETURN |
| | 3131 | static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) { |
| | 3132 | ErrorMsg *msg = add_node_error(g, source_node, |
| | 3133 | buf_sprintf("TODO: support C ABI for more targets. https://github.com/ziglang/zig/issues/1481")); |
| | 3134 | add_error_note(g, msg, source_node, |
| | 3135 | buf_sprintf("pointers, integers, floats, bools, and enums work on all targets")); |
| | 3136 | report_errors_and_exit(g); |
| | 3137 | } |
| | 3138 | |
| | 3139 | static void gen_c_abi_param(CodeGen *g, ZigList<LLVMValueRef> *gen_param_values, LLVMValueRef val, |
| | 3140 | ZigType *ty, AstNode *source_node) |
| | 3141 | { |
| | 3142 | if (ty->id == ZigTypeIdInt || |
| | 3143 | ty->id == ZigTypeIdFloat || |
| | 3144 | ty->id == ZigTypeIdBool || |
| | 3145 | ty->id == ZigTypeIdEnum || |
| | 3146 | get_codegen_ptr_type(ty) != nullptr) |
| | 3147 | { |
| | 3148 | gen_param_values->append(val); |
| | 3149 | return; |
| | 3150 | } |
| | 3151 | |
| | 3152 | if (g->zig_target.arch.arch == ZigLLVM_x86_64) { |
| | 3153 | give_up_with_c_abi_error(g, source_node); |
| | 3154 | } else { |
| | 3155 | give_up_with_c_abi_error(g, source_node); |
| | 3156 | } |
| | 3157 | } |
| | 3158 | |
| 3114 | static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) { | 3159 | static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) { |
| 3115 | LLVMValueRef fn_val; | 3160 | LLVMValueRef fn_val; |
| 3116 | ZigType *fn_type; | 3161 | ZigType *fn_type; |
| ... | @@ -3128,29 +3173,25 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -3128,29 +3173,25 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3128 | ZigType *src_return_type = fn_type_id->return_type; | 3173 | ZigType *src_return_type = fn_type_id->return_type; |
| 3129 | bool ret_has_bits = type_has_bits(src_return_type); | 3174 | bool ret_has_bits = type_has_bits(src_return_type); |
| 3130 | | 3175 | |
| | 3176 | CallingConvention cc = fn_type->data.fn.fn_type_id.cc; |
| | 3177 | bool is_c_abi = cc == CallingConventionC; |
| | 3178 | |
| 3131 | bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type) && | 3179 | bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type) && |
| 3132 | calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc); | 3180 | calling_convention_does_first_arg_return(cc); |
| 3133 | bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack(g, fn_type_id); | 3181 | bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack(g, fn_type_id); |
| 3134 | // +2 for the async args | | |
| 3135 | size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0) + 2; | | |
| 3136 | bool is_var_args = fn_type_id->is_var_args; | 3182 | bool is_var_args = fn_type_id->is_var_args; |
| 3137 | LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count); | 3183 | ZigList<LLVMValueRef> gen_param_values = {}; |
| 3138 | size_t gen_param_index = 0; | | |
| 3139 | if (first_arg_ret) { | 3184 | if (first_arg_ret) { |
| 3140 | gen_param_values[gen_param_index] = instruction->tmp_ptr; | 3185 | gen_param_values.append(instruction->tmp_ptr); |
| 3141 | gen_param_index += 1; | | |
| 3142 | } | 3186 | } |
| 3143 | if (prefix_arg_err_ret_stack) { | 3187 | if (prefix_arg_err_ret_stack) { |
| 3144 | gen_param_values[gen_param_index] = get_cur_err_ret_trace_val(g, instruction->base.scope); | 3188 | gen_param_values.append(get_cur_err_ret_trace_val(g, instruction->base.scope)); |
| 3145 | gen_param_index += 1; | | |
| 3146 | } | 3189 | } |
| 3147 | if (instruction->is_async) { | 3190 | if (instruction->is_async) { |
| 3148 | gen_param_values[gen_param_index] = ir_llvm_value(g, instruction->async_allocator); | 3191 | gen_param_values.append(ir_llvm_value(g, instruction->async_allocator)); |
| 3149 | gen_param_index += 1; | | |
| 3150 | | 3192 | |
| 3151 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, ""); | 3193 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, ""); |
| 3152 | gen_param_values[gen_param_index] = err_val_ptr; | 3194 | gen_param_values.append(err_val_ptr); |
| 3153 | gen_param_index += 1; | | |
| 3154 | } | 3195 | } |
| 3155 | for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) { | 3196 | for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) { |
| 3156 | IrInstruction *param_instruction = instruction->args[call_i]; | 3197 | IrInstruction *param_instruction = instruction->args[call_i]; |
| ... | @@ -3158,8 +3199,11 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -3158,8 +3199,11 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3158 | if (is_var_args || type_has_bits(param_type)) { | 3199 | if (is_var_args || type_has_bits(param_type)) { |
| 3159 | LLVMValueRef param_value = ir_llvm_value(g, param_instruction); | 3200 | LLVMValueRef param_value = ir_llvm_value(g, param_instruction); |
| 3160 | assert(param_value); | 3201 | assert(param_value); |
| 3161 | gen_param_values[gen_param_index] = param_value; | 3202 | if (is_c_abi) { |
| 3162 | gen_param_index += 1; | 3203 | gen_c_abi_param(g, &gen_param_values, param_value, param_type, param_instruction->source_node); |
| | 3204 | } else { |
| | 3205 | gen_param_values.append(param_value); |
| | 3206 | } |
| 3163 | } | 3207 | } |
| 3164 | } | 3208 | } |
| 3165 | | 3209 | |
| ... | @@ -3176,12 +3220,12 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -3176,12 +3220,12 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3176 | break; | 3220 | break; |
| 3177 | } | 3221 | } |
| 3178 | | 3222 | |
| 3179 | LLVMCallConv llvm_cc = get_llvm_cc(g, fn_type->data.fn.fn_type_id.cc); | 3223 | LLVMCallConv llvm_cc = get_llvm_cc(g, cc); |
| 3180 | LLVMValueRef result; | 3224 | LLVMValueRef result; |
| 3181 | | 3225 | |
| 3182 | if (instruction->new_stack == nullptr) { | 3226 | if (instruction->new_stack == nullptr) { |
| 3183 | result = ZigLLVMBuildCall(g->builder, fn_val, | 3227 | result = ZigLLVMBuildCall(g->builder, fn_val, |
| 3184 | gen_param_values, (unsigned)gen_param_index, llvm_cc, fn_inline, ""); | 3228 | gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, ""); |
| 3185 | } else { | 3229 | } else { |
| 3186 | LLVMValueRef stacksave_fn_val = get_stacksave_fn_val(g); | 3230 | LLVMValueRef stacksave_fn_val = get_stacksave_fn_val(g); |
| 3187 | LLVMValueRef stackrestore_fn_val = get_stackrestore_fn_val(g); | 3231 | LLVMValueRef stackrestore_fn_val = get_stackrestore_fn_val(g); |
| ... | @@ -3190,7 +3234,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -3190,7 +3234,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3190 | LLVMValueRef old_stack_ref = LLVMBuildCall(g->builder, stacksave_fn_val, nullptr, 0, ""); | 3234 | LLVMValueRef old_stack_ref = LLVMBuildCall(g->builder, stacksave_fn_val, nullptr, 0, ""); |
| 3191 | gen_set_stack_pointer(g, new_stack_addr); | 3235 | gen_set_stack_pointer(g, new_stack_addr); |
| 3192 | result = ZigLLVMBuildCall(g->builder, fn_val, | 3236 | result = ZigLLVMBuildCall(g->builder, fn_val, |
| 3193 | gen_param_values, (unsigned)gen_param_index, llvm_cc, fn_inline, ""); | 3237 | gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, ""); |
| 3194 | LLVMBuildCall(g->builder, stackrestore_fn_val, &old_stack_ref, 1, ""); | 3238 | LLVMBuildCall(g->builder, stackrestore_fn_val, &old_stack_ref, 1, ""); |
| 3195 | } | 3239 | } |
| 3196 | | 3240 | |
| ... | @@ -5735,16 +5779,6 @@ static void ensure_cache_dir(CodeGen *g) { | ... | @@ -5735,16 +5779,6 @@ static void ensure_cache_dir(CodeGen *g) { |
| 5735 | } | 5779 | } |
| 5736 | } | 5780 | } |
| 5737 | | 5781 | |
| 5738 | static void report_errors_and_maybe_exit(CodeGen *g) { | | |
| 5739 | if (g->errors.length != 0) { | | |
| 5740 | for (size_t i = 0; i < g->errors.length; i += 1) { | | |
| 5741 | ErrorMsg *err = g->errors.at(i); | | |
| 5742 | print_err_msg(err, g->err_color); | | |
| 5743 | } | | |
| 5744 | exit(1); | | |
| 5745 | } | | |
| 5746 | } | | |
| 5747 | | | |
| 5748 | static void validate_inline_fns(CodeGen *g) { | 5782 | static void validate_inline_fns(CodeGen *g) { |
| 5749 | for (size_t i = 0; i < g->inline_fns.length; i += 1) { | 5783 | for (size_t i = 0; i < g->inline_fns.length; i += 1) { |
| 5750 | ZigFn *fn_entry = g->inline_fns.at(i); | 5784 | ZigFn *fn_entry = g->inline_fns.at(i); |