authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-23 21:12:29-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-23 21:12:29-07:00
logfbfae832eaf520f7fcc632580b4b4a7fb171f90f
tree1a8b34df8132e7bffc336235cfdae17f261f41c9
parent49be88859d3cef22c5cc27c908264a235c78a4d0

AstGen: emit nosuspend function calls

Inside a nosuspend block, emit function calls as nosuspend calls. Also inside a comptime block, emit function calls as comptime calls. Also emit `async foo()` calls as async calls. Remove compile error for `nosuspend` block inside `suspend` block. Instead of implicitly treating every `suspend` block also as a `nosuspend` block (which would make sense), we leave suspension points as compile errors, to hint to the programmer about accidents. Of course they may then assert `nosuspend` by introducing a block within their suspend block. To make room in `Zir.Inst.Tag` I moved `typeof_peer` and `compile_log` to `Extended`.

5 files changed, 118 insertions(+), 69 deletions(-)

BRANCH_TODO-1
...@@ -37,7 +37,6 @@...@@ -37,7 +37,6 @@
37 * when handling decls, catch the error and continue, so that37 * when handling decls, catch the error and continue, so that
38 AstGen can report more than one compile error.38 AstGen can report more than one compile error.
3939
40 * AstGen: inside a nosuspend block, emit function calls as nosuspend calls
41 * AstGen: add result location pointers to function calls40 * AstGen: add result location pointers to function calls
4241
43 const container_name_hash: Scope.NameHash = if (found_pkg) |pkg|42 const container_name_hash: Scope.NameHash = if (found_pkg) |pkg|
src/AstGen.zig+17-24
...@@ -900,11 +900,6 @@ pub fn nosuspendExpr(...@@ -900,11 +900,6 @@ pub fn nosuspendExpr(
900 try astgen.errNoteNode(gz.nosuspend_node, "other nosuspend block here", .{}),900 try astgen.errNoteNode(gz.nosuspend_node, "other nosuspend block here", .{}),
901 });901 });
902 }902 }
903 if (gz.suspend_node != 0) {
904 return astgen.failNodeNotes(node, "inside a suspend block, nosuspend is implied", .{}, &[_]u32{
905 try astgen.errNoteNode(gz.suspend_node, "suspend block here", .{}),
906 });
907 }
908 gz.nosuspend_node = node;903 gz.nosuspend_node = node;
909 const result = try expr(gz, scope, rl, body_node);904 const result = try expr(gz, scope, rl, body_node);
910 gz.nosuspend_node = 0;905 gz.nosuspend_node = 0;
...@@ -1803,6 +1798,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner...@@ -1803,6 +1798,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
1803 .bool_and,1798 .bool_and,
1804 .bool_or,1799 .bool_or,
1805 .call_compile_time,1800 .call_compile_time,
1801 .call_nosuspend,
1802 .call_async,
1806 .cmp_lt,1803 .cmp_lt,
1807 .cmp_lte,1804 .cmp_lte,
1808 .cmp_eq,1805 .cmp_eq,
...@@ -1876,7 +1873,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner...@@ -1876,7 +1873,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
1876 .slice_end,1873 .slice_end,
1877 .slice_sentinel,1874 .slice_sentinel,
1878 .import,1875 .import,
1879 .typeof_peer,
1880 .switch_block,1876 .switch_block,
1881 .switch_block_multi,1877 .switch_block_multi,
1882 .switch_block_else,1878 .switch_block_else,
...@@ -2001,7 +1997,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner...@@ -2001,7 +1997,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
2001 .ensure_result_non_error,1997 .ensure_result_non_error,
2002 .@"export",1998 .@"export",
2003 .set_eval_branch_quota,1999 .set_eval_branch_quota,
2004 .compile_log,
2005 .ensure_err_payload_void,2000 .ensure_err_payload_void,
2006 .@"break",2001 .@"break",
2007 .break_inline,2002 .break_inline,
...@@ -6074,11 +6069,7 @@ fn typeOf(...@@ -6074,11 +6069,7 @@ fn typeOf(
6074 items[param_i] = try expr(gz, scope, .none, param);6069 items[param_i] = try expr(gz, scope, .none, param);
6075 }6070 }
60766071
6077 const result = try gz.addPlNode(.typeof_peer, node, Zir.Inst.MultiOp{6072 const result = try gz.addExtendedMultiOp(.typeof_peer, node, items);
6078 .operands_len = @intCast(u32, params.len),
6079 });
6080 try gz.astgen.appendRefs(items);
6081
6082 return rvalue(gz, scope, rl, result, node);6073 return rvalue(gz, scope, rl, result, node);
6083}6074}
60846075
...@@ -6138,10 +6129,7 @@ fn builtinCall(...@@ -6138,10 +6129,7 @@ fn builtinCall(
61386129
6139 for (params) |param, i| arg_refs[i] = try expr(gz, scope, .none, param);6130 for (params) |param, i| arg_refs[i] = try expr(gz, scope, .none, param);
61406131
6141 const result = try gz.addPlNode(.compile_log, node, Zir.Inst.MultiOp{6132 const result = try gz.addExtendedMultiOp(.compile_log, node, arg_refs);
6142 .operands_len = @intCast(u32, params.len),
6143 });
6144 try gz.astgen.appendRefs(arg_refs);
6145 return rvalue(gz, scope, rl, result, node);6133 return rvalue(gz, scope, rl, result, node);
6146 },6134 },
6147 .field => {6135 .field => {
...@@ -6745,9 +6733,6 @@ fn callExpr(...@@ -6745,9 +6733,6 @@ fn callExpr(
6745 call: ast.full.Call,6733 call: ast.full.Call,
6746) InnerError!Zir.Inst.Ref {6734) InnerError!Zir.Inst.Ref {
6747 const astgen = gz.astgen;6735 const astgen = gz.astgen;
6748 if (call.async_token) |async_token| {
6749 return astgen.failTok(async_token, "async and related features are not yet supported", .{});
6750 }
6751 const lhs = try expr(gz, scope, .none, call.ast.fn_expr);6736 const lhs = try expr(gz, scope, .none, call.ast.fn_expr);
67526737
6753 const args = try astgen.gpa.alloc(Zir.Inst.Ref, call.ast.params.len);6738 const args = try astgen.gpa.alloc(Zir.Inst.Ref, call.ast.params.len);
...@@ -6764,9 +6749,17 @@ fn callExpr(...@@ -6764,9 +6749,17 @@ fn callExpr(
6764 args[i] = try expr(gz, scope, .{ .ty = param_type }, param_node);6749 args[i] = try expr(gz, scope, .{ .ty = param_type }, param_node);
6765 }6750 }
67666751
6767 const modifier: std.builtin.CallOptions.Modifier = switch (call.async_token != null) {6752 const modifier: std.builtin.CallOptions.Modifier = blk: {
6768 true => .async_kw,6753 if (gz.force_comptime) {
6769 false => .auto,6754 break :blk .compile_time;
6755 }
6756 if (call.async_token != null) {
6757 break :blk .async_kw;
6758 }
6759 if (gz.nosuspend_node != 0) {
6760 break :blk .no_async;
6761 }
6762 break :blk .auto;
6770 };6763 };
6771 const result: Zir.Inst.Ref = res: {6764 const result: Zir.Inst.Ref = res: {
6772 const tag: Zir.Inst.Tag = switch (modifier) {6765 const tag: Zir.Inst.Tag = switch (modifier) {
...@@ -6774,10 +6767,10 @@ fn callExpr(...@@ -6774,10 +6767,10 @@ fn callExpr(
6774 true => break :res try gz.addUnNode(.call_none, lhs, node),6767 true => break :res try gz.addUnNode(.call_none, lhs, node),
6775 false => .call,6768 false => .call,
6776 },6769 },
6777 .async_kw => return astgen.failNode(node, "async and related features are not yet supported", .{}),6770 .async_kw => .call_async,
6778 .never_tail => unreachable,6771 .never_tail => unreachable,
6779 .never_inline => unreachable,6772 .never_inline => unreachable,
6780 .no_async => return astgen.failNode(node, "async and related features are not yet supported", .{}),6773 .no_async => .call_nosuspend,
6781 .always_tail => unreachable,6774 .always_tail => unreachable,
6782 .always_inline => unreachable,6775 .always_inline => unreachable,
6783 .compile_time => .call_compile_time,6776 .compile_time => .call_compile_time,
src/Module.zig+33
...@@ -1533,6 +1533,39 @@ pub const Scope = struct {...@@ -1533,6 +1533,39 @@ pub const Scope = struct {
1533 return gz.indexToRef(new_index);1533 return gz.indexToRef(new_index);
1534 }1534 }
15351535
1536 pub fn addExtendedMultiOp(
1537 gz: *GenZir,
1538 opcode: Zir.Inst.Extended,
1539 node: ast.Node.Index,
1540 operands: []const Zir.Inst.Ref,
1541 ) !Zir.Inst.Ref {
1542 const astgen = gz.astgen;
1543 const gpa = astgen.gpa;
1544
1545 try gz.instructions.ensureUnusedCapacity(gpa, 1);
1546 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
1547 try astgen.extra.ensureUnusedCapacity(
1548 gpa,
1549 @typeInfo(Zir.Inst.NodeMultiOp).Struct.fields.len + operands.len,
1550 );
1551
1552 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.NodeMultiOp{
1553 .src_node = gz.nodeIndexToRelative(node),
1554 });
1555 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
1556 astgen.instructions.appendAssumeCapacity(.{
1557 .tag = .extended,
1558 .data = .{ .extended = .{
1559 .opcode = opcode,
1560 .small = @intCast(u16, operands.len),
1561 .operand = payload_index,
1562 } },
1563 });
1564 gz.instructions.appendAssumeCapacity(new_index);
1565 astgen.appendRefsAssumeCapacity(operands);
1566 return gz.indexToRef(new_index);
1567 }
1568
1536 pub fn addArrayTypeSentinel(1569 pub fn addArrayTypeSentinel(
1537 gz: *GenZir,1570 gz: *GenZir,
1538 len: Zir.Inst.Ref,1571 len: Zir.Inst.Ref,
src/Sema.zig+26-16
...@@ -161,6 +161,8 @@ pub fn analyzeBody(...@@ -161,6 +161,8 @@ pub fn analyzeBody(
161 .call => try sema.zirCall(block, inst, .auto, false),161 .call => try sema.zirCall(block, inst, .auto, false),
162 .call_chkused => try sema.zirCall(block, inst, .auto, true),162 .call_chkused => try sema.zirCall(block, inst, .auto, true),
163 .call_compile_time => try sema.zirCall(block, inst, .compile_time, false),163 .call_compile_time => try sema.zirCall(block, inst, .compile_time, false),
164 .call_nosuspend => try sema.zirCall(block, inst, .no_async, false),
165 .call_async => try sema.zirCall(block, inst, .async_kw, false),
164 .call_none => try sema.zirCallNone(block, inst, false),166 .call_none => try sema.zirCallNone(block, inst, false),
165 .call_none_chkused => try sema.zirCallNone(block, inst, true),167 .call_none_chkused => try sema.zirCallNone(block, inst, true),
166 .cmp_eq => try sema.zirCmp(block, inst, .eq),168 .cmp_eq => try sema.zirCmp(block, inst, .eq),
...@@ -254,7 +256,6 @@ pub fn analyzeBody(...@@ -254,7 +256,6 @@ pub fn analyzeBody(
254 .bit_size_of => try sema.zirBitSizeOf(block, inst),256 .bit_size_of => try sema.zirBitSizeOf(block, inst),
255 .typeof => try sema.zirTypeof(block, inst),257 .typeof => try sema.zirTypeof(block, inst),
256 .typeof_elem => try sema.zirTypeofElem(block, inst),258 .typeof_elem => try sema.zirTypeofElem(block, inst),
257 .typeof_peer => try sema.zirTypeofPeer(block, inst),
258 .log2_int_type => try sema.zirLog2IntType(block, inst),259 .log2_int_type => try sema.zirLog2IntType(block, inst),
259 .typeof_log2_int_type => try sema.zirTypeofLog2IntType(block, inst),260 .typeof_log2_int_type => try sema.zirTypeofLog2IntType(block, inst),
260 .xor => try sema.zirBitwise(block, inst, .xor),261 .xor => try sema.zirBitwise(block, inst, .xor),
...@@ -403,10 +404,6 @@ pub fn analyzeBody(...@@ -403,10 +404,6 @@ pub fn analyzeBody(
403 try sema.zirEnsureResultUsed(block, inst);404 try sema.zirEnsureResultUsed(block, inst);
404 continue;405 continue;
405 },406 },
406 .compile_log => {
407 try sema.zirCompileLog(block, inst);
408 continue;
409 },
410 .set_eval_branch_quota => {407 .set_eval_branch_quota => {
411 try sema.zirSetEvalBranchQuota(block, inst);408 try sema.zirSetEvalBranchQuota(block, inst);
412 continue;409 continue;
...@@ -519,6 +516,8 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro...@@ -519,6 +516,8 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro
519 .alloc => return sema.zirAllocExtended( block, extended),516 .alloc => return sema.zirAllocExtended( block, extended),
520 .builtin_extern => return sema.zirBuiltinExtern( block, extended),517 .builtin_extern => return sema.zirBuiltinExtern( block, extended),
521 .@"asm" => return sema.zirAsm( block, extended),518 .@"asm" => return sema.zirAsm( block, extended),
519 .typeof_peer => return sema.zirTypeofPeer( block, extended),
520 .compile_log => return sema.zirCompileLog( block, extended),
522 .c_undef => return sema.zirCUndef( block, extended),521 .c_undef => return sema.zirCUndef( block, extended),
523 .c_include => return sema.zirCInclude( block, extended),522 .c_include => return sema.zirCInclude( block, extended),
524 .c_define => return sema.zirCDefine( block, extended),523 .c_define => return sema.zirCDefine( block, extended),
...@@ -1533,14 +1532,18 @@ fn zirCompileError(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Inner...@@ -1533,14 +1532,18 @@ fn zirCompileError(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Inner
1533 return sema.mod.fail(&block.base, src, "{s}", .{msg});1532 return sema.mod.fail(&block.base, src, "{s}", .{msg});
1534}1533}
15351534
1536fn zirCompileLog(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {1535fn zirCompileLog(
1536 sema: *Sema,
1537 block: *Scope.Block,
1538 extended: Zir.Inst.Extended.InstData,
1539) InnerError!*Inst {
1537 var managed = sema.mod.compile_log_text.toManaged(sema.gpa);1540 var managed = sema.mod.compile_log_text.toManaged(sema.gpa);
1538 defer sema.mod.compile_log_text = managed.moveToUnmanaged();1541 defer sema.mod.compile_log_text = managed.moveToUnmanaged();
1539 const writer = managed.writer();1542 const writer = managed.writer();
15401543
1541 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;1544 const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);
1542 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);1545 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
1543 const args = sema.code.refSlice(extra.end, extra.data.operands_len);1546 const args = sema.code.refSlice(extra.end, extended.small);
15441547
1545 for (args) |arg_ref, i| {1548 for (args) |arg_ref, i| {
1546 if (i != 0) try writer.print(", ", .{});1549 if (i != 0) try writer.print(", ", .{});
...@@ -1556,8 +1559,12 @@ fn zirCompileLog(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr...@@ -1556,8 +1559,12 @@ fn zirCompileLog(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr
15561559
1557 const gop = try sema.mod.compile_log_decls.getOrPut(sema.gpa, sema.owner_decl);1560 const gop = try sema.mod.compile_log_decls.getOrPut(sema.gpa, sema.owner_decl);
1558 if (!gop.found_existing) {1561 if (!gop.found_existing) {
1559 gop.entry.value = inst_data.src().toSrcLoc(&block.base);1562 gop.entry.value = src.toSrcLoc(&block.base);
1560 }1563 }
1564 return sema.mod.constInst(sema.arena, src, .{
1565 .ty = Type.initTag(.void),
1566 .val = Value.initTag(.void_value),
1567 });
1561}1568}
15621569
1563fn zirRepeat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Zir.Inst.Index {1570fn zirRepeat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Zir.Inst.Index {
...@@ -4680,16 +4687,19 @@ fn zirLog2IntType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerE...@@ -4680,16 +4687,19 @@ fn zirLog2IntType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerE
4680 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirLog2IntType", .{});4687 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirLog2IntType", .{});
4681}4688}
46824689
4683fn zirTypeofPeer(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {4690fn zirTypeofPeer(
4691 sema: *Sema,
4692 block: *Scope.Block,
4693 extended: Zir.Inst.Extended.InstData,
4694) InnerError!*Inst {
4684 const tracy = trace(@src());4695 const tracy = trace(@src());
4685 defer tracy.end();4696 defer tracy.end();
46864697
4687 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;4698 const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand);
4688 const src = inst_data.src();4699 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
4689 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);4700 const args = sema.code.refSlice(extra.end, extended.small);
4690 const args = sema.code.refSlice(extra.end, extra.data.operands_len);
46914701
4692 const inst_list = try sema.gpa.alloc(*ir.Inst, extra.data.operands_len);4702 const inst_list = try sema.gpa.alloc(*ir.Inst, args.len);
4693 defer sema.gpa.free(inst_list);4703 defer sema.gpa.free(inst_list);
46944704
4695 for (args) |arg_ref, i| {4705 for (args) |arg_ref, i| {
src/Zir.zig+42-28
...@@ -238,6 +238,10 @@ pub const Inst = struct {...@@ -238,6 +238,10 @@ pub const Inst = struct {
238 call_chkused,238 call_chkused,
239 /// Same as `call` but with modifier `.compile_time`.239 /// Same as `call` but with modifier `.compile_time`.
240 call_compile_time,240 call_compile_time,
241 /// Same as `call` but with modifier `.no_suspend`.
242 call_nosuspend,
243 /// Same as `call` but with modifier `.async_kw`.
244 call_async,
241 /// Function call with modifier `.auto`, empty parameter list.245 /// Function call with modifier `.auto`, empty parameter list.
242 /// Uses the `un_node` field. Operand is callee. AST node is the function call.246 /// Uses the `un_node` field. Operand is callee. AST node is the function call.
243 call_none,247 call_none,
...@@ -266,10 +270,6 @@ pub const Inst = struct {...@@ -266,10 +270,6 @@ pub const Inst = struct {
266 /// Uses the `bin` union field.270 /// Uses the `bin` union field.
267 /// LHS is destination element type, RHS is result pointer.271 /// LHS is destination element type, RHS is result pointer.
268 coerce_result_ptr,272 coerce_result_ptr,
269 /// Log compile time variables and emit an error message.
270 /// Uses the `pl_node` union field. The AST node is the compile log builtin call.
271 /// The payload is `MultiOp`.
272 compile_log,
273 /// Conditional branch. Splits control flow based on a boolean condition value.273 /// Conditional branch. Splits control flow based on a boolean condition value.
274 /// Uses the `pl_node` union field. AST node is an if, while, for, etc.274 /// Uses the `pl_node` union field. AST node is an if, while, for, etc.
275 /// Payload is `CondBr`.275 /// Payload is `CondBr`.
...@@ -523,10 +523,6 @@ pub const Inst = struct {...@@ -523,10 +523,6 @@ pub const Inst = struct {
523 /// Given a value which is a pointer, returns the element type.523 /// Given a value which is a pointer, returns the element type.
524 /// Uses the `un_node` field.524 /// Uses the `un_node` field.
525 typeof_elem,525 typeof_elem,
526 /// The builtin `@TypeOf` which returns the type after Peer Type Resolution
527 /// of one or more params.
528 /// Uses the `pl_node` field. AST node is the `@TypeOf` call. Payload is `MultiOp`.
529 typeof_peer,
530 /// Given a value, look at the type of it, which must be an integer type.526 /// Given a value, look at the type of it, which must be an integer type.
531 /// Returns the integer type for the RHS of a shift operation.527 /// Returns the integer type for the RHS of a shift operation.
532 /// Uses the `un_node` field.528 /// Uses the `un_node` field.
...@@ -990,6 +986,8 @@ pub const Inst = struct {...@@ -990,6 +986,8 @@ pub const Inst = struct {
990 .call,986 .call,
991 .call_chkused,987 .call_chkused,
992 .call_compile_time,988 .call_compile_time,
989 .call_nosuspend,
990 .call_async,
993 .call_none,991 .call_none,
994 .call_none_chkused,992 .call_none_chkused,
995 .cmp_lt,993 .cmp_lt,
...@@ -1085,12 +1083,10 @@ pub const Inst = struct {...@@ -1085,12 +1083,10 @@ pub const Inst = struct {
1085 .slice_end,1083 .slice_end,
1086 .slice_sentinel,1084 .slice_sentinel,
1087 .import,1085 .import,
1088 .typeof_peer,
1089 .typeof_log2_int_type,1086 .typeof_log2_int_type,
1090 .log2_int_type,1087 .log2_int_type,
1091 .resolve_inferred_alloc,1088 .resolve_inferred_alloc,
1092 .set_eval_branch_quota,1089 .set_eval_branch_quota,
1093 .compile_log,
1094 .switch_capture,1090 .switch_capture,
1095 .switch_capture_ref,1091 .switch_capture_ref,
1096 .switch_capture_multi,1092 .switch_capture_multi,
...@@ -1268,6 +1264,17 @@ pub const Inst = struct {...@@ -1268,6 +1264,17 @@ pub const Inst = struct {
1268 /// * 0bX0000000_00000000 - is volatile1264 /// * 0bX0000000_00000000 - is volatile
1269 /// `operand` is payload index to `Asm`.1265 /// `operand` is payload index to `Asm`.
1270 @"asm",1266 @"asm",
1267 /// Log compile time variables and emit an error message.
1268 /// `operand` is payload index to `NodeMultiOp`.
1269 /// `small` is `operands_len`.
1270 /// The AST node is the compile log builtin call.
1271 compile_log,
1272 /// The builtin `@TypeOf` which returns the type after Peer Type Resolution
1273 /// of one or more params.
1274 /// `operand` is payload index to `NodeMultiOp`.
1275 /// `small` is `operands_len`.
1276 /// The AST node is the builtin call.
1277 typeof_peer,
1271 /// `operand` is payload index to `UnNode`.1278 /// `operand` is payload index to `UnNode`.
1272 c_undef,1279 c_undef,
1273 /// `operand` is payload index to `UnNode`.1280 /// `operand` is payload index to `UnNode`.
...@@ -1897,6 +1904,11 @@ pub const Inst = struct {...@@ -1897,6 +1904,11 @@ pub const Inst = struct {
1897 operands_len: u32,1904 operands_len: u32,
1898 };1905 };
18991906
1907 /// Trailing: operand: Ref, // for each `operands_len` (stored in `small`).
1908 pub const NodeMultiOp = struct {
1909 src_node: i32,
1910 };
1911
1900 /// This data is stored inside extra, with trailing operands according to `body_len`.1912 /// This data is stored inside extra, with trailing operands according to `body_len`.
1901 /// Each operand is an `Index`.1913 /// Each operand is an `Index`.
1902 pub const Block = struct {1914 pub const Block = struct {
...@@ -2540,6 +2552,8 @@ const Writer = struct {...@@ -2540,6 +2552,8 @@ const Writer = struct {
2540 .call,2552 .call,
2541 .call_chkused,2553 .call_chkused,
2542 .call_compile_time,2554 .call_compile_time,
2555 .call_nosuspend,
2556 .call_async,
2543 => try self.writePlNodeCall(stream, inst),2557 => try self.writePlNodeCall(stream, inst),
25442558
2545 .block,2559 .block,
...@@ -2584,10 +2598,6 @@ const Writer = struct {...@@ -2584,10 +2598,6 @@ const Writer = struct {
2584 .switch_block_ref_else_multi => try self.writePlNodeSwitchBlockMulti(stream, inst, .@"else"),2598 .switch_block_ref_else_multi => try self.writePlNodeSwitchBlockMulti(stream, inst, .@"else"),
2585 .switch_block_ref_under_multi => try self.writePlNodeSwitchBlockMulti(stream, inst, .under),2599 .switch_block_ref_under_multi => try self.writePlNodeSwitchBlockMulti(stream, inst, .under),
25862600
2587 .compile_log,
2588 .typeof_peer,
2589 => try self.writePlNodeMultiOp(stream, inst),
2590
2591 .field_ptr,2601 .field_ptr,
2592 .field_val,2602 .field_val,
2593 => try self.writePlNodeField(stream, inst),2603 => try self.writePlNodeField(stream, inst),
...@@ -2646,6 +2656,10 @@ const Writer = struct {...@@ -2646,6 +2656,10 @@ const Writer = struct {
2646 .@"asm" => try self.writeAsm(stream, extended),2656 .@"asm" => try self.writeAsm(stream, extended),
2647 .func => try self.writeFuncExtended(stream, extended),2657 .func => try self.writeFuncExtended(stream, extended),
26482658
2659 .compile_log,
2660 .typeof_peer,
2661 => try self.writeNodeMultiOp(stream, extended),
2662
2649 .alloc,2663 .alloc,
2650 .builtin_extern,2664 .builtin_extern,
2651 .c_undef,2665 .c_undef,
...@@ -2836,6 +2850,19 @@ const Writer = struct {...@@ -2836,6 +2850,19 @@ const Writer = struct {
2836 try self.writeSrc(stream, inst_data.src());2850 try self.writeSrc(stream, inst_data.src());
2837 }2851 }
28382852
2853 fn writeNodeMultiOp(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
2854 const extra = self.code.extraData(Inst.NodeMultiOp, extended.operand);
2855 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
2856 const operands = self.code.refSlice(extra.end, extended.small);
2857
2858 for (operands) |operand, i| {
2859 if (i != 0) try stream.writeAll(", ");
2860 try self.writeInstRef(stream, operand);
2861 }
2862 try stream.writeAll(")) ");
2863 try self.writeSrc(stream, src);
2864 }
2865
2839 fn writeAsm(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {2866 fn writeAsm(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void {
2840 const extra = self.code.extraData(Inst.Asm, extended.operand);2867 const extra = self.code.extraData(Inst.Asm, extended.operand);
2841 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };2868 const src: LazySrcLoc = .{ .node_offset = extra.data.src_node };
...@@ -2902,7 +2929,7 @@ const Writer = struct {...@@ -2902,7 +2929,7 @@ const Writer = struct {
2902 }2929 }
2903 }2930 }
2904 }2931 }
2905 try stream.writeAll(") ");2932 try stream.writeAll(")) ");
2906 try self.writeSrc(stream, src);2933 try self.writeSrc(stream, src);
2907 }2934 }
29082935
...@@ -3457,19 +3484,6 @@ const Writer = struct {...@@ -3457,19 +3484,6 @@ const Writer = struct {
3457 try self.writeSrc(stream, inst_data.src());3484 try self.writeSrc(stream, inst_data.src());
3458 }3485 }
34593486
3460 fn writePlNodeMultiOp(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3461 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3462 const extra = self.code.extraData(Inst.MultiOp, inst_data.payload_index);
3463 const operands = self.code.refSlice(extra.end, extra.data.operands_len);
3464
3465 for (operands) |operand, i| {
3466 if (i != 0) try stream.writeAll(", ");
3467 try self.writeInstRef(stream, operand);
3468 }
3469 try stream.writeAll(") ");
3470 try self.writeSrc(stream, inst_data.src());
3471 }
3472
3473 fn writePlNodeField(self: *Writer, stream: anytype, inst: Inst.Index) !void {3487 fn writePlNodeField(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3474 const inst_data = self.code.instructions.items(.data)[inst].pl_node;3488 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
3475 const extra = self.code.extraData(Inst.Field, inst_data.payload_index).data;3489 const extra = self.code.extraData(Inst.Field, inst_data.payload_index).data;