| ... | ... | @@ -3327,6 +3327,92 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) { |
| 3327 | 3327 | LLVMAddCallSiteAttribute(call_instr, 1, sret_attr); |
| 3328 | 3328 | } |
| 3329 | 3329 | |
| 3330 | static void render_async_spills(CodeGen *g) { |
| 3331 | ZigType *fn_type = g->cur_fn->type_entry; |
| 3332 | ZigType *import = get_scope_import(&g->cur_fn->fndef_scope->base); |
| 3333 | size_t async_var_index = coro_arg_start + (type_has_bits(fn_type->data.fn.fn_type_id.return_type) ? 2 : 0); |
| 3334 | for (size_t var_i = 0; var_i < g->cur_fn->variable_list.length; var_i += 1) { |
| 3335 | ZigVar *var = g->cur_fn->variable_list.at(var_i); |
| 3336 | |
| 3337 | if (!type_has_bits(var->var_type)) { |
| 3338 | continue; |
| 3339 | } |
| 3340 | if (ir_get_var_is_comptime(var)) |
| 3341 | continue; |
| 3342 | switch (type_requires_comptime(g, var->var_type)) { |
| 3343 | case ReqCompTimeInvalid: |
| 3344 | zig_unreachable(); |
| 3345 | case ReqCompTimeYes: |
| 3346 | continue; |
| 3347 | case ReqCompTimeNo: |
| 3348 | break; |
| 3349 | } |
| 3350 | if (var->src_arg_index == SIZE_MAX) { |
| 3351 | continue; |
| 3352 | } |
| 3353 | |
| 3354 | var->value_ref = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, async_var_index, |
| 3355 | buf_ptr(&var->name)); |
| 3356 | async_var_index += 1; |
| 3357 | if (var->decl_node) { |
| 3358 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), |
| 3359 | buf_ptr(&var->name), import->data.structure.root_struct->di_file, |
| 3360 | (unsigned)(var->decl_node->line + 1), |
| 3361 | get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0); |
| 3362 | gen_var_debug_decl(g, var); |
| 3363 | } |
| 3364 | } |
| 3365 | for (size_t alloca_i = 0; alloca_i < g->cur_fn->alloca_gen_list.length; alloca_i += 1) { |
| 3366 | IrInstructionAllocaGen *instruction = g->cur_fn->alloca_gen_list.at(alloca_i); |
| 3367 | ZigType *ptr_type = instruction->base.value.type; |
| 3368 | assert(ptr_type->id == ZigTypeIdPointer); |
| 3369 | ZigType *child_type = ptr_type->data.pointer.child_type; |
| 3370 | if (!type_has_bits(child_type)) |
| 3371 | continue; |
| 3372 | if (instruction->base.ref_count == 0) |
| 3373 | continue; |
| 3374 | if (instruction->base.value.special != ConstValSpecialRuntime) { |
| 3375 | if (const_ptr_pointee(nullptr, g, &instruction->base.value, nullptr)->special != |
| 3376 | ConstValSpecialRuntime) |
| 3377 | { |
| 3378 | continue; |
| 3379 | } |
| 3380 | } |
| 3381 | instruction->base.llvm_value = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, async_var_index, |
| 3382 | instruction->name_hint); |
| 3383 | async_var_index += 1; |
| 3384 | } |
| 3385 | } |
| 3386 | |
| 3387 | static void render_async_var_decls(CodeGen *g, Scope *scope) { |
| 3388 | render_async_spills(g); |
| 3389 | for (;;) { |
| 3390 | switch (scope->id) { |
| 3391 | case ScopeIdCImport: |
| 3392 | zig_unreachable(); |
| 3393 | case ScopeIdFnDef: |
| 3394 | return; |
| 3395 | case ScopeIdVarDecl: { |
| 3396 | ZigVar *var = reinterpret_cast<ScopeVarDecl *>(scope)->var; |
| 3397 | if (var->ptr_instruction != nullptr) { |
| 3398 | render_decl_var(g, var); |
| 3399 | } |
| 3400 | // fallthrough |
| 3401 | } |
| 3402 | case ScopeIdDecls: |
| 3403 | case ScopeIdBlock: |
| 3404 | case ScopeIdDefer: |
| 3405 | case ScopeIdDeferExpr: |
| 3406 | case ScopeIdLoop: |
| 3407 | case ScopeIdSuspend: |
| 3408 | case ScopeIdCompTime: |
| 3409 | case ScopeIdRuntime: |
| 3410 | scope = scope->parent; |
| 3411 | continue; |
| 3412 | } |
| 3413 | } |
| 3414 | } |
| 3415 | |
| 3330 | 3416 | static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCallGen *instruction) { |
| 3331 | 3417 | LLVMValueRef fn_val; |
| 3332 | 3418 | ZigType *fn_type; |
| ... | ... | @@ -3431,15 +3517,19 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3431 | 3517 | ZigLLVMBuildCall(g->builder, fn_val, &frame_result_loc, 1, llvm_cc, fn_inline, ""); |
| 3432 | 3518 | return nullptr; |
| 3433 | 3519 | } else if (callee_is_async) { |
| 3520 | LLVMValueRef split_llvm_fn = make_fn_llvm_value(g, g->cur_fn); |
| 3434 | 3521 | LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_fn_ptr_index, ""); |
| 3435 | | LLVMValueRef new_fn_ptr = instruction->resume_block->split_llvm_fn; |
| 3436 | | LLVMBuildStore(g->builder, new_fn_ptr, fn_ptr_ptr); |
| 3522 | LLVMBuildStore(g->builder, split_llvm_fn, fn_ptr_ptr); |
| 3437 | 3523 | |
| 3438 | 3524 | LLVMValueRef call_inst = ZigLLVMBuildCall(g->builder, fn_val, &frame_result_loc, 1, llvm_cc, fn_inline, ""); |
| 3439 | 3525 | ZigLLVMSetTailCall(call_inst); |
| 3440 | 3526 | LLVMBuildRetVoid(g->builder); |
| 3441 | 3527 | |
| 3442 | | LLVMPositionBuilderAtEnd(g->builder, instruction->resume_block->llvm_block); |
| 3528 | g->cur_fn_val = split_llvm_fn; |
| 3529 | g->cur_ret_ptr = LLVMGetParam(split_llvm_fn, 0); |
| 3530 | LLVMBasicBlockRef call_bb = LLVMAppendBasicBlock(split_llvm_fn, "CallResume"); |
| 3531 | LLVMPositionBuilderAtEnd(g->builder, call_bb); |
| 3532 | render_async_var_decls(g, instruction->base.scope); |
| 3443 | 3533 | return nullptr; |
| 3444 | 3534 | } |
| 3445 | 3535 | |
| ... | ... | @@ -5193,92 +5283,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5193 | 5283 | zig_unreachable(); |
| 5194 | 5284 | } |
| 5195 | 5285 | |
| 5196 | | static void render_async_spills(CodeGen *g) { |
| 5197 | | ZigType *fn_type = g->cur_fn->type_entry; |
| 5198 | | ZigType *import = get_scope_import(&g->cur_fn->fndef_scope->base); |
| 5199 | | size_t async_var_index = coro_arg_start + (type_has_bits(fn_type->data.fn.fn_type_id.return_type) ? 2 : 0); |
| 5200 | | for (size_t var_i = 0; var_i < g->cur_fn->variable_list.length; var_i += 1) { |
| 5201 | | ZigVar *var = g->cur_fn->variable_list.at(var_i); |
| 5202 | | |
| 5203 | | if (!type_has_bits(var->var_type)) { |
| 5204 | | continue; |
| 5205 | | } |
| 5206 | | if (ir_get_var_is_comptime(var)) |
| 5207 | | continue; |
| 5208 | | switch (type_requires_comptime(g, var->var_type)) { |
| 5209 | | case ReqCompTimeInvalid: |
| 5210 | | zig_unreachable(); |
| 5211 | | case ReqCompTimeYes: |
| 5212 | | continue; |
| 5213 | | case ReqCompTimeNo: |
| 5214 | | break; |
| 5215 | | } |
| 5216 | | if (var->src_arg_index == SIZE_MAX) { |
| 5217 | | continue; |
| 5218 | | } |
| 5219 | | |
| 5220 | | var->value_ref = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, async_var_index, |
| 5221 | | buf_ptr(&var->name)); |
| 5222 | | async_var_index += 1; |
| 5223 | | if (var->decl_node) { |
| 5224 | | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), |
| 5225 | | buf_ptr(&var->name), import->data.structure.root_struct->di_file, |
| 5226 | | (unsigned)(var->decl_node->line + 1), |
| 5227 | | get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0); |
| 5228 | | gen_var_debug_decl(g, var); |
| 5229 | | } |
| 5230 | | } |
| 5231 | | for (size_t alloca_i = 0; alloca_i < g->cur_fn->alloca_gen_list.length; alloca_i += 1) { |
| 5232 | | IrInstructionAllocaGen *instruction = g->cur_fn->alloca_gen_list.at(alloca_i); |
| 5233 | | ZigType *ptr_type = instruction->base.value.type; |
| 5234 | | assert(ptr_type->id == ZigTypeIdPointer); |
| 5235 | | ZigType *child_type = ptr_type->data.pointer.child_type; |
| 5236 | | if (!type_has_bits(child_type)) |
| 5237 | | continue; |
| 5238 | | if (instruction->base.ref_count == 0) |
| 5239 | | continue; |
| 5240 | | if (instruction->base.value.special != ConstValSpecialRuntime) { |
| 5241 | | if (const_ptr_pointee(nullptr, g, &instruction->base.value, nullptr)->special != |
| 5242 | | ConstValSpecialRuntime) |
| 5243 | | { |
| 5244 | | continue; |
| 5245 | | } |
| 5246 | | } |
| 5247 | | instruction->base.llvm_value = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, async_var_index, |
| 5248 | | instruction->name_hint); |
| 5249 | | async_var_index += 1; |
| 5250 | | } |
| 5251 | | } |
| 5252 | | |
| 5253 | | static void render_async_var_decls(CodeGen *g, Scope *scope) { |
| 5254 | | render_async_spills(g); |
| 5255 | | for (;;) { |
| 5256 | | switch (scope->id) { |
| 5257 | | case ScopeIdCImport: |
| 5258 | | zig_unreachable(); |
| 5259 | | case ScopeIdFnDef: |
| 5260 | | return; |
| 5261 | | case ScopeIdVarDecl: { |
| 5262 | | ZigVar *var = reinterpret_cast<ScopeVarDecl *>(scope)->var; |
| 5263 | | if (var->ptr_instruction != nullptr) { |
| 5264 | | render_decl_var(g, var); |
| 5265 | | } |
| 5266 | | // fallthrough |
| 5267 | | } |
| 5268 | | case ScopeIdDecls: |
| 5269 | | case ScopeIdBlock: |
| 5270 | | case ScopeIdDefer: |
| 5271 | | case ScopeIdDeferExpr: |
| 5272 | | case ScopeIdLoop: |
| 5273 | | case ScopeIdSuspend: |
| 5274 | | case ScopeIdCompTime: |
| 5275 | | case ScopeIdRuntime: |
| 5276 | | scope = scope->parent; |
| 5277 | | continue; |
| 5278 | | } |
| 5279 | | } |
| 5280 | | } |
| 5281 | | |
| 5282 | 5286 | static void ir_render(CodeGen *g, ZigFn *fn_entry) { |
| 5283 | 5287 | assert(fn_entry); |
| 5284 | 5288 | |