| ... | ... | @@ -88,7 +88,7 @@ fn varDecl(mod: *Module, scope: *Scope, node: *ast.Node.VarDecl) InnerError!Scop |
| 88 | 88 | // or an rvalue as a result location. If it is an rvalue, we can use the instruction as |
| 89 | 89 | // the variable, no memory location needed. |
| 90 | 90 | const init_node = node.getTrailer("init_node").?; |
| 91 | | if (nodeNeedsMemoryLocation(init_node)) { |
| 91 | if (nodeMayNeedMemoryLocation(init_node)) { |
| 92 | 92 | return mod.failNode(scope, init_node, "TODO implement result locations", .{}); |
| 93 | 93 | } |
| 94 | 94 | const init_inst = try expr(mod, scope, init_node); |
| ... | ... | @@ -579,120 +579,130 @@ fn getSimplePrimitiveValue(name: []const u8) ?TypedValue { |
| 579 | 579 | return null; |
| 580 | 580 | } |
| 581 | 581 | |
| 582 | | fn nodeNeedsMemoryLocation(node: *ast.Node) bool { |
| 583 | | return switch (node.tag) { |
| 584 | | .Root, |
| 585 | | .Use, |
| 586 | | .TestDecl, |
| 587 | | .DocComment, |
| 588 | | .SwitchCase, |
| 589 | | .SwitchElse, |
| 590 | | .Else, |
| 591 | | .Payload, |
| 592 | | .PointerPayload, |
| 593 | | .PointerIndexPayload, |
| 594 | | .ContainerField, |
| 595 | | .ErrorTag, |
| 596 | | .FieldInitializer, |
| 597 | | => unreachable, |
| 598 | | |
| 599 | | .ControlFlowExpression, |
| 600 | | .BitNot, |
| 601 | | .BoolNot, |
| 602 | | .VarDecl, |
| 603 | | .Defer, |
| 604 | | .AddressOf, |
| 605 | | .OptionalType, |
| 606 | | .Negation, |
| 607 | | .NegationWrap, |
| 608 | | .Resume, |
| 609 | | .ArrayType, |
| 610 | | .ArrayTypeSentinel, |
| 611 | | .PtrType, |
| 612 | | .SliceType, |
| 613 | | .Suspend, |
| 614 | | .AnyType, |
| 615 | | .ErrorType, |
| 616 | | .FnProto, |
| 617 | | .AnyFrameType, |
| 618 | | .IntegerLiteral, |
| 619 | | .FloatLiteral, |
| 620 | | .EnumLiteral, |
| 621 | | .StringLiteral, |
| 622 | | .MultilineStringLiteral, |
| 623 | | .CharLiteral, |
| 624 | | .BoolLiteral, |
| 625 | | .NullLiteral, |
| 626 | | .UndefinedLiteral, |
| 627 | | .Unreachable, |
| 628 | | .Identifier, |
| 629 | | .ErrorSetDecl, |
| 630 | | .ContainerDecl, |
| 631 | | .Asm, |
| 632 | | .Add, |
| 633 | | .AddWrap, |
| 634 | | .ArrayCat, |
| 635 | | .ArrayMult, |
| 636 | | .Assign, |
| 637 | | .AssignBitAnd, |
| 638 | | .AssignBitOr, |
| 639 | | .AssignBitShiftLeft, |
| 640 | | .AssignBitShiftRight, |
| 641 | | .AssignBitXor, |
| 642 | | .AssignDiv, |
| 643 | | .AssignSub, |
| 644 | | .AssignSubWrap, |
| 645 | | .AssignMod, |
| 646 | | .AssignAdd, |
| 647 | | .AssignAddWrap, |
| 648 | | .AssignMul, |
| 649 | | .AssignMulWrap, |
| 650 | | .BangEqual, |
| 651 | | .BitAnd, |
| 652 | | .BitOr, |
| 653 | | .BitShiftLeft, |
| 654 | | .BitShiftRight, |
| 655 | | .BitXor, |
| 656 | | .BoolAnd, |
| 657 | | .BoolOr, |
| 658 | | .Div, |
| 659 | | .EqualEqual, |
| 660 | | .ErrorUnion, |
| 661 | | .GreaterOrEqual, |
| 662 | | .GreaterThan, |
| 663 | | .LessOrEqual, |
| 664 | | .LessThan, |
| 665 | | .MergeErrorSets, |
| 666 | | .Mod, |
| 667 | | .Mul, |
| 668 | | .MulWrap, |
| 669 | | .Range, |
| 670 | | .Period, |
| 671 | | .Sub, |
| 672 | | .SubWrap, |
| 673 | | => false, |
| 674 | | |
| 675 | | .ArrayInitializer, |
| 676 | | .ArrayInitializerDot, |
| 677 | | .StructInitializer, |
| 678 | | .StructInitializerDot, |
| 679 | | => true, |
| 680 | | |
| 681 | | .GroupedExpression => nodeNeedsMemoryLocation(node.castTag(.GroupedExpression).?.expr), |
| 682 | | |
| 683 | | .UnwrapOptional => @panic("TODO nodeNeedsMemoryLocation for UnwrapOptional"), |
| 684 | | .Catch => @panic("TODO nodeNeedsMemoryLocation for Catch"), |
| 685 | | .Await => @panic("TODO nodeNeedsMemoryLocation for Await"), |
| 686 | | .Try => @panic("TODO nodeNeedsMemoryLocation for Try"), |
| 687 | | .If => @panic("TODO nodeNeedsMemoryLocation for If"), |
| 688 | | .SuffixOp => @panic("TODO nodeNeedsMemoryLocation for SuffixOp"), |
| 689 | | .Call => @panic("TODO nodeNeedsMemoryLocation for Call"), |
| 690 | | .Switch => @panic("TODO nodeNeedsMemoryLocation for Switch"), |
| 691 | | .While => @panic("TODO nodeNeedsMemoryLocation for While"), |
| 692 | | .For => @panic("TODO nodeNeedsMemoryLocation for For"), |
| 693 | | .BuiltinCall => @panic("TODO nodeNeedsMemoryLocation for BuiltinCall"), |
| 694 | | .Comptime => @panic("TODO nodeNeedsMemoryLocation for Comptime"), |
| 695 | | .Nosuspend => @panic("TODO nodeNeedsMemoryLocation for Nosuspend"), |
| 696 | | .Block => @panic("TODO nodeNeedsMemoryLocation for Block"), |
| 697 | | }; |
| 582 | fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool { |
| 583 | var node = start_node; |
| 584 | while (true) { |
| 585 | switch (node.tag) { |
| 586 | .Root, |
| 587 | .Use, |
| 588 | .TestDecl, |
| 589 | .DocComment, |
| 590 | .SwitchCase, |
| 591 | .SwitchElse, |
| 592 | .Else, |
| 593 | .Payload, |
| 594 | .PointerPayload, |
| 595 | .PointerIndexPayload, |
| 596 | .ContainerField, |
| 597 | .ErrorTag, |
| 598 | .FieldInitializer, |
| 599 | => unreachable, |
| 600 | |
| 601 | .ControlFlowExpression, |
| 602 | .BitNot, |
| 603 | .BoolNot, |
| 604 | .VarDecl, |
| 605 | .Defer, |
| 606 | .AddressOf, |
| 607 | .OptionalType, |
| 608 | .Negation, |
| 609 | .NegationWrap, |
| 610 | .Resume, |
| 611 | .ArrayType, |
| 612 | .ArrayTypeSentinel, |
| 613 | .PtrType, |
| 614 | .SliceType, |
| 615 | .Suspend, |
| 616 | .AnyType, |
| 617 | .ErrorType, |
| 618 | .FnProto, |
| 619 | .AnyFrameType, |
| 620 | .IntegerLiteral, |
| 621 | .FloatLiteral, |
| 622 | .EnumLiteral, |
| 623 | .StringLiteral, |
| 624 | .MultilineStringLiteral, |
| 625 | .CharLiteral, |
| 626 | .BoolLiteral, |
| 627 | .NullLiteral, |
| 628 | .UndefinedLiteral, |
| 629 | .Unreachable, |
| 630 | .Identifier, |
| 631 | .ErrorSetDecl, |
| 632 | .ContainerDecl, |
| 633 | .Asm, |
| 634 | .Add, |
| 635 | .AddWrap, |
| 636 | .ArrayCat, |
| 637 | .ArrayMult, |
| 638 | .Assign, |
| 639 | .AssignBitAnd, |
| 640 | .AssignBitOr, |
| 641 | .AssignBitShiftLeft, |
| 642 | .AssignBitShiftRight, |
| 643 | .AssignBitXor, |
| 644 | .AssignDiv, |
| 645 | .AssignSub, |
| 646 | .AssignSubWrap, |
| 647 | .AssignMod, |
| 648 | .AssignAdd, |
| 649 | .AssignAddWrap, |
| 650 | .AssignMul, |
| 651 | .AssignMulWrap, |
| 652 | .BangEqual, |
| 653 | .BitAnd, |
| 654 | .BitOr, |
| 655 | .BitShiftLeft, |
| 656 | .BitShiftRight, |
| 657 | .BitXor, |
| 658 | .BoolAnd, |
| 659 | .BoolOr, |
| 660 | .Div, |
| 661 | .EqualEqual, |
| 662 | .ErrorUnion, |
| 663 | .GreaterOrEqual, |
| 664 | .GreaterThan, |
| 665 | .LessOrEqual, |
| 666 | .LessThan, |
| 667 | .MergeErrorSets, |
| 668 | .Mod, |
| 669 | .Mul, |
| 670 | .MulWrap, |
| 671 | .Range, |
| 672 | .Period, |
| 673 | .Sub, |
| 674 | .SubWrap, |
| 675 | => return false, |
| 676 | |
| 677 | // Forward the question to a sub-expression. |
| 678 | .GroupedExpression => node = node.castTag(.GroupedExpression).?.expr, |
| 679 | .Try => node = node.castTag(.Try).?.rhs, |
| 680 | .Await => node = node.castTag(.Await).?.rhs, |
| 681 | .Catch => node = node.castTag(.Catch).?.rhs, |
| 682 | .OrElse => node = node.castTag(.OrElse).?.rhs, |
| 683 | .Comptime => node = node.castTag(.Comptime).?.expr, |
| 684 | .Nosuspend => node = node.castTag(.Nosuspend).?.expr, |
| 685 | |
| 686 | // True because these are exactly the expressions we need memory locations for. |
| 687 | .ArrayInitializer, |
| 688 | .ArrayInitializerDot, |
| 689 | .StructInitializer, |
| 690 | .StructInitializerDot, |
| 691 | => return true, |
| 692 | |
| 693 | // True because depending on comptime conditions, sub-expressions |
| 694 | // may be the kind that need memory locations. |
| 695 | .While, |
| 696 | .For, |
| 697 | .Switch, |
| 698 | .Call, |
| 699 | .BuiltinCall, // TODO some of these can return false |
| 700 | .SuffixOp, // TODO this should be split up |
| 701 | => return true, |
| 702 | |
| 703 | // Depending on AST properties, they may need memory locations. |
| 704 | .If => return node.castTag(.If).?.@"else" != null, |
| 705 | .Block => return node.castTag(.Block).?.label != null, |
| 706 | } |
| 707 | } |
| 698 | 708 | } |