| author | |
| committer | |
| log | 5d215838a79a24c21842fbc76fd77aca4c28b162 |
| tree | 4f0c95e0b2a6dea5a7b7dbcb53649d9839dadcd1 |
| parent | 065c6e7946e712dc8563c975a4ca951927145da7 |
| signature |
I've realised that the cause of at least some of our weird CI flakiness
was a bug in how `Nav` values were resolved. Consider this scenario: the
frontend resolves the type of a `Nav`, and then sends a function to the
backend, which requires the backend to lower a pointer to that `Nav`.
The backend calls `InternPool.getNav` to determine the `Nav`'s type.
However, this races with the frontend resolving the *value* of that
`Nav`. This involves writing separately to two fields, `bits` and
`type_or_value`. If only one of these changes is observed, then the
backend will incorrectly interpret the type as the value or vice versa,
leading to a crash or even a miscompilation. (Of course, there's also
the straightforward issue that the racing loads were non-atomic, making
them illegal).
The only good solution to this was to make `Nav` 4 bytes bigger, giving
it separate `type` and `value` fields. In theory that's a quite small
change, but it ended up having a bunch of nice consequences which led to
this diff being a bit bulkier than expected:
* `Nav.Repr.Bits` was simplified, because it no longer has to track
"resolution status": we can use `.none` for that. This frees up some
bits to make things more consistent between the "type resolved" and
"fully resolved" states.
* This consistency allowed the `Nav.status` union to be replaced with a
simpler field `Nav.resolved`, which is a bit nicer to work with.
* Most of the "getter" functions were able to be removed from `Nav`
because the state they were fetching had been moved to simple fields
on `Nav.resolved`.
* There were still a handful of free bits in `Nav.Repr.Bits`, which
could be used to represent the "const" and "threadlocal" flags rather
than these being stored on `Key.Extern` and `Key.Variable`. This is a
bit more convenient for linkers.
* With those bits gone, `Key.Variable` is a trivial wrapper around a
type and an initial value, and the fact that a declaration is mutable
can be represented solely through the "const" flag. Therefore,
`Key.Variable` no longer served a purpose, and could be eliminated
entirely in favour of storing the variable's initial value directly in
the "value" field of the `Nav`.
So, I'm quite pleased with this refactor! But anyway, regarding the bug
fix which actually motivated this: if I've done my job correctly, this
should solve some crashes, such as these (which were what tipped me off
to this bug in the first place):
https://codeberg.org/ziglang/zig/actions/runs/2306/jobs/7/attempt/1
https://codeberg.org/ziglang/zig/actions/runs/2173/jobs/6/attempt/1
...and, who knows, perhaps even the random SIGSEGVs we've seen on some
targets! Probably not, but one can hope.33 files changed, 593 insertions(+), 965 deletions(-)
src/IncrementalDebugServer.zig+12-9| ... | ... | @@ -215,22 +215,25 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const |
| 215 | 215 | try w.print( |
| 216 | 216 | \\name: '{f}' |
| 217 | 217 | \\fqn: '{f}' |
| 218 | \\status: {s} | |
| 219 | 218 | \\created on generation: {d} |
| 220 | 219 | \\ |
| 221 | 220 | , .{ |
| 222 | 221 | nav.name.fmt(ip), |
| 223 | 222 | nav.fqn.fmt(ip), |
| 224 | @tagName(nav.status), | |
| 225 | 223 | create_gen, |
| 226 | 224 | }); |
| 227 | switch (nav.status) { | |
| 228 | .unresolved => {}, | |
| 229 | .type_resolved, .fully_resolved => { | |
| 230 | try w.writeAll("type: "); | |
| 231 | try printType(.fromInterned(nav.typeOf(ip)), zcu, w); | |
| 232 | try w.writeByte('\n'); | |
| 233 | }, | |
| 225 | if (nav.resolved) |r| { | |
| 226 | try w.writeAll("status: resolved\n type: "); | |
| 227 | try printType(.fromInterned(r.type), zcu, w); | |
| 228 | try w.writeAll("\n value: "); | |
| 229 | if (r.value == .none) { | |
| 230 | try w.writeAll("(unresolved)"); | |
| 231 | } else { | |
| 232 | try printType(.fromInterned(r.type), zcu, w); | |
| 233 | } | |
| 234 | try w.writeByte('\n'); | |
| 235 | } else { | |
| 236 | try w.writeAll("status: unresolved\n"); | |
| 234 | 237 | } |
| 235 | 238 | } else if (std.mem.eql(u8, cmd_str, "find_type")) { |
| 236 | 239 | if (arg_str.len == 0) return w.writeAll("bad usage"); |
src/InternPool.zig+182-402| ... | ... | @@ -548,144 +548,61 @@ pub const Nav = struct { |
| 548 | 548 | /// The fully-qualified name of this `Nav`. |
| 549 | 549 | fqn: NullTerminatedString, |
| 550 | 550 | /// This field is populated iff this `Nav` is resolved by semantic analysis. |
| 551 | /// If this is `null`, then `status == .fully_resolved` always. | |
| 551 | /// If this is `null`, then `resolved` is *not* `null`. | |
| 552 | 552 | analysis: ?struct { |
| 553 | 553 | namespace: NamespaceIndex, |
| 554 | 554 | zir_index: TrackedInst.Index, |
| 555 | 555 | /// Initially `false`. Set to `true` by `setWantNavAnalysis`. |
| 556 | 556 | wanted: bool, |
| 557 | 557 | }, |
| 558 | status: union(enum) { | |
| 559 | /// This `Nav` is pending semantic analysis. | |
| 560 | unresolved, | |
| 561 | /// The type of this `Nav` is resolved; the value is queued for resolution. | |
| 562 | type_resolved: struct { | |
| 563 | type: InternPool.Index, | |
| 564 | is_const: bool, | |
| 565 | alignment: Alignment, | |
| 566 | @"linksection": OptionalNullTerminatedString, | |
| 567 | @"addrspace": std.builtin.AddressSpace, | |
| 568 | is_threadlocal: bool, | |
| 569 | /// This field is whether this `Nav` is a literal `extern` definition. | |
| 570 | /// It does *not* tell you whether this might alias an extern fn (see #21027). | |
| 571 | is_extern_decl: bool, | |
| 572 | }, | |
| 573 | /// The value of this `Nav` is resolved. | |
| 574 | fully_resolved: struct { | |
| 575 | val: InternPool.Index, | |
| 576 | is_const: bool, | |
| 577 | alignment: Alignment, | |
| 578 | @"linksection": OptionalNullTerminatedString, | |
| 579 | @"addrspace": std.builtin.AddressSpace, | |
| 580 | }, | |
| 581 | }, | |
| 582 | ||
| 583 | /// Asserts that `status != .unresolved`. | |
| 584 | pub fn typeOf(nav: Nav, ip: *const InternPool) InternPool.Index { | |
| 585 | return switch (nav.status) { | |
| 586 | .unresolved => unreachable, | |
| 587 | .type_resolved => |r| r.type, | |
| 588 | .fully_resolved => |r| ip.typeOf(r.val), | |
| 589 | }; | |
| 590 | } | |
| 591 | ||
| 592 | /// This function is intended to be used by code generation, since semantic | |
| 593 | /// analysis will ensure that any `Nav` which is potentially `extern` is | |
| 594 | /// fully resolved. | |
| 595 | /// Asserts that `status == .fully_resolved`. | |
| 596 | pub fn getResolvedExtern(nav: Nav, ip: *const InternPool) ?Key.Extern { | |
| 597 | assert(nav.status == .fully_resolved); | |
| 598 | return nav.getExtern(ip); | |
| 599 | } | |
| 600 | ||
| 601 | /// Always returns `null` for `status == .type_resolved`. This function is inteded | |
| 602 | /// to be used by code generation, since semantic analysis will ensure that any `Nav` | |
| 603 | /// which is potentially `extern` is fully resolved. | |
| 604 | /// Asserts that `status != .unresolved`. | |
| 558 | /// If this is `null`, then `analysis` is *not* `null`, and semantic analysis is required to | |
| 559 | /// resolve the type and value of this `Nav`. Otherwise, the type is resolved---therefore, | |
| 560 | /// `Nav.resolved.?.type` is never `.none`. However, the *value* may not be resolved yet even | |
| 561 | /// if this field is not `null`---see `Resolved.value` for details. | |
| 562 | resolved: ?Resolved, | |
| 563 | ||
| 564 | pub const Resolved = struct { | |
| 565 | /// This is never `.none` | |
| 566 | type: InternPool.Index, | |
| 567 | @"align": Alignment, | |
| 568 | @"linksection": OptionalNullTerminatedString, | |
| 569 | @"addrspace": std.builtin.AddressSpace, | |
| 570 | @"const": bool, | |
| 571 | @"threadlocal": bool, | |
| 572 | /// This field is whether this `Nav` is a literal `extern` definition. | |
| 573 | /// It does *not* tell you whether this might alias an extern fn (see #21027). | |
| 574 | is_extern_decl: bool, | |
| 575 | /// If the type is resolved but not the value, this is `.none`. In that case, the value will | |
| 576 | /// be resolved by semantic analysis, so `Nav.analysis` is definitely not `null`. | |
| 577 | /// | |
| 578 | /// If this is an extern, the special key `Key.@"extern"` is used. | |
| 579 | /// | |
| 580 | /// If this is a variable (`Resolved.@"const" == false`) and not an extern, then this value | |
| 581 | /// is the global variable's initializer; the value loaded from the variable at runtime may | |
| 582 | /// of course be different. | |
| 583 | value: InternPool.Index, | |
| 584 | }; | |
| 585 | ||
| 586 | /// If the value of this `Nav` is resolved and is an extern, returns the `Key.Extern`. If the | |
| 587 | /// value is *not* an extern, *or* if the value is not yet resolved (only the type is), returns | |
| 588 | /// `null`. | |
| 589 | /// | |
| 590 | /// This logic works because the frontend ensures that if a `Nav` *might* be extern, its value | |
| 591 | /// is resolved more eagerly (see logic in `Sema.analyzeNavRefInner`). Therefore, if we see that | |
| 592 | /// the value is not yet resolved, we know the frontend determined that the `Nav` is definitely | |
| 593 | /// *not* extern. | |
| 594 | /// | |
| 595 | /// This function is only intended be used by the compiler backend (codegen/link). The guarantee | |
| 596 | /// mentioned above does not necessarily hold in the compiler frontend (if we haven't reached | |
| 597 | /// `Sema.analyzeNavRefInner` yet). | |
| 598 | /// | |
| 599 | /// Asserts that `nav.resolved != null`. | |
| 605 | 600 | pub fn getExtern(nav: Nav, ip: *const InternPool) ?Key.Extern { |
| 606 | return switch (nav.status) { | |
| 607 | .unresolved => unreachable, | |
| 608 | .type_resolved => null, | |
| 609 | .fully_resolved => |r| switch (ip.indexToKey(r.val)) { | |
| 610 | .@"extern" => |e| e, | |
| 611 | else => null, | |
| 612 | }, | |
| 613 | }; | |
| 614 | } | |
| 615 | ||
| 616 | /// Asserts that `status != .unresolved`. | |
| 617 | pub fn getAddrspace(nav: Nav) std.builtin.AddressSpace { | |
| 618 | return switch (nav.status) { | |
| 619 | .unresolved => unreachable, | |
| 620 | .type_resolved => |r| r.@"addrspace", | |
| 621 | .fully_resolved => |r| r.@"addrspace", | |
| 622 | }; | |
| 623 | } | |
| 624 | ||
| 625 | /// Asserts that `status != .unresolved`. | |
| 626 | pub fn getAlignment(nav: Nav) Alignment { | |
| 627 | return switch (nav.status) { | |
| 628 | .unresolved => unreachable, | |
| 629 | .type_resolved => |r| r.alignment, | |
| 630 | .fully_resolved => |r| r.alignment, | |
| 631 | }; | |
| 632 | } | |
| 633 | ||
| 634 | /// Asserts that `status != .unresolved`. | |
| 635 | pub fn getLinkSection(nav: Nav) OptionalNullTerminatedString { | |
| 636 | return switch (nav.status) { | |
| 637 | .unresolved => unreachable, | |
| 638 | .type_resolved => |r| r.@"linksection", | |
| 639 | .fully_resolved => |r| r.@"linksection", | |
| 640 | }; | |
| 641 | } | |
| 642 | ||
| 643 | /// Asserts that `status != .unresolved`. | |
| 644 | pub fn isThreadlocal(nav: Nav, ip: *const InternPool) bool { | |
| 645 | return switch (nav.status) { | |
| 646 | .unresolved => unreachable, | |
| 647 | .type_resolved => |r| r.is_threadlocal, | |
| 648 | .fully_resolved => |r| switch (ip.indexToKey(r.val)) { | |
| 649 | .@"extern" => |e| e.is_threadlocal, | |
| 650 | .variable => |v| v.is_threadlocal, | |
| 651 | else => false, | |
| 652 | }, | |
| 653 | }; | |
| 654 | } | |
| 655 | ||
| 656 | pub fn isFn(nav: Nav, ip: *const InternPool) bool { | |
| 657 | return switch (nav.status) { | |
| 658 | .unresolved => unreachable, | |
| 659 | .type_resolved => |r| { | |
| 660 | const tag = ip.zigTypeTag(r.type); | |
| 661 | return tag == .@"fn"; | |
| 662 | }, | |
| 663 | .fully_resolved => |r| { | |
| 664 | const tag = ip.zigTypeTag(ip.typeOf(r.val)); | |
| 665 | return tag == .@"fn"; | |
| 666 | }, | |
| 667 | }; | |
| 668 | } | |
| 669 | ||
| 670 | /// If this returns `true`, then a pointer to this `Nav` might actually be encoded as a pointer | |
| 671 | /// to some other `Nav` due to an extern definition or extern alias (see #21027). | |
| 672 | /// This query is valid on `Nav`s for whom only the type is resolved. | |
| 673 | /// Asserts that `status != .unresolved`. | |
| 674 | pub fn isExternOrFn(nav: Nav, ip: *const InternPool) bool { | |
| 675 | return switch (nav.status) { | |
| 676 | .unresolved => unreachable, | |
| 677 | .type_resolved => |r| { | |
| 678 | if (r.is_extern_decl) return true; | |
| 679 | const tag = ip.zigTypeTag(r.type); | |
| 680 | if (tag == .@"fn") return true; | |
| 681 | return false; | |
| 682 | }, | |
| 683 | .fully_resolved => |r| { | |
| 684 | if (ip.indexToKey(r.val) == .@"extern") return true; | |
| 685 | const tag = ip.zigTypeTag(ip.typeOf(r.val)); | |
| 686 | if (tag == .@"fn") return true; | |
| 687 | return false; | |
| 688 | }, | |
| 601 | const r = nav.resolved.?; | |
| 602 | if (r.value == .none) return null; | |
| 603 | return switch (ip.indexToKey(r.value)) { | |
| 604 | .@"extern" => |e| e, | |
| 605 | else => null, | |
| 689 | 606 | }; |
| 690 | 607 | } |
| 691 | 608 | |
| ... | ... | @@ -696,7 +613,7 @@ pub const Nav = struct { |
| 696 | 613 | return a.zir_index; |
| 697 | 614 | } |
| 698 | 615 | // A `Nav` which does not undergo analysis always has a resolved value. |
| 699 | return switch (ip.indexToKey(nav.status.fully_resolved.val)) { | |
| 616 | return switch (ip.indexToKey(nav.resolved.?.value)) { | |
| 700 | 617 | .func => |func| { |
| 701 | 618 | // Since `analysis` was not populated, this must be an instantiation. |
| 702 | 619 | // Go up to the generic owner and consult *its* `analysis` field. |
| ... | ... | @@ -747,30 +664,26 @@ pub const Nav = struct { |
| 747 | 664 | }; |
| 748 | 665 | |
| 749 | 666 | /// The compact in-memory representation of a `Nav`. |
| 750 | /// 26 bytes. | |
| 667 | /// 30 bytes. | |
| 751 | 668 | const Repr = struct { |
| 752 | 669 | name: NullTerminatedString, |
| 753 | 670 | fqn: NullTerminatedString, |
| 754 | 671 | // The following 2 fields are either both populated, or both `.none`. |
| 755 | 672 | analysis_namespace: OptionalNamespaceIndex, |
| 756 | 673 | analysis_zir_index: TrackedInst.Index.Optional, |
| 757 | /// Populated only if `bits.status != .unresolved`. | |
| 758 | type_or_val: InternPool.Index, | |
| 759 | /// Populated only if `bits.status != .unresolved`. | |
| 674 | type: InternPool.Index, | |
| 675 | value: InternPool.Index, | |
| 760 | 676 | @"linksection": OptionalNullTerminatedString, |
| 761 | 677 | bits: Bits, |
| 762 | 678 | |
| 763 | 679 | const Bits = packed struct(u16) { |
| 764 | status: enum(u2) { unresolved, type_resolved, fully_resolved, type_resolved_extern_decl }, | |
| 765 | /// Populated only if `bits.status != .unresolved`. | |
| 766 | is_const: bool, | |
| 767 | /// Populated only if `bits.status != .unresolved`. | |
| 768 | alignment: Alignment, | |
| 769 | /// Populated only if `bits.status != .unresolved`. | |
| 680 | @"align": Alignment, | |
| 770 | 681 | @"addrspace": std.builtin.AddressSpace, |
| 771 | /// Populated only if `bits.status == .type_resolved`. | |
| 772 | is_threadlocal: bool, | |
| 682 | @"const": bool, | |
| 683 | @"threadlocal": bool, | |
| 684 | is_extern_decl: bool, | |
| 773 | 685 | want_analysis: bool, |
| 686 | _: u1 = 0, | |
| 774 | 687 | }; |
| 775 | 688 | |
| 776 | 689 | fn unpack(repr: Repr) Nav { |
| ... | ... | @@ -785,72 +698,46 @@ pub const Nav = struct { |
| 785 | 698 | assert(repr.analysis_zir_index == .none); |
| 786 | 699 | break :a null; |
| 787 | 700 | }, |
| 788 | .status = switch (repr.bits.status) { | |
| 789 | .unresolved => .unresolved, | |
| 790 | .type_resolved, .type_resolved_extern_decl => .{ .type_resolved = .{ | |
| 791 | .type = repr.type_or_val, | |
| 792 | .is_const = repr.bits.is_const, | |
| 793 | .alignment = repr.bits.alignment, | |
| 794 | .@"linksection" = repr.@"linksection", | |
| 795 | .@"addrspace" = repr.bits.@"addrspace", | |
| 796 | .is_threadlocal = repr.bits.is_threadlocal, | |
| 797 | .is_extern_decl = repr.bits.status == .type_resolved_extern_decl, | |
| 798 | } }, | |
| 799 | .fully_resolved => .{ .fully_resolved = .{ | |
| 800 | .val = repr.type_or_val, | |
| 801 | .is_const = repr.bits.is_const, | |
| 802 | .alignment = repr.bits.alignment, | |
| 803 | .@"linksection" = repr.@"linksection", | |
| 804 | .@"addrspace" = repr.bits.@"addrspace", | |
| 805 | } }, | |
| 701 | .resolved = if (repr.type == .none) null else .{ | |
| 702 | .type = repr.type, | |
| 703 | .@"align" = repr.bits.@"align", | |
| 704 | .@"linksection" = repr.@"linksection", | |
| 705 | .@"addrspace" = repr.bits.@"addrspace", | |
| 706 | .@"const" = repr.bits.@"const", | |
| 707 | .@"threadlocal" = repr.bits.@"threadlocal", | |
| 708 | .is_extern_decl = repr.bits.is_extern_decl, | |
| 709 | .value = repr.value, | |
| 806 | 710 | }, |
| 807 | 711 | }; |
| 808 | 712 | } |
| 809 | 713 | }; |
| 810 | 714 | |
| 811 | 715 | fn pack(nav: Nav) Repr { |
| 812 | // Note that in the `unresolved` case, we do not mark fields as `undefined`, even though they should not be used. | |
| 813 | // This is to avoid writing undefined bytes to disk when serializing buffers. | |
| 716 | // Note that even if `nav.resolved == null`, we do not set any fields to `undefined`, even | |
| 717 | // though they should not be used. This is to avoid writing undefined bytes to disk when | |
| 718 | // serializing buffers. | |
| 814 | 719 | return .{ |
| 815 | 720 | .name = nav.name, |
| 816 | 721 | .fqn = nav.fqn, |
| 817 | 722 | .analysis_namespace = if (nav.analysis) |a| a.namespace.toOptional() else .none, |
| 818 | 723 | .analysis_zir_index = if (nav.analysis) |a| a.zir_index.toOptional() else .none, |
| 819 | .type_or_val = switch (nav.status) { | |
| 820 | .unresolved => .none, | |
| 821 | .type_resolved => |r| r.type, | |
| 822 | .fully_resolved => |r| r.val, | |
| 823 | }, | |
| 824 | .@"linksection" = switch (nav.status) { | |
| 825 | .unresolved => .none, | |
| 826 | .type_resolved => |r| r.@"linksection", | |
| 827 | .fully_resolved => |r| r.@"linksection", | |
| 828 | }, | |
| 829 | .bits = switch (nav.status) { | |
| 830 | .unresolved => .{ | |
| 831 | .status = .unresolved, | |
| 832 | .is_const = false, | |
| 833 | .alignment = .none, | |
| 834 | .@"addrspace" = .generic, | |
| 835 | .is_threadlocal = false, | |
| 836 | .want_analysis = if (nav.analysis) |a| a.wanted else false, | |
| 837 | }, | |
| 838 | .type_resolved => |r| .{ | |
| 839 | .status = if (r.is_extern_decl) .type_resolved_extern_decl else .type_resolved, | |
| 840 | .is_const = r.is_const, | |
| 841 | .alignment = r.alignment, | |
| 842 | .@"addrspace" = r.@"addrspace", | |
| 843 | .is_threadlocal = r.is_threadlocal, | |
| 844 | .want_analysis = if (nav.analysis) |a| a.wanted else false, | |
| 845 | }, | |
| 846 | .fully_resolved => |r| .{ | |
| 847 | .status = .fully_resolved, | |
| 848 | .is_const = r.is_const, | |
| 849 | .alignment = r.alignment, | |
| 850 | .@"addrspace" = r.@"addrspace", | |
| 851 | .is_threadlocal = false, | |
| 852 | .want_analysis = if (nav.analysis) |a| a.wanted else false, | |
| 853 | }, | |
| 724 | .type = if (nav.resolved) |r| r.type else .none, | |
| 725 | .value = if (nav.resolved) |r| r.value else .none, | |
| 726 | .@"linksection" = if (nav.resolved) |r| r.@"linksection" else .none, | |
| 727 | .bits = if (nav.resolved) |r| .{ | |
| 728 | .@"align" = r.@"align", | |
| 729 | .@"addrspace" = r.@"addrspace", | |
| 730 | .@"const" = r.@"const", | |
| 731 | .@"threadlocal" = r.@"threadlocal", | |
| 732 | .is_extern_decl = r.is_extern_decl, | |
| 733 | .want_analysis = if (nav.analysis) |a| a.wanted else false, | |
| 734 | } else .{ | |
| 735 | .@"align" = .none, | |
| 736 | .@"addrspace" = .generic, | |
| 737 | .@"const" = false, | |
| 738 | .@"threadlocal" = false, | |
| 739 | .is_extern_decl = false, | |
| 740 | .want_analysis = if (nav.analysis) |a| a.wanted else false, | |
| 854 | 741 | }, |
| 855 | 742 | }; |
| 856 | 743 | } |
| ... | ... | @@ -2110,7 +1997,6 @@ pub const Key = union(enum) { |
| 2110 | 1997 | /// via `simple_value` and has a named `Index` tag for it. |
| 2111 | 1998 | undef: Index, |
| 2112 | 1999 | simple_value: SimpleValue, |
| 2113 | variable: Variable, | |
| 2114 | 2000 | @"extern": Extern, |
| 2115 | 2001 | func: Func, |
| 2116 | 2002 | int: Key.Int, |
| ... | ... | @@ -2311,14 +2197,6 @@ pub const Key = union(enum) { |
| 2311 | 2197 | } |
| 2312 | 2198 | }; |
| 2313 | 2199 | |
| 2314 | /// A runtime variable defined in this `Zcu`. | |
| 2315 | pub const Variable = struct { | |
| 2316 | ty: Index, | |
| 2317 | init: Index, | |
| 2318 | owner_nav: Nav.Index, | |
| 2319 | is_threadlocal: bool, | |
| 2320 | }; | |
| 2321 | ||
| 2322 | 2200 | pub const Extern = struct { |
| 2323 | 2201 | /// The name of the extern symbol. |
| 2324 | 2202 | name: NullTerminatedString, |
| ... | ... | @@ -2543,7 +2421,7 @@ pub const Key = union(enum) { |
| 2543 | 2421 | pub const BaseAddr = union(enum) { |
| 2544 | 2422 | const Tag = @typeInfo(BaseAddr).@"union".tag_type.?; |
| 2545 | 2423 | |
| 2546 | /// Points to the value of a single `Nav`, which may be constant or a `variable`. | |
| 2424 | /// Points to the value of a single `Nav`. | |
| 2547 | 2425 | nav: Nav.Index, |
| 2548 | 2426 | |
| 2549 | 2427 | /// Points to the value of a single comptime alloc stored in `Sema`. |
| ... | ... | @@ -2735,8 +2613,6 @@ pub const Key = union(enum) { |
| 2735 | 2613 | .payload => |y| Hash.hash(seed + 1, asBytes(&x.ty) ++ asBytes(&y)), |
| 2736 | 2614 | }, |
| 2737 | 2615 | |
| 2738 | .variable => |variable| Hash.hash(seed, asBytes(&variable.owner_nav)), | |
| 2739 | ||
| 2740 | 2616 | .opaque_type, |
| 2741 | 2617 | .enum_type, |
| 2742 | 2618 | .union_type, |
| ... | ... | @@ -3011,13 +2887,6 @@ pub const Key = union(enum) { |
| 3011 | 2887 | return a_info.ty == b_info.ty and a_info.backing_int_val == b_info.backing_int_val; |
| 3012 | 2888 | }, |
| 3013 | 2889 | |
| 3014 | .variable => |a_info| { | |
| 3015 | const b_info = b.variable; | |
| 3016 | return a_info.ty == b_info.ty and | |
| 3017 | a_info.init == b_info.init and | |
| 3018 | a_info.owner_nav == b_info.owner_nav and | |
| 3019 | a_info.is_threadlocal == b_info.is_threadlocal; | |
| 3020 | }, | |
| 3021 | 2890 | .@"extern" => |a_info| { |
| 3022 | 2891 | const b_info = b.@"extern"; |
| 3023 | 2892 | return a_info.name == b_info.name and |
| ... | ... | @@ -3277,7 +3146,6 @@ pub const Key = union(enum) { |
| 3277 | 3146 | .int, |
| 3278 | 3147 | .float, |
| 3279 | 3148 | .opt, |
| 3280 | .variable, | |
| 3281 | 3149 | .@"extern", |
| 3282 | 3150 | .func, |
| 3283 | 3151 | .err, |
| ... | ... | @@ -4390,8 +4258,6 @@ pub const Index = enum(u32) { |
| 4390 | 4258 | float_c_longdouble_f80: struct { data: *Float80 }, |
| 4391 | 4259 | float_c_longdouble_f128: struct { data: *Float128 }, |
| 4392 | 4260 | float_comptime_float: struct { data: *Float128 }, |
| 4393 | variable: struct { data: *Tag.Variable }, | |
| 4394 | threadlocal_variable: struct { data: *Tag.Variable }, | |
| 4395 | 4261 | @"extern": struct { data: *Tag.Extern }, |
| 4396 | 4262 | func_decl: struct { |
| 4397 | 4263 | const @"data.analysis.inferred_error_set" = opaque {}; |
| ... | ... | @@ -5115,12 +4981,6 @@ pub const Tag = enum(u8) { |
| 5115 | 4981 | /// A comptime_float value. |
| 5116 | 4982 | /// data is extra index to Float128. |
| 5117 | 4983 | float_comptime_float, |
| 5118 | /// A global variable. | |
| 5119 | /// data is extra index to Variable. | |
| 5120 | variable, | |
| 5121 | /// A global threadlocal variable. | |
| 5122 | /// data is extra index to Variable. | |
| 5123 | threadlocal_variable, | |
| 5124 | 4984 | /// An extern function or variable. |
| 5125 | 4985 | /// data is extra index to Extern. |
| 5126 | 4986 | /// Some parts of the key are stored in `owner_nav`. |
| ... | ... | @@ -5457,8 +5317,6 @@ pub const Tag = enum(u8) { |
| 5457 | 5317 | .float_c_longdouble_f80 = .{ .summary = .@"@as(c_longdouble, {.payload%value})", .payload = f80 }, |
| 5458 | 5318 | .float_c_longdouble_f128 = .{ .summary = .@"@as(c_longdouble, {.payload%value})", .payload = f128 }, |
| 5459 | 5319 | .float_comptime_float = .{ .summary = .@"{.payload%value}", .payload = f128 }, |
| 5460 | .variable = .{ .summary = .@"{.payload.owner_nav.fqn%summary#\"}", .payload = Variable }, | |
| 5461 | .threadlocal_variable = .{ .summary = .@"{.payload.owner_nav.fqn%summary#\"}", .payload = Variable }, | |
| 5462 | 5320 | .@"extern" = .{ .summary = .@"{.payload.owner_nav.fqn%summary#\"}", .payload = Extern }, |
| 5463 | 5321 | .func_decl = .{ |
| 5464 | 5322 | .summary = .@"{.payload.owner_nav.fqn%summary#\"}", |
| ... | ... | @@ -5505,13 +5363,6 @@ pub const Tag = enum(u8) { |
| 5505 | 5363 | return @field(encodings, @tagName(tag)).payload; |
| 5506 | 5364 | } |
| 5507 | 5365 | |
| 5508 | pub const Variable = struct { | |
| 5509 | ty: Index, | |
| 5510 | /// May be `none`. | |
| 5511 | init: Index, | |
| 5512 | owner_nav: Nav.Index, | |
| 5513 | }; | |
| 5514 | ||
| 5515 | 5366 | pub const Extern = struct { |
| 5516 | 5367 | // name, is_const, alignment, addrspace come from `owner_nav`. |
| 5517 | 5368 | ty: Index, |
| ... | ... | @@ -5525,12 +5376,11 @@ pub const Tag = enum(u8) { |
| 5525 | 5376 | pub const Flags = packed struct(u32) { |
| 5526 | 5377 | linkage: std.builtin.GlobalLinkage, |
| 5527 | 5378 | visibility: std.builtin.SymbolVisibility, |
| 5528 | is_threadlocal: bool, | |
| 5529 | 5379 | is_dll_import: bool, |
| 5530 | 5380 | relocation: std.builtin.ExternOptions.Relocation, |
| 5531 | 5381 | source: Source, |
| 5532 | 5382 | decoration_type: DecorationType, |
| 5533 | _: u22 = 0, | |
| 5383 | _: u23 = 0, | |
| 5534 | 5384 | |
| 5535 | 5385 | pub const Source = enum(u1) { builtin, syntax }; |
| 5536 | 5386 | pub const DecorationType = enum(u2) { none, location, descriptor }; |
| ... | ... | @@ -6894,19 +6744,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 6894 | 6744 | .ty = .comptime_float_type, |
| 6895 | 6745 | .storage = .{ .f128 = extraData(unwrapped_index.getExtra(ip), Float128, data).get() }, |
| 6896 | 6746 | } }, |
| 6897 | .variable, .threadlocal_variable => { | |
| 6898 | const extra = extraData(unwrapped_index.getExtra(ip), Tag.Variable, data); | |
| 6899 | return .{ .variable = .{ | |
| 6900 | .ty = extra.ty, | |
| 6901 | .init = extra.init, | |
| 6902 | .owner_nav = extra.owner_nav, | |
| 6903 | .is_threadlocal = switch (item.tag) { | |
| 6904 | else => unreachable, | |
| 6905 | .variable => false, | |
| 6906 | .threadlocal_variable => true, | |
| 6907 | }, | |
| 6908 | } }; | |
| 6909 | }, | |
| 6910 | 6747 | .@"extern" => { |
| 6911 | 6748 | const extra = extraData(unwrapped_index.getExtra(ip), Tag.Extern, data); |
| 6912 | 6749 | const nav = ip.getNav(extra.owner_nav); |
| ... | ... | @@ -6916,13 +6753,13 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 6916 | 6753 | .lib_name = extra.lib_name, |
| 6917 | 6754 | .linkage = extra.flags.linkage, |
| 6918 | 6755 | .visibility = extra.flags.visibility, |
| 6919 | .is_threadlocal = extra.flags.is_threadlocal, | |
| 6756 | .is_threadlocal = nav.resolved.?.@"threadlocal", | |
| 6920 | 6757 | .is_dll_import = extra.flags.is_dll_import, |
| 6921 | 6758 | .relocation = extra.flags.relocation, |
| 6922 | 6759 | .decoration = extra.decoration(), |
| 6923 | .is_const = nav.status.fully_resolved.is_const, | |
| 6924 | .alignment = nav.status.fully_resolved.alignment, | |
| 6925 | .@"addrspace" = nav.status.fully_resolved.@"addrspace", | |
| 6760 | .is_const = nav.resolved.?.@"const", | |
| 6761 | .alignment = nav.resolved.?.@"align", | |
| 6762 | .@"addrspace" = nav.resolved.?.@"addrspace", | |
| 6926 | 6763 | .zir_index = extra.zir_index, |
| 6927 | 6764 | .owner_nav = extra.owner_nav, |
| 6928 | 6765 | .source = extra.flags.source, |
| ... | ... | @@ -7516,22 +7353,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: |
| 7516 | 7353 | .func => unreachable, // use getFuncInstance() or getFuncDecl() instead |
| 7517 | 7354 | .un => unreachable, // use getUnion instead |
| 7518 | 7355 | |
| 7519 | .variable => |variable| { | |
| 7520 | const has_init = variable.init != .none; | |
| 7521 | if (has_init) assert(variable.ty == ip.typeOf(variable.init)); | |
| 7522 | items.appendAssumeCapacity(.{ | |
| 7523 | .tag = switch (variable.is_threadlocal) { | |
| 7524 | false => .variable, | |
| 7525 | true => .threadlocal_variable, | |
| 7526 | }, | |
| 7527 | .data = try addExtra(extra, Tag.Variable{ | |
| 7528 | .ty = variable.ty, | |
| 7529 | .init = variable.init, | |
| 7530 | .owner_nav = variable.owner_nav, | |
| 7531 | }), | |
| 7532 | }); | |
| 7533 | }, | |
| 7534 | ||
| 7535 | 7356 | .slice => |slice| { |
| 7536 | 7357 | assert(ip.indexToKey(slice.ty).ptr_type.flags.size == .slice); |
| 7537 | 7358 | assert(ip.indexToKey(ip.typeOf(slice.ptr)).ptr_type.flags.size == .many); |
| ... | ... | @@ -9245,14 +9066,15 @@ pub fn getExtern( |
| 9245 | 9066 | .tid = tid, |
| 9246 | 9067 | .index = items.mutate.len, |
| 9247 | 9068 | }, ip); |
| 9248 | const owner_nav = ip.createNav(gpa, io, tid, .{ | |
| 9249 | .name = key.name, | |
| 9250 | .fqn = key.name, | |
| 9251 | .val = extern_index, | |
| 9252 | .is_const = key.is_const, | |
| 9253 | .alignment = key.alignment, | |
| 9069 | const owner_nav = ip.createNav(gpa, io, tid, key.name, key.name, .{ | |
| 9070 | .type = key.ty, | |
| 9071 | .@"align" = key.alignment, | |
| 9254 | 9072 | .@"linksection" = .none, |
| 9255 | 9073 | .@"addrspace" = key.@"addrspace", |
| 9074 | .@"const" = key.is_const, | |
| 9075 | .@"threadlocal" = key.is_threadlocal, | |
| 9076 | .is_extern_decl = true, | |
| 9077 | .value = extern_index, | |
| 9256 | 9078 | }) catch unreachable; // capacity asserted above |
| 9257 | 9079 | const decoration_type, const location_or_descriptor_set, const descriptor_binding = if (key.decoration) |decoration| switch (decoration) { |
| 9258 | 9080 | .location => |location| .{ Tag.Extern.Flags.DecorationType.location, location, undefined }, |
| ... | ... | @@ -9266,7 +9088,6 @@ pub fn getExtern( |
| 9266 | 9088 | .flags = .{ |
| 9267 | 9089 | .linkage = key.linkage, |
| 9268 | 9090 | .visibility = key.visibility, |
| 9269 | .is_threadlocal = key.is_threadlocal, | |
| 9270 | 9091 | .is_dll_import = key.is_dll_import, |
| 9271 | 9092 | .relocation = key.relocation, |
| 9272 | 9093 | .decoration_type = decoration_type, |
| ... | ... | @@ -9846,14 +9667,16 @@ fn finishFuncInstance( |
| 9846 | 9667 | const nav_name = try ip.getOrPutStringFmt(gpa, io, tid, "{f}__anon_{d}", .{ |
| 9847 | 9668 | fn_owner_nav.name.fmt(ip), @intFromEnum(func_index), |
| 9848 | 9669 | }, .no_embedded_nulls); |
| 9849 | const nav_index = try ip.createNav(gpa, io, tid, .{ | |
| 9850 | .name = nav_name, | |
| 9851 | .fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, io, tid, nav_name), | |
| 9852 | .val = func_index, | |
| 9853 | .is_const = fn_owner_nav.status.fully_resolved.is_const, | |
| 9854 | .alignment = fn_owner_nav.status.fully_resolved.alignment, | |
| 9855 | .@"linksection" = fn_owner_nav.status.fully_resolved.@"linksection", | |
| 9856 | .@"addrspace" = fn_owner_nav.status.fully_resolved.@"addrspace", | |
| 9670 | const nav_fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, io, tid, nav_name); | |
| 9671 | const nav_index = try ip.createNav(gpa, io, tid, nav_name, nav_fqn, .{ | |
| 9672 | .type = ip.typeOf(func_index), | |
| 9673 | .@"align" = fn_owner_nav.resolved.?.@"align", | |
| 9674 | .@"linksection" = fn_owner_nav.resolved.?.@"linksection", | |
| 9675 | .@"addrspace" = fn_owner_nav.resolved.?.@"addrspace", | |
| 9676 | .@"const" = true, | |
| 9677 | .@"threadlocal" = false, | |
| 9678 | .is_extern_decl = false, | |
| 9679 | .value = func_index, | |
| 9857 | 9680 | }); |
| 9858 | 9681 | |
| 9859 | 9682 | // Populate the owner_nav field which was left undefined until now. |
| ... | ... | @@ -10616,20 +10439,6 @@ pub fn errorUnionPayload(ip: *const InternPool, ty: Index) Index { |
| 10616 | 10439 | return ip.indexToKey(ty).error_union_type.payload_type; |
| 10617 | 10440 | } |
| 10618 | 10441 | |
| 10619 | /// The is only legal because the initializer is not part of the hash. | |
| 10620 | pub fn mutateVarInit(ip: *InternPool, io: Io, index: Index, init_index: Index) void { | |
| 10621 | const unwrapped_index = index.unwrap(ip); | |
| 10622 | ||
| 10623 | const local = ip.getLocal(unwrapped_index.tid); | |
| 10624 | local.mutate.extra.mutex.lockUncancelable(io); | |
| 10625 | defer local.mutate.extra.mutex.unlock(io); | |
| 10626 | ||
| 10627 | const extra_items = local.shared.extra.view().items(.@"0"); | |
| 10628 | const item = unwrapped_index.getItem(ip); | |
| 10629 | assert(item.tag == .variable); | |
| 10630 | @atomicStore(u32, &extra_items[item.data + std.meta.fieldIndex(Tag.Variable, "init").?], @intFromEnum(init_index), .release); | |
| 10631 | } | |
| 10632 | ||
| 10633 | 10442 | pub fn dump(ip: *const InternPool) void { |
| 10634 | 10443 | var buffer: [4096]u8 = undefined; |
| 10635 | 10444 | const stderr = std.debug.lockStderr(&buffer); |
| ... | ... | @@ -10969,7 +10778,6 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo |
| 10969 | 10778 | .float_c_longdouble_f80 => @sizeOf(Float80), |
| 10970 | 10779 | .float_c_longdouble_f128 => @sizeOf(Float128), |
| 10971 | 10780 | .float_comptime_float => @sizeOf(Float128), |
| 10972 | .variable, .threadlocal_variable => @sizeOf(Tag.Variable), | |
| 10973 | 10781 | .@"extern" => @sizeOf(Tag.Extern), |
| 10974 | 10782 | .func_decl => @sizeOf(Tag.FuncDecl), |
| 10975 | 10783 | .func_instance => b: { |
| ... | ... | @@ -11089,8 +10897,6 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void { |
| 11089 | 10897 | .float_c_longdouble_f80, |
| 11090 | 10898 | .float_c_longdouble_f128, |
| 11091 | 10899 | .float_comptime_float, |
| 11092 | .variable, | |
| 11093 | .threadlocal_variable, | |
| 11094 | 10900 | .@"extern", |
| 11095 | 10901 | .func_decl, |
| 11096 | 10902 | .func_instance, |
| ... | ... | @@ -11175,8 +10981,24 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator, |
| 11175 | 10981 | |
| 11176 | 10982 | pub fn getNav(ip: *const InternPool, index: Nav.Index) Nav { |
| 11177 | 10983 | const unwrapped = index.unwrap(ip); |
| 11178 | const navs = ip.getLocalShared(unwrapped.tid).navs.acquire(); | |
| 11179 | return navs.view().get(unwrapped.index).unpack(); | |
| 10984 | const view = ip.getLocalShared(unwrapped.tid).navs.acquire().view(); | |
| 10985 | // We can't just call `view.get(unwrapped.index)`, because a concurrent call to `resolveNav` | |
| 10986 | // could be writing to fields, making a non-atomic load illegal. Instead, atomically load | |
| 10987 | // each field. We don't need any ordering guarantees because if we need to see (e.g.) the | |
| 10988 | // resolved type of a `Nav`, that information should have already been released to our caller. | |
| 10989 | const repr: Nav.Repr = .{ | |
| 10990 | // Load the first few fields non-atomically---they are never mutated after `Nav` creation. | |
| 10991 | .name = view.items(.name)[unwrapped.index], | |
| 10992 | .fqn = view.items(.fqn)[unwrapped.index], | |
| 10993 | .analysis_namespace = view.items(.analysis_namespace)[unwrapped.index], | |
| 10994 | .analysis_zir_index = view.items(.analysis_zir_index)[unwrapped.index], | |
| 10995 | // The last few fields are populated by `resolveNav` so must be loaded atomically. | |
| 10996 | .type = @atomicLoad(InternPool.Index, &view.items(.type)[unwrapped.index], .monotonic), | |
| 10997 | .value = @atomicLoad(InternPool.Index, &view.items(.value)[unwrapped.index], .monotonic), | |
| 10998 | .@"linksection" = @atomicLoad(OptionalNullTerminatedString, &view.items(.@"linksection")[unwrapped.index], .monotonic), | |
| 10999 | .bits = @atomicLoad(Nav.Repr.Bits, &view.items(.bits)[unwrapped.index], .monotonic), | |
| 11000 | }; | |
| 11001 | return repr.unpack(); | |
| 11180 | 11002 | } |
| 11181 | 11003 | |
| 11182 | 11004 | pub fn namespacePtr(ip: *InternPool, namespace_index: NamespaceIndex) *Zcu.Namespace { |
| ... | ... | @@ -11220,15 +11042,9 @@ fn createNav( |
| 11220 | 11042 | gpa: Allocator, |
| 11221 | 11043 | io: Io, |
| 11222 | 11044 | tid: Zcu.PerThread.Id, |
| 11223 | opts: struct { | |
| 11224 | name: NullTerminatedString, | |
| 11225 | fqn: NullTerminatedString, | |
| 11226 | val: InternPool.Index, | |
| 11227 | is_const: bool, | |
| 11228 | alignment: Alignment, | |
| 11229 | @"linksection": OptionalNullTerminatedString, | |
| 11230 | @"addrspace": std.builtin.AddressSpace, | |
| 11231 | }, | |
| 11045 | name: NullTerminatedString, | |
| 11046 | fqn: NullTerminatedString, | |
| 11047 | resolved: @typeInfo(@FieldType(Nav, "resolved")).optional.child, | |
| 11232 | 11048 | ) Allocator.Error!Nav.Index { |
| 11233 | 11049 | const navs = ip.getLocal(tid).getMutableNavs(gpa, io); |
| 11234 | 11050 | const index_unwrapped: Nav.Index.Unwrapped = .{ |
| ... | ... | @@ -11236,16 +11052,10 @@ fn createNav( |
| 11236 | 11052 | .index = navs.mutate.len, |
| 11237 | 11053 | }; |
| 11238 | 11054 | try navs.append(Nav.pack(.{ |
| 11239 | .name = opts.name, | |
| 11240 | .fqn = opts.fqn, | |
| 11055 | .name = name, | |
| 11056 | .fqn = fqn, | |
| 11241 | 11057 | .analysis = null, |
| 11242 | .status = .{ .fully_resolved = .{ | |
| 11243 | .val = opts.val, | |
| 11244 | .is_const = opts.is_const, | |
| 11245 | .alignment = opts.alignment, | |
| 11246 | .@"linksection" = opts.@"linksection", | |
| 11247 | .@"addrspace" = opts.@"addrspace", | |
| 11248 | } }, | |
| 11058 | .resolved = resolved, | |
| 11249 | 11059 | })); |
| 11250 | 11060 | return index_unwrapped.wrap(ip); |
| 11251 | 11061 | } |
| ... | ... | @@ -11279,27 +11089,19 @@ pub fn createDeclNav( |
| 11279 | 11089 | .zir_index = zir_index, |
| 11280 | 11090 | .wanted = false, |
| 11281 | 11091 | }, |
| 11282 | .status = .unresolved, | |
| 11092 | .resolved = null, | |
| 11283 | 11093 | })); |
| 11284 | 11094 | |
| 11285 | 11095 | return nav; |
| 11286 | 11096 | } |
| 11287 | 11097 | |
| 11288 | /// Resolve the type of a `Nav` with an analysis owner. | |
| 11098 | /// Resolve the type (and possibly the value) of a `Nav` with an analysis owner. | |
| 11289 | 11099 | /// If its status is already `resolved`, the old value is discarded. |
| 11290 | pub fn resolveNavType( | |
| 11100 | pub fn resolveNav( | |
| 11291 | 11101 | ip: *InternPool, |
| 11292 | 11102 | io: Io, |
| 11293 | 11103 | nav: Nav.Index, |
| 11294 | resolved: struct { | |
| 11295 | type: InternPool.Index, | |
| 11296 | is_const: bool, | |
| 11297 | alignment: Alignment, | |
| 11298 | @"linksection": OptionalNullTerminatedString, | |
| 11299 | @"addrspace": std.builtin.AddressSpace, | |
| 11300 | is_threadlocal: bool, | |
| 11301 | is_extern_decl: bool, | |
| 11302 | }, | |
| 11104 | resolved: @typeInfo(@FieldType(Nav, "resolved")).optional.child, | |
| 11303 | 11105 | ) void { |
| 11304 | 11106 | const unwrapped = nav.unwrap(ip); |
| 11305 | 11107 | |
| ... | ... | @@ -11311,65 +11113,45 @@ pub fn resolveNavType( |
| 11311 | 11113 | |
| 11312 | 11114 | const nav_analysis_namespace = navs.items(.analysis_namespace); |
| 11313 | 11115 | const nav_analysis_zir_index = navs.items(.analysis_zir_index); |
| 11314 | const nav_types = navs.items(.type_or_val); | |
| 11116 | const nav_types = navs.items(.type); | |
| 11117 | const nav_values = navs.items(.value); | |
| 11315 | 11118 | const nav_linksections = navs.items(.@"linksection"); |
| 11316 | 11119 | const nav_bits = navs.items(.bits); |
| 11317 | 11120 | |
| 11318 | 11121 | assert(nav_analysis_namespace[unwrapped.index] != .none); |
| 11319 | 11122 | assert(nav_analysis_zir_index[unwrapped.index] != .none); |
| 11320 | 11123 | |
| 11321 | @atomicStore(InternPool.Index, &nav_types[unwrapped.index], resolved.type, .release); | |
| 11322 | @atomicStore(OptionalNullTerminatedString, &nav_linksections[unwrapped.index], resolved.@"linksection", .release); | |
| 11323 | ||
| 11324 | var bits = nav_bits[unwrapped.index]; | |
| 11325 | bits.status = if (resolved.is_extern_decl) .type_resolved_extern_decl else .type_resolved; | |
| 11326 | bits.is_const = resolved.is_const; | |
| 11327 | bits.alignment = resolved.alignment; | |
| 11328 | bits.@"addrspace" = resolved.@"addrspace"; | |
| 11329 | bits.is_threadlocal = resolved.is_threadlocal; | |
| 11330 | @atomicStore(Nav.Repr.Bits, &nav_bits[unwrapped.index], bits, .release); | |
| 11331 | } | |
| 11332 | ||
| 11333 | /// Resolve the value of a `Nav` with an analysis owner. | |
| 11334 | /// If its status is already `resolved`, the old value is discarded. | |
| 11335 | pub fn resolveNavValue( | |
| 11336 | ip: *InternPool, | |
| 11337 | io: Io, | |
| 11338 | nav: Nav.Index, | |
| 11339 | resolved: struct { | |
| 11340 | val: InternPool.Index, | |
| 11341 | is_const: bool, | |
| 11342 | alignment: Alignment, | |
| 11343 | @"linksection": OptionalNullTerminatedString, | |
| 11344 | @"addrspace": std.builtin.AddressSpace, | |
| 11345 | }, | |
| 11346 | ) void { | |
| 11347 | const unwrapped = nav.unwrap(ip); | |
| 11348 | ||
| 11349 | const local = ip.getLocal(unwrapped.tid); | |
| 11350 | local.mutate.extra.mutex.lockUncancelable(io); | |
| 11351 | defer local.mutate.extra.mutex.unlock(io); | |
| 11352 | ||
| 11353 | const navs = local.shared.navs.view(); | |
| 11354 | ||
| 11355 | const nav_analysis_namespace = navs.items(.analysis_namespace); | |
| 11356 | const nav_analysis_zir_index = navs.items(.analysis_zir_index); | |
| 11357 | const nav_vals = navs.items(.type_or_val); | |
| 11358 | const nav_linksections = navs.items(.@"linksection"); | |
| 11359 | const nav_bits = navs.items(.bits); | |
| 11360 | ||
| 11361 | assert(nav_analysis_namespace[unwrapped.index] != .none); | |
| 11362 | assert(nav_analysis_zir_index[unwrapped.index] != .none); | |
| 11124 | @atomicStore( | |
| 11125 | OptionalNullTerminatedString, | |
| 11126 | &nav_linksections[unwrapped.index], | |
| 11127 | resolved.@"linksection", | |
| 11128 | .monotonic, | |
| 11129 | ); | |
| 11363 | 11130 | |
| 11364 | @atomicStore(InternPool.Index, &nav_vals[unwrapped.index], resolved.val, .release); | |
| 11365 | @atomicStore(OptionalNullTerminatedString, &nav_linksections[unwrapped.index], resolved.@"linksection", .release); | |
| 11131 | const bits = &nav_bits[unwrapped.index]; | |
| 11132 | assert(@atomicLoad(Nav.Repr.Bits, bits, .monotonic).want_analysis); // otherwise we wouldn't be resolving `nav` at all | |
| 11133 | @atomicStore(Nav.Repr.Bits, bits, .{ | |
| 11134 | .@"align" = resolved.@"align", | |
| 11135 | .@"addrspace" = resolved.@"addrspace", | |
| 11136 | .@"const" = resolved.@"const", | |
| 11137 | .@"threadlocal" = resolved.@"threadlocal", | |
| 11138 | .is_extern_decl = resolved.is_extern_decl, | |
| 11139 | .want_analysis = true, // asserted above that this is already `true` | |
| 11140 | }, .monotonic); | |
| 11141 | ||
| 11142 | @atomicStore( | |
| 11143 | InternPool.Index, | |
| 11144 | &nav_types[unwrapped.index], | |
| 11145 | resolved.type, | |
| 11146 | .monotonic, | |
| 11147 | ); | |
| 11366 | 11148 | |
| 11367 | var bits = nav_bits[unwrapped.index]; | |
| 11368 | bits.status = .fully_resolved; | |
| 11369 | bits.is_const = resolved.is_const; | |
| 11370 | bits.alignment = resolved.alignment; | |
| 11371 | bits.@"addrspace" = resolved.@"addrspace"; | |
| 11372 | @atomicStore(Nav.Repr.Bits, &nav_bits[unwrapped.index], bits, .release); | |
| 11149 | @atomicStore( | |
| 11150 | InternPool.Index, | |
| 11151 | &nav_values[unwrapped.index], | |
| 11152 | resolved.value, | |
| 11153 | .monotonic, | |
| 11154 | ); | |
| 11373 | 11155 | } |
| 11374 | 11156 | |
| 11375 | 11157 | pub fn createNamespace( |
| ... | ... | @@ -11841,8 +11623,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 11841 | 11623 | .error_set_error, |
| 11842 | 11624 | .error_union_error, |
| 11843 | 11625 | .enum_tag, |
| 11844 | .variable, | |
| 11845 | .threadlocal_variable, | |
| 11846 | 11626 | .@"extern", |
| 11847 | 11627 | .func_decl, |
| 11848 | 11628 | .func_instance, |
| ... | ... | @@ -11949,11 +11729,7 @@ pub fn funcTypeReturnType(ip: *const InternPool, ty: Index) Index { |
| 11949 | 11729 | } |
| 11950 | 11730 | |
| 11951 | 11731 | pub fn isUndef(ip: *const InternPool, val: Index) bool { |
| 11952 | return val == .undef or val.unwrap(ip).getTag(ip) == .undef; | |
| 11953 | } | |
| 11954 | ||
| 11955 | pub fn isVariable(ip: *const InternPool, val: Index) bool { | |
| 11956 | return val.unwrap(ip).getTag(ip) == .variable; | |
| 11732 | return val.unwrap(ip).getTag(ip) == .undef; | |
| 11957 | 11733 | } |
| 11958 | 11734 | |
| 11959 | 11735 | pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.BaseAddr.Tag { |
| ... | ... | @@ -12220,8 +11996,6 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId { |
| 12220 | 11996 | .float_c_longdouble_f80, |
| 12221 | 11997 | .float_c_longdouble_f128, |
| 12222 | 11998 | .float_comptime_float, |
| 12223 | .variable, | |
| 12224 | .threadlocal_variable, | |
| 12225 | 11999 | .@"extern", |
| 12226 | 12000 | .func_decl, |
| 12227 | 12001 | .func_instance, |
| ... | ... | @@ -13001,11 +12775,17 @@ pub fn setWantNavAnalysis(ip: *InternPool, io: Io, nav_index: Nav.Index) bool { |
| 13001 | 12775 | return false; |
| 13002 | 12776 | } |
| 13003 | 12777 | |
| 13004 | const bits = &navs.items(.bits)[unwrapped.index]; | |
| 13005 | if (bits.want_analysis) { | |
| 13006 | return false; | |
| 13007 | } else { | |
| 13008 | bits.want_analysis = true; | |
| 13009 | return true; | |
| 13010 | } | |
| 12778 | // Mutate `bits` atomically so that we don't introduce an illegal data race with `getNav`. | |
| 12779 | const old_bits = @atomicRmw( | |
| 12780 | Nav.Repr.Bits, | |
| 12781 | &navs.items(.bits)[unwrapped.index], | |
| 12782 | .Or, | |
| 12783 | mask: { | |
| 12784 | var mask: Nav.Repr.Bits = @bitCast(@as(u16, 0)); | |
| 12785 | mask.want_analysis = true; | |
| 12786 | break :mask mask; | |
| 12787 | }, | |
| 12788 | .monotonic, | |
| 12789 | ); | |
| 12790 | return !old_bits.want_analysis; | |
| 13011 | 12791 | } |
src/Sema.zig+60-57| ... | ... | @@ -2276,28 +2276,26 @@ fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) ?Value { |
| 2276 | 2276 | assert(inst != .none); |
| 2277 | 2277 | |
| 2278 | 2278 | if (inst.toInterned()) |ip_index| { |
| 2279 | const val: Value = .fromInterned(ip_index); | |
| 2280 | assert(val.getVariable(zcu) == null); | |
| 2281 | return val; | |
| 2282 | } else { | |
| 2283 | // Runtime-known value. | |
| 2284 | const air_tags = sema.air_instructions.items(.tag); | |
| 2285 | switch (air_tags[@intFromEnum(inst.toIndex().?)]) { | |
| 2286 | .inferred_alloc => unreachable, // assertion failure | |
| 2287 | .inferred_alloc_comptime => unreachable, // assertion failure | |
| 2288 | else => {}, | |
| 2289 | } | |
| 2290 | // LLVM fails to eliminate this `classify` call in ReleaseFast, which hurts performance, so | |
| 2291 | // we must explicitly check for `std.debug.runtime_safety`. | |
| 2292 | if (std.debug.runtime_safety) switch (sema.typeOf(inst).classify(zcu)) { | |
| 2293 | .no_possible_value => unreachable, // values of this type do not exist | |
| 2294 | .one_possible_value => unreachable, // the value should be comptime-known | |
| 2295 | .partially_comptime => unreachable, // the value should be comptime-known | |
| 2296 | .fully_comptime => unreachable, // the value should be comptime-known | |
| 2297 | .runtime => {}, | |
| 2298 | }; | |
| 2299 | return null; | |
| 2279 | return .fromInterned(ip_index); | |
| 2300 | 2280 | } |
| 2281 | ||
| 2282 | // Runtime-known value. We'll be returning `null`, but first, some assertions. | |
| 2283 | const air_tags = sema.air_instructions.items(.tag); | |
| 2284 | switch (air_tags[@intFromEnum(inst.toIndex().?)]) { | |
| 2285 | .inferred_alloc => unreachable, // assertion failure | |
| 2286 | .inferred_alloc_comptime => unreachable, // assertion failure | |
| 2287 | else => {}, | |
| 2288 | } | |
| 2289 | // LLVM fails to eliminate this `classify` call in ReleaseFast, which hurts performance, so | |
| 2290 | // we must explicitly check for `std.debug.runtime_safety`. | |
| 2291 | if (std.debug.runtime_safety) switch (sema.typeOf(inst).classify(zcu)) { | |
| 2292 | .no_possible_value => unreachable, // values of this type do not exist | |
| 2293 | .one_possible_value => unreachable, // the value should be comptime-known | |
| 2294 | .partially_comptime => unreachable, // the value should be comptime-known | |
| 2295 | .fully_comptime => unreachable, // the value should be comptime-known | |
| 2296 | .runtime => {}, | |
| 2297 | }; | |
| 2298 | return null; | |
| 2301 | 2299 | } |
| 2302 | 2300 | |
| 2303 | 2301 | /// Like `resolveValue`, but emits an error if the value is not comptime-known. |
| ... | ... | @@ -5738,8 +5736,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 5738 | 5736 | .uav => |uav| .{ .uav = uav.val }, |
| 5739 | 5737 | .nav => |orig_nav| target: { |
| 5740 | 5738 | try sema.ensureNavResolved(block, src, orig_nav, .fully); |
| 5741 | const export_nav = switch (ip.indexToKey(ip.getNav(orig_nav).status.fully_resolved.val)) { | |
| 5742 | .variable => |v| v.owner_nav, | |
| 5739 | const export_nav = switch (ip.indexToKey(ip.getNav(orig_nav).resolved.?.value)) { | |
| 5743 | 5740 | .@"extern" => |e| e.owner_nav, |
| 5744 | 5741 | .func => |f| f.owner_nav, |
| 5745 | 5742 | else => orig_nav, |
| ... | ... | @@ -5778,7 +5775,7 @@ pub fn analyzeExportSelfNav( |
| 5778 | 5775 | const ip = &zcu.intern_pool; |
| 5779 | 5776 | |
| 5780 | 5777 | const orig_nav = sema.owner.unwrap().nav_val; |
| 5781 | const export_val: Value = .fromInterned(ip.getNav(orig_nav).status.fully_resolved.val); | |
| 5778 | const export_val: Value = .fromInterned(ip.getNav(orig_nav).resolved.?.value); | |
| 5782 | 5779 | const export_ty = export_val.typeOf(zcu); |
| 5783 | 5780 | |
| 5784 | 5781 | if (!export_ty.validateExtern(.other, zcu)) { |
| ... | ... | @@ -5792,7 +5789,6 @@ pub fn analyzeExportSelfNav( |
| 5792 | 5789 | } |
| 5793 | 5790 | |
| 5794 | 5791 | const export_nav = switch (ip.indexToKey(export_val.toIntern())) { |
| 5795 | .variable => |v| v.owner_nav, | |
| 5796 | 5792 | .@"extern" => |e| e.owner_nav, |
| 5797 | 5793 | .func => |f| export_nav: { |
| 5798 | 5794 | assert(export_ty.fnHasRuntimeBits(zcu)); // otherwise `validateExtern` failed above |
| ... | ... | @@ -30005,7 +30001,7 @@ pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: |
| 30005 | 30001 | |
| 30006 | 30002 | const nav = ip.getNav(nav_index); |
| 30007 | 30003 | if (nav.analysis == null) { |
| 30008 | assert(nav.status == .fully_resolved); | |
| 30004 | assert(nav.resolved.?.value != .none); | |
| 30009 | 30005 | return; |
| 30010 | 30006 | } |
| 30011 | 30007 | |
| ... | ... | @@ -30066,11 +30062,20 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde |
| 30066 | 30062 | try sema.ensureNavResolved(block, src, orig_nav_index, if (is_ref) .type else .fully); |
| 30067 | 30063 | |
| 30068 | 30064 | const nav_index = nav: { |
| 30069 | if (ip.getNav(orig_nav_index).isExternOrFn(ip)) { | |
| 30070 | // Getting a pointer to this `Nav` might mean we actually get a pointer to something else! | |
| 30071 | // We need to resolve the value to know for sure. | |
| 30072 | if (is_ref) try sema.ensureNavResolved(block, src, orig_nav_index, .fully); | |
| 30073 | switch (ip.indexToKey(ip.getNav(orig_nav_index).status.fully_resolved.val)) { | |
| 30065 | const orig_nav = ip.getNav(orig_nav_index); | |
| 30066 | if (orig_nav.resolved.?.is_extern_decl or ip.zigTypeTag(orig_nav.resolved.?.type) == .@"fn") { | |
| 30067 | // A pointer to this `Nav` might actually be encoded as a pointer to a different `Nav` | |
| 30068 | // because this is either an `extern` definition or an `extern` alias. (The latter case | |
| 30069 | // is unsolved language weirdness; see https://github.com/ziglang/zig/issues/21027.) To | |
| 30070 | // know for sure how to encode this pointer, we need to check the *value* of this `Nav`. | |
| 30071 | const orig_nav_value = switch (is_ref) { | |
| 30072 | false => orig_nav.resolved.?.value, | |
| 30073 | true => orig_val: { | |
| 30074 | try sema.ensureNavResolved(block, src, orig_nav_index, .fully); | |
| 30075 | break :orig_val ip.getNav(orig_nav_index).resolved.?.value; | |
| 30076 | }, | |
| 30077 | }; | |
| 30078 | switch (ip.indexToKey(orig_nav_value)) { | |
| 30074 | 30079 | .func => |f| break :nav f.owner_nav, |
| 30075 | 30080 | .@"extern" => |e| break :nav e.owner_nav, |
| 30076 | 30081 | else => {}, |
| ... | ... | @@ -30079,33 +30084,31 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde |
| 30079 | 30084 | break :nav orig_nav_index; |
| 30080 | 30085 | }; |
| 30081 | 30086 | |
| 30082 | const nav_status = ip.getNav(nav_index).status; | |
| 30087 | const nav_resolved = ip.getNav(nav_index).resolved.?; | |
| 30083 | 30088 | |
| 30084 | const is_runtime = switch (nav_status) { | |
| 30085 | .unresolved => unreachable, | |
| 30086 | // dllimports go straight to `fully_resolved`; the only option is threadlocal | |
| 30087 | .type_resolved => |r| r.is_threadlocal, | |
| 30088 | .fully_resolved => |r| switch (ip.indexToKey(r.val)) { | |
| 30089 | .@"extern" => |e| e.is_threadlocal or e.is_dll_import or switch (e.relocation) { | |
| 30090 | .any => false, | |
| 30091 | .pcrel => true, | |
| 30092 | }, | |
| 30093 | .variable => |v| v.is_threadlocal, | |
| 30094 | else => false, | |
| 30095 | }, | |
| 30089 | const is_runtime: bool = runtime: { | |
| 30090 | if (nav_resolved.@"threadlocal") break :runtime true; | |
| 30091 | if (nav_resolved.value == .none) { | |
| 30092 | // This didn't come from `@extern`, so even if extern it couldn't be dllimport or pcrel. | |
| 30093 | break :runtime false; | |
| 30094 | } | |
| 30095 | const @"extern" = switch (ip.indexToKey(nav_resolved.value)) { | |
| 30096 | .@"extern" => |e| e, | |
| 30097 | else => break :runtime false, | |
| 30098 | }; | |
| 30099 | if (@"extern".is_dll_import) break :runtime true; | |
| 30100 | break :runtime switch (@"extern".relocation) { | |
| 30101 | .any => false, | |
| 30102 | .pcrel => true, | |
| 30103 | }; | |
| 30096 | 30104 | }; |
| 30097 | 30105 | |
| 30098 | const ty, const alignment, const @"addrspace", const is_const = switch (nav_status) { | |
| 30099 | .unresolved => unreachable, | |
| 30100 | .type_resolved => |r| .{ r.type, r.alignment, r.@"addrspace", r.is_const }, | |
| 30101 | .fully_resolved => |r| .{ ip.typeOf(r.val), r.alignment, r.@"addrspace", r.is_const }, | |
| 30102 | }; | |
| 30103 | 30106 | const ptr_ty = try pt.ptrType(.{ |
| 30104 | .child = ty, | |
| 30107 | .child = nav_resolved.type, | |
| 30105 | 30108 | .flags = .{ |
| 30106 | .alignment = alignment, | |
| 30107 | .is_const = is_const, | |
| 30108 | .address_space = @"addrspace", | |
| 30109 | .alignment = nav_resolved.@"align", | |
| 30110 | .is_const = nav_resolved.@"const", | |
| 30111 | .address_space = nav_resolved.@"addrspace", | |
| 30109 | 30112 | }, |
| 30110 | 30113 | }); |
| 30111 | 30114 | |
| ... | ... | @@ -30140,7 +30143,7 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, block: *Block, src: LazySrcLoc, nav_i |
| 30140 | 30143 | // If it is, we can resolve the *value*, and queue analysis as needed. |
| 30141 | 30144 | |
| 30142 | 30145 | try sema.ensureNavResolved(block, src, nav_index, .type); |
| 30143 | const nav_ty: Type = .fromInterned(ip.getNav(nav_index).typeOf(ip)); | |
| 30146 | const nav_ty: Type = .fromInterned(ip.getNav(nav_index).resolved.?.type); | |
| 30144 | 30147 | if (nav_ty.zigTypeTag(zcu) != .@"fn") return; |
| 30145 | 30148 | if (!nav_ty.fnHasRuntimeBits(zcu)) return; |
| 30146 | 30149 | |
| ... | ... | @@ -34006,7 +34009,7 @@ pub fn getBuiltin(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) SemaError |
| 34006 | 34009 | } |
| 34007 | 34010 | |
| 34008 | 34011 | pub const NavPtrModifiers = struct { |
| 34009 | alignment: Alignment, | |
| 34012 | @"align": Alignment, | |
| 34010 | 34013 | @"linksection": InternPool.OptionalNullTerminatedString, |
| 34011 | 34014 | @"addrspace": std.builtin.AddressSpace, |
| 34012 | 34015 | }; |
| ... | ... | @@ -34029,7 +34032,7 @@ pub fn resolveNavPtrModifiers( |
| 34029 | 34032 | const section_src = block.src(.{ .node_offset_var_decl_section = .zero }); |
| 34030 | 34033 | const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = .zero }); |
| 34031 | 34034 | |
| 34032 | const alignment: InternPool.Alignment = a: { | |
| 34035 | const @"align": InternPool.Alignment = a: { | |
| 34033 | 34036 | const align_body = zir_decl.align_body orelse break :a .none; |
| 34034 | 34037 | const align_ref = try sema.resolveInlineBody(block, align_body, decl_inst); |
| 34035 | 34038 | break :a try sema.analyzeAsAlign(block, align_src, align_ref); |
| ... | ... | @@ -34067,7 +34070,7 @@ pub fn resolveNavPtrModifiers( |
| 34067 | 34070 | }; |
| 34068 | 34071 | |
| 34069 | 34072 | return .{ |
| 34070 | .alignment = alignment, | |
| 34073 | .@"align" = @"align", | |
| 34071 | 34074 | .@"linksection" = @"linksection", |
| 34072 | 34075 | .@"addrspace" = @"addrspace", |
| 34073 | 34076 | }; |
src/Sema/bitcast.zig-1| ... | ... | @@ -253,7 +253,6 @@ const UnpackValueBits = struct { |
| 253 | 253 | .func_type, |
| 254 | 254 | .error_set_type, |
| 255 | 255 | .inferred_error_set_type, |
| 256 | .variable, | |
| 257 | 256 | .@"extern", |
| 258 | 257 | .func, |
| 259 | 258 | .err, |
src/Sema/comptime_ptr_access.zig+10-12| ... | ... | @@ -225,19 +225,17 @@ fn loadComptimePtrInner( |
| 225 | 225 | }; |
| 226 | 226 | |
| 227 | 227 | const base_val: MutableValue = switch (ptr.base_addr) { |
| 228 | .nav => |nav| val: { | |
| 229 | try sema.ensureNavResolved(block, src, nav, .fully); | |
| 230 | const val = ip.getNav(nav).status.fully_resolved.val; | |
| 231 | switch (ip.indexToKey(val)) { | |
| 232 | .variable => return .runtime_load, | |
| 233 | // We let `.@"extern"` through here if it's a function. | |
| 234 | // This allows you to alias `extern fn`s. | |
| 235 | .@"extern" => |e| if (Type.fromInterned(e.ty).zigTypeTag(zcu) == .@"fn") | |
| 236 | break :val .{ .interned = val } | |
| 237 | else | |
| 238 | return .runtime_load, | |
| 239 | else => break :val .{ .interned = val }, | |
| 228 | .nav => |nav_id| val: { | |
| 229 | try sema.ensureNavResolved(block, src, nav_id, .fully); | |
| 230 | const nav = ip.getNav(nav_id); | |
| 231 | if (!nav.resolved.?.@"const") return .runtime_load; | |
| 232 | // We let `.@"extern"` through here if it's a fn. This allows aliasing `extern fn`s. | |
| 233 | if (ip.indexToKey(nav.resolved.?.value) == .@"extern" and | |
| 234 | Type.fromInterned(nav.resolved.?.type).zigTypeTag(zcu) != .@"fn") | |
| 235 | { | |
| 236 | return .runtime_load; | |
| 240 | 237 | } |
| 238 | break :val .{ .interned = nav.resolved.?.value }; | |
| 241 | 239 | }, |
| 242 | 240 | .comptime_alloc => |alloc_index| sema.getComptimeAlloc(alloc_index).val, |
| 243 | 241 | .uav => |uav| .{ .interned = uav.val }, |
src/Sema/type_resolution.zig-1| ... | ... | @@ -115,7 +115,6 @@ fn ensureLayoutResolvedInner(sema: *Sema, ty: Type, orig_ty: Type, reason: *cons |
| 115 | 115 | // values, not types |
| 116 | 116 | .undef, |
| 117 | 117 | .simple_value, |
| 118 | .variable, | |
| 119 | 118 | .@"extern", |
| 120 | 119 | .func, |
| 121 | 120 | .int, |
src/Type.zig-10| ... | ... | @@ -239,7 +239,6 @@ pub fn classify(start_ty: Type, zcu: *const Zcu) Class { |
| 239 | 239 | // values, not types |
| 240 | 240 | .undef, |
| 241 | 241 | .simple_value, |
| 242 | .variable, | |
| 243 | 242 | .@"extern", |
| 244 | 243 | .func, |
| 245 | 244 | .int, |
| ... | ... | @@ -675,7 +674,6 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari |
| 675 | 674 | |
| 676 | 675 | // values, not types |
| 677 | 676 | .simple_value, |
| 678 | .variable, | |
| 679 | 677 | .@"extern", |
| 680 | 678 | .func, |
| 681 | 679 | .int, |
| ... | ... | @@ -814,7 +812,6 @@ pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool { |
| 814 | 812 | // values, not types |
| 815 | 813 | .undef, |
| 816 | 814 | .simple_value, |
| 817 | .variable, | |
| 818 | 815 | .@"extern", |
| 819 | 816 | .func, |
| 820 | 817 | .int, |
| ... | ... | @@ -1046,7 +1043,6 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment { |
| 1046 | 1043 | // values, not types |
| 1047 | 1044 | .undef, |
| 1048 | 1045 | .simple_value, |
| 1049 | .variable, | |
| 1050 | 1046 | .@"extern", |
| 1051 | 1047 | .func, |
| 1052 | 1048 | .int, |
| ... | ... | @@ -1187,7 +1183,6 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 { |
| 1187 | 1183 | // values, not types |
| 1188 | 1184 | .undef, |
| 1189 | 1185 | .simple_value, |
| 1190 | .variable, | |
| 1191 | 1186 | .@"extern", |
| 1192 | 1187 | .func, |
| 1193 | 1188 | .int, |
| ... | ... | @@ -1311,7 +1306,6 @@ pub fn bitSize(ty: Type, zcu: *const Zcu) u64 { |
| 1311 | 1306 | // values, not types |
| 1312 | 1307 | .undef, |
| 1313 | 1308 | .simple_value, |
| 1314 | .variable, | |
| 1315 | 1309 | .@"extern", |
| 1316 | 1310 | .func, |
| 1317 | 1311 | .int, |
| ... | ... | @@ -1867,7 +1861,6 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType { |
| 1867 | 1861 | // values, not types |
| 1868 | 1862 | .undef, |
| 1869 | 1863 | .simple_value, |
| 1870 | .variable, | |
| 1871 | 1864 | .@"extern", |
| 1872 | 1865 | .func, |
| 1873 | 1866 | .int, |
| ... | ... | @@ -2162,7 +2155,6 @@ pub fn onePossibleValue(ty: Type, pt: Zcu.PerThread) !?Value { |
| 2162 | 2155 | // values, not types |
| 2163 | 2156 | .undef, |
| 2164 | 2157 | .simple_value, |
| 2165 | .variable, | |
| 2166 | 2158 | .@"extern", |
| 2167 | 2159 | .func, |
| 2168 | 2160 | .int, |
| ... | ... | @@ -3284,7 +3276,6 @@ pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void { |
| 3284 | 3276 | |
| 3285 | 3277 | // values, not types |
| 3286 | 3278 | .simple_value, |
| 3287 | .variable, | |
| 3288 | 3279 | .@"extern", |
| 3289 | 3280 | .func, |
| 3290 | 3281 | .int, |
| ... | ... | @@ -3362,7 +3353,6 @@ fn collectSubtypes(ty: Type, pt: Zcu.PerThread, visited: *std.AutoArrayHashMapUn |
| 3362 | 3353 | |
| 3363 | 3354 | // values, not types |
| 3364 | 3355 | .simple_value, |
| 3365 | .variable, | |
| 3366 | 3356 | .@"extern", |
| 3367 | 3357 | .func, |
| 3368 | 3358 | .int, |
src/Value.zig+1-9| ... | ... | @@ -176,13 +176,6 @@ pub fn getFunction(val: Value, zcu: *Zcu) ?InternPool.Key.Func { |
| 176 | 176 | }; |
| 177 | 177 | } |
| 178 | 178 | |
| 179 | pub fn getVariable(val: Value, mod: *Zcu) ?InternPool.Key.Variable { | |
| 180 | return switch (mod.intern_pool.indexToKey(val.toIntern())) { | |
| 181 | .variable => |variable| variable, | |
| 182 | else => null, | |
| 183 | }; | |
| 184 | } | |
| 185 | ||
| 186 | 179 | /// Asserts the value is a (defined) integer and it fits in a u64. |
| 187 | 180 | pub fn toUnsignedInt(val: Value, zcu: *const Zcu) u64 { |
| 188 | 181 | return getUnsignedInt(val, zcu).?; |
| ... | ... | @@ -808,7 +801,6 @@ pub fn canMutateComptimeVarState(val: Value, zcu: *Zcu) bool { |
| 808 | 801 | pub fn pointerNav(val: Value, zcu: *const Zcu) ?InternPool.Nav.Index { |
| 809 | 802 | return switch (zcu.intern_pool.indexToKey(val.toIntern())) { |
| 810 | 803 | // TODO: these 3 cases are weird; these aren't pointer values! |
| 811 | .variable => |v| v.owner_nav, | |
| 812 | 804 | .@"extern" => |e| e.owner_nav, |
| 813 | 805 | .func => |func| func.owner_nav, |
| 814 | 806 | .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) { |
| ... | ... | @@ -2539,7 +2531,7 @@ pub fn intFitsInType( |
| 2539 | 2531 | .zero_usize, .zero_u8 => return true, |
| 2540 | 2532 | else => switch (zcu.intern_pool.indexToKey(val.toIntern())) { |
| 2541 | 2533 | .undef => return true, |
| 2542 | .variable, .@"extern", .func, .ptr => { | |
| 2534 | .@"extern", .func, .ptr => { | |
| 2543 | 2535 | const target = zcu.getTarget(); |
| 2544 | 2536 | const ptr_bits = target.ptrBitWidth(); |
| 2545 | 2537 | return switch (info.signedness) { |
src/Zcu.zig+9-15| ... | ... | @@ -723,11 +723,7 @@ pub const Exported = union(enum) { |
| 723 | 723 | |
| 724 | 724 | pub fn getAlign(exported: Exported, zcu: *Zcu) Alignment { |
| 725 | 725 | return switch (exported) { |
| 726 | .nav => |nav| switch (zcu.intern_pool.getNav(nav).status) { | |
| 727 | .unresolved => unreachable, | |
| 728 | .type_resolved => |r| r.alignment, | |
| 729 | .fully_resolved => |r| r.alignment, | |
| 730 | }, | |
| 726 | .nav => |nav| zcu.intern_pool.getNav(nav).resolved.?.@"align", | |
| 731 | 727 | .uav => .none, |
| 732 | 728 | }; |
| 733 | 729 | } |
| ... | ... | @@ -4252,8 +4248,8 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.AutoArrayHashMapUnmanag |
| 4252 | 4248 | } |
| 4253 | 4249 | } |
| 4254 | 4250 | // Non-fatal AstGen errors could mean this test decl failed |
| 4255 | if (nav.status == .fully_resolved) { | |
| 4256 | const gop = try units.getOrPut(gpa, .wrap(.{ .func = nav.status.fully_resolved.val })); | |
| 4251 | if (nav.resolved != null and nav.resolved.?.value != .none) { | |
| 4252 | const gop = try units.getOrPut(gpa, .wrap(.{ .func = nav.resolved.?.value })); | |
| 4257 | 4253 | if (!gop.found_existing) gop.value_ptr.* = referencer; |
| 4258 | 4254 | } |
| 4259 | 4255 | } |
| ... | ... | @@ -4419,7 +4415,7 @@ pub fn navSrcLine(zcu: *Zcu, nav_index: InternPool.Nav.Index) u32 { |
| 4419 | 4415 | } |
| 4420 | 4416 | |
| 4421 | 4417 | pub fn navValue(zcu: *const Zcu, nav_index: InternPool.Nav.Index) Value { |
| 4422 | return Value.fromInterned(zcu.intern_pool.getNav(nav_index).status.fully_resolved.val); | |
| 4418 | return .fromInterned(zcu.intern_pool.getNav(nav_index).resolved.?.value); | |
| 4423 | 4419 | } |
| 4424 | 4420 | |
| 4425 | 4421 | pub fn navFileScopeIndex(zcu: *Zcu, nav: InternPool.Nav.Index) File.Index { |
| ... | ... | @@ -4431,14 +4427,12 @@ pub fn navFileScope(zcu: *Zcu, nav: InternPool.Nav.Index) *File { |
| 4431 | 4427 | return zcu.fileByIndex(zcu.navFileScopeIndex(nav)); |
| 4432 | 4428 | } |
| 4433 | 4429 | |
| 4434 | pub fn navAlignment(zcu: *Zcu, nav_index: InternPool.Nav.Index) InternPool.Alignment { | |
| 4435 | const ty: Type, const alignment = switch (zcu.intern_pool.getNav(nav_index).status) { | |
| 4436 | .unresolved => unreachable, | |
| 4437 | .type_resolved => |r| .{ .fromInterned(r.type), r.alignment }, | |
| 4438 | .fully_resolved => |r| .{ Value.fromInterned(r.val).typeOf(zcu), r.alignment }, | |
| 4430 | pub fn navAlignment(zcu: *Zcu, nav_id: InternPool.Nav.Index) InternPool.Alignment { | |
| 4431 | const resolved = zcu.intern_pool.getNav(nav_id).resolved.?; | |
| 4432 | return switch (resolved.@"align") { | |
| 4433 | else => |a| a, | |
| 4434 | .none => Type.fromInterned(resolved.type).abiAlignment(zcu), | |
| 4439 | 4435 | }; |
| 4440 | if (alignment != .none) return alignment; | |
| 4441 | return ty.abiAlignment(zcu); | |
| 4442 | 4436 | } |
| 4443 | 4437 | |
| 4444 | 4438 | pub fn fmtAnalUnit(zcu: *Zcu, unit: AnalUnit) std.fmt.Alt(FormatAnalUnit, formatAnalUnit) { |
src/Zcu/PerThread.zig+76-110| ... | ... | @@ -1584,10 +1584,6 @@ pub fn ensureNavValUpToDate( |
| 1584 | 1584 | |
| 1585 | 1585 | try zcu.ensureNavValAnalysisQueued(nav_id); |
| 1586 | 1586 | |
| 1587 | // Determine whether or not this `Nav`'s value is outdated. This also includes checking if the | |
| 1588 | // status is `.unresolved`, which indicates that the value is outdated because it has *never* | |
| 1589 | // been analyzed so far. | |
| 1590 | // | |
| 1591 | 1587 | // Note that if the unit is PO, we pessimistically assume that it *does* require re-analysis, to |
| 1592 | 1588 | // ensure that the unit is definitely up-to-date when this function returns. This mechanism could |
| 1593 | 1589 | // result in over-analysis if analysis occurs in a poor order; we do our best to avoid this by |
| ... | ... | @@ -1603,7 +1599,7 @@ pub fn ensureNavValUpToDate( |
| 1603 | 1599 | } else { |
| 1604 | 1600 | // We can trust the current information about this unit. |
| 1605 | 1601 | if (prev_failed) return error.AnalysisFail; |
| 1606 | assert(nav.status == .fully_resolved); | |
| 1602 | assert(nav.resolved.?.value != .none); | |
| 1607 | 1603 | return; |
| 1608 | 1604 | } |
| 1609 | 1605 | |
| ... | ... | @@ -1740,7 +1736,7 @@ fn analyzeNavVal( |
| 1740 | 1736 | const maybe_ty: ?Type = if (zir_decl.type_body != null) ty: { |
| 1741 | 1737 | // Since we have a type body, the type is resolved separately! |
| 1742 | 1738 | try sema.ensureNavResolved(&block, init_src, nav_id, .type); |
| 1743 | break :ty .fromInterned(ip.getNav(nav_id).typeOf(ip)); | |
| 1739 | break :ty .fromInterned(ip.getNav(nav_id).resolved.?.type); | |
| 1744 | 1740 | } else null; |
| 1745 | 1741 | |
| 1746 | 1742 | const final_val: ?Value = if (zir_decl.value_body) |value_body| val: { |
| ... | ... | @@ -1786,14 +1782,12 @@ fn analyzeNavVal( |
| 1786 | 1782 | const modifiers: Sema.NavPtrModifiers = if (zir_decl.type_body != null) m: { |
| 1787 | 1783 | // `analyzeNavType` (from the `ensureNavTypeUpToDate` call above) has already populated this data into |
| 1788 | 1784 | // the `Nav`. Load the new one, and pull the modifiers out. |
| 1789 | switch (ip.getNav(nav_id).status) { | |
| 1790 | .unresolved => unreachable, // `analyzeNavType` will never leave us in this state | |
| 1791 | inline .type_resolved, .fully_resolved => |r| break :m .{ | |
| 1792 | .alignment = r.alignment, | |
| 1793 | .@"linksection" = r.@"linksection", | |
| 1794 | .@"addrspace" = r.@"addrspace", | |
| 1795 | }, | |
| 1796 | } | |
| 1785 | const r = ip.getNav(nav_id).resolved.?; | |
| 1786 | break :m .{ | |
| 1787 | .@"align" = r.@"align", | |
| 1788 | .@"linksection" = r.@"linksection", | |
| 1789 | .@"addrspace" = r.@"addrspace", | |
| 1790 | }; | |
| 1797 | 1791 | } else m: { |
| 1798 | 1792 | // `analyzeNavType` is essentially a stub which calls us. We are responsible for resolving this data. |
| 1799 | 1793 | break :m try sema.resolveNavPtrModifiers(&block, zir_decl, inst_resolved.inst, nav_ty); |
| ... | ... | @@ -1803,15 +1797,7 @@ fn analyzeNavVal( |
| 1803 | 1797 | // This isn't necessarily the same as `final_val`! |
| 1804 | 1798 | |
| 1805 | 1799 | const nav_val: Value = switch (zir_decl.linkage) { |
| 1806 | .normal, .@"export" => switch (zir_decl.kind) { | |
| 1807 | .@"var" => .fromInterned(try pt.intern(.{ .variable = .{ | |
| 1808 | .ty = nav_ty.toIntern(), | |
| 1809 | .init = final_val.?.toIntern(), | |
| 1810 | .owner_nav = nav_id, | |
| 1811 | .is_threadlocal = zir_decl.is_threadlocal, | |
| 1812 | } })), | |
| 1813 | else => final_val.?, | |
| 1814 | }, | |
| 1800 | .normal, .@"export" => final_val.?, | |
| 1815 | 1801 | .@"extern" => val: { |
| 1816 | 1802 | assert(final_val == null); // extern decls do not have a value body |
| 1817 | 1803 | const lib_name: ?[]const u8 = if (zir_decl.lib_name != .empty) l: { |
| ... | ... | @@ -1832,7 +1818,7 @@ fn analyzeNavVal( |
| 1832 | 1818 | .relocation = .any, |
| 1833 | 1819 | .decoration = null, |
| 1834 | 1820 | .is_const = is_const, |
| 1835 | .alignment = modifiers.alignment, | |
| 1821 | .alignment = modifiers.@"align", | |
| 1836 | 1822 | .@"addrspace" = modifiers.@"addrspace", |
| 1837 | 1823 | .zir_index = old_nav.analysis.?.zir_index, // `declaration` instruction |
| 1838 | 1824 | .owner_nav = undefined, // ignored by `getExtern` |
| ... | ... | @@ -1852,11 +1838,7 @@ fn analyzeNavVal( |
| 1852 | 1838 | |
| 1853 | 1839 | const queue_linker_work, const is_owned_fn = switch (ip.indexToKey(nav_val.toIntern())) { |
| 1854 | 1840 | .func => |f| .{ true, f.owner_nav == nav_id }, // note that this lets function aliases reach codegen |
| 1855 | .variable => |v| .{ v.owner_nav == nav_id, false }, | |
| 1856 | .@"extern" => |e| .{ | |
| 1857 | false, | |
| 1858 | Type.fromInterned(e.ty).zigTypeTag(zcu) == .@"fn" and zir_decl.linkage == .@"extern", | |
| 1859 | }, | |
| 1841 | .@"extern" => .{ false, nav_ty.zigTypeTag(zcu) == .@"fn" and zir_decl.linkage == .@"extern" }, | |
| 1860 | 1842 | else => .{ true, false }, |
| 1861 | 1843 | }; |
| 1862 | 1844 | |
| ... | ... | @@ -1895,23 +1877,22 @@ fn analyzeNavVal( |
| 1895 | 1877 | info.last_update_gen = zcu.generation; |
| 1896 | 1878 | info.deps.clearRetainingCapacity(); |
| 1897 | 1879 | } |
| 1898 | const type_changed: bool = switch (old_nav.status) { | |
| 1899 | .unresolved => true, | |
| 1900 | .type_resolved => |old| old.type != nav_ty.toIntern(), | |
| 1901 | .fully_resolved => |old| ip.typeOf(old.val) != nav_ty.toIntern(), | |
| 1902 | }; | |
| 1880 | const type_changed: bool = if (old_nav.resolved) |r| r.type != nav_ty.toIntern() else true; | |
| 1903 | 1881 | if (type_changed) { |
| 1904 | 1882 | try zcu.markDependeeOutdated(.marked_po, .{ .nav_ty = nav_id }); |
| 1905 | 1883 | } else { |
| 1906 | 1884 | try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav_id }); |
| 1907 | 1885 | } |
| 1908 | 1886 | } |
| 1909 | ip.resolveNavValue(io, nav_id, .{ | |
| 1910 | .val = nav_val.toIntern(), | |
| 1911 | .is_const = is_const, | |
| 1912 | .alignment = modifiers.alignment, | |
| 1887 | ip.resolveNav(io, nav_id, .{ | |
| 1888 | .type = nav_ty.toIntern(), | |
| 1889 | .@"align" = modifiers.@"align", | |
| 1913 | 1890 | .@"linksection" = modifiers.@"linksection", |
| 1914 | 1891 | .@"addrspace" = modifiers.@"addrspace", |
| 1892 | .@"const" = is_const, | |
| 1893 | .@"threadlocal" = zir_decl.is_threadlocal, | |
| 1894 | .is_extern_decl = zir_decl.linkage == .@"extern", | |
| 1895 | .value = nav_val.toIntern(), | |
| 1915 | 1896 | }); |
| 1916 | 1897 | |
| 1917 | 1898 | if (zir_decl.linkage == .@"export") { |
| ... | ... | @@ -1943,9 +1924,10 @@ fn analyzeNavVal( |
| 1943 | 1924 | try zcu.ensureFuncBodyAnalysisQueued(nav_val.toIntern()); |
| 1944 | 1925 | } |
| 1945 | 1926 | |
| 1946 | return switch (old_nav.status) { | |
| 1947 | .unresolved, .type_resolved => .{ .val_changed = true }, | |
| 1948 | .fully_resolved => |old| .{ .val_changed = old.val != nav_val.toIntern() }, | |
| 1927 | return if (old_nav.resolved) |old_resolved| .{ | |
| 1928 | .val_changed = old_resolved.value != nav_val.toIntern(), | |
| 1929 | } else .{ | |
| 1930 | .val_changed = true, | |
| 1949 | 1931 | }; |
| 1950 | 1932 | } |
| 1951 | 1933 | |
| ... | ... | @@ -1971,10 +1953,6 @@ pub fn ensureNavTypeUpToDate( |
| 1971 | 1953 | |
| 1972 | 1954 | try zcu.ensureNavValAnalysisQueued(nav_id); |
| 1973 | 1955 | |
| 1974 | // Determine whether or not this `Nav`'s type is outdated. This also includes checking if the | |
| 1975 | // status is `.unresolved`, which indicates that the value is outdated because it has *never* | |
| 1976 | // been analyzed so far. | |
| 1977 | // | |
| 1978 | 1956 | // Note that if the unit is PO, we pessimistically assume that it *does* require re-analysis, to |
| 1979 | 1957 | // ensure that the unit is definitely up-to-date when this function returns. This mechanism could |
| 1980 | 1958 | // result in over-analysis if analysis occurs in a poor order; we do our best to avoid this by |
| ... | ... | @@ -1990,7 +1968,7 @@ pub fn ensureNavTypeUpToDate( |
| 1990 | 1968 | } else { |
| 1991 | 1969 | // We can trust the current information about this unit. |
| 1992 | 1970 | if (prev_failed) return error.AnalysisFail; |
| 1993 | assert(nav.status != .unresolved); | |
| 1971 | assert(nav.resolved != null); | |
| 1994 | 1972 | return; |
| 1995 | 1973 | } |
| 1996 | 1974 | |
| ... | ... | @@ -2124,24 +2102,16 @@ fn analyzeNavType( |
| 2124 | 2102 | // the previous update. As such, after this call, we will be able to determine whether the |
| 2125 | 2103 | // type changed. |
| 2126 | 2104 | try sema.ensureNavResolved(&block, init_src, nav_id, .fully); |
| 2127 | const new = ip.getNav(nav_id).status.fully_resolved; | |
| 2128 | const new_is_extern_decl = ip.indexToKey(new.val) == .@"extern"; | |
| 2129 | const changed = switch (old_nav.status) { | |
| 2130 | .unresolved => true, | |
| 2131 | .type_resolved => |r| r.type != ip.typeOf(new.val) or | |
| 2132 | r.alignment != new.alignment or | |
| 2133 | r.@"linksection" != new.@"linksection" or | |
| 2134 | r.@"addrspace" != new.@"addrspace" or | |
| 2135 | r.is_const != new.is_const or | |
| 2136 | r.is_extern_decl != new_is_extern_decl, | |
| 2137 | .fully_resolved => |r| ip.typeOf(r.val) != ip.typeOf(new.val) or | |
| 2138 | r.alignment != new.alignment or | |
| 2139 | r.@"linksection" != new.@"linksection" or | |
| 2140 | r.@"addrspace" != new.@"addrspace" or | |
| 2141 | r.is_const != new.is_const or | |
| 2142 | (old_nav.getExtern(ip) != null) != new_is_extern_decl, | |
| 2143 | }; | |
| 2144 | return .{ .type_changed = changed }; | |
| 2105 | const new = ip.getNav(nav_id).resolved.?; | |
| 2106 | return if (old_nav.resolved) |old| .{ | |
| 2107 | .type_changed = old.type != new.type or | |
| 2108 | old.@"align" != new.@"align" or | |
| 2109 | old.@"linksection" != new.@"linksection" or | |
| 2110 | old.@"addrspace" != new.@"addrspace" or | |
| 2111 | old.@"const" != new.@"const" or | |
| 2112 | old.@"threadlocal" != new.@"threadlocal" or | |
| 2113 | old.is_extern_decl != new.is_extern_decl, | |
| 2114 | } else .{ .type_changed = true }; | |
| 2145 | 2115 | }; |
| 2146 | 2116 | |
| 2147 | 2117 | block.comptime_reason = .{ .reason = .{ |
| ... | ... | @@ -2169,37 +2139,34 @@ fn analyzeNavType( |
| 2169 | 2139 | |
| 2170 | 2140 | const is_extern_decl = zir_decl.linkage == .@"extern"; |
| 2171 | 2141 | |
| 2172 | // Now for the question of the day: are the type and modifiers the same as before? | |
| 2173 | // If they are, then we should actually keep the `Nav` as `fully_resolved` if it currently is. | |
| 2174 | // That's because `analyzeNavVal` will later want to look at the resolved value to figure out | |
| 2175 | // whether it's changed: if we threw that data away now, it would have to assume that the value | |
| 2176 | // had changed, potentially spinning off loads of unnecessary re-analysis! | |
| 2177 | const changed = switch (old_nav.status) { | |
| 2178 | .unresolved => true, | |
| 2179 | .type_resolved => |r| r.type != resolved_ty.toIntern() or | |
| 2180 | r.alignment != modifiers.alignment or | |
| 2181 | r.@"linksection" != modifiers.@"linksection" or | |
| 2182 | r.@"addrspace" != modifiers.@"addrspace" or | |
| 2183 | r.is_const != is_const or | |
| 2184 | r.is_extern_decl != is_extern_decl, | |
| 2185 | .fully_resolved => |r| ip.typeOf(r.val) != resolved_ty.toIntern() or | |
| 2186 | r.alignment != modifiers.alignment or | |
| 2187 | r.@"linksection" != modifiers.@"linksection" or | |
| 2188 | r.@"addrspace" != modifiers.@"addrspace" or | |
| 2189 | r.is_const != is_const or | |
| 2190 | (old_nav.getExtern(ip) != null) != is_extern_decl, | |
| 2191 | }; | |
| 2142 | // Now for the question of the day: are the type and modifiers the same as before? If they are, | |
| 2143 | // then we should actually avoid calling `ip.resolveNav`. This is because `analyzeNavVal` will | |
| 2144 | // later wanmt to look at the resolved *value* to figure out whether *that* has changed: if we | |
| 2145 | // threw that data away now, it would have to assume the value *had* changed even if it actually | |
| 2146 | // hadn't, which could spin off a bunch of unnecessary re-analysis! OTOH, if the type *has* | |
| 2147 | // changed, then we obviously know that the value will also have changed, so resetting the value | |
| 2148 | // to `.none` is fine in that case. | |
| 2149 | const changed: bool = if (old_nav.resolved) |old| changed: { | |
| 2150 | break :changed old.type != resolved_ty.toIntern() or | |
| 2151 | old.@"align" != modifiers.@"align" or | |
| 2152 | old.@"linksection" != modifiers.@"linksection" or | |
| 2153 | old.@"addrspace" != modifiers.@"addrspace" or | |
| 2154 | old.@"const" != is_const or | |
| 2155 | old.@"threadlocal" != zir_decl.is_threadlocal or | |
| 2156 | old.is_extern_decl != is_extern_decl; | |
| 2157 | } else true; | |
| 2192 | 2158 | |
| 2193 | 2159 | if (!changed) return .{ .type_changed = false }; |
| 2194 | 2160 | |
| 2195 | ip.resolveNavType(io, nav_id, .{ | |
| 2161 | ip.resolveNav(io, nav_id, .{ | |
| 2196 | 2162 | .type = resolved_ty.toIntern(), |
| 2197 | .is_const = is_const, | |
| 2198 | .alignment = modifiers.alignment, | |
| 2163 | .@"align" = modifiers.@"align", | |
| 2199 | 2164 | .@"linksection" = modifiers.@"linksection", |
| 2200 | 2165 | .@"addrspace" = modifiers.@"addrspace", |
| 2201 | .is_threadlocal = zir_decl.is_threadlocal, | |
| 2166 | .@"const" = is_const, | |
| 2167 | .@"threadlocal" = zir_decl.is_threadlocal, | |
| 2202 | 2168 | .is_extern_decl = is_extern_decl, |
| 2169 | .value = .none, | |
| 2203 | 2170 | }); |
| 2204 | 2171 | |
| 2205 | 2172 | return .{ .type_changed = true }; |
| ... | ... | @@ -3358,13 +3325,13 @@ fn analyzeFuncBodyInner( |
| 3358 | 3325 | |
| 3359 | 3326 | if (func.generic_owner == .none) { |
| 3360 | 3327 | try pt.ensureNavValUpToDate(func.owner_nav, reason); |
| 3361 | if (ip.getNav(func.owner_nav).status.fully_resolved.val != func_index) { | |
| 3328 | if (ip.getNav(func.owner_nav).resolved.?.value != func_index) { | |
| 3362 | 3329 | return error.AnalysisFail; |
| 3363 | 3330 | } |
| 3364 | 3331 | } else { |
| 3365 | 3332 | const go_nav = zcu.funcInfo(func.generic_owner).owner_nav; |
| 3366 | 3333 | try pt.ensureNavValUpToDate(go_nav, reason); |
| 3367 | if (ip.getNav(go_nav).status.fully_resolved.val != func.generic_owner) { | |
| 3334 | if (ip.getNav(go_nav).resolved.?.value != func.generic_owner) { | |
| 3368 | 3335 | return error.AnalysisFail; |
| 3369 | 3336 | } |
| 3370 | 3337 | } |
| ... | ... | @@ -3757,9 +3724,9 @@ fn processExportsInner( |
| 3757 | 3724 | if (zcu.failed_analysis.contains(unit)) break :failed true; |
| 3758 | 3725 | if (zcu.transitive_failed_analysis.contains(unit)) break :failed true; |
| 3759 | 3726 | } |
| 3760 | const val = switch (nav.status) { | |
| 3761 | .unresolved, .type_resolved => break :failed true, | |
| 3762 | .fully_resolved => |r| Value.fromInterned(r.val), | |
| 3727 | const val: Value = switch ((nav.resolved orelse break :failed true).value) { | |
| 3728 | .none => break :failed true, | |
| 3729 | else => |val| .fromInterned(val), | |
| 3763 | 3730 | }; |
| 3764 | 3731 | // If the value is a function, we also need to check if that function succeeded analysis. |
| 3765 | 3732 | if (val.typeOf(zcu).zigTypeTag(zcu) == .@"fn") { |
| ... | ... | @@ -3805,14 +3772,16 @@ pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void { |
| 3805 | 3772 | if (builtin_root_type == .none) return; // `@import("builtin")` never analyzed |
| 3806 | 3773 | const builtin_namespace = Type.fromInterned(builtin_root_type).getNamespace(zcu).unwrap().?; |
| 3807 | 3774 | // We know that the namespace has a `test_functions`... |
| 3808 | const nav_index = zcu.namespacePtr(builtin_namespace).pub_decls.getKeyAdapted( | |
| 3775 | const test_fns_nav_index = zcu.namespacePtr(builtin_namespace).pub_decls.getKeyAdapted( | |
| 3809 | 3776 | try ip.getOrPutString(gpa, io, pt.tid, "test_functions", .no_embedded_nulls), |
| 3810 | 3777 | Zcu.Namespace.NameAdapter{ .zcu = zcu }, |
| 3811 | 3778 | ).?; |
| 3779 | const test_fns_nav = ip.getNav(test_fns_nav_index); | |
| 3812 | 3780 | // ...but it might not be populated, so let's check that! |
| 3813 | if (zcu.failed_analysis.contains(.wrap(.{ .nav_val = nav_index })) or | |
| 3814 | zcu.transitive_failed_analysis.contains(.wrap(.{ .nav_val = nav_index })) or | |
| 3815 | ip.getNav(nav_index).status != .fully_resolved) | |
| 3781 | if (zcu.failed_analysis.contains(.wrap(.{ .nav_val = test_fns_nav_index })) or | |
| 3782 | zcu.transitive_failed_analysis.contains(.wrap(.{ .nav_val = test_fns_nav_index })) or | |
| 3783 | test_fns_nav.resolved == null or | |
| 3784 | test_fns_nav.resolved.?.value == .none) | |
| 3816 | 3785 | { |
| 3817 | 3786 | // The value of `builtin.test_functions` was either never referenced, or failed analysis. |
| 3818 | 3787 | // Either way, we don't need to do anything. |
| ... | ... | @@ -3822,8 +3791,7 @@ pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void { |
| 3822 | 3791 | // Okay, `builtin.test_functions` is (potentially) referenced and valid. Our job now is to swap |
| 3823 | 3792 | // its placeholder `&.{}` value for the actual list of all test functions. |
| 3824 | 3793 | |
| 3825 | const test_fns_val = zcu.navValue(nav_index); | |
| 3826 | const test_fn_ty = test_fns_val.typeOf(zcu).slicePtrFieldType(zcu).childType(zcu); | |
| 3794 | const test_fn_ty = Type.fromInterned(test_fns_nav.resolved.?.type).slicePtrFieldType(zcu).childType(zcu); | |
| 3827 | 3795 | |
| 3828 | 3796 | const array_anon_decl: InternPool.Key.Ptr.BaseAddr.Uav = array: { |
| 3829 | 3797 | // Add zcu.test_functions to an array decl then make the test_functions |
| ... | ... | @@ -3914,10 +3882,12 @@ pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void { |
| 3914 | 3882 | } }), |
| 3915 | 3883 | .len = (try pt.intValue(Type.usize, zcu.test_functions.count())).toIntern(), |
| 3916 | 3884 | } }); |
| 3917 | ip.mutateVarInit(io, test_fns_val.toIntern(), new_init); | |
| 3885 | var new_resolved_test_fns = test_fns_nav.resolved.?; | |
| 3886 | new_resolved_test_fns.value = new_init; | |
| 3887 | ip.resolveNav(io, test_fns_nav_index, new_resolved_test_fns); | |
| 3918 | 3888 | } |
| 3919 | 3889 | // The linker thread is not running, so we actually need to dispatch this task directly. |
| 3920 | @import("../link.zig").linkTestFunctionsNav(pt, nav_index); | |
| 3890 | @import("../link.zig").linkTestFunctionsNav(pt, test_fns_nav_index); | |
| 3921 | 3891 | } |
| 3922 | 3892 | |
| 3923 | 3893 | /// Stores an error in `pt.zcu.failed_files` for this file, and sets the file |
| ... | ... | @@ -4402,17 +4372,13 @@ pub fn intBitsForValue(pt: Zcu.PerThread, val: Value, sign: bool) u16 { |
| 4402 | 4372 | pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Error!Type { |
| 4403 | 4373 | const zcu = pt.zcu; |
| 4404 | 4374 | const ip = &zcu.intern_pool; |
| 4405 | const ty, const alignment, const @"addrspace", const is_const = switch (ip.getNav(nav_id).status) { | |
| 4406 | .unresolved => unreachable, | |
| 4407 | .type_resolved => |r| .{ r.type, r.alignment, r.@"addrspace", r.is_const }, | |
| 4408 | .fully_resolved => |r| .{ ip.typeOf(r.val), r.alignment, r.@"addrspace", r.is_const }, | |
| 4409 | }; | |
| 4375 | const resolved_nav = ip.getNav(nav_id).resolved.?; | |
| 4410 | 4376 | return pt.ptrType(.{ |
| 4411 | .child = ty, | |
| 4377 | .child = resolved_nav.type, | |
| 4412 | 4378 | .flags = .{ |
| 4413 | .alignment = alignment, | |
| 4414 | .address_space = @"addrspace", | |
| 4415 | .is_const = is_const, | |
| 4379 | .alignment = resolved_nav.@"align", | |
| 4380 | .address_space = resolved_nav.@"addrspace", | |
| 4381 | .is_const = resolved_nav.@"const", | |
| 4416 | 4382 | }, |
| 4417 | 4383 | }); |
| 4418 | 4384 | } |
src/codegen.zig+6-6| ... | ... | @@ -352,7 +352,6 @@ pub fn generateSymbol( |
| 352 | 352 | else => unreachable, |
| 353 | 353 | }), |
| 354 | 354 | }, |
| 355 | .variable, | |
| 356 | 355 | .@"extern", |
| 357 | 356 | .func, |
| 358 | 357 | .enum_literal, |
| ... | ... | @@ -787,7 +786,7 @@ fn lowerNavRef( |
| 787 | 786 | const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result; |
| 788 | 787 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); |
| 789 | 788 | const is_obj = lf.comp.config.output_mode == .Obj; |
| 790 | const nav_ty = Type.fromInterned(ip.getNav(nav_index).typeOf(ip)); | |
| 789 | const nav_ty = Type.fromInterned(ip.getNav(nav_index).resolved.?.type); | |
| 791 | 790 | |
| 792 | 791 | if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) and ip.getNav(nav_index).getExtern(ip) == null) { |
| 793 | 792 | try w.splatByteAll(0xaa, ptr_width_bytes); |
| ... | ... | @@ -876,10 +875,11 @@ pub fn genNavRef( |
| 876 | 875 | const nav = ip.getNav(nav_index); |
| 877 | 876 | log.debug("genNavRef({f})", .{nav.fqn.fmt(ip)}); |
| 878 | 877 | |
| 879 | const lib_name, const linkage, const is_threadlocal = if (nav.getExtern(ip)) |e| | |
| 880 | .{ e.lib_name, e.linkage, e.is_threadlocal and zcu.comp.config.any_non_single_threaded } | |
| 878 | const is_threadlocal = nav.resolved.?.@"threadlocal" and zcu.comp.config.any_non_single_threaded; | |
| 879 | const lib_name, const linkage = if (nav.getExtern(ip)) |e| | |
| 880 | .{ e.lib_name, e.linkage } | |
| 881 | 881 | else |
| 882 | .{ .none, .internal, false }; | |
| 882 | .{ .none, .internal }; | |
| 883 | 883 | if (lf.cast(.elf)) |elf_file| { |
| 884 | 884 | const zo = elf_file.zigObjectPtr().?; |
| 885 | 885 | switch (linkage) { |
| ... | ... | @@ -1038,7 +1038,7 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo |
| 1038 | 1038 | |
| 1039 | 1039 | .nav => |nav_index| { |
| 1040 | 1040 | const nav = ip.getNav(nav_index); |
| 1041 | const nav_ty: Type = .fromInterned(nav.typeOf(ip)); | |
| 1041 | const nav_ty: Type = .fromInterned(nav.resolved.?.type); | |
| 1042 | 1042 | if (nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) or nav.getExtern(ip) != null) { |
| 1043 | 1043 | return .{ .lea_nav = nav_index }; |
| 1044 | 1044 | } else { |
src/codegen/aarch64/Mir.zig+1-1| ... | ... | @@ -69,7 +69,7 @@ pub fn emit( |
| 69 | 69 | const target = &mod.resolved_target.result; |
| 70 | 70 | mir_log.debug("{f}:", .{nav.fqn.fmt(ip)}); |
| 71 | 71 | |
| 72 | const func_align = switch (nav.status.fully_resolved.alignment) { | |
| 72 | const func_align = switch (nav.resolved.?.@"align") { | |
| 73 | 73 | .none => switch (mod.optimize_mode) { |
| 74 | 74 | .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target), |
| 75 | 75 | .ReleaseSmall => target_util.minFunctionAlignment(target), |
src/codegen/aarch64/Select.zig+2-4| ... | ... | @@ -7207,7 +7207,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 7207 | 7207 | const ptr_ra = try ptr_vi.value.defReg(isel) orelse break :unused; |
| 7208 | 7208 | |
| 7209 | 7209 | const ty_nav = air.data(air.inst_index).ty_nav; |
| 7210 | if (ZigType.fromInterned(ip.getNav(ty_nav.nav).typeOf(ip)).isRuntimeFnOrHasRuntimeBits(zcu)) switch (true) { | |
| 7210 | if (ZigType.fromInterned(ip.getNav(ty_nav.nav).resolved.?.type).isRuntimeFnOrHasRuntimeBits(zcu)) switch (true) { | |
| 7211 | 7211 | false => { |
| 7212 | 7212 | try isel.nav_relocs.append(gpa, .{ |
| 7213 | 7213 | .nav = ty_nav.nav, |
| ... | ... | @@ -10577,7 +10577,6 @@ pub const Value = struct { |
| 10577 | 10577 | => continue :type_key .{ .simple_type = .anyerror }, |
| 10578 | 10578 | .undef, |
| 10579 | 10579 | .simple_value, |
| 10580 | .variable, | |
| 10581 | 10580 | .@"extern", |
| 10582 | 10581 | .func, |
| 10583 | 10582 | .int, |
| ... | ... | @@ -10914,7 +10913,7 @@ pub const Value = struct { |
| 10914 | 10913 | .ptr => |ptr| { |
| 10915 | 10914 | assert(offset == 0 and size == 8); |
| 10916 | 10915 | break :free switch (ptr.base_addr) { |
| 10917 | .nav => |nav| if (ZigType.fromInterned(ip.getNav(nav).typeOf(ip)).isRuntimeFnOrHasRuntimeBits(zcu)) switch (true) { | |
| 10916 | .nav => |nav| if (ZigType.fromInterned(ip.getNav(nav).resolved.?.type).isRuntimeFnOrHasRuntimeBits(zcu)) switch (true) { | |
| 10918 | 10917 | false => { |
| 10919 | 10918 | try isel.nav_relocs.append(zcu.gpa, .{ |
| 10920 | 10919 | .nav = nav, |
| ... | ... | @@ -12300,7 +12299,6 @@ pub const CallAbiIterator = struct { |
| 12300 | 12299 | => continue :type_key .{ .simple_type = .anyerror }, |
| 12301 | 12300 | .undef, |
| 12302 | 12301 | .simple_value, |
| 12303 | .variable, | |
| 12304 | 12302 | .@"extern", |
| 12305 | 12303 | .func, |
| 12306 | 12304 | .int, |
src/codegen/c.zig+31-41| ... | ... | @@ -669,11 +669,9 @@ pub const DeclGen = struct { |
| 669 | 669 | return dg.renderUndefValue(w, ptr_ty, location); |
| 670 | 670 | } |
| 671 | 671 | |
| 672 | // Chase function values in order to be able to reference the original function. | |
| 673 | 672 | switch (ip.indexToKey(uav.val)) { |
| 674 | .variable => unreachable, | |
| 675 | .func => |func| return dg.renderNav(w, func.owner_nav, location), | |
| 676 | .@"extern" => |@"extern"| return dg.renderNav(w, @"extern".owner_nav, location), | |
| 673 | .func => unreachable, | |
| 674 | .@"extern" => unreachable, | |
| 677 | 675 | else => {}, |
| 678 | 676 | } |
| 679 | 677 | |
| ... | ... | @@ -721,10 +719,9 @@ pub const DeclGen = struct { |
| 721 | 719 | const ip = &zcu.intern_pool; |
| 722 | 720 | |
| 723 | 721 | // Chase function values in order to be able to reference the original function. |
| 724 | const owner_nav = switch (ip.getNav(nav_index).status) { | |
| 725 | .unresolved => unreachable, | |
| 726 | .type_resolved => nav_index, // this can't be an extern or a function | |
| 727 | .fully_resolved => |r| switch (ip.indexToKey(r.val)) { | |
| 722 | const owner_nav = switch (ip.getNav(nav_index).resolved.?.value) { | |
| 723 | .none => nav_index, // this can't be an extern or a function | |
| 724 | else => |value| switch (ip.indexToKey(value)) { | |
| 728 | 725 | .func => |f| f.owner_nav, |
| 729 | 726 | .@"extern" => |e| e.owner_nav, |
| 730 | 727 | else => nav_index, |
| ... | ... | @@ -732,7 +729,7 @@ pub const DeclGen = struct { |
| 732 | 729 | }; |
| 733 | 730 | |
| 734 | 731 | // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. |
| 735 | const nav_ty: Type = .fromInterned(ip.getNav(owner_nav).typeOf(ip)); | |
| 732 | const nav_ty: Type = .fromInterned(ip.getNav(owner_nav).resolved.?.type); | |
| 736 | 733 | const ptr_ty = try pt.navPtrType(owner_nav); |
| 737 | 734 | if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { |
| 738 | 735 | return dg.renderUndefValue(w, ptr_ty, location); |
| ... | ... | @@ -924,7 +921,6 @@ pub const DeclGen = struct { |
| 924 | 921 | .false => try w.writeAll("false"), |
| 925 | 922 | .true => try w.writeAll("true"), |
| 926 | 923 | }, |
| 927 | .variable, | |
| 928 | 924 | .@"extern", |
| 929 | 925 | .func, |
| 930 | 926 | .enum_literal, |
| ... | ... | @@ -1575,7 +1571,6 @@ pub const DeclGen = struct { |
| 1575 | 1571 | |
| 1576 | 1572 | .undef, |
| 1577 | 1573 | .simple_value, |
| 1578 | .variable, | |
| 1579 | 1574 | .@"extern", |
| 1580 | 1575 | .func, |
| 1581 | 1576 | .int, |
| ... | ... | @@ -2276,13 +2271,13 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E |
| 2276 | 2271 | try f.dg.renderFunctionSignature( |
| 2277 | 2272 | fwd_decl_writer, |
| 2278 | 2273 | nav_val, |
| 2279 | nav.status.fully_resolved.alignment, | |
| 2274 | nav.resolved.?.@"align", | |
| 2280 | 2275 | .forward_decl, |
| 2281 | 2276 | .{ .nav = nav_index }, |
| 2282 | 2277 | ); |
| 2283 | 2278 | try fwd_decl_writer.writeAll(";\n"); |
| 2284 | 2279 | |
| 2285 | if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |s| | |
| 2280 | if (nav.resolved.?.@"linksection".toSlice(ip)) |s| | |
| 2286 | 2281 | try header_writer.print("zig_linksection_fn({f}) ", .{fmtStringLiteral(s, null)}); |
| 2287 | 2282 | try f.dg.renderFunctionSignature( |
| 2288 | 2283 | header_writer, |
| ... | ... | @@ -2360,28 +2355,26 @@ pub fn genDecl(dg: *DeclGen, w: *Writer) Error!void { |
| 2360 | 2355 | const zcu = pt.zcu; |
| 2361 | 2356 | const ip = &zcu.intern_pool; |
| 2362 | 2357 | const nav = ip.getNav(dg.owner_nav.unwrap().?); |
| 2363 | const nav_ty: Type = .fromInterned(nav.typeOf(ip)); | |
| 2358 | const nav_ty: Type = .fromInterned(nav.resolved.?.type); | |
| 2364 | 2359 | |
| 2365 | const is_const: bool, const is_threadlocal: bool, const init_val: Value = switch (ip.indexToKey(nav.status.fully_resolved.val)) { | |
| 2366 | else => .{ true, false, .fromInterned(nav.status.fully_resolved.val) }, | |
| 2367 | .variable => |v| .{ false, v.is_threadlocal, .fromInterned(v.init) }, | |
| 2368 | .@"extern" => return, | |
| 2369 | }; | |
| 2360 | if (ip.indexToKey(nav.resolved.?.value) == .@"extern") return; | |
| 2370 | 2361 | |
| 2371 | if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |s| { | |
| 2362 | const init_val: Value = .fromInterned(nav.resolved.?.value); | |
| 2363 | ||
| 2364 | if (nav.resolved.?.@"linksection".toSlice(ip)) |s| { | |
| 2372 | 2365 | try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)}); |
| 2373 | 2366 | } |
| 2374 | 2367 | |
| 2375 | 2368 | // We don't bother underaligning---it's unnecessary and hurts compatibility. |
| 2376 | const a = nav.status.fully_resolved.alignment; | |
| 2369 | const a = nav.resolved.?.@"align"; | |
| 2377 | 2370 | if (a != .none and a.compareStrict(.gt, nav_ty.abiAlignment(zcu))) { |
| 2378 | 2371 | try w.print("zig_align({d}) ", .{a.toByteUnits().?}); |
| 2379 | 2372 | } |
| 2380 | 2373 | |
| 2381 | 2374 | try genDeclValue(dg, w, .{ |
| 2382 | 2375 | .name = .{ .nav = dg.owner_nav.unwrap().? }, |
| 2383 | .@"const" = is_const, | |
| 2384 | .@"threadlocal" = is_threadlocal, | |
| 2376 | .@"const" = nav.resolved.?.@"const", | |
| 2377 | .@"threadlocal" = nav.resolved.?.@"threadlocal", | |
| 2385 | 2378 | .init_val = init_val, |
| 2386 | 2379 | }); |
| 2387 | 2380 | } |
| ... | ... | @@ -2393,19 +2386,18 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void { |
| 2393 | 2386 | const zcu = pt.zcu; |
| 2394 | 2387 | const ip = &zcu.intern_pool; |
| 2395 | 2388 | const nav = ip.getNav(dg.owner_nav.unwrap().?); |
| 2396 | const nav_ty: Type = .fromInterned(nav.typeOf(ip)); | |
| 2389 | const nav_ty: Type = .fromInterned(nav.resolved.?.type); | |
| 2397 | 2390 | |
| 2398 | const is_const: bool, const is_threadlocal: bool, const init_val: Value = switch (ip.indexToKey(nav.status.fully_resolved.val)) { | |
| 2399 | else => .{ true, false, .fromInterned(nav.status.fully_resolved.val) }, | |
| 2400 | .variable => |v| .{ false, v.is_threadlocal, .fromInterned(v.init) }, | |
| 2391 | const init_val: Value = switch (ip.indexToKey(nav.resolved.?.value)) { | |
| 2392 | else => .fromInterned(nav.resolved.?.value), | |
| 2401 | 2393 | |
| 2402 | 2394 | .@"extern" => |@"extern"| switch (nav_ty.zigTypeTag(zcu)) { |
| 2403 | 2395 | .@"fn" => { |
| 2404 | 2396 | try w.writeAll("zig_extern "); |
| 2405 | 2397 | try dg.renderFunctionSignature( |
| 2406 | 2398 | w, |
| 2407 | Value.fromInterned(nav.status.fully_resolved.val), | |
| 2408 | nav.status.fully_resolved.alignment, | |
| 2399 | .fromInterned(nav.resolved.?.value), | |
| 2400 | nav.resolved.?.@"align", | |
| 2409 | 2401 | .forward_decl, |
| 2410 | 2402 | .{ .@"export" = .{ |
| 2411 | 2403 | .main_name = nav.name, |
| ... | ... | @@ -2422,15 +2414,15 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void { |
| 2422 | 2414 | .weak => try w.print("zig_extern zig_weak_linkage zig_visibility({t}) ", .{@"extern".visibility}), |
| 2423 | 2415 | .link_once => return dg.fail("TODO: CBE: implement linkonce linkage?", .{}), |
| 2424 | 2416 | } |
| 2425 | if (@"extern".is_threadlocal and !dg.mod.single_threaded) { | |
| 2417 | if (nav.resolved.?.@"threadlocal" and !dg.mod.single_threaded) { | |
| 2426 | 2418 | try w.writeAll("zig_threadlocal "); |
| 2427 | 2419 | } |
| 2428 | 2420 | try dg.renderTypeAndName( |
| 2429 | 2421 | w, |
| 2430 | .fromInterned(nav.typeOf(ip)), | |
| 2422 | .fromInterned(nav.resolved.?.type), | |
| 2431 | 2423 | .{ .nav = dg.owner_nav.unwrap().? }, |
| 2432 | .{ .@"const" = @"extern".is_const }, | |
| 2433 | nav.getAlignment(), | |
| 2424 | .{ .@"const" = nav.resolved.?.@"const" }, | |
| 2425 | nav.resolved.?.@"align", | |
| 2434 | 2426 | ); |
| 2435 | 2427 | try w.writeAll(";\n"); |
| 2436 | 2428 | return; |
| ... | ... | @@ -2439,15 +2431,15 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void { |
| 2439 | 2431 | }; |
| 2440 | 2432 | |
| 2441 | 2433 | // We don't bother underaligning---it's unnecessary and hurts compatibility. |
| 2442 | const a = nav.status.fully_resolved.alignment; | |
| 2434 | const a = nav.resolved.?.@"align"; | |
| 2443 | 2435 | if (a != .none and a.compareStrict(.gt, nav_ty.abiAlignment(zcu))) { |
| 2444 | 2436 | try w.print("zig_align({d}) ", .{a.toByteUnits().?}); |
| 2445 | 2437 | } |
| 2446 | 2438 | |
| 2447 | 2439 | try genDeclValueFwd(dg, w, .{ |
| 2448 | 2440 | .name = .{ .nav = dg.owner_nav.unwrap().? }, |
| 2449 | .@"const" = is_const, | |
| 2450 | .@"threadlocal" = is_threadlocal, | |
| 2441 | .@"const" = nav.resolved.?.@"const", | |
| 2442 | .@"threadlocal" = nav.resolved.?.@"threadlocal", | |
| 2451 | 2443 | .init_val = init_val, |
| 2452 | 2444 | }); |
| 2453 | 2445 | } |
| ... | ... | @@ -2514,11 +2506,9 @@ pub fn genExports(dg: *DeclGen, w: *Writer, exported: Zcu.Exported, export_indic |
| 2514 | 2506 | ); |
| 2515 | 2507 | try w.writeAll(";\n"); |
| 2516 | 2508 | }; |
| 2517 | const is_const = switch (ip.indexToKey(exported_val.toIntern())) { | |
| 2518 | .func => unreachable, | |
| 2519 | .@"extern" => |@"extern"| @"extern".is_const, | |
| 2520 | .variable => false, | |
| 2521 | else => true, | |
| 2509 | const is_const = switch (exported) { | |
| 2510 | .nav => |nav| ip.getNav(nav).resolved.?.@"const", | |
| 2511 | .uav => true, | |
| 2522 | 2512 | }; |
| 2523 | 2513 | for (export_indices) |export_index| { |
| 2524 | 2514 | const @"export" = export_index.ptr(zcu); |
src/codegen/c/type.zig-1| ... | ... | @@ -990,7 +990,6 @@ pub const CType = union(enum) { |
| 990 | 990 | // values, not types |
| 991 | 991 | .undef, |
| 992 | 992 | .simple_value, |
| 993 | .variable, | |
| 994 | 993 | .@"extern", |
| 995 | 994 | .func, |
| 996 | 995 | .int, |
src/codegen/llvm.zig+27-34| ... | ... | @@ -1279,7 +1279,7 @@ pub const Object = struct { |
| 1279 | 1279 | } }, &o.builder); |
| 1280 | 1280 | } |
| 1281 | 1281 | |
| 1282 | if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |section| | |
| 1282 | if (nav.resolved.?.@"linksection".toSlice(ip)) |section| | |
| 1283 | 1283 | function_index.setSection(try o.builder.string(section), &o.builder); |
| 1284 | 1284 | |
| 1285 | 1285 | var deinit_wip = true; |
| ... | ... | @@ -1487,7 +1487,7 @@ pub const Object = struct { |
| 1487 | 1487 | const file = try o.getDebugFile(pt, file_scope); |
| 1488 | 1488 | |
| 1489 | 1489 | const line_number = zcu.navSrcLine(func.owner_nav) + 1; |
| 1490 | const is_internal_linkage = ip.indexToKey(nav.status.fully_resolved.val) != .@"extern"; | |
| 1490 | const is_internal_linkage = ip.indexToKey(nav.resolved.?.value) != .@"extern"; | |
| 1491 | 1491 | const debug_decl_type = try o.getDebugType(pt, fn_ty); |
| 1492 | 1492 | |
| 1493 | 1493 | const subprogram = try o.builder.debugSubprogram( |
| ... | ... | @@ -1662,7 +1662,7 @@ pub const Object = struct { |
| 1662 | 1662 | .elf, .wasm => break :coff_export_flags, |
| 1663 | 1663 | .coff => |*coff| coff, |
| 1664 | 1664 | }; |
| 1665 | if (!ip.isFunctionType(ip.getNav(nav_index).typeOf(ip))) break :coff_export_flags; | |
| 1665 | if (!ip.isFunctionType(ip.getNav(nav_index).resolved.?.type)) break :coff_export_flags; | |
| 1666 | 1666 | const flags = &coff.lld_export_flags; |
| 1667 | 1667 | for (export_indices) |export_index| { |
| 1668 | 1668 | const name = export_index.ptr(zcu).opts.name; |
| ... | ... | @@ -2677,7 +2677,7 @@ pub const Object = struct { |
| 2677 | 2677 | const gpa = o.gpa; |
| 2678 | 2678 | const nav = ip.getNav(nav_index); |
| 2679 | 2679 | const owner_mod = zcu.navFileScope(nav_index).mod.?; |
| 2680 | const ty: Type = .fromInterned(nav.typeOf(ip)); | |
| 2680 | const ty: Type = .fromInterned(nav.resolved.?.type); | |
| 2681 | 2681 | const gop = try o.nav_map.getOrPut(gpa, nav_index); |
| 2682 | 2682 | if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function; |
| 2683 | 2683 | |
| ... | ... | @@ -2692,7 +2692,7 @@ pub const Object = struct { |
| 2692 | 2692 | const function_index = try o.builder.addFunction( |
| 2693 | 2693 | try o.lowerType(pt, ty), |
| 2694 | 2694 | try o.builder.strtabString((if (is_extern) nav.name else nav.fqn).toSlice(ip)), |
| 2695 | toLlvmAddressSpace(nav.getAddrspace(), target), | |
| 2695 | toLlvmAddressSpace(nav.resolved.?.@"addrspace", target), | |
| 2696 | 2696 | ); |
| 2697 | 2697 | gop.value_ptr.* = function_index.ptrConst(&o.builder).global; |
| 2698 | 2698 | |
| ... | ... | @@ -2809,8 +2809,8 @@ pub const Object = struct { |
| 2809 | 2809 | } |
| 2810 | 2810 | } |
| 2811 | 2811 | |
| 2812 | if (nav.getAlignment() != .none) | |
| 2813 | function_index.setAlignment(nav.getAlignment().toLlvm(), &o.builder); | |
| 2812 | if (nav.resolved.?.@"align" != .none) | |
| 2813 | function_index.setAlignment(nav.resolved.?.@"align".toLlvm(), &o.builder); | |
| 2814 | 2814 | |
| 2815 | 2815 | // Function attributes that are independent of analysis results of the function body. |
| 2816 | 2816 | try o.addCommonFnAttributes( |
| ... | ... | @@ -2951,15 +2951,12 @@ pub const Object = struct { |
| 2951 | 2951 | const zcu = pt.zcu; |
| 2952 | 2952 | const ip = &zcu.intern_pool; |
| 2953 | 2953 | const nav = ip.getNav(nav_index); |
| 2954 | const linkage: std.builtin.GlobalLinkage, const visibility: Builder.Visibility, const is_threadlocal, const is_dll_import = switch (nav.status) { | |
| 2955 | .unresolved => unreachable, | |
| 2956 | .fully_resolved => |r| switch (ip.indexToKey(r.val)) { | |
| 2957 | .variable => |variable| .{ .internal, .default, variable.is_threadlocal, false }, | |
| 2958 | .@"extern" => |@"extern"| .{ @"extern".linkage, .fromSymbolVisibility(@"extern".visibility), @"extern".is_threadlocal, @"extern".is_dll_import }, | |
| 2959 | else => .{ .internal, .default, false, false }, | |
| 2954 | const linkage: std.builtin.GlobalLinkage, const visibility: Builder.Visibility, const is_dll_import: bool = switch (nav.resolved.?.value) { | |
| 2955 | .none => .{ .internal, .default, false }, // this is a source declaration which is *not* marked `extern` | |
| 2956 | else => |val| switch (ip.indexToKey(val)) { | |
| 2957 | else => .{ .internal, .default, false }, | |
| 2958 | .@"extern" => |e| .{ e.linkage, .fromSymbolVisibility(e.visibility), e.is_dll_import }, | |
| 2960 | 2959 | }, |
| 2961 | // This means it's a source declaration which is not `extern`! | |
| 2962 | .type_resolved => |r| .{ .internal, .default, r.is_threadlocal, false }, | |
| 2963 | 2960 | }; |
| 2964 | 2961 | |
| 2965 | 2962 | const variable_index = try o.builder.addVariable( |
| ... | ... | @@ -2968,8 +2965,8 @@ pub const Object = struct { |
| 2968 | 2965 | .strong, .weak => nav.name, |
| 2969 | 2966 | .link_once => unreachable, |
| 2970 | 2967 | }.toSlice(ip)), |
| 2971 | try o.lowerType(pt, Type.fromInterned(nav.typeOf(ip))), | |
| 2972 | toLlvmGlobalAddressSpace(nav.getAddrspace(), zcu.getTarget()), | |
| 2968 | try o.lowerType(pt, .fromInterned(nav.resolved.?.type)), | |
| 2969 | toLlvmGlobalAddressSpace(nav.resolved.?.@"addrspace", zcu.getTarget()), | |
| 2973 | 2970 | ); |
| 2974 | 2971 | gop.value_ptr.* = variable_index.ptrConst(&o.builder).global; |
| 2975 | 2972 | |
| ... | ... | @@ -2987,7 +2984,7 @@ pub const Object = struct { |
| 2987 | 2984 | .link_once => unreachable, |
| 2988 | 2985 | }, &o.builder); |
| 2989 | 2986 | variable_index.setUnnamedAddr(.default, &o.builder); |
| 2990 | if (is_threadlocal and !zcu.navFileScope(nav_index).mod.?.single_threaded) | |
| 2987 | if (nav.resolved.?.@"threadlocal" and !zcu.navFileScope(nav_index).mod.?.single_threaded) | |
| 2991 | 2988 | variable_index.setThreadLocal(.generaldynamic, &o.builder); |
| 2992 | 2989 | if (is_dll_import) variable_index.setDllStorageClass(.dllimport, &o.builder); |
| 2993 | 2990 | }, |
| ... | ... | @@ -3422,7 +3419,6 @@ pub const Object = struct { |
| 3422 | 3419 | // values, not types |
| 3423 | 3420 | .undef, |
| 3424 | 3421 | .simple_value, |
| 3425 | .variable, | |
| 3426 | 3422 | .@"extern", |
| 3427 | 3423 | .func, |
| 3428 | 3424 | .int, |
| ... | ... | @@ -3553,9 +3549,7 @@ pub const Object = struct { |
| 3553 | 3549 | .false => .false, |
| 3554 | 3550 | .true => .true, |
| 3555 | 3551 | }, |
| 3556 | .variable, | |
| 3557 | .enum_literal, | |
| 3558 | => unreachable, // non-runtime values | |
| 3552 | .enum_literal => unreachable, // non-runtime value | |
| 3559 | 3553 | .@"extern" => |@"extern"| { |
| 3560 | 3554 | const function_index = try o.resolveLlvmFunction(pt, @"extern".owner_nav); |
| 3561 | 3555 | return function_index.ptrConst(&o.builder).global.toConst(); |
| ... | ... | @@ -4131,7 +4125,7 @@ pub const Object = struct { |
| 4131 | 4125 | |
| 4132 | 4126 | const nav = ip.getNav(nav_index); |
| 4133 | 4127 | |
| 4134 | const nav_ty = Type.fromInterned(nav.typeOf(ip)); | |
| 4128 | const nav_ty: Type = .fromInterned(nav.resolved.?.type); | |
| 4135 | 4129 | const ptr_ty = try pt.navPtrType(nav_index); |
| 4136 | 4130 | |
| 4137 | 4131 | if (nav.getExtern(ip) == null and !nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { |
| ... | ... | @@ -4145,7 +4139,7 @@ pub const Object = struct { |
| 4145 | 4139 | |
| 4146 | 4140 | const llvm_val = try o.builder.convConst( |
| 4147 | 4141 | llvm_global.toConst(), |
| 4148 | try o.builder.ptrType(toLlvmAddressSpace(nav.getAddrspace(), zcu.getTarget())), | |
| 4142 | try o.builder.ptrType(toLlvmAddressSpace(nav.resolved.?.@"addrspace", zcu.getTarget())), | |
| 4149 | 4143 | ); |
| 4150 | 4144 | |
| 4151 | 4145 | return o.builder.convConst(llvm_val, try o.lowerType(pt, ptr_ty)); |
| ... | ... | @@ -4398,14 +4392,13 @@ pub const NavGen = struct { |
| 4398 | 4392 | const ip = &zcu.intern_pool; |
| 4399 | 4393 | const nav_index = ng.nav_index; |
| 4400 | 4394 | const nav = ip.getNav(nav_index); |
| 4401 | const resolved = nav.status.fully_resolved; | |
| 4395 | const resolved = nav.resolved.?; | |
| 4402 | 4396 | |
| 4403 | const lib_name, const linkage, const visibility: Builder.Visibility, const is_threadlocal, const is_dll_import, const is_const, const init_val, const owner_nav = switch (ip.indexToKey(resolved.val)) { | |
| 4404 | .variable => |variable| .{ .none, .internal, .default, variable.is_threadlocal, false, false, variable.init, variable.owner_nav }, | |
| 4405 | .@"extern" => |@"extern"| .{ @"extern".lib_name, @"extern".linkage, .fromSymbolVisibility(@"extern".visibility), @"extern".is_threadlocal, @"extern".is_dll_import, @"extern".is_const, .none, @"extern".owner_nav }, | |
| 4406 | else => .{ .none, .internal, .default, false, false, true, resolved.val, nav_index }, | |
| 4397 | const lib_name, const linkage, const visibility: Builder.Visibility, const is_dll_import, const init_val, const owner_nav = switch (ip.indexToKey(resolved.value)) { | |
| 4398 | else => .{ .none, .internal, .default, false, resolved.value, nav_index }, | |
| 4399 | .@"extern" => |e| .{ e.lib_name, e.linkage, .fromSymbolVisibility(e.visibility), e.is_dll_import, .none, e.owner_nav }, | |
| 4407 | 4400 | }; |
| 4408 | const ty = Type.fromInterned(nav.typeOf(ip)); | |
| 4401 | const ty: Type = .fromInterned(nav.resolved.?.type); | |
| 4409 | 4402 | |
| 4410 | 4403 | if (linkage != .internal and ip.isFunctionType(ty.toIntern())) { |
| 4411 | 4404 | const function_index = try o.resolveLlvmFunction(pt, owner_nav); |
| ... | ... | @@ -4448,7 +4441,7 @@ pub const NavGen = struct { |
| 4448 | 4441 | variable_index.setAlignment(zcu.navAlignment(nav_index).toLlvm(), &o.builder); |
| 4449 | 4442 | if (resolved.@"linksection".toSlice(ip)) |section| |
| 4450 | 4443 | variable_index.setSection(try o.builder.string(section), &o.builder); |
| 4451 | if (is_const) variable_index.setMutability(.constant, &o.builder); | |
| 4444 | if (resolved.@"const") variable_index.setMutability(.constant, &o.builder); | |
| 4452 | 4445 | try variable_index.setInitializer(switch (init_val) { |
| 4453 | 4446 | .none => .no_init, |
| 4454 | 4447 | else => try o.lowerValue(pt, init_val), |
| ... | ... | @@ -4457,7 +4450,7 @@ pub const NavGen = struct { |
| 4457 | 4450 | |
| 4458 | 4451 | const file_scope = zcu.navFileScopeIndex(nav_index); |
| 4459 | 4452 | const mod = zcu.fileByIndex(file_scope).mod.?; |
| 4460 | if (is_threadlocal and !mod.single_threaded) | |
| 4453 | if (resolved.@"threadlocal" and !mod.single_threaded) | |
| 4461 | 4454 | variable_index.setThreadLocal(.generaldynamic, &o.builder); |
| 4462 | 4455 | |
| 4463 | 4456 | const line_number = zcu.navSrcLine(nav_index) + 1; |
| ... | ... | @@ -5475,7 +5468,7 @@ pub const FuncGen = struct { |
| 5475 | 5468 | _ = try self.wip.retVoid(); |
| 5476 | 5469 | return; |
| 5477 | 5470 | } |
| 5478 | const fn_info = zcu.typeToFunc(Type.fromInterned(ip.getNav(self.ng.nav_index).typeOf(ip))).?; | |
| 5471 | const fn_info = zcu.typeToFunc(Type.fromInterned(ip.getNav(self.ng.nav_index).resolved.?.type)).?; | |
| 5479 | 5472 | if (!ret_ty.hasRuntimeBits(zcu)) { |
| 5480 | 5473 | if (Type.fromInterned(fn_info.return_type).isError(zcu)) { |
| 5481 | 5474 | // Functions with an empty error set are emitted with an error code |
| ... | ... | @@ -5540,7 +5533,7 @@ pub const FuncGen = struct { |
| 5540 | 5533 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 5541 | 5534 | const ptr_ty = self.typeOf(un_op); |
| 5542 | 5535 | const ret_ty = ptr_ty.childType(zcu); |
| 5543 | const fn_info = zcu.typeToFunc(Type.fromInterned(ip.getNav(self.ng.nav_index).typeOf(ip))).?; | |
| 5536 | const fn_info = zcu.typeToFunc(.fromInterned(ip.getNav(self.ng.nav_index).resolved.?.type)).?; | |
| 5544 | 5537 | if (!ret_ty.hasRuntimeBits(zcu)) { |
| 5545 | 5538 | if (Type.fromInterned(fn_info.return_type).isError(zcu)) { |
| 5546 | 5539 | // Functions with an empty error set are emitted with an error code |
src/codegen/spirv/CodeGen.zig+39-58| ... | ... | @@ -256,7 +256,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { |
| 256 | 256 | .global => { |
| 257 | 257 | const key = ip.indexToKey(val.toIntern()).@"extern"; |
| 258 | 258 | |
| 259 | const storage_class = cg.module.storageClass(nav.getAddrspace()); | |
| 259 | const storage_class = cg.module.storageClass(nav.resolved.?.@"addrspace"); | |
| 260 | 260 | assert(storage_class != .generic); // These should be instance globals |
| 261 | 261 | |
| 262 | 262 | const ty_id = try cg.resolveType(ty, .indirect); |
| ... | ... | @@ -314,64 +314,47 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { |
| 314 | 314 | try cg.module.debugName(result_id, nav.fqn.toSlice(ip)); |
| 315 | 315 | }, |
| 316 | 316 | .invocation_global => { |
| 317 | const maybe_init_val: ?Value = switch (ip.indexToKey(val.toIntern())) { | |
| 318 | .func => unreachable, | |
| 319 | .variable => |variable| .fromInterned(variable.init), | |
| 320 | .@"extern" => null, | |
| 321 | else => val, | |
| 322 | }; | |
| 323 | ||
| 324 | 317 | const ty_id = try cg.resolveType(ty, .indirect); |
| 325 | 318 | const ptr_ty_id = try cg.module.ptrType(ty_id, .function); |
| 326 | 319 | |
| 327 | if (maybe_init_val) |init_val| { | |
| 328 | // TODO: Combine with resolveAnonDecl? | |
| 329 | const void_ty_id = try cg.resolveType(.void, .direct); | |
| 330 | const initializer_proto_ty_id = try cg.module.functionType(void_ty_id, &.{}); | |
| 331 | ||
| 332 | const initializer_id = cg.module.allocId(); | |
| 333 | try cg.prologue.emit(gpa, .OpFunction, .{ | |
| 334 | .id_result_type = try cg.resolveType(.void, .direct), | |
| 335 | .id_result = initializer_id, | |
| 336 | .function_control = .{}, | |
| 337 | .function_type = initializer_proto_ty_id, | |
| 338 | }); | |
| 320 | // TODO: Combine with resolveAnonDecl? | |
| 321 | const void_ty_id = try cg.resolveType(.void, .direct); | |
| 322 | const initializer_proto_ty_id = try cg.module.functionType(void_ty_id, &.{}); | |
| 339 | 323 | |
| 340 | const root_block_id = cg.module.allocId(); | |
| 341 | try cg.prologue.emit(gpa, .OpLabel, .{ | |
| 342 | .id_result = root_block_id, | |
| 343 | }); | |
| 344 | cg.block_label = root_block_id; | |
| 324 | const initializer_id = cg.module.allocId(); | |
| 325 | try cg.prologue.emit(gpa, .OpFunction, .{ | |
| 326 | .id_result_type = try cg.resolveType(.void, .direct), | |
| 327 | .id_result = initializer_id, | |
| 328 | .function_control = .{}, | |
| 329 | .function_type = initializer_proto_ty_id, | |
| 330 | }); | |
| 345 | 331 | |
| 346 | const val_id = try cg.constant(ty, init_val, .indirect); | |
| 347 | try cg.body.emit(gpa, .OpStore, .{ | |
| 348 | .pointer = result_id, | |
| 349 | .object = val_id, | |
| 350 | }); | |
| 332 | const root_block_id = cg.module.allocId(); | |
| 333 | try cg.prologue.emit(gpa, .OpLabel, .{ | |
| 334 | .id_result = root_block_id, | |
| 335 | }); | |
| 336 | cg.block_label = root_block_id; | |
| 351 | 337 | |
| 352 | try cg.body.emit(gpa, .OpReturn, {}); | |
| 353 | try cg.body.emit(gpa, .OpFunctionEnd, {}); | |
| 354 | try cg.module.sections.functions.append(gpa, cg.prologue); | |
| 355 | try cg.module.sections.functions.append(gpa, cg.body); | |
| 338 | const val_id = try cg.constant(ty, val, .indirect); | |
| 339 | try cg.body.emit(gpa, .OpStore, .{ | |
| 340 | .pointer = result_id, | |
| 341 | .object = val_id, | |
| 342 | }); | |
| 356 | 343 | |
| 357 | try cg.module.debugNameFmt(initializer_id, "initializer of {f}", .{nav.fqn.fmt(ip)}); | |
| 344 | try cg.body.emit(gpa, .OpReturn, {}); | |
| 345 | try cg.body.emit(gpa, .OpFunctionEnd, {}); | |
| 346 | try cg.module.sections.functions.append(gpa, cg.prologue); | |
| 347 | try cg.module.sections.functions.append(gpa, cg.body); | |
| 358 | 348 | |
| 359 | try cg.module.sections.globals.emit(gpa, .OpExtInst, .{ | |
| 360 | .id_result_type = ptr_ty_id, | |
| 361 | .id_result = result_id, | |
| 362 | .set = try cg.module.importInstructionSet(.zig), | |
| 363 | .instruction = .{ .inst = @intFromEnum(spec.Zig.InvocationGlobal) }, | |
| 364 | .id_ref_4 = &.{initializer_id}, | |
| 365 | }); | |
| 366 | } else { | |
| 367 | try cg.module.sections.globals.emit(gpa, .OpExtInst, .{ | |
| 368 | .id_result_type = ptr_ty_id, | |
| 369 | .id_result = result_id, | |
| 370 | .set = try cg.module.importInstructionSet(.zig), | |
| 371 | .instruction = .{ .inst = @intFromEnum(spec.Zig.InvocationGlobal) }, | |
| 372 | .id_ref_4 = &.{}, | |
| 373 | }); | |
| 374 | } | |
| 349 | try cg.module.debugNameFmt(initializer_id, "initializer of {f}", .{nav.fqn.fmt(ip)}); | |
| 350 | ||
| 351 | try cg.module.sections.globals.emit(gpa, .OpExtInst, .{ | |
| 352 | .id_result_type = ptr_ty_id, | |
| 353 | .id_result = result_id, | |
| 354 | .set = try cg.module.importInstructionSet(.zig), | |
| 355 | .instruction = .{ .inst = @intFromEnum(spec.Zig.InvocationGlobal) }, | |
| 356 | .id_ref_4 = &.{initializer_id}, | |
| 357 | }); | |
| 375 | 358 | }, |
| 376 | 359 | } |
| 377 | 360 | |
| ... | ... | @@ -810,7 +793,6 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { |
| 810 | 793 | |
| 811 | 794 | .undef => unreachable, // handled above |
| 812 | 795 | |
| 813 | .variable, | |
| 814 | 796 | .@"extern", |
| 815 | 797 | .func, |
| 816 | 798 | .enum_literal, |
| ... | ... | @@ -1170,12 +1152,11 @@ fn constantNavRef(cg: *CodeGen, ty: Type, nav_index: InternPool.Nav.Index) !Id { |
| 1170 | 1152 | const ip = &zcu.intern_pool; |
| 1171 | 1153 | const ty_id = try cg.resolveType(ty, .direct); |
| 1172 | 1154 | const nav = ip.getNav(nav_index); |
| 1173 | const nav_ty: Type = .fromInterned(nav.typeOf(ip)); | |
| 1155 | const nav_ty: Type = .fromInterned(nav.resolved.?.type); | |
| 1174 | 1156 | |
| 1175 | switch (nav.status) { | |
| 1176 | .unresolved => unreachable, | |
| 1177 | .type_resolved => {}, // this is not a function or extern | |
| 1178 | .fully_resolved => |r| switch (ip.indexToKey(r.val)) { | |
| 1157 | switch (nav.resolved.?.value) { | |
| 1158 | .none => {}, // this is not a function or extern | |
| 1159 | else => |value| switch (ip.indexToKey(value)) { | |
| 1179 | 1160 | .func => { |
| 1180 | 1161 | // TODO: Properly lower function pointers. For now we are going to hack around it and |
| 1181 | 1162 | // just generate an empty pointer. Function pointers are represented by a pointer to usize. |
| ... | ... | @@ -1196,7 +1177,7 @@ fn constantNavRef(cg: *CodeGen, ty: Type, nav_index: InternPool.Nav.Index) !Id { |
| 1196 | 1177 | const spv_decl_result_id = spv_decl.result_id; |
| 1197 | 1178 | assert(spv_decl.kind != .func); |
| 1198 | 1179 | |
| 1199 | const storage_class = cg.module.storageClass(nav.getAddrspace()); | |
| 1180 | const storage_class = cg.module.storageClass(nav.resolved.?.@"addrspace"); | |
| 1200 | 1181 | try cg.addFunctionDep(spv_decl_index, storage_class); |
| 1201 | 1182 | |
| 1202 | 1183 | const nav_ty_id = try cg.resolveType(nav_ty, .indirect); |
src/codegen/spirv/Module.zig+2-2| ... | ... | @@ -252,9 +252,9 @@ pub fn resolveNav(module: *Module, ip: *InternPool, nav_index: InternPool.Nav.In |
| 252 | 252 | if (!entry.found_existing) { |
| 253 | 253 | const nav = ip.getNav(nav_index); |
| 254 | 254 | // TODO: Extern fn? |
| 255 | const kind: Decl.Kind = if (ip.isFunctionType(nav.typeOf(ip))) | |
| 255 | const kind: Decl.Kind = if (ip.isFunctionType(nav.resolved.?.type)) | |
| 256 | 256 | .func |
| 257 | else switch (nav.getAddrspace()) { | |
| 257 | else switch (nav.resolved.?.@"addrspace") { | |
| 258 | 258 | .generic => .invocation_global, |
| 259 | 259 | else => .global, |
| 260 | 260 | }; |
src/codegen/wasm/CodeGen.zig+1-2| ... | ... | @@ -575,7 +575,7 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void { |
| 575 | 575 | .nav_ref => |nav_ref| { |
| 576 | 576 | const zcu = cg.pt.zcu; |
| 577 | 577 | const ip = &zcu.intern_pool; |
| 578 | if (ip.getNav(nav_ref.nav_index).isFn(ip)) { | |
| 578 | if (ip.zigTypeTag(ip.getNav(nav_ref.nav_index).resolved.?.type) == .@"fn") { | |
| 579 | 579 | assert(nav_ref.offset == 0); |
| 580 | 580 | try cg.mir_indirect_function_set.put(cg.gpa, nav_ref.nav_index, {}); |
| 581 | 581 | try cg.addInst(.{ .tag = .func_ref, .data = .{ .nav_index = nav_ref.nav_index } }); |
| ... | ... | @@ -4401,7 +4401,6 @@ fn lowerConstant(cg: *CodeGen, val: Value) InnerError!WValue { |
| 4401 | 4401 | else => unreachable, |
| 4402 | 4402 | } }, |
| 4403 | 4403 | }, |
| 4404 | .variable, | |
| 4405 | 4404 | .@"extern", |
| 4406 | 4405 | .func, |
| 4407 | 4406 | .enum_literal, |
src/codegen/wasm/Emit.zig+1-1| ... | ... | @@ -970,7 +970,7 @@ fn navRefOff(wasm: *Wasm, code: *ArrayList(u8), data: Mir.NavRefOff, is_wasm32: |
| 970 | 970 | const ip = &zcu.intern_pool; |
| 971 | 971 | const gpa = comp.gpa; |
| 972 | 972 | const is_obj = comp.config.output_mode == .Obj; |
| 973 | const nav_ty = ip.getNav(data.nav_index).typeOf(ip); | |
| 973 | const nav_ty = ip.getNav(data.nav_index).resolved.?.type; | |
| 974 | 974 | assert(!ip.isFunctionType(nav_ty)); |
| 975 | 975 | |
| 976 | 976 | try code.ensureUnusedCapacity(gpa, 11); |
src/codegen/x86_64/CodeGen.zig+2-2| ... | ... | @@ -173046,7 +173046,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 173046 | 173046 | .runtime_nav_ptr => { |
| 173047 | 173047 | const ty_nav = air_datas[@intFromEnum(inst)].ty_nav; |
| 173048 | 173048 | const nav = ip.getNav(ty_nav.nav); |
| 173049 | const is_threadlocal = zcu.comp.config.any_non_single_threaded and nav.isThreadlocal(ip); | |
| 173049 | const is_threadlocal = zcu.comp.config.any_non_single_threaded and nav.resolved.?.@"threadlocal"; | |
| 173050 | 173050 | |
| 173051 | 173051 | if (is_threadlocal) switch (cg.target.ofmt) { |
| 173052 | 173052 | .elf => if (cg.mod.pic) { |
| ... | ... | @@ -179146,7 +179146,7 @@ fn genSetMem( |
| 179146 | 179146 | .off = disp, |
| 179147 | 179147 | }).compare(.gte, src_align), |
| 179148 | 179148 | .table, .rip_inst, .lazy_sym, .extern_func => unreachable, |
| 179149 | .nav => |nav| ip.getNav(nav).getAlignment().compare(.gte, src_align), | |
| 179149 | .nav => |nav| ip.getNav(nav).resolved.?.@"align".compare(.gte, src_align), | |
| 179150 | 179150 | .uav => |uav| Type.fromInterned(uav.orig_ty).ptrAlignment(zcu).compare(.gte, src_align), |
| 179151 | 179151 | })).write(self, .{ |
| 179152 | 179152 | .base = base, |
src/codegen/x86_64/Emit.zig+16-23| ... | ... | @@ -115,33 +115,26 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 115 | 115 | return error.EmitFail; |
| 116 | 116 | }, |
| 117 | 117 | }; |
| 118 | break :target switch (ip.getNav(nav).status) { | |
| 119 | .unresolved => unreachable, | |
| 120 | .type_resolved => |type_resolved| .{ | |
| 118 | const resolved_nav = ip.getNav(nav).resolved.?; | |
| 119 | if (resolved_nav.value != .none) switch (ip.indexToKey(resolved_nav.value)) { | |
| 120 | .@"extern" => |@"extern"| break :target .{ | |
| 121 | 121 | .index = sym_index, |
| 122 | .is_extern = false, | |
| 123 | .type = if (type_resolved.is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol, | |
| 124 | }, | |
| 125 | .fully_resolved => |fully_resolved| switch (ip.indexToKey(fully_resolved.val)) { | |
| 126 | .@"extern" => |@"extern"| .{ | |
| 127 | .index = sym_index, | |
| 128 | .is_extern = switch (@"extern".visibility) { | |
| 129 | .default => true, | |
| 130 | .hidden, .protected => false, | |
| 131 | }, | |
| 132 | .type = if (@"extern".is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol, | |
| 133 | .force_pcrel_direct = switch (@"extern".relocation) { | |
| 134 | .any => false, | |
| 135 | .pcrel => true, | |
| 136 | }, | |
| 122 | .is_extern = switch (@"extern".visibility) { | |
| 123 | .default => true, | |
| 124 | .hidden, .protected => false, | |
| 137 | 125 | }, |
| 138 | .variable => |variable| .{ | |
| 139 | .index = sym_index, | |
| 140 | .is_extern = false, | |
| 141 | .type = if (variable.is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol, | |
| 126 | .type = if (resolved_nav.@"threadlocal" and comp.config.any_non_single_threaded) .tlv else .symbol, | |
| 127 | .force_pcrel_direct = switch (@"extern".relocation) { | |
| 128 | .any => false, | |
| 129 | .pcrel => true, | |
| 142 | 130 | }, |
| 143 | else => .{ .index = sym_index, .is_extern = false, .type = .symbol }, | |
| 144 | 131 | }, |
| 132 | else => {}, | |
| 133 | }; | |
| 134 | break :target .{ | |
| 135 | .index = sym_index, | |
| 136 | .is_extern = false, | |
| 137 | .type = if (resolved_nav.@"threadlocal" and comp.config.any_non_single_threaded) .tlv else .symbol, | |
| 145 | 138 | }; |
| 146 | 139 | }, |
| 147 | 140 | .uav => |uav| .{ |
src/link.zig+1-1| ... | ... | @@ -781,7 +781,7 @@ pub const File = struct { |
| 781 | 781 | fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateNavError!void { |
| 782 | 782 | assert(base.comp.zcu.?.llvm_object == null); |
| 783 | 783 | const nav = pt.zcu.intern_pool.getNav(nav_index); |
| 784 | assert(nav.status == .fully_resolved); | |
| 784 | assert(nav.resolved.?.value != .none); | |
| 785 | 785 | switch (base.tag) { |
| 786 | 786 | .lld => unreachable, |
| 787 | 787 | .plan9 => unreachable, |
src/link/C.zig+7-6| ... | ... | @@ -534,11 +534,11 @@ pub fn updateNav( |
| 534 | 534 | const ip = &zcu.intern_pool; |
| 535 | 535 | |
| 536 | 536 | const nav = ip.getNav(nav_index); |
| 537 | switch (ip.indexToKey(nav.status.fully_resolved.val)) { | |
| 537 | switch (ip.indexToKey(nav.resolved.?.value)) { | |
| 538 | 538 | .func => return, |
| 539 | 539 | .@"extern" => {}, |
| 540 | 540 | else => { |
| 541 | const nav_ty: Type = .fromInterned(nav.typeOf(ip)); | |
| 541 | const nav_ty: Type = .fromInterned(nav.resolved.?.type); | |
| 542 | 542 | if (!nav_ty.hasRuntimeBits(zcu)) { |
| 543 | 543 | if (c.navs.fetchSwapRemove(nav_index)) |kv| { |
| 544 | 544 | var old_rendered = kv.value; |
| ... | ... | @@ -762,7 +762,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog |
| 762 | 762 | { |
| 763 | 763 | const unit_references = try zcu.resolveReferences(); |
| 764 | 764 | for (c.navs.keys()) |nav| { |
| 765 | const nav_val = ip.getNav(nav).status.fully_resolved.val; | |
| 765 | const nav_val = ip.getNav(nav).resolved.?.value; | |
| 766 | 766 | const check_unit: ?InternPool.AnalUnit = switch (ip.indexToKey(nav_val)) { |
| 767 | 767 | else => .wrap(.{ .nav_val = nav }), |
| 768 | 768 | .func => .wrap(.{ .func = nav_val }), |
| ... | ... | @@ -1092,8 +1092,9 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog |
| 1092 | 1092 | // NAV forward declarations |
| 1093 | 1093 | for (need_navs.keys()) |nav| { |
| 1094 | 1094 | if (c.exported_navs.contains(nav)) continue; // the export was the declaration |
| 1095 | if (ip.getNav(nav).getExtern(ip)) |e| { | |
| 1096 | if (export_names.contains(e.name)) continue; | |
| 1095 | switch (ip.indexToKey(ip.getNav(nav).resolved.?.value)) { | |
| 1096 | .@"extern" => |e| if (export_names.contains(e.name)) continue, | |
| 1097 | else => {}, | |
| 1097 | 1098 | } |
| 1098 | 1099 | const fwd_decl = c.navs.getPtr(nav).?.fwd_decl; |
| 1099 | 1100 | f.appendBufAssumeCapacity(fwd_decl.get(c)); |
| ... | ... | @@ -1200,7 +1201,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog |
| 1200 | 1201 | const code = c.navs.getPtr(nav).?.code; |
| 1201 | 1202 | if (code.len == 0) continue; |
| 1202 | 1203 | if (!c.exported_navs.contains(nav)) { |
| 1203 | const is_extern = ip.getNav(nav).getExtern(ip) != null; | |
| 1204 | const is_extern = ip.indexToKey(ip.getNav(nav).resolved.?.value) == .@"extern"; | |
| 1204 | 1205 | f.appendBufAssumeCapacity(if (is_extern) "zig_extern " else "static "); |
| 1205 | 1206 | } |
| 1206 | 1207 | f.appendBufAssumeCapacity(code.get(c)); |
src/link/Coff.zig+21-34| ... | ... | @@ -1226,34 +1226,26 @@ pub fn globalSymbol(coff: *Coff, name: []const u8, lib_name: ?[]const u8) !Symbo |
| 1226 | 1226 | fn navSection( |
| 1227 | 1227 | coff: *Coff, |
| 1228 | 1228 | zcu: *Zcu, |
| 1229 | nav_fr: @FieldType(@FieldType(InternPool.Nav, "status"), "fully_resolved"), | |
| 1229 | nav_resolved: @typeInfo(@FieldType(InternPool.Nav, "resolved")).optional.child, | |
| 1230 | 1230 | ) !Symbol.Index { |
| 1231 | 1231 | const ip = &zcu.intern_pool; |
| 1232 | 1232 | const default: String, const attributes: ObjectSectionAttributes = |
| 1233 | switch (ip.indexToKey(nav_fr.val)) { | |
| 1234 | else => .{ .@".rdata", .{ .read = true } }, | |
| 1235 | .variable => |variable| if (variable.is_threadlocal and | |
| 1236 | coff.base.comp.config.any_non_single_threaded) | |
| 1237 | .{ .@".tls$", .{ .read = true, .write = true } } | |
| 1238 | else | |
| 1239 | .{ .@".data", .{ .read = true, .write = true } }, | |
| 1240 | .@"extern" => |@"extern"| if (@"extern".is_threadlocal and | |
| 1241 | coff.base.comp.config.any_non_single_threaded) | |
| 1242 | .{ .@".tls$", .{ .read = true, .write = true } } | |
| 1243 | else if (ip.isFunctionType(@"extern".ty)) | |
| 1244 | .{ .@".text", .{ .read = true, .execute = true } } | |
| 1245 | else if (@"extern".is_const) | |
| 1246 | .{ .@".rdata", .{ .read = true } } | |
| 1247 | else | |
| 1248 | .{ .@".data", .{ .read = true, .write = true } }, | |
| 1249 | .func => .{ .@".text", .{ .read = true, .execute = true } }, | |
| 1233 | if (nav_resolved.@"threadlocal" and coff.base.comp.config.any_non_single_threaded) .{ | |
| 1234 | .@".tls$", .{ .read = true, .write = true }, | |
| 1235 | } else if (ip.isFunctionType(nav_resolved.type)) .{ | |
| 1236 | .@".text", .{ .read = true, .execute = true }, | |
| 1237 | } else if (nav_resolved.@"const") .{ | |
| 1238 | .@".rdata", .{ .read = true }, | |
| 1239 | } else .{ | |
| 1240 | .@".data", .{ .read = true, .write = true }, | |
| 1250 | 1241 | }; |
| 1242 | ||
| 1251 | 1243 | return (try coff.objectSectionMapIndex( |
| 1252 | (try coff.getOrPutOptionalString(nav_fr.@"linksection".toSlice(ip))).unwrap() orelse default, | |
| 1253 | switch (nav_fr.@"linksection") { | |
| 1244 | (try coff.getOrPutOptionalString(nav_resolved.@"linksection".toSlice(ip))).unwrap() orelse default, | |
| 1245 | switch (nav_resolved.@"linksection") { | |
| 1254 | 1246 | .none => coff.mf.flags.block_size, |
| 1255 | else => switch (nav_fr.alignment) { | |
| 1256 | .none => Type.fromInterned(ip.typeOf(nav_fr.val)).abiAlignment(zcu), | |
| 1247 | else => switch (nav_resolved.@"align") { | |
| 1248 | .none => Type.fromInterned(ip.typeOf(nav_resolved.value)).abiAlignment(zcu), | |
| 1257 | 1249 | else => |alignment| alignment, |
| 1258 | 1250 | }.toStdMem(), |
| 1259 | 1251 | }, |
| ... | ... | @@ -1536,20 +1528,15 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde |
| 1536 | 1528 | const ip = &zcu.intern_pool; |
| 1537 | 1529 | |
| 1538 | 1530 | const nav = ip.getNav(nav_index); |
| 1539 | const nav_val = nav.status.fully_resolved.val; | |
| 1540 | const nav_init = switch (ip.indexToKey(nav_val)) { | |
| 1541 | else => nav_val, | |
| 1542 | .variable => |variable| variable.init, | |
| 1543 | .@"extern", .func => .none, | |
| 1544 | }; | |
| 1545 | if (nav_init == .none or !Type.fromInterned(ip.typeOf(nav_init)).hasRuntimeBits(zcu)) return; | |
| 1531 | if (ip.indexToKey(nav.resolved.?.value) == .@"extern") return; | |
| 1532 | if (!Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) return; | |
| 1546 | 1533 | |
| 1547 | 1534 | const nmi = try coff.navMapIndex(zcu, nav_index); |
| 1548 | 1535 | const si = nmi.symbol(coff); |
| 1549 | 1536 | const ni = ni: { |
| 1550 | 1537 | switch (si.get(coff).ni) { |
| 1551 | 1538 | .none => { |
| 1552 | const sec_si = try coff.navSection(zcu, nav.status.fully_resolved); | |
| 1539 | const sec_si = try coff.navSection(zcu, nav.resolved.?); | |
| 1553 | 1540 | try coff.nodes.ensureUnusedCapacity(gpa, 1); |
| 1554 | 1541 | const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{ |
| 1555 | 1542 | .alignment = zcu.navAlignment(nav_index).toStdMem(), |
| ... | ... | @@ -1576,7 +1563,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde |
| 1576 | 1563 | &coff.base, |
| 1577 | 1564 | pt, |
| 1578 | 1565 | zcu.navSrcLoc(nav_index), |
| 1579 | .fromInterned(nav_init), | |
| 1566 | .fromInterned(nav.resolved.?.value), | |
| 1580 | 1567 | &nw.interface, |
| 1581 | 1568 | .{ .atom_index = @intFromEnum(si) }, |
| 1582 | 1569 | ) catch |err| switch (err) { |
| ... | ... | @@ -1587,7 +1574,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde |
| 1587 | 1574 | si.applyLocationRelocs(coff); |
| 1588 | 1575 | } |
| 1589 | 1576 | |
| 1590 | if (nav.status.fully_resolved.@"linksection".unwrap()) |_| { | |
| 1577 | if (nav.resolved.?.@"linksection".unwrap()) |_| { | |
| 1591 | 1578 | try ni.resize(&coff.mf, gpa, si.get(coff).size); |
| 1592 | 1579 | var parent_ni = ni; |
| 1593 | 1580 | while (true) { |
| ... | ... | @@ -1674,12 +1661,12 @@ fn updateFuncInner( |
| 1674 | 1661 | const ni = ni: { |
| 1675 | 1662 | switch (si.get(coff).ni) { |
| 1676 | 1663 | .none => { |
| 1677 | const sec_si = try coff.navSection(zcu, nav.status.fully_resolved); | |
| 1664 | const sec_si = try coff.navSection(zcu, nav.resolved.?); | |
| 1678 | 1665 | try coff.nodes.ensureUnusedCapacity(gpa, 1); |
| 1679 | 1666 | const mod = zcu.navFileScope(func.owner_nav).mod.?; |
| 1680 | 1667 | const target = &mod.resolved_target.result; |
| 1681 | 1668 | const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{ |
| 1682 | .alignment = switch (nav.status.fully_resolved.alignment) { | |
| 1669 | .alignment = switch (nav.resolved.?.@"align") { | |
| 1683 | 1670 | .none => switch (mod.optimize_mode) { |
| 1684 | 1671 | .Debug, |
| 1685 | 1672 | .ReleaseSafe, |
src/link/Dwarf.zig+8-11| ... | ... | @@ -2681,7 +2681,7 @@ fn initWipNavInner( |
| 2681 | 2681 | } else try wip_nav.infoExprLoc(.{ .addr_reloc = sym_index }); |
| 2682 | 2682 | }, |
| 2683 | 2683 | .syntax => switch (ip.isFunctionType(@"extern".ty)) { |
| 2684 | false => continue :nav_val .{ .variable = undefined }, | |
| 2684 | false => continue :nav_val .{ .undef = @"extern".ty }, | |
| 2685 | 2685 | true => { |
| 2686 | 2686 | const func_type = ip.indexToKey(@"extern".ty).func_type; |
| 2687 | 2687 | const diw = &wip_nav.debug_info.writer; |
| ... | ... | @@ -2777,7 +2777,7 @@ fn initWipNavInner( |
| 2777 | 2777 | wip_nav.func_high_pc = @intCast(diw.end); |
| 2778 | 2778 | try diw.writeInt(u32, 0, dwarf.endian); |
| 2779 | 2779 | const target = &mod.resolved_target.result; |
| 2780 | try diw.writeUleb128(switch (nav.status.fully_resolved.alignment) { | |
| 2780 | try diw.writeUleb128(switch (nav.resolved.?.@"align") { | |
| 2781 | 2781 | .none => target_info.defaultFunctionAlignment(target), |
| 2782 | 2782 | else => |a| a.maxStrict(target_info.minFunctionAlignment(target)), |
| 2783 | 2783 | }.toByteUnits().?); |
| ... | ... | @@ -2845,7 +2845,7 @@ fn initWipNavInner( |
| 2845 | 2845 | .@"const" => { |
| 2846 | 2846 | const const_ty_reloc_index = try wip_nav.refForward(); |
| 2847 | 2847 | try wip_nav.infoExprLoc(loc); |
| 2848 | try diw.writeUleb128(nav.status.fully_resolved.alignment.toByteUnits() orelse | |
| 2848 | try diw.writeUleb128(nav.resolved.?.@"align".toByteUnits() orelse | |
| 2849 | 2849 | ty.abiAlignment(zcu).toByteUnits().?); |
| 2850 | 2850 | try diw.writeByte(@intFromBool(decl.linkage != .normal)); |
| 2851 | 2851 | wip_nav.finishForward(const_ty_reloc_index); |
| ... | ... | @@ -2855,7 +2855,7 @@ fn initWipNavInner( |
| 2855 | 2855 | .@"var" => { |
| 2856 | 2856 | try wip_nav.refType(ty); |
| 2857 | 2857 | try wip_nav.infoExprLoc(loc); |
| 2858 | try diw.writeUleb128(nav.status.fully_resolved.alignment.toByteUnits() orelse | |
| 2858 | try diw.writeUleb128(nav.resolved.?.@"align".toByteUnits() orelse | |
| 2859 | 2859 | ty.abiAlignment(zcu).toByteUnits().?); |
| 2860 | 2860 | try diw.writeByte(@intFromBool(decl.linkage != .normal)); |
| 2861 | 2861 | }, |
| ... | ... | @@ -3028,10 +3028,10 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3028 | 3028 | const zcu = pt.zcu; |
| 3029 | 3029 | const ip = &zcu.intern_pool; |
| 3030 | 3030 | const nav_src_loc = zcu.navSrcLoc(nav_index); |
| 3031 | const nav_val = zcu.navValue(nav_index); | |
| 3032 | 3031 | |
| 3033 | 3032 | const nav = ip.getNav(nav_index); |
| 3034 | 3033 | const inst_info = nav.srcInst(ip).resolveFull(ip).?; |
| 3034 | const nav_val: Value = .fromInterned(nav.resolved.?.value); | |
| 3035 | 3035 | const file = zcu.fileByIndex(inst_info.file); |
| 3036 | 3036 | const decl = file.zir.?.getDeclaration(inst_info.inst); |
| 3037 | 3037 | log.debug("updateComptimeNav({s}:{d}:{d} %{d} = {f})", .{ |
| ... | ... | @@ -3127,9 +3127,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3127 | 3127 | .aggregate, |
| 3128 | 3128 | .un, |
| 3129 | 3129 | .bitpack, |
| 3130 | => .@"const", | |
| 3131 | ||
| 3132 | .variable => .@"var", | |
| 3130 | => if (nav.resolved.?.@"const") .@"const" else .@"var", | |
| 3133 | 3131 | |
| 3134 | 3132 | .@"extern" => unreachable, |
| 3135 | 3133 | |
| ... | ... | @@ -3210,7 +3208,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3210 | 3208 | const nav_ty = nav_val.typeOf(zcu); |
| 3211 | 3209 | try wip_nav.refType(nav_ty); |
| 3212 | 3210 | try wip_nav.blockValue(nav_src_loc, nav_val); |
| 3213 | try diw.writeUleb128(nav.status.fully_resolved.alignment.toByteUnits() orelse | |
| 3211 | try diw.writeUleb128(nav.resolved.?.@"align".toByteUnits() orelse | |
| 3214 | 3212 | nav_ty.abiAlignment(zcu).toByteUnits().?); |
| 3215 | 3213 | try diw.writeByte(@intFromBool(decl.linkage != .normal)); |
| 3216 | 3214 | }, |
| ... | ... | @@ -3240,7 +3238,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo |
| 3240 | 3238 | .@"extern", .@"export" => nav.name, |
| 3241 | 3239 | }.toSlice(ip)); |
| 3242 | 3240 | const nav_ty_reloc_index = try wip_nav.refForward(); |
| 3243 | try diw.writeUleb128(nav.status.fully_resolved.alignment.toByteUnits() orelse | |
| 3241 | try diw.writeUleb128(nav.resolved.?.@"align".toByteUnits() orelse | |
| 3244 | 3242 | nav_ty.abiAlignment(zcu).toByteUnits().?); |
| 3245 | 3243 | try diw.writeByte(@intFromBool(decl.linkage != .normal)); |
| 3246 | 3244 | if (has_runtime_bits) try wip_nav.blockValue(nav_src_loc, nav_val); |
| ... | ... | @@ -4281,7 +4279,6 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co |
| 4281 | 4279 | try wip_nav.refType(.null); |
| 4282 | 4280 | }, |
| 4283 | 4281 | }, |
| 4284 | .variable => unreachable, // not a value | |
| 4285 | 4282 | .int => |int| { |
| 4286 | 4283 | try wip_nav.bigIntConstValue(.{ |
| 4287 | 4284 | .sdata = .sdata_comptime_value, |
src/link/Elf/ZigObject.zig+16-20| ... | ... | @@ -1113,7 +1113,7 @@ pub fn getOrCreateMetadataForNav(self: *ZigObject, zcu: *Zcu, nav_index: InternP |
| 1113 | 1113 | if (!gop.found_existing) { |
| 1114 | 1114 | const symbol_index = try self.newSymbolWithAtom(gpa, 0); |
| 1115 | 1115 | const sym = self.symbol(symbol_index); |
| 1116 | if (ip.getNav(nav_index).isThreadlocal(ip) and zcu.comp.config.any_non_single_threaded) { | |
| 1116 | if (ip.getNav(nav_index).resolved.?.@"threadlocal" and zcu.comp.config.any_non_single_threaded) { | |
| 1117 | 1117 | sym.flags.is_tls = true; |
| 1118 | 1118 | } |
| 1119 | 1119 | gop.value_ptr.* = .{ .symbol_index = symbol_index }; |
| ... | ... | @@ -1143,9 +1143,10 @@ fn getNavShdrIndex( |
| 1143 | 1143 | const gpa = elf_file.base.comp.gpa; |
| 1144 | 1144 | const ptr_size = elf_file.ptrWidthBytes(); |
| 1145 | 1145 | const ip = &zcu.intern_pool; |
| 1146 | const nav_val = zcu.navValue(nav_index); | |
| 1146 | const nav = ip.getNav(nav_index); | |
| 1147 | const nav_val: Value = .fromInterned(nav.resolved.?.value); | |
| 1147 | 1148 | const is_func = ip.isFunctionType(nav_val.typeOf(zcu).toIntern()); |
| 1148 | if (ip.getNav(nav_index).getLinkSection().unwrap()) |@"linksection"| { | |
| 1149 | if (ip.getNav(nav_index).resolved.?.@"linksection".unwrap()) |@"linksection"| { | |
| 1149 | 1150 | const section_name = @"linksection".toSlice(ip); |
| 1150 | 1151 | if (elf_file.sectionByName(section_name)) |osec| { |
| 1151 | 1152 | if (is_func) { |
| ... | ... | @@ -1258,13 +1259,8 @@ fn getNavShdrIndex( |
| 1258 | 1259 | self.text_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".text"), osec); |
| 1259 | 1260 | return osec; |
| 1260 | 1261 | } |
| 1261 | const is_const, const is_threadlocal, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) { | |
| 1262 | .variable => |variable| .{ false, variable.is_threadlocal, variable.init }, | |
| 1263 | .@"extern" => |@"extern"| .{ @"extern".is_const, @"extern".is_threadlocal, .none }, | |
| 1264 | else => .{ true, false, nav_val.toIntern() }, | |
| 1265 | }; | |
| 1266 | 1262 | const has_relocs = self.symbol(sym_index).atom(elf_file).?.relocs(elf_file).len > 0; |
| 1267 | if (is_threadlocal and elf_file.base.comp.config.any_non_single_threaded) { | |
| 1263 | if (nav.resolved.?.@"threadlocal" and elf_file.base.comp.config.any_non_single_threaded) { | |
| 1268 | 1264 | const is_bss = !has_relocs and for (code) |byte| { |
| 1269 | 1265 | if (byte != 0) break false; |
| 1270 | 1266 | } else true; |
| ... | ... | @@ -1291,7 +1287,7 @@ fn getNavShdrIndex( |
| 1291 | 1287 | self.tdata_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".tdata"), osec); |
| 1292 | 1288 | return osec; |
| 1293 | 1289 | } |
| 1294 | if (is_const) { | |
| 1290 | if (nav.resolved.?.@"const") { | |
| 1295 | 1291 | if (self.data_relro_index) |symbol_index| |
| 1296 | 1292 | return self.symbol(symbol_index).outputShndx(elf_file).?; |
| 1297 | 1293 | const osec = try elf_file.addSection(.{ |
| ... | ... | @@ -1303,7 +1299,7 @@ fn getNavShdrIndex( |
| 1303 | 1299 | self.data_relro_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".data.rel.ro"), osec); |
| 1304 | 1300 | return osec; |
| 1305 | 1301 | } |
| 1306 | if (nav_init != .none and Value.fromInterned(nav_init).isUndef(zcu)) | |
| 1302 | if (nav_val.isUndef(zcu)) | |
| 1307 | 1303 | return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) { |
| 1308 | 1304 | .Debug, .ReleaseSafe => { |
| 1309 | 1305 | if (self.data_index) |symbol_index| |
| ... | ... | @@ -1378,7 +1374,7 @@ fn updateNavCode( |
| 1378 | 1374 | |
| 1379 | 1375 | const mod = zcu.navFileScope(nav_index).mod.?; |
| 1380 | 1376 | const target = &mod.resolved_target.result; |
| 1381 | const required_alignment = switch (nav.status.fully_resolved.alignment) { | |
| 1377 | const required_alignment = switch (nav.resolved.?.@"align") { | |
| 1382 | 1378 | .none => switch (mod.optimize_mode) { |
| 1383 | 1379 | .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target), |
| 1384 | 1380 | .ReleaseSmall => target_util.minFunctionAlignment(target), |
| ... | ... | @@ -1647,16 +1643,17 @@ pub fn updateNav( |
| 1647 | 1643 | |
| 1648 | 1644 | log.debug("updateNav {f}({d})", .{ nav.fqn.fmt(ip), nav_index }); |
| 1649 | 1645 | |
| 1650 | const nav_init = switch (ip.indexToKey(nav.status.fully_resolved.val)) { | |
| 1651 | .func => .none, | |
| 1652 | .variable => |variable| variable.init, | |
| 1646 | switch (ip.indexToKey(nav.resolved.?.value)) { | |
| 1647 | else => {}, | |
| 1653 | 1648 | .@"extern" => |@"extern"| { |
| 1654 | 1649 | const sym_index = try self.getGlobalSymbol( |
| 1655 | 1650 | elf_file, |
| 1656 | 1651 | nav.name.toSlice(ip), |
| 1657 | 1652 | @"extern".lib_name.toSlice(ip), |
| 1658 | 1653 | ); |
| 1659 | if (@"extern".is_threadlocal and elf_file.base.comp.config.any_non_single_threaded) self.symbol(sym_index).flags.is_tls = true; | |
| 1654 | if (nav.resolved.?.@"threadlocal" and elf_file.base.comp.config.any_non_single_threaded) { | |
| 1655 | self.symbol(sym_index).flags.is_tls = true; | |
| 1656 | } | |
| 1660 | 1657 | if (self.dwarf) |*dwarf| { |
| 1661 | 1658 | var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index); |
| 1662 | 1659 | defer debug_wip_nav.deinit(); |
| ... | ... | @@ -1668,10 +1665,9 @@ pub fn updateNav( |
| 1668 | 1665 | } |
| 1669 | 1666 | return; |
| 1670 | 1667 | }, |
| 1671 | else => nav.status.fully_resolved.val, | |
| 1672 | }; | |
| 1668 | } | |
| 1673 | 1669 | |
| 1674 | if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) { | |
| 1670 | if (Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) { | |
| 1675 | 1671 | const sym_index = try self.getOrCreateMetadataForNav(zcu, nav_index); |
| 1676 | 1672 | self.symbol(sym_index).atom(elf_file).?.freeRelocs(self); |
| 1677 | 1673 | |
| ... | ... | @@ -1685,7 +1681,7 @@ pub fn updateNav( |
| 1685 | 1681 | &elf_file.base, |
| 1686 | 1682 | pt, |
| 1687 | 1683 | zcu.navSrcLoc(nav_index), |
| 1688 | Value.fromInterned(nav_init), | |
| 1684 | .fromInterned(nav.resolved.?.value), | |
| 1689 | 1685 | &aw.writer, |
| 1690 | 1686 | .{ .atom_index = sym_index }, |
| 1691 | 1687 | ) catch |err| switch (err) { |
src/link/Elf2.zig+19-41| ... | ... | @@ -1876,32 +1876,15 @@ pub fn globalSymbol(elf: *Elf, opts: struct { |
| 1876 | 1876 | |
| 1877 | 1877 | fn navType( |
| 1878 | 1878 | ip: *const InternPool, |
| 1879 | nav_status: @FieldType(InternPool.Nav, "status"), | |
| 1879 | nav_resolved: @typeInfo(@FieldType(InternPool.Nav, "resolved")).optional.child, | |
| 1880 | 1880 | any_non_single_threaded: bool, |
| 1881 | 1881 | ) std.elf.STT { |
| 1882 | return switch (nav_status) { | |
| 1883 | .unresolved => unreachable, | |
| 1884 | .type_resolved => |tr| if (any_non_single_threaded and tr.is_threadlocal) | |
| 1885 | .TLS | |
| 1886 | else if (ip.isFunctionType(tr.type)) | |
| 1887 | .FUNC | |
| 1888 | else | |
| 1889 | .OBJECT, | |
| 1890 | .fully_resolved => |fr| switch (ip.indexToKey(fr.val)) { | |
| 1891 | else => .OBJECT, | |
| 1892 | .variable => |variable| if (any_non_single_threaded and variable.is_threadlocal) | |
| 1893 | .TLS | |
| 1894 | else | |
| 1895 | .OBJECT, | |
| 1896 | .@"extern" => |@"extern"| if (any_non_single_threaded and @"extern".is_threadlocal) | |
| 1897 | .TLS | |
| 1898 | else if (ip.isFunctionType(@"extern".ty)) | |
| 1899 | .FUNC | |
| 1900 | else | |
| 1901 | .OBJECT, | |
| 1902 | .func => .FUNC, | |
| 1903 | }, | |
| 1904 | }; | |
| 1882 | return if (any_non_single_threaded and nav_resolved.@"threadlocal") | |
| 1883 | .TLS | |
| 1884 | else if (ip.isFunctionType(nav_resolved.type)) | |
| 1885 | .FUNC | |
| 1886 | else | |
| 1887 | .OBJECT; | |
| 1905 | 1888 | } |
| 1906 | 1889 | fn namedSection(elf: *const Elf, name: []const u8) ?Symbol.Index { |
| 1907 | 1890 | if (std.mem.eql(u8, name, ".rodata") or |
| ... | ... | @@ -1917,13 +1900,13 @@ fn namedSection(elf: *const Elf, name: []const u8) ?Symbol.Index { |
| 1917 | 1900 | fn navSection( |
| 1918 | 1901 | elf: *Elf, |
| 1919 | 1902 | ip: *const InternPool, |
| 1920 | nav_fr: @FieldType(@FieldType(InternPool.Nav, "status"), "fully_resolved"), | |
| 1903 | nav_resolved: @typeInfo(@FieldType(InternPool.Nav, "resolved")).optional.child, | |
| 1921 | 1904 | ) Symbol.Index { |
| 1922 | if (nav_fr.@"linksection".toSlice(ip)) |@"linksection"| | |
| 1905 | if (nav_resolved.@"linksection".toSlice(ip)) |@"linksection"| | |
| 1923 | 1906 | if (elf.namedSection(@"linksection")) |si| return si; |
| 1924 | 1907 | return switch (navType( |
| 1925 | 1908 | ip, |
| 1926 | .{ .fully_resolved = nav_fr }, | |
| 1909 | nav_resolved, | |
| 1927 | 1910 | elf.base.comp.config.any_non_single_threaded, |
| 1928 | 1911 | )) { |
| 1929 | 1912 | else => unreachable, |
| ... | ... | @@ -1940,7 +1923,7 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.NavM |
| 1940 | 1923 | const nav_gop = try elf.navs.getOrPut(gpa, nav_index); |
| 1941 | 1924 | if (!nav_gop.found_existing) nav_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{ |
| 1942 | 1925 | .name = nav.fqn.toSlice(ip), |
| 1943 | .type = navType(ip, nav.status, elf.base.comp.config.any_non_single_threaded), | |
| 1926 | .type = navType(ip, nav.resolved.?, elf.base.comp.config.any_non_single_threaded), | |
| 1944 | 1927 | }); |
| 1945 | 1928 | return @enumFromInt(nav_gop.index); |
| 1946 | 1929 | } |
| ... | ... | @@ -1950,7 +1933,7 @@ pub fn navSymbol(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol. |
| 1950 | 1933 | if (nav.getExtern(ip)) |@"extern"| return elf.globalSymbol(.{ |
| 1951 | 1934 | .name = @"extern".name.toSlice(ip), |
| 1952 | 1935 | .lib_name = @"extern".lib_name.toSlice(ip), |
| 1953 | .type = navType(ip, nav.status, elf.base.comp.config.any_non_single_threaded), | |
| 1936 | .type = navType(ip, nav.resolved.?, elf.base.comp.config.any_non_single_threaded), | |
| 1954 | 1937 | .bind = switch (@"extern".linkage) { |
| 1955 | 1938 | .internal => .LOCAL, |
| 1956 | 1939 | .strong => .GLOBAL, |
| ... | ... | @@ -2889,13 +2872,8 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) |
| 2889 | 2872 | const ip = &zcu.intern_pool; |
| 2890 | 2873 | |
| 2891 | 2874 | const nav = ip.getNav(nav_index); |
| 2892 | const nav_val = nav.status.fully_resolved.val; | |
| 2893 | const nav_init = switch (ip.indexToKey(nav_val)) { | |
| 2894 | else => nav_val, | |
| 2895 | .variable => |variable| variable.init, | |
| 2896 | .@"extern", .func => .none, | |
| 2897 | }; | |
| 2898 | if (nav_init == .none or !Type.fromInterned(ip.typeOf(nav_init)).hasRuntimeBits(zcu)) return; | |
| 2875 | if (ip.indexToKey(nav.resolved.?.value) == .@"extern") return; | |
| 2876 | if (!Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) return; | |
| 2899 | 2877 | |
| 2900 | 2878 | const nmi = try elf.navMapIndex(zcu, nav_index); |
| 2901 | 2879 | const si = nmi.symbol(elf); |
| ... | ... | @@ -2904,7 +2882,7 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) |
| 2904 | 2882 | switch (sym.ni) { |
| 2905 | 2883 | .none => { |
| 2906 | 2884 | try elf.nodes.ensureUnusedCapacity(gpa, 1); |
| 2907 | const sec_si = elf.navSection(ip, nav.status.fully_resolved); | |
| 2885 | const sec_si = elf.navSection(ip, nav.resolved.?); | |
| 2908 | 2886 | const ni = try elf.mf.addLastChildNode(gpa, sec_si.node(elf), .{ |
| 2909 | 2887 | .alignment = zcu.navAlignment(nav_index).toStdMem(), |
| 2910 | 2888 | .moved = true, |
| ... | ... | @@ -2930,7 +2908,7 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) |
| 2930 | 2908 | &elf.base, |
| 2931 | 2909 | pt, |
| 2932 | 2910 | zcu.navSrcLoc(nav_index), |
| 2933 | .fromInterned(nav_init), | |
| 2911 | .fromInterned(nav.resolved.?.value), | |
| 2934 | 2912 | &nw.interface, |
| 2935 | 2913 | .{ .atom_index = @intFromEnum(si) }, |
| 2936 | 2914 | ) catch |err| switch (err) { |
| ... | ... | @@ -3021,11 +2999,11 @@ fn updateFuncInner( |
| 3021 | 2999 | switch (sym.ni) { |
| 3022 | 3000 | .none => { |
| 3023 | 3001 | try elf.nodes.ensureUnusedCapacity(gpa, 1); |
| 3024 | const sec_si = elf.navSection(ip, nav.status.fully_resolved); | |
| 3002 | const sec_si = elf.navSection(ip, nav.resolved.?); | |
| 3025 | 3003 | const mod = zcu.navFileScope(func.owner_nav).mod.?; |
| 3026 | 3004 | const target = &mod.resolved_target.result; |
| 3027 | 3005 | const ni = try elf.mf.addLastChildNode(gpa, sec_si.node(elf), .{ |
| 3028 | .alignment = switch (nav.status.fully_resolved.alignment) { | |
| 3006 | .alignment = switch (nav.resolved.?.@"align") { | |
| 3029 | 3007 | .none => switch (mod.optimize_mode) { |
| 3030 | 3008 | .Debug, |
| 3031 | 3009 | .ReleaseSafe, |
| ... | ... | @@ -3677,7 +3655,7 @@ fn updateExportsInner( |
| 3677 | 3655 | const exported_si: Symbol.Index, const @"type": std.elf.STT = switch (exported) { |
| 3678 | 3656 | .nav => |nav| .{ |
| 3679 | 3657 | try elf.navSymbol(zcu, nav), |
| 3680 | navType(ip, ip.getNav(nav).status, elf.base.comp.config.any_non_single_threaded), | |
| 3658 | navType(ip, ip.getNav(nav).resolved.?, elf.base.comp.config.any_non_single_threaded), | |
| 3681 | 3659 | }, |
| 3682 | 3660 | .uav => |uav| .{ @enumFromInt(switch (try elf.lowerUav( |
| 3683 | 3661 | pt, |
src/link/MachO/ZigObject.zig+13-19| ... | ... | @@ -877,15 +877,14 @@ pub fn updateNav( |
| 877 | 877 | const ip = &zcu.intern_pool; |
| 878 | 878 | const nav = ip.getNav(nav_index); |
| 879 | 879 | |
| 880 | const nav_init = switch (ip.indexToKey(nav.status.fully_resolved.val)) { | |
| 881 | .func => .none, | |
| 882 | .variable => |variable| variable.init, | |
| 880 | switch (ip.indexToKey(nav.resolved.?.value)) { | |
| 881 | else => {}, | |
| 883 | 882 | .@"extern" => |@"extern"| { |
| 884 | 883 | // Extern variable gets a __got entry only |
| 885 | 884 | const name = @"extern".name.toSlice(ip); |
| 886 | 885 | const lib_name = @"extern".lib_name.toSlice(ip); |
| 887 | 886 | const sym_index = try self.getGlobalSymbol(macho_file, name, lib_name); |
| 888 | if (@"extern".is_threadlocal and macho_file.base.comp.config.any_non_single_threaded) self.symbols.items[sym_index].flags.tlv = true; | |
| 887 | if (nav.resolved.?.@"threadlocal" and macho_file.base.comp.config.any_non_single_threaded) self.symbols.items[sym_index].flags.tlv = true; | |
| 889 | 888 | if (self.dwarf) |*dwarf| { |
| 890 | 889 | var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index); |
| 891 | 890 | defer debug_wip_nav.deinit(); |
| ... | ... | @@ -897,10 +896,9 @@ pub fn updateNav( |
| 897 | 896 | } |
| 898 | 897 | return; |
| 899 | 898 | }, |
| 900 | else => nav.status.fully_resolved.val, | |
| 901 | }; | |
| 899 | } | |
| 902 | 900 | |
| 903 | if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) { | |
| 901 | if (Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) { | |
| 904 | 902 | const sym_index = try self.getOrCreateMetadataForNav(macho_file, nav_index); |
| 905 | 903 | self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file); |
| 906 | 904 | |
| ... | ... | @@ -914,7 +912,7 @@ pub fn updateNav( |
| 914 | 912 | &macho_file.base, |
| 915 | 913 | pt, |
| 916 | 914 | zcu.navSrcLoc(nav_index), |
| 917 | Value.fromInterned(nav_init), | |
| 915 | .fromInterned(nav.resolved.?.value), | |
| 918 | 916 | &aw.writer, |
| 919 | 917 | .{ .atom_index = sym_index }, |
| 920 | 918 | ) catch |err| switch (err) { |
| ... | ... | @@ -959,7 +957,7 @@ fn updateNavCode( |
| 959 | 957 | |
| 960 | 958 | const mod = zcu.navFileScope(nav_index).mod.?; |
| 961 | 959 | const target = &mod.resolved_target.result; |
| 962 | const required_alignment = switch (nav.status.fully_resolved.alignment) { | |
| 960 | const required_alignment = switch (nav.resolved.?.@"align") { | |
| 963 | 961 | .none => switch (mod.optimize_mode) { |
| 964 | 962 | .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target), |
| 965 | 963 | .ReleaseSmall => target_util.minFunctionAlignment(target), |
| ... | ... | @@ -1167,14 +1165,10 @@ fn getNavOutputSection( |
| 1167 | 1165 | ) error{OutOfMemory}!u8 { |
| 1168 | 1166 | _ = self; |
| 1169 | 1167 | const ip = &zcu.intern_pool; |
| 1170 | const nav_val = zcu.navValue(nav_index); | |
| 1168 | const nav = ip.getNav(nav_index); | |
| 1169 | const nav_val: Value = .fromInterned(nav.resolved.?.value); | |
| 1171 | 1170 | if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) return macho_file.zig_text_sect_index.?; |
| 1172 | const is_const, const is_threadlocal, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) { | |
| 1173 | .variable => |variable| .{ false, variable.is_threadlocal, variable.init }, | |
| 1174 | .@"extern" => |@"extern"| .{ @"extern".is_const, @"extern".is_threadlocal, .none }, | |
| 1175 | else => .{ true, false, nav_val.toIntern() }, | |
| 1176 | }; | |
| 1177 | if (is_threadlocal and macho_file.base.comp.config.any_non_single_threaded) { | |
| 1171 | if (nav.resolved.?.@"threadlocal" and macho_file.base.comp.config.any_non_single_threaded) { | |
| 1178 | 1172 | for (code) |byte| { |
| 1179 | 1173 | if (byte != 0) break; |
| 1180 | 1174 | } else return macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection( |
| ... | ... | @@ -1188,8 +1182,8 @@ fn getNavOutputSection( |
| 1188 | 1182 | .{ .flags = macho.S_THREAD_LOCAL_REGULAR }, |
| 1189 | 1183 | ); |
| 1190 | 1184 | } |
| 1191 | if (is_const) return macho_file.zig_const_sect_index.?; | |
| 1192 | if (nav_init != .none and Value.fromInterned(nav_init).isUndef(zcu)) | |
| 1185 | if (nav.resolved.?.@"const") return macho_file.zig_const_sect_index.?; | |
| 1186 | if (nav_val.isUndef(zcu)) | |
| 1193 | 1187 | return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) { |
| 1194 | 1188 | .Debug, .ReleaseSafe => macho_file.zig_data_sect_index.?, |
| 1195 | 1189 | .ReleaseFast, .ReleaseSmall => macho_file.zig_bss_sect_index.?, |
| ... | ... | @@ -1550,7 +1544,7 @@ fn isThreadlocal(macho_file: *MachO, nav_index: InternPool.Nav.Index) bool { |
| 1550 | 1544 | if (!macho_file.base.comp.config.any_non_single_threaded) |
| 1551 | 1545 | return false; |
| 1552 | 1546 | const ip = &macho_file.base.comp.zcu.?.intern_pool; |
| 1553 | return ip.getNav(nav_index).isThreadlocal(ip); | |
| 1547 | return ip.getNav(nav_index).resolved.?.@"threadlocal"; | |
| 1554 | 1548 | } |
| 1555 | 1549 | |
| 1556 | 1550 | fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index { |
src/link/SpirV.zig+1-1| ... | ... | @@ -189,7 +189,7 @@ pub fn updateExports( |
| 189 | 189 | @panic("TODO: implement Linker linker code for exporting a constant value"); |
| 190 | 190 | }, |
| 191 | 191 | }; |
| 192 | const nav_ty = ip.getNav(nav_index).typeOf(ip); | |
| 192 | const nav_ty = ip.getNav(nav_index).resolved.?.type; | |
| 193 | 193 | const target = zcu.getTarget(); |
| 194 | 194 | if (ip.isFunctionType(nav_ty)) { |
| 195 | 195 | const spv_decl_index = try linker.module.resolveNav(ip, nav_index); |
src/link/Wasm.zig+28-29| ... | ... | @@ -420,7 +420,7 @@ pub const OutputFunctionIndex = enum(u32) { |
| 420 | 420 | const zcu = wasm.base.comp.zcu.?; |
| 421 | 421 | const ip = &zcu.intern_pool; |
| 422 | 422 | const nav = ip.getNav(nav_index); |
| 423 | return fromIpIndex(wasm, nav.status.fully_resolved.val); | |
| 423 | return fromIpIndex(wasm, nav.resolved.?.value); | |
| 424 | 424 | } |
| 425 | 425 | |
| 426 | 426 | pub fn fromTagNameType(wasm: *const Wasm, tag_type: InternPool.Index) OutputFunctionIndex { |
| ... | ... | @@ -1022,7 +1022,7 @@ pub const FunctionImport = extern struct { |
| 1022 | 1022 | pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) Resolution { |
| 1023 | 1023 | const zcu = wasm.base.comp.zcu.?; |
| 1024 | 1024 | const ip = &zcu.intern_pool; |
| 1025 | return fromIpIndex(wasm, ip.getNav(nav_index).status.fully_resolved.val); | |
| 1025 | return fromIpIndex(wasm, ip.getNav(nav_index).resolved.?.value); | |
| 1026 | 1026 | } |
| 1027 | 1027 | |
| 1028 | 1028 | pub fn fromZcuFunc(wasm: *const Wasm, i: ZcuFunc.Index) Resolution { |
| ... | ... | @@ -1885,7 +1885,7 @@ pub const DataSegmentId = enum(u32) { |
| 1885 | 1885 | const zcu = wasm.base.comp.zcu.?; |
| 1886 | 1886 | const ip = &zcu.intern_pool; |
| 1887 | 1887 | const nav = ip.getNav(i.key(wasm).*); |
| 1888 | if (nav.isThreadlocal(ip)) return .tls; | |
| 1888 | if (nav.resolved.?.@"threadlocal") return .tls; | |
| 1889 | 1889 | const code = i.value(wasm).code; |
| 1890 | 1890 | return if (code.off == .none) .zero else .data; |
| 1891 | 1891 | }, |
| ... | ... | @@ -1908,7 +1908,7 @@ pub const DataSegmentId = enum(u32) { |
| 1908 | 1908 | const zcu = wasm.base.comp.zcu.?; |
| 1909 | 1909 | const ip = &zcu.intern_pool; |
| 1910 | 1910 | const nav = ip.getNav(i.key(wasm).*); |
| 1911 | return nav.isThreadlocal(ip); | |
| 1911 | return nav.resolved.?.@"threadlocal"; | |
| 1912 | 1912 | }, |
| 1913 | 1913 | }; |
| 1914 | 1914 | } |
| ... | ... | @@ -1934,7 +1934,7 @@ pub const DataSegmentId = enum(u32) { |
| 1934 | 1934 | const zcu = wasm.base.comp.zcu.?; |
| 1935 | 1935 | const ip = &zcu.intern_pool; |
| 1936 | 1936 | const nav = ip.getNav(i.key(wasm).*); |
| 1937 | return nav.getLinkSection().toSlice(ip) orelse switch (category(id, wasm)) { | |
| 1937 | return nav.resolved.?.@"linksection".toSlice(ip) orelse switch (category(id, wasm)) { | |
| 1938 | 1938 | .tls => ".tdata", |
| 1939 | 1939 | .data => ".data", |
| 1940 | 1940 | .zero => ".bss", |
| ... | ... | @@ -1962,9 +1962,9 @@ pub const DataSegmentId = enum(u32) { |
| 1962 | 1962 | const zcu = wasm.base.comp.zcu.?; |
| 1963 | 1963 | const ip = &zcu.intern_pool; |
| 1964 | 1964 | const nav = ip.getNav(i.key(wasm).*); |
| 1965 | const explicit = nav.getAlignment(); | |
| 1965 | const explicit = nav.resolved.?.@"align"; | |
| 1966 | 1966 | if (explicit != .none) return explicit; |
| 1967 | const ty: Zcu.Type = .fromInterned(nav.typeOf(ip)); | |
| 1967 | const ty: Zcu.Type = .fromInterned(nav.resolved.?.type); | |
| 1968 | 1968 | const result = ty.abiAlignment(zcu); |
| 1969 | 1969 | assert(result != .none); |
| 1970 | 1970 | return result; |
| ... | ... | @@ -2269,7 +2269,7 @@ pub const ZcuImportIndex = enum(u32) { |
| 2269 | 2269 | const zcu = wasm.base.comp.zcu.?; |
| 2270 | 2270 | const ip = &zcu.intern_pool; |
| 2271 | 2271 | const nav_index = index.ptr(wasm).*; |
| 2272 | const ext = ip.getNav(nav_index).getResolvedExtern(ip).?; | |
| 2272 | const ext = ip.indexToKey(ip.getNav(nav_index).resolved.?.value).@"extern"; | |
| 2273 | 2273 | const name_slice = ext.name.toSlice(ip); |
| 2274 | 2274 | return wasm.getExistingString(name_slice).?; |
| 2275 | 2275 | } |
| ... | ... | @@ -2278,7 +2278,7 @@ pub const ZcuImportIndex = enum(u32) { |
| 2278 | 2278 | const zcu = wasm.base.comp.zcu.?; |
| 2279 | 2279 | const ip = &zcu.intern_pool; |
| 2280 | 2280 | const nav_index = index.ptr(wasm).*; |
| 2281 | const ext = ip.getNav(nav_index).getResolvedExtern(ip).?; | |
| 2281 | const ext = ip.indexToKey(ip.getNav(nav_index).resolved.?.value).@"extern"; | |
| 2282 | 2282 | const lib_name = ext.lib_name.toSlice(ip) orelse return .none; |
| 2283 | 2283 | return wasm.getExistingString(lib_name).?.toOptional(); |
| 2284 | 2284 | } |
| ... | ... | @@ -2289,7 +2289,7 @@ pub const ZcuImportIndex = enum(u32) { |
| 2289 | 2289 | const zcu = comp.zcu.?; |
| 2290 | 2290 | const ip = &zcu.intern_pool; |
| 2291 | 2291 | const nav_index = index.ptr(wasm).*; |
| 2292 | const ext = ip.getNav(nav_index).getResolvedExtern(ip).?; | |
| 2292 | const ext = ip.indexToKey(ip.getNav(nav_index).resolved.?.value).@"extern"; | |
| 2293 | 2293 | const fn_info = zcu.typeToFunc(.fromInterned(ext.ty)).?; |
| 2294 | 2294 | return getExistingFunctionType(wasm, fn_info.cc, fn_info.param_types.get(ip), .fromInterned(fn_info.return_type), target).?; |
| 2295 | 2295 | } |
| ... | ... | @@ -2381,7 +2381,7 @@ pub const FunctionImportId = enum(u32) { |
| 2381 | 2381 | .zcu_import => |i| { |
| 2382 | 2382 | const zcu = wasm.base.comp.zcu.?; |
| 2383 | 2383 | const ip = &zcu.intern_pool; |
| 2384 | const ext = ip.getNav(i.ptr(wasm).*).getResolvedExtern(ip).?; | |
| 2384 | const ext = ip.indexToKey(ip.getNav(i.ptr(wasm).*).resolved.?.value).@"extern"; | |
| 2385 | 2385 | return ext.linkage != .weak and ext.lib_name != .none; |
| 2386 | 2386 | }, |
| 2387 | 2387 | }; |
| ... | ... | @@ -3288,7 +3288,8 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index |
| 3288 | 3288 | const is_obj = comp.config.output_mode == .Obj; |
| 3289 | 3289 | const target = &comp.root_mod.resolved_target.result; |
| 3290 | 3290 | |
| 3291 | const nav_init, const chased_nav_index = switch (ip.indexToKey(nav.status.fully_resolved.val)) { | |
| 3291 | switch (ip.indexToKey(nav.resolved.?.value)) { | |
| 3292 | else => {}, | |
| 3292 | 3293 | .func => return, // global const which is a function alias |
| 3293 | 3294 | .@"extern" => |ext| { |
| 3294 | 3295 | if (is_obj) { |
| ... | ... | @@ -3302,7 +3303,7 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index |
| 3302 | 3303 | try wasm.function_imports.ensureUnusedCapacity(gpa, 1); |
| 3303 | 3304 | try wasm.data_imports.ensureUnusedCapacity(gpa, 1); |
| 3304 | 3305 | const zcu_import = wasm.addZcuImportReserved(ext.owner_nav); |
| 3305 | if (ip.isFunctionType(nav.typeOf(ip))) { | |
| 3306 | if (ip.isFunctionType(nav.resolved.?.type)) { | |
| 3306 | 3307 | wasm.function_imports.putAssumeCapacity(name, .fromZcuImport(zcu_import, wasm)); |
| 3307 | 3308 | // Ensure there is a corresponding function type table entry. |
| 3308 | 3309 | const fn_info = zcu.typeToFunc(.fromInterned(ext.ty)).?; |
| ... | ... | @@ -3312,31 +3313,29 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index |
| 3312 | 3313 | } |
| 3313 | 3314 | return; |
| 3314 | 3315 | }, |
| 3315 | .variable => |variable| .{ variable.init, variable.owner_nav }, | |
| 3316 | else => .{ nav.status.fully_resolved.val, nav_index }, | |
| 3317 | }; | |
| 3318 | //log.debug("updateNav {f} {d}", .{ nav.fqn.fmt(ip), chased_nav_index }); | |
| 3319 | assert(!wasm.imports.contains(chased_nav_index)); | |
| 3316 | } | |
| 3317 | //log.debug("updateNav {f} {d}", .{ nav.fqn.fmt(ip), nav_index }); | |
| 3318 | assert(!wasm.imports.contains(nav_index)); | |
| 3320 | 3319 | |
| 3321 | if (nav_init != .none and !Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) { | |
| 3320 | if (!Zcu.Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) { | |
| 3322 | 3321 | if (is_obj) { |
| 3323 | assert(!wasm.navs_obj.contains(chased_nav_index)); | |
| 3322 | assert(!wasm.navs_obj.contains(nav_index)); | |
| 3324 | 3323 | } else { |
| 3325 | assert(!wasm.navs_exe.contains(chased_nav_index)); | |
| 3324 | assert(!wasm.navs_exe.contains(nav_index)); | |
| 3326 | 3325 | } |
| 3327 | 3326 | return; |
| 3328 | 3327 | } |
| 3329 | 3328 | |
| 3330 | 3329 | if (is_obj) { |
| 3331 | 3330 | const zcu_data_starts: ZcuDataStarts = .initObj(wasm); |
| 3332 | const navs_i = try refNavObj(wasm, chased_nav_index); | |
| 3333 | const zcu_data = try lowerZcuData(wasm, pt, nav_init); | |
| 3331 | const navs_i = try refNavObj(wasm, nav_index); | |
| 3332 | const zcu_data = try lowerZcuData(wasm, pt, nav.resolved.?.value); | |
| 3334 | 3333 | navs_i.value(wasm).* = zcu_data; |
| 3335 | 3334 | try zcu_data_starts.finishObj(wasm, pt); |
| 3336 | 3335 | } else { |
| 3337 | 3336 | const zcu_data_starts: ZcuDataStarts = .initExe(wasm); |
| 3338 | const navs_i = try refNavExe(wasm, chased_nav_index); | |
| 3339 | const zcu_data = try lowerZcuData(wasm, pt, nav_init); | |
| 3337 | const navs_i = try refNavExe(wasm, nav_index); | |
| 3338 | const zcu_data = try lowerZcuData(wasm, pt, nav.resolved.?.value); | |
| 3340 | 3339 | navs_i.value(wasm).code = zcu_data.code; |
| 3341 | 3340 | try zcu_data_starts.finishExe(wasm, pt); |
| 3342 | 3341 | } |
| ... | ... | @@ -4173,9 +4172,8 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 { |
| 4173 | 4172 | } |
| 4174 | 4173 | const zcu = comp.zcu.?; |
| 4175 | 4174 | const ip = &zcu.intern_pool; |
| 4176 | const nav = ip.getNav(nav_index); | |
| 4177 | if (nav.getResolvedExtern(ip)) |ext| { | |
| 4178 | if (wasm.getExistingString(ext.name.toSlice(ip))) |symbol_name| { | |
| 4175 | switch (ip.indexToKey(ip.getNav(nav_index).resolved.?.value)) { | |
| 4176 | .@"extern" => |ext| if (wasm.getExistingString(ext.name.toSlice(ip))) |symbol_name| { | |
| 4179 | 4177 | if (wasm.object_data_imports.getPtr(symbol_name)) |import| { |
| 4180 | 4178 | switch (import.resolution.unpack(wasm)) { |
| 4181 | 4179 | .unresolved => unreachable, |
| ... | ... | @@ -4195,7 +4193,8 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 { |
| 4195 | 4193 | .nav_obj => @panic("TODO"), |
| 4196 | 4194 | } |
| 4197 | 4195 | } |
| 4198 | } | |
| 4196 | }, | |
| 4197 | else => {}, | |
| 4199 | 4198 | } |
| 4200 | 4199 | // Otherwise it's a zero bit type; any address will do. |
| 4201 | 4200 | return 0; |
src/link/Wasm/Flush.zig+1-1| ... | ... | @@ -211,7 +211,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 211 | 211 | } |
| 212 | 212 | |
| 213 | 213 | for (wasm.nav_exports.keys(), wasm.nav_exports.values()) |*nav_export, export_index| { |
| 214 | if (ip.isFunctionType(ip.getNav(nav_export.nav_index).typeOf(ip))) { | |
| 214 | if (ip.isFunctionType(ip.getNav(nav_export.nav_index).resolved.?.type)) { | |
| 215 | 215 | log.debug("flush export '{s}' nav={d}", .{ nav_export.name.slice(wasm), nav_export.nav_index }); |
| 216 | 216 | const function_index = Wasm.FunctionIndex.fromIpNav(wasm, nav_export.nav_index).?; |
| 217 | 217 | const explicit = f.missing_exports.swapRemove(nav_export.name); |
src/print_value.zig-1| ... | ... | @@ -74,7 +74,6 @@ pub fn print( |
| 74 | 74 | .@"unreachable", |
| 75 | 75 | => try writer.writeAll(@tagName(simple_value)), |
| 76 | 76 | }, |
| 77 | .variable => try writer.writeAll("(variable)"), | |
| 78 | 77 | .@"extern" => |e| try writer.print("(extern '{f}')", .{e.name.fmt(ip)}), |
| 79 | 78 | .func => |func| try writer.print("(function '{f}')", .{ip.getNav(func.owner_nav).name.fmt(ip)}), |
| 80 | 79 | .int => |int| switch (int.storage) { |