authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-09-21 14:33:42-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-26 15:57:06-07:00
loga6eb83bd1b7739156ab01e3fc55588f67d924daa
treec89741b3b0e9fdfa1433031eab13e611634b5e1f
parente70c34cdb7ea7d9b7b6feddb2d8e6194ed1188a4

AIR: add call_async_alloc instruction

This is for async calls that also act as an alloca. This helps avoid unnecessarily complicated machinery for the simple case of `var a = async b();`. The `call_async` instruction has a frame pointer and returns void always, which will be used for the other form: `a = async b();`.

13 files changed, 128 insertions(+), 35 deletions(-)

src/Air.zig+15-3
...@@ -310,9 +310,14 @@ pub const Inst = struct {...@@ -310,9 +310,14 @@ pub const Inst = struct {
310 call_never_tail,310 call_never_tail,
311 /// Same as `call` except with the `never_inline` attribute.311 /// Same as `call` except with the `never_inline` attribute.
312 call_never_inline,312 call_never_inline,
313 /// Async function call.313 /// Async function call, using a provided frame pointer.
314 /// Uses `ty_pl` field with the `AsyncCall` payload.314 /// Uses `pl_op` field with the `AsyncCall` payload. operand is the callee.
315 /// Result type is always void.
315 call_async,316 call_async,
317 /// Async function call, which allocates the frame for the callee on the stack.
318 /// This instruction also acts as an alloc.
319 /// Uses `ty_pl` field with the `AsyncCallAlloc` payload.
320 call_async_alloc,
316 /// Count leading zeroes of an integer according to its representation in twos complement.321 /// Count leading zeroes of an integer according to its representation in twos complement.
317 /// Result type will always be an unsigned integer big enough to fit the answer.322 /// Result type will always be an unsigned integer big enough to fit the answer.
318 /// Uses the `ty_op` field.323 /// Uses the `ty_op` field.
...@@ -1076,6 +1081,11 @@ pub const Call = struct {...@@ -1076,6 +1081,11 @@ pub const Call = struct {
1076/// Trailing is a list of `Inst.Ref` for every `args_len`.1081/// Trailing is a list of `Inst.Ref` for every `args_len`.
1077pub const AsyncCall = struct {1082pub const AsyncCall = struct {
1078 frame_ptr: Inst.Ref,1083 frame_ptr: Inst.Ref,
1084 args_len: u32,
1085};
1086
1087/// Trailing is a list of `Inst.Ref` for every `args_len`.
1088pub const AsyncCallAlloc = struct {
1079 callee: Inst.Ref,1089 callee: Inst.Ref,
1080 args_len: u32,1090 args_len: u32,
1081};1091};
...@@ -1350,7 +1360,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)...@@ -1350,7 +1360,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
1350 .ptr_add,1360 .ptr_add,
1351 .ptr_sub,1361 .ptr_sub,
1352 .try_ptr,1362 .try_ptr,
1353 .call_async,1363 .call_async_alloc,
1354 => return air.getRefType(datas[inst].ty_pl.ty),1364 => return air.getRefType(datas[inst].ty_pl.ty),
13551365
1356 .interned => return ip.typeOf(datas[inst].interned).toType(),1366 .interned => return ip.typeOf(datas[inst].interned).toType(),
...@@ -1429,6 +1439,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)...@@ -1429,6 +1439,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
1429 .set_err_return_trace,1439 .set_err_return_trace,
1430 .vector_store_elem,1440 .vector_store_elem,
1431 .c_va_end,1441 .c_va_end,
1442 .call_async,
1432 => return Type.void,1443 => return Type.void,
14331444
1434 .int_from_ptr,1445 .int_from_ptr,
...@@ -1595,6 +1606,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {...@@ -1595,6 +1606,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
1595 .call_never_tail,1606 .call_never_tail,
1596 .call_never_inline,1607 .call_never_inline,
1597 .call_async,1608 .call_async,
1609 .call_async_alloc,
1598 .cond_br,1610 .cond_br,
1599 .switch_br,1611 .switch_br,
1600 .@"try",1612 .@"try",
src/Liveness.zig+63-18
...@@ -484,15 +484,25 @@ pub fn categorizeOperand(...@@ -484,15 +484,25 @@ pub fn categorizeOperand(
484 const inst_data = air_datas[inst].pl_op;484 const inst_data = air_datas[inst].pl_op;
485 const callee = inst_data.operand;485 const callee = inst_data.operand;
486 const extra = air.extraData(Air.Call, inst_data.payload);486 const extra = air.extraData(Air.Call, inst_data.payload);
487 const frame_ptr: Air.Inst.Ref = .none;
487 const args: []const Air.Inst.Ref = @ptrCast(air.extra[extra.end..][0..extra.data.args_len]);488 const args: []const Air.Inst.Ref = @ptrCast(air.extra[extra.end..][0..extra.data.args_len]);
488 return categorizeOperandCall(l, inst, operand_ref, callee, args);489 return categorizeOperandCall(l, inst, operand_ref, frame_ptr, callee, args);
489 },490 },
490 .call_async => {491 .call_async => {
491 const inst_data = air_datas[inst].ty_pl;492 const inst_data = air_datas[inst].pl_op;
492 const extra = air.extraData(Air.AsyncCall, inst_data.payload);493 const extra = air.extraData(Air.AsyncCall, inst_data.payload);
494 const callee = inst_data.operand;
495 const frame_ptr = extra.data.frame_ptr;
496 const args: []const Air.Inst.Ref = @ptrCast(air.extra[extra.end..][0..extra.data.args_len]);
497 return categorizeOperandCall(l, inst, operand_ref, frame_ptr, callee, args);
498 },
499 .call_async_alloc => {
500 const inst_data = air_datas[inst].ty_pl;
501 const extra = air.extraData(Air.AsyncCallAlloc, inst_data.payload);
493 const callee = extra.data.callee;502 const callee = extra.data.callee;
503 const frame_ptr: Air.Inst.Ref = .none;
494 const args: []const Air.Inst.Ref = @ptrCast(air.extra[extra.end..][0..extra.data.args_len]);504 const args: []const Air.Inst.Ref = @ptrCast(air.extra[extra.end..][0..extra.data.args_len]);
495 return categorizeOperandCall(l, inst, operand_ref, callee, args);505 return categorizeOperandCall(l, inst, operand_ref, frame_ptr, callee, args);
496 },506 },
497 .select => {507 .select => {
498 const pl_op = air_datas[inst].pl_op;508 const pl_op = air_datas[inst].pl_op;
...@@ -661,21 +671,37 @@ pub fn categorizeOperand(...@@ -661,21 +671,37 @@ pub fn categorizeOperand(
661 }671 }
662}672}
663673
664fn categorizeOperandCall(674pub fn categorizeOperandCall(
665 l: Liveness,675 l: Liveness,
666 inst: Air.Inst.Index,676 inst: Air.Inst.Index,
667 operand_ref: Air.Inst.Ref,677 operand_ref: Air.Inst.Ref,
678 frame_ptr: Air.Inst.Ref,
668 callee: Air.Inst.Ref,679 callee: Air.Inst.Ref,
669 args: []const Air.Inst.Ref,680 args: []const Air.Inst.Ref,
670) OperandCategory {681) OperandCategory {
671 if (args.len + 1 <= bpi - 1) {682 const total = args.len + 1 + @intFromBool(frame_ptr != .none);
672 if (callee == operand_ref) return matchOperandSmallIndex(l, inst, 0, .write);683 if (total <= bpi - 1) {
673 for (args, 0..) |arg, i| {684 var op_index: OperandInt = 0;
674 if (arg == operand_ref) return matchOperandSmallIndex(l, inst, @intCast(i + 1), .write);685 if (frame_ptr != .none) {
686 if (frame_ptr == operand_ref) return matchOperandSmallIndex(l, inst, op_index, .write);
687 op_index += 1;
688 }
689 if (callee == operand_ref) return matchOperandSmallIndex(l, inst, op_index, .write);
690
691 for (args) |arg| {
692 op_index += 1;
693 if (arg == operand_ref) return matchOperandSmallIndex(l, inst, op_index, .write);
675 }694 }
676 return .write;695 return .write;
677 }696 }
678 var bt = l.iterateBigTomb(inst);697 var bt = l.iterateBigTomb(inst);
698 if (frame_ptr != .none) {
699 if (bt.feed()) {
700 if (frame_ptr == operand_ref) return .tomb;
701 } else {
702 if (frame_ptr == operand_ref) return .write;
703 }
704 }
679 if (bt.feed()) {705 if (bt.feed()) {
680 if (callee == operand_ref) return .tomb;706 if (callee == operand_ref) return .tomb;
681 } else {707 } else {
...@@ -1122,18 +1148,28 @@ fn analyzeInst(...@@ -1122,18 +1148,28 @@ fn analyzeInst(
1122 },1148 },
11231149
1124 .call, .call_always_tail, .call_never_tail, .call_never_inline => {1150 .call, .call_always_tail, .call_never_tail, .call_never_inline => {
1125 const inst_data = inst_datas[inst].pl_op;1151 const pl_op = inst_datas[inst].pl_op;
1126 const callee = inst_data.operand;1152 const callee = pl_op.operand;
1127 const extra = a.air.extraData(Air.Call, inst_data.payload);1153 const frame_ptr: Air.Inst.Ref = .none;
1154 const extra = a.air.extraData(Air.Call, pl_op.payload);
1128 const args: []const Air.Inst.Ref = @ptrCast(a.air.extra[extra.end..][0..extra.data.args_len]);1155 const args: []const Air.Inst.Ref = @ptrCast(a.air.extra[extra.end..][0..extra.data.args_len]);
1129 return analyzeInstCall(a, pass, data, inst, callee, args);1156 return analyzeInstCall(a, pass, data, inst, frame_ptr, callee, args);
1130 },1157 },
1131 .call_async => {1158 .call_async => {
1132 const inst_data = inst_datas[inst].ty_pl;1159 const inst_data = inst_datas[inst].pl_op;
1133 const extra = a.air.extraData(Air.AsyncCall, inst_data.payload);1160 const extra = a.air.extraData(Air.AsyncCall, inst_data.payload);
1161 const callee = inst_data.operand;
1162 const args: []const Air.Inst.Ref = @ptrCast(a.air.extra[extra.end..][0..extra.data.args_len]);
1163 const frame_ptr = extra.data.frame_ptr;
1164 return analyzeInstCall(a, pass, data, inst, frame_ptr, callee, args);
1165 },
1166 .call_async_alloc => {
1167 const ty_pl = inst_datas[inst].ty_pl;
1168 const extra = a.air.extraData(Air.AsyncCallAlloc, ty_pl.payload);
1134 const callee = extra.data.callee;1169 const callee = extra.data.callee;
1170 const frame_ptr: Air.Inst.Ref = .none;
1135 const args: []const Air.Inst.Ref = @ptrCast(a.air.extra[extra.end..][0..extra.data.args_len]);1171 const args: []const Air.Inst.Ref = @ptrCast(a.air.extra[extra.end..][0..extra.data.args_len]);
1136 return analyzeInstCall(a, pass, data, inst, callee, args);1172 return analyzeInstCall(a, pass, data, inst, frame_ptr, callee, args);
1137 },1173 },
1138 .select => {1174 .select => {
1139 const pl_op = inst_datas[inst].pl_op;1175 const pl_op = inst_datas[inst].pl_op;
...@@ -1267,24 +1303,33 @@ fn analyzeInstCall(...@@ -1267,24 +1303,33 @@ fn analyzeInstCall(
1267 comptime pass: LivenessPass,1303 comptime pass: LivenessPass,
1268 data: *LivenessPassData(pass),1304 data: *LivenessPassData(pass),
1269 inst: Air.Inst.Index,1305 inst: Air.Inst.Index,
1306 frame_ptr: Air.Inst.Ref,
1270 callee: Air.Inst.Ref,1307 callee: Air.Inst.Ref,
1271 args: []const Air.Inst.Ref,1308 args: []const Air.Inst.Ref,
1272) Allocator.Error!void {1309) Allocator.Error!void {
1273 if (args.len + 1 <= bpi - 1) {1310 const total = args.len + 1 + @intFromBool(frame_ptr != .none);
1311 if (total <= bpi - 1) {
1274 var buf = [1]Air.Inst.Ref{.none} ** (bpi - 1);1312 var buf = [1]Air.Inst.Ref{.none} ** (bpi - 1);
1275 buf[0] = callee;1313 var op_index: OperandInt = 0;
1276 @memcpy(buf[1..][0..args.len], args);1314 if (frame_ptr != .none) {
1315 buf[op_index] = frame_ptr;
1316 op_index += 1;
1317 }
1318 buf[op_index] = callee;
1319 op_index += 1;
1320 @memcpy(buf[op_index..][0..args.len], args);
1277 return analyzeOperands(a, pass, data, inst, buf);1321 return analyzeOperands(a, pass, data, inst, buf);
1278 }1322 }
12791323
1280 var big = try AnalyzeBigOperands(pass).init(a, data, inst, args.len + 1);1324 var big = try AnalyzeBigOperands(pass).init(a, data, inst, args.len + 1);
1281 defer big.deinit();1325 defer big.deinit();
1326 if (frame_ptr != .none) try big.feed(frame_ptr);
1327 try big.feed(callee);
1282 var i: usize = args.len;1328 var i: usize = args.len;
1283 while (i > 0) {1329 while (i > 0) {
1284 i -= 1;1330 i -= 1;
1285 try big.feed(args[i]);1331 try big.feed(args[i]);
1286 }1332 }
1287 try big.feed(callee);
1288 return big.finish();1333 return big.finish();
1289}1334}
12901335
src/Liveness/Verify.zig+17-1
...@@ -350,8 +350,24 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -350,8 +350,24 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
350 try self.verifyInst(inst);350 try self.verifyInst(inst);
351 },351 },
352 .call_async => {352 .call_async => {
353 const pl_op = data[inst].pl_op;
354 const extra = self.air.extraData(Air.AsyncCall, pl_op.payload);
355 const args: []const Air.Inst.Ref = @ptrCast(
356 self.air.extra[extra.end..][0..extra.data.args_len],
357 );
358 const callee = pl_op.operand;
359
360 var bt = self.liveness.iterateBigTomb(inst);
361 try self.verifyOperand(inst, extra.data.frame_ptr, bt.feed());
362 try self.verifyOperand(inst, callee, bt.feed());
363 for (args) |arg| {
364 try self.verifyOperand(inst, arg, bt.feed());
365 }
366 try self.verifyInst(inst);
367 },
368 .call_async_alloc => {
353 const ty_pl = data[inst].ty_pl;369 const ty_pl = data[inst].ty_pl;
354 const extra = self.air.extraData(Air.AsyncCall, ty_pl.payload);370 const extra = self.air.extraData(Air.AsyncCallAlloc, ty_pl.payload);
355 const args: []const Air.Inst.Ref = @ptrCast(371 const args: []const Air.Inst.Ref = @ptrCast(
356 self.air.extra[extra.end..][0..extra.data.args_len],372 self.air.extra[extra.end..][0..extra.data.args_len],
357 );373 );
src/Sema.zig+2-4
...@@ -7299,18 +7299,16 @@ fn addAsyncCallInst(...@@ -7299,18 +7299,16 @@ fn addAsyncCallInst(
7299) Allocator.Error!Air.Inst.Ref {7299) Allocator.Error!Air.Inst.Ref {
7300 const mod = sema.mod;7300 const mod = sema.mod;
7301 const ptr_frame_ty = try mod.singleMutPtrType(try mod.asyncFrameType(callee_fn));7301 const ptr_frame_ty = try mod.singleMutPtrType(try mod.asyncFrameType(callee_fn));
7302 const frame_ptr = try block.addTy(.alloc, ptr_frame_ty);
7303 const ptr_frame_ty_ref = try sema.addType(ptr_frame_ty);7302 const ptr_frame_ty_ref = try sema.addType(ptr_frame_ty);
7304 try sema.air_extra.ensureUnusedCapacity(7303 try sema.air_extra.ensureUnusedCapacity(
7305 sema.gpa,7304 sema.gpa,
7306 @typeInfo(Air.AsyncCall).Struct.fields.len + args.len,7305 @typeInfo(Air.AsyncCall).Struct.fields.len + args.len,
7307 );7306 );
7308 const call_inst = try block.addInst(.{7307 const call_inst = try block.addInst(.{
7309 .tag = .call_async,7308 .tag = .call_async_alloc,
7310 .data = .{ .ty_pl = .{7309 .data = .{ .ty_pl = .{
7311 .ty = ptr_frame_ty_ref,7310 .ty = ptr_frame_ty_ref,
7312 .payload = sema.addExtraAssumeCapacity(Air.AsyncCall{7311 .payload = sema.addExtraAssumeCapacity(Air.AsyncCallAlloc{
7313 .frame_ptr = frame_ptr,
7314 .callee = callee,7312 .callee = callee,
7315 .args_len = @intCast(args.len),7313 .args_len = @intCast(args.len),
7316 }),7314 }),
src/arch/aarch64/CodeGen.zig+1
...@@ -820,6 +820,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -820,6 +820,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
820 .call_never_tail => try self.airCall(inst, .never_tail),820 .call_never_tail => try self.airCall(inst, .never_tail),
821 .call_never_inline => try self.airCall(inst, .never_inline),821 .call_never_inline => try self.airCall(inst, .never_inline),
822 .call_async => try self.airCall(inst, .async_kw),822 .call_async => try self.airCall(inst, .async_kw),
823 .call_async_alloc => try self.airCall(inst, .async_kw),
823824
824 .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),825 .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
825 .atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),826 .atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
src/arch/arm/CodeGen.zig+1
...@@ -804,6 +804,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -804,6 +804,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
804 .call_never_tail => try self.airCall(inst, .never_tail),804 .call_never_tail => try self.airCall(inst, .never_tail),
805 .call_never_inline => try self.airCall(inst, .never_inline),805 .call_never_inline => try self.airCall(inst, .never_inline),
806 .call_async => try self.airCall(inst, .async_kw),806 .call_async => try self.airCall(inst, .async_kw),
807 .call_async_alloc => try self.airCall(inst, .async_kw),
807808
808 .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),809 .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
809 .atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),810 .atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
src/arch/riscv64/CodeGen.zig+1
...@@ -639,6 +639,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -639,6 +639,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
639 .call_never_tail => try self.airCall(inst, .never_tail),639 .call_never_tail => try self.airCall(inst, .never_tail),
640 .call_never_inline => try self.airCall(inst, .never_inline),640 .call_never_inline => try self.airCall(inst, .never_inline),
641 .call_async => try self.airCall(inst, .async_kw),641 .call_async => try self.airCall(inst, .async_kw),
642 .call_async_alloc => try self.airCall(inst, .async_kw),
642643
643 .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),644 .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
644 .atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),645 .atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
src/arch/sparc64/CodeGen.zig+1
...@@ -652,6 +652,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -652,6 +652,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
652 .call_never_tail => try self.airCall(inst, .never_tail),652 .call_never_tail => try self.airCall(inst, .never_tail),
653 .call_never_inline => try self.airCall(inst, .never_inline),653 .call_never_inline => try self.airCall(inst, .never_inline),
654 .call_async => try self.airCall(inst, .async_kw),654 .call_async => try self.airCall(inst, .async_kw),
655 .call_async_alloc => try self.airCall(inst, .async_kw),
655656
656 .atomic_store_unordered => @panic("TODO try self.airAtomicStore(inst, .Unordered)"),657 .atomic_store_unordered => @panic("TODO try self.airAtomicStore(inst, .Unordered)"),
657 .atomic_store_monotonic => @panic("TODO try self.airAtomicStore(inst, .Monotonic)"),658 .atomic_store_monotonic => @panic("TODO try self.airAtomicStore(inst, .Monotonic)"),
src/arch/wasm/CodeGen.zig+1
...@@ -1931,6 +1931,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -1931,6 +1931,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
1931 .call_never_tail => func.airCall(inst, .never_tail),1931 .call_never_tail => func.airCall(inst, .never_tail),
1932 .call_never_inline => func.airCall(inst, .never_inline),1932 .call_never_inline => func.airCall(inst, .never_inline),
1933 .call_async => func.airCall(inst, .async_kw),1933 .call_async => func.airCall(inst, .async_kw),
1934 .call_async_alloc => func.airCall(inst, .async_kw),
19341935
1935 .is_err => func.airIsErr(inst, .i32_ne),1936 .is_err => func.airIsErr(inst, .i32_ne),
1936 .is_non_err => func.airIsErr(inst, .i32_eq),1937 .is_non_err => func.airIsErr(inst, .i32_eq),
src/arch/x86_64/CodeGen.zig+1
...@@ -1902,6 +1902,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -1902,6 +1902,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1902 .call_never_tail => try self.airCall(inst, .never_tail),1902 .call_never_tail => try self.airCall(inst, .never_tail),
1903 .call_never_inline => try self.airCall(inst, .never_inline),1903 .call_never_inline => try self.airCall(inst, .never_inline),
1904 .call_async => try self.airCall(inst, .async_kw),1904 .call_async => try self.airCall(inst, .async_kw),
1905 .call_async_alloc => try self.airCall(inst, .async_kw),
19051906
1906 .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),1907 .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
1907 .atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),1908 .atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
src/codegen/c.zig+1
...@@ -3001,6 +3001,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -3001,6 +3001,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
3001 .call_never_tail => try airCall(f, inst, .never_tail),3001 .call_never_tail => try airCall(f, inst, .never_tail),
3002 .call_never_inline => try airCall(f, inst, .never_inline),3002 .call_never_inline => try airCall(f, inst, .never_inline),
3003 .call_async => try airCall(f, inst, .async_kw),3003 .call_async => try airCall(f, inst, .async_kw),
3004 .call_async_alloc => try airCall(f, inst, .async_kw),
30043005
3005 .float_from_int,3006 .float_from_int,
3006 .int_from_float,3007 .int_from_float,
src/codegen/llvm.zig+12-7
...@@ -3035,12 +3035,11 @@ pub const Object = struct {...@@ -3035,12 +3035,11 @@ pub const Object = struct {
3035 const llvm_struct_ty = o.context.structCreateNamed(name);3035 const llvm_struct_ty = o.context.structCreateNamed(name);
3036 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls3036 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
30373037
3038 return lowerAsyncFrameType(o, func, llvm_struct_ty);3038 if (func.isAsync()) {
3039 //if (func.isAsync()) {3039 return lowerAsyncFrameType(o, func, llvm_struct_ty);
3040 // return lowerAsyncFrameType(o, func, llvm_struct_ty);3040 } else {
3041 //} else {3041 @panic("lower llvm @Frame() type of non-async function");
3042 // @panic("lower llvm @Frame() type of non-async function");3042 }
3043 //}
3044 },3043 },
3045 .AnyFrame => return o.context.pointerType(0),3044 .AnyFrame => return o.context.pointerType(0),
3046 }3045 }
...@@ -4522,6 +4521,7 @@ pub const FuncGen = struct {...@@ -4522,6 +4521,7 @@ pub const FuncGen = struct {
4522 .call_always_tail => try self.airCall(inst, .AlwaysTail),4521 .call_always_tail => try self.airCall(inst, .AlwaysTail),
4523 .call_never_tail => try self.airCall(inst, .NeverTail),4522 .call_never_tail => try self.airCall(inst, .NeverTail),
4524 .call_never_inline => try self.airCall(inst, .NeverInline),4523 .call_never_inline => try self.airCall(inst, .NeverInline),
4524 .call_async_alloc => try self.airCallAsyncAlloc(inst),
4525 .call_async => try self.airCallAsync(inst),4525 .call_async => try self.airCallAsync(inst),
45264526
4527 .ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0),4527 .ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0),
...@@ -4990,7 +4990,12 @@ pub const FuncGen = struct {...@@ -4990,7 +4990,12 @@ pub const FuncGen = struct {
49904990
4991 fn airCallAsync(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {4991 fn airCallAsync(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
4992 _ = inst;4992 _ = inst;
4993 return self.todo("lower async call", .{});4993 return self.todo("lower call_async", .{});
4994 }
4995
4996 fn airCallAsyncAlloc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
4997 _ = inst;
4998 return self.todo("lower call_async_alloc", .{});
4994 }4999 }
49955000
4996 fn airRet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {5001 fn airRet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
src/print_air.zig+12-2
...@@ -330,6 +330,7 @@ const Writer = struct {...@@ -330,6 +330,7 @@ const Writer = struct {
330 .cmp_vector, .cmp_vector_optimized => try w.writeCmpVector(s, inst),330 .cmp_vector, .cmp_vector_optimized => try w.writeCmpVector(s, inst),
331 .vector_store_elem => try w.writeVectorStoreElem(s, inst),331 .vector_store_elem => try w.writeVectorStoreElem(s, inst),
332 .call_async => try w.writeCallAsync(s, inst),332 .call_async => try w.writeCallAsync(s, inst),
333 .call_async_alloc => try w.writeCallAsyncAlloc(s, inst),
333334
334 .dbg_block_begin, .dbg_block_end => {},335 .dbg_block_begin, .dbg_block_end => {},
335336
...@@ -705,11 +706,20 @@ const Writer = struct {...@@ -705,11 +706,20 @@ const Writer = struct {
705 }706 }
706707
707 fn writeCallAsync(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {708 fn writeCallAsync(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
709 const pl_op = w.air.instructions.items(.data)[inst].pl_op;
710 const extra = w.air.extraData(Air.AsyncCall, pl_op.payload);
711 const callee = pl_op.operand;
712 const frame_ptr = extra.data.frame_ptr;
713 const args: []const Air.Inst.Ref = @ptrCast(w.air.extra[extra.end..][0..extra.data.args_len]);
714 return finishWriteCall(w, s, inst, frame_ptr, callee, args);
715 }
716
717 fn writeCallAsyncAlloc(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
708 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;718 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
709 const extra = w.air.extraData(Air.AsyncCall, ty_pl.payload);719 const extra = w.air.extraData(Air.AsyncCallAlloc, ty_pl.payload);
710 const callee = extra.data.callee;720 const callee = extra.data.callee;
721 const frame_ptr: Air.Inst.Ref = .none;
711 const args: []const Air.Inst.Ref = @ptrCast(w.air.extra[extra.end..][0..extra.data.args_len]);722 const args: []const Air.Inst.Ref = @ptrCast(w.air.extra[extra.end..][0..extra.data.args_len]);
712 const frame_ptr = extra.data.frame_ptr;
713 return finishWriteCall(w, s, inst, frame_ptr, callee, args);723 return finishWriteCall(w, s, inst, frame_ptr, callee, args);
714 }724 }
715725