| author | |
| committer | |
| log | 17e6e09285ed29ead1a3de5d5bfeb4d287f23215 |
| tree | 26dce4f4fd7ec0822aa3c73af8b69ad37a60245e |
| parent | 9f722f43ac449caa0e09c1b7bb1bad0581ef323d |
| signature |
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 | } |
| 415 | 423 | ||
| ... | @@ -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 | } |
| 441 | 453 | ||
| ... | @@ -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 | } |
| 466 | 481 | ||
| ... | @@ -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 | } |
| 477 | 494 | ||
| ... | @@ -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 | }; |
| 511 | 560 | ||
| 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 needing | 789 | /// 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, | ||
| 743 | 794 | ||
| 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 | }; |
| 777 | 838 | ||
| 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), |
| 628 | 628 | ||
| 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", .{}), |
| 634 | 637 | ||
| 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", .{}), |
| 654 | 657 | ||
| 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 | } |
| 666 | 666 | ||
| ... | @@ -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 | } |
| 3634 | 3644 | ||
| 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 location | 3654 | // TODO function call with result location |
| 3641 | return rvalue(mod, scope, rl, result); | 3655 | return rvalue(mod, scope, rl, result); |
| 3642 | } | 3656 | } |
| 3643 | 3657 | ||
| 3658 | fn 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 | |||
| 3708 | fn 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 | |||
| 3719 | fn 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 | |||
| 3741 | fn 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 | |||
| 3644 | pub const simple_types = std.ComptimeStringMap(Value.Tag, .{ | 3749 | pub 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 the | 219 | /// 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 the | 230 | /// 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, |
| 373 | 385 | ||
| 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, |
| 421 | 436 | ||
| 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, |
| 465 | 481 | ||
| 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, |
| 637 | 656 | ||
| 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).?), | ||
| 163 | 168 | ||
| 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 | } |
| 1082 | 1087 | ||
| 1088 | fn zirAwait(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | ||
| 1089 | return mod.fail(scope, inst.base.src, "TODO implement await", .{}); | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | fn zirResume(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | ||
| 1093 | return mod.fail(scope, inst.base.src, "TODO implement resume", .{}); | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | fn zirSuspend(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst { | ||
| 1097 | return mod.fail(scope, inst.base.src, "TODO implement suspend", .{}); | ||
| 1098 | } | ||
| 1099 | |||
| 1100 | fn zirSuspendBlock(mod: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerError!*Inst { | ||
| 1101 | return mod.fail(scope, inst.base.src, "TODO implement suspend", .{}); | ||
| 1102 | } | ||
| 1103 | |||
| 1083 | fn zirIntType(mod: *Module, scope: *Scope, inttype: *zir.Inst.IntType) InnerError!*Inst { | 1104 | fn 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, |