authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-01 16:41:30-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-01 16:41:30-04:00
log1dd0c3d49f929fc280d5bb4bbeed6538b50b2535
treed1a6bfbec914f33009c1c300c1f9a8b2efff1593
parente7ae4e4645a46a216c5913e2f9120cb02c10008c
signature Commit is signed but in an unrecognized format.

fix calling an inferred async function


5 files changed, 142 insertions(+), 148 deletions(-)

BRANCH_TODO-2
...@@ -1,5 +1,3 @@...@@ -1,5 +1,3 @@
1 * fix @frameSize
2 * fix calling an inferred async function
3 * await1 * await
4 * await of a non async function2 * await of a non async function
5 * await in single-threaded mode3 * await in single-threaded mode
src/all_types.hpp-1
...@@ -2605,7 +2605,6 @@ struct IrInstructionCallGen {...@@ -2605,7 +2605,6 @@ struct IrInstructionCallGen {
2605 IrInstruction **args;2605 IrInstruction **args;
2606 IrInstruction *result_loc;2606 IrInstruction *result_loc;
2607 IrInstruction *frame_result_loc;2607 IrInstruction *frame_result_loc;
2608 IrBasicBlock *resume_block;
26092608
2610 IrInstruction *new_stack;2609 IrInstruction *new_stack;
2611 FnInline fn_inline;2610 FnInline fn_inline;
src/analyze.cpp-7
...@@ -5185,13 +5185,6 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {...@@ -5185,13 +5185,6 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {
5185 if (!fn_is_async(callee))5185 if (!fn_is_async(callee))
5186 continue;5186 continue;
51875187
5188 IrBasicBlock *new_resume_block = allocate<IrBasicBlock>(1);
5189 new_resume_block->name_hint = "CallResume";
5190 new_resume_block->split_llvm_fn = reinterpret_cast<LLVMValueRef>(0x1);
5191 fn->resume_blocks.append(new_resume_block);
5192 call->resume_block = new_resume_block;
5193 fn->analyzed_executable.basic_block_list.append(new_resume_block);
5194
5195 ZigType *callee_frame_type = get_coro_frame_type(g, callee);5188 ZigType *callee_frame_type = get_coro_frame_type(g, callee);
51965189
5197 IrInstructionAllocaGen *alloca_gen = allocate<IrInstructionAllocaGen>(1);5190 IrInstructionAllocaGen *alloca_gen = allocate<IrInstructionAllocaGen>(1);
src/codegen.cpp+93-89
...@@ -3327,6 +3327,92 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) {...@@ -3327,6 +3327,92 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) {
3327 LLVMAddCallSiteAttribute(call_instr, 1, sret_attr);3327 LLVMAddCallSiteAttribute(call_instr, 1, sret_attr);
3328}3328}
33293329
3330static 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
3387static 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
3330static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCallGen *instruction) {3416static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCallGen *instruction) {
3331 LLVMValueRef fn_val;3417 LLVMValueRef fn_val;
3332 ZigType *fn_type;3418 ZigType *fn_type;
...@@ -3431,15 +3517,19 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3431,15 +3517,19 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3431 ZigLLVMBuildCall(g->builder, fn_val, &frame_result_loc, 1, llvm_cc, fn_inline, "");3517 ZigLLVMBuildCall(g->builder, fn_val, &frame_result_loc, 1, llvm_cc, fn_inline, "");
3432 return nullptr;3518 return nullptr;
3433 } else if (callee_is_async) {3519 } else if (callee_is_async) {
3520 LLVMValueRef split_llvm_fn = make_fn_llvm_value(g, g->cur_fn);
3434 LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_fn_ptr_index, "");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;3522 LLVMBuildStore(g->builder, split_llvm_fn, fn_ptr_ptr);
3436 LLVMBuildStore(g->builder, new_fn_ptr, fn_ptr_ptr);
34373523
3438 LLVMValueRef call_inst = ZigLLVMBuildCall(g->builder, fn_val, &frame_result_loc, 1, llvm_cc, fn_inline, "");3524 LLVMValueRef call_inst = ZigLLVMBuildCall(g->builder, fn_val, &frame_result_loc, 1, llvm_cc, fn_inline, "");
3439 ZigLLVMSetTailCall(call_inst);3525 ZigLLVMSetTailCall(call_inst);
3440 LLVMBuildRetVoid(g->builder);3526 LLVMBuildRetVoid(g->builder);
34413527
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 return nullptr;3533 return nullptr;
3444 }3534 }
34453535
...@@ -5193,92 +5283,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5193,92 +5283,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5193 zig_unreachable();5283 zig_unreachable();
5194}5284}
51955285
5196static 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
5253static 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
5282static void ir_render(CodeGen *g, ZigFn *fn_entry) {5286static void ir_render(CodeGen *g, ZigFn *fn_entry) {
5283 assert(fn_entry);5287 assert(fn_entry);
52845288
test/stage1/behavior/coroutines.zig+49-49
...@@ -82,55 +82,55 @@ test "local variable in async function" {...@@ -82,55 +82,55 @@ test "local variable in async function" {
82 S.doTheTest();82 S.doTheTest();
83}83}
8484
85//test "calling an inferred async function" {85test "calling an inferred async function" {
86// const S = struct {86 const S = struct {
87// var x: i32 = 1;87 var x: i32 = 1;
88// var other_frame: *@Frame(other) = undefined;88 var other_frame: *@Frame(other) = undefined;
89//89
90// fn doTheTest() void {90 fn doTheTest() void {
91// const p = async first();91 const p = async first();
92// expect(x == 1);92 expect(x == 1);
93// resume other_frame.*;93 resume other_frame.*;
94// expect(x == 2);94 expect(x == 2);
95// }95 }
96//96
97// fn first() void {97 fn first() void {
98// other();98 other();
99// }99 }
100// fn other() void {100 fn other() void {
101// other_frame = @frame();101 other_frame = @frame();
102// suspend;102 suspend;
103// x += 1;103 x += 1;
104// }104 }
105// };105 };
106// S.doTheTest();106 S.doTheTest();
107//}107}
108//108
109//test "@frameSize" {109test "@frameSize" {
110// const S = struct {110 const S = struct {
111// fn doTheTest() void {111 fn doTheTest() void {
112// {112 {
113// var ptr = @ptrCast(async fn(i32) void, other);113 var ptr = @ptrCast(async fn(i32) void, other);
114// const size = @frameSize(ptr);114 const size = @frameSize(ptr);
115// expect(size == @sizeOf(@Frame(other)));115 expect(size == @sizeOf(@Frame(other)));
116// }116 }
117// {117 {
118// var ptr = @ptrCast(async fn() void, first);118 var ptr = @ptrCast(async fn() void, first);
119// const size = @frameSize(ptr);119 const size = @frameSize(ptr);
120// expect(size == @sizeOf(@Frame(first)));120 expect(size == @sizeOf(@Frame(first)));
121// }121 }
122// }122 }
123//123
124// fn first() void {124 fn first() void {
125// other(1);125 other(1);
126// }126 }
127// fn other(param: i32) void {127 fn other(param: i32) void {
128// var local: i32 = undefined;128 var local: i32 = undefined;
129// suspend;129 suspend;
130// }130 }
131// };131 };
132// S.doTheTest();132 S.doTheTest();
133//}133}
134134
135//test "coroutine suspend, resume" {135//test "coroutine suspend, resume" {
136// seq('a');136// seq('a');