| ... | @@ -343,22 +343,54 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { | ... | @@ -343,22 +343,54 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { |
| 343 | zig_unreachable(); | 343 | zig_unreachable(); |
| 344 | } | 344 | } |
| 345 | | 345 | |
| | 346 | struct CalcLLVMFieldIndex { |
| | 347 | uint32_t offset; |
| | 348 | uint32_t field_index; |
| | 349 | }; |
| | 350 | |
| | 351 | static void calc_llvm_field_index_add(CodeGen *g, CalcLLVMFieldIndex *calc, ZigType *ty) { |
| | 352 | if (!type_has_bits(ty)) return; |
| | 353 | uint32_t ty_align = get_abi_alignment(g, ty); |
| | 354 | if (calc->offset % ty_align != 0) { |
| | 355 | uint32_t llvm_align = LLVMABIAlignmentOfType(g->target_data_ref, get_llvm_type(g, ty)); |
| | 356 | if (llvm_align >= ty_align) { |
| | 357 | ty_align = llvm_align; // llvm's padding is sufficient |
| | 358 | } else if (calc->offset) { |
| | 359 | calc->field_index += 1; // zig will insert an extra padding field here |
| | 360 | } |
| | 361 | calc->offset += ty_align - (calc->offset % ty_align); // padding bytes |
| | 362 | } |
| | 363 | calc->offset += ty->abi_size; |
| | 364 | calc->field_index += 1; |
| | 365 | } |
| | 366 | |
| 346 | // label (grep this): [fn_frame_struct_layout] | 367 | // label (grep this): [fn_frame_struct_layout] |
| | 368 | static void frame_index_trace_arg_calc(CodeGen *g, CalcLLVMFieldIndex *calc, ZigType *return_type) { |
| | 369 | calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // function pointer |
| | 370 | calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // resume index |
| | 371 | calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // awaiter index |
| | 372 | |
| | 373 | if (type_has_bits(return_type)) { |
| | 374 | calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // *ReturnType (callee's) |
| | 375 | calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // *ReturnType (awaiter's) |
| | 376 | calc_llvm_field_index_add(g, calc, return_type); // ReturnType |
| | 377 | } |
| | 378 | } |
| | 379 | |
| 347 | static uint32_t frame_index_trace_arg(CodeGen *g, ZigType *return_type) { | 380 | static uint32_t frame_index_trace_arg(CodeGen *g, ZigType *return_type) { |
| 348 | // [0] *ReturnType (callee's) | 381 | CalcLLVMFieldIndex calc = {0}; |
| 349 | // [1] *ReturnType (awaiter's) | 382 | frame_index_trace_arg_calc(g, &calc, return_type); |
| 350 | // [2] ReturnType | 383 | return calc.field_index; |
| 351 | uint32_t return_field_count = type_has_bits(return_type) ? 3 : 0; | | |
| 352 | return frame_ret_start + return_field_count; | | |
| 353 | } | 384 | } |
| 354 | | 385 | |
| 355 | // label (grep this): [fn_frame_struct_layout] | 386 | // label (grep this): [fn_frame_struct_layout] |
| 356 | static uint32_t frame_index_arg(CodeGen *g, ZigType *return_type) { | 387 | static void frame_index_arg_calc(CodeGen *g, CalcLLVMFieldIndex *calc, ZigType *return_type) { |
| 357 | bool have_stack_trace = codegen_fn_has_err_ret_tracing_arg(g, return_type); | 388 | frame_index_trace_arg_calc(g, calc, return_type); |
| 358 | // [0] *StackTrace (callee's) | 389 | |
| 359 | // [1] *StackTrace (awaiter's) | 390 | if (codegen_fn_has_err_ret_tracing_arg(g, return_type)) { |
| 360 | uint32_t trace_field_count = have_stack_trace ? 2 : 0; | 391 | calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // *StackTrace (callee's) |
| 361 | return frame_index_trace_arg(g, return_type) + trace_field_count; | 392 | calc_llvm_field_index_add(g, calc, g->builtin_types.entry_usize); // *StackTrace (awaiter's) |
| | 393 | } |
| 362 | } | 394 | } |
| 363 | | 395 | |
| 364 | // label (grep this): [fn_frame_struct_layout] | 396 | // label (grep this): [fn_frame_struct_layout] |
| ... | @@ -3922,7 +3954,9 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) { | ... | @@ -3922,7 +3954,9 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) { |
| 3922 | static void render_async_spills(CodeGen *g) { | 3954 | static void render_async_spills(CodeGen *g) { |
| 3923 | ZigType *fn_type = g->cur_fn->type_entry; | 3955 | ZigType *fn_type = g->cur_fn->type_entry; |
| 3924 | ZigType *import = get_scope_import(&g->cur_fn->fndef_scope->base); | 3956 | ZigType *import = get_scope_import(&g->cur_fn->fndef_scope->base); |
| 3925 | uint32_t async_var_index = frame_index_arg(g, fn_type->data.fn.fn_type_id.return_type); | 3957 | |
| | 3958 | CalcLLVMFieldIndex arg_calc = {0}; |
| | 3959 | frame_index_arg_calc(g, &arg_calc, fn_type->data.fn.fn_type_id.return_type); |
| 3926 | for (size_t var_i = 0; var_i < g->cur_fn->variable_list.length; var_i += 1) { | 3960 | for (size_t var_i = 0; var_i < g->cur_fn->variable_list.length; var_i += 1) { |
| 3927 | ZigVar *var = g->cur_fn->variable_list.at(var_i); | 3961 | ZigVar *var = g->cur_fn->variable_list.at(var_i); |
| 3928 | | 3962 | |
| ... | @@ -3943,8 +3977,8 @@ static void render_async_spills(CodeGen *g) { | ... | @@ -3943,8 +3977,8 @@ static void render_async_spills(CodeGen *g) { |
| 3943 | continue; | 3977 | continue; |
| 3944 | } | 3978 | } |
| 3945 | | 3979 | |
| 3946 | var->value_ref = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, async_var_index, var->name); | 3980 | calc_llvm_field_index_add(g, &arg_calc, var->var_type); |
| 3947 | async_var_index += 1; | 3981 | var->value_ref = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, arg_calc.field_index - 1, var->name); |
| 3948 | if (var->decl_node) { | 3982 | if (var->decl_node) { |
| 3949 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), | 3983 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), |
| 3950 | var->name, import->data.structure.root_struct->di_file, | 3984 | var->name, import->data.structure.root_struct->di_file, |
| ... | @@ -4267,17 +4301,35 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn | ... | @@ -4267,17 +4301,35 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn |
| 4267 | LLVMValueRef result; | 4301 | LLVMValueRef result; |
| 4268 | | 4302 | |
| 4269 | if (callee_is_async) { | 4303 | if (callee_is_async) { |
| 4270 | uint32_t arg_start_i = frame_index_arg(g, fn_type->data.fn.fn_type_id.return_type); | 4304 | CalcLLVMFieldIndex arg_calc_start = {0}; |
| | 4305 | frame_index_arg_calc(g, &arg_calc_start, fn_type->data.fn.fn_type_id.return_type); |
| 4271 | | 4306 | |
| 4272 | LLVMValueRef casted_frame; | 4307 | LLVMValueRef casted_frame; |
| 4273 | if (instruction->new_stack != nullptr && instruction->fn_entry == nullptr) { | 4308 | if (instruction->new_stack != nullptr && instruction->fn_entry == nullptr) { |
| 4274 | // We need the frame type to be a pointer to a struct that includes the args | 4309 | // We need the frame type to be a pointer to a struct that includes the args |
| 4275 | size_t field_count = arg_start_i + gen_param_values.length; | 4310 | |
| | 4311 | // Count ahead to determine how many llvm struct fields we need. |
| | 4312 | CalcLLVMFieldIndex arg_calc = arg_calc_start; |
| | 4313 | for (size_t i = 0; i < gen_param_types.length; i += 1) { |
| | 4314 | calc_llvm_field_index_add(g, &arg_calc, gen_param_types.at(i)); |
| | 4315 | } |
| | 4316 | size_t field_count = arg_calc.field_index; |
| | 4317 | |
| 4276 | LLVMTypeRef *field_types = allocate_nonzero<LLVMTypeRef>(field_count); | 4318 | LLVMTypeRef *field_types = allocate_nonzero<LLVMTypeRef>(field_count); |
| 4277 | LLVMGetStructElementTypes(LLVMGetElementType(LLVMTypeOf(frame_result_loc)), field_types); | 4319 | LLVMGetStructElementTypes(LLVMGetElementType(LLVMTypeOf(frame_result_loc)), field_types); |
| 4278 | assert(LLVMCountStructElementTypes(LLVMGetElementType(LLVMTypeOf(frame_result_loc))) == arg_start_i); | 4320 | assert(LLVMCountStructElementTypes(LLVMGetElementType(LLVMTypeOf(frame_result_loc))) == arg_calc_start.field_index); |
| | 4321 | |
| | 4322 | arg_calc = arg_calc_start; |
| 4279 | for (size_t arg_i = 0; arg_i < gen_param_values.length; arg_i += 1) { | 4323 | for (size_t arg_i = 0; arg_i < gen_param_values.length; arg_i += 1) { |
| 4280 | field_types[arg_start_i + arg_i] = LLVMTypeOf(gen_param_values.at(arg_i)); | 4324 | CalcLLVMFieldIndex prev = arg_calc; |
| | 4325 | calc_llvm_field_index_add(g, &arg_calc, gen_param_types.at(arg_i)); |
| | 4326 | field_types[arg_calc.field_index - 1] = LLVMTypeOf(gen_param_values.at(arg_i)); |
| | 4327 | if (arg_calc.field_index - prev.field_index > 1) { |
| | 4328 | // Padding field |
| | 4329 | uint32_t pad_bytes = arg_calc.offset - prev.offset - gen_param_types.at(arg_i)->abi_size; |
| | 4330 | LLVMTypeRef pad_llvm_type = LLVMArrayType(LLVMInt8Type(), pad_bytes); |
| | 4331 | field_types[arg_calc.field_index - 2] = pad_llvm_type; |
| | 4332 | } |
| 4281 | } | 4333 | } |
| 4282 | LLVMTypeRef frame_with_args_type = LLVMStructType(field_types, field_count, false); | 4334 | LLVMTypeRef frame_with_args_type = LLVMStructType(field_types, field_count, false); |
| 4283 | LLVMTypeRef ptr_frame_with_args_type = LLVMPointerType(frame_with_args_type, 0); | 4335 | LLVMTypeRef ptr_frame_with_args_type = LLVMPointerType(frame_with_args_type, 0); |
| ... | @@ -4287,8 +4339,10 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn | ... | @@ -4287,8 +4339,10 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn |
| 4287 | casted_frame = frame_result_loc; | 4339 | casted_frame = frame_result_loc; |
| 4288 | } | 4340 | } |
| 4289 | | 4341 | |
| | 4342 | CalcLLVMFieldIndex arg_calc = arg_calc_start; |
| 4290 | for (size_t arg_i = 0; arg_i < gen_param_values.length; arg_i += 1) { | 4343 | for (size_t arg_i = 0; arg_i < gen_param_values.length; arg_i += 1) { |
| 4291 | LLVMValueRef arg_ptr = LLVMBuildStructGEP(g->builder, casted_frame, arg_start_i + arg_i, ""); | 4344 | calc_llvm_field_index_add(g, &arg_calc, gen_param_types.at(arg_i)); |
| | 4345 | LLVMValueRef arg_ptr = LLVMBuildStructGEP(g->builder, casted_frame, arg_calc.field_index - 1, ""); |
| 4292 | gen_assign_raw(g, arg_ptr, get_pointer_to_type(g, gen_param_types.at(arg_i), true), | 4346 | gen_assign_raw(g, arg_ptr, get_pointer_to_type(g, gen_param_types.at(arg_i), true), |
| 4293 | gen_param_values.at(arg_i)); | 4347 | gen_param_values.at(arg_i)); |
| 4294 | } | 4348 | } |