| ... | @@ -1954,6 +1954,15 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ | ... | @@ -1954,6 +1954,15 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 1954 | source_node = var->decl_node; | 1954 | source_node = var->decl_node; |
| 1955 | llvm_fn = fn_walk->data.vars.llvm_fn; | 1955 | llvm_fn = fn_walk->data.vars.llvm_fn; |
| 1956 | break; | 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 | if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat || | 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,6 +1999,14 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 1990 | dest_ty = ty; | 1999 | dest_ty = ty; |
| 1991 | goto var_ok; | 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 | return true; | 2011 | return true; |
| 1995 | } | 2012 | } |
| ... | @@ -2018,6 +2035,12 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ | ... | @@ -2018,6 +2035,12 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 2018 | fn_walk->data.vars.gen_i += 1; | 2035 | fn_walk->data.vars.gen_i += 1; |
| 2019 | goto var_ok; | 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 | return true; | 2045 | return true; |
| 2023 | } | 2046 | } |
| ... | @@ -2052,6 +2075,12 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ | ... | @@ -2052,6 +2075,12 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 2052 | fn_walk->data.vars.gen_i += 1; | 2075 | fn_walk->data.vars.gen_i += 1; |
| 2053 | goto var_ok; | 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 | return true; | 2085 | return true; |
| 2057 | } | 2086 | } |
| ... | @@ -2092,6 +2121,18 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ | ... | @@ -2092,6 +2121,18 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 2092 | fn_walk->data.vars.gen_i += 1; | 2121 | fn_walk->data.vars.gen_i += 1; |
| 2093 | goto var_ok; | 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 | return true; | 2137 | return true; |
| 2097 | } | 2138 | } |
| ... | @@ -2140,6 +2181,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) { | ... | @@ -2140,6 +2181,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) { |
| 2140 | } | 2181 | } |
| 2141 | return; | 2182 | return; |
| 2142 | } | 2183 | } |
| | 2184 | size_t next_var_i = 0; |
| 2143 | for (size_t param_i = 0; param_i < fn_type->data.fn.fn_type_id.param_count; param_i += 1) { | 2185 | for (size_t param_i = 0; param_i < fn_type->data.fn.fn_type_id.param_count; param_i += 1) { |
| 2144 | FnGenParamInfo *gen_info = &fn_type->data.fn.gen_param_info[param_i]; | 2186 | FnGenParamInfo *gen_info = &fn_type->data.fn.gen_param_info[param_i]; |
| 2145 | size_t gen_index = gen_info->gen_index; | 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,6 +2208,27 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) { |
| 2166 | } | 2208 | } |
| 2167 | break; | 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 | case FnWalkIdCall: | 2232 | case FnWalkIdCall: |
| 2170 | // handled before for loop | 2233 | // handled before for loop |
| 2171 | zig_unreachable(); | 2234 | zig_unreachable(); |
| ... | @@ -3402,80 +3465,6 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) { | ... | @@ -3402,80 +3465,6 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) { |
| 3402 | LLVMAddCallSiteAttribute(call_instr, 1, sret_attr); | 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 | static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) { | 3468 | static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) { |
| 3480 | LLVMValueRef fn_val; | 3469 | LLVMValueRef fn_val; |
| 3481 | ZigType *fn_type; | 3470 | ZigType *fn_type; |
| ... | @@ -6289,12 +6278,12 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6289,12 +6278,12 @@ static void do_code_gen(CodeGen *g) { |
| 6289 | ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base); | 6278 | ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base); |
| 6290 | | 6279 | |
| 6291 | // create debug variable declarations for variables and allocate all local variables | 6280 | // create debug variable declarations for variables and allocate all local variables |
| 6292 | FnWalk fn_walk = {}; | 6281 | FnWalk fn_walk_var = {}; |
| 6293 | fn_walk.id = FnWalkIdVars; | 6282 | fn_walk_var.id = FnWalkIdVars; |
| 6294 | fn_walk.data.vars.import = import; | 6283 | fn_walk_var.data.vars.import = import; |
| 6295 | fn_walk.data.vars.fn = fn_table_entry; | 6284 | fn_walk_var.data.vars.fn = fn_table_entry; |
| 6296 | fn_walk.data.vars.llvm_fn = fn; | 6285 | fn_walk_var.data.vars.llvm_fn = fn; |
| 6297 | fn_walk.data.vars.gen_i = 0; | 6286 | fn_walk_var.data.vars.gen_i = 0; |
| 6298 | for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) { | 6287 | for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) { |
| 6299 | ZigVar *var = fn_table_entry->variable_list.at(var_i); | 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,8 +6303,8 @@ static void do_code_gen(CodeGen *g) { |
| 6314 | var->value->type->di_type, !g->strip_debug_symbols, 0); | 6303 | var->value->type->di_type, !g->strip_debug_symbols, 0); |
| 6315 | | 6304 | |
| 6316 | } else if (is_c_abi) { | 6305 | } else if (is_c_abi) { |
| 6317 | fn_walk.data.vars.var = var; | 6306 | fn_walk_var.data.vars.var = var; |
| 6318 | iter_function_params_c_abi(g, fn_table_entry->type_entry, &fn_walk, var->src_arg_index); | 6307 | iter_function_params_c_abi(g, fn_table_entry->type_entry, &fn_walk_var, var->src_arg_index); |
| 6319 | } else { | 6308 | } else { |
| 6320 | assert(var->gen_arg_index != SIZE_MAX); | 6309 | assert(var->gen_arg_index != SIZE_MAX); |
| 6321 | ZigType *gen_type; | 6310 | ZigType *gen_type; |
| ... | @@ -6367,40 +6356,13 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6367,40 +6356,13 @@ static void do_code_gen(CodeGen *g) { |
| 6367 | gen_store(g, LLVMConstInt(usize->type_ref, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false)); | 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 | // create debug variable declarations for parameters | 6359 | // create debug variable declarations for parameters |
| 6373 | // rely on the first variables in the variable_list being parameters. | 6360 | // rely on the first variables in the variable_list being parameters. |
| 6374 | size_t next_var_i = 0; | 6361 | FnWalk fn_walk_init = {}; |
| 6375 | unsigned c_abi_arg_init_index = 0; | 6362 | fn_walk_init.id = FnWalkIdInits; |
| 6376 | for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) { | 6363 | fn_walk_init.data.inits.fn = fn_table_entry; |
| 6377 | if (is_c_abi) { | 6364 | fn_walk_init.data.inits.llvm_fn = fn; |
| 6378 | ZigVar *var = fn_table_entry->variable_list.at(param_i); | 6365 | walk_function_params(g, fn_table_entry->type_entry, &fn_walk_init); |
| 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 | } | | |
| 6404 | | 6366 | |
| 6405 | ir_render(g, fn_table_entry); | 6367 | ir_render(g, fn_table_entry); |
| 6406 | | 6368 | |