| author | |
| committer | |
| log | eefcd044628ea080d8fe3346ae4d01e8ed4008e6 |
| tree | e7d81544fc762133e142146515bfc477d7ec0580 |
| parent | 50b70bd77f31bba6ffca33b6acb90186e739118e |
3 files changed, 39 insertions(+), 21 deletions(-)
src/ir.cpp+10-5| ... | ... | @@ -6260,7 +6260,7 @@ static IrInstSrc *ir_gen_async_call(IrBuilderSrc *irb, Scope *scope, AstNode *aw |
| 6260 | 6260 | if (args == irb->codegen->invalid_inst_src) |
| 6261 | 6261 | return args; |
| 6262 | 6262 | |
| 6263 | IrInstSrc *call = ir_build_async_call_extra(irb, scope, call_node, modifier, fn_ref, bytes, ret_ptr, args, result_loc); | |
| 6263 | IrInstSrc *call = ir_build_async_call_extra(irb, scope, call_node, modifier, fn_ref, ret_ptr, bytes, args, result_loc); | |
| 6264 | 6264 | return ir_lval_wrap(irb, scope, call, lval, result_loc); |
| 6265 | 6265 | } |
| 6266 | 6266 | |
| ... | ... | @@ -20277,7 +20277,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, |
| 20277 | 20277 | // Fork a scope of the function with known values for the parameters. |
| 20278 | 20278 | Scope *parent_scope = fn_entry->fndef_scope->base.parent; |
| 20279 | 20279 | ZigFn *impl_fn = create_fn(ira->codegen, fn_proto_node); |
| 20280 | ||
| 20280 | impl_fn->param_source_nodes = heap::c_allocator.allocate<AstNode *>(new_fn_arg_count); | |
| 20281 | 20281 | buf_init_from_buf(&impl_fn->symbol_name, &fn_entry->symbol_name); |
| 20282 | 20282 | impl_fn->fndef_scope = create_fndef_scope(ira->codegen, impl_fn->body_node, parent_scope, impl_fn); |
| 20283 | 20283 | impl_fn->child_scope = &impl_fn->fndef_scope->base; |
| ... | ... | @@ -20772,11 +20772,17 @@ static IrInstGen *ir_analyze_async_call_extra(IrAnalyze *ira, IrInst* source_ins |
| 20772 | 20772 | return ira->codegen->invalid_inst_gen; |
| 20773 | 20773 | } |
| 20774 | 20774 | |
| 20775 | IrInstGen *first_arg_ptr = nullptr; | |
| 20776 | IrInst *first_arg_ptr_src = nullptr; | |
| 20775 | 20777 | ZigFn *fn = nullptr; |
| 20776 | 20778 | if (instr_is_comptime(fn_ref)) { |
| 20777 | 20779 | if (fn_ref->value->type->id == ZigTypeIdBoundFn) { |
| 20778 | 20780 | assert(fn_ref->value->special == ConstValSpecialStatic); |
| 20779 | 20781 | fn = fn_ref->value->data.x_bound_fn.fn; |
| 20782 | first_arg_ptr = fn_ref->value->data.x_bound_fn.first_arg; | |
| 20783 | first_arg_ptr_src = fn_ref->value->data.x_bound_fn.first_arg_src; | |
| 20784 | if (type_is_invalid(first_arg_ptr->value->type)) | |
| 20785 | return ira->codegen->invalid_inst_gen; | |
| 20780 | 20786 | } else { |
| 20781 | 20787 | fn = ir_resolve_fn(ira, fn_ref); |
| 20782 | 20788 | } |
| ... | ... | @@ -20795,9 +20801,8 @@ static IrInstGen *ir_analyze_async_call_extra(IrAnalyze *ira, IrInst* source_ins |
| 20795 | 20801 | if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type)) |
| 20796 | 20802 | return ira->codegen->invalid_inst_gen; |
| 20797 | 20803 | |
| 20798 | IrInstGen *result = ir_analyze_async_call(ira, source_instr, fn, fn_type, fn_ref, args_ptr, args_len, | |
| 20799 | casted_new_stack, true, ret_ptr_uncasted, result_loc); | |
| 20800 | return ir_finish_anal(ira, result); | |
| 20804 | return ir_analyze_fn_call(ira, source_instr, fn, fn_type, fn_ref, first_arg_ptr, first_arg_ptr_src, | |
| 20805 | modifier, casted_new_stack, &new_stack->base, true, args_ptr, args_len, ret_ptr_uncasted, result_loc); | |
| 20801 | 20806 | } |
| 20802 | 20807 | |
| 20803 | 20808 | static bool ir_extract_tuple_call_args(IrAnalyze *ira, IrInst *source_instr, IrInstGen *args, IrInstGen ***args_ptr, size_t *args_len) { |
test/compile_errors.zig+16-3| ... | ... | @@ -1144,13 +1144,26 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 1144 | 1144 | "tmp.zig:2:15: error: @Type not available for 'TypeInfo.Struct'", |
| 1145 | 1145 | }); |
| 1146 | 1146 | |
| 1147 | cases.add("wrong type for argument tuple to @asyncCall", | |
| 1148 | \\export fn entry1() void { | |
| 1149 | \\ var frame: @Frame(foo) = undefined; | |
| 1150 | \\ @asyncCall(&frame, {}, foo, {}); | |
| 1151 | \\} | |
| 1152 | \\ | |
| 1153 | \\fn foo() i32 { | |
| 1154 | \\ return 0; | |
| 1155 | \\} | |
| 1156 | , &[_][]const u8{ | |
| 1157 | "tmp.zig:3:33: error: expected tuple or struct, found 'void'", | |
| 1158 | }); | |
| 1159 | ||
| 1147 | 1160 | cases.add("wrong type for result ptr to @asyncCall", |
| 1148 | 1161 | \\export fn entry() void { |
| 1149 | 1162 | \\ _ = async amain(); |
| 1150 | 1163 | \\} |
| 1151 | 1164 | \\fn amain() i32 { |
| 1152 | 1165 | \\ var frame: @Frame(foo) = undefined; |
| 1153 | \\ return await @asyncCall(&frame, false, foo); | |
| 1166 | \\ return await @asyncCall(&frame, false, foo, .{}); | |
| 1154 | 1167 | \\} |
| 1155 | 1168 | \\fn foo() i32 { |
| 1156 | 1169 | \\ return 1234; |
| ... | ... | @@ -1291,7 +1304,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 1291 | 1304 | \\export fn entry() void { |
| 1292 | 1305 | \\ var ptr: fn () callconv(.Async) void = func; |
| 1293 | 1306 | \\ var bytes: [64]u8 = undefined; |
| 1294 | \\ _ = @asyncCall(&bytes, {}, ptr); | |
| 1307 | \\ _ = @asyncCall(&bytes, {}, ptr, .{}); | |
| 1295 | 1308 | \\} |
| 1296 | 1309 | \\fn func() callconv(.Async) void {} |
| 1297 | 1310 | , &[_][]const u8{ |
| ... | ... | @@ -1467,7 +1480,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 1467 | 1480 | \\export fn entry() void { |
| 1468 | 1481 | \\ var ptr = afunc; |
| 1469 | 1482 | \\ var bytes: [100]u8 align(16) = undefined; |
| 1470 | \\ _ = @asyncCall(&bytes, {}, ptr); | |
| 1483 | \\ _ = @asyncCall(&bytes, {}, ptr, .{}); | |
| 1471 | 1484 | \\} |
| 1472 | 1485 | \\fn afunc() void { } |
| 1473 | 1486 | , &[_][]const u8{ |
test/stage1/behavior/async_fn.zig+13-13| ... | ... | @@ -282,7 +282,7 @@ test "async fn pointer in a struct field" { |
| 282 | 282 | }; |
| 283 | 283 | var foo = Foo{ .bar = simpleAsyncFn2 }; |
| 284 | 284 | var bytes: [64]u8 align(16) = undefined; |
| 285 | const f = @asyncCall(&bytes, {}, foo.bar, &data); | |
| 285 | const f = @asyncCall(&bytes, {}, foo.bar, .{&data}); | |
| 286 | 286 | comptime expect(@TypeOf(f) == anyframe->void); |
| 287 | 287 | expect(data == 2); |
| 288 | 288 | resume f; |
| ... | ... | @@ -318,7 +318,7 @@ test "@asyncCall with return type" { |
| 318 | 318 | var foo = Foo{ .bar = Foo.middle }; |
| 319 | 319 | var bytes: [150]u8 align(16) = undefined; |
| 320 | 320 | var aresult: i32 = 0; |
| 321 | _ = @asyncCall(&bytes, &aresult, foo.bar); | |
| 321 | _ = @asyncCall(&bytes, &aresult, foo.bar, .{}); | |
| 322 | 322 | expect(aresult == 0); |
| 323 | 323 | resume Foo.global_frame; |
| 324 | 324 | expect(aresult == 1234); |
| ... | ... | @@ -332,7 +332,7 @@ test "async fn with inferred error set" { |
| 332 | 332 | var frame: [1]@Frame(middle) = undefined; |
| 333 | 333 | var fn_ptr = middle; |
| 334 | 334 | var result: @TypeOf(fn_ptr).ReturnType.ErrorSet!void = undefined; |
| 335 | _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, fn_ptr); | |
| 335 | _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, fn_ptr, .{}); | |
| 336 | 336 | resume global_frame; |
| 337 | 337 | std.testing.expectError(error.Fail, result); |
| 338 | 338 | } |
| ... | ... | @@ -827,7 +827,7 @@ test "cast fn to async fn when it is inferred to be async" { |
| 827 | 827 | ptr = func; |
| 828 | 828 | var buf: [100]u8 align(16) = undefined; |
| 829 | 829 | var result: i32 = undefined; |
| 830 | const f = @asyncCall(&buf, &result, ptr); | |
| 830 | const f = @asyncCall(&buf, &result, ptr, .{}); | |
| 831 | 831 | _ = await f; |
| 832 | 832 | expect(result == 1234); |
| 833 | 833 | ok = true; |
| ... | ... | @@ -855,7 +855,7 @@ test "cast fn to async fn when it is inferred to be async, awaited directly" { |
| 855 | 855 | ptr = func; |
| 856 | 856 | var buf: [100]u8 align(16) = undefined; |
| 857 | 857 | var result: i32 = undefined; |
| 858 | _ = await @asyncCall(&buf, &result, ptr); | |
| 858 | _ = await @asyncCall(&buf, &result, ptr, .{}); | |
| 859 | 859 | expect(result == 1234); |
| 860 | 860 | ok = true; |
| 861 | 861 | } |
| ... | ... | @@ -951,7 +951,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" { |
| 951 | 951 | fn doTheTest() void { |
| 952 | 952 | var frame: [1]@Frame(middle) = undefined; |
| 953 | 953 | var result: @TypeOf(middle).ReturnType.ErrorSet!void = undefined; |
| 954 | _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, middle); | |
| 954 | _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, middle, .{}); | |
| 955 | 955 | resume global_frame; |
| 956 | 956 | std.testing.expectError(error.Fail, result); |
| 957 | 957 | } |
| ... | ... | @@ -982,7 +982,7 @@ test "@asyncCall with actual frame instead of byte buffer" { |
| 982 | 982 | }; |
| 983 | 983 | var frame: @Frame(S.func) = undefined; |
| 984 | 984 | var result: i32 = undefined; |
| 985 | const ptr = @asyncCall(&frame, &result, S.func); | |
| 985 | const ptr = @asyncCall(&frame, &result, S.func, .{}); | |
| 986 | 986 | resume ptr; |
| 987 | 987 | expect(result == 1234); |
| 988 | 988 | } |
| ... | ... | @@ -1005,7 +1005,7 @@ test "@asyncCall using the result location inside the frame" { |
| 1005 | 1005 | }; |
| 1006 | 1006 | var foo = Foo{ .bar = S.simple2 }; |
| 1007 | 1007 | var bytes: [64]u8 align(16) = undefined; |
| 1008 | const f = @asyncCall(&bytes, {}, foo.bar, &data); | |
| 1008 | const f = @asyncCall(&bytes, {}, foo.bar, .{&data}); | |
| 1009 | 1009 | comptime expect(@TypeOf(f) == anyframe->i32); |
| 1010 | 1010 | expect(data == 2); |
| 1011 | 1011 | resume f; |
| ... | ... | @@ -1042,7 +1042,7 @@ test "using @TypeOf on a generic function call" { |
| 1042 | 1042 | } |
| 1043 | 1043 | const F = @TypeOf(async amain(x - 1)); |
| 1044 | 1044 | const frame = @intToPtr(*F, @ptrToInt(&buf)); |
| 1045 | return await @asyncCall(frame, {}, amain, x - 1); | |
| 1045 | return await @asyncCall(frame, {}, amain, .{x - 1}); | |
| 1046 | 1046 | } |
| 1047 | 1047 | }; |
| 1048 | 1048 | _ = async S.amain(@as(u32, 1)); |
| ... | ... | @@ -1067,7 +1067,7 @@ test "recursive call of await @asyncCall with struct return type" { |
| 1067 | 1067 | } |
| 1068 | 1068 | const F = @TypeOf(async amain(x - 1)); |
| 1069 | 1069 | const frame = @intToPtr(*F, @ptrToInt(&buf)); |
| 1070 | return await @asyncCall(frame, {}, amain, x - 1); | |
| 1070 | return await @asyncCall(frame, {}, amain, .{x - 1}); | |
| 1071 | 1071 | } |
| 1072 | 1072 | |
| 1073 | 1073 | const Foo = struct { |
| ... | ... | @@ -1078,7 +1078,7 @@ test "recursive call of await @asyncCall with struct return type" { |
| 1078 | 1078 | }; |
| 1079 | 1079 | var res: S.Foo = undefined; |
| 1080 | 1080 | var frame: @TypeOf(async S.amain(@as(u32, 1))) = undefined; |
| 1081 | _ = @asyncCall(&frame, &res, S.amain, @as(u32, 1)); | |
| 1081 | _ = @asyncCall(&frame, &res, S.amain, .{@as(u32, 1)}); | |
| 1082 | 1082 | resume S.global_frame; |
| 1083 | 1083 | expect(S.global_ok); |
| 1084 | 1084 | expect(res.x == 1); |
| ... | ... | @@ -1377,7 +1377,7 @@ test "async function call resolves target fn frame, comptime func" { |
| 1377 | 1377 | fn foo() anyerror!void { |
| 1378 | 1378 | const stack_size = 1000; |
| 1379 | 1379 | var stack_frame: [stack_size]u8 align(std.Target.stack_align) = undefined; |
| 1380 | return await @asyncCall(&stack_frame, {}, bar); | |
| 1380 | return await @asyncCall(&stack_frame, {}, bar, .{}); | |
| 1381 | 1381 | } |
| 1382 | 1382 | |
| 1383 | 1383 | fn bar() anyerror!void { |
| ... | ... | @@ -1400,7 +1400,7 @@ test "async function call resolves target fn frame, runtime func" { |
| 1400 | 1400 | const stack_size = 1000; |
| 1401 | 1401 | var stack_frame: [stack_size]u8 align(std.Target.stack_align) = undefined; |
| 1402 | 1402 | var func: fn () callconv(.Async) anyerror!void = bar; |
| 1403 | return await @asyncCall(&stack_frame, {}, func); | |
| 1403 | return await @asyncCall(&stack_frame, {}, func, .{}); | |
| 1404 | 1404 | } |
| 1405 | 1405 | |
| 1406 | 1406 | fn bar() anyerror!void { |