| ... | ... | @@ -1954,6 +1954,15 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 1954 | 1954 | source_node = var->decl_node; |
| 1955 | 1955 | llvm_fn = fn_walk->data.vars.llvm_fn; |
| 1956 | 1956 | break; |
| 1957 | case FnWalkIdInits: |
| 1958 | if (src_i >= fn_type->data.fn.fn_type_id.param_count) |
| 1959 | return false; |
| 1960 | param_info = &fn_type->data.fn.fn_type_id.param_info[src_i]; |
| 1961 | ty = param_info->type; |
| 1962 | var = fn_walk->data.inits.fn->variable_list.at(src_i); |
| 1963 | source_node = fn_walk->data.inits.fn->proto_node; |
| 1964 | llvm_fn = fn_walk->data.inits.llvm_fn; |
| 1965 | break; |
| 1957 | 1966 | } |
| 1958 | 1967 | |
| 1959 | 1968 | if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat || |
| ... | ... | @@ -1990,6 +1999,14 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 1990 | 1999 | dest_ty = ty; |
| 1991 | 2000 | goto var_ok; |
| 1992 | 2001 | } |
| 2002 | case FnWalkIdInits: |
| 2003 | clear_debug_source_node(g); |
| 2004 | gen_store_untyped(g, LLVMGetParam(llvm_fn, fn_walk->data.inits.gen_i), var->value_ref, var->align_bytes, false); |
| 2005 | if (var->decl_node) { |
| 2006 | gen_var_debug_decl(g, var); |
| 2007 | } |
| 2008 | fn_walk->data.inits.gen_i += 1; |
| 2009 | break; |
| 1993 | 2010 | } |
| 1994 | 2011 | return true; |
| 1995 | 2012 | } |
| ... | ... | @@ -2018,6 +2035,12 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 2018 | 2035 | fn_walk->data.vars.gen_i += 1; |
| 2019 | 2036 | goto var_ok; |
| 2020 | 2037 | } |
| 2038 | case FnWalkIdInits: |
| 2039 | if (var->decl_node) { |
| 2040 | gen_var_debug_decl(g, var); |
| 2041 | } |
| 2042 | fn_walk->data.inits.gen_i += 1; |
| 2043 | break; |
| 2021 | 2044 | } |
| 2022 | 2045 | return true; |
| 2023 | 2046 | } |
| ... | ... | @@ -2052,6 +2075,12 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 2052 | 2075 | fn_walk->data.vars.gen_i += 1; |
| 2053 | 2076 | goto var_ok; |
| 2054 | 2077 | } |
| 2078 | case FnWalkIdInits: |
| 2079 | if (var->decl_node) { |
| 2080 | gen_var_debug_decl(g, var); |
| 2081 | } |
| 2082 | fn_walk->data.inits.gen_i += 1; |
| 2083 | break; |
| 2055 | 2084 | } |
| 2056 | 2085 | return true; |
| 2057 | 2086 | } |
| ... | ... | @@ -2092,6 +2121,18 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 2092 | 2121 | fn_walk->data.vars.gen_i += 1; |
| 2093 | 2122 | goto var_ok; |
| 2094 | 2123 | } |
| 2124 | case FnWalkIdInits: { |
| 2125 | clear_debug_source_node(g); |
| 2126 | LLVMValueRef arg = LLVMGetParam(llvm_fn, fn_walk->data.inits.gen_i += 1); |
| 2127 | LLVMTypeRef ptr_to_int_type_ref = LLVMPointerType(LLVMIntType((unsigned)ty_size * 8), 0); |
| 2128 | LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, var->value_ref, ptr_to_int_type_ref, ""); |
| 2129 | gen_store_untyped(g, arg, bitcasted, var->align_bytes, false); |
| 2130 | if (var->decl_node) { |
| 2131 | gen_var_debug_decl(g, var); |
| 2132 | } |
| 2133 | fn_walk->data.inits.gen_i += 1; |
| 2134 | break; |
| 2135 | } |
| 2095 | 2136 | } |
| 2096 | 2137 | return true; |
| 2097 | 2138 | } |
| ... | ... | @@ -2140,6 +2181,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) { |
| 2140 | 2181 | } |
| 2141 | 2182 | return; |
| 2142 | 2183 | } |
| 2184 | size_t next_var_i = 0; |
| 2143 | 2185 | for (size_t param_i = 0; param_i < fn_type->data.fn.fn_type_id.param_count; param_i += 1) { |
| 2144 | 2186 | FnGenParamInfo *gen_info = &fn_type->data.fn.gen_param_info[param_i]; |
| 2145 | 2187 | size_t gen_index = gen_info->gen_index; |
| ... | ... | @@ -2166,6 +2208,27 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) { |
| 2166 | 2208 | } |
| 2167 | 2209 | break; |
| 2168 | 2210 | } |
| 2211 | case FnWalkIdInits: { |
| 2212 | ZigFn *fn_table_entry = fn_walk->data.inits.fn; |
| 2213 | LLVMValueRef llvm_fn = fn_table_entry->llvm_value; |
| 2214 | ZigVar *variable = fn_table_entry->variable_list.at(next_var_i); |
| 2215 | assert(variable->src_arg_index != SIZE_MAX); |
| 2216 | next_var_i += 1; |
| 2217 | |
| 2218 | assert(variable); |
| 2219 | assert(variable->value_ref); |
| 2220 | |
| 2221 | if (!handle_is_ptr(variable->value->type)) { |
| 2222 | clear_debug_source_node(g); |
| 2223 | gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index), variable->value_ref, |
| 2224 | variable->align_bytes, false); |
| 2225 | } |
| 2226 | |
| 2227 | if (variable->decl_node) { |
| 2228 | gen_var_debug_decl(g, variable); |
| 2229 | } |
| 2230 | break; |
| 2231 | } |
| 2169 | 2232 | case FnWalkIdCall: |
| 2170 | 2233 | // handled before for loop |
| 2171 | 2234 | zig_unreachable(); |
| ... | ... | @@ -3402,80 +3465,6 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) { |
| 3402 | 3465 | LLVMAddCallSiteAttribute(call_instr, 1, sret_attr); |
| 3403 | 3466 | } |
| 3404 | 3467 | |
| 3405 | | // If you edit this function you have to edit the corresponding code: |
| 3406 | | // codegen.cpp:gen_c_abi_param_var |
| 3407 | | // codegen.cpp:gen_c_abi_param_var_init |
| 3408 | | static void gen_c_abi_param_var_init(CodeGen *g, ImportTableEntry *import, LLVMValueRef llvm_fn, ZigFn *fn, |
| 3409 | | ZigVar *var, unsigned *arg_index) |
| 3410 | | { |
| 3411 | | ZigType *ty = var->value->type; |
| 3412 | | |
| 3413 | | if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat || |
| 3414 | | ty->id == ZigTypeIdInt // TODO investigate if we need to change this |
| 3415 | | ) { |
| 3416 | | clear_debug_source_node(g); |
| 3417 | | gen_store_untyped(g, LLVMGetParam(llvm_fn, *arg_index), var->value_ref, var->align_bytes, false); |
| 3418 | | if (var->decl_node) { |
| 3419 | | gen_var_debug_decl(g, var); |
| 3420 | | } |
| 3421 | | *arg_index += 1; |
| 3422 | | return; |
| 3423 | | } |
| 3424 | | |
| 3425 | | // Arrays are just pointers |
| 3426 | | if (ty->id == ZigTypeIdArray) { |
| 3427 | | if (var->decl_node) { |
| 3428 | | gen_var_debug_decl(g, var); |
| 3429 | | } |
| 3430 | | *arg_index += 1; |
| 3431 | | return; |
| 3432 | | } |
| 3433 | | |
| 3434 | | if (g->zig_target.arch.arch == ZigLLVM_x86_64) { |
| 3435 | | assert(handle_is_ptr(ty)); |
| 3436 | | size_t ty_size = type_size(g, ty); |
| 3437 | | |
| 3438 | | if (ty->id == ZigTypeIdStruct || ty->id == ZigTypeIdUnion) { |
| 3439 | | // "If the size of an object is larger than four eightbytes, or it contains unaligned |
| 3440 | | // fields, it has class MEMORY" |
| 3441 | | if (ty_size > 32) { |
| 3442 | | if (var->decl_node) { |
| 3443 | | gen_var_debug_decl(g, var); |
| 3444 | | } |
| 3445 | | *arg_index += 1; |
| 3446 | | return; |
| 3447 | | } |
| 3448 | | } |
| 3449 | | if (ty->id == ZigTypeIdStruct) { |
| 3450 | | // "If the size of the aggregate exceeds a single eightbyte, each is classified |
| 3451 | | // separately. Each eightbyte gets initialized to class NO_CLASS." |
| 3452 | | if (ty_size <= 8) { |
| 3453 | | bool contains_int = false; |
| 3454 | | for (size_t i = 0; i < ty->data.structure.src_field_count; i += 1) { |
| 3455 | | if (type_is_c_abi_int(g, ty->data.structure.fields[i].type_entry)) { |
| 3456 | | contains_int = true; |
| 3457 | | break; |
| 3458 | | } |
| 3459 | | } |
| 3460 | | if (contains_int) { |
| 3461 | | clear_debug_source_node(g); |
| 3462 | | LLVMValueRef arg = LLVMGetParam(llvm_fn, *arg_index); |
| 3463 | | LLVMTypeRef ptr_to_int_type_ref = LLVMPointerType(LLVMIntType((unsigned)ty_size * 8), 0); |
| 3464 | | LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, var->value_ref, ptr_to_int_type_ref, ""); |
| 3465 | | gen_store_untyped(g, arg, bitcasted, var->align_bytes, false); |
| 3466 | | if (var->decl_node) { |
| 3467 | | gen_var_debug_decl(g, var); |
| 3468 | | } |
| 3469 | | *arg_index += 1; |
| 3470 | | return; |
| 3471 | | } |
| 3472 | | } |
| 3473 | | } |
| 3474 | | } |
| 3475 | | |
| 3476 | | give_up_with_c_abi_error(g, fn->proto_node); |
| 3477 | | } |
| 3478 | | |
| 3479 | 3468 | static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) { |
| 3480 | 3469 | LLVMValueRef fn_val; |
| 3481 | 3470 | ZigType *fn_type; |
| ... | ... | @@ -6289,12 +6278,12 @@ static void do_code_gen(CodeGen *g) { |
| 6289 | 6278 | ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base); |
| 6290 | 6279 | |
| 6291 | 6280 | // create debug variable declarations for variables and allocate all local variables |
| 6292 | | FnWalk fn_walk = {}; |
| 6293 | | fn_walk.id = FnWalkIdVars; |
| 6294 | | fn_walk.data.vars.import = import; |
| 6295 | | fn_walk.data.vars.fn = fn_table_entry; |
| 6296 | | fn_walk.data.vars.llvm_fn = fn; |
| 6297 | | fn_walk.data.vars.gen_i = 0; |
| 6281 | FnWalk fn_walk_var = {}; |
| 6282 | fn_walk_var.id = FnWalkIdVars; |
| 6283 | fn_walk_var.data.vars.import = import; |
| 6284 | fn_walk_var.data.vars.fn = fn_table_entry; |
| 6285 | fn_walk_var.data.vars.llvm_fn = fn; |
| 6286 | fn_walk_var.data.vars.gen_i = 0; |
| 6298 | 6287 | for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) { |
| 6299 | 6288 | ZigVar *var = fn_table_entry->variable_list.at(var_i); |
| 6300 | 6289 | |
| ... | ... | @@ -6314,8 +6303,8 @@ static void do_code_gen(CodeGen *g) { |
| 6314 | 6303 | var->value->type->di_type, !g->strip_debug_symbols, 0); |
| 6315 | 6304 | |
| 6316 | 6305 | } else if (is_c_abi) { |
| 6317 | | fn_walk.data.vars.var = var; |
| 6318 | | iter_function_params_c_abi(g, fn_table_entry->type_entry, &fn_walk, var->src_arg_index); |
| 6306 | fn_walk_var.data.vars.var = var; |
| 6307 | iter_function_params_c_abi(g, fn_table_entry->type_entry, &fn_walk_var, var->src_arg_index); |
| 6319 | 6308 | } else { |
| 6320 | 6309 | assert(var->gen_arg_index != SIZE_MAX); |
| 6321 | 6310 | ZigType *gen_type; |
| ... | ... | @@ -6367,40 +6356,13 @@ static void do_code_gen(CodeGen *g) { |
| 6367 | 6356 | gen_store(g, LLVMConstInt(usize->type_ref, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false)); |
| 6368 | 6357 | } |
| 6369 | 6358 | |
| 6370 | | FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id; |
| 6371 | | |
| 6372 | 6359 | // create debug variable declarations for parameters |
| 6373 | 6360 | // rely on the first variables in the variable_list being parameters. |
| 6374 | | size_t next_var_i = 0; |
| 6375 | | unsigned c_abi_arg_init_index = 0; |
| 6376 | | for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) { |
| 6377 | | if (is_c_abi) { |
| 6378 | | ZigVar *var = fn_table_entry->variable_list.at(param_i); |
| 6379 | | gen_c_abi_param_var_init(g, import, fn, fn_table_entry, var, &c_abi_arg_init_index); |
| 6380 | | continue; |
| 6381 | | } |
| 6382 | | |
| 6383 | | FnGenParamInfo *info = &fn_table_entry->type_entry->data.fn.gen_param_info[param_i]; |
| 6384 | | if (info->gen_index == SIZE_MAX) |
| 6385 | | continue; |
| 6386 | | |
| 6387 | | ZigVar *variable = fn_table_entry->variable_list.at(next_var_i); |
| 6388 | | assert(variable->src_arg_index != SIZE_MAX); |
| 6389 | | next_var_i += 1; |
| 6390 | | |
| 6391 | | assert(variable); |
| 6392 | | assert(variable->value_ref); |
| 6393 | | |
| 6394 | | if (!handle_is_ptr(variable->value->type)) { |
| 6395 | | clear_debug_source_node(g); |
| 6396 | | gen_store_untyped(g, LLVMGetParam(fn, (unsigned)variable->gen_arg_index), variable->value_ref, |
| 6397 | | variable->align_bytes, false); |
| 6398 | | } |
| 6399 | | |
| 6400 | | if (variable->decl_node) { |
| 6401 | | gen_var_debug_decl(g, variable); |
| 6402 | | } |
| 6403 | | } |
| 6361 | FnWalk fn_walk_init = {}; |
| 6362 | fn_walk_init.id = FnWalkIdInits; |
| 6363 | fn_walk_init.data.inits.fn = fn_table_entry; |
| 6364 | fn_walk_init.data.inits.llvm_fn = fn; |
| 6365 | walk_function_params(g, fn_table_entry->type_entry, &fn_walk_init); |
| 6404 | 6366 | |
| 6405 | 6367 | ir_render(g, fn_table_entry); |
| 6406 | 6368 | |