authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-03-15 10:34:13+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-03-15 11:47:14+00:00
log5d215838a79a24c21842fbc76fd77aca4c28b162
tree4f0c95e0b2a6dea5a7b7dbcb53649d9839dadcd1
parent065c6e7946e712dc8563c975a4ca951927145da7
signaturelock-open Commit is signed but in an unrecognized format.

InternPool.Nav: fix race, refactor

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,22 +215,25 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const
215 try w.print(215 try w.print(
216 \\name: '{f}'216 \\name: '{f}'
217 \\fqn: '{f}'217 \\fqn: '{f}'
218 \\status: {s}
219 \\created on generation: {d}218 \\created on generation: {d}
220 \\219 \\
221 , .{220 , .{
222 nav.name.fmt(ip),221 nav.name.fmt(ip),
223 nav.fqn.fmt(ip),222 nav.fqn.fmt(ip),
224 @tagName(nav.status),
225 create_gen,223 create_gen,
226 });224 });
227 switch (nav.status) {225 if (nav.resolved) |r| {
228 .unresolved => {},226 try w.writeAll("status: resolved\n type: ");
229 .type_resolved, .fully_resolved => {227 try printType(.fromInterned(r.type), zcu, w);
230 try w.writeAll("type: ");228 try w.writeAll("\n value: ");
231 try printType(.fromInterned(nav.typeOf(ip)), zcu, w);229 if (r.value == .none) {
232 try w.writeByte('\n');230 try w.writeAll("(unresolved)");
233 },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 } else if (std.mem.eql(u8, cmd_str, "find_type")) {238 } else if (std.mem.eql(u8, cmd_str, "find_type")) {
236 if (arg_str.len == 0) return w.writeAll("bad usage");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,144 +548,61 @@ pub const Nav = struct {
548 /// The fully-qualified name of this `Nav`.548 /// The fully-qualified name of this `Nav`.
549 fqn: NullTerminatedString,549 fqn: NullTerminatedString,
550 /// This field is populated iff this `Nav` is resolved by semantic analysis.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 analysis: ?struct {552 analysis: ?struct {
553 namespace: NamespaceIndex,553 namespace: NamespaceIndex,
554 zir_index: TrackedInst.Index,554 zir_index: TrackedInst.Index,
555 /// Initially `false`. Set to `true` by `setWantNavAnalysis`.555 /// Initially `false`. Set to `true` by `setWantNavAnalysis`.
556 wanted: bool,556 wanted: bool,
557 },557 },
558 status: union(enum) {558 /// If this is `null`, then `analysis` is *not* `null`, and semantic analysis is required to
559 /// This `Nav` is pending semantic analysis.559 /// resolve the type and value of this `Nav`. Otherwise, the type is resolved---therefore,
560 unresolved,560 /// `Nav.resolved.?.type` is never `.none`. However, the *value* may not be resolved yet even
561 /// The type of this `Nav` is resolved; the value is queued for resolution.561 /// if this field is not `null`---see `Resolved.value` for details.
562 type_resolved: struct {562 resolved: ?Resolved,
563 type: InternPool.Index,563
564 is_const: bool,564 pub const Resolved = struct {
565 alignment: Alignment,565 /// This is never `.none`
566 @"linksection": OptionalNullTerminatedString,566 type: InternPool.Index,
567 @"addrspace": std.builtin.AddressSpace,567 @"align": Alignment,
568 is_threadlocal: bool,568 @"linksection": OptionalNullTerminatedString,
569 /// This field is whether this `Nav` is a literal `extern` definition.569 @"addrspace": std.builtin.AddressSpace,
570 /// It does *not* tell you whether this might alias an extern fn (see #21027).570 @"const": bool,
571 is_extern_decl: bool,571 @"threadlocal": bool,
572 },572 /// This field is whether this `Nav` is a literal `extern` definition.
573 /// The value of this `Nav` is resolved.573 /// It does *not* tell you whether this might alias an extern fn (see #21027).
574 fully_resolved: struct {574 is_extern_decl: bool,
575 val: InternPool.Index,575 /// If the type is resolved but not the value, this is `.none`. In that case, the value will
576 is_const: bool,576 /// be resolved by semantic analysis, so `Nav.analysis` is definitely not `null`.
577 alignment: Alignment,577 ///
578 @"linksection": OptionalNullTerminatedString,578 /// If this is an extern, the special key `Key.@"extern"` is used.
579 @"addrspace": std.builtin.AddressSpace,579 ///
580 },580 /// If this is a variable (`Resolved.@"const" == false`) and not an extern, then this value
581 },581 /// is the global variable's initializer; the value loaded from the variable at runtime may
582582 /// of course be different.
583 /// Asserts that `status != .unresolved`.583 value: InternPool.Index,
584 pub fn typeOf(nav: Nav, ip: *const InternPool) InternPool.Index {584 };
585 return switch (nav.status) {585
586 .unresolved => unreachable,586 /// If the value of this `Nav` is resolved and is an extern, returns the `Key.Extern`. If the
587 .type_resolved => |r| r.type,587 /// value is *not* an extern, *or* if the value is not yet resolved (only the type is), returns
588 .fully_resolved => |r| ip.typeOf(r.val),588 /// `null`.
589 };589 ///
590 }590 /// This logic works because the frontend ensures that if a `Nav` *might* be extern, its value
591591 /// is resolved more eagerly (see logic in `Sema.analyzeNavRefInner`). Therefore, if we see that
592 /// This function is intended to be used by code generation, since semantic592 /// the value is not yet resolved, we know the frontend determined that the `Nav` is definitely
593 /// analysis will ensure that any `Nav` which is potentially `extern` is593 /// *not* extern.
594 /// fully resolved.594 ///
595 /// Asserts that `status == .fully_resolved`.595 /// This function is only intended be used by the compiler backend (codegen/link). The guarantee
596 pub fn getResolvedExtern(nav: Nav, ip: *const InternPool) ?Key.Extern {596 /// mentioned above does not necessarily hold in the compiler frontend (if we haven't reached
597 assert(nav.status == .fully_resolved);597 /// `Sema.analyzeNavRefInner` yet).
598 return nav.getExtern(ip);598 ///
599 }599 /// Asserts that `nav.resolved != null`.
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`.
605 pub fn getExtern(nav: Nav, ip: *const InternPool) ?Key.Extern {600 pub fn getExtern(nav: Nav, ip: *const InternPool) ?Key.Extern {
606 return switch (nav.status) {601 const r = nav.resolved.?;
607 .unresolved => unreachable,602 if (r.value == .none) return null;
608 .type_resolved => null,603 return switch (ip.indexToKey(r.value)) {
609 .fully_resolved => |r| switch (ip.indexToKey(r.val)) {604 .@"extern" => |e| e,
610 .@"extern" => |e| e,605 else => null,
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 },
689 };606 };
690 }607 }
691608
...@@ -696,7 +613,7 @@ pub const Nav = struct {...@@ -696,7 +613,7 @@ pub const Nav = struct {
696 return a.zir_index;613 return a.zir_index;
697 }614 }
698 // A `Nav` which does not undergo analysis always has a resolved value.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 .func => |func| {617 .func => |func| {
701 // Since `analysis` was not populated, this must be an instantiation.618 // Since `analysis` was not populated, this must be an instantiation.
702 // Go up to the generic owner and consult *its* `analysis` field.619 // Go up to the generic owner and consult *its* `analysis` field.
...@@ -747,30 +664,26 @@ pub const Nav = struct {...@@ -747,30 +664,26 @@ pub const Nav = struct {
747 };664 };
748665
749 /// The compact in-memory representation of a `Nav`.666 /// The compact in-memory representation of a `Nav`.
750 /// 26 bytes.667 /// 30 bytes.
751 const Repr = struct {668 const Repr = struct {
752 name: NullTerminatedString,669 name: NullTerminatedString,
753 fqn: NullTerminatedString,670 fqn: NullTerminatedString,
754 // The following 2 fields are either both populated, or both `.none`.671 // The following 2 fields are either both populated, or both `.none`.
755 analysis_namespace: OptionalNamespaceIndex,672 analysis_namespace: OptionalNamespaceIndex,
756 analysis_zir_index: TrackedInst.Index.Optional,673 analysis_zir_index: TrackedInst.Index.Optional,
757 /// Populated only if `bits.status != .unresolved`.674 type: InternPool.Index,
758 type_or_val: InternPool.Index,675 value: InternPool.Index,
759 /// Populated only if `bits.status != .unresolved`.
760 @"linksection": OptionalNullTerminatedString,676 @"linksection": OptionalNullTerminatedString,
761 bits: Bits,677 bits: Bits,
762678
763 const Bits = packed struct(u16) {679 const Bits = packed struct(u16) {
764 status: enum(u2) { unresolved, type_resolved, fully_resolved, type_resolved_extern_decl },680 @"align": Alignment,
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`.
770 @"addrspace": std.builtin.AddressSpace,681 @"addrspace": std.builtin.AddressSpace,
771 /// Populated only if `bits.status == .type_resolved`.682 @"const": bool,
772 is_threadlocal: bool,683 @"threadlocal": bool,
684 is_extern_decl: bool,
773 want_analysis: bool,685 want_analysis: bool,
686 _: u1 = 0,
774 };687 };
775688
776 fn unpack(repr: Repr) Nav {689 fn unpack(repr: Repr) Nav {
...@@ -785,72 +698,46 @@ pub const Nav = struct {...@@ -785,72 +698,46 @@ pub const Nav = struct {
785 assert(repr.analysis_zir_index == .none);698 assert(repr.analysis_zir_index == .none);
786 break :a null;699 break :a null;
787 },700 },
788 .status = switch (repr.bits.status) {701 .resolved = if (repr.type == .none) null else .{
789 .unresolved => .unresolved,702 .type = repr.type,
790 .type_resolved, .type_resolved_extern_decl => .{ .type_resolved = .{703 .@"align" = repr.bits.@"align",
791 .type = repr.type_or_val,704 .@"linksection" = repr.@"linksection",
792 .is_const = repr.bits.is_const,705 .@"addrspace" = repr.bits.@"addrspace",
793 .alignment = repr.bits.alignment,706 .@"const" = repr.bits.@"const",
794 .@"linksection" = repr.@"linksection",707 .@"threadlocal" = repr.bits.@"threadlocal",
795 .@"addrspace" = repr.bits.@"addrspace",708 .is_extern_decl = repr.bits.is_extern_decl,
796 .is_threadlocal = repr.bits.is_threadlocal,709 .value = repr.value,
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 } },
806 },710 },
807 };711 };
808 }712 }
809 };713 };
810714
811 fn pack(nav: Nav) Repr {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.716 // Note that even if `nav.resolved == null`, we do not set any fields to `undefined`, even
813 // This is to avoid writing undefined bytes to disk when serializing buffers.717 // though they should not be used. This is to avoid writing undefined bytes to disk when
718 // serializing buffers.
814 return .{719 return .{
815 .name = nav.name,720 .name = nav.name,
816 .fqn = nav.fqn,721 .fqn = nav.fqn,
817 .analysis_namespace = if (nav.analysis) |a| a.namespace.toOptional() else .none,722 .analysis_namespace = if (nav.analysis) |a| a.namespace.toOptional() else .none,
818 .analysis_zir_index = if (nav.analysis) |a| a.zir_index.toOptional() else .none,723 .analysis_zir_index = if (nav.analysis) |a| a.zir_index.toOptional() else .none,
819 .type_or_val = switch (nav.status) {724 .type = if (nav.resolved) |r| r.type else .none,
820 .unresolved => .none,725 .value = if (nav.resolved) |r| r.value else .none,
821 .type_resolved => |r| r.type,726 .@"linksection" = if (nav.resolved) |r| r.@"linksection" else .none,
822 .fully_resolved => |r| r.val,727 .bits = if (nav.resolved) |r| .{
823 },728 .@"align" = r.@"align",
824 .@"linksection" = switch (nav.status) {729 .@"addrspace" = r.@"addrspace",
825 .unresolved => .none,730 .@"const" = r.@"const",
826 .type_resolved => |r| r.@"linksection",731 .@"threadlocal" = r.@"threadlocal",
827 .fully_resolved => |r| r.@"linksection",732 .is_extern_decl = r.is_extern_decl,
828 },733 .want_analysis = if (nav.analysis) |a| a.wanted else false,
829 .bits = switch (nav.status) {734 } else .{
830 .unresolved => .{735 .@"align" = .none,
831 .status = .unresolved,736 .@"addrspace" = .generic,
832 .is_const = false,737 .@"const" = false,
833 .alignment = .none,738 .@"threadlocal" = false,
834 .@"addrspace" = .generic,739 .is_extern_decl = false,
835 .is_threadlocal = false,740 .want_analysis = if (nav.analysis) |a| a.wanted else 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 },
854 },741 },
855 };742 };
856 }743 }
...@@ -2110,7 +1997,6 @@ pub const Key = union(enum) {...@@ -2110,7 +1997,6 @@ pub const Key = union(enum) {
2110 /// via `simple_value` and has a named `Index` tag for it.1997 /// via `simple_value` and has a named `Index` tag for it.
2111 undef: Index,1998 undef: Index,
2112 simple_value: SimpleValue,1999 simple_value: SimpleValue,
2113 variable: Variable,
2114 @"extern": Extern,2000 @"extern": Extern,
2115 func: Func,2001 func: Func,
2116 int: Key.Int,2002 int: Key.Int,
...@@ -2311,14 +2197,6 @@ pub const Key = union(enum) {...@@ -2311,14 +2197,6 @@ pub const Key = union(enum) {
2311 }2197 }
2312 };2198 };
23132199
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 pub const Extern = struct {2200 pub const Extern = struct {
2323 /// The name of the extern symbol.2201 /// The name of the extern symbol.
2324 name: NullTerminatedString,2202 name: NullTerminatedString,
...@@ -2543,7 +2421,7 @@ pub const Key = union(enum) {...@@ -2543,7 +2421,7 @@ pub const Key = union(enum) {
2543 pub const BaseAddr = union(enum) {2421 pub const BaseAddr = union(enum) {
2544 const Tag = @typeInfo(BaseAddr).@"union".tag_type.?;2422 const Tag = @typeInfo(BaseAddr).@"union".tag_type.?;
25452423
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 nav: Nav.Index,2425 nav: Nav.Index,
25482426
2549 /// Points to the value of a single comptime alloc stored in `Sema`.2427 /// Points to the value of a single comptime alloc stored in `Sema`.
...@@ -2735,8 +2613,6 @@ pub const Key = union(enum) {...@@ -2735,8 +2613,6 @@ pub const Key = union(enum) {
2735 .payload => |y| Hash.hash(seed + 1, asBytes(&x.ty) ++ asBytes(&y)),2613 .payload => |y| Hash.hash(seed + 1, asBytes(&x.ty) ++ asBytes(&y)),
2736 },2614 },
27372615
2738 .variable => |variable| Hash.hash(seed, asBytes(&variable.owner_nav)),
2739
2740 .opaque_type,2616 .opaque_type,
2741 .enum_type,2617 .enum_type,
2742 .union_type,2618 .union_type,
...@@ -3011,13 +2887,6 @@ pub const Key = union(enum) {...@@ -3011,13 +2887,6 @@ pub const Key = union(enum) {
3011 return a_info.ty == b_info.ty and a_info.backing_int_val == b_info.backing_int_val;2887 return a_info.ty == b_info.ty and a_info.backing_int_val == b_info.backing_int_val;
3012 },2888 },
30132889
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 .@"extern" => |a_info| {2890 .@"extern" => |a_info| {
3022 const b_info = b.@"extern";2891 const b_info = b.@"extern";
3023 return a_info.name == b_info.name and2892 return a_info.name == b_info.name and
...@@ -3277,7 +3146,6 @@ pub const Key = union(enum) {...@@ -3277,7 +3146,6 @@ pub const Key = union(enum) {
3277 .int,3146 .int,
3278 .float,3147 .float,
3279 .opt,3148 .opt,
3280 .variable,
3281 .@"extern",3149 .@"extern",
3282 .func,3150 .func,
3283 .err,3151 .err,
...@@ -4390,8 +4258,6 @@ pub const Index = enum(u32) {...@@ -4390,8 +4258,6 @@ pub const Index = enum(u32) {
4390 float_c_longdouble_f80: struct { data: *Float80 },4258 float_c_longdouble_f80: struct { data: *Float80 },
4391 float_c_longdouble_f128: struct { data: *Float128 },4259 float_c_longdouble_f128: struct { data: *Float128 },
4392 float_comptime_float: struct { data: *Float128 },4260 float_comptime_float: struct { data: *Float128 },
4393 variable: struct { data: *Tag.Variable },
4394 threadlocal_variable: struct { data: *Tag.Variable },
4395 @"extern": struct { data: *Tag.Extern },4261 @"extern": struct { data: *Tag.Extern },
4396 func_decl: struct {4262 func_decl: struct {
4397 const @"data.analysis.inferred_error_set" = opaque {};4263 const @"data.analysis.inferred_error_set" = opaque {};
...@@ -5115,12 +4981,6 @@ pub const Tag = enum(u8) {...@@ -5115,12 +4981,6 @@ pub const Tag = enum(u8) {
5115 /// A comptime_float value.4981 /// A comptime_float value.
5116 /// data is extra index to Float128.4982 /// data is extra index to Float128.
5117 float_comptime_float,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 /// An extern function or variable.4984 /// An extern function or variable.
5125 /// data is extra index to Extern.4985 /// data is extra index to Extern.
5126 /// Some parts of the key are stored in `owner_nav`.4986 /// Some parts of the key are stored in `owner_nav`.
...@@ -5457,8 +5317,6 @@ pub const Tag = enum(u8) {...@@ -5457,8 +5317,6 @@ pub const Tag = enum(u8) {
5457 .float_c_longdouble_f80 = .{ .summary = .@"@as(c_longdouble, {.payload%value})", .payload = f80 },5317 .float_c_longdouble_f80 = .{ .summary = .@"@as(c_longdouble, {.payload%value})", .payload = f80 },
5458 .float_c_longdouble_f128 = .{ .summary = .@"@as(c_longdouble, {.payload%value})", .payload = f128 },5318 .float_c_longdouble_f128 = .{ .summary = .@"@as(c_longdouble, {.payload%value})", .payload = f128 },
5459 .float_comptime_float = .{ .summary = .@"{.payload%value}", .payload = f128 },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 .@"extern" = .{ .summary = .@"{.payload.owner_nav.fqn%summary#\"}", .payload = Extern },5320 .@"extern" = .{ .summary = .@"{.payload.owner_nav.fqn%summary#\"}", .payload = Extern },
5463 .func_decl = .{5321 .func_decl = .{
5464 .summary = .@"{.payload.owner_nav.fqn%summary#\"}",5322 .summary = .@"{.payload.owner_nav.fqn%summary#\"}",
...@@ -5505,13 +5363,6 @@ pub const Tag = enum(u8) {...@@ -5505,13 +5363,6 @@ pub const Tag = enum(u8) {
5505 return @field(encodings, @tagName(tag)).payload;5363 return @field(encodings, @tagName(tag)).payload;
5506 }5364 }
55075365
5508 pub const Variable = struct {
5509 ty: Index,
5510 /// May be `none`.
5511 init: Index,
5512 owner_nav: Nav.Index,
5513 };
5514
5515 pub const Extern = struct {5366 pub const Extern = struct {
5516 // name, is_const, alignment, addrspace come from `owner_nav`.5367 // name, is_const, alignment, addrspace come from `owner_nav`.
5517 ty: Index,5368 ty: Index,
...@@ -5525,12 +5376,11 @@ pub const Tag = enum(u8) {...@@ -5525,12 +5376,11 @@ pub const Tag = enum(u8) {
5525 pub const Flags = packed struct(u32) {5376 pub const Flags = packed struct(u32) {
5526 linkage: std.builtin.GlobalLinkage,5377 linkage: std.builtin.GlobalLinkage,
5527 visibility: std.builtin.SymbolVisibility,5378 visibility: std.builtin.SymbolVisibility,
5528 is_threadlocal: bool,
5529 is_dll_import: bool,5379 is_dll_import: bool,
5530 relocation: std.builtin.ExternOptions.Relocation,5380 relocation: std.builtin.ExternOptions.Relocation,
5531 source: Source,5381 source: Source,
5532 decoration_type: DecorationType,5382 decoration_type: DecorationType,
5533 _: u22 = 0,5383 _: u23 = 0,
55345384
5535 pub const Source = enum(u1) { builtin, syntax };5385 pub const Source = enum(u1) { builtin, syntax };
5536 pub const DecorationType = enum(u2) { none, location, descriptor };5386 pub const DecorationType = enum(u2) { none, location, descriptor };
...@@ -6894,19 +6744,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -6894,19 +6744,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
6894 .ty = .comptime_float_type,6744 .ty = .comptime_float_type,
6895 .storage = .{ .f128 = extraData(unwrapped_index.getExtra(ip), Float128, data).get() },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 .@"extern" => {6747 .@"extern" => {
6911 const extra = extraData(unwrapped_index.getExtra(ip), Tag.Extern, data);6748 const extra = extraData(unwrapped_index.getExtra(ip), Tag.Extern, data);
6912 const nav = ip.getNav(extra.owner_nav);6749 const nav = ip.getNav(extra.owner_nav);
...@@ -6916,13 +6753,13 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -6916,13 +6753,13 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
6916 .lib_name = extra.lib_name,6753 .lib_name = extra.lib_name,
6917 .linkage = extra.flags.linkage,6754 .linkage = extra.flags.linkage,
6918 .visibility = extra.flags.visibility,6755 .visibility = extra.flags.visibility,
6919 .is_threadlocal = extra.flags.is_threadlocal,6756 .is_threadlocal = nav.resolved.?.@"threadlocal",
6920 .is_dll_import = extra.flags.is_dll_import,6757 .is_dll_import = extra.flags.is_dll_import,
6921 .relocation = extra.flags.relocation,6758 .relocation = extra.flags.relocation,
6922 .decoration = extra.decoration(),6759 .decoration = extra.decoration(),
6923 .is_const = nav.status.fully_resolved.is_const,6760 .is_const = nav.resolved.?.@"const",
6924 .alignment = nav.status.fully_resolved.alignment,6761 .alignment = nav.resolved.?.@"align",
6925 .@"addrspace" = nav.status.fully_resolved.@"addrspace",6762 .@"addrspace" = nav.resolved.?.@"addrspace",
6926 .zir_index = extra.zir_index,6763 .zir_index = extra.zir_index,
6927 .owner_nav = extra.owner_nav,6764 .owner_nav = extra.owner_nav,
6928 .source = extra.flags.source,6765 .source = extra.flags.source,
...@@ -7516,22 +7353,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key:...@@ -7516,22 +7353,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key:
7516 .func => unreachable, // use getFuncInstance() or getFuncDecl() instead7353 .func => unreachable, // use getFuncInstance() or getFuncDecl() instead
7517 .un => unreachable, // use getUnion instead7354 .un => unreachable, // use getUnion instead
75187355
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 .slice => |slice| {7356 .slice => |slice| {
7536 assert(ip.indexToKey(slice.ty).ptr_type.flags.size == .slice);7357 assert(ip.indexToKey(slice.ty).ptr_type.flags.size == .slice);
7537 assert(ip.indexToKey(ip.typeOf(slice.ptr)).ptr_type.flags.size == .many);7358 assert(ip.indexToKey(ip.typeOf(slice.ptr)).ptr_type.flags.size == .many);
...@@ -9245,14 +9066,15 @@ pub fn getExtern(...@@ -9245,14 +9066,15 @@ pub fn getExtern(
9245 .tid = tid,9066 .tid = tid,
9246 .index = items.mutate.len,9067 .index = items.mutate.len,
9247 }, ip);9068 }, ip);
9248 const owner_nav = ip.createNav(gpa, io, tid, .{9069 const owner_nav = ip.createNav(gpa, io, tid, key.name, key.name, .{
9249 .name = key.name,9070 .type = key.ty,
9250 .fqn = key.name,9071 .@"align" = key.alignment,
9251 .val = extern_index,
9252 .is_const = key.is_const,
9253 .alignment = key.alignment,
9254 .@"linksection" = .none,9072 .@"linksection" = .none,
9255 .@"addrspace" = key.@"addrspace",9073 .@"addrspace" = key.@"addrspace",
9074 .@"const" = key.is_const,
9075 .@"threadlocal" = key.is_threadlocal,
9076 .is_extern_decl = true,
9077 .value = extern_index,
9256 }) catch unreachable; // capacity asserted above9078 }) catch unreachable; // capacity asserted above
9257 const decoration_type, const location_or_descriptor_set, const descriptor_binding = if (key.decoration) |decoration| switch (decoration) {9079 const decoration_type, const location_or_descriptor_set, const descriptor_binding = if (key.decoration) |decoration| switch (decoration) {
9258 .location => |location| .{ Tag.Extern.Flags.DecorationType.location, location, undefined },9080 .location => |location| .{ Tag.Extern.Flags.DecorationType.location, location, undefined },
...@@ -9266,7 +9088,6 @@ pub fn getExtern(...@@ -9266,7 +9088,6 @@ pub fn getExtern(
9266 .flags = .{9088 .flags = .{
9267 .linkage = key.linkage,9089 .linkage = key.linkage,
9268 .visibility = key.visibility,9090 .visibility = key.visibility,
9269 .is_threadlocal = key.is_threadlocal,
9270 .is_dll_import = key.is_dll_import,9091 .is_dll_import = key.is_dll_import,
9271 .relocation = key.relocation,9092 .relocation = key.relocation,
9272 .decoration_type = decoration_type,9093 .decoration_type = decoration_type,
...@@ -9846,14 +9667,16 @@ fn finishFuncInstance(...@@ -9846,14 +9667,16 @@ fn finishFuncInstance(
9846 const nav_name = try ip.getOrPutStringFmt(gpa, io, tid, "{f}__anon_{d}", .{9667 const nav_name = try ip.getOrPutStringFmt(gpa, io, tid, "{f}__anon_{d}", .{
9847 fn_owner_nav.name.fmt(ip), @intFromEnum(func_index),9668 fn_owner_nav.name.fmt(ip), @intFromEnum(func_index),
9848 }, .no_embedded_nulls);9669 }, .no_embedded_nulls);
9849 const nav_index = try ip.createNav(gpa, io, tid, .{9670 const nav_fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, io, tid, nav_name);
9850 .name = nav_name,9671 const nav_index = try ip.createNav(gpa, io, tid, nav_name, nav_fqn, .{
9851 .fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, io, tid, nav_name),9672 .type = ip.typeOf(func_index),
9852 .val = func_index,9673 .@"align" = fn_owner_nav.resolved.?.@"align",
9853 .is_const = fn_owner_nav.status.fully_resolved.is_const,9674 .@"linksection" = fn_owner_nav.resolved.?.@"linksection",
9854 .alignment = fn_owner_nav.status.fully_resolved.alignment,9675 .@"addrspace" = fn_owner_nav.resolved.?.@"addrspace",
9855 .@"linksection" = fn_owner_nav.status.fully_resolved.@"linksection",9676 .@"const" = true,
9856 .@"addrspace" = fn_owner_nav.status.fully_resolved.@"addrspace",9677 .@"threadlocal" = false,
9678 .is_extern_decl = false,
9679 .value = func_index,
9857 });9680 });
98589681
9859 // Populate the owner_nav field which was left undefined until now.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,20 +10439,6 @@ pub fn errorUnionPayload(ip: *const InternPool, ty: Index) Index {
10616 return ip.indexToKey(ty).error_union_type.payload_type;10439 return ip.indexToKey(ty).error_union_type.payload_type;
10617}10440}
1061810441
10619/// The is only legal because the initializer is not part of the hash.
10620pub 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
10633pub fn dump(ip: *const InternPool) void {10442pub fn dump(ip: *const InternPool) void {
10634 var buffer: [4096]u8 = undefined;10443 var buffer: [4096]u8 = undefined;
10635 const stderr = std.debug.lockStderr(&buffer);10444 const stderr = std.debug.lockStderr(&buffer);
...@@ -10969,7 +10778,6 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo...@@ -10969,7 +10778,6 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo
10969 .float_c_longdouble_f80 => @sizeOf(Float80),10778 .float_c_longdouble_f80 => @sizeOf(Float80),
10970 .float_c_longdouble_f128 => @sizeOf(Float128),10779 .float_c_longdouble_f128 => @sizeOf(Float128),
10971 .float_comptime_float => @sizeOf(Float128),10780 .float_comptime_float => @sizeOf(Float128),
10972 .variable, .threadlocal_variable => @sizeOf(Tag.Variable),
10973 .@"extern" => @sizeOf(Tag.Extern),10781 .@"extern" => @sizeOf(Tag.Extern),
10974 .func_decl => @sizeOf(Tag.FuncDecl),10782 .func_decl => @sizeOf(Tag.FuncDecl),
10975 .func_instance => b: {10783 .func_instance => b: {
...@@ -11089,8 +10897,6 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void {...@@ -11089,8 +10897,6 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void {
11089 .float_c_longdouble_f80,10897 .float_c_longdouble_f80,
11090 .float_c_longdouble_f128,10898 .float_c_longdouble_f128,
11091 .float_comptime_float,10899 .float_comptime_float,
11092 .variable,
11093 .threadlocal_variable,
11094 .@"extern",10900 .@"extern",
11095 .func_decl,10901 .func_decl,
11096 .func_instance,10902 .func_instance,
...@@ -11175,8 +10981,24 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator,...@@ -11175,8 +10981,24 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator,
1117510981
11176pub fn getNav(ip: *const InternPool, index: Nav.Index) Nav {10982pub fn getNav(ip: *const InternPool, index: Nav.Index) Nav {
11177 const unwrapped = index.unwrap(ip);10983 const unwrapped = index.unwrap(ip);
11178 const navs = ip.getLocalShared(unwrapped.tid).navs.acquire();10984 const view = ip.getLocalShared(unwrapped.tid).navs.acquire().view();
11179 return navs.view().get(unwrapped.index).unpack();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}
1118111003
11182pub fn namespacePtr(ip: *InternPool, namespace_index: NamespaceIndex) *Zcu.Namespace {11004pub fn namespacePtr(ip: *InternPool, namespace_index: NamespaceIndex) *Zcu.Namespace {
...@@ -11220,15 +11042,9 @@ fn createNav(...@@ -11220,15 +11042,9 @@ fn createNav(
11220 gpa: Allocator,11042 gpa: Allocator,
11221 io: Io,11043 io: Io,
11222 tid: Zcu.PerThread.Id,11044 tid: Zcu.PerThread.Id,
11223 opts: struct {11045 name: NullTerminatedString,
11224 name: NullTerminatedString,11046 fqn: NullTerminatedString,
11225 fqn: NullTerminatedString,11047 resolved: @typeInfo(@FieldType(Nav, "resolved")).optional.child,
11226 val: InternPool.Index,
11227 is_const: bool,
11228 alignment: Alignment,
11229 @"linksection": OptionalNullTerminatedString,
11230 @"addrspace": std.builtin.AddressSpace,
11231 },
11232) Allocator.Error!Nav.Index {11048) Allocator.Error!Nav.Index {
11233 const navs = ip.getLocal(tid).getMutableNavs(gpa, io);11049 const navs = ip.getLocal(tid).getMutableNavs(gpa, io);
11234 const index_unwrapped: Nav.Index.Unwrapped = .{11050 const index_unwrapped: Nav.Index.Unwrapped = .{
...@@ -11236,16 +11052,10 @@ fn createNav(...@@ -11236,16 +11052,10 @@ fn createNav(
11236 .index = navs.mutate.len,11052 .index = navs.mutate.len,
11237 };11053 };
11238 try navs.append(Nav.pack(.{11054 try navs.append(Nav.pack(.{
11239 .name = opts.name,11055 .name = name,
11240 .fqn = opts.fqn,11056 .fqn = fqn,
11241 .analysis = null,11057 .analysis = null,
11242 .status = .{ .fully_resolved = .{11058 .resolved = resolved,
11243 .val = opts.val,
11244 .is_const = opts.is_const,
11245 .alignment = opts.alignment,
11246 .@"linksection" = opts.@"linksection",
11247 .@"addrspace" = opts.@"addrspace",
11248 } },
11249 }));11059 }));
11250 return index_unwrapped.wrap(ip);11060 return index_unwrapped.wrap(ip);
11251}11061}
...@@ -11279,27 +11089,19 @@ pub fn createDeclNav(...@@ -11279,27 +11089,19 @@ pub fn createDeclNav(
11279 .zir_index = zir_index,11089 .zir_index = zir_index,
11280 .wanted = false,11090 .wanted = false,
11281 },11091 },
11282 .status = .unresolved,11092 .resolved = null,
11283 }));11093 }));
1128411094
11285 return nav;11095 return nav;
11286}11096}
1128711097
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/// If its status is already `resolved`, the old value is discarded.11099/// If its status is already `resolved`, the old value is discarded.
11290pub fn resolveNavType(11100pub fn resolveNav(
11291 ip: *InternPool,11101 ip: *InternPool,
11292 io: Io,11102 io: Io,
11293 nav: Nav.Index,11103 nav: Nav.Index,
11294 resolved: struct {11104 resolved: @typeInfo(@FieldType(Nav, "resolved")).optional.child,
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 },
11303) void {11105) void {
11304 const unwrapped = nav.unwrap(ip);11106 const unwrapped = nav.unwrap(ip);
1130511107
...@@ -11311,65 +11113,45 @@ pub fn resolveNavType(...@@ -11311,65 +11113,45 @@ pub fn resolveNavType(
1131111113
11312 const nav_analysis_namespace = navs.items(.analysis_namespace);11114 const nav_analysis_namespace = navs.items(.analysis_namespace);
11313 const nav_analysis_zir_index = navs.items(.analysis_zir_index);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 const nav_linksections = navs.items(.@"linksection");11118 const nav_linksections = navs.items(.@"linksection");
11316 const nav_bits = navs.items(.bits);11119 const nav_bits = navs.items(.bits);
1131711120
11318 assert(nav_analysis_namespace[unwrapped.index] != .none);11121 assert(nav_analysis_namespace[unwrapped.index] != .none);
11319 assert(nav_analysis_zir_index[unwrapped.index] != .none);11122 assert(nav_analysis_zir_index[unwrapped.index] != .none);
1132011123
11321 @atomicStore(InternPool.Index, &nav_types[unwrapped.index], resolved.type, .release);11124 @atomicStore(
11322 @atomicStore(OptionalNullTerminatedString, &nav_linksections[unwrapped.index], resolved.@"linksection", .release);11125 OptionalNullTerminatedString,
1132311126 &nav_linksections[unwrapped.index],
11324 var bits = nav_bits[unwrapped.index];11127 resolved.@"linksection",
11325 bits.status = if (resolved.is_extern_decl) .type_resolved_extern_decl else .type_resolved;11128 .monotonic,
11326 bits.is_const = resolved.is_const;11129 );
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.
11335pub 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);
1136311130
11364 @atomicStore(InternPool.Index, &nav_vals[unwrapped.index], resolved.val, .release);11131 const bits = &nav_bits[unwrapped.index];
11365 @atomicStore(OptionalNullTerminatedString, &nav_linksections[unwrapped.index], resolved.@"linksection", .release);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 );
1136611148
11367 var bits = nav_bits[unwrapped.index];11149 @atomicStore(
11368 bits.status = .fully_resolved;11150 InternPool.Index,
11369 bits.is_const = resolved.is_const;11151 &nav_values[unwrapped.index],
11370 bits.alignment = resolved.alignment;11152 resolved.value,
11371 bits.@"addrspace" = resolved.@"addrspace";11153 .monotonic,
11372 @atomicStore(Nav.Repr.Bits, &nav_bits[unwrapped.index], bits, .release);11154 );
11373}11155}
1137411156
11375pub fn createNamespace(11157pub fn createNamespace(
...@@ -11841,8 +11623,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -11841,8 +11623,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
11841 .error_set_error,11623 .error_set_error,
11842 .error_union_error,11624 .error_union_error,
11843 .enum_tag,11625 .enum_tag,
11844 .variable,
11845 .threadlocal_variable,
11846 .@"extern",11626 .@"extern",
11847 .func_decl,11627 .func_decl,
11848 .func_instance,11628 .func_instance,
...@@ -11949,11 +11729,7 @@ pub fn funcTypeReturnType(ip: *const InternPool, ty: Index) Index {...@@ -11949,11 +11729,7 @@ pub fn funcTypeReturnType(ip: *const InternPool, ty: Index) Index {
11949}11729}
1195011730
11951pub fn isUndef(ip: *const InternPool, val: Index) bool {11731pub fn isUndef(ip: *const InternPool, val: Index) bool {
11952 return val == .undef or val.unwrap(ip).getTag(ip) == .undef;11732 return val.unwrap(ip).getTag(ip) == .undef;
11953}
11954
11955pub fn isVariable(ip: *const InternPool, val: Index) bool {
11956 return val.unwrap(ip).getTag(ip) == .variable;
11957}11733}
1195811734
11959pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.BaseAddr.Tag {11735pub 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,8 +11996,6 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId {
12220 .float_c_longdouble_f80,11996 .float_c_longdouble_f80,
12221 .float_c_longdouble_f128,11997 .float_c_longdouble_f128,
12222 .float_comptime_float,11998 .float_comptime_float,
12223 .variable,
12224 .threadlocal_variable,
12225 .@"extern",11999 .@"extern",
12226 .func_decl,12000 .func_decl,
12227 .func_instance,12001 .func_instance,
...@@ -13001,11 +12775,17 @@ pub fn setWantNavAnalysis(ip: *InternPool, io: Io, nav_index: Nav.Index) bool {...@@ -13001,11 +12775,17 @@ pub fn setWantNavAnalysis(ip: *InternPool, io: Io, nav_index: Nav.Index) bool {
13001 return false;12775 return false;
13002 }12776 }
1300312777
13004 const bits = &navs.items(.bits)[unwrapped.index];12778 // Mutate `bits` atomically so that we don't introduce an illegal data race with `getNav`.
13005 if (bits.want_analysis) {12779 const old_bits = @atomicRmw(
13006 return false;12780 Nav.Repr.Bits,
13007 } else {12781 &navs.items(.bits)[unwrapped.index],
13008 bits.want_analysis = true;12782 .Or,
13009 return true;12783 mask: {
13010 }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,28 +2276,26 @@ fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) ?Value {
2276 assert(inst != .none);2276 assert(inst != .none);
22772277
2278 if (inst.toInterned()) |ip_index| {2278 if (inst.toInterned()) |ip_index| {
2279 const val: Value = .fromInterned(ip_index);2279 return .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;
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}
23022300
2303/// Like `resolveValue`, but emits an error if the value is not comptime-known.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,8 +5736,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
5738 .uav => |uav| .{ .uav = uav.val },5736 .uav => |uav| .{ .uav = uav.val },
5739 .nav => |orig_nav| target: {5737 .nav => |orig_nav| target: {
5740 try sema.ensureNavResolved(block, src, orig_nav, .fully);5738 try sema.ensureNavResolved(block, src, orig_nav, .fully);
5741 const export_nav = switch (ip.indexToKey(ip.getNav(orig_nav).status.fully_resolved.val)) {5739 const export_nav = switch (ip.indexToKey(ip.getNav(orig_nav).resolved.?.value)) {
5742 .variable => |v| v.owner_nav,
5743 .@"extern" => |e| e.owner_nav,5740 .@"extern" => |e| e.owner_nav,
5744 .func => |f| f.owner_nav,5741 .func => |f| f.owner_nav,
5745 else => orig_nav,5742 else => orig_nav,
...@@ -5778,7 +5775,7 @@ pub fn analyzeExportSelfNav(...@@ -5778,7 +5775,7 @@ pub fn analyzeExportSelfNav(
5778 const ip = &zcu.intern_pool;5775 const ip = &zcu.intern_pool;
57795776
5780 const orig_nav = sema.owner.unwrap().nav_val;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 const export_ty = export_val.typeOf(zcu);5779 const export_ty = export_val.typeOf(zcu);
57835780
5784 if (!export_ty.validateExtern(.other, zcu)) {5781 if (!export_ty.validateExtern(.other, zcu)) {
...@@ -5792,7 +5789,6 @@ pub fn analyzeExportSelfNav(...@@ -5792,7 +5789,6 @@ pub fn analyzeExportSelfNav(
5792 }5789 }
57935790
5794 const export_nav = switch (ip.indexToKey(export_val.toIntern())) {5791 const export_nav = switch (ip.indexToKey(export_val.toIntern())) {
5795 .variable => |v| v.owner_nav,
5796 .@"extern" => |e| e.owner_nav,5792 .@"extern" => |e| e.owner_nav,
5797 .func => |f| export_nav: {5793 .func => |f| export_nav: {
5798 assert(export_ty.fnHasRuntimeBits(zcu)); // otherwise `validateExtern` failed above5794 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,7 +30001,7 @@ pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index:
3000530001
30006 const nav = ip.getNav(nav_index);30002 const nav = ip.getNav(nav_index);
30007 if (nav.analysis == null) {30003 if (nav.analysis == null) {
30008 assert(nav.status == .fully_resolved);30004 assert(nav.resolved.?.value != .none);
30009 return;30005 return;
30010 }30006 }
3001130007
...@@ -30066,11 +30062,20 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde...@@ -30066,11 +30062,20 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde
30066 try sema.ensureNavResolved(block, src, orig_nav_index, if (is_ref) .type else .fully);30062 try sema.ensureNavResolved(block, src, orig_nav_index, if (is_ref) .type else .fully);
3006730063
30068 const nav_index = nav: {30064 const nav_index = nav: {
30069 if (ip.getNav(orig_nav_index).isExternOrFn(ip)) {30065 const orig_nav = ip.getNav(orig_nav_index);
30070 // Getting a pointer to this `Nav` might mean we actually get a pointer to something else!30066 if (orig_nav.resolved.?.is_extern_decl or ip.zigTypeTag(orig_nav.resolved.?.type) == .@"fn") {
30071 // We need to resolve the value to know for sure.30067 // A pointer to this `Nav` might actually be encoded as a pointer to a different `Nav`
30072 if (is_ref) try sema.ensureNavResolved(block, src, orig_nav_index, .fully);30068 // because this is either an `extern` definition or an `extern` alias. (The latter case
30073 switch (ip.indexToKey(ip.getNav(orig_nav_index).status.fully_resolved.val)) {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 .func => |f| break :nav f.owner_nav,30079 .func => |f| break :nav f.owner_nav,
30075 .@"extern" => |e| break :nav e.owner_nav,30080 .@"extern" => |e| break :nav e.owner_nav,
30076 else => {},30081 else => {},
...@@ -30079,33 +30084,31 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde...@@ -30079,33 +30084,31 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde
30079 break :nav orig_nav_index;30084 break :nav orig_nav_index;
30080 };30085 };
3008130086
30082 const nav_status = ip.getNav(nav_index).status;30087 const nav_resolved = ip.getNav(nav_index).resolved.?;
3008330088
30084 const is_runtime = switch (nav_status) {30089 const is_runtime: bool = runtime: {
30085 .unresolved => unreachable,30090 if (nav_resolved.@"threadlocal") break :runtime true;
30086 // dllimports go straight to `fully_resolved`; the only option is threadlocal30091 if (nav_resolved.value == .none) {
30087 .type_resolved => |r| r.is_threadlocal,30092 // This didn't come from `@extern`, so even if extern it couldn't be dllimport or pcrel.
30088 .fully_resolved => |r| switch (ip.indexToKey(r.val)) {30093 break :runtime false;
30089 .@"extern" => |e| e.is_threadlocal or e.is_dll_import or switch (e.relocation) {30094 }
30090 .any => false,30095 const @"extern" = switch (ip.indexToKey(nav_resolved.value)) {
30091 .pcrel => true,30096 .@"extern" => |e| e,
30092 },30097 else => break :runtime false,
30093 .variable => |v| v.is_threadlocal,30098 };
30094 else => false,30099 if (@"extern".is_dll_import) break :runtime true;
30095 },30100 break :runtime switch (@"extern".relocation) {
30101 .any => false,
30102 .pcrel => true,
30103 };
30096 };30104 };
3009730105
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 const ptr_ty = try pt.ptrType(.{30106 const ptr_ty = try pt.ptrType(.{
30104 .child = ty,30107 .child = nav_resolved.type,
30105 .flags = .{30108 .flags = .{
30106 .alignment = alignment,30109 .alignment = nav_resolved.@"align",
30107 .is_const = is_const,30110 .is_const = nav_resolved.@"const",
30108 .address_space = @"addrspace",30111 .address_space = nav_resolved.@"addrspace",
30109 },30112 },
30110 });30113 });
3011130114
...@@ -30140,7 +30143,7 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, block: *Block, src: LazySrcLoc, nav_i...@@ -30140,7 +30143,7 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, block: *Block, src: LazySrcLoc, nav_i
30140 // If it is, we can resolve the *value*, and queue analysis as needed.30143 // If it is, we can resolve the *value*, and queue analysis as needed.
3014130144
30142 try sema.ensureNavResolved(block, src, nav_index, .type);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 if (nav_ty.zigTypeTag(zcu) != .@"fn") return;30147 if (nav_ty.zigTypeTag(zcu) != .@"fn") return;
30145 if (!nav_ty.fnHasRuntimeBits(zcu)) return;30148 if (!nav_ty.fnHasRuntimeBits(zcu)) return;
3014630149
...@@ -34006,7 +34009,7 @@ pub fn getBuiltin(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) SemaError...@@ -34006,7 +34009,7 @@ pub fn getBuiltin(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) SemaError
34006}34009}
3400734010
34008pub const NavPtrModifiers = struct {34011pub const NavPtrModifiers = struct {
34009 alignment: Alignment,34012 @"align": Alignment,
34010 @"linksection": InternPool.OptionalNullTerminatedString,34013 @"linksection": InternPool.OptionalNullTerminatedString,
34011 @"addrspace": std.builtin.AddressSpace,34014 @"addrspace": std.builtin.AddressSpace,
34012};34015};
...@@ -34029,7 +34032,7 @@ pub fn resolveNavPtrModifiers(...@@ -34029,7 +34032,7 @@ pub fn resolveNavPtrModifiers(
34029 const section_src = block.src(.{ .node_offset_var_decl_section = .zero });34032 const section_src = block.src(.{ .node_offset_var_decl_section = .zero });
34030 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = .zero });34033 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = .zero });
3403134034
34032 const alignment: InternPool.Alignment = a: {34035 const @"align": InternPool.Alignment = a: {
34033 const align_body = zir_decl.align_body orelse break :a .none;34036 const align_body = zir_decl.align_body orelse break :a .none;
34034 const align_ref = try sema.resolveInlineBody(block, align_body, decl_inst);34037 const align_ref = try sema.resolveInlineBody(block, align_body, decl_inst);
34035 break :a try sema.analyzeAsAlign(block, align_src, align_ref);34038 break :a try sema.analyzeAsAlign(block, align_src, align_ref);
...@@ -34067,7 +34070,7 @@ pub fn resolveNavPtrModifiers(...@@ -34067,7 +34070,7 @@ pub fn resolveNavPtrModifiers(
34067 };34070 };
3406834071
34069 return .{34072 return .{
34070 .alignment = alignment,34073 .@"align" = @"align",
34071 .@"linksection" = @"linksection",34074 .@"linksection" = @"linksection",
34072 .@"addrspace" = @"addrspace",34075 .@"addrspace" = @"addrspace",
34073 };34076 };
src/Sema/bitcast.zig-1
...@@ -253,7 +253,6 @@ const UnpackValueBits = struct {...@@ -253,7 +253,6 @@ const UnpackValueBits = struct {
253 .func_type,253 .func_type,
254 .error_set_type,254 .error_set_type,
255 .inferred_error_set_type,255 .inferred_error_set_type,
256 .variable,
257 .@"extern",256 .@"extern",
258 .func,257 .func,
259 .err,258 .err,
src/Sema/comptime_ptr_access.zig+10-12
...@@ -225,19 +225,17 @@ fn loadComptimePtrInner(...@@ -225,19 +225,17 @@ fn loadComptimePtrInner(
225 };225 };
226226
227 const base_val: MutableValue = switch (ptr.base_addr) {227 const base_val: MutableValue = switch (ptr.base_addr) {
228 .nav => |nav| val: {228 .nav => |nav_id| val: {
229 try sema.ensureNavResolved(block, src, nav, .fully);229 try sema.ensureNavResolved(block, src, nav_id, .fully);
230 const val = ip.getNav(nav).status.fully_resolved.val;230 const nav = ip.getNav(nav_id);
231 switch (ip.indexToKey(val)) {231 if (!nav.resolved.?.@"const") return .runtime_load;
232 .variable => return .runtime_load,232 // We let `.@"extern"` through here if it's a fn. This allows aliasing `extern fn`s.
233 // We let `.@"extern"` through here if it's a function.233 if (ip.indexToKey(nav.resolved.?.value) == .@"extern" and
234 // This allows you to alias `extern fn`s.234 Type.fromInterned(nav.resolved.?.type).zigTypeTag(zcu) != .@"fn")
235 .@"extern" => |e| if (Type.fromInterned(e.ty).zigTypeTag(zcu) == .@"fn")235 {
236 break :val .{ .interned = val }236 return .runtime_load;
237 else
238 return .runtime_load,
239 else => break :val .{ .interned = val },
240 }237 }
238 break :val .{ .interned = nav.resolved.?.value };
241 },239 },
242 .comptime_alloc => |alloc_index| sema.getComptimeAlloc(alloc_index).val,240 .comptime_alloc => |alloc_index| sema.getComptimeAlloc(alloc_index).val,
243 .uav => |uav| .{ .interned = uav.val },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,7 +115,6 @@ fn ensureLayoutResolvedInner(sema: *Sema, ty: Type, orig_ty: Type, reason: *cons
115 // values, not types115 // values, not types
116 .undef,116 .undef,
117 .simple_value,117 .simple_value,
118 .variable,
119 .@"extern",118 .@"extern",
120 .func,119 .func,
121 .int,120 .int,
src/Type.zig-10
...@@ -239,7 +239,6 @@ pub fn classify(start_ty: Type, zcu: *const Zcu) Class {...@@ -239,7 +239,6 @@ pub fn classify(start_ty: Type, zcu: *const Zcu) Class {
239 // values, not types239 // values, not types
240 .undef,240 .undef,
241 .simple_value,241 .simple_value,
242 .variable,
243 .@"extern",242 .@"extern",
244 .func,243 .func,
245 .int,244 .int,
...@@ -675,7 +674,6 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari...@@ -675,7 +674,6 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari
675674
676 // values, not types675 // values, not types
677 .simple_value,676 .simple_value,
678 .variable,
679 .@"extern",677 .@"extern",
680 .func,678 .func,
681 .int,679 .int,
...@@ -814,7 +812,6 @@ pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool {...@@ -814,7 +812,6 @@ pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool {
814 // values, not types812 // values, not types
815 .undef,813 .undef,
816 .simple_value,814 .simple_value,
817 .variable,
818 .@"extern",815 .@"extern",
819 .func,816 .func,
820 .int,817 .int,
...@@ -1046,7 +1043,6 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment {...@@ -1046,7 +1043,6 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment {
1046 // values, not types1043 // values, not types
1047 .undef,1044 .undef,
1048 .simple_value,1045 .simple_value,
1049 .variable,
1050 .@"extern",1046 .@"extern",
1051 .func,1047 .func,
1052 .int,1048 .int,
...@@ -1187,7 +1183,6 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 {...@@ -1187,7 +1183,6 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 {
1187 // values, not types1183 // values, not types
1188 .undef,1184 .undef,
1189 .simple_value,1185 .simple_value,
1190 .variable,
1191 .@"extern",1186 .@"extern",
1192 .func,1187 .func,
1193 .int,1188 .int,
...@@ -1311,7 +1306,6 @@ pub fn bitSize(ty: Type, zcu: *const Zcu) u64 {...@@ -1311,7 +1306,6 @@ pub fn bitSize(ty: Type, zcu: *const Zcu) u64 {
1311 // values, not types1306 // values, not types
1312 .undef,1307 .undef,
1313 .simple_value,1308 .simple_value,
1314 .variable,
1315 .@"extern",1309 .@"extern",
1316 .func,1310 .func,
1317 .int,1311 .int,
...@@ -1867,7 +1861,6 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType {...@@ -1867,7 +1861,6 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType {
1867 // values, not types1861 // values, not types
1868 .undef,1862 .undef,
1869 .simple_value,1863 .simple_value,
1870 .variable,
1871 .@"extern",1864 .@"extern",
1872 .func,1865 .func,
1873 .int,1866 .int,
...@@ -2162,7 +2155,6 @@ pub fn onePossibleValue(ty: Type, pt: Zcu.PerThread) !?Value {...@@ -2162,7 +2155,6 @@ pub fn onePossibleValue(ty: Type, pt: Zcu.PerThread) !?Value {
2162 // values, not types2155 // values, not types
2163 .undef,2156 .undef,
2164 .simple_value,2157 .simple_value,
2165 .variable,
2166 .@"extern",2158 .@"extern",
2167 .func,2159 .func,
2168 .int,2160 .int,
...@@ -3284,7 +3276,6 @@ pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void {...@@ -3284,7 +3276,6 @@ pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void {
32843276
3285 // values, not types3277 // values, not types
3286 .simple_value,3278 .simple_value,
3287 .variable,
3288 .@"extern",3279 .@"extern",
3289 .func,3280 .func,
3290 .int,3281 .int,
...@@ -3362,7 +3353,6 @@ fn collectSubtypes(ty: Type, pt: Zcu.PerThread, visited: *std.AutoArrayHashMapUn...@@ -3362,7 +3353,6 @@ fn collectSubtypes(ty: Type, pt: Zcu.PerThread, visited: *std.AutoArrayHashMapUn
33623353
3363 // values, not types3354 // values, not types
3364 .simple_value,3355 .simple_value,
3365 .variable,
3366 .@"extern",3356 .@"extern",
3367 .func,3357 .func,
3368 .int,3358 .int,
src/Value.zig+1-9
...@@ -176,13 +176,6 @@ pub fn getFunction(val: Value, zcu: *Zcu) ?InternPool.Key.Func {...@@ -176,13 +176,6 @@ pub fn getFunction(val: Value, zcu: *Zcu) ?InternPool.Key.Func {
176 };176 };
177}177}
178178
179pub 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/// Asserts the value is a (defined) integer and it fits in a u64.179/// Asserts the value is a (defined) integer and it fits in a u64.
187pub fn toUnsignedInt(val: Value, zcu: *const Zcu) u64 {180pub fn toUnsignedInt(val: Value, zcu: *const Zcu) u64 {
188 return getUnsignedInt(val, zcu).?;181 return getUnsignedInt(val, zcu).?;
...@@ -808,7 +801,6 @@ pub fn canMutateComptimeVarState(val: Value, zcu: *Zcu) bool {...@@ -808,7 +801,6 @@ pub fn canMutateComptimeVarState(val: Value, zcu: *Zcu) bool {
808pub fn pointerNav(val: Value, zcu: *const Zcu) ?InternPool.Nav.Index {801pub fn pointerNav(val: Value, zcu: *const Zcu) ?InternPool.Nav.Index {
809 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {802 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {
810 // TODO: these 3 cases are weird; these aren't pointer values!803 // TODO: these 3 cases are weird; these aren't pointer values!
811 .variable => |v| v.owner_nav,
812 .@"extern" => |e| e.owner_nav,804 .@"extern" => |e| e.owner_nav,
813 .func => |func| func.owner_nav,805 .func => |func| func.owner_nav,
814 .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) {806 .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) {
...@@ -2539,7 +2531,7 @@ pub fn intFitsInType(...@@ -2539,7 +2531,7 @@ pub fn intFitsInType(
2539 .zero_usize, .zero_u8 => return true,2531 .zero_usize, .zero_u8 => return true,
2540 else => switch (zcu.intern_pool.indexToKey(val.toIntern())) {2532 else => switch (zcu.intern_pool.indexToKey(val.toIntern())) {
2541 .undef => return true,2533 .undef => return true,
2542 .variable, .@"extern", .func, .ptr => {2534 .@"extern", .func, .ptr => {
2543 const target = zcu.getTarget();2535 const target = zcu.getTarget();
2544 const ptr_bits = target.ptrBitWidth();2536 const ptr_bits = target.ptrBitWidth();
2545 return switch (info.signedness) {2537 return switch (info.signedness) {
src/Zcu.zig+9-15
...@@ -723,11 +723,7 @@ pub const Exported = union(enum) {...@@ -723,11 +723,7 @@ pub const Exported = union(enum) {
723723
724 pub fn getAlign(exported: Exported, zcu: *Zcu) Alignment {724 pub fn getAlign(exported: Exported, zcu: *Zcu) Alignment {
725 return switch (exported) {725 return switch (exported) {
726 .nav => |nav| switch (zcu.intern_pool.getNav(nav).status) {726 .nav => |nav| zcu.intern_pool.getNav(nav).resolved.?.@"align",
727 .unresolved => unreachable,
728 .type_resolved => |r| r.alignment,
729 .fully_resolved => |r| r.alignment,
730 },
731 .uav => .none,727 .uav => .none,
732 };728 };
733 }729 }
...@@ -4252,8 +4248,8 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.AutoArrayHashMapUnmanag...@@ -4252,8 +4248,8 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.AutoArrayHashMapUnmanag
4252 }4248 }
4253 }4249 }
4254 // Non-fatal AstGen errors could mean this test decl failed4250 // Non-fatal AstGen errors could mean this test decl failed
4255 if (nav.status == .fully_resolved) {4251 if (nav.resolved != null and nav.resolved.?.value != .none) {
4256 const gop = try units.getOrPut(gpa, .wrap(.{ .func = nav.status.fully_resolved.val }));4252 const gop = try units.getOrPut(gpa, .wrap(.{ .func = nav.resolved.?.value }));
4257 if (!gop.found_existing) gop.value_ptr.* = referencer;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,7 +4415,7 @@ pub fn navSrcLine(zcu: *Zcu, nav_index: InternPool.Nav.Index) u32 {
4419}4415}
44204416
4421pub fn navValue(zcu: *const Zcu, nav_index: InternPool.Nav.Index) Value {4417pub 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}
44244420
4425pub fn navFileScopeIndex(zcu: *Zcu, nav: InternPool.Nav.Index) File.Index {4421pub 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,14 +4427,12 @@ pub fn navFileScope(zcu: *Zcu, nav: InternPool.Nav.Index) *File {
4431 return zcu.fileByIndex(zcu.navFileScopeIndex(nav));4427 return zcu.fileByIndex(zcu.navFileScopeIndex(nav));
4432}4428}
44334429
4434pub fn navAlignment(zcu: *Zcu, nav_index: InternPool.Nav.Index) InternPool.Alignment {4430pub fn navAlignment(zcu: *Zcu, nav_id: InternPool.Nav.Index) InternPool.Alignment {
4435 const ty: Type, const alignment = switch (zcu.intern_pool.getNav(nav_index).status) {4431 const resolved = zcu.intern_pool.getNav(nav_id).resolved.?;
4436 .unresolved => unreachable,4432 return switch (resolved.@"align") {
4437 .type_resolved => |r| .{ .fromInterned(r.type), r.alignment },4433 else => |a| a,
4438 .fully_resolved => |r| .{ Value.fromInterned(r.val).typeOf(zcu), r.alignment },4434 .none => Type.fromInterned(resolved.type).abiAlignment(zcu),
4439 };4435 };
4440 if (alignment != .none) return alignment;
4441 return ty.abiAlignment(zcu);
4442}4436}
44434437
4444pub fn fmtAnalUnit(zcu: *Zcu, unit: AnalUnit) std.fmt.Alt(FormatAnalUnit, formatAnalUnit) {4438pub 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,10 +1584,6 @@ pub fn ensureNavValUpToDate(
15841584
1585 try zcu.ensureNavValAnalysisQueued(nav_id);1585 try zcu.ensureNavValAnalysisQueued(nav_id);
15861586
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 // Note that if the unit is PO, we pessimistically assume that it *does* require re-analysis, to1587 // Note that if the unit is PO, we pessimistically assume that it *does* require re-analysis, to
1592 // ensure that the unit is definitely up-to-date when this function returns. This mechanism could1588 // ensure that the unit is definitely up-to-date when this function returns. This mechanism could
1593 // result in over-analysis if analysis occurs in a poor order; we do our best to avoid this by1589 // 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,7 +1599,7 @@ pub fn ensureNavValUpToDate(
1603 } else {1599 } else {
1604 // We can trust the current information about this unit.1600 // We can trust the current information about this unit.
1605 if (prev_failed) return error.AnalysisFail;1601 if (prev_failed) return error.AnalysisFail;
1606 assert(nav.status == .fully_resolved);1602 assert(nav.resolved.?.value != .none);
1607 return;1603 return;
1608 }1604 }
16091605
...@@ -1740,7 +1736,7 @@ fn analyzeNavVal(...@@ -1740,7 +1736,7 @@ fn analyzeNavVal(
1740 const maybe_ty: ?Type = if (zir_decl.type_body != null) ty: {1736 const maybe_ty: ?Type = if (zir_decl.type_body != null) ty: {
1741 // Since we have a type body, the type is resolved separately!1737 // Since we have a type body, the type is resolved separately!
1742 try sema.ensureNavResolved(&block, init_src, nav_id, .type);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 } else null;1740 } else null;
17451741
1746 const final_val: ?Value = if (zir_decl.value_body) |value_body| val: {1742 const final_val: ?Value = if (zir_decl.value_body) |value_body| val: {
...@@ -1786,14 +1782,12 @@ fn analyzeNavVal(...@@ -1786,14 +1782,12 @@ fn analyzeNavVal(
1786 const modifiers: Sema.NavPtrModifiers = if (zir_decl.type_body != null) m: {1782 const modifiers: Sema.NavPtrModifiers = if (zir_decl.type_body != null) m: {
1787 // `analyzeNavType` (from the `ensureNavTypeUpToDate` call above) has already populated this data into1783 // `analyzeNavType` (from the `ensureNavTypeUpToDate` call above) has already populated this data into
1788 // the `Nav`. Load the new one, and pull the modifiers out.1784 // the `Nav`. Load the new one, and pull the modifiers out.
1789 switch (ip.getNav(nav_id).status) {1785 const r = ip.getNav(nav_id).resolved.?;
1790 .unresolved => unreachable, // `analyzeNavType` will never leave us in this state1786 break :m .{
1791 inline .type_resolved, .fully_resolved => |r| break :m .{1787 .@"align" = r.@"align",
1792 .alignment = r.alignment,1788 .@"linksection" = r.@"linksection",
1793 .@"linksection" = r.@"linksection",1789 .@"addrspace" = r.@"addrspace",
1794 .@"addrspace" = r.@"addrspace",1790 };
1795 },
1796 }
1797 } else m: {1791 } else m: {
1798 // `analyzeNavType` is essentially a stub which calls us. We are responsible for resolving this data.1792 // `analyzeNavType` is essentially a stub which calls us. We are responsible for resolving this data.
1799 break :m try sema.resolveNavPtrModifiers(&block, zir_decl, inst_resolved.inst, nav_ty);1793 break :m try sema.resolveNavPtrModifiers(&block, zir_decl, inst_resolved.inst, nav_ty);
...@@ -1803,15 +1797,7 @@ fn analyzeNavVal(...@@ -1803,15 +1797,7 @@ fn analyzeNavVal(
1803 // This isn't necessarily the same as `final_val`!1797 // This isn't necessarily the same as `final_val`!
18041798
1805 const nav_val: Value = switch (zir_decl.linkage) {1799 const nav_val: Value = switch (zir_decl.linkage) {
1806 .normal, .@"export" => switch (zir_decl.kind) {1800 .normal, .@"export" => final_val.?,
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 },
1815 .@"extern" => val: {1801 .@"extern" => val: {
1816 assert(final_val == null); // extern decls do not have a value body1802 assert(final_val == null); // extern decls do not have a value body
1817 const lib_name: ?[]const u8 = if (zir_decl.lib_name != .empty) l: {1803 const lib_name: ?[]const u8 = if (zir_decl.lib_name != .empty) l: {
...@@ -1832,7 +1818,7 @@ fn analyzeNavVal(...@@ -1832,7 +1818,7 @@ fn analyzeNavVal(
1832 .relocation = .any,1818 .relocation = .any,
1833 .decoration = null,1819 .decoration = null,
1834 .is_const = is_const,1820 .is_const = is_const,
1835 .alignment = modifiers.alignment,1821 .alignment = modifiers.@"align",
1836 .@"addrspace" = modifiers.@"addrspace",1822 .@"addrspace" = modifiers.@"addrspace",
1837 .zir_index = old_nav.analysis.?.zir_index, // `declaration` instruction1823 .zir_index = old_nav.analysis.?.zir_index, // `declaration` instruction
1838 .owner_nav = undefined, // ignored by `getExtern`1824 .owner_nav = undefined, // ignored by `getExtern`
...@@ -1852,11 +1838,7 @@ fn analyzeNavVal(...@@ -1852,11 +1838,7 @@ fn analyzeNavVal(
18521838
1853 const queue_linker_work, const is_owned_fn = switch (ip.indexToKey(nav_val.toIntern())) {1839 const queue_linker_work, const is_owned_fn = switch (ip.indexToKey(nav_val.toIntern())) {
1854 .func => |f| .{ true, f.owner_nav == nav_id }, // note that this lets function aliases reach codegen1840 .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 },1841 .@"extern" => .{ false, nav_ty.zigTypeTag(zcu) == .@"fn" and zir_decl.linkage == .@"extern" },
1856 .@"extern" => |e| .{
1857 false,
1858 Type.fromInterned(e.ty).zigTypeTag(zcu) == .@"fn" and zir_decl.linkage == .@"extern",
1859 },
1860 else => .{ true, false },1842 else => .{ true, false },
1861 };1843 };
18621844
...@@ -1895,23 +1877,22 @@ fn analyzeNavVal(...@@ -1895,23 +1877,22 @@ fn analyzeNavVal(
1895 info.last_update_gen = zcu.generation;1877 info.last_update_gen = zcu.generation;
1896 info.deps.clearRetainingCapacity();1878 info.deps.clearRetainingCapacity();
1897 }1879 }
1898 const type_changed: bool = switch (old_nav.status) {1880 const type_changed: bool = if (old_nav.resolved) |r| r.type != nav_ty.toIntern() else true;
1899 .unresolved => true,
1900 .type_resolved => |old| old.type != nav_ty.toIntern(),
1901 .fully_resolved => |old| ip.typeOf(old.val) != nav_ty.toIntern(),
1902 };
1903 if (type_changed) {1881 if (type_changed) {
1904 try zcu.markDependeeOutdated(.marked_po, .{ .nav_ty = nav_id });1882 try zcu.markDependeeOutdated(.marked_po, .{ .nav_ty = nav_id });
1905 } else {1883 } else {
1906 try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav_id });1884 try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav_id });
1907 }1885 }
1908 }1886 }
1909 ip.resolveNavValue(io, nav_id, .{1887 ip.resolveNav(io, nav_id, .{
1910 .val = nav_val.toIntern(),1888 .type = nav_ty.toIntern(),
1911 .is_const = is_const,1889 .@"align" = modifiers.@"align",
1912 .alignment = modifiers.alignment,
1913 .@"linksection" = modifiers.@"linksection",1890 .@"linksection" = modifiers.@"linksection",
1914 .@"addrspace" = modifiers.@"addrspace",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 });
19161897
1917 if (zir_decl.linkage == .@"export") {1898 if (zir_decl.linkage == .@"export") {
...@@ -1943,9 +1924,10 @@ fn analyzeNavVal(...@@ -1943,9 +1924,10 @@ fn analyzeNavVal(
1943 try zcu.ensureFuncBodyAnalysisQueued(nav_val.toIntern());1924 try zcu.ensureFuncBodyAnalysisQueued(nav_val.toIntern());
1944 }1925 }
19451926
1946 return switch (old_nav.status) {1927 return if (old_nav.resolved) |old_resolved| .{
1947 .unresolved, .type_resolved => .{ .val_changed = true },1928 .val_changed = old_resolved.value != nav_val.toIntern(),
1948 .fully_resolved => |old| .{ .val_changed = old.val != nav_val.toIntern() },1929 } else .{
1930 .val_changed = true,
1949 };1931 };
1950}1932}
19511933
...@@ -1971,10 +1953,6 @@ pub fn ensureNavTypeUpToDate(...@@ -1971,10 +1953,6 @@ pub fn ensureNavTypeUpToDate(
19711953
1972 try zcu.ensureNavValAnalysisQueued(nav_id);1954 try zcu.ensureNavValAnalysisQueued(nav_id);
19731955
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 // Note that if the unit is PO, we pessimistically assume that it *does* require re-analysis, to1956 // Note that if the unit is PO, we pessimistically assume that it *does* require re-analysis, to
1979 // ensure that the unit is definitely up-to-date when this function returns. This mechanism could1957 // ensure that the unit is definitely up-to-date when this function returns. This mechanism could
1980 // result in over-analysis if analysis occurs in a poor order; we do our best to avoid this by1958 // 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,7 +1968,7 @@ pub fn ensureNavTypeUpToDate(
1990 } else {1968 } else {
1991 // We can trust the current information about this unit.1969 // We can trust the current information about this unit.
1992 if (prev_failed) return error.AnalysisFail;1970 if (prev_failed) return error.AnalysisFail;
1993 assert(nav.status != .unresolved);1971 assert(nav.resolved != null);
1994 return;1972 return;
1995 }1973 }
19961974
...@@ -2124,24 +2102,16 @@ fn analyzeNavType(...@@ -2124,24 +2102,16 @@ fn analyzeNavType(
2124 // the previous update. As such, after this call, we will be able to determine whether the2102 // the previous update. As such, after this call, we will be able to determine whether the
2125 // type changed.2103 // type changed.
2126 try sema.ensureNavResolved(&block, init_src, nav_id, .fully);2104 try sema.ensureNavResolved(&block, init_src, nav_id, .fully);
2127 const new = ip.getNav(nav_id).status.fully_resolved;2105 const new = ip.getNav(nav_id).resolved.?;
2128 const new_is_extern_decl = ip.indexToKey(new.val) == .@"extern";2106 return if (old_nav.resolved) |old| .{
2129 const changed = switch (old_nav.status) {2107 .type_changed = old.type != new.type or
2130 .unresolved => true,2108 old.@"align" != new.@"align" or
2131 .type_resolved => |r| r.type != ip.typeOf(new.val) or2109 old.@"linksection" != new.@"linksection" or
2132 r.alignment != new.alignment or2110 old.@"addrspace" != new.@"addrspace" or
2133 r.@"linksection" != new.@"linksection" or2111 old.@"const" != new.@"const" or
2134 r.@"addrspace" != new.@"addrspace" or2112 old.@"threadlocal" != new.@"threadlocal" or
2135 r.is_const != new.is_const or2113 old.is_extern_decl != new.is_extern_decl,
2136 r.is_extern_decl != new_is_extern_decl,2114 } else .{ .type_changed = true };
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 };
2145 };2115 };
21462116
2147 block.comptime_reason = .{ .reason = .{2117 block.comptime_reason = .{ .reason = .{
...@@ -2169,37 +2139,34 @@ fn analyzeNavType(...@@ -2169,37 +2139,34 @@ fn analyzeNavType(
21692139
2170 const is_extern_decl = zir_decl.linkage == .@"extern";2140 const is_extern_decl = zir_decl.linkage == .@"extern";
21712141
2172 // Now for the question of the day: are the type and modifiers the same as before?2142 // Now for the question of the day: are the type and modifiers the same as before? If they are,
2173 // If they are, then we should actually keep the `Nav` as `fully_resolved` if it currently is.2143 // then we should actually avoid calling `ip.resolveNav`. This is because `analyzeNavVal` will
2174 // That's because `analyzeNavVal` will later want to look at the resolved value to figure out2144 // later wanmt to look at the resolved *value* to figure out whether *that* has changed: if we
2175 // whether it's changed: if we threw that data away now, it would have to assume that the value2145 // threw that data away now, it would have to assume the value *had* changed even if it actually
2176 // had changed, potentially spinning off loads of unnecessary re-analysis!2146 // hadn't, which could spin off a bunch of unnecessary re-analysis! OTOH, if the type *has*
2177 const changed = switch (old_nav.status) {2147 // changed, then we obviously know that the value will also have changed, so resetting the value
2178 .unresolved => true,2148 // to `.none` is fine in that case.
2179 .type_resolved => |r| r.type != resolved_ty.toIntern() or2149 const changed: bool = if (old_nav.resolved) |old| changed: {
2180 r.alignment != modifiers.alignment or2150 break :changed old.type != resolved_ty.toIntern() or
2181 r.@"linksection" != modifiers.@"linksection" or2151 old.@"align" != modifiers.@"align" or
2182 r.@"addrspace" != modifiers.@"addrspace" or2152 old.@"linksection" != modifiers.@"linksection" or
2183 r.is_const != is_const or2153 old.@"addrspace" != modifiers.@"addrspace" or
2184 r.is_extern_decl != is_extern_decl,2154 old.@"const" != is_const or
2185 .fully_resolved => |r| ip.typeOf(r.val) != resolved_ty.toIntern() or2155 old.@"threadlocal" != zir_decl.is_threadlocal or
2186 r.alignment != modifiers.alignment or2156 old.is_extern_decl != is_extern_decl;
2187 r.@"linksection" != modifiers.@"linksection" or2157 } else true;
2188 r.@"addrspace" != modifiers.@"addrspace" or
2189 r.is_const != is_const or
2190 (old_nav.getExtern(ip) != null) != is_extern_decl,
2191 };
21922158
2193 if (!changed) return .{ .type_changed = false };2159 if (!changed) return .{ .type_changed = false };
21942160
2195 ip.resolveNavType(io, nav_id, .{2161 ip.resolveNav(io, nav_id, .{
2196 .type = resolved_ty.toIntern(),2162 .type = resolved_ty.toIntern(),
2197 .is_const = is_const,2163 .@"align" = modifiers.@"align",
2198 .alignment = modifiers.alignment,
2199 .@"linksection" = modifiers.@"linksection",2164 .@"linksection" = modifiers.@"linksection",
2200 .@"addrspace" = modifiers.@"addrspace",2165 .@"addrspace" = modifiers.@"addrspace",
2201 .is_threadlocal = zir_decl.is_threadlocal,2166 .@"const" = is_const,
2167 .@"threadlocal" = zir_decl.is_threadlocal,
2202 .is_extern_decl = is_extern_decl,2168 .is_extern_decl = is_extern_decl,
2169 .value = .none,
2203 });2170 });
22042171
2205 return .{ .type_changed = true };2172 return .{ .type_changed = true };
...@@ -3358,13 +3325,13 @@ fn analyzeFuncBodyInner(...@@ -3358,13 +3325,13 @@ fn analyzeFuncBodyInner(
33583325
3359 if (func.generic_owner == .none) {3326 if (func.generic_owner == .none) {
3360 try pt.ensureNavValUpToDate(func.owner_nav, reason);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 return error.AnalysisFail;3329 return error.AnalysisFail;
3363 }3330 }
3364 } else {3331 } else {
3365 const go_nav = zcu.funcInfo(func.generic_owner).owner_nav;3332 const go_nav = zcu.funcInfo(func.generic_owner).owner_nav;
3366 try pt.ensureNavValUpToDate(go_nav, reason);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 return error.AnalysisFail;3335 return error.AnalysisFail;
3369 }3336 }
3370 }3337 }
...@@ -3757,9 +3724,9 @@ fn processExportsInner(...@@ -3757,9 +3724,9 @@ fn processExportsInner(
3757 if (zcu.failed_analysis.contains(unit)) break :failed true;3724 if (zcu.failed_analysis.contains(unit)) break :failed true;
3758 if (zcu.transitive_failed_analysis.contains(unit)) break :failed true;3725 if (zcu.transitive_failed_analysis.contains(unit)) break :failed true;
3759 }3726 }
3760 const val = switch (nav.status) {3727 const val: Value = switch ((nav.resolved orelse break :failed true).value) {
3761 .unresolved, .type_resolved => break :failed true,3728 .none => break :failed true,
3762 .fully_resolved => |r| Value.fromInterned(r.val),3729 else => |val| .fromInterned(val),
3763 };3730 };
3764 // If the value is a function, we also need to check if that function succeeded analysis.3731 // If the value is a function, we also need to check if that function succeeded analysis.
3765 if (val.typeOf(zcu).zigTypeTag(zcu) == .@"fn") {3732 if (val.typeOf(zcu).zigTypeTag(zcu) == .@"fn") {
...@@ -3805,14 +3772,16 @@ pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void {...@@ -3805,14 +3772,16 @@ pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void {
3805 if (builtin_root_type == .none) return; // `@import("builtin")` never analyzed3772 if (builtin_root_type == .none) return; // `@import("builtin")` never analyzed
3806 const builtin_namespace = Type.fromInterned(builtin_root_type).getNamespace(zcu).unwrap().?;3773 const builtin_namespace = Type.fromInterned(builtin_root_type).getNamespace(zcu).unwrap().?;
3807 // We know that the namespace has a `test_functions`...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 try ip.getOrPutString(gpa, io, pt.tid, "test_functions", .no_embedded_nulls),3776 try ip.getOrPutString(gpa, io, pt.tid, "test_functions", .no_embedded_nulls),
3810 Zcu.Namespace.NameAdapter{ .zcu = zcu },3777 Zcu.Namespace.NameAdapter{ .zcu = zcu },
3811 ).?;3778 ).?;
3779 const test_fns_nav = ip.getNav(test_fns_nav_index);
3812 // ...but it might not be populated, so let's check that!3780 // ...but it might not be populated, so let's check that!
3813 if (zcu.failed_analysis.contains(.wrap(.{ .nav_val = nav_index })) or3781 if (zcu.failed_analysis.contains(.wrap(.{ .nav_val = test_fns_nav_index })) or
3814 zcu.transitive_failed_analysis.contains(.wrap(.{ .nav_val = nav_index })) or3782 zcu.transitive_failed_analysis.contains(.wrap(.{ .nav_val = test_fns_nav_index })) or
3815 ip.getNav(nav_index).status != .fully_resolved)3783 test_fns_nav.resolved == null or
3784 test_fns_nav.resolved.?.value == .none)
3816 {3785 {
3817 // The value of `builtin.test_functions` was either never referenced, or failed analysis.3786 // The value of `builtin.test_functions` was either never referenced, or failed analysis.
3818 // Either way, we don't need to do anything.3787 // Either way, we don't need to do anything.
...@@ -3822,8 +3791,7 @@ pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void {...@@ -3822,8 +3791,7 @@ pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void {
3822 // Okay, `builtin.test_functions` is (potentially) referenced and valid. Our job now is to swap3791 // Okay, `builtin.test_functions` is (potentially) referenced and valid. Our job now is to swap
3823 // its placeholder `&.{}` value for the actual list of all test functions.3792 // its placeholder `&.{}` value for the actual list of all test functions.
38243793
3825 const test_fns_val = zcu.navValue(nav_index);3794 const test_fn_ty = Type.fromInterned(test_fns_nav.resolved.?.type).slicePtrFieldType(zcu).childType(zcu);
3826 const test_fn_ty = test_fns_val.typeOf(zcu).slicePtrFieldType(zcu).childType(zcu);
38273795
3828 const array_anon_decl: InternPool.Key.Ptr.BaseAddr.Uav = array: {3796 const array_anon_decl: InternPool.Key.Ptr.BaseAddr.Uav = array: {
3829 // Add zcu.test_functions to an array decl then make the test_functions3797 // 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,10 +3882,12 @@ pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void {
3914 } }),3882 } }),
3915 .len = (try pt.intValue(Type.usize, zcu.test_functions.count())).toIntern(),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 // The linker thread is not running, so we actually need to dispatch this task directly.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}
39223892
3923/// Stores an error in `pt.zcu.failed_files` for this file, and sets the file3893/// 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,17 +4372,13 @@ pub fn intBitsForValue(pt: Zcu.PerThread, val: Value, sign: bool) u16 {
4402pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Error!Type {4372pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Error!Type {
4403 const zcu = pt.zcu;4373 const zcu = pt.zcu;
4404 const ip = &zcu.intern_pool;4374 const ip = &zcu.intern_pool;
4405 const ty, const alignment, const @"addrspace", const is_const = switch (ip.getNav(nav_id).status) {4375 const resolved_nav = ip.getNav(nav_id).resolved.?;
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 };
4410 return pt.ptrType(.{4376 return pt.ptrType(.{
4411 .child = ty,4377 .child = resolved_nav.type,
4412 .flags = .{4378 .flags = .{
4413 .alignment = alignment,4379 .alignment = resolved_nav.@"align",
4414 .address_space = @"addrspace",4380 .address_space = resolved_nav.@"addrspace",
4415 .is_const = is_const,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,7 +352,6 @@ pub fn generateSymbol(
352 else => unreachable,352 else => unreachable,
353 }),353 }),
354 },354 },
355 .variable,
356 .@"extern",355 .@"extern",
357 .func,356 .func,
358 .enum_literal,357 .enum_literal,
...@@ -787,7 +786,7 @@ fn lowerNavRef(...@@ -787,7 +786,7 @@ fn lowerNavRef(
787 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;786 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;
788 const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);787 const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);
789 const is_obj = lf.comp.config.output_mode == .Obj;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);
791790
792 if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) and ip.getNav(nav_index).getExtern(ip) == null) {791 if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) and ip.getNav(nav_index).getExtern(ip) == null) {
793 try w.splatByteAll(0xaa, ptr_width_bytes);792 try w.splatByteAll(0xaa, ptr_width_bytes);
...@@ -876,10 +875,11 @@ pub fn genNavRef(...@@ -876,10 +875,11 @@ pub fn genNavRef(
876 const nav = ip.getNav(nav_index);875 const nav = ip.getNav(nav_index);
877 log.debug("genNavRef({f})", .{nav.fqn.fmt(ip)});876 log.debug("genNavRef({f})", .{nav.fqn.fmt(ip)});
878877
879 const lib_name, const linkage, const is_threadlocal = if (nav.getExtern(ip)) |e|878 const is_threadlocal = nav.resolved.?.@"threadlocal" and zcu.comp.config.any_non_single_threaded;
880 .{ e.lib_name, e.linkage, e.is_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 else881 else
882 .{ .none, .internal, false };882 .{ .none, .internal };
883 if (lf.cast(.elf)) |elf_file| {883 if (lf.cast(.elf)) |elf_file| {
884 const zo = elf_file.zigObjectPtr().?;884 const zo = elf_file.zigObjectPtr().?;
885 switch (linkage) {885 switch (linkage) {
...@@ -1038,7 +1038,7 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo...@@ -1038,7 +1038,7 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo
10381038
1039 .nav => |nav_index| {1039 .nav => |nav_index| {
1040 const nav = ip.getNav(nav_index);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 if (nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) or nav.getExtern(ip) != null) {1042 if (nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) or nav.getExtern(ip) != null) {
1043 return .{ .lea_nav = nav_index };1043 return .{ .lea_nav = nav_index };
1044 } else {1044 } else {
src/codegen/aarch64/Mir.zig+1-1
...@@ -69,7 +69,7 @@ pub fn emit(...@@ -69,7 +69,7 @@ pub fn emit(
69 const target = &mod.resolved_target.result;69 const target = &mod.resolved_target.result;
70 mir_log.debug("{f}:", .{nav.fqn.fmt(ip)});70 mir_log.debug("{f}:", .{nav.fqn.fmt(ip)});
7171
72 const func_align = switch (nav.status.fully_resolved.alignment) {72 const func_align = switch (nav.resolved.?.@"align") {
73 .none => switch (mod.optimize_mode) {73 .none => switch (mod.optimize_mode) {
74 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),74 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),
75 .ReleaseSmall => target_util.minFunctionAlignment(target),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,7 +7207,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
7207 const ptr_ra = try ptr_vi.value.defReg(isel) orelse break :unused;7207 const ptr_ra = try ptr_vi.value.defReg(isel) orelse break :unused;
72087208
7209 const ty_nav = air.data(air.inst_index).ty_nav;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 false => {7211 false => {
7212 try isel.nav_relocs.append(gpa, .{7212 try isel.nav_relocs.append(gpa, .{
7213 .nav = ty_nav.nav,7213 .nav = ty_nav.nav,
...@@ -10577,7 +10577,6 @@ pub const Value = struct {...@@ -10577,7 +10577,6 @@ pub const Value = struct {
10577 => continue :type_key .{ .simple_type = .anyerror },10577 => continue :type_key .{ .simple_type = .anyerror },
10578 .undef,10578 .undef,
10579 .simple_value,10579 .simple_value,
10580 .variable,
10581 .@"extern",10580 .@"extern",
10582 .func,10581 .func,
10583 .int,10582 .int,
...@@ -10914,7 +10913,7 @@ pub const Value = struct {...@@ -10914,7 +10913,7 @@ pub const Value = struct {
10914 .ptr => |ptr| {10913 .ptr => |ptr| {
10915 assert(offset == 0 and size == 8);10914 assert(offset == 0 and size == 8);
10916 break :free switch (ptr.base_addr) {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 false => {10917 false => {
10919 try isel.nav_relocs.append(zcu.gpa, .{10918 try isel.nav_relocs.append(zcu.gpa, .{
10920 .nav = nav,10919 .nav = nav,
...@@ -12300,7 +12299,6 @@ pub const CallAbiIterator = struct {...@@ -12300,7 +12299,6 @@ pub const CallAbiIterator = struct {
12300 => continue :type_key .{ .simple_type = .anyerror },12299 => continue :type_key .{ .simple_type = .anyerror },
12301 .undef,12300 .undef,
12302 .simple_value,12301 .simple_value,
12303 .variable,
12304 .@"extern",12302 .@"extern",
12305 .func,12303 .func,
12306 .int,12304 .int,
src/codegen/c.zig+31-41
...@@ -669,11 +669,9 @@ pub const DeclGen = struct {...@@ -669,11 +669,9 @@ pub const DeclGen = struct {
669 return dg.renderUndefValue(w, ptr_ty, location);669 return dg.renderUndefValue(w, ptr_ty, location);
670 }670 }
671671
672 // Chase function values in order to be able to reference the original function.
673 switch (ip.indexToKey(uav.val)) {672 switch (ip.indexToKey(uav.val)) {
674 .variable => unreachable,673 .func => unreachable,
675 .func => |func| return dg.renderNav(w, func.owner_nav, location),674 .@"extern" => unreachable,
676 .@"extern" => |@"extern"| return dg.renderNav(w, @"extern".owner_nav, location),
677 else => {},675 else => {},
678 }676 }
679677
...@@ -721,10 +719,9 @@ pub const DeclGen = struct {...@@ -721,10 +719,9 @@ pub const DeclGen = struct {
721 const ip = &zcu.intern_pool;719 const ip = &zcu.intern_pool;
722720
723 // Chase function values in order to be able to reference the original function.721 // Chase function values in order to be able to reference the original function.
724 const owner_nav = switch (ip.getNav(nav_index).status) {722 const owner_nav = switch (ip.getNav(nav_index).resolved.?.value) {
725 .unresolved => unreachable,723 .none => nav_index, // this can't be an extern or a function
726 .type_resolved => nav_index, // this can't be an extern or a function724 else => |value| switch (ip.indexToKey(value)) {
727 .fully_resolved => |r| switch (ip.indexToKey(r.val)) {
728 .func => |f| f.owner_nav,725 .func => |f| f.owner_nav,
729 .@"extern" => |e| e.owner_nav,726 .@"extern" => |e| e.owner_nav,
730 else => nav_index,727 else => nav_index,
...@@ -732,7 +729,7 @@ pub const DeclGen = struct {...@@ -732,7 +729,7 @@ pub const DeclGen = struct {
732 };729 };
733730
734 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.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 const ptr_ty = try pt.navPtrType(owner_nav);733 const ptr_ty = try pt.navPtrType(owner_nav);
737 if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {734 if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
738 return dg.renderUndefValue(w, ptr_ty, location);735 return dg.renderUndefValue(w, ptr_ty, location);
...@@ -924,7 +921,6 @@ pub const DeclGen = struct {...@@ -924,7 +921,6 @@ pub const DeclGen = struct {
924 .false => try w.writeAll("false"),921 .false => try w.writeAll("false"),
925 .true => try w.writeAll("true"),922 .true => try w.writeAll("true"),
926 },923 },
927 .variable,
928 .@"extern",924 .@"extern",
929 .func,925 .func,
930 .enum_literal,926 .enum_literal,
...@@ -1575,7 +1571,6 @@ pub const DeclGen = struct {...@@ -1575,7 +1571,6 @@ pub const DeclGen = struct {
15751571
1576 .undef,1572 .undef,
1577 .simple_value,1573 .simple_value,
1578 .variable,
1579 .@"extern",1574 .@"extern",
1580 .func,1575 .func,
1581 .int,1576 .int,
...@@ -2276,13 +2271,13 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E...@@ -2276,13 +2271,13 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E
2276 try f.dg.renderFunctionSignature(2271 try f.dg.renderFunctionSignature(
2277 fwd_decl_writer,2272 fwd_decl_writer,
2278 nav_val,2273 nav_val,
2279 nav.status.fully_resolved.alignment,2274 nav.resolved.?.@"align",
2280 .forward_decl,2275 .forward_decl,
2281 .{ .nav = nav_index },2276 .{ .nav = nav_index },
2282 );2277 );
2283 try fwd_decl_writer.writeAll(";\n");2278 try fwd_decl_writer.writeAll(";\n");
22842279
2285 if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |s|2280 if (nav.resolved.?.@"linksection".toSlice(ip)) |s|
2286 try header_writer.print("zig_linksection_fn({f}) ", .{fmtStringLiteral(s, null)});2281 try header_writer.print("zig_linksection_fn({f}) ", .{fmtStringLiteral(s, null)});
2287 try f.dg.renderFunctionSignature(2282 try f.dg.renderFunctionSignature(
2288 header_writer,2283 header_writer,
...@@ -2360,28 +2355,26 @@ pub fn genDecl(dg: *DeclGen, w: *Writer) Error!void {...@@ -2360,28 +2355,26 @@ pub fn genDecl(dg: *DeclGen, w: *Writer) Error!void {
2360 const zcu = pt.zcu;2355 const zcu = pt.zcu;
2361 const ip = &zcu.intern_pool;2356 const ip = &zcu.intern_pool;
2362 const nav = ip.getNav(dg.owner_nav.unwrap().?);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);
23642359
2365 const is_const: bool, const is_threadlocal: bool, const init_val: Value = switch (ip.indexToKey(nav.status.fully_resolved.val)) {2360 if (ip.indexToKey(nav.resolved.?.value) == .@"extern") return;
2366 else => .{ true, false, .fromInterned(nav.status.fully_resolved.val) },
2367 .variable => |v| .{ false, v.is_threadlocal, .fromInterned(v.init) },
2368 .@"extern" => return,
2369 };
23702361
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 try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)});2365 try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)});
2373 }2366 }
23742367
2375 // We don't bother underaligning---it's unnecessary and hurts compatibility.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 if (a != .none and a.compareStrict(.gt, nav_ty.abiAlignment(zcu))) {2370 if (a != .none and a.compareStrict(.gt, nav_ty.abiAlignment(zcu))) {
2378 try w.print("zig_align({d}) ", .{a.toByteUnits().?});2371 try w.print("zig_align({d}) ", .{a.toByteUnits().?});
2379 }2372 }
23802373
2381 try genDeclValue(dg, w, .{2374 try genDeclValue(dg, w, .{
2382 .name = .{ .nav = dg.owner_nav.unwrap().? },2375 .name = .{ .nav = dg.owner_nav.unwrap().? },
2383 .@"const" = is_const,2376 .@"const" = nav.resolved.?.@"const",
2384 .@"threadlocal" = is_threadlocal,2377 .@"threadlocal" = nav.resolved.?.@"threadlocal",
2385 .init_val = init_val,2378 .init_val = init_val,
2386 });2379 });
2387}2380}
...@@ -2393,19 +2386,18 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void {...@@ -2393,19 +2386,18 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void {
2393 const zcu = pt.zcu;2386 const zcu = pt.zcu;
2394 const ip = &zcu.intern_pool;2387 const ip = &zcu.intern_pool;
2395 const nav = ip.getNav(dg.owner_nav.unwrap().?);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);
23972390
2398 const is_const: bool, const is_threadlocal: bool, const init_val: Value = switch (ip.indexToKey(nav.status.fully_resolved.val)) {2391 const init_val: Value = switch (ip.indexToKey(nav.resolved.?.value)) {
2399 else => .{ true, false, .fromInterned(nav.status.fully_resolved.val) },2392 else => .fromInterned(nav.resolved.?.value),
2400 .variable => |v| .{ false, v.is_threadlocal, .fromInterned(v.init) },
24012393
2402 .@"extern" => |@"extern"| switch (nav_ty.zigTypeTag(zcu)) {2394 .@"extern" => |@"extern"| switch (nav_ty.zigTypeTag(zcu)) {
2403 .@"fn" => {2395 .@"fn" => {
2404 try w.writeAll("zig_extern ");2396 try w.writeAll("zig_extern ");
2405 try dg.renderFunctionSignature(2397 try dg.renderFunctionSignature(
2406 w,2398 w,
2407 Value.fromInterned(nav.status.fully_resolved.val),2399 .fromInterned(nav.resolved.?.value),
2408 nav.status.fully_resolved.alignment,2400 nav.resolved.?.@"align",
2409 .forward_decl,2401 .forward_decl,
2410 .{ .@"export" = .{2402 .{ .@"export" = .{
2411 .main_name = nav.name,2403 .main_name = nav.name,
...@@ -2422,15 +2414,15 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void {...@@ -2422,15 +2414,15 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void {
2422 .weak => try w.print("zig_extern zig_weak_linkage zig_visibility({t}) ", .{@"extern".visibility}),2414 .weak => try w.print("zig_extern zig_weak_linkage zig_visibility({t}) ", .{@"extern".visibility}),
2423 .link_once => return dg.fail("TODO: CBE: implement linkonce linkage?", .{}),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 try w.writeAll("zig_threadlocal ");2418 try w.writeAll("zig_threadlocal ");
2427 }2419 }
2428 try dg.renderTypeAndName(2420 try dg.renderTypeAndName(
2429 w,2421 w,
2430 .fromInterned(nav.typeOf(ip)),2422 .fromInterned(nav.resolved.?.type),
2431 .{ .nav = dg.owner_nav.unwrap().? },2423 .{ .nav = dg.owner_nav.unwrap().? },
2432 .{ .@"const" = @"extern".is_const },2424 .{ .@"const" = nav.resolved.?.@"const" },
2433 nav.getAlignment(),2425 nav.resolved.?.@"align",
2434 );2426 );
2435 try w.writeAll(";\n");2427 try w.writeAll(";\n");
2436 return;2428 return;
...@@ -2439,15 +2431,15 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void {...@@ -2439,15 +2431,15 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void {
2439 };2431 };
24402432
2441 // We don't bother underaligning---it's unnecessary and hurts compatibility.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 if (a != .none and a.compareStrict(.gt, nav_ty.abiAlignment(zcu))) {2435 if (a != .none and a.compareStrict(.gt, nav_ty.abiAlignment(zcu))) {
2444 try w.print("zig_align({d}) ", .{a.toByteUnits().?});2436 try w.print("zig_align({d}) ", .{a.toByteUnits().?});
2445 }2437 }
24462438
2447 try genDeclValueFwd(dg, w, .{2439 try genDeclValueFwd(dg, w, .{
2448 .name = .{ .nav = dg.owner_nav.unwrap().? },2440 .name = .{ .nav = dg.owner_nav.unwrap().? },
2449 .@"const" = is_const,2441 .@"const" = nav.resolved.?.@"const",
2450 .@"threadlocal" = is_threadlocal,2442 .@"threadlocal" = nav.resolved.?.@"threadlocal",
2451 .init_val = init_val,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,11 +2506,9 @@ pub fn genExports(dg: *DeclGen, w: *Writer, exported: Zcu.Exported, export_indic
2514 );2506 );
2515 try w.writeAll(";\n");2507 try w.writeAll(";\n");
2516 };2508 };
2517 const is_const = switch (ip.indexToKey(exported_val.toIntern())) {2509 const is_const = switch (exported) {
2518 .func => unreachable,2510 .nav => |nav| ip.getNav(nav).resolved.?.@"const",
2519 .@"extern" => |@"extern"| @"extern".is_const,2511 .uav => true,
2520 .variable => false,
2521 else => true,
2522 };2512 };
2523 for (export_indices) |export_index| {2513 for (export_indices) |export_index| {
2524 const @"export" = export_index.ptr(zcu);2514 const @"export" = export_index.ptr(zcu);
src/codegen/c/type.zig-1
...@@ -990,7 +990,6 @@ pub const CType = union(enum) {...@@ -990,7 +990,6 @@ pub const CType = union(enum) {
990 // values, not types990 // values, not types
991 .undef,991 .undef,
992 .simple_value,992 .simple_value,
993 .variable,
994 .@"extern",993 .@"extern",
995 .func,994 .func,
996 .int,995 .int,
src/codegen/llvm.zig+27-34
...@@ -1279,7 +1279,7 @@ pub const Object = struct {...@@ -1279,7 +1279,7 @@ pub const Object = struct {
1279 } }, &o.builder);1279 } }, &o.builder);
1280 }1280 }
12811281
1282 if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |section|1282 if (nav.resolved.?.@"linksection".toSlice(ip)) |section|
1283 function_index.setSection(try o.builder.string(section), &o.builder);1283 function_index.setSection(try o.builder.string(section), &o.builder);
12841284
1285 var deinit_wip = true;1285 var deinit_wip = true;
...@@ -1487,7 +1487,7 @@ pub const Object = struct {...@@ -1487,7 +1487,7 @@ pub const Object = struct {
1487 const file = try o.getDebugFile(pt, file_scope);1487 const file = try o.getDebugFile(pt, file_scope);
14881488
1489 const line_number = zcu.navSrcLine(func.owner_nav) + 1;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 const debug_decl_type = try o.getDebugType(pt, fn_ty);1491 const debug_decl_type = try o.getDebugType(pt, fn_ty);
14921492
1493 const subprogram = try o.builder.debugSubprogram(1493 const subprogram = try o.builder.debugSubprogram(
...@@ -1662,7 +1662,7 @@ pub const Object = struct {...@@ -1662,7 +1662,7 @@ pub const Object = struct {
1662 .elf, .wasm => break :coff_export_flags,1662 .elf, .wasm => break :coff_export_flags,
1663 .coff => |*coff| coff,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 const flags = &coff.lld_export_flags;1666 const flags = &coff.lld_export_flags;
1667 for (export_indices) |export_index| {1667 for (export_indices) |export_index| {
1668 const name = export_index.ptr(zcu).opts.name;1668 const name = export_index.ptr(zcu).opts.name;
...@@ -2677,7 +2677,7 @@ pub const Object = struct {...@@ -2677,7 +2677,7 @@ pub const Object = struct {
2677 const gpa = o.gpa;2677 const gpa = o.gpa;
2678 const nav = ip.getNav(nav_index);2678 const nav = ip.getNav(nav_index);
2679 const owner_mod = zcu.navFileScope(nav_index).mod.?;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 const gop = try o.nav_map.getOrPut(gpa, nav_index);2681 const gop = try o.nav_map.getOrPut(gpa, nav_index);
2682 if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function;2682 if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function;
26832683
...@@ -2692,7 +2692,7 @@ pub const Object = struct {...@@ -2692,7 +2692,7 @@ pub const Object = struct {
2692 const function_index = try o.builder.addFunction(2692 const function_index = try o.builder.addFunction(
2693 try o.lowerType(pt, ty),2693 try o.lowerType(pt, ty),
2694 try o.builder.strtabString((if (is_extern) nav.name else nav.fqn).toSlice(ip)),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 gop.value_ptr.* = function_index.ptrConst(&o.builder).global;2697 gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
26982698
...@@ -2809,8 +2809,8 @@ pub const Object = struct {...@@ -2809,8 +2809,8 @@ pub const Object = struct {
2809 }2809 }
2810 }2810 }
28112811
2812 if (nav.getAlignment() != .none)2812 if (nav.resolved.?.@"align" != .none)
2813 function_index.setAlignment(nav.getAlignment().toLlvm(), &o.builder);2813 function_index.setAlignment(nav.resolved.?.@"align".toLlvm(), &o.builder);
28142814
2815 // Function attributes that are independent of analysis results of the function body.2815 // Function attributes that are independent of analysis results of the function body.
2816 try o.addCommonFnAttributes(2816 try o.addCommonFnAttributes(
...@@ -2951,15 +2951,12 @@ pub const Object = struct {...@@ -2951,15 +2951,12 @@ pub const Object = struct {
2951 const zcu = pt.zcu;2951 const zcu = pt.zcu;
2952 const ip = &zcu.intern_pool;2952 const ip = &zcu.intern_pool;
2953 const nav = ip.getNav(nav_index);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) {2954 const linkage: std.builtin.GlobalLinkage, const visibility: Builder.Visibility, const is_dll_import: bool = switch (nav.resolved.?.value) {
2955 .unresolved => unreachable,2955 .none => .{ .internal, .default, false }, // this is a source declaration which is *not* marked `extern`
2956 .fully_resolved => |r| switch (ip.indexToKey(r.val)) {2956 else => |val| switch (ip.indexToKey(val)) {
2957 .variable => |variable| .{ .internal, .default, variable.is_threadlocal, false },2957 else => .{ .internal, .default, false },
2958 .@"extern" => |@"extern"| .{ @"extern".linkage, .fromSymbolVisibility(@"extern".visibility), @"extern".is_threadlocal, @"extern".is_dll_import },2958 .@"extern" => |e| .{ e.linkage, .fromSymbolVisibility(e.visibility), e.is_dll_import },
2959 else => .{ .internal, .default, false, false },
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 };
29642961
2965 const variable_index = try o.builder.addVariable(2962 const variable_index = try o.builder.addVariable(
...@@ -2968,8 +2965,8 @@ pub const Object = struct {...@@ -2968,8 +2965,8 @@ pub const Object = struct {
2968 .strong, .weak => nav.name,2965 .strong, .weak => nav.name,
2969 .link_once => unreachable,2966 .link_once => unreachable,
2970 }.toSlice(ip)),2967 }.toSlice(ip)),
2971 try o.lowerType(pt, Type.fromInterned(nav.typeOf(ip))),2968 try o.lowerType(pt, .fromInterned(nav.resolved.?.type)),
2972 toLlvmGlobalAddressSpace(nav.getAddrspace(), zcu.getTarget()),2969 toLlvmGlobalAddressSpace(nav.resolved.?.@"addrspace", zcu.getTarget()),
2973 );2970 );
2974 gop.value_ptr.* = variable_index.ptrConst(&o.builder).global;2971 gop.value_ptr.* = variable_index.ptrConst(&o.builder).global;
29752972
...@@ -2987,7 +2984,7 @@ pub const Object = struct {...@@ -2987,7 +2984,7 @@ pub const Object = struct {
2987 .link_once => unreachable,2984 .link_once => unreachable,
2988 }, &o.builder);2985 }, &o.builder);
2989 variable_index.setUnnamedAddr(.default, &o.builder);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 variable_index.setThreadLocal(.generaldynamic, &o.builder);2988 variable_index.setThreadLocal(.generaldynamic, &o.builder);
2992 if (is_dll_import) variable_index.setDllStorageClass(.dllimport, &o.builder);2989 if (is_dll_import) variable_index.setDllStorageClass(.dllimport, &o.builder);
2993 },2990 },
...@@ -3422,7 +3419,6 @@ pub const Object = struct {...@@ -3422,7 +3419,6 @@ pub const Object = struct {
3422 // values, not types3419 // values, not types
3423 .undef,3420 .undef,
3424 .simple_value,3421 .simple_value,
3425 .variable,
3426 .@"extern",3422 .@"extern",
3427 .func,3423 .func,
3428 .int,3424 .int,
...@@ -3553,9 +3549,7 @@ pub const Object = struct {...@@ -3553,9 +3549,7 @@ pub const Object = struct {
3553 .false => .false,3549 .false => .false,
3554 .true => .true,3550 .true => .true,
3555 },3551 },
3556 .variable,3552 .enum_literal => unreachable, // non-runtime value
3557 .enum_literal,
3558 => unreachable, // non-runtime values
3559 .@"extern" => |@"extern"| {3553 .@"extern" => |@"extern"| {
3560 const function_index = try o.resolveLlvmFunction(pt, @"extern".owner_nav);3554 const function_index = try o.resolveLlvmFunction(pt, @"extern".owner_nav);
3561 return function_index.ptrConst(&o.builder).global.toConst();3555 return function_index.ptrConst(&o.builder).global.toConst();
...@@ -4131,7 +4125,7 @@ pub const Object = struct {...@@ -4131,7 +4125,7 @@ pub const Object = struct {
41314125
4132 const nav = ip.getNav(nav_index);4126 const nav = ip.getNav(nav_index);
41334127
4134 const nav_ty = Type.fromInterned(nav.typeOf(ip));4128 const nav_ty: Type = .fromInterned(nav.resolved.?.type);
4135 const ptr_ty = try pt.navPtrType(nav_index);4129 const ptr_ty = try pt.navPtrType(nav_index);
41364130
4137 if (nav.getExtern(ip) == null and !nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {4131 if (nav.getExtern(ip) == null and !nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
...@@ -4145,7 +4139,7 @@ pub const Object = struct {...@@ -4145,7 +4139,7 @@ pub const Object = struct {
41454139
4146 const llvm_val = try o.builder.convConst(4140 const llvm_val = try o.builder.convConst(
4147 llvm_global.toConst(),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 );
41504144
4151 return o.builder.convConst(llvm_val, try o.lowerType(pt, ptr_ty));4145 return o.builder.convConst(llvm_val, try o.lowerType(pt, ptr_ty));
...@@ -4398,14 +4392,13 @@ pub const NavGen = struct {...@@ -4398,14 +4392,13 @@ pub const NavGen = struct {
4398 const ip = &zcu.intern_pool;4392 const ip = &zcu.intern_pool;
4399 const nav_index = ng.nav_index;4393 const nav_index = ng.nav_index;
4400 const nav = ip.getNav(nav_index);4394 const nav = ip.getNav(nav_index);
4401 const resolved = nav.status.fully_resolved;4395 const resolved = nav.resolved.?;
44024396
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)) {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)) {
4404 .variable => |variable| .{ .none, .internal, .default, variable.is_threadlocal, false, false, variable.init, variable.owner_nav },4398 else => .{ .none, .internal, .default, false, resolved.value, nav_index },
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 },4399 .@"extern" => |e| .{ e.lib_name, e.linkage, .fromSymbolVisibility(e.visibility), e.is_dll_import, .none, e.owner_nav },
4406 else => .{ .none, .internal, .default, false, false, true, resolved.val, nav_index },
4407 };4400 };
4408 const ty = Type.fromInterned(nav.typeOf(ip));4401 const ty: Type = .fromInterned(nav.resolved.?.type);
44094402
4410 if (linkage != .internal and ip.isFunctionType(ty.toIntern())) {4403 if (linkage != .internal and ip.isFunctionType(ty.toIntern())) {
4411 const function_index = try o.resolveLlvmFunction(pt, owner_nav);4404 const function_index = try o.resolveLlvmFunction(pt, owner_nav);
...@@ -4448,7 +4441,7 @@ pub const NavGen = struct {...@@ -4448,7 +4441,7 @@ pub const NavGen = struct {
4448 variable_index.setAlignment(zcu.navAlignment(nav_index).toLlvm(), &o.builder);4441 variable_index.setAlignment(zcu.navAlignment(nav_index).toLlvm(), &o.builder);
4449 if (resolved.@"linksection".toSlice(ip)) |section|4442 if (resolved.@"linksection".toSlice(ip)) |section|
4450 variable_index.setSection(try o.builder.string(section), &o.builder);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 try variable_index.setInitializer(switch (init_val) {4445 try variable_index.setInitializer(switch (init_val) {
4453 .none => .no_init,4446 .none => .no_init,
4454 else => try o.lowerValue(pt, init_val),4447 else => try o.lowerValue(pt, init_val),
...@@ -4457,7 +4450,7 @@ pub const NavGen = struct {...@@ -4457,7 +4450,7 @@ pub const NavGen = struct {
44574450
4458 const file_scope = zcu.navFileScopeIndex(nav_index);4451 const file_scope = zcu.navFileScopeIndex(nav_index);
4459 const mod = zcu.fileByIndex(file_scope).mod.?;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 variable_index.setThreadLocal(.generaldynamic, &o.builder);4454 variable_index.setThreadLocal(.generaldynamic, &o.builder);
44624455
4463 const line_number = zcu.navSrcLine(nav_index) + 1;4456 const line_number = zcu.navSrcLine(nav_index) + 1;
...@@ -5475,7 +5468,7 @@ pub const FuncGen = struct {...@@ -5475,7 +5468,7 @@ pub const FuncGen = struct {
5475 _ = try self.wip.retVoid();5468 _ = try self.wip.retVoid();
5476 return;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 if (!ret_ty.hasRuntimeBits(zcu)) {5472 if (!ret_ty.hasRuntimeBits(zcu)) {
5480 if (Type.fromInterned(fn_info.return_type).isError(zcu)) {5473 if (Type.fromInterned(fn_info.return_type).isError(zcu)) {
5481 // Functions with an empty error set are emitted with an error code5474 // Functions with an empty error set are emitted with an error code
...@@ -5540,7 +5533,7 @@ pub const FuncGen = struct {...@@ -5540,7 +5533,7 @@ pub const FuncGen = struct {
5540 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;5533 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
5541 const ptr_ty = self.typeOf(un_op);5534 const ptr_ty = self.typeOf(un_op);
5542 const ret_ty = ptr_ty.childType(zcu);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 if (!ret_ty.hasRuntimeBits(zcu)) {5537 if (!ret_ty.hasRuntimeBits(zcu)) {
5545 if (Type.fromInterned(fn_info.return_type).isError(zcu)) {5538 if (Type.fromInterned(fn_info.return_type).isError(zcu)) {
5546 // Functions with an empty error set are emitted with an error code5539 // 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,7 +256,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {
256 .global => {256 .global => {
257 const key = ip.indexToKey(val.toIntern()).@"extern";257 const key = ip.indexToKey(val.toIntern()).@"extern";
258258
259 const storage_class = cg.module.storageClass(nav.getAddrspace());259 const storage_class = cg.module.storageClass(nav.resolved.?.@"addrspace");
260 assert(storage_class != .generic); // These should be instance globals260 assert(storage_class != .generic); // These should be instance globals
261261
262 const ty_id = try cg.resolveType(ty, .indirect);262 const ty_id = try cg.resolveType(ty, .indirect);
...@@ -314,64 +314,47 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {...@@ -314,64 +314,47 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {
314 try cg.module.debugName(result_id, nav.fqn.toSlice(ip));314 try cg.module.debugName(result_id, nav.fqn.toSlice(ip));
315 },315 },
316 .invocation_global => {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 const ty_id = try cg.resolveType(ty, .indirect);317 const ty_id = try cg.resolveType(ty, .indirect);
325 const ptr_ty_id = try cg.module.ptrType(ty_id, .function);318 const ptr_ty_id = try cg.module.ptrType(ty_id, .function);
326319
327 if (maybe_init_val) |init_val| {320 // TODO: Combine with resolveAnonDecl?
328 // TODO: Combine with resolveAnonDecl?321 const void_ty_id = try cg.resolveType(.void, .direct);
329 const void_ty_id = try cg.resolveType(.void, .direct);322 const initializer_proto_ty_id = try cg.module.functionType(void_ty_id, &.{});
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 });
339323
340 const root_block_id = cg.module.allocId();324 const initializer_id = cg.module.allocId();
341 try cg.prologue.emit(gpa, .OpLabel, .{325 try cg.prologue.emit(gpa, .OpFunction, .{
342 .id_result = root_block_id,326 .id_result_type = try cg.resolveType(.void, .direct),
343 });327 .id_result = initializer_id,
344 cg.block_label = root_block_id;328 .function_control = .{},
329 .function_type = initializer_proto_ty_id,
330 });
345331
346 const val_id = try cg.constant(ty, init_val, .indirect);332 const root_block_id = cg.module.allocId();
347 try cg.body.emit(gpa, .OpStore, .{333 try cg.prologue.emit(gpa, .OpLabel, .{
348 .pointer = result_id,334 .id_result = root_block_id,
349 .object = val_id,335 });
350 });336 cg.block_label = root_block_id;
351337
352 try cg.body.emit(gpa, .OpReturn, {});338 const val_id = try cg.constant(ty, val, .indirect);
353 try cg.body.emit(gpa, .OpFunctionEnd, {});339 try cg.body.emit(gpa, .OpStore, .{
354 try cg.module.sections.functions.append(gpa, cg.prologue);340 .pointer = result_id,
355 try cg.module.sections.functions.append(gpa, cg.body);341 .object = val_id,
342 });
356343
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);
358348
359 try cg.module.sections.globals.emit(gpa, .OpExtInst, .{349 try cg.module.debugNameFmt(initializer_id, "initializer of {f}", .{nav.fqn.fmt(ip)});
360 .id_result_type = ptr_ty_id,350
361 .id_result = result_id,351 try cg.module.sections.globals.emit(gpa, .OpExtInst, .{
362 .set = try cg.module.importInstructionSet(.zig),352 .id_result_type = ptr_ty_id,
363 .instruction = .{ .inst = @intFromEnum(spec.Zig.InvocationGlobal) },353 .id_result = result_id,
364 .id_ref_4 = &.{initializer_id},354 .set = try cg.module.importInstructionSet(.zig),
365 });355 .instruction = .{ .inst = @intFromEnum(spec.Zig.InvocationGlobal) },
366 } else {356 .id_ref_4 = &.{initializer_id},
367 try cg.module.sections.globals.emit(gpa, .OpExtInst, .{357 });
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 }
375 },358 },
376 }359 }
377360
...@@ -810,7 +793,6 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id {...@@ -810,7 +793,6 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id {
810793
811 .undef => unreachable, // handled above794 .undef => unreachable, // handled above
812795
813 .variable,
814 .@"extern",796 .@"extern",
815 .func,797 .func,
816 .enum_literal,798 .enum_literal,
...@@ -1170,12 +1152,11 @@ fn constantNavRef(cg: *CodeGen, ty: Type, nav_index: InternPool.Nav.Index) !Id {...@@ -1170,12 +1152,11 @@ fn constantNavRef(cg: *CodeGen, ty: Type, nav_index: InternPool.Nav.Index) !Id {
1170 const ip = &zcu.intern_pool;1152 const ip = &zcu.intern_pool;
1171 const ty_id = try cg.resolveType(ty, .direct);1153 const ty_id = try cg.resolveType(ty, .direct);
1172 const nav = ip.getNav(nav_index);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);
11741156
1175 switch (nav.status) {1157 switch (nav.resolved.?.value) {
1176 .unresolved => unreachable,1158 .none => {}, // this is not a function or extern
1177 .type_resolved => {}, // this is not a function or extern1159 else => |value| switch (ip.indexToKey(value)) {
1178 .fully_resolved => |r| switch (ip.indexToKey(r.val)) {
1179 .func => {1160 .func => {
1180 // TODO: Properly lower function pointers. For now we are going to hack around it and1161 // TODO: Properly lower function pointers. For now we are going to hack around it and
1181 // just generate an empty pointer. Function pointers are represented by a pointer to usize.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,7 +1177,7 @@ fn constantNavRef(cg: *CodeGen, ty: Type, nav_index: InternPool.Nav.Index) !Id {
1196 const spv_decl_result_id = spv_decl.result_id;1177 const spv_decl_result_id = spv_decl.result_id;
1197 assert(spv_decl.kind != .func);1178 assert(spv_decl.kind != .func);
11981179
1199 const storage_class = cg.module.storageClass(nav.getAddrspace());1180 const storage_class = cg.module.storageClass(nav.resolved.?.@"addrspace");
1200 try cg.addFunctionDep(spv_decl_index, storage_class);1181 try cg.addFunctionDep(spv_decl_index, storage_class);
12011182
1202 const nav_ty_id = try cg.resolveType(nav_ty, .indirect);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,9 +252,9 @@ pub fn resolveNav(module: *Module, ip: *InternPool, nav_index: InternPool.Nav.In
252 if (!entry.found_existing) {252 if (!entry.found_existing) {
253 const nav = ip.getNav(nav_index);253 const nav = ip.getNav(nav_index);
254 // TODO: Extern fn?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 .func256 .func
257 else switch (nav.getAddrspace()) {257 else switch (nav.resolved.?.@"addrspace") {
258 .generic => .invocation_global,258 .generic => .invocation_global,
259 else => .global,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,7 +575,7 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {
575 .nav_ref => |nav_ref| {575 .nav_ref => |nav_ref| {
576 const zcu = cg.pt.zcu;576 const zcu = cg.pt.zcu;
577 const ip = &zcu.intern_pool;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 assert(nav_ref.offset == 0);579 assert(nav_ref.offset == 0);
580 try cg.mir_indirect_function_set.put(cg.gpa, nav_ref.nav_index, {});580 try cg.mir_indirect_function_set.put(cg.gpa, nav_ref.nav_index, {});
581 try cg.addInst(.{ .tag = .func_ref, .data = .{ .nav_index = nav_ref.nav_index } });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,7 +4401,6 @@ fn lowerConstant(cg: *CodeGen, val: Value) InnerError!WValue {
4401 else => unreachable,4401 else => unreachable,
4402 } },4402 } },
4403 },4403 },
4404 .variable,
4405 .@"extern",4404 .@"extern",
4406 .func,4405 .func,
4407 .enum_literal,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,7 +970,7 @@ fn navRefOff(wasm: *Wasm, code: *ArrayList(u8), data: Mir.NavRefOff, is_wasm32:
970 const ip = &zcu.intern_pool;970 const ip = &zcu.intern_pool;
971 const gpa = comp.gpa;971 const gpa = comp.gpa;
972 const is_obj = comp.config.output_mode == .Obj;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 assert(!ip.isFunctionType(nav_ty));974 assert(!ip.isFunctionType(nav_ty));
975975
976 try code.ensureUnusedCapacity(gpa, 11);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,7 +173046,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
173046 .runtime_nav_ptr => {173046 .runtime_nav_ptr => {
173047 const ty_nav = air_datas[@intFromEnum(inst)].ty_nav;173047 const ty_nav = air_datas[@intFromEnum(inst)].ty_nav;
173048 const nav = ip.getNav(ty_nav.nav);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";
173050173050
173051 if (is_threadlocal) switch (cg.target.ofmt) {173051 if (is_threadlocal) switch (cg.target.ofmt) {
173052 .elf => if (cg.mod.pic) {173052 .elf => if (cg.mod.pic) {
...@@ -179146,7 +179146,7 @@ fn genSetMem(...@@ -179146,7 +179146,7 @@ fn genSetMem(
179146 .off = disp,179146 .off = disp,
179147 }).compare(.gte, src_align),179147 }).compare(.gte, src_align),
179148 .table, .rip_inst, .lazy_sym, .extern_func => unreachable,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 .uav => |uav| Type.fromInterned(uav.orig_ty).ptrAlignment(zcu).compare(.gte, src_align),179150 .uav => |uav| Type.fromInterned(uav.orig_ty).ptrAlignment(zcu).compare(.gte, src_align),
179151 })).write(self, .{179151 })).write(self, .{
179152 .base = base,179152 .base = base,
src/codegen/x86_64/Emit.zig+16-23
...@@ -115,33 +115,26 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -115,33 +115,26 @@ pub fn emitMir(emit: *Emit) Error!void {
115 return error.EmitFail;115 return error.EmitFail;
116 },116 },
117 };117 };
118 break :target switch (ip.getNav(nav).status) {118 const resolved_nav = ip.getNav(nav).resolved.?;
119 .unresolved => unreachable,119 if (resolved_nav.value != .none) switch (ip.indexToKey(resolved_nav.value)) {
120 .type_resolved => |type_resolved| .{120 .@"extern" => |@"extern"| break :target .{
121 .index = sym_index,121 .index = sym_index,
122 .is_extern = false,122 .is_extern = switch (@"extern".visibility) {
123 .type = if (type_resolved.is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol,123 .default => true,
124 },124 .hidden, .protected => false,
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 },
137 },125 },
138 .variable => |variable| .{126 .type = if (resolved_nav.@"threadlocal" and comp.config.any_non_single_threaded) .tlv else .symbol,
139 .index = sym_index,127 .force_pcrel_direct = switch (@"extern".relocation) {
140 .is_extern = false,128 .any => false,
141 .type = if (variable.is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol,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 .uav => |uav| .{140 .uav => |uav| .{
src/link.zig+1-1
...@@ -781,7 +781,7 @@ pub const File = struct {...@@ -781,7 +781,7 @@ pub const File = struct {
781 fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateNavError!void {781 fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateNavError!void {
782 assert(base.comp.zcu.?.llvm_object == null);782 assert(base.comp.zcu.?.llvm_object == null);
783 const nav = pt.zcu.intern_pool.getNav(nav_index);783 const nav = pt.zcu.intern_pool.getNav(nav_index);
784 assert(nav.status == .fully_resolved);784 assert(nav.resolved.?.value != .none);
785 switch (base.tag) {785 switch (base.tag) {
786 .lld => unreachable,786 .lld => unreachable,
787 .plan9 => unreachable,787 .plan9 => unreachable,
src/link/C.zig+7-6
...@@ -534,11 +534,11 @@ pub fn updateNav(...@@ -534,11 +534,11 @@ pub fn updateNav(
534 const ip = &zcu.intern_pool;534 const ip = &zcu.intern_pool;
535535
536 const nav = ip.getNav(nav_index);536 const nav = ip.getNav(nav_index);
537 switch (ip.indexToKey(nav.status.fully_resolved.val)) {537 switch (ip.indexToKey(nav.resolved.?.value)) {
538 .func => return,538 .func => return,
539 .@"extern" => {},539 .@"extern" => {},
540 else => {540 else => {
541 const nav_ty: Type = .fromInterned(nav.typeOf(ip));541 const nav_ty: Type = .fromInterned(nav.resolved.?.type);
542 if (!nav_ty.hasRuntimeBits(zcu)) {542 if (!nav_ty.hasRuntimeBits(zcu)) {
543 if (c.navs.fetchSwapRemove(nav_index)) |kv| {543 if (c.navs.fetchSwapRemove(nav_index)) |kv| {
544 var old_rendered = kv.value;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,7 +762,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
762 {762 {
763 const unit_references = try zcu.resolveReferences();763 const unit_references = try zcu.resolveReferences();
764 for (c.navs.keys()) |nav| {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 const check_unit: ?InternPool.AnalUnit = switch (ip.indexToKey(nav_val)) {766 const check_unit: ?InternPool.AnalUnit = switch (ip.indexToKey(nav_val)) {
767 else => .wrap(.{ .nav_val = nav }),767 else => .wrap(.{ .nav_val = nav }),
768 .func => .wrap(.{ .func = nav_val }),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,8 +1092,9 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
1092 // NAV forward declarations1092 // NAV forward declarations
1093 for (need_navs.keys()) |nav| {1093 for (need_navs.keys()) |nav| {
1094 if (c.exported_navs.contains(nav)) continue; // the export was the declaration1094 if (c.exported_navs.contains(nav)) continue; // the export was the declaration
1095 if (ip.getNav(nav).getExtern(ip)) |e| {1095 switch (ip.indexToKey(ip.getNav(nav).resolved.?.value)) {
1096 if (export_names.contains(e.name)) continue;1096 .@"extern" => |e| if (export_names.contains(e.name)) continue,
1097 else => {},
1097 }1098 }
1098 const fwd_decl = c.navs.getPtr(nav).?.fwd_decl;1099 const fwd_decl = c.navs.getPtr(nav).?.fwd_decl;
1099 f.appendBufAssumeCapacity(fwd_decl.get(c));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,7 +1201,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
1200 const code = c.navs.getPtr(nav).?.code;1201 const code = c.navs.getPtr(nav).?.code;
1201 if (code.len == 0) continue;1202 if (code.len == 0) continue;
1202 if (!c.exported_navs.contains(nav)) {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 f.appendBufAssumeCapacity(if (is_extern) "zig_extern " else "static ");1205 f.appendBufAssumeCapacity(if (is_extern) "zig_extern " else "static ");
1205 }1206 }
1206 f.appendBufAssumeCapacity(code.get(c));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,34 +1226,26 @@ pub fn globalSymbol(coff: *Coff, name: []const u8, lib_name: ?[]const u8) !Symbo
1226fn navSection(1226fn navSection(
1227 coff: *Coff,1227 coff: *Coff,
1228 zcu: *Zcu,1228 zcu: *Zcu,
1229 nav_fr: @FieldType(@FieldType(InternPool.Nav, "status"), "fully_resolved"),1229 nav_resolved: @typeInfo(@FieldType(InternPool.Nav, "resolved")).optional.child,
1230) !Symbol.Index {1230) !Symbol.Index {
1231 const ip = &zcu.intern_pool;1231 const ip = &zcu.intern_pool;
1232 const default: String, const attributes: ObjectSectionAttributes =1232 const default: String, const attributes: ObjectSectionAttributes =
1233 switch (ip.indexToKey(nav_fr.val)) {1233 if (nav_resolved.@"threadlocal" and coff.base.comp.config.any_non_single_threaded) .{
1234 else => .{ .@".rdata", .{ .read = true } },1234 .@".tls$", .{ .read = true, .write = true },
1235 .variable => |variable| if (variable.is_threadlocal and1235 } else if (ip.isFunctionType(nav_resolved.type)) .{
1236 coff.base.comp.config.any_non_single_threaded)1236 .@".text", .{ .read = true, .execute = true },
1237 .{ .@".tls$", .{ .read = true, .write = true } }1237 } else if (nav_resolved.@"const") .{
1238 else1238 .@".rdata", .{ .read = true },
1239 .{ .@".data", .{ .read = true, .write = true } },1239 } else .{
1240 .@"extern" => |@"extern"| if (@"extern".is_threadlocal and1240 .@".data", .{ .read = true, .write = true },
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 } },
1250 };1241 };
1242
1251 return (try coff.objectSectionMapIndex(1243 return (try coff.objectSectionMapIndex(
1252 (try coff.getOrPutOptionalString(nav_fr.@"linksection".toSlice(ip))).unwrap() orelse default,1244 (try coff.getOrPutOptionalString(nav_resolved.@"linksection".toSlice(ip))).unwrap() orelse default,
1253 switch (nav_fr.@"linksection") {1245 switch (nav_resolved.@"linksection") {
1254 .none => coff.mf.flags.block_size,1246 .none => coff.mf.flags.block_size,
1255 else => switch (nav_fr.alignment) {1247 else => switch (nav_resolved.@"align") {
1256 .none => Type.fromInterned(ip.typeOf(nav_fr.val)).abiAlignment(zcu),1248 .none => Type.fromInterned(ip.typeOf(nav_resolved.value)).abiAlignment(zcu),
1257 else => |alignment| alignment,1249 else => |alignment| alignment,
1258 }.toStdMem(),1250 }.toStdMem(),
1259 },1251 },
...@@ -1536,20 +1528,15 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde...@@ -1536,20 +1528,15 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
1536 const ip = &zcu.intern_pool;1528 const ip = &zcu.intern_pool;
15371529
1538 const nav = ip.getNav(nav_index);1530 const nav = ip.getNav(nav_index);
1539 const nav_val = nav.status.fully_resolved.val;1531 if (ip.indexToKey(nav.resolved.?.value) == .@"extern") return;
1540 const nav_init = switch (ip.indexToKey(nav_val)) {1532 if (!Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) return;
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;
15461533
1547 const nmi = try coff.navMapIndex(zcu, nav_index);1534 const nmi = try coff.navMapIndex(zcu, nav_index);
1548 const si = nmi.symbol(coff);1535 const si = nmi.symbol(coff);
1549 const ni = ni: {1536 const ni = ni: {
1550 switch (si.get(coff).ni) {1537 switch (si.get(coff).ni) {
1551 .none => {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 try coff.nodes.ensureUnusedCapacity(gpa, 1);1540 try coff.nodes.ensureUnusedCapacity(gpa, 1);
1554 const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{1541 const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{
1555 .alignment = zcu.navAlignment(nav_index).toStdMem(),1542 .alignment = zcu.navAlignment(nav_index).toStdMem(),
...@@ -1576,7 +1563,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde...@@ -1576,7 +1563,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
1576 &coff.base,1563 &coff.base,
1577 pt,1564 pt,
1578 zcu.navSrcLoc(nav_index),1565 zcu.navSrcLoc(nav_index),
1579 .fromInterned(nav_init),1566 .fromInterned(nav.resolved.?.value),
1580 &nw.interface,1567 &nw.interface,
1581 .{ .atom_index = @intFromEnum(si) },1568 .{ .atom_index = @intFromEnum(si) },
1582 ) catch |err| switch (err) {1569 ) catch |err| switch (err) {
...@@ -1587,7 +1574,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde...@@ -1587,7 +1574,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
1587 si.applyLocationRelocs(coff);1574 si.applyLocationRelocs(coff);
1588 }1575 }
15891576
1590 if (nav.status.fully_resolved.@"linksection".unwrap()) |_| {1577 if (nav.resolved.?.@"linksection".unwrap()) |_| {
1591 try ni.resize(&coff.mf, gpa, si.get(coff).size);1578 try ni.resize(&coff.mf, gpa, si.get(coff).size);
1592 var parent_ni = ni;1579 var parent_ni = ni;
1593 while (true) {1580 while (true) {
...@@ -1674,12 +1661,12 @@ fn updateFuncInner(...@@ -1674,12 +1661,12 @@ fn updateFuncInner(
1674 const ni = ni: {1661 const ni = ni: {
1675 switch (si.get(coff).ni) {1662 switch (si.get(coff).ni) {
1676 .none => {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 try coff.nodes.ensureUnusedCapacity(gpa, 1);1665 try coff.nodes.ensureUnusedCapacity(gpa, 1);
1679 const mod = zcu.navFileScope(func.owner_nav).mod.?;1666 const mod = zcu.navFileScope(func.owner_nav).mod.?;
1680 const target = &mod.resolved_target.result;1667 const target = &mod.resolved_target.result;
1681 const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{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 .none => switch (mod.optimize_mode) {1670 .none => switch (mod.optimize_mode) {
1684 .Debug,1671 .Debug,
1685 .ReleaseSafe,1672 .ReleaseSafe,
src/link/Dwarf.zig+8-11
...@@ -2681,7 +2681,7 @@ fn initWipNavInner(...@@ -2681,7 +2681,7 @@ fn initWipNavInner(
2681 } else try wip_nav.infoExprLoc(.{ .addr_reloc = sym_index });2681 } else try wip_nav.infoExprLoc(.{ .addr_reloc = sym_index });
2682 },2682 },
2683 .syntax => switch (ip.isFunctionType(@"extern".ty)) {2683 .syntax => switch (ip.isFunctionType(@"extern".ty)) {
2684 false => continue :nav_val .{ .variable = undefined },2684 false => continue :nav_val .{ .undef = @"extern".ty },
2685 true => {2685 true => {
2686 const func_type = ip.indexToKey(@"extern".ty).func_type;2686 const func_type = ip.indexToKey(@"extern".ty).func_type;
2687 const diw = &wip_nav.debug_info.writer;2687 const diw = &wip_nav.debug_info.writer;
...@@ -2777,7 +2777,7 @@ fn initWipNavInner(...@@ -2777,7 +2777,7 @@ fn initWipNavInner(
2777 wip_nav.func_high_pc = @intCast(diw.end);2777 wip_nav.func_high_pc = @intCast(diw.end);
2778 try diw.writeInt(u32, 0, dwarf.endian);2778 try diw.writeInt(u32, 0, dwarf.endian);
2779 const target = &mod.resolved_target.result;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 .none => target_info.defaultFunctionAlignment(target),2781 .none => target_info.defaultFunctionAlignment(target),
2782 else => |a| a.maxStrict(target_info.minFunctionAlignment(target)),2782 else => |a| a.maxStrict(target_info.minFunctionAlignment(target)),
2783 }.toByteUnits().?);2783 }.toByteUnits().?);
...@@ -2845,7 +2845,7 @@ fn initWipNavInner(...@@ -2845,7 +2845,7 @@ fn initWipNavInner(
2845 .@"const" => {2845 .@"const" => {
2846 const const_ty_reloc_index = try wip_nav.refForward();2846 const const_ty_reloc_index = try wip_nav.refForward();
2847 try wip_nav.infoExprLoc(loc);2847 try wip_nav.infoExprLoc(loc);
2848 try diw.writeUleb128(nav.status.fully_resolved.alignment.toByteUnits() orelse2848 try diw.writeUleb128(nav.resolved.?.@"align".toByteUnits() orelse
2849 ty.abiAlignment(zcu).toByteUnits().?);2849 ty.abiAlignment(zcu).toByteUnits().?);
2850 try diw.writeByte(@intFromBool(decl.linkage != .normal));2850 try diw.writeByte(@intFromBool(decl.linkage != .normal));
2851 wip_nav.finishForward(const_ty_reloc_index);2851 wip_nav.finishForward(const_ty_reloc_index);
...@@ -2855,7 +2855,7 @@ fn initWipNavInner(...@@ -2855,7 +2855,7 @@ fn initWipNavInner(
2855 .@"var" => {2855 .@"var" => {
2856 try wip_nav.refType(ty);2856 try wip_nav.refType(ty);
2857 try wip_nav.infoExprLoc(loc);2857 try wip_nav.infoExprLoc(loc);
2858 try diw.writeUleb128(nav.status.fully_resolved.alignment.toByteUnits() orelse2858 try diw.writeUleb128(nav.resolved.?.@"align".toByteUnits() orelse
2859 ty.abiAlignment(zcu).toByteUnits().?);2859 ty.abiAlignment(zcu).toByteUnits().?);
2860 try diw.writeByte(@intFromBool(decl.linkage != .normal));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,10 +3028,10 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3028 const zcu = pt.zcu;3028 const zcu = pt.zcu;
3029 const ip = &zcu.intern_pool;3029 const ip = &zcu.intern_pool;
3030 const nav_src_loc = zcu.navSrcLoc(nav_index);3030 const nav_src_loc = zcu.navSrcLoc(nav_index);
3031 const nav_val = zcu.navValue(nav_index);
30323031
3033 const nav = ip.getNav(nav_index);3032 const nav = ip.getNav(nav_index);
3034 const inst_info = nav.srcInst(ip).resolveFull(ip).?;3033 const inst_info = nav.srcInst(ip).resolveFull(ip).?;
3034 const nav_val: Value = .fromInterned(nav.resolved.?.value);
3035 const file = zcu.fileByIndex(inst_info.file);3035 const file = zcu.fileByIndex(inst_info.file);
3036 const decl = file.zir.?.getDeclaration(inst_info.inst);3036 const decl = file.zir.?.getDeclaration(inst_info.inst);
3037 log.debug("updateComptimeNav({s}:{d}:{d} %{d} = {f})", .{3037 log.debug("updateComptimeNav({s}:{d}:{d} %{d} = {f})", .{
...@@ -3127,9 +3127,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3127,9 +3127,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3127 .aggregate,3127 .aggregate,
3128 .un,3128 .un,
3129 .bitpack,3129 .bitpack,
3130 => .@"const",3130 => if (nav.resolved.?.@"const") .@"const" else .@"var",
3131
3132 .variable => .@"var",
31333131
3134 .@"extern" => unreachable,3132 .@"extern" => unreachable,
31353133
...@@ -3210,7 +3208,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3210,7 +3208,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3210 const nav_ty = nav_val.typeOf(zcu);3208 const nav_ty = nav_val.typeOf(zcu);
3211 try wip_nav.refType(nav_ty);3209 try wip_nav.refType(nav_ty);
3212 try wip_nav.blockValue(nav_src_loc, nav_val);3210 try wip_nav.blockValue(nav_src_loc, nav_val);
3213 try diw.writeUleb128(nav.status.fully_resolved.alignment.toByteUnits() orelse3211 try diw.writeUleb128(nav.resolved.?.@"align".toByteUnits() orelse
3214 nav_ty.abiAlignment(zcu).toByteUnits().?);3212 nav_ty.abiAlignment(zcu).toByteUnits().?);
3215 try diw.writeByte(@intFromBool(decl.linkage != .normal));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,7 +3238,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3240 .@"extern", .@"export" => nav.name,3238 .@"extern", .@"export" => nav.name,
3241 }.toSlice(ip));3239 }.toSlice(ip));
3242 const nav_ty_reloc_index = try wip_nav.refForward();3240 const nav_ty_reloc_index = try wip_nav.refForward();
3243 try diw.writeUleb128(nav.status.fully_resolved.alignment.toByteUnits() orelse3241 try diw.writeUleb128(nav.resolved.?.@"align".toByteUnits() orelse
3244 nav_ty.abiAlignment(zcu).toByteUnits().?);3242 nav_ty.abiAlignment(zcu).toByteUnits().?);
3245 try diw.writeByte(@intFromBool(decl.linkage != .normal));3243 try diw.writeByte(@intFromBool(decl.linkage != .normal));
3246 if (has_runtime_bits) try wip_nav.blockValue(nav_src_loc, nav_val);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,7 +4279,6 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
4281 try wip_nav.refType(.null);4279 try wip_nav.refType(.null);
4282 },4280 },
4283 },4281 },
4284 .variable => unreachable, // not a value
4285 .int => |int| {4282 .int => |int| {
4286 try wip_nav.bigIntConstValue(.{4283 try wip_nav.bigIntConstValue(.{
4287 .sdata = .sdata_comptime_value,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,7 +1113,7 @@ pub fn getOrCreateMetadataForNav(self: *ZigObject, zcu: *Zcu, nav_index: InternP
1113 if (!gop.found_existing) {1113 if (!gop.found_existing) {
1114 const symbol_index = try self.newSymbolWithAtom(gpa, 0);1114 const symbol_index = try self.newSymbolWithAtom(gpa, 0);
1115 const sym = self.symbol(symbol_index);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 sym.flags.is_tls = true;1117 sym.flags.is_tls = true;
1118 }1118 }
1119 gop.value_ptr.* = .{ .symbol_index = symbol_index };1119 gop.value_ptr.* = .{ .symbol_index = symbol_index };
...@@ -1143,9 +1143,10 @@ fn getNavShdrIndex(...@@ -1143,9 +1143,10 @@ fn getNavShdrIndex(
1143 const gpa = elf_file.base.comp.gpa;1143 const gpa = elf_file.base.comp.gpa;
1144 const ptr_size = elf_file.ptrWidthBytes();1144 const ptr_size = elf_file.ptrWidthBytes();
1145 const ip = &zcu.intern_pool;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 const is_func = ip.isFunctionType(nav_val.typeOf(zcu).toIntern());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 const section_name = @"linksection".toSlice(ip);1150 const section_name = @"linksection".toSlice(ip);
1150 if (elf_file.sectionByName(section_name)) |osec| {1151 if (elf_file.sectionByName(section_name)) |osec| {
1151 if (is_func) {1152 if (is_func) {
...@@ -1258,13 +1259,8 @@ fn getNavShdrIndex(...@@ -1258,13 +1259,8 @@ fn getNavShdrIndex(
1258 self.text_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".text"), osec);1259 self.text_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".text"), osec);
1259 return osec;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 const has_relocs = self.symbol(sym_index).atom(elf_file).?.relocs(elf_file).len > 0;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 const is_bss = !has_relocs and for (code) |byte| {1264 const is_bss = !has_relocs and for (code) |byte| {
1269 if (byte != 0) break false;1265 if (byte != 0) break false;
1270 } else true;1266 } else true;
...@@ -1291,7 +1287,7 @@ fn getNavShdrIndex(...@@ -1291,7 +1287,7 @@ fn getNavShdrIndex(
1291 self.tdata_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".tdata"), osec);1287 self.tdata_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".tdata"), osec);
1292 return osec;1288 return osec;
1293 }1289 }
1294 if (is_const) {1290 if (nav.resolved.?.@"const") {
1295 if (self.data_relro_index) |symbol_index|1291 if (self.data_relro_index) |symbol_index|
1296 return self.symbol(symbol_index).outputShndx(elf_file).?;1292 return self.symbol(symbol_index).outputShndx(elf_file).?;
1297 const osec = try elf_file.addSection(.{1293 const osec = try elf_file.addSection(.{
...@@ -1303,7 +1299,7 @@ fn getNavShdrIndex(...@@ -1303,7 +1299,7 @@ fn getNavShdrIndex(
1303 self.data_relro_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".data.rel.ro"), osec);1299 self.data_relro_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".data.rel.ro"), osec);
1304 return osec;1300 return osec;
1305 }1301 }
1306 if (nav_init != .none and Value.fromInterned(nav_init).isUndef(zcu))1302 if (nav_val.isUndef(zcu))
1307 return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) {1303 return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) {
1308 .Debug, .ReleaseSafe => {1304 .Debug, .ReleaseSafe => {
1309 if (self.data_index) |symbol_index|1305 if (self.data_index) |symbol_index|
...@@ -1378,7 +1374,7 @@ fn updateNavCode(...@@ -1378,7 +1374,7 @@ fn updateNavCode(
13781374
1379 const mod = zcu.navFileScope(nav_index).mod.?;1375 const mod = zcu.navFileScope(nav_index).mod.?;
1380 const target = &mod.resolved_target.result;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 .none => switch (mod.optimize_mode) {1378 .none => switch (mod.optimize_mode) {
1383 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),1379 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),
1384 .ReleaseSmall => target_util.minFunctionAlignment(target),1380 .ReleaseSmall => target_util.minFunctionAlignment(target),
...@@ -1647,16 +1643,17 @@ pub fn updateNav(...@@ -1647,16 +1643,17 @@ pub fn updateNav(
16471643
1648 log.debug("updateNav {f}({d})", .{ nav.fqn.fmt(ip), nav_index });1644 log.debug("updateNav {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
16491645
1650 const nav_init = switch (ip.indexToKey(nav.status.fully_resolved.val)) {1646 switch (ip.indexToKey(nav.resolved.?.value)) {
1651 .func => .none,1647 else => {},
1652 .variable => |variable| variable.init,
1653 .@"extern" => |@"extern"| {1648 .@"extern" => |@"extern"| {
1654 const sym_index = try self.getGlobalSymbol(1649 const sym_index = try self.getGlobalSymbol(
1655 elf_file,1650 elf_file,
1656 nav.name.toSlice(ip),1651 nav.name.toSlice(ip),
1657 @"extern".lib_name.toSlice(ip),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 if (self.dwarf) |*dwarf| {1657 if (self.dwarf) |*dwarf| {
1661 var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index);1658 var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index);
1662 defer debug_wip_nav.deinit();1659 defer debug_wip_nav.deinit();
...@@ -1668,10 +1665,9 @@ pub fn updateNav(...@@ -1668,10 +1665,9 @@ pub fn updateNav(
1668 }1665 }
1669 return;1666 return;
1670 },1667 },
1671 else => nav.status.fully_resolved.val,1668 }
1672 };
16731669
1674 if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) {1670 if (Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) {
1675 const sym_index = try self.getOrCreateMetadataForNav(zcu, nav_index);1671 const sym_index = try self.getOrCreateMetadataForNav(zcu, nav_index);
1676 self.symbol(sym_index).atom(elf_file).?.freeRelocs(self);1672 self.symbol(sym_index).atom(elf_file).?.freeRelocs(self);
16771673
...@@ -1685,7 +1681,7 @@ pub fn updateNav(...@@ -1685,7 +1681,7 @@ pub fn updateNav(
1685 &elf_file.base,1681 &elf_file.base,
1686 pt,1682 pt,
1687 zcu.navSrcLoc(nav_index),1683 zcu.navSrcLoc(nav_index),
1688 Value.fromInterned(nav_init),1684 .fromInterned(nav.resolved.?.value),
1689 &aw.writer,1685 &aw.writer,
1690 .{ .atom_index = sym_index },1686 .{ .atom_index = sym_index },
1691 ) catch |err| switch (err) {1687 ) catch |err| switch (err) {
src/link/Elf2.zig+19-41
...@@ -1876,32 +1876,15 @@ pub fn globalSymbol(elf: *Elf, opts: struct {...@@ -1876,32 +1876,15 @@ pub fn globalSymbol(elf: *Elf, opts: struct {
18761876
1877fn navType(1877fn navType(
1878 ip: *const InternPool,1878 ip: *const InternPool,
1879 nav_status: @FieldType(InternPool.Nav, "status"),1879 nav_resolved: @typeInfo(@FieldType(InternPool.Nav, "resolved")).optional.child,
1880 any_non_single_threaded: bool,1880 any_non_single_threaded: bool,
1881) std.elf.STT {1881) std.elf.STT {
1882 return switch (nav_status) {1882 return if (any_non_single_threaded and nav_resolved.@"threadlocal")
1883 .unresolved => unreachable,1883 .TLS
1884 .type_resolved => |tr| if (any_non_single_threaded and tr.is_threadlocal)1884 else if (ip.isFunctionType(nav_resolved.type))
1885 .TLS1885 .FUNC
1886 else if (ip.isFunctionType(tr.type))1886 else
1887 .FUNC1887 .OBJECT;
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 };
1905}1888}
1906fn namedSection(elf: *const Elf, name: []const u8) ?Symbol.Index {1889fn namedSection(elf: *const Elf, name: []const u8) ?Symbol.Index {
1907 if (std.mem.eql(u8, name, ".rodata") or1890 if (std.mem.eql(u8, name, ".rodata") or
...@@ -1917,13 +1900,13 @@ fn namedSection(elf: *const Elf, name: []const u8) ?Symbol.Index {...@@ -1917,13 +1900,13 @@ fn namedSection(elf: *const Elf, name: []const u8) ?Symbol.Index {
1917fn navSection(1900fn navSection(
1918 elf: *Elf,1901 elf: *Elf,
1919 ip: *const InternPool,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) Symbol.Index {1904) Symbol.Index {
1922 if (nav_fr.@"linksection".toSlice(ip)) |@"linksection"|1905 if (nav_resolved.@"linksection".toSlice(ip)) |@"linksection"|
1923 if (elf.namedSection(@"linksection")) |si| return si;1906 if (elf.namedSection(@"linksection")) |si| return si;
1924 return switch (navType(1907 return switch (navType(
1925 ip,1908 ip,
1926 .{ .fully_resolved = nav_fr },1909 nav_resolved,
1927 elf.base.comp.config.any_non_single_threaded,1910 elf.base.comp.config.any_non_single_threaded,
1928 )) {1911 )) {
1929 else => unreachable,1912 else => unreachable,
...@@ -1940,7 +1923,7 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.NavM...@@ -1940,7 +1923,7 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.NavM
1940 const nav_gop = try elf.navs.getOrPut(gpa, nav_index);1923 const nav_gop = try elf.navs.getOrPut(gpa, nav_index);
1941 if (!nav_gop.found_existing) nav_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{1924 if (!nav_gop.found_existing) nav_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{
1942 .name = nav.fqn.toSlice(ip),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 return @enumFromInt(nav_gop.index);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,7 +1933,7 @@ pub fn navSymbol(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol.
1950 if (nav.getExtern(ip)) |@"extern"| return elf.globalSymbol(.{1933 if (nav.getExtern(ip)) |@"extern"| return elf.globalSymbol(.{
1951 .name = @"extern".name.toSlice(ip),1934 .name = @"extern".name.toSlice(ip),
1952 .lib_name = @"extern".lib_name.toSlice(ip),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 .bind = switch (@"extern".linkage) {1937 .bind = switch (@"extern".linkage) {
1955 .internal => .LOCAL,1938 .internal => .LOCAL,
1956 .strong => .GLOBAL,1939 .strong => .GLOBAL,
...@@ -2889,13 +2872,8 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)...@@ -2889,13 +2872,8 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
2889 const ip = &zcu.intern_pool;2872 const ip = &zcu.intern_pool;
28902873
2891 const nav = ip.getNav(nav_index);2874 const nav = ip.getNav(nav_index);
2892 const nav_val = nav.status.fully_resolved.val;2875 if (ip.indexToKey(nav.resolved.?.value) == .@"extern") return;
2893 const nav_init = switch (ip.indexToKey(nav_val)) {2876 if (!Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) return;
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;
28992877
2900 const nmi = try elf.navMapIndex(zcu, nav_index);2878 const nmi = try elf.navMapIndex(zcu, nav_index);
2901 const si = nmi.symbol(elf);2879 const si = nmi.symbol(elf);
...@@ -2904,7 +2882,7 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)...@@ -2904,7 +2882,7 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
2904 switch (sym.ni) {2882 switch (sym.ni) {
2905 .none => {2883 .none => {
2906 try elf.nodes.ensureUnusedCapacity(gpa, 1);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 const ni = try elf.mf.addLastChildNode(gpa, sec_si.node(elf), .{2886 const ni = try elf.mf.addLastChildNode(gpa, sec_si.node(elf), .{
2909 .alignment = zcu.navAlignment(nav_index).toStdMem(),2887 .alignment = zcu.navAlignment(nav_index).toStdMem(),
2910 .moved = true,2888 .moved = true,
...@@ -2930,7 +2908,7 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)...@@ -2930,7 +2908,7 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
2930 &elf.base,2908 &elf.base,
2931 pt,2909 pt,
2932 zcu.navSrcLoc(nav_index),2910 zcu.navSrcLoc(nav_index),
2933 .fromInterned(nav_init),2911 .fromInterned(nav.resolved.?.value),
2934 &nw.interface,2912 &nw.interface,
2935 .{ .atom_index = @intFromEnum(si) },2913 .{ .atom_index = @intFromEnum(si) },
2936 ) catch |err| switch (err) {2914 ) catch |err| switch (err) {
...@@ -3021,11 +2999,11 @@ fn updateFuncInner(...@@ -3021,11 +2999,11 @@ fn updateFuncInner(
3021 switch (sym.ni) {2999 switch (sym.ni) {
3022 .none => {3000 .none => {
3023 try elf.nodes.ensureUnusedCapacity(gpa, 1);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 const mod = zcu.navFileScope(func.owner_nav).mod.?;3003 const mod = zcu.navFileScope(func.owner_nav).mod.?;
3026 const target = &mod.resolved_target.result;3004 const target = &mod.resolved_target.result;
3027 const ni = try elf.mf.addLastChildNode(gpa, sec_si.node(elf), .{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 .none => switch (mod.optimize_mode) {3007 .none => switch (mod.optimize_mode) {
3030 .Debug,3008 .Debug,
3031 .ReleaseSafe,3009 .ReleaseSafe,
...@@ -3677,7 +3655,7 @@ fn updateExportsInner(...@@ -3677,7 +3655,7 @@ fn updateExportsInner(
3677 const exported_si: Symbol.Index, const @"type": std.elf.STT = switch (exported) {3655 const exported_si: Symbol.Index, const @"type": std.elf.STT = switch (exported) {
3678 .nav => |nav| .{3656 .nav => |nav| .{
3679 try elf.navSymbol(zcu, nav),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 .uav => |uav| .{ @enumFromInt(switch (try elf.lowerUav(3660 .uav => |uav| .{ @enumFromInt(switch (try elf.lowerUav(
3683 pt,3661 pt,
src/link/MachO/ZigObject.zig+13-19
...@@ -877,15 +877,14 @@ pub fn updateNav(...@@ -877,15 +877,14 @@ pub fn updateNav(
877 const ip = &zcu.intern_pool;877 const ip = &zcu.intern_pool;
878 const nav = ip.getNav(nav_index);878 const nav = ip.getNav(nav_index);
879879
880 const nav_init = switch (ip.indexToKey(nav.status.fully_resolved.val)) {880 switch (ip.indexToKey(nav.resolved.?.value)) {
881 .func => .none,881 else => {},
882 .variable => |variable| variable.init,
883 .@"extern" => |@"extern"| {882 .@"extern" => |@"extern"| {
884 // Extern variable gets a __got entry only883 // Extern variable gets a __got entry only
885 const name = @"extern".name.toSlice(ip);884 const name = @"extern".name.toSlice(ip);
886 const lib_name = @"extern".lib_name.toSlice(ip);885 const lib_name = @"extern".lib_name.toSlice(ip);
887 const sym_index = try self.getGlobalSymbol(macho_file, name, lib_name);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 if (self.dwarf) |*dwarf| {888 if (self.dwarf) |*dwarf| {
890 var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index);889 var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index);
891 defer debug_wip_nav.deinit();890 defer debug_wip_nav.deinit();
...@@ -897,10 +896,9 @@ pub fn updateNav(...@@ -897,10 +896,9 @@ pub fn updateNav(
897 }896 }
898 return;897 return;
899 },898 },
900 else => nav.status.fully_resolved.val,899 }
901 };
902900
903 if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) {901 if (Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) {
904 const sym_index = try self.getOrCreateMetadataForNav(macho_file, nav_index);902 const sym_index = try self.getOrCreateMetadataForNav(macho_file, nav_index);
905 self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file);903 self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file);
906904
...@@ -914,7 +912,7 @@ pub fn updateNav(...@@ -914,7 +912,7 @@ pub fn updateNav(
914 &macho_file.base,912 &macho_file.base,
915 pt,913 pt,
916 zcu.navSrcLoc(nav_index),914 zcu.navSrcLoc(nav_index),
917 Value.fromInterned(nav_init),915 .fromInterned(nav.resolved.?.value),
918 &aw.writer,916 &aw.writer,
919 .{ .atom_index = sym_index },917 .{ .atom_index = sym_index },
920 ) catch |err| switch (err) {918 ) catch |err| switch (err) {
...@@ -959,7 +957,7 @@ fn updateNavCode(...@@ -959,7 +957,7 @@ fn updateNavCode(
959957
960 const mod = zcu.navFileScope(nav_index).mod.?;958 const mod = zcu.navFileScope(nav_index).mod.?;
961 const target = &mod.resolved_target.result;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 .none => switch (mod.optimize_mode) {961 .none => switch (mod.optimize_mode) {
964 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),962 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),
965 .ReleaseSmall => target_util.minFunctionAlignment(target),963 .ReleaseSmall => target_util.minFunctionAlignment(target),
...@@ -1167,14 +1165,10 @@ fn getNavOutputSection(...@@ -1167,14 +1165,10 @@ fn getNavOutputSection(
1167) error{OutOfMemory}!u8 {1165) error{OutOfMemory}!u8 {
1168 _ = self;1166 _ = self;
1169 const ip = &zcu.intern_pool;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 if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) return macho_file.zig_text_sect_index.?;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())) {1171 if (nav.resolved.?.@"threadlocal" and macho_file.base.comp.config.any_non_single_threaded) {
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) {
1178 for (code) |byte| {1172 for (code) |byte| {
1179 if (byte != 0) break;1173 if (byte != 0) break;
1180 } else return macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection(1174 } else return macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection(
...@@ -1188,8 +1182,8 @@ fn getNavOutputSection(...@@ -1188,8 +1182,8 @@ fn getNavOutputSection(
1188 .{ .flags = macho.S_THREAD_LOCAL_REGULAR },1182 .{ .flags = macho.S_THREAD_LOCAL_REGULAR },
1189 );1183 );
1190 }1184 }
1191 if (is_const) return macho_file.zig_const_sect_index.?;1185 if (nav.resolved.?.@"const") return macho_file.zig_const_sect_index.?;
1192 if (nav_init != .none and Value.fromInterned(nav_init).isUndef(zcu))1186 if (nav_val.isUndef(zcu))
1193 return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) {1187 return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) {
1194 .Debug, .ReleaseSafe => macho_file.zig_data_sect_index.?,1188 .Debug, .ReleaseSafe => macho_file.zig_data_sect_index.?,
1195 .ReleaseFast, .ReleaseSmall => macho_file.zig_bss_sect_index.?,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,7 +1544,7 @@ fn isThreadlocal(macho_file: *MachO, nav_index: InternPool.Nav.Index) bool {
1550 if (!macho_file.base.comp.config.any_non_single_threaded)1544 if (!macho_file.base.comp.config.any_non_single_threaded)
1551 return false;1545 return false;
1552 const ip = &macho_file.base.comp.zcu.?.intern_pool;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}
15551549
1556fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index {1550fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index {
src/link/SpirV.zig+1-1
...@@ -189,7 +189,7 @@ pub fn updateExports(...@@ -189,7 +189,7 @@ pub fn updateExports(
189 @panic("TODO: implement Linker linker code for exporting a constant value");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 const target = zcu.getTarget();193 const target = zcu.getTarget();
194 if (ip.isFunctionType(nav_ty)) {194 if (ip.isFunctionType(nav_ty)) {
195 const spv_decl_index = try linker.module.resolveNav(ip, nav_index);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,7 +420,7 @@ pub const OutputFunctionIndex = enum(u32) {
420 const zcu = wasm.base.comp.zcu.?;420 const zcu = wasm.base.comp.zcu.?;
421 const ip = &zcu.intern_pool;421 const ip = &zcu.intern_pool;
422 const nav = ip.getNav(nav_index);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 }
425425
426 pub fn fromTagNameType(wasm: *const Wasm, tag_type: InternPool.Index) OutputFunctionIndex {426 pub fn fromTagNameType(wasm: *const Wasm, tag_type: InternPool.Index) OutputFunctionIndex {
...@@ -1022,7 +1022,7 @@ pub const FunctionImport = extern struct {...@@ -1022,7 +1022,7 @@ pub const FunctionImport = extern struct {
1022 pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) Resolution {1022 pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) Resolution {
1023 const zcu = wasm.base.comp.zcu.?;1023 const zcu = wasm.base.comp.zcu.?;
1024 const ip = &zcu.intern_pool;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 }
10271027
1028 pub fn fromZcuFunc(wasm: *const Wasm, i: ZcuFunc.Index) Resolution {1028 pub fn fromZcuFunc(wasm: *const Wasm, i: ZcuFunc.Index) Resolution {
...@@ -1885,7 +1885,7 @@ pub const DataSegmentId = enum(u32) {...@@ -1885,7 +1885,7 @@ pub const DataSegmentId = enum(u32) {
1885 const zcu = wasm.base.comp.zcu.?;1885 const zcu = wasm.base.comp.zcu.?;
1886 const ip = &zcu.intern_pool;1886 const ip = &zcu.intern_pool;
1887 const nav = ip.getNav(i.key(wasm).*);1887 const nav = ip.getNav(i.key(wasm).*);
1888 if (nav.isThreadlocal(ip)) return .tls;1888 if (nav.resolved.?.@"threadlocal") return .tls;
1889 const code = i.value(wasm).code;1889 const code = i.value(wasm).code;
1890 return if (code.off == .none) .zero else .data;1890 return if (code.off == .none) .zero else .data;
1891 },1891 },
...@@ -1908,7 +1908,7 @@ pub const DataSegmentId = enum(u32) {...@@ -1908,7 +1908,7 @@ pub const DataSegmentId = enum(u32) {
1908 const zcu = wasm.base.comp.zcu.?;1908 const zcu = wasm.base.comp.zcu.?;
1909 const ip = &zcu.intern_pool;1909 const ip = &zcu.intern_pool;
1910 const nav = ip.getNav(i.key(wasm).*);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,7 +1934,7 @@ pub const DataSegmentId = enum(u32) {
1934 const zcu = wasm.base.comp.zcu.?;1934 const zcu = wasm.base.comp.zcu.?;
1935 const ip = &zcu.intern_pool;1935 const ip = &zcu.intern_pool;
1936 const nav = ip.getNav(i.key(wasm).*);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 .tls => ".tdata",1938 .tls => ".tdata",
1939 .data => ".data",1939 .data => ".data",
1940 .zero => ".bss",1940 .zero => ".bss",
...@@ -1962,9 +1962,9 @@ pub const DataSegmentId = enum(u32) {...@@ -1962,9 +1962,9 @@ pub const DataSegmentId = enum(u32) {
1962 const zcu = wasm.base.comp.zcu.?;1962 const zcu = wasm.base.comp.zcu.?;
1963 const ip = &zcu.intern_pool;1963 const ip = &zcu.intern_pool;
1964 const nav = ip.getNav(i.key(wasm).*);1964 const nav = ip.getNav(i.key(wasm).*);
1965 const explicit = nav.getAlignment();1965 const explicit = nav.resolved.?.@"align";
1966 if (explicit != .none) return explicit;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 const result = ty.abiAlignment(zcu);1968 const result = ty.abiAlignment(zcu);
1969 assert(result != .none);1969 assert(result != .none);
1970 return result;1970 return result;
...@@ -2269,7 +2269,7 @@ pub const ZcuImportIndex = enum(u32) {...@@ -2269,7 +2269,7 @@ pub const ZcuImportIndex = enum(u32) {
2269 const zcu = wasm.base.comp.zcu.?;2269 const zcu = wasm.base.comp.zcu.?;
2270 const ip = &zcu.intern_pool;2270 const ip = &zcu.intern_pool;
2271 const nav_index = index.ptr(wasm).*;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 const name_slice = ext.name.toSlice(ip);2273 const name_slice = ext.name.toSlice(ip);
2274 return wasm.getExistingString(name_slice).?;2274 return wasm.getExistingString(name_slice).?;
2275 }2275 }
...@@ -2278,7 +2278,7 @@ pub const ZcuImportIndex = enum(u32) {...@@ -2278,7 +2278,7 @@ pub const ZcuImportIndex = enum(u32) {
2278 const zcu = wasm.base.comp.zcu.?;2278 const zcu = wasm.base.comp.zcu.?;
2279 const ip = &zcu.intern_pool;2279 const ip = &zcu.intern_pool;
2280 const nav_index = index.ptr(wasm).*;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 const lib_name = ext.lib_name.toSlice(ip) orelse return .none;2282 const lib_name = ext.lib_name.toSlice(ip) orelse return .none;
2283 return wasm.getExistingString(lib_name).?.toOptional();2283 return wasm.getExistingString(lib_name).?.toOptional();
2284 }2284 }
...@@ -2289,7 +2289,7 @@ pub const ZcuImportIndex = enum(u32) {...@@ -2289,7 +2289,7 @@ pub const ZcuImportIndex = enum(u32) {
2289 const zcu = comp.zcu.?;2289 const zcu = comp.zcu.?;
2290 const ip = &zcu.intern_pool;2290 const ip = &zcu.intern_pool;
2291 const nav_index = index.ptr(wasm).*;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 const fn_info = zcu.typeToFunc(.fromInterned(ext.ty)).?;2293 const fn_info = zcu.typeToFunc(.fromInterned(ext.ty)).?;
2294 return getExistingFunctionType(wasm, fn_info.cc, fn_info.param_types.get(ip), .fromInterned(fn_info.return_type), target).?;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,7 +2381,7 @@ pub const FunctionImportId = enum(u32) {
2381 .zcu_import => |i| {2381 .zcu_import => |i| {
2382 const zcu = wasm.base.comp.zcu.?;2382 const zcu = wasm.base.comp.zcu.?;
2383 const ip = &zcu.intern_pool;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 return ext.linkage != .weak and ext.lib_name != .none;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,7 +3288,8 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
3288 const is_obj = comp.config.output_mode == .Obj;3288 const is_obj = comp.config.output_mode == .Obj;
3289 const target = &comp.root_mod.resolved_target.result;3289 const target = &comp.root_mod.resolved_target.result;
32903290
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 .func => return, // global const which is a function alias3293 .func => return, // global const which is a function alias
3293 .@"extern" => |ext| {3294 .@"extern" => |ext| {
3294 if (is_obj) {3295 if (is_obj) {
...@@ -3302,7 +3303,7 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index...@@ -3302,7 +3303,7 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
3302 try wasm.function_imports.ensureUnusedCapacity(gpa, 1);3303 try wasm.function_imports.ensureUnusedCapacity(gpa, 1);
3303 try wasm.data_imports.ensureUnusedCapacity(gpa, 1);3304 try wasm.data_imports.ensureUnusedCapacity(gpa, 1);
3304 const zcu_import = wasm.addZcuImportReserved(ext.owner_nav);3305 const zcu_import = wasm.addZcuImportReserved(ext.owner_nav);
3305 if (ip.isFunctionType(nav.typeOf(ip))) {3306 if (ip.isFunctionType(nav.resolved.?.type)) {
3306 wasm.function_imports.putAssumeCapacity(name, .fromZcuImport(zcu_import, wasm));3307 wasm.function_imports.putAssumeCapacity(name, .fromZcuImport(zcu_import, wasm));
3307 // Ensure there is a corresponding function type table entry.3308 // Ensure there is a corresponding function type table entry.
3308 const fn_info = zcu.typeToFunc(.fromInterned(ext.ty)).?;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,31 +3313,29 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
3312 }3313 }
3313 return;3314 return;
3314 },3315 },
3315 .variable => |variable| .{ variable.init, variable.owner_nav },3316 }
3316 else => .{ nav.status.fully_resolved.val, nav_index },3317 //log.debug("updateNav {f} {d}", .{ nav.fqn.fmt(ip), nav_index });
3317 };3318 assert(!wasm.imports.contains(nav_index));
3318 //log.debug("updateNav {f} {d}", .{ nav.fqn.fmt(ip), chased_nav_index });
3319 assert(!wasm.imports.contains(chased_nav_index));
33203319
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 if (is_obj) {3321 if (is_obj) {
3323 assert(!wasm.navs_obj.contains(chased_nav_index));3322 assert(!wasm.navs_obj.contains(nav_index));
3324 } else {3323 } else {
3325 assert(!wasm.navs_exe.contains(chased_nav_index));3324 assert(!wasm.navs_exe.contains(nav_index));
3326 }3325 }
3327 return;3326 return;
3328 }3327 }
33293328
3330 if (is_obj) {3329 if (is_obj) {
3331 const zcu_data_starts: ZcuDataStarts = .initObj(wasm);3330 const zcu_data_starts: ZcuDataStarts = .initObj(wasm);
3332 const navs_i = try refNavObj(wasm, chased_nav_index);3331 const navs_i = try refNavObj(wasm, nav_index);
3333 const zcu_data = try lowerZcuData(wasm, pt, nav_init);3332 const zcu_data = try lowerZcuData(wasm, pt, nav.resolved.?.value);
3334 navs_i.value(wasm).* = zcu_data;3333 navs_i.value(wasm).* = zcu_data;
3335 try zcu_data_starts.finishObj(wasm, pt);3334 try zcu_data_starts.finishObj(wasm, pt);
3336 } else {3335 } else {
3337 const zcu_data_starts: ZcuDataStarts = .initExe(wasm);3336 const zcu_data_starts: ZcuDataStarts = .initExe(wasm);
3338 const navs_i = try refNavExe(wasm, chased_nav_index);3337 const navs_i = try refNavExe(wasm, nav_index);
3339 const zcu_data = try lowerZcuData(wasm, pt, nav_init);3338 const zcu_data = try lowerZcuData(wasm, pt, nav.resolved.?.value);
3340 navs_i.value(wasm).code = zcu_data.code;3339 navs_i.value(wasm).code = zcu_data.code;
3341 try zcu_data_starts.finishExe(wasm, pt);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,9 +4172,8 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 {
4173 }4172 }
4174 const zcu = comp.zcu.?;4173 const zcu = comp.zcu.?;
4175 const ip = &zcu.intern_pool;4174 const ip = &zcu.intern_pool;
4176 const nav = ip.getNav(nav_index);4175 switch (ip.indexToKey(ip.getNav(nav_index).resolved.?.value)) {
4177 if (nav.getResolvedExtern(ip)) |ext| {4176 .@"extern" => |ext| if (wasm.getExistingString(ext.name.toSlice(ip))) |symbol_name| {
4178 if (wasm.getExistingString(ext.name.toSlice(ip))) |symbol_name| {
4179 if (wasm.object_data_imports.getPtr(symbol_name)) |import| {4177 if (wasm.object_data_imports.getPtr(symbol_name)) |import| {
4180 switch (import.resolution.unpack(wasm)) {4178 switch (import.resolution.unpack(wasm)) {
4181 .unresolved => unreachable,4179 .unresolved => unreachable,
...@@ -4195,7 +4193,8 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 {...@@ -4195,7 +4193,8 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 {
4195 .nav_obj => @panic("TODO"),4193 .nav_obj => @panic("TODO"),
4196 }4194 }
4197 }4195 }
4198 }4196 },
4197 else => {},
4199 }4198 }
4200 // Otherwise it's a zero bit type; any address will do.4199 // Otherwise it's a zero bit type; any address will do.
4201 return 0;4200 return 0;
src/link/Wasm/Flush.zig+1-1
...@@ -211,7 +211,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -211,7 +211,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
211 }211 }
212212
213 for (wasm.nav_exports.keys(), wasm.nav_exports.values()) |*nav_export, export_index| {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 log.debug("flush export '{s}' nav={d}", .{ nav_export.name.slice(wasm), nav_export.nav_index });215 log.debug("flush export '{s}' nav={d}", .{ nav_export.name.slice(wasm), nav_export.nav_index });
216 const function_index = Wasm.FunctionIndex.fromIpNav(wasm, nav_export.nav_index).?;216 const function_index = Wasm.FunctionIndex.fromIpNav(wasm, nav_export.nav_index).?;
217 const explicit = f.missing_exports.swapRemove(nav_export.name);217 const explicit = f.missing_exports.swapRemove(nav_export.name);
src/print_value.zig-1
...@@ -74,7 +74,6 @@ pub fn print(...@@ -74,7 +74,6 @@ pub fn print(
74 .@"unreachable",74 .@"unreachable",
75 => try writer.writeAll(@tagName(simple_value)),75 => try writer.writeAll(@tagName(simple_value)),
76 },76 },
77 .variable => try writer.writeAll("(variable)"),
78 .@"extern" => |e| try writer.print("(extern '{f}')", .{e.name.fmt(ip)}),77 .@"extern" => |e| try writer.print("(extern '{f}')", .{e.name.fmt(ip)}),
79 .func => |func| try writer.print("(function '{f}')", .{ip.getNav(func.owner_nav).name.fmt(ip)}),78 .func => |func| try writer.print("(function '{f}')", .{ip.getNav(func.owner_nav).name.fmt(ip)}),
80 .int => |int| switch (int.storage) {79 .int => |int| switch (int.storage) {