authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-01-28 22:38:25+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-03-06 15:01:25+02:00
log17e6e09285ed29ead1a3de5d5bfeb4d287f23215
tree26dce4f4fd7ec0822aa3c73af8b69ad37a60245e
parent9f722f43ac449caa0e09c1b7bb1bad0581ef323d
signaturelock-open Commit is signed but in an unrecognized format.

stage2: astgen async


4 files changed, 223 insertions(+), 9 deletions(-)

src/Module.zig+69-2
...@@ -370,6 +370,8 @@ pub const Scope = struct {...@@ -370,6 +370,8 @@ pub const Scope = struct {
370 .gen_zir => return self.cast(GenZIR).?.arena,370 .gen_zir => return self.cast(GenZIR).?.arena,
371 .local_val => return self.cast(LocalVal).?.gen_zir.arena,371 .local_val => return self.cast(LocalVal).?.gen_zir.arena,
372 .local_ptr => return self.cast(LocalPtr).?.gen_zir.arena,372 .local_ptr => return self.cast(LocalPtr).?.gen_zir.arena,
373 .gen_suspend => return self.cast(GenZIR).?.arena,
374 .gen_nosuspend => return self.cast(Nosuspend).?.gen_zir.arena,
373 .file => unreachable,375 .file => unreachable,
374 .container => unreachable,376 .container => unreachable,
375 }377 }
...@@ -385,6 +387,8 @@ pub const Scope = struct {...@@ -385,6 +387,8 @@ pub const Scope = struct {
385 .gen_zir => self.cast(GenZIR).?.decl,387 .gen_zir => self.cast(GenZIR).?.decl,
386 .local_val => self.cast(LocalVal).?.gen_zir.decl,388 .local_val => self.cast(LocalVal).?.gen_zir.decl,
387 .local_ptr => self.cast(LocalPtr).?.gen_zir.decl,389 .local_ptr => self.cast(LocalPtr).?.gen_zir.decl,
390 .gen_suspend => return self.cast(GenZIR).?.decl,
391 .gen_nosuspend => return self.cast(Nosuspend).?.gen_zir.decl,
388 .file => null,392 .file => null,
389 .container => null,393 .container => null,
390 };394 };
...@@ -396,6 +400,8 @@ pub const Scope = struct {...@@ -396,6 +400,8 @@ pub const Scope = struct {
396 .gen_zir => self.cast(GenZIR).?.decl,400 .gen_zir => self.cast(GenZIR).?.decl,
397 .local_val => self.cast(LocalVal).?.gen_zir.decl,401 .local_val => self.cast(LocalVal).?.gen_zir.decl,
398 .local_ptr => self.cast(LocalPtr).?.gen_zir.decl,402 .local_ptr => self.cast(LocalPtr).?.gen_zir.decl,
403 .gen_suspend => return self.cast(GenZIR).?.decl,
404 .gen_nosuspend => return self.cast(Nosuspend).?.gen_zir.decl,
399 .file => null,405 .file => null,
400 .container => null,406 .container => null,
401 };407 };
...@@ -410,6 +416,8 @@ pub const Scope = struct {...@@ -410,6 +416,8 @@ pub const Scope = struct {
410 .local_ptr => return self.cast(LocalPtr).?.gen_zir.decl.container,416 .local_ptr => return self.cast(LocalPtr).?.gen_zir.decl.container,
411 .file => return &self.cast(File).?.root_container,417 .file => return &self.cast(File).?.root_container,
412 .container => return self.cast(Container).?,418 .container => return self.cast(Container).?,
419 .gen_suspend => return self.cast(GenZIR).?.decl.container,
420 .gen_nosuspend => return self.cast(Nosuspend).?.gen_zir.decl.container,
413 }421 }
414 }422 }
415423
...@@ -422,6 +430,8 @@ pub const Scope = struct {...@@ -422,6 +430,8 @@ pub const Scope = struct {
422 .gen_zir => unreachable,430 .gen_zir => unreachable,
423 .local_val => unreachable,431 .local_val => unreachable,
424 .local_ptr => unreachable,432 .local_ptr => unreachable,
433 .gen_suspend => unreachable,
434 .gen_nosuspend => unreachable,
425 .file => unreachable,435 .file => unreachable,
426 .container => return self.cast(Container).?.fullyQualifiedNameHash(name),436 .container => return self.cast(Container).?.fullyQualifiedNameHash(name),
427 }437 }
...@@ -436,6 +446,8 @@ pub const Scope = struct {...@@ -436,6 +446,8 @@ pub const Scope = struct {
436 .local_val => return &self.cast(LocalVal).?.gen_zir.decl.container.file_scope.tree,446 .local_val => return &self.cast(LocalVal).?.gen_zir.decl.container.file_scope.tree,
437 .local_ptr => return &self.cast(LocalPtr).?.gen_zir.decl.container.file_scope.tree,447 .local_ptr => return &self.cast(LocalPtr).?.gen_zir.decl.container.file_scope.tree,
438 .container => return &self.cast(Container).?.file_scope.tree,448 .container => return &self.cast(Container).?.file_scope.tree,
449 .gen_suspend => return &self.cast(GenZIR).?.decl.container.file_scope.tree,
450 .gen_nosuspend => return &self.cast(Nosuspend).?.gen_zir.decl.container.file_scope.tree,
439 }451 }
440 }452 }
441453
...@@ -443,9 +455,10 @@ pub const Scope = struct {...@@ -443,9 +455,10 @@ pub const Scope = struct {
443 pub fn getGenZIR(self: *Scope) *GenZIR {455 pub fn getGenZIR(self: *Scope) *GenZIR {
444 return switch (self.tag) {456 return switch (self.tag) {
445 .block => unreachable,457 .block => unreachable,
446 .gen_zir => self.cast(GenZIR).?,458 .gen_zir, .gen_suspend => self.cast(GenZIR).?,
447 .local_val => return self.cast(LocalVal).?.gen_zir,459 .local_val => return self.cast(LocalVal).?.gen_zir,
448 .local_ptr => return self.cast(LocalPtr).?.gen_zir,460 .local_ptr => return self.cast(LocalPtr).?.gen_zir,
461 .gen_nosuspend => return self.cast(Nosuspend).?.gen_zir,
449 .file => unreachable,462 .file => unreachable,
450 .container => unreachable,463 .container => unreachable,
451 };464 };
...@@ -461,6 +474,8 @@ pub const Scope = struct {...@@ -461,6 +474,8 @@ pub const Scope = struct {
461 .gen_zir => unreachable,474 .gen_zir => unreachable,
462 .local_val => unreachable,475 .local_val => unreachable,
463 .local_ptr => unreachable,476 .local_ptr => unreachable,
477 .gen_suspend => unreachable,
478 .gen_nosuspend => unreachable,
464 }479 }
465 }480 }
466481
...@@ -472,6 +487,8 @@ pub const Scope = struct {...@@ -472,6 +487,8 @@ pub const Scope = struct {
472 .local_val => unreachable,487 .local_val => unreachable,
473 .local_ptr => unreachable,488 .local_ptr => unreachable,
474 .block => unreachable,489 .block => unreachable,
490 .gen_suspend => unreachable,
491 .gen_nosuspend => unreachable,
475 }492 }
476 }493 }
477494
...@@ -486,6 +503,36 @@ pub const Scope = struct {...@@ -486,6 +503,36 @@ pub const Scope = struct {
486 .local_val => @fieldParentPtr(LocalVal, "base", cur).parent,503 .local_val => @fieldParentPtr(LocalVal, "base", cur).parent,
487 .local_ptr => @fieldParentPtr(LocalPtr, "base", cur).parent,504 .local_ptr => @fieldParentPtr(LocalPtr, "base", cur).parent,
488 .block => return @fieldParentPtr(Block, "base", cur).src_decl.container.file_scope,505 .block => return @fieldParentPtr(Block, "base", cur).src_decl.container.file_scope,
506 .gen_suspend => @fieldParentPtr(GenZIR, "base", cur).parent,
507 .gen_nosuspend => @fieldParentPtr(Nosuspend, "base", cur).parent,
508 };
509 }
510 }
511
512 pub fn getSuspend(base: *Scope) ?*Scope.GenZIR {
513 var cur = base;
514 while (true) {
515 cur = switch (cur.tag) {
516 .gen_zir => @fieldParentPtr(GenZIR, "base", cur).parent,
517 .local_val => @fieldParentPtr(LocalVal, "base", cur).parent,
518 .local_ptr => @fieldParentPtr(LocalPtr, "base", cur).parent,
519 .gen_nosuspend => @fieldParentPtr(Nosuspend, "base", cur).parent,
520 .gen_suspend => return @fieldParentPtr(GenZIR, "base", cur),
521 else => return null,
522 };
523 }
524 }
525
526 pub fn getNosuspend(base: *Scope) ?*Scope.Nosuspend {
527 var cur = base;
528 while (true) {
529 cur = switch (cur.tag) {
530 .gen_zir => @fieldParentPtr(GenZIR, "base", cur).parent,
531 .local_val => @fieldParentPtr(LocalVal, "base", cur).parent,
532 .local_ptr => @fieldParentPtr(LocalPtr, "base", cur).parent,
533 .gen_suspend => @fieldParentPtr(GenZIR, "base", cur).parent,
534 .gen_nosuspend => return @fieldParentPtr(Nosuspend, "base", cur),
535 else => return null,
489 };536 };
490 }537 }
491 }538 }
...@@ -507,6 +554,8 @@ pub const Scope = struct {...@@ -507,6 +554,8 @@ pub const Scope = struct {
507 gen_zir,554 gen_zir,
508 local_val,555 local_val,
509 local_ptr,556 local_ptr,
557 gen_suspend,
558 gen_nosuspend,
510 };559 };
511560
512 pub const Container = struct {561 pub const Container = struct {
...@@ -740,6 +789,8 @@ pub const Scope = struct {...@@ -740,6 +789,8 @@ pub const Scope = struct {
740 /// so they can possibly be elided later if the labeled block ends up not needing789 /// so they can possibly be elided later if the labeled block ends up not needing
741 /// a result location pointer.790 /// a result location pointer.
742 labeled_store_to_block_ptr_list: std.ArrayListUnmanaged(*zir.Inst.BinOp) = .{},791 labeled_store_to_block_ptr_list: std.ArrayListUnmanaged(*zir.Inst.BinOp) = .{},
792 /// for suspend error notes
793 src: usize = 0,
743794
744 pub const Label = struct {795 pub const Label = struct {
745 token: ast.TokenIndex,796 token: ast.TokenIndex,
...@@ -773,6 +824,16 @@ pub const Scope = struct {...@@ -773,6 +824,16 @@ pub const Scope = struct {
773 name: []const u8,824 name: []const u8,
774 ptr: *zir.Inst,825 ptr: *zir.Inst,
775 };826 };
827
828 pub const Nosuspend = struct {
829 pub const base_tag: Tag = .gen_nosuspend;
830
831 base: Scope = Scope{ .tag = base_tag },
832 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZIR`.
833 parent: *Scope,
834 gen_zir: *GenZIR,
835 src: usize,
836 };
776};837};
777838
778/// This struct holds data necessary to construct API-facing `AllErrors.Message`.839/// This struct holds data necessary to construct API-facing `AllErrors.Message`.
...@@ -3586,7 +3647,7 @@ pub fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, err_msg: *ErrorMsg) I...@@ -3586,7 +3647,7 @@ pub fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, err_msg: *ErrorMsg) I
3586 }3647 }
3587 self.failed_decls.putAssumeCapacityNoClobber(block.owner_decl, err_msg);3648 self.failed_decls.putAssumeCapacityNoClobber(block.owner_decl, err_msg);
3588 },3649 },
3589 .gen_zir => {3650 .gen_zir, .gen_suspend => {
3590 const gen_zir = scope.cast(Scope.GenZIR).?;3651 const gen_zir = scope.cast(Scope.GenZIR).?;
3591 gen_zir.decl.analysis = .sema_failure;3652 gen_zir.decl.analysis = .sema_failure;
3592 gen_zir.decl.generation = self.generation;3653 gen_zir.decl.generation = self.generation;
...@@ -3604,6 +3665,12 @@ pub fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, err_msg: *ErrorMsg) I...@@ -3604,6 +3665,12 @@ pub fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, err_msg: *ErrorMsg) I
3604 gen_zir.decl.generation = self.generation;3665 gen_zir.decl.generation = self.generation;
3605 self.failed_decls.putAssumeCapacityNoClobber(gen_zir.decl, err_msg);3666 self.failed_decls.putAssumeCapacityNoClobber(gen_zir.decl, err_msg);
3606 },3667 },
3668 .gen_nosuspend => {
3669 const gen_zir = scope.cast(Scope.Nosuspend).?.gen_zir;
3670 gen_zir.decl.analysis = .sema_failure;
3671 gen_zir.decl.generation = self.generation;
3672 self.failed_decls.putAssumeCapacityNoClobber(gen_zir.decl, err_msg);
3673 },
3607 .file => unreachable,3674 .file => unreachable,
3608 .container => unreachable,3675 .container => unreachable,
3609 }3676 }
src/astgen.zig+110-5
...@@ -626,10 +626,13 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In...@@ -626,10 +626,13 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
626 .@"comptime" => return comptimeExpr(mod, scope, rl, node_datas[node].lhs),626 .@"comptime" => return comptimeExpr(mod, scope, rl, node_datas[node].lhs),
627 .@"switch", .switch_comma => return switchExpr(mod, scope, rl, node),627 .@"switch", .switch_comma => return switchExpr(mod, scope, rl, node),
628628
629 .@"nosuspend" => return nosuspendExpr(mod, scope, rl, node),
630 .@"suspend" => return rvalue(mod, scope, rl, try suspendExpr(mod, scope, node)),
631 .@"await" => return awaitExpr(mod, scope, rl, node),
632 .@"resume" => return rvalue(mod, scope, rl, try resumeExpr(mod, scope, node)),
633
629 .@"defer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .defer", .{}),634 .@"defer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .defer", .{}),
630 .@"errdefer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .errdefer", .{}),635 .@"errdefer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .errdefer", .{}),
631 .@"await" => return mod.failNode(scope, node, "TODO implement astgen.expr for .await", .{}),
632 .@"resume" => return mod.failNode(scope, node, "TODO implement astgen.expr for .resume", .{}),
633 .@"try" => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}),636 .@"try" => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}),
634637
635 .array_init_one,638 .array_init_one,
...@@ -652,15 +655,12 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In...@@ -652,15 +655,12 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
652 .struct_init_comma,655 .struct_init_comma,
653 => return mod.failNode(scope, node, "TODO implement astgen.expr for struct literals", .{}),656 => return mod.failNode(scope, node, "TODO implement astgen.expr for struct literals", .{}),
654657
655 .@"suspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .suspend", .{}),
656 .@"anytype" => return mod.failNode(scope, node, "TODO implement astgen.expr for .anytype", .{}),658 .@"anytype" => return mod.failNode(scope, node, "TODO implement astgen.expr for .anytype", .{}),
657 .fn_proto_simple,659 .fn_proto_simple,
658 .fn_proto_multi,660 .fn_proto_multi,
659 .fn_proto_one,661 .fn_proto_one,
660 .fn_proto,662 .fn_proto,
661 => return mod.failNode(scope, node, "TODO implement astgen.expr for function prototypes", .{}),663 => return mod.failNode(scope, node, "TODO implement astgen.expr for function prototypes", .{}),
662
663 .@"nosuspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .nosuspend", .{}),
664 }664 }
665}665}
666666
...@@ -766,6 +766,8 @@ fn breakExpr(...@@ -766,6 +766,8 @@ fn breakExpr(
766 },766 },
767 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,767 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
768 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,768 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
769 .gen_suspend => scope = scope.cast(Scope.GenZIR).?.parent,
770 .gen_nosuspend => scope = scope.cast(Scope.Nosuspend).?.parent,
769 else => if (break_label != 0) {771 else => if (break_label != 0) {
770 const label_name = try mod.identifierTokenString(parent_scope, break_label);772 const label_name = try mod.identifierTokenString(parent_scope, break_label);
771 return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name});773 return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name});
...@@ -819,6 +821,8 @@ fn continueExpr(...@@ -819,6 +821,8 @@ fn continueExpr(
819 },821 },
820 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,822 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
821 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,823 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
824 .gen_suspend => scope = scope.cast(Scope.GenZIR).?.parent,
825 .gen_nosuspend => scope = scope.cast(Scope.Nosuspend).?.parent,
822 else => if (break_label != 0) {826 else => if (break_label != 0) {
823 const label_name = try mod.identifierTokenString(parent_scope, break_label);827 const label_name = try mod.identifierTokenString(parent_scope, break_label);
824 return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name});828 return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name});
...@@ -893,6 +897,8 @@ fn checkLabelRedefinition(mod: *Module, parent_scope: *Scope, label: ast.TokenIn...@@ -893,6 +897,8 @@ fn checkLabelRedefinition(mod: *Module, parent_scope: *Scope, label: ast.TokenIn
893 },897 },
894 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,898 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
895 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,899 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
900 .gen_suspend => scope = scope.cast(Scope.GenZIR).?.parent,
901 .gen_nosuspend => scope = scope.cast(Scope.Nosuspend).?.parent,
896 else => return,902 else => return,
897 }903 }
898 }904 }
...@@ -1100,6 +1106,8 @@ fn varDecl(...@@ -1100,6 +1106,8 @@ fn varDecl(
1100 s = local_ptr.parent;1106 s = local_ptr.parent;
1101 },1107 },
1102 .gen_zir => s = s.cast(Scope.GenZIR).?.parent,1108 .gen_zir => s = s.cast(Scope.GenZIR).?.parent,
1109 .gen_suspend => s = s.cast(Scope.GenZIR).?.parent,
1110 .gen_nosuspend => s = s.cast(Scope.Nosuspend).?.parent,
1103 else => break,1111 else => break,
1104 };1112 };
1105 }1113 }
...@@ -3021,6 +3029,8 @@ fn identifier(...@@ -3021,6 +3029,8 @@ fn identifier(
3021 s = local_ptr.parent;3029 s = local_ptr.parent;
3022 },3030 },
3023 .gen_zir => s = s.cast(Scope.GenZIR).?.parent,3031 .gen_zir => s = s.cast(Scope.GenZIR).?.parent,
3032 .gen_suspend => s = s.cast(Scope.GenZIR).?.parent,
3033 .gen_nosuspend => s = s.cast(Scope.Nosuspend).?.parent,
3024 else => break,3034 else => break,
3025 };3035 };
3026 }3036 }
...@@ -3633,14 +3643,109 @@ fn callExpr(...@@ -3633,14 +3643,109 @@ fn callExpr(
3633 }3643 }
36343644
3635 const src = token_starts[call.ast.lparen];3645 const src = token_starts[call.ast.lparen];
3646 var modifier: std.builtin.CallOptions.Modifier = .auto;
3647 if (call.async_token) |_| modifier = .async_kw;
3648
3636 const result = try addZIRInst(mod, scope, src, zir.Inst.Call, .{3649 const result = try addZIRInst(mod, scope, src, zir.Inst.Call, .{
3637 .func = lhs,3650 .func = lhs,
3638 .args = args,3651 .args = args,
3652 .modifier = modifier,
3639 }, .{});3653 }, .{});
3640 // TODO function call with result location3654 // TODO function call with result location
3641 return rvalue(mod, scope, rl, result);3655 return rvalue(mod, scope, rl, result);
3642}3656}
36433657
3658fn suspendExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.Inst {
3659 const tree = scope.tree();
3660 const src = tree.tokens.items(.start)[tree.nodes.items(.main_token)[node]];
3661
3662 if (scope.getNosuspend()) |some| {
3663 const msg = msg: {
3664 const msg = try mod.errMsg(scope, src, "suspend in nosuspend block", .{});
3665 errdefer msg.destroy(mod.gpa);
3666 try mod.errNote(scope, some.src, msg, "nosuspend block here", .{});
3667 break :msg msg;
3668 };
3669 return mod.failWithOwnedErrorMsg(scope, msg);
3670 }
3671
3672 if (scope.getSuspend()) |some| {
3673 const msg = msg: {
3674 const msg = try mod.errMsg(scope, src, "cannot suspend inside suspend block", .{});
3675 errdefer msg.destroy(mod.gpa);
3676 try mod.errNote(scope, some.src, msg, "other suspend block here", .{});
3677 break :msg msg;
3678 };
3679 return mod.failWithOwnedErrorMsg(scope, msg);
3680 }
3681
3682 var suspend_scope: Scope.GenZIR = .{
3683 .base = .{ .tag = .gen_suspend },
3684 .parent = scope,
3685 .decl = scope.ownerDecl().?,
3686 .arena = scope.arena(),
3687 .force_comptime = scope.isComptime(),
3688 .instructions = .{},
3689 };
3690 defer suspend_scope.instructions.deinit(mod.gpa);
3691
3692 const operand = tree.nodes.items(.data)[node].lhs;
3693 if (operand != 0) {
3694 const possibly_unused_result = try expr(mod, &suspend_scope.base, .none, operand);
3695 if (!possibly_unused_result.tag.isNoReturn()) {
3696 _ = try addZIRUnOp(mod, &suspend_scope.base, src, .ensure_result_used, possibly_unused_result);
3697 }
3698 } else {
3699 return addZIRNoOp(mod, scope, src, .@"suspend");
3700 }
3701
3702 const block = try addZIRInstBlock(mod, scope, src, .suspend_block, .{
3703 .instructions = try scope.arena().dupe(*zir.Inst, suspend_scope.instructions.items),
3704 });
3705 return &block.base;
3706}
3707
3708fn nosuspendExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!*zir.Inst {
3709 const tree = scope.tree();
3710 var child_scope = Scope.Nosuspend{
3711 .parent = scope,
3712 .gen_zir = scope.getGenZIR(),
3713 .src = tree.tokens.items(.start)[tree.nodes.items(.main_token)[node]],
3714 };
3715
3716 return expr(mod, &child_scope.base, rl, tree.nodes.items(.data)[node].lhs);
3717}
3718
3719fn awaitExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!*zir.Inst {
3720 const tree = scope.tree();
3721 const src = tree.tokens.items(.start)[tree.nodes.items(.main_token)[node]];
3722 const is_nosuspend = scope.getNosuspend() != null;
3723
3724 // TODO some @asyncCall stuff
3725
3726 if (scope.getSuspend()) |some| {
3727 const msg = msg: {
3728 const msg = try mod.errMsg(scope, src, "cannot await inside suspend block", .{});
3729 errdefer msg.destroy(mod.gpa);
3730 try mod.errNote(scope, some.src, msg, "suspend block here", .{});
3731 break :msg msg;
3732 };
3733 return mod.failWithOwnedErrorMsg(scope, msg);
3734 }
3735
3736 const operand = try expr(mod, scope, .ref, tree.nodes.items(.data)[node].lhs);
3737 // TODO pass result location
3738 return addZIRUnOp(mod, scope, src, if (is_nosuspend) .nosuspend_await else .@"await", operand);
3739}
3740
3741fn resumeExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.Inst {
3742 const tree = scope.tree();
3743 const src = tree.tokens.items(.start)[tree.nodes.items(.main_token)[node]];
3744
3745 const operand = try expr(mod, scope, .ref, tree.nodes.items(.data)[node].lhs);
3746 return addZIRUnOp(mod, scope, src, .@"resume", operand);
3747}
3748
3644pub const simple_types = std.ComptimeStringMap(Value.Tag, .{3749pub const simple_types = std.ComptimeStringMap(Value.Tag, .{
3645 .{ "u8", .u8_type },3750 .{ "u8", .u8_type },
3646 .{ "i8", .i8_type },3751 .{ "i8", .i8_type },
src/zir.zig+21
...@@ -61,6 +61,8 @@ pub const Inst = struct {...@@ -61,6 +61,8 @@ pub const Inst = struct {
61 as,61 as,
62 /// Inline assembly.62 /// Inline assembly.
63 @"asm",63 @"asm",
64 /// Await an async function.
65 @"await",
64 /// Bitwise AND. `&`66 /// Bitwise AND. `&`
65 bit_and,67 bit_and,
66 /// TODO delete this instruction, it has no purpose.68 /// TODO delete this instruction, it has no purpose.
...@@ -212,6 +214,8 @@ pub const Inst = struct {...@@ -212,6 +214,8 @@ pub const Inst = struct {
212 mul,214 mul,
213 /// Twos complement wrapping integer multiplication.215 /// Twos complement wrapping integer multiplication.
214 mulwrap,216 mulwrap,
217 /// An await inside a nosuspend scope.
218 nosuspend_await,
215 /// Given a reference to a function and a parameter index, returns the219 /// Given a reference to a function and a parameter index, returns the
216 /// type of the parameter. TODO what happens when the parameter is `anytype`?220 /// type of the parameter. TODO what happens when the parameter is `anytype`?
217 param_type,221 param_type,
...@@ -226,6 +230,8 @@ pub const Inst = struct {...@@ -226,6 +230,8 @@ pub const Inst = struct {
226 /// the memory location is in the stack frame, local to the scope containing the230 /// the memory location is in the stack frame, local to the scope containing the
227 /// instruction.231 /// instruction.
228 ref,232 ref,
233 /// Resume an async function.
234 @"resume",
229 /// Obtains a pointer to the return value.235 /// Obtains a pointer to the return value.
230 ret_ptr,236 ret_ptr,
231 /// Obtains the return type of the in-scope function.237 /// Obtains the return type of the in-scope function.
...@@ -348,6 +354,11 @@ pub const Inst = struct {...@@ -348,6 +354,11 @@ pub const Inst = struct {
348 enum_type,354 enum_type,
349 /// Does nothing; returns a void value.355 /// Does nothing; returns a void value.
350 void_value,356 void_value,
357 /// Suspend an async function.
358 @"suspend",
359 /// Suspend an async function.
360 /// Same as .suspend but with a block.
361 suspend_block,
351 /// A switch expression.362 /// A switch expression.
352 switchbr,363 switchbr,
353 /// Same as `switchbr` but the target is a pointer to the value being switched on.364 /// Same as `switchbr` but the target is a pointer to the value being switched on.
...@@ -369,6 +380,7 @@ pub const Inst = struct {...@@ -369,6 +380,7 @@ pub const Inst = struct {
369 .unreachable_unsafe,380 .unreachable_unsafe,
370 .unreachable_safe,381 .unreachable_safe,
371 .void_value,382 .void_value,
383 .@"suspend",
372 => NoOp,384 => NoOp,
373385
374 .alloc,386 .alloc,
...@@ -417,6 +429,9 @@ pub const Inst = struct {...@@ -417,6 +429,9 @@ pub const Inst = struct {
417 .import,429 .import,
418 .set_eval_branch_quota,430 .set_eval_branch_quota,
419 .indexable_ptr_len,431 .indexable_ptr_len,
432 .@"resume",
433 .@"await",
434 .nosuspend_await,
420 => UnOp,435 => UnOp,
421436
422 .add,437 .add,
...@@ -461,6 +476,7 @@ pub const Inst = struct {...@@ -461,6 +476,7 @@ pub const Inst = struct {
461 .block_flat,476 .block_flat,
462 .block_comptime,477 .block_comptime,
463 .block_comptime_flat,478 .block_comptime_flat,
479 .suspend_block,
464 => Block,480 => Block,
465481
466 .switchbr, .switchbr_ref => SwitchBr,482 .switchbr, .switchbr_ref => SwitchBr,
...@@ -633,6 +649,9 @@ pub const Inst = struct {...@@ -633,6 +649,9 @@ pub const Inst = struct {
633 .struct_type,649 .struct_type,
634 .void_value,650 .void_value,
635 .switch_range,651 .switch_range,
652 .@"resume",
653 .@"await",
654 .nosuspend_await,
636 => false,655 => false,
637656
638 .@"break",657 .@"break",
...@@ -649,6 +668,8 @@ pub const Inst = struct {...@@ -649,6 +668,8 @@ pub const Inst = struct {
649 .container_field,668 .container_field,
650 .switchbr,669 .switchbr,
651 .switchbr_ref,670 .switchbr_ref,
671 .@"suspend",
672 .suspend_block,
652 => true,673 => true,
653 };674 };
654 }675 }
src/zir_sema.zig+23-2
...@@ -160,6 +160,11 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!...@@ -160,6 +160,11 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
160 .switchbr => return zirSwitchBr(mod, scope, old_inst.castTag(.switchbr).?, false),160 .switchbr => return zirSwitchBr(mod, scope, old_inst.castTag(.switchbr).?, false),
161 .switchbr_ref => return zirSwitchBr(mod, scope, old_inst.castTag(.switchbr_ref).?, true),161 .switchbr_ref => return zirSwitchBr(mod, scope, old_inst.castTag(.switchbr_ref).?, true),
162 .switch_range => return zirSwitchRange(mod, scope, old_inst.castTag(.switch_range).?),162 .switch_range => return zirSwitchRange(mod, scope, old_inst.castTag(.switch_range).?),
163 .@"await" => return zirAwait(mod, scope, old_inst.castTag(.@"await").?),
164 .nosuspend_await => return zirAwait(mod, scope, old_inst.castTag(.nosuspend_await).?),
165 .@"resume" => return zirResume(mod, scope, old_inst.castTag(.@"resume").?),
166 .@"suspend" => return zirSuspend(mod, scope, old_inst.castTag(.@"suspend").?),
167 .suspend_block => return zirSuspendBlock(mod, scope, old_inst.castTag(.suspend_block).?),
163168
164 .container_field_named,169 .container_field_named,
165 .container_field_typed,170 .container_field_typed,
...@@ -1080,6 +1085,22 @@ fn zirFn(mod: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!*Inst {...@@ -1080,6 +1085,22 @@ fn zirFn(mod: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError!*Inst {
1080 });1085 });
1081}1086}
10821087
1088fn zirAwait(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
1089 return mod.fail(scope, inst.base.src, "TODO implement await", .{});
1090}
1091
1092fn zirResume(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
1093 return mod.fail(scope, inst.base.src, "TODO implement resume", .{});
1094}
1095
1096fn zirSuspend(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {
1097 return mod.fail(scope, inst.base.src, "TODO implement suspend", .{});
1098}
1099
1100fn zirSuspendBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerError!*Inst {
1101 return mod.fail(scope, inst.base.src, "TODO implement suspend", .{});
1102}
1103
1083fn zirIntType(mod: *Module, scope: *Scope, inttype: *zir.Inst.IntType) InnerError!*Inst {1104fn zirIntType(mod: *Module, scope: *Scope, inttype: *zir.Inst.IntType) InnerError!*Inst {
1084 const tracy = trace(@src());1105 const tracy = trace(@src());
1085 defer tracy.end();1106 defer tracy.end();
...@@ -2046,7 +2067,7 @@ fn zirBitwise(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*In...@@ -2046,7 +2067,7 @@ fn zirBitwise(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*In
2046 rhs.ty.arrayLen(),2067 rhs.ty.arrayLen(),
2047 });2068 });
2048 }2069 }
2049 return mod.fail(scope, inst.base.src, "TODO implement support for vectors in analyzeInstBitwise", .{});2070 return mod.fail(scope, inst.base.src, "TODO implement support for vectors in zirBitwise", .{});
2050 } else if (lhs.ty.zigTypeTag() == .Vector or rhs.ty.zigTypeTag() == .Vector) {2071 } else if (lhs.ty.zigTypeTag() == .Vector or rhs.ty.zigTypeTag() == .Vector) {
2051 return mod.fail(scope, inst.base.src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{2072 return mod.fail(scope, inst.base.src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{
2052 lhs.ty,2073 lhs.ty,
...@@ -2127,7 +2148,7 @@ fn zirArithmetic(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!...@@ -2127,7 +2148,7 @@ fn zirArithmetic(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!
2127 rhs.ty.arrayLen(),2148 rhs.ty.arrayLen(),
2128 });2149 });
2129 }2150 }
2130 return mod.fail(scope, inst.base.src, "TODO implement support for vectors in analyzeInstBinOp", .{});2151 return mod.fail(scope, inst.base.src, "TODO implement support for vectors in zirBinOp", .{});
2131 } else if (lhs.ty.zigTypeTag() == .Vector or rhs.ty.zigTypeTag() == .Vector) {2152 } else if (lhs.ty.zigTypeTag() == .Vector or rhs.ty.zigTypeTag() == .Vector) {
2132 return mod.fail(scope, inst.base.src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{2153 return mod.fail(scope, inst.base.src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{
2133 lhs.ty,2154 lhs.ty,