@@ -3111,6 +3111,51 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) {
3111
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
3159
static LLVMValueRef ir_render_call (CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) {
3115
3160
LLVMValueRef fn_val;
3116
3161
ZigType *fn_type;
@@ -3128,38 +3173,37 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3128
3173
ZigType *src_return_type = fn_type_id->return_type ;
3129
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
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
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
3182
bool is_var_args = fn_type_id->is_var_args ;
3137
- LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count);
3138
- size_t gen_param_index = 0 ;
3183
+ ZigList<LLVMValueRef> gen_param_values = {};
3139
3184
if (first_arg_ret) {
3140
- gen_param_values[gen_param_index] = instruction->tmp_ptr ;
3141
- gen_param_index += 1 ;
3185
+ gen_param_values.append (instruction->tmp_ptr );
3142
3186
}
3143
3187
if (prefix_arg_err_ret_stack) {
3144
- gen_param_values[gen_param_index] = get_cur_err_ret_trace_val (g, instruction->base .scope );
3145
- gen_param_index += 1 ;
3188
+ gen_param_values.append (get_cur_err_ret_trace_val (g, instruction->base .scope ));
3146
3189
}
3147
3190
if (instruction->is_async ) {
3148
- gen_param_values[gen_param_index] = ir_llvm_value (g, instruction->async_allocator );
3149
- gen_param_index += 1 ;
3191
+ gen_param_values.append (ir_llvm_value (g, instruction->async_allocator ));
3150
3192
3151
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;
3153
- gen_param_index += 1 ;
3194
+ gen_param_values.append (err_val_ptr);
3154
3195
}
3155
3196
for (size_t call_i = 0 ; call_i < instruction->arg_count ; call_i += 1 ) {
3156
3197
IrInstruction *param_instruction = instruction->args [call_i];
3157
3198
ZigType *param_type = param_instruction->value .type ;
3158
3199
if (is_var_args || type_has_bits (param_type)) {
3159
3200
LLVMValueRef param_value = ir_llvm_value (g, param_instruction);
3160
3201
assert (param_value);
3161
- gen_param_values[gen_param_index] = param_value;
3162
- gen_param_index += 1 ;
3202
+ if (is_c_abi) {
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
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
3224
LLVMValueRef result;
3181
3225
3182
3226
if (instruction->new_stack == nullptr ) {
3183
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
3229
} else {
3186
3230
LLVMValueRef stacksave_fn_val = get_stacksave_fn_val (g);
3187
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
3234
LLVMValueRef old_stack_ref = LLVMBuildCall (g->builder , stacksave_fn_val, nullptr , 0 , " " );
3191
3235
gen_set_stack_pointer (g, new_stack_addr);
3192
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
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
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
5782
static void validate_inline_fns (CodeGen *g) {
5749
5783
for (size_t i = 0 ; i < g->inline_fns .length ; i += 1 ) {
5750
5784
ZigFn *fn_entry = g->inline_fns .at (i);
0 commit comments