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
215215 try w.print(
216216 \\name: '{f}'
217217 \\fqn: '{f}'
218 \\status: {s}
219218 \\created on generation: {d}
220219 \\
221220 , .{
222221 nav.name.fmt(ip),
223222 nav.fqn.fmt(ip),
224 @tagName(nav.status),
225223 create_gen,
226224 });
227 switch (nav.status) {
228 .unresolved => {},
229 .type_resolved, .fully_resolved => {
230 try w.writeAll("type: ");
231 try printType(.fromInterned(nav.typeOf(ip)), zcu, w);
232 try w.writeByte('\n');
233 },
225 if (nav.resolved) |r| {
226 try w.writeAll("status: resolved\n type: ");
227 try printType(.fromInterned(r.type), zcu, w);
228 try w.writeAll("\n value: ");
229 if (r.value == .none) {
230 try w.writeAll("(unresolved)");
231 } else {
232 try printType(.fromInterned(r.type), zcu, w);
233 }
234 try w.writeByte('\n');
235 } else {
236 try w.writeAll("status: unresolved\n");
234237 }
235238 } else if (std.mem.eql(u8, cmd_str, "find_type")) {
236239 if (arg_str.len == 0) return w.writeAll("bad usage");
src/InternPool.zig+182-402
......@@ -548,144 +548,61 @@ pub const Nav = struct {
548548 /// The fully-qualified name of this `Nav`.
549549 fqn: NullTerminatedString,
550550 /// 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`.
552552 analysis: ?struct {
553553 namespace: NamespaceIndex,
554554 zir_index: TrackedInst.Index,
555555 /// Initially `false`. Set to `true` by `setWantNavAnalysis`.
556556 wanted: bool,
557557 },
558 status: union(enum) {
559 /// This `Nav` is pending semantic analysis.
560 unresolved,
561 /// The type of this `Nav` is resolved; the value is queued for resolution.
562 type_resolved: struct {
563 type: InternPool.Index,
564 is_const: bool,
565 alignment: Alignment,
566 @"linksection": OptionalNullTerminatedString,
567 @"addrspace": std.builtin.AddressSpace,
568 is_threadlocal: bool,
569 /// This field is whether this `Nav` is a literal `extern` definition.
570 /// It does *not* tell you whether this might alias an extern fn (see #21027).
571 is_extern_decl: bool,
572 },
573 /// The value of this `Nav` is resolved.
574 fully_resolved: struct {
575 val: InternPool.Index,
576 is_const: bool,
577 alignment: Alignment,
578 @"linksection": OptionalNullTerminatedString,
579 @"addrspace": std.builtin.AddressSpace,
580 },
581 },
582
583 /// Asserts that `status != .unresolved`.
584 pub fn typeOf(nav: Nav, ip: *const InternPool) InternPool.Index {
585 return switch (nav.status) {
586 .unresolved => unreachable,
587 .type_resolved => |r| r.type,
588 .fully_resolved => |r| ip.typeOf(r.val),
589 };
590 }
591
592 /// This function is intended to be used by code generation, since semantic
593 /// analysis will ensure that any `Nav` which is potentially `extern` is
594 /// fully resolved.
595 /// Asserts that `status == .fully_resolved`.
596 pub fn getResolvedExtern(nav: Nav, ip: *const InternPool) ?Key.Extern {
597 assert(nav.status == .fully_resolved);
598 return nav.getExtern(ip);
599 }
600
601 /// Always returns `null` for `status == .type_resolved`. This function is inteded
602 /// to be used by code generation, since semantic analysis will ensure that any `Nav`
603 /// which is potentially `extern` is fully resolved.
604 /// Asserts that `status != .unresolved`.
558 /// If this is `null`, then `analysis` is *not* `null`, and semantic analysis is required to
559 /// resolve the type and value of this `Nav`. Otherwise, the type is resolved---therefore,
560 /// `Nav.resolved.?.type` is never `.none`. However, the *value* may not be resolved yet even
561 /// if this field is not `null`---see `Resolved.value` for details.
562 resolved: ?Resolved,
563
564 pub const Resolved = struct {
565 /// This is never `.none`
566 type: InternPool.Index,
567 @"align": Alignment,
568 @"linksection": OptionalNullTerminatedString,
569 @"addrspace": std.builtin.AddressSpace,
570 @"const": bool,
571 @"threadlocal": bool,
572 /// This field is whether this `Nav` is a literal `extern` definition.
573 /// It does *not* tell you whether this might alias an extern fn (see #21027).
574 is_extern_decl: bool,
575 /// If the type is resolved but not the value, this is `.none`. In that case, the value will
576 /// be resolved by semantic analysis, so `Nav.analysis` is definitely not `null`.
577 ///
578 /// If this is an extern, the special key `Key.@"extern"` is used.
579 ///
580 /// If this is a variable (`Resolved.@"const" == false`) and not an extern, then this value
581 /// is the global variable's initializer; the value loaded from the variable at runtime may
582 /// of course be different.
583 value: InternPool.Index,
584 };
585
586 /// If the value of this `Nav` is resolved and is an extern, returns the `Key.Extern`. If the
587 /// value is *not* an extern, *or* if the value is not yet resolved (only the type is), returns
588 /// `null`.
589 ///
590 /// This logic works because the frontend ensures that if a `Nav` *might* be extern, its value
591 /// is resolved more eagerly (see logic in `Sema.analyzeNavRefInner`). Therefore, if we see that
592 /// the value is not yet resolved, we know the frontend determined that the `Nav` is definitely
593 /// *not* extern.
594 ///
595 /// This function is only intended be used by the compiler backend (codegen/link). The guarantee
596 /// mentioned above does not necessarily hold in the compiler frontend (if we haven't reached
597 /// `Sema.analyzeNavRefInner` yet).
598 ///
599 /// Asserts that `nav.resolved != null`.
605600 pub fn getExtern(nav: Nav, ip: *const InternPool) ?Key.Extern {
606 return switch (nav.status) {
607 .unresolved => unreachable,
608 .type_resolved => null,
609 .fully_resolved => |r| switch (ip.indexToKey(r.val)) {
610 .@"extern" => |e| e,
611 else => null,
612 },
613 };
614 }
615
616 /// Asserts that `status != .unresolved`.
617 pub fn getAddrspace(nav: Nav) std.builtin.AddressSpace {
618 return switch (nav.status) {
619 .unresolved => unreachable,
620 .type_resolved => |r| r.@"addrspace",
621 .fully_resolved => |r| r.@"addrspace",
622 };
623 }
624
625 /// Asserts that `status != .unresolved`.
626 pub fn getAlignment(nav: Nav) Alignment {
627 return switch (nav.status) {
628 .unresolved => unreachable,
629 .type_resolved => |r| r.alignment,
630 .fully_resolved => |r| r.alignment,
631 };
632 }
633
634 /// Asserts that `status != .unresolved`.
635 pub fn getLinkSection(nav: Nav) OptionalNullTerminatedString {
636 return switch (nav.status) {
637 .unresolved => unreachable,
638 .type_resolved => |r| r.@"linksection",
639 .fully_resolved => |r| r.@"linksection",
640 };
641 }
642
643 /// Asserts that `status != .unresolved`.
644 pub fn isThreadlocal(nav: Nav, ip: *const InternPool) bool {
645 return switch (nav.status) {
646 .unresolved => unreachable,
647 .type_resolved => |r| r.is_threadlocal,
648 .fully_resolved => |r| switch (ip.indexToKey(r.val)) {
649 .@"extern" => |e| e.is_threadlocal,
650 .variable => |v| v.is_threadlocal,
651 else => false,
652 },
653 };
654 }
655
656 pub fn isFn(nav: Nav, ip: *const InternPool) bool {
657 return switch (nav.status) {
658 .unresolved => unreachable,
659 .type_resolved => |r| {
660 const tag = ip.zigTypeTag(r.type);
661 return tag == .@"fn";
662 },
663 .fully_resolved => |r| {
664 const tag = ip.zigTypeTag(ip.typeOf(r.val));
665 return tag == .@"fn";
666 },
667 };
668 }
669
670 /// If this returns `true`, then a pointer to this `Nav` might actually be encoded as a pointer
671 /// to some other `Nav` due to an extern definition or extern alias (see #21027).
672 /// This query is valid on `Nav`s for whom only the type is resolved.
673 /// Asserts that `status != .unresolved`.
674 pub fn isExternOrFn(nav: Nav, ip: *const InternPool) bool {
675 return switch (nav.status) {
676 .unresolved => unreachable,
677 .type_resolved => |r| {
678 if (r.is_extern_decl) return true;
679 const tag = ip.zigTypeTag(r.type);
680 if (tag == .@"fn") return true;
681 return false;
682 },
683 .fully_resolved => |r| {
684 if (ip.indexToKey(r.val) == .@"extern") return true;
685 const tag = ip.zigTypeTag(ip.typeOf(r.val));
686 if (tag == .@"fn") return true;
687 return false;
688 },
601 const r = nav.resolved.?;
602 if (r.value == .none) return null;
603 return switch (ip.indexToKey(r.value)) {
604 .@"extern" => |e| e,
605 else => null,
689606 };
690607 }
691608
......@@ -696,7 +613,7 @@ pub const Nav = struct {
696613 return a.zir_index;
697614 }
698615 // 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)) {
700617 .func => |func| {
701618 // Since `analysis` was not populated, this must be an instantiation.
702619 // Go up to the generic owner and consult *its* `analysis` field.
......@@ -747,30 +664,26 @@ pub const Nav = struct {
747664 };
748665
749666 /// The compact in-memory representation of a `Nav`.
750 /// 26 bytes.
667 /// 30 bytes.
751668 const Repr = struct {
752669 name: NullTerminatedString,
753670 fqn: NullTerminatedString,
754671 // The following 2 fields are either both populated, or both `.none`.
755672 analysis_namespace: OptionalNamespaceIndex,
756673 analysis_zir_index: TrackedInst.Index.Optional,
757 /// Populated only if `bits.status != .unresolved`.
758 type_or_val: InternPool.Index,
759 /// Populated only if `bits.status != .unresolved`.
674 type: InternPool.Index,
675 value: InternPool.Index,
760676 @"linksection": OptionalNullTerminatedString,
761677 bits: Bits,
762678
763679 const Bits = packed struct(u16) {
764 status: enum(u2) { unresolved, type_resolved, fully_resolved, type_resolved_extern_decl },
765 /// Populated only if `bits.status != .unresolved`.
766 is_const: bool,
767 /// Populated only if `bits.status != .unresolved`.
768 alignment: Alignment,
769 /// Populated only if `bits.status != .unresolved`.
680 @"align": Alignment,
770681 @"addrspace": std.builtin.AddressSpace,
771 /// Populated only if `bits.status == .type_resolved`.
772 is_threadlocal: bool,
682 @"const": bool,
683 @"threadlocal": bool,
684 is_extern_decl: bool,
773685 want_analysis: bool,
686 _: u1 = 0,
774687 };
775688
776689 fn unpack(repr: Repr) Nav {
......@@ -785,72 +698,46 @@ pub const Nav = struct {
785698 assert(repr.analysis_zir_index == .none);
786699 break :a null;
787700 },
788 .status = switch (repr.bits.status) {
789 .unresolved => .unresolved,
790 .type_resolved, .type_resolved_extern_decl => .{ .type_resolved = .{
791 .type = repr.type_or_val,
792 .is_const = repr.bits.is_const,
793 .alignment = repr.bits.alignment,
794 .@"linksection" = repr.@"linksection",
795 .@"addrspace" = repr.bits.@"addrspace",
796 .is_threadlocal = repr.bits.is_threadlocal,
797 .is_extern_decl = repr.bits.status == .type_resolved_extern_decl,
798 } },
799 .fully_resolved => .{ .fully_resolved = .{
800 .val = repr.type_or_val,
801 .is_const = repr.bits.is_const,
802 .alignment = repr.bits.alignment,
803 .@"linksection" = repr.@"linksection",
804 .@"addrspace" = repr.bits.@"addrspace",
805 } },
701 .resolved = if (repr.type == .none) null else .{
702 .type = repr.type,
703 .@"align" = repr.bits.@"align",
704 .@"linksection" = repr.@"linksection",
705 .@"addrspace" = repr.bits.@"addrspace",
706 .@"const" = repr.bits.@"const",
707 .@"threadlocal" = repr.bits.@"threadlocal",
708 .is_extern_decl = repr.bits.is_extern_decl,
709 .value = repr.value,
806710 },
807711 };
808712 }
809713 };
810714
811715 fn pack(nav: Nav) Repr {
812 // Note that in the `unresolved` case, we do not mark fields as `undefined`, even though they should not be used.
813 // This is to avoid writing undefined bytes to disk when serializing buffers.
716 // Note that even if `nav.resolved == null`, we do not set any fields to `undefined`, even
717 // though they should not be used. This is to avoid writing undefined bytes to disk when
718 // serializing buffers.
814719 return .{
815720 .name = nav.name,
816721 .fqn = nav.fqn,
817722 .analysis_namespace = if (nav.analysis) |a| a.namespace.toOptional() else .none,
818723 .analysis_zir_index = if (nav.analysis) |a| a.zir_index.toOptional() else .none,
819 .type_or_val = switch (nav.status) {
820 .unresolved => .none,
821 .type_resolved => |r| r.type,
822 .fully_resolved => |r| r.val,
823 },
824 .@"linksection" = switch (nav.status) {
825 .unresolved => .none,
826 .type_resolved => |r| r.@"linksection",
827 .fully_resolved => |r| r.@"linksection",
828 },
829 .bits = switch (nav.status) {
830 .unresolved => .{
831 .status = .unresolved,
832 .is_const = false,
833 .alignment = .none,
834 .@"addrspace" = .generic,
835 .is_threadlocal = false,
836 .want_analysis = if (nav.analysis) |a| a.wanted else false,
837 },
838 .type_resolved => |r| .{
839 .status = if (r.is_extern_decl) .type_resolved_extern_decl else .type_resolved,
840 .is_const = r.is_const,
841 .alignment = r.alignment,
842 .@"addrspace" = r.@"addrspace",
843 .is_threadlocal = r.is_threadlocal,
844 .want_analysis = if (nav.analysis) |a| a.wanted else false,
845 },
846 .fully_resolved => |r| .{
847 .status = .fully_resolved,
848 .is_const = r.is_const,
849 .alignment = r.alignment,
850 .@"addrspace" = r.@"addrspace",
851 .is_threadlocal = false,
852 .want_analysis = if (nav.analysis) |a| a.wanted else false,
853 },
724 .type = if (nav.resolved) |r| r.type else .none,
725 .value = if (nav.resolved) |r| r.value else .none,
726 .@"linksection" = if (nav.resolved) |r| r.@"linksection" else .none,
727 .bits = if (nav.resolved) |r| .{
728 .@"align" = r.@"align",
729 .@"addrspace" = r.@"addrspace",
730 .@"const" = r.@"const",
731 .@"threadlocal" = r.@"threadlocal",
732 .is_extern_decl = r.is_extern_decl,
733 .want_analysis = if (nav.analysis) |a| a.wanted else false,
734 } else .{
735 .@"align" = .none,
736 .@"addrspace" = .generic,
737 .@"const" = false,
738 .@"threadlocal" = false,
739 .is_extern_decl = false,
740 .want_analysis = if (nav.analysis) |a| a.wanted else false,
854741 },
855742 };
856743 }
......@@ -2110,7 +1997,6 @@ pub const Key = union(enum) {
21101997 /// via `simple_value` and has a named `Index` tag for it.
21111998 undef: Index,
21121999 simple_value: SimpleValue,
2113 variable: Variable,
21142000 @"extern": Extern,
21152001 func: Func,
21162002 int: Key.Int,
......@@ -2311,14 +2197,6 @@ pub const Key = union(enum) {
23112197 }
23122198 };
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
23222200 pub const Extern = struct {
23232201 /// The name of the extern symbol.
23242202 name: NullTerminatedString,
......@@ -2543,7 +2421,7 @@ pub const Key = union(enum) {
25432421 pub const BaseAddr = union(enum) {
25442422 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`.
25472425 nav: Nav.Index,
25482426
25492427 /// Points to the value of a single comptime alloc stored in `Sema`.
......@@ -2735,8 +2613,6 @@ pub const Key = union(enum) {
27352613 .payload => |y| Hash.hash(seed + 1, asBytes(&x.ty) ++ asBytes(&y)),
27362614 },
27372615
2738 .variable => |variable| Hash.hash(seed, asBytes(&variable.owner_nav)),
2739
27402616 .opaque_type,
27412617 .enum_type,
27422618 .union_type,
......@@ -3011,13 +2887,6 @@ pub const Key = union(enum) {
30112887 return a_info.ty == b_info.ty and a_info.backing_int_val == b_info.backing_int_val;
30122888 },
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 },
30212890 .@"extern" => |a_info| {
30222891 const b_info = b.@"extern";
30232892 return a_info.name == b_info.name and
......@@ -3277,7 +3146,6 @@ pub const Key = union(enum) {
32773146 .int,
32783147 .float,
32793148 .opt,
3280 .variable,
32813149 .@"extern",
32823150 .func,
32833151 .err,
......@@ -4390,8 +4258,6 @@ pub const Index = enum(u32) {
43904258 float_c_longdouble_f80: struct { data: *Float80 },
43914259 float_c_longdouble_f128: struct { data: *Float128 },
43924260 float_comptime_float: struct { data: *Float128 },
4393 variable: struct { data: *Tag.Variable },
4394 threadlocal_variable: struct { data: *Tag.Variable },
43954261 @"extern": struct { data: *Tag.Extern },
43964262 func_decl: struct {
43974263 const @"data.analysis.inferred_error_set" = opaque {};
......@@ -5115,12 +4981,6 @@ pub const Tag = enum(u8) {
51154981 /// A comptime_float value.
51164982 /// data is extra index to Float128.
51174983 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,
51244984 /// An extern function or variable.
51254985 /// data is extra index to Extern.
51264986 /// Some parts of the key are stored in `owner_nav`.
......@@ -5457,8 +5317,6 @@ pub const Tag = enum(u8) {
54575317 .float_c_longdouble_f80 = .{ .summary = .@"@as(c_longdouble, {.payload%value})", .payload = f80 },
54585318 .float_c_longdouble_f128 = .{ .summary = .@"@as(c_longdouble, {.payload%value})", .payload = f128 },
54595319 .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 },
54625320 .@"extern" = .{ .summary = .@"{.payload.owner_nav.fqn%summary#\"}", .payload = Extern },
54635321 .func_decl = .{
54645322 .summary = .@"{.payload.owner_nav.fqn%summary#\"}",
......@@ -5505,13 +5363,6 @@ pub const Tag = enum(u8) {
55055363 return @field(encodings, @tagName(tag)).payload;
55065364 }
55075365
5508 pub const Variable = struct {
5509 ty: Index,
5510 /// May be `none`.
5511 init: Index,
5512 owner_nav: Nav.Index,
5513 };
5514
55155366 pub const Extern = struct {
55165367 // name, is_const, alignment, addrspace come from `owner_nav`.
55175368 ty: Index,
......@@ -5525,12 +5376,11 @@ pub const Tag = enum(u8) {
55255376 pub const Flags = packed struct(u32) {
55265377 linkage: std.builtin.GlobalLinkage,
55275378 visibility: std.builtin.SymbolVisibility,
5528 is_threadlocal: bool,
55295379 is_dll_import: bool,
55305380 relocation: std.builtin.ExternOptions.Relocation,
55315381 source: Source,
55325382 decoration_type: DecorationType,
5533 _: u22 = 0,
5383 _: u23 = 0,
55345384
55355385 pub const Source = enum(u1) { builtin, syntax };
55365386 pub const DecorationType = enum(u2) { none, location, descriptor };
......@@ -6894,19 +6744,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
68946744 .ty = .comptime_float_type,
68956745 .storage = .{ .f128 = extraData(unwrapped_index.getExtra(ip), Float128, data).get() },
68966746 } },
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 },
69106747 .@"extern" => {
69116748 const extra = extraData(unwrapped_index.getExtra(ip), Tag.Extern, data);
69126749 const nav = ip.getNav(extra.owner_nav);
......@@ -6916,13 +6753,13 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
69166753 .lib_name = extra.lib_name,
69176754 .linkage = extra.flags.linkage,
69186755 .visibility = extra.flags.visibility,
6919 .is_threadlocal = extra.flags.is_threadlocal,
6756 .is_threadlocal = nav.resolved.?.@"threadlocal",
69206757 .is_dll_import = extra.flags.is_dll_import,
69216758 .relocation = extra.flags.relocation,
69226759 .decoration = extra.decoration(),
6923 .is_const = nav.status.fully_resolved.is_const,
6924 .alignment = nav.status.fully_resolved.alignment,
6925 .@"addrspace" = nav.status.fully_resolved.@"addrspace",
6760 .is_const = nav.resolved.?.@"const",
6761 .alignment = nav.resolved.?.@"align",
6762 .@"addrspace" = nav.resolved.?.@"addrspace",
69266763 .zir_index = extra.zir_index,
69276764 .owner_nav = extra.owner_nav,
69286765 .source = extra.flags.source,
......@@ -7516,22 +7353,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key:
75167353 .func => unreachable, // use getFuncInstance() or getFuncDecl() instead
75177354 .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
75357356 .slice => |slice| {
75367357 assert(ip.indexToKey(slice.ty).ptr_type.flags.size == .slice);
75377358 assert(ip.indexToKey(ip.typeOf(slice.ptr)).ptr_type.flags.size == .many);
......@@ -9245,14 +9066,15 @@ pub fn getExtern(
92459066 .tid = tid,
92469067 .index = items.mutate.len,
92479068 }, ip);
9248 const owner_nav = ip.createNav(gpa, io, tid, .{
9249 .name = key.name,
9250 .fqn = key.name,
9251 .val = extern_index,
9252 .is_const = key.is_const,
9253 .alignment = key.alignment,
9069 const owner_nav = ip.createNav(gpa, io, tid, key.name, key.name, .{
9070 .type = key.ty,
9071 .@"align" = key.alignment,
92549072 .@"linksection" = .none,
92559073 .@"addrspace" = key.@"addrspace",
9074 .@"const" = key.is_const,
9075 .@"threadlocal" = key.is_threadlocal,
9076 .is_extern_decl = true,
9077 .value = extern_index,
92569078 }) catch unreachable; // capacity asserted above
92579079 const decoration_type, const location_or_descriptor_set, const descriptor_binding = if (key.decoration) |decoration| switch (decoration) {
92589080 .location => |location| .{ Tag.Extern.Flags.DecorationType.location, location, undefined },
......@@ -9266,7 +9088,6 @@ pub fn getExtern(
92669088 .flags = .{
92679089 .linkage = key.linkage,
92689090 .visibility = key.visibility,
9269 .is_threadlocal = key.is_threadlocal,
92709091 .is_dll_import = key.is_dll_import,
92719092 .relocation = key.relocation,
92729093 .decoration_type = decoration_type,
......@@ -9846,14 +9667,16 @@ fn finishFuncInstance(
98469667 const nav_name = try ip.getOrPutStringFmt(gpa, io, tid, "{f}__anon_{d}", .{
98479668 fn_owner_nav.name.fmt(ip), @intFromEnum(func_index),
98489669 }, .no_embedded_nulls);
9849 const nav_index = try ip.createNav(gpa, io, tid, .{
9850 .name = nav_name,
9851 .fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, io, tid, nav_name),
9852 .val = func_index,
9853 .is_const = fn_owner_nav.status.fully_resolved.is_const,
9854 .alignment = fn_owner_nav.status.fully_resolved.alignment,
9855 .@"linksection" = fn_owner_nav.status.fully_resolved.@"linksection",
9856 .@"addrspace" = fn_owner_nav.status.fully_resolved.@"addrspace",
9670 const nav_fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, io, tid, nav_name);
9671 const nav_index = try ip.createNav(gpa, io, tid, nav_name, nav_fqn, .{
9672 .type = ip.typeOf(func_index),
9673 .@"align" = fn_owner_nav.resolved.?.@"align",
9674 .@"linksection" = fn_owner_nav.resolved.?.@"linksection",
9675 .@"addrspace" = fn_owner_nav.resolved.?.@"addrspace",
9676 .@"const" = true,
9677 .@"threadlocal" = false,
9678 .is_extern_decl = false,
9679 .value = func_index,
98579680 });
98589681
98599682 // Populate the owner_nav field which was left undefined until now.
......@@ -10616,20 +10439,6 @@ pub fn errorUnionPayload(ip: *const InternPool, ty: Index) Index {
1061610439 return ip.indexToKey(ty).error_union_type.payload_type;
1061710440}
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
1063310442pub fn dump(ip: *const InternPool) void {
1063410443 var buffer: [4096]u8 = undefined;
1063510444 const stderr = std.debug.lockStderr(&buffer);
......@@ -10969,7 +10778,6 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo
1096910778 .float_c_longdouble_f80 => @sizeOf(Float80),
1097010779 .float_c_longdouble_f128 => @sizeOf(Float128),
1097110780 .float_comptime_float => @sizeOf(Float128),
10972 .variable, .threadlocal_variable => @sizeOf(Tag.Variable),
1097310781 .@"extern" => @sizeOf(Tag.Extern),
1097410782 .func_decl => @sizeOf(Tag.FuncDecl),
1097510783 .func_instance => b: {
......@@ -11089,8 +10897,6 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void {
1108910897 .float_c_longdouble_f80,
1109010898 .float_c_longdouble_f128,
1109110899 .float_comptime_float,
11092 .variable,
11093 .threadlocal_variable,
1109410900 .@"extern",
1109510901 .func_decl,
1109610902 .func_instance,
......@@ -11175,8 +10981,24 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator,
1117510981
1117610982pub fn getNav(ip: *const InternPool, index: Nav.Index) Nav {
1117710983 const unwrapped = index.unwrap(ip);
11178 const navs = ip.getLocalShared(unwrapped.tid).navs.acquire();
11179 return navs.view().get(unwrapped.index).unpack();
10984 const view = ip.getLocalShared(unwrapped.tid).navs.acquire().view();
10985 // We can't just call `view.get(unwrapped.index)`, because a concurrent call to `resolveNav`
10986 // could be writing to fields, making a non-atomic load illegal. Instead, atomically load
10987 // each field. We don't need any ordering guarantees because if we need to see (e.g.) the
10988 // resolved type of a `Nav`, that information should have already been released to our caller.
10989 const repr: Nav.Repr = .{
10990 // Load the first few fields non-atomically---they are never mutated after `Nav` creation.
10991 .name = view.items(.name)[unwrapped.index],
10992 .fqn = view.items(.fqn)[unwrapped.index],
10993 .analysis_namespace = view.items(.analysis_namespace)[unwrapped.index],
10994 .analysis_zir_index = view.items(.analysis_zir_index)[unwrapped.index],
10995 // The last few fields are populated by `resolveNav` so must be loaded atomically.
10996 .type = @atomicLoad(InternPool.Index, &view.items(.type)[unwrapped.index], .monotonic),
10997 .value = @atomicLoad(InternPool.Index, &view.items(.value)[unwrapped.index], .monotonic),
10998 .@"linksection" = @atomicLoad(OptionalNullTerminatedString, &view.items(.@"linksection")[unwrapped.index], .monotonic),
10999 .bits = @atomicLoad(Nav.Repr.Bits, &view.items(.bits)[unwrapped.index], .monotonic),
11000 };
11001 return repr.unpack();
1118011002}
1118111003
1118211004pub fn namespacePtr(ip: *InternPool, namespace_index: NamespaceIndex) *Zcu.Namespace {
......@@ -11220,15 +11042,9 @@ fn createNav(
1122011042 gpa: Allocator,
1122111043 io: Io,
1122211044 tid: Zcu.PerThread.Id,
11223 opts: struct {
11224 name: NullTerminatedString,
11225 fqn: NullTerminatedString,
11226 val: InternPool.Index,
11227 is_const: bool,
11228 alignment: Alignment,
11229 @"linksection": OptionalNullTerminatedString,
11230 @"addrspace": std.builtin.AddressSpace,
11231 },
11045 name: NullTerminatedString,
11046 fqn: NullTerminatedString,
11047 resolved: @typeInfo(@FieldType(Nav, "resolved")).optional.child,
1123211048) Allocator.Error!Nav.Index {
1123311049 const navs = ip.getLocal(tid).getMutableNavs(gpa, io);
1123411050 const index_unwrapped: Nav.Index.Unwrapped = .{
......@@ -11236,16 +11052,10 @@ fn createNav(
1123611052 .index = navs.mutate.len,
1123711053 };
1123811054 try navs.append(Nav.pack(.{
11239 .name = opts.name,
11240 .fqn = opts.fqn,
11055 .name = name,
11056 .fqn = fqn,
1124111057 .analysis = null,
11242 .status = .{ .fully_resolved = .{
11243 .val = opts.val,
11244 .is_const = opts.is_const,
11245 .alignment = opts.alignment,
11246 .@"linksection" = opts.@"linksection",
11247 .@"addrspace" = opts.@"addrspace",
11248 } },
11058 .resolved = resolved,
1124911059 }));
1125011060 return index_unwrapped.wrap(ip);
1125111061}
......@@ -11279,27 +11089,19 @@ pub fn createDeclNav(
1127911089 .zir_index = zir_index,
1128011090 .wanted = false,
1128111091 },
11282 .status = .unresolved,
11092 .resolved = null,
1128311093 }));
1128411094
1128511095 return nav;
1128611096}
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.
1128911099/// If its status is already `resolved`, the old value is discarded.
11290pub fn resolveNavType(
11100pub fn resolveNav(
1129111101 ip: *InternPool,
1129211102 io: Io,
1129311103 nav: Nav.Index,
11294 resolved: struct {
11295 type: InternPool.Index,
11296 is_const: bool,
11297 alignment: Alignment,
11298 @"linksection": OptionalNullTerminatedString,
11299 @"addrspace": std.builtin.AddressSpace,
11300 is_threadlocal: bool,
11301 is_extern_decl: bool,
11302 },
11104 resolved: @typeInfo(@FieldType(Nav, "resolved")).optional.child,
1130311105) void {
1130411106 const unwrapped = nav.unwrap(ip);
1130511107
......@@ -11311,65 +11113,45 @@ pub fn resolveNavType(
1131111113
1131211114 const nav_analysis_namespace = navs.items(.analysis_namespace);
1131311115 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);
1131511118 const nav_linksections = navs.items(.@"linksection");
1131611119 const nav_bits = navs.items(.bits);
1131711120
1131811121 assert(nav_analysis_namespace[unwrapped.index] != .none);
1131911122 assert(nav_analysis_zir_index[unwrapped.index] != .none);
1132011123
11321 @atomicStore(InternPool.Index, &nav_types[unwrapped.index], resolved.type, .release);
11322 @atomicStore(OptionalNullTerminatedString, &nav_linksections[unwrapped.index], resolved.@"linksection", .release);
11323
11324 var bits = nav_bits[unwrapped.index];
11325 bits.status = if (resolved.is_extern_decl) .type_resolved_extern_decl else .type_resolved;
11326 bits.is_const = resolved.is_const;
11327 bits.alignment = resolved.alignment;
11328 bits.@"addrspace" = resolved.@"addrspace";
11329 bits.is_threadlocal = resolved.is_threadlocal;
11330 @atomicStore(Nav.Repr.Bits, &nav_bits[unwrapped.index], bits, .release);
11331}
11332
11333/// Resolve the value of a `Nav` with an analysis owner.
11334/// If its status is already `resolved`, the old value is discarded.
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);
11124 @atomicStore(
11125 OptionalNullTerminatedString,
11126 &nav_linksections[unwrapped.index],
11127 resolved.@"linksection",
11128 .monotonic,
11129 );
1136311130
11364 @atomicStore(InternPool.Index, &nav_vals[unwrapped.index], resolved.val, .release);
11365 @atomicStore(OptionalNullTerminatedString, &nav_linksections[unwrapped.index], resolved.@"linksection", .release);
11131 const bits = &nav_bits[unwrapped.index];
11132 assert(@atomicLoad(Nav.Repr.Bits, bits, .monotonic).want_analysis); // otherwise we wouldn't be resolving `nav` at all
11133 @atomicStore(Nav.Repr.Bits, bits, .{
11134 .@"align" = resolved.@"align",
11135 .@"addrspace" = resolved.@"addrspace",
11136 .@"const" = resolved.@"const",
11137 .@"threadlocal" = resolved.@"threadlocal",
11138 .is_extern_decl = resolved.is_extern_decl,
11139 .want_analysis = true, // asserted above that this is already `true`
11140 }, .monotonic);
11141
11142 @atomicStore(
11143 InternPool.Index,
11144 &nav_types[unwrapped.index],
11145 resolved.type,
11146 .monotonic,
11147 );
1136611148
11367 var bits = nav_bits[unwrapped.index];
11368 bits.status = .fully_resolved;
11369 bits.is_const = resolved.is_const;
11370 bits.alignment = resolved.alignment;
11371 bits.@"addrspace" = resolved.@"addrspace";
11372 @atomicStore(Nav.Repr.Bits, &nav_bits[unwrapped.index], bits, .release);
11149 @atomicStore(
11150 InternPool.Index,
11151 &nav_values[unwrapped.index],
11152 resolved.value,
11153 .monotonic,
11154 );
1137311155}
1137411156
1137511157pub fn createNamespace(
......@@ -11841,8 +11623,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
1184111623 .error_set_error,
1184211624 .error_union_error,
1184311625 .enum_tag,
11844 .variable,
11845 .threadlocal_variable,
1184611626 .@"extern",
1184711627 .func_decl,
1184811628 .func_instance,
......@@ -11949,11 +11729,7 @@ pub fn funcTypeReturnType(ip: *const InternPool, ty: Index) Index {
1194911729}
1195011730
1195111731pub fn isUndef(ip: *const InternPool, val: Index) bool {
11952 return val == .undef or 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;
11732 return val.unwrap(ip).getTag(ip) == .undef;
1195711733}
1195811734
1195911735pub 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 {
1222011996 .float_c_longdouble_f80,
1222111997 .float_c_longdouble_f128,
1222211998 .float_comptime_float,
12223 .variable,
12224 .threadlocal_variable,
1222511999 .@"extern",
1222612000 .func_decl,
1222712001 .func_instance,
......@@ -13001,11 +12775,17 @@ pub fn setWantNavAnalysis(ip: *InternPool, io: Io, nav_index: Nav.Index) bool {
1300112775 return false;
1300212776 }
1300312777
13004 const bits = &navs.items(.bits)[unwrapped.index];
13005 if (bits.want_analysis) {
13006 return false;
13007 } else {
13008 bits.want_analysis = true;
13009 return true;
13010 }
12778 // Mutate `bits` atomically so that we don't introduce an illegal data race with `getNav`.
12779 const old_bits = @atomicRmw(
12780 Nav.Repr.Bits,
12781 &navs.items(.bits)[unwrapped.index],
12782 .Or,
12783 mask: {
12784 var mask: Nav.Repr.Bits = @bitCast(@as(u16, 0));
12785 mask.want_analysis = true;
12786 break :mask mask;
12787 },
12788 .monotonic,
12789 );
12790 return !old_bits.want_analysis;
1301112791}
src/Sema.zig+60-57
......@@ -2276,28 +2276,26 @@ fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) ?Value {
22762276 assert(inst != .none);
22772277
22782278 if (inst.toInterned()) |ip_index| {
2279 const val: Value = .fromInterned(ip_index);
2280 assert(val.getVariable(zcu) == null);
2281 return val;
2282 } else {
2283 // Runtime-known value.
2284 const air_tags = sema.air_instructions.items(.tag);
2285 switch (air_tags[@intFromEnum(inst.toIndex().?)]) {
2286 .inferred_alloc => unreachable, // assertion failure
2287 .inferred_alloc_comptime => unreachable, // assertion failure
2288 else => {},
2289 }
2290 // LLVM fails to eliminate this `classify` call in ReleaseFast, which hurts performance, so
2291 // we must explicitly check for `std.debug.runtime_safety`.
2292 if (std.debug.runtime_safety) switch (sema.typeOf(inst).classify(zcu)) {
2293 .no_possible_value => unreachable, // values of this type do not exist
2294 .one_possible_value => unreachable, // the value should be comptime-known
2295 .partially_comptime => unreachable, // the value should be comptime-known
2296 .fully_comptime => unreachable, // the value should be comptime-known
2297 .runtime => {},
2298 };
2299 return null;
2279 return .fromInterned(ip_index);
23002280 }
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;
23012299}
23022300
23032301/// 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
57385736 .uav => |uav| .{ .uav = uav.val },
57395737 .nav => |orig_nav| target: {
57405738 try sema.ensureNavResolved(block, src, orig_nav, .fully);
5741 const export_nav = switch (ip.indexToKey(ip.getNav(orig_nav).status.fully_resolved.val)) {
5742 .variable => |v| v.owner_nav,
5739 const export_nav = switch (ip.indexToKey(ip.getNav(orig_nav).resolved.?.value)) {
57435740 .@"extern" => |e| e.owner_nav,
57445741 .func => |f| f.owner_nav,
57455742 else => orig_nav,
......@@ -5778,7 +5775,7 @@ pub fn analyzeExportSelfNav(
57785775 const ip = &zcu.intern_pool;
57795776
57805777 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);
57825779 const export_ty = export_val.typeOf(zcu);
57835780
57845781 if (!export_ty.validateExtern(.other, zcu)) {
......@@ -5792,7 +5789,6 @@ pub fn analyzeExportSelfNav(
57925789 }
57935790
57945791 const export_nav = switch (ip.indexToKey(export_val.toIntern())) {
5795 .variable => |v| v.owner_nav,
57965792 .@"extern" => |e| e.owner_nav,
57975793 .func => |f| export_nav: {
57985794 assert(export_ty.fnHasRuntimeBits(zcu)); // otherwise `validateExtern` failed above
......@@ -30005,7 +30001,7 @@ pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index:
3000530001
3000630002 const nav = ip.getNav(nav_index);
3000730003 if (nav.analysis == null) {
30008 assert(nav.status == .fully_resolved);
30004 assert(nav.resolved.?.value != .none);
3000930005 return;
3001030006 }
3001130007
......@@ -30066,11 +30062,20 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde
3006630062 try sema.ensureNavResolved(block, src, orig_nav_index, if (is_ref) .type else .fully);
3006730063
3006830064 const nav_index = nav: {
30069 if (ip.getNav(orig_nav_index).isExternOrFn(ip)) {
30070 // Getting a pointer to this `Nav` might mean we actually get a pointer to something else!
30071 // We need to resolve the value to know for sure.
30072 if (is_ref) try sema.ensureNavResolved(block, src, orig_nav_index, .fully);
30073 switch (ip.indexToKey(ip.getNav(orig_nav_index).status.fully_resolved.val)) {
30065 const orig_nav = ip.getNav(orig_nav_index);
30066 if (orig_nav.resolved.?.is_extern_decl or ip.zigTypeTag(orig_nav.resolved.?.type) == .@"fn") {
30067 // A pointer to this `Nav` might actually be encoded as a pointer to a different `Nav`
30068 // because this is either an `extern` definition or an `extern` alias. (The latter case
30069 // is unsolved language weirdness; see https://github.com/ziglang/zig/issues/21027.) To
30070 // know for sure how to encode this pointer, we need to check the *value* of this `Nav`.
30071 const orig_nav_value = switch (is_ref) {
30072 false => orig_nav.resolved.?.value,
30073 true => orig_val: {
30074 try sema.ensureNavResolved(block, src, orig_nav_index, .fully);
30075 break :orig_val ip.getNav(orig_nav_index).resolved.?.value;
30076 },
30077 };
30078 switch (ip.indexToKey(orig_nav_value)) {
3007430079 .func => |f| break :nav f.owner_nav,
3007530080 .@"extern" => |e| break :nav e.owner_nav,
3007630081 else => {},
......@@ -30079,33 +30084,31 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde
3007930084 break :nav orig_nav_index;
3008030085 };
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) {
30085 .unresolved => unreachable,
30086 // dllimports go straight to `fully_resolved`; the only option is threadlocal
30087 .type_resolved => |r| r.is_threadlocal,
30088 .fully_resolved => |r| switch (ip.indexToKey(r.val)) {
30089 .@"extern" => |e| e.is_threadlocal or e.is_dll_import or switch (e.relocation) {
30090 .any => false,
30091 .pcrel => true,
30092 },
30093 .variable => |v| v.is_threadlocal,
30094 else => false,
30095 },
30089 const is_runtime: bool = runtime: {
30090 if (nav_resolved.@"threadlocal") break :runtime true;
30091 if (nav_resolved.value == .none) {
30092 // This didn't come from `@extern`, so even if extern it couldn't be dllimport or pcrel.
30093 break :runtime false;
30094 }
30095 const @"extern" = switch (ip.indexToKey(nav_resolved.value)) {
30096 .@"extern" => |e| e,
30097 else => break :runtime false,
30098 };
30099 if (@"extern".is_dll_import) break :runtime true;
30100 break :runtime switch (@"extern".relocation) {
30101 .any => false,
30102 .pcrel => true,
30103 };
3009630104 };
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 };
3010330106 const ptr_ty = try pt.ptrType(.{
30104 .child = ty,
30107 .child = nav_resolved.type,
3010530108 .flags = .{
30106 .alignment = alignment,
30107 .is_const = is_const,
30108 .address_space = @"addrspace",
30109 .alignment = nav_resolved.@"align",
30110 .is_const = nav_resolved.@"const",
30111 .address_space = nav_resolved.@"addrspace",
3010930112 },
3011030113 });
3011130114
......@@ -30140,7 +30143,7 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, block: *Block, src: LazySrcLoc, nav_i
3014030143 // If it is, we can resolve the *value*, and queue analysis as needed.
3014130144
3014230145 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);
3014430147 if (nav_ty.zigTypeTag(zcu) != .@"fn") return;
3014530148 if (!nav_ty.fnHasRuntimeBits(zcu)) return;
3014630149
......@@ -34006,7 +34009,7 @@ pub fn getBuiltin(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) SemaError
3400634009}
3400734010
3400834011pub const NavPtrModifiers = struct {
34009 alignment: Alignment,
34012 @"align": Alignment,
3401034013 @"linksection": InternPool.OptionalNullTerminatedString,
3401134014 @"addrspace": std.builtin.AddressSpace,
3401234015};
......@@ -34029,7 +34032,7 @@ pub fn resolveNavPtrModifiers(
3402934032 const section_src = block.src(.{ .node_offset_var_decl_section = .zero });
3403034033 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = .zero });
3403134034
34032 const alignment: InternPool.Alignment = a: {
34035 const @"align": InternPool.Alignment = a: {
3403334036 const align_body = zir_decl.align_body orelse break :a .none;
3403434037 const align_ref = try sema.resolveInlineBody(block, align_body, decl_inst);
3403534038 break :a try sema.analyzeAsAlign(block, align_src, align_ref);
......@@ -34067,7 +34070,7 @@ pub fn resolveNavPtrModifiers(
3406734070 };
3406834071
3406934072 return .{
34070 .alignment = alignment,
34073 .@"align" = @"align",
3407134074 .@"linksection" = @"linksection",
3407234075 .@"addrspace" = @"addrspace",
3407334076 };
src/Sema/bitcast.zig-1
......@@ -253,7 +253,6 @@ const UnpackValueBits = struct {
253253 .func_type,
254254 .error_set_type,
255255 .inferred_error_set_type,
256 .variable,
257256 .@"extern",
258257 .func,
259258 .err,
src/Sema/comptime_ptr_access.zig+10-12
......@@ -225,19 +225,17 @@ fn loadComptimePtrInner(
225225 };
226226
227227 const base_val: MutableValue = switch (ptr.base_addr) {
228 .nav => |nav| val: {
229 try sema.ensureNavResolved(block, src, nav, .fully);
230 const val = ip.getNav(nav).status.fully_resolved.val;
231 switch (ip.indexToKey(val)) {
232 .variable => return .runtime_load,
233 // We let `.@"extern"` through here if it's a function.
234 // This allows you to alias `extern fn`s.
235 .@"extern" => |e| if (Type.fromInterned(e.ty).zigTypeTag(zcu) == .@"fn")
236 break :val .{ .interned = val }
237 else
238 return .runtime_load,
239 else => break :val .{ .interned = val },
228 .nav => |nav_id| val: {
229 try sema.ensureNavResolved(block, src, nav_id, .fully);
230 const nav = ip.getNav(nav_id);
231 if (!nav.resolved.?.@"const") return .runtime_load;
232 // We let `.@"extern"` through here if it's a fn. This allows aliasing `extern fn`s.
233 if (ip.indexToKey(nav.resolved.?.value) == .@"extern" and
234 Type.fromInterned(nav.resolved.?.type).zigTypeTag(zcu) != .@"fn")
235 {
236 return .runtime_load;
240237 }
238 break :val .{ .interned = nav.resolved.?.value };
241239 },
242240 .comptime_alloc => |alloc_index| sema.getComptimeAlloc(alloc_index).val,
243241 .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
115115 // values, not types
116116 .undef,
117117 .simple_value,
118 .variable,
119118 .@"extern",
120119 .func,
121120 .int,
src/Type.zig-10
......@@ -239,7 +239,6 @@ pub fn classify(start_ty: Type, zcu: *const Zcu) Class {
239239 // values, not types
240240 .undef,
241241 .simple_value,
242 .variable,
243242 .@"extern",
244243 .func,
245244 .int,
......@@ -675,7 +674,6 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari
675674
676675 // values, not types
677676 .simple_value,
678 .variable,
679677 .@"extern",
680678 .func,
681679 .int,
......@@ -814,7 +812,6 @@ pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool {
814812 // values, not types
815813 .undef,
816814 .simple_value,
817 .variable,
818815 .@"extern",
819816 .func,
820817 .int,
......@@ -1046,7 +1043,6 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment {
10461043 // values, not types
10471044 .undef,
10481045 .simple_value,
1049 .variable,
10501046 .@"extern",
10511047 .func,
10521048 .int,
......@@ -1187,7 +1183,6 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 {
11871183 // values, not types
11881184 .undef,
11891185 .simple_value,
1190 .variable,
11911186 .@"extern",
11921187 .func,
11931188 .int,
......@@ -1311,7 +1306,6 @@ pub fn bitSize(ty: Type, zcu: *const Zcu) u64 {
13111306 // values, not types
13121307 .undef,
13131308 .simple_value,
1314 .variable,
13151309 .@"extern",
13161310 .func,
13171311 .int,
......@@ -1867,7 +1861,6 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType {
18671861 // values, not types
18681862 .undef,
18691863 .simple_value,
1870 .variable,
18711864 .@"extern",
18721865 .func,
18731866 .int,
......@@ -2162,7 +2155,6 @@ pub fn onePossibleValue(ty: Type, pt: Zcu.PerThread) !?Value {
21622155 // values, not types
21632156 .undef,
21642157 .simple_value,
2165 .variable,
21662158 .@"extern",
21672159 .func,
21682160 .int,
......@@ -3284,7 +3276,6 @@ pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void {
32843276
32853277 // values, not types
32863278 .simple_value,
3287 .variable,
32883279 .@"extern",
32893280 .func,
32903281 .int,
......@@ -3362,7 +3353,6 @@ fn collectSubtypes(ty: Type, pt: Zcu.PerThread, visited: *std.AutoArrayHashMapUn
33623353
33633354 // values, not types
33643355 .simple_value,
3365 .variable,
33663356 .@"extern",
33673357 .func,
33683358 .int,
src/Value.zig+1-9
......@@ -176,13 +176,6 @@ pub fn getFunction(val: Value, zcu: *Zcu) ?InternPool.Key.Func {
176176 };
177177}
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
186179/// Asserts the value is a (defined) integer and it fits in a u64.
187180pub fn toUnsignedInt(val: Value, zcu: *const Zcu) u64 {
188181 return getUnsignedInt(val, zcu).?;
......@@ -808,7 +801,6 @@ pub fn canMutateComptimeVarState(val: Value, zcu: *Zcu) bool {
808801pub fn pointerNav(val: Value, zcu: *const Zcu) ?InternPool.Nav.Index {
809802 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {
810803 // TODO: these 3 cases are weird; these aren't pointer values!
811 .variable => |v| v.owner_nav,
812804 .@"extern" => |e| e.owner_nav,
813805 .func => |func| func.owner_nav,
814806 .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) {
......@@ -2539,7 +2531,7 @@ pub fn intFitsInType(
25392531 .zero_usize, .zero_u8 => return true,
25402532 else => switch (zcu.intern_pool.indexToKey(val.toIntern())) {
25412533 .undef => return true,
2542 .variable, .@"extern", .func, .ptr => {
2534 .@"extern", .func, .ptr => {
25432535 const target = zcu.getTarget();
25442536 const ptr_bits = target.ptrBitWidth();
25452537 return switch (info.signedness) {
src/Zcu.zig+9-15
......@@ -723,11 +723,7 @@ pub const Exported = union(enum) {
723723
724724 pub fn getAlign(exported: Exported, zcu: *Zcu) Alignment {
725725 return switch (exported) {
726 .nav => |nav| switch (zcu.intern_pool.getNav(nav).status) {
727 .unresolved => unreachable,
728 .type_resolved => |r| r.alignment,
729 .fully_resolved => |r| r.alignment,
730 },
726 .nav => |nav| zcu.intern_pool.getNav(nav).resolved.?.@"align",
731727 .uav => .none,
732728 };
733729 }
......@@ -4252,8 +4248,8 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.AutoArrayHashMapUnmanag
42524248 }
42534249 }
42544250 // Non-fatal AstGen errors could mean this test decl failed
4255 if (nav.status == .fully_resolved) {
4256 const gop = try units.getOrPut(gpa, .wrap(.{ .func = nav.status.fully_resolved.val }));
4251 if (nav.resolved != null and nav.resolved.?.value != .none) {
4252 const gop = try units.getOrPut(gpa, .wrap(.{ .func = nav.resolved.?.value }));
42574253 if (!gop.found_existing) gop.value_ptr.* = referencer;
42584254 }
42594255 }
......@@ -4419,7 +4415,7 @@ pub fn navSrcLine(zcu: *Zcu, nav_index: InternPool.Nav.Index) u32 {
44194415}
44204416
44214417pub 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);
44234419}
44244420
44254421pub fn navFileScopeIndex(zcu: *Zcu, nav: InternPool.Nav.Index) File.Index {
......@@ -4431,14 +4427,12 @@ pub fn navFileScope(zcu: *Zcu, nav: InternPool.Nav.Index) *File {
44314427 return zcu.fileByIndex(zcu.navFileScopeIndex(nav));
44324428}
44334429
4434pub fn navAlignment(zcu: *Zcu, nav_index: InternPool.Nav.Index) InternPool.Alignment {
4435 const ty: Type, const alignment = switch (zcu.intern_pool.getNav(nav_index).status) {
4436 .unresolved => unreachable,
4437 .type_resolved => |r| .{ .fromInterned(r.type), r.alignment },
4438 .fully_resolved => |r| .{ Value.fromInterned(r.val).typeOf(zcu), r.alignment },
4430pub fn navAlignment(zcu: *Zcu, nav_id: InternPool.Nav.Index) InternPool.Alignment {
4431 const resolved = zcu.intern_pool.getNav(nav_id).resolved.?;
4432 return switch (resolved.@"align") {
4433 else => |a| a,
4434 .none => Type.fromInterned(resolved.type).abiAlignment(zcu),
44394435 };
4440 if (alignment != .none) return alignment;
4441 return ty.abiAlignment(zcu);
44424436}
44434437
44444438pub fn fmtAnalUnit(zcu: *Zcu, unit: AnalUnit) std.fmt.Alt(FormatAnalUnit, formatAnalUnit) {
src/Zcu/PerThread.zig+76-110
......@@ -1584,10 +1584,6 @@ pub fn ensureNavValUpToDate(
15841584
15851585 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 //
15911587 // Note that if the unit is PO, we pessimistically assume that it *does* require re-analysis, to
15921588 // ensure that the unit is definitely up-to-date when this function returns. This mechanism could
15931589 // 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(
16031599 } else {
16041600 // We can trust the current information about this unit.
16051601 if (prev_failed) return error.AnalysisFail;
1606 assert(nav.status == .fully_resolved);
1602 assert(nav.resolved.?.value != .none);
16071603 return;
16081604 }
16091605
......@@ -1740,7 +1736,7 @@ fn analyzeNavVal(
17401736 const maybe_ty: ?Type = if (zir_decl.type_body != null) ty: {
17411737 // Since we have a type body, the type is resolved separately!
17421738 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);
17441740 } else null;
17451741
17461742 const final_val: ?Value = if (zir_decl.value_body) |value_body| val: {
......@@ -1786,14 +1782,12 @@ fn analyzeNavVal(
17861782 const modifiers: Sema.NavPtrModifiers = if (zir_decl.type_body != null) m: {
17871783 // `analyzeNavType` (from the `ensureNavTypeUpToDate` call above) has already populated this data into
17881784 // the `Nav`. Load the new one, and pull the modifiers out.
1789 switch (ip.getNav(nav_id).status) {
1790 .unresolved => unreachable, // `analyzeNavType` will never leave us in this state
1791 inline .type_resolved, .fully_resolved => |r| break :m .{
1792 .alignment = r.alignment,
1793 .@"linksection" = r.@"linksection",
1794 .@"addrspace" = r.@"addrspace",
1795 },
1796 }
1785 const r = ip.getNav(nav_id).resolved.?;
1786 break :m .{
1787 .@"align" = r.@"align",
1788 .@"linksection" = r.@"linksection",
1789 .@"addrspace" = r.@"addrspace",
1790 };
17971791 } else m: {
17981792 // `analyzeNavType` is essentially a stub which calls us. We are responsible for resolving this data.
17991793 break :m try sema.resolveNavPtrModifiers(&block, zir_decl, inst_resolved.inst, nav_ty);
......@@ -1803,15 +1797,7 @@ fn analyzeNavVal(
18031797 // This isn't necessarily the same as `final_val`!
18041798
18051799 const nav_val: Value = switch (zir_decl.linkage) {
1806 .normal, .@"export" => switch (zir_decl.kind) {
1807 .@"var" => .fromInterned(try pt.intern(.{ .variable = .{
1808 .ty = nav_ty.toIntern(),
1809 .init = final_val.?.toIntern(),
1810 .owner_nav = nav_id,
1811 .is_threadlocal = zir_decl.is_threadlocal,
1812 } })),
1813 else => final_val.?,
1814 },
1800 .normal, .@"export" => final_val.?,
18151801 .@"extern" => val: {
18161802 assert(final_val == null); // extern decls do not have a value body
18171803 const lib_name: ?[]const u8 = if (zir_decl.lib_name != .empty) l: {
......@@ -1832,7 +1818,7 @@ fn analyzeNavVal(
18321818 .relocation = .any,
18331819 .decoration = null,
18341820 .is_const = is_const,
1835 .alignment = modifiers.alignment,
1821 .alignment = modifiers.@"align",
18361822 .@"addrspace" = modifiers.@"addrspace",
18371823 .zir_index = old_nav.analysis.?.zir_index, // `declaration` instruction
18381824 .owner_nav = undefined, // ignored by `getExtern`
......@@ -1852,11 +1838,7 @@ fn analyzeNavVal(
18521838
18531839 const queue_linker_work, const is_owned_fn = switch (ip.indexToKey(nav_val.toIntern())) {
18541840 .func => |f| .{ true, f.owner_nav == nav_id }, // note that this lets function aliases reach codegen
1855 .variable => |v| .{ v.owner_nav == nav_id, false },
1856 .@"extern" => |e| .{
1857 false,
1858 Type.fromInterned(e.ty).zigTypeTag(zcu) == .@"fn" and zir_decl.linkage == .@"extern",
1859 },
1841 .@"extern" => .{ false, nav_ty.zigTypeTag(zcu) == .@"fn" and zir_decl.linkage == .@"extern" },
18601842 else => .{ true, false },
18611843 };
18621844
......@@ -1895,23 +1877,22 @@ fn analyzeNavVal(
18951877 info.last_update_gen = zcu.generation;
18961878 info.deps.clearRetainingCapacity();
18971879 }
1898 const type_changed: bool = switch (old_nav.status) {
1899 .unresolved => true,
1900 .type_resolved => |old| old.type != nav_ty.toIntern(),
1901 .fully_resolved => |old| ip.typeOf(old.val) != nav_ty.toIntern(),
1902 };
1880 const type_changed: bool = if (old_nav.resolved) |r| r.type != nav_ty.toIntern() else true;
19031881 if (type_changed) {
19041882 try zcu.markDependeeOutdated(.marked_po, .{ .nav_ty = nav_id });
19051883 } else {
19061884 try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav_id });
19071885 }
19081886 }
1909 ip.resolveNavValue(io, nav_id, .{
1910 .val = nav_val.toIntern(),
1911 .is_const = is_const,
1912 .alignment = modifiers.alignment,
1887 ip.resolveNav(io, nav_id, .{
1888 .type = nav_ty.toIntern(),
1889 .@"align" = modifiers.@"align",
19131890 .@"linksection" = modifiers.@"linksection",
19141891 .@"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(),
19151896 });
19161897
19171898 if (zir_decl.linkage == .@"export") {
......@@ -1943,9 +1924,10 @@ fn analyzeNavVal(
19431924 try zcu.ensureFuncBodyAnalysisQueued(nav_val.toIntern());
19441925 }
19451926
1946 return switch (old_nav.status) {
1947 .unresolved, .type_resolved => .{ .val_changed = true },
1948 .fully_resolved => |old| .{ .val_changed = old.val != nav_val.toIntern() },
1927 return if (old_nav.resolved) |old_resolved| .{
1928 .val_changed = old_resolved.value != nav_val.toIntern(),
1929 } else .{
1930 .val_changed = true,
19491931 };
19501932}
19511933
......@@ -1971,10 +1953,6 @@ pub fn ensureNavTypeUpToDate(
19711953
19721954 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 //
19781956 // Note that if the unit is PO, we pessimistically assume that it *does* require re-analysis, to
19791957 // ensure that the unit is definitely up-to-date when this function returns. This mechanism could
19801958 // 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(
19901968 } else {
19911969 // We can trust the current information about this unit.
19921970 if (prev_failed) return error.AnalysisFail;
1993 assert(nav.status != .unresolved);
1971 assert(nav.resolved != null);
19941972 return;
19951973 }
19961974
......@@ -2124,24 +2102,16 @@ fn analyzeNavType(
21242102 // the previous update. As such, after this call, we will be able to determine whether the
21252103 // type changed.
21262104 try sema.ensureNavResolved(&block, init_src, nav_id, .fully);
2127 const new = ip.getNav(nav_id).status.fully_resolved;
2128 const new_is_extern_decl = ip.indexToKey(new.val) == .@"extern";
2129 const changed = switch (old_nav.status) {
2130 .unresolved => true,
2131 .type_resolved => |r| r.type != ip.typeOf(new.val) or
2132 r.alignment != new.alignment or
2133 r.@"linksection" != new.@"linksection" or
2134 r.@"addrspace" != new.@"addrspace" or
2135 r.is_const != new.is_const or
2136 r.is_extern_decl != new_is_extern_decl,
2137 .fully_resolved => |r| ip.typeOf(r.val) != ip.typeOf(new.val) or
2138 r.alignment != new.alignment or
2139 r.@"linksection" != new.@"linksection" or
2140 r.@"addrspace" != new.@"addrspace" or
2141 r.is_const != new.is_const or
2142 (old_nav.getExtern(ip) != null) != new_is_extern_decl,
2143 };
2144 return .{ .type_changed = changed };
2105 const new = ip.getNav(nav_id).resolved.?;
2106 return if (old_nav.resolved) |old| .{
2107 .type_changed = old.type != new.type or
2108 old.@"align" != new.@"align" or
2109 old.@"linksection" != new.@"linksection" or
2110 old.@"addrspace" != new.@"addrspace" or
2111 old.@"const" != new.@"const" or
2112 old.@"threadlocal" != new.@"threadlocal" or
2113 old.is_extern_decl != new.is_extern_decl,
2114 } else .{ .type_changed = true };
21452115 };
21462116
21472117 block.comptime_reason = .{ .reason = .{
......@@ -2169,37 +2139,34 @@ fn analyzeNavType(
21692139
21702140 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?
2173 // If they are, then we should actually keep the `Nav` as `fully_resolved` if it currently is.
2174 // That's because `analyzeNavVal` will later want to look at the resolved value to figure out
2175 // whether it's changed: if we threw that data away now, it would have to assume that the value
2176 // had changed, potentially spinning off loads of unnecessary re-analysis!
2177 const changed = switch (old_nav.status) {
2178 .unresolved => true,
2179 .type_resolved => |r| r.type != resolved_ty.toIntern() or
2180 r.alignment != modifiers.alignment or
2181 r.@"linksection" != modifiers.@"linksection" or
2182 r.@"addrspace" != modifiers.@"addrspace" or
2183 r.is_const != is_const or
2184 r.is_extern_decl != is_extern_decl,
2185 .fully_resolved => |r| ip.typeOf(r.val) != resolved_ty.toIntern() or
2186 r.alignment != modifiers.alignment or
2187 r.@"linksection" != modifiers.@"linksection" or
2188 r.@"addrspace" != modifiers.@"addrspace" or
2189 r.is_const != is_const or
2190 (old_nav.getExtern(ip) != null) != is_extern_decl,
2191 };
2142 // Now for the question of the day: are the type and modifiers the same as before? If they are,
2143 // then we should actually avoid calling `ip.resolveNav`. This is because `analyzeNavVal` will
2144 // later wanmt to look at the resolved *value* to figure out whether *that* has changed: if we
2145 // threw that data away now, it would have to assume the value *had* changed even if it actually
2146 // hadn't, which could spin off a bunch of unnecessary re-analysis! OTOH, if the type *has*
2147 // changed, then we obviously know that the value will also have changed, so resetting the value
2148 // to `.none` is fine in that case.
2149 const changed: bool = if (old_nav.resolved) |old| changed: {
2150 break :changed old.type != resolved_ty.toIntern() or
2151 old.@"align" != modifiers.@"align" or
2152 old.@"linksection" != modifiers.@"linksection" or
2153 old.@"addrspace" != modifiers.@"addrspace" or
2154 old.@"const" != is_const or
2155 old.@"threadlocal" != zir_decl.is_threadlocal or
2156 old.is_extern_decl != is_extern_decl;
2157 } else true;
21922158
21932159 if (!changed) return .{ .type_changed = false };
21942160
2195 ip.resolveNavType(io, nav_id, .{
2161 ip.resolveNav(io, nav_id, .{
21962162 .type = resolved_ty.toIntern(),
2197 .is_const = is_const,
2198 .alignment = modifiers.alignment,
2163 .@"align" = modifiers.@"align",
21992164 .@"linksection" = modifiers.@"linksection",
22002165 .@"addrspace" = modifiers.@"addrspace",
2201 .is_threadlocal = zir_decl.is_threadlocal,
2166 .@"const" = is_const,
2167 .@"threadlocal" = zir_decl.is_threadlocal,
22022168 .is_extern_decl = is_extern_decl,
2169 .value = .none,
22032170 });
22042171
22052172 return .{ .type_changed = true };
......@@ -3358,13 +3325,13 @@ fn analyzeFuncBodyInner(
33583325
33593326 if (func.generic_owner == .none) {
33603327 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) {
33623329 return error.AnalysisFail;
33633330 }
33643331 } else {
33653332 const go_nav = zcu.funcInfo(func.generic_owner).owner_nav;
33663333 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) {
33683335 return error.AnalysisFail;
33693336 }
33703337 }
......@@ -3757,9 +3724,9 @@ fn processExportsInner(
37573724 if (zcu.failed_analysis.contains(unit)) break :failed true;
37583725 if (zcu.transitive_failed_analysis.contains(unit)) break :failed true;
37593726 }
3760 const val = switch (nav.status) {
3761 .unresolved, .type_resolved => break :failed true,
3762 .fully_resolved => |r| Value.fromInterned(r.val),
3727 const val: Value = switch ((nav.resolved orelse break :failed true).value) {
3728 .none => break :failed true,
3729 else => |val| .fromInterned(val),
37633730 };
37643731 // If the value is a function, we also need to check if that function succeeded analysis.
37653732 if (val.typeOf(zcu).zigTypeTag(zcu) == .@"fn") {
......@@ -3805,14 +3772,16 @@ pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void {
38053772 if (builtin_root_type == .none) return; // `@import("builtin")` never analyzed
38063773 const builtin_namespace = Type.fromInterned(builtin_root_type).getNamespace(zcu).unwrap().?;
38073774 // 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(
38093776 try ip.getOrPutString(gpa, io, pt.tid, "test_functions", .no_embedded_nulls),
38103777 Zcu.Namespace.NameAdapter{ .zcu = zcu },
38113778 ).?;
3779 const test_fns_nav = ip.getNav(test_fns_nav_index);
38123780 // ...but it might not be populated, so let's check that!
3813 if (zcu.failed_analysis.contains(.wrap(.{ .nav_val = nav_index })) or
3814 zcu.transitive_failed_analysis.contains(.wrap(.{ .nav_val = nav_index })) or
3815 ip.getNav(nav_index).status != .fully_resolved)
3781 if (zcu.failed_analysis.contains(.wrap(.{ .nav_val = test_fns_nav_index })) or
3782 zcu.transitive_failed_analysis.contains(.wrap(.{ .nav_val = test_fns_nav_index })) or
3783 test_fns_nav.resolved == null or
3784 test_fns_nav.resolved.?.value == .none)
38163785 {
38173786 // The value of `builtin.test_functions` was either never referenced, or failed analysis.
38183787 // Either way, we don't need to do anything.
......@@ -3822,8 +3791,7 @@ pub fn populateTestFunctions(pt: Zcu.PerThread) Allocator.Error!void {
38223791 // Okay, `builtin.test_functions` is (potentially) referenced and valid. Our job now is to swap
38233792 // its placeholder `&.{}` value for the actual list of all test functions.
38243793
3825 const test_fns_val = zcu.navValue(nav_index);
3826 const test_fn_ty = test_fns_val.typeOf(zcu).slicePtrFieldType(zcu).childType(zcu);
3794 const test_fn_ty = Type.fromInterned(test_fns_nav.resolved.?.type).slicePtrFieldType(zcu).childType(zcu);
38273795
38283796 const array_anon_decl: InternPool.Key.Ptr.BaseAddr.Uav = array: {
38293797 // 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 {
39143882 } }),
39153883 .len = (try pt.intValue(Type.usize, zcu.test_functions.count())).toIntern(),
39163884 } });
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);
39183888 }
39193889 // 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);
39213891}
39223892
39233893/// 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 {
44024372pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Error!Type {
44034373 const zcu = pt.zcu;
44044374 const ip = &zcu.intern_pool;
4405 const ty, const alignment, const @"addrspace", const is_const = switch (ip.getNav(nav_id).status) {
4406 .unresolved => unreachable,
4407 .type_resolved => |r| .{ r.type, r.alignment, r.@"addrspace", r.is_const },
4408 .fully_resolved => |r| .{ ip.typeOf(r.val), r.alignment, r.@"addrspace", r.is_const },
4409 };
4375 const resolved_nav = ip.getNav(nav_id).resolved.?;
44104376 return pt.ptrType(.{
4411 .child = ty,
4377 .child = resolved_nav.type,
44124378 .flags = .{
4413 .alignment = alignment,
4414 .address_space = @"addrspace",
4415 .is_const = is_const,
4379 .alignment = resolved_nav.@"align",
4380 .address_space = resolved_nav.@"addrspace",
4381 .is_const = resolved_nav.@"const",
44164382 },
44174383 });
44184384}
src/codegen.zig+6-6
......@@ -352,7 +352,6 @@ pub fn generateSymbol(
352352 else => unreachable,
353353 }),
354354 },
355 .variable,
356355 .@"extern",
357356 .func,
358357 .enum_literal,
......@@ -787,7 +786,7 @@ fn lowerNavRef(
787786 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;
788787 const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);
789788 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
792791 if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) and ip.getNav(nav_index).getExtern(ip) == null) {
793792 try w.splatByteAll(0xaa, ptr_width_bytes);
......@@ -876,10 +875,11 @@ pub fn genNavRef(
876875 const nav = ip.getNav(nav_index);
877876 log.debug("genNavRef({f})", .{nav.fqn.fmt(ip)});
878877
879 const lib_name, const linkage, const is_threadlocal = if (nav.getExtern(ip)) |e|
880 .{ e.lib_name, e.linkage, e.is_threadlocal and zcu.comp.config.any_non_single_threaded }
878 const is_threadlocal = nav.resolved.?.@"threadlocal" and zcu.comp.config.any_non_single_threaded;
879 const lib_name, const linkage = if (nav.getExtern(ip)) |e|
880 .{ e.lib_name, e.linkage }
881881 else
882 .{ .none, .internal, false };
882 .{ .none, .internal };
883883 if (lf.cast(.elf)) |elf_file| {
884884 const zo = elf_file.zigObjectPtr().?;
885885 switch (linkage) {
......@@ -1038,7 +1038,7 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo
10381038
10391039 .nav => |nav_index| {
10401040 const nav = ip.getNav(nav_index);
1041 const nav_ty: Type = .fromInterned(nav.typeOf(ip));
1041 const nav_ty: Type = .fromInterned(nav.resolved.?.type);
10421042 if (nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) or nav.getExtern(ip) != null) {
10431043 return .{ .lea_nav = nav_index };
10441044 } else {
src/codegen/aarch64/Mir.zig+1-1
......@@ -69,7 +69,7 @@ pub fn emit(
6969 const target = &mod.resolved_target.result;
7070 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") {
7373 .none => switch (mod.optimize_mode) {
7474 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),
7575 .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,
72077207 const ptr_ra = try ptr_vi.value.defReg(isel) orelse break :unused;
72087208
72097209 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) {
72117211 false => {
72127212 try isel.nav_relocs.append(gpa, .{
72137213 .nav = ty_nav.nav,
......@@ -10577,7 +10577,6 @@ pub const Value = struct {
1057710577 => continue :type_key .{ .simple_type = .anyerror },
1057810578 .undef,
1057910579 .simple_value,
10580 .variable,
1058110580 .@"extern",
1058210581 .func,
1058310582 .int,
......@@ -10914,7 +10913,7 @@ pub const Value = struct {
1091410913 .ptr => |ptr| {
1091510914 assert(offset == 0 and size == 8);
1091610915 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) {
1091810917 false => {
1091910918 try isel.nav_relocs.append(zcu.gpa, .{
1092010919 .nav = nav,
......@@ -12300,7 +12299,6 @@ pub const CallAbiIterator = struct {
1230012299 => continue :type_key .{ .simple_type = .anyerror },
1230112300 .undef,
1230212301 .simple_value,
12303 .variable,
1230412302 .@"extern",
1230512303 .func,
1230612304 .int,
src/codegen/c.zig+31-41
......@@ -669,11 +669,9 @@ pub const DeclGen = struct {
669669 return dg.renderUndefValue(w, ptr_ty, location);
670670 }
671671
672 // Chase function values in order to be able to reference the original function.
673672 switch (ip.indexToKey(uav.val)) {
674 .variable => unreachable,
675 .func => |func| return dg.renderNav(w, func.owner_nav, location),
676 .@"extern" => |@"extern"| return dg.renderNav(w, @"extern".owner_nav, location),
673 .func => unreachable,
674 .@"extern" => unreachable,
677675 else => {},
678676 }
679677
......@@ -721,10 +719,9 @@ pub const DeclGen = struct {
721719 const ip = &zcu.intern_pool;
722720
723721 // Chase function values in order to be able to reference the original function.
724 const owner_nav = switch (ip.getNav(nav_index).status) {
725 .unresolved => unreachable,
726 .type_resolved => nav_index, // this can't be an extern or a function
727 .fully_resolved => |r| switch (ip.indexToKey(r.val)) {
722 const owner_nav = switch (ip.getNav(nav_index).resolved.?.value) {
723 .none => nav_index, // this can't be an extern or a function
724 else => |value| switch (ip.indexToKey(value)) {
728725 .func => |f| f.owner_nav,
729726 .@"extern" => |e| e.owner_nav,
730727 else => nav_index,
......@@ -732,7 +729,7 @@ pub const DeclGen = struct {
732729 };
733730
734731 // 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);
736733 const ptr_ty = try pt.navPtrType(owner_nav);
737734 if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
738735 return dg.renderUndefValue(w, ptr_ty, location);
......@@ -924,7 +921,6 @@ pub const DeclGen = struct {
924921 .false => try w.writeAll("false"),
925922 .true => try w.writeAll("true"),
926923 },
927 .variable,
928924 .@"extern",
929925 .func,
930926 .enum_literal,
......@@ -1575,7 +1571,6 @@ pub const DeclGen = struct {
15751571
15761572 .undef,
15771573 .simple_value,
1578 .variable,
15791574 .@"extern",
15801575 .func,
15811576 .int,
......@@ -2276,13 +2271,13 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E
22762271 try f.dg.renderFunctionSignature(
22772272 fwd_decl_writer,
22782273 nav_val,
2279 nav.status.fully_resolved.alignment,
2274 nav.resolved.?.@"align",
22802275 .forward_decl,
22812276 .{ .nav = nav_index },
22822277 );
22832278 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|
22862281 try header_writer.print("zig_linksection_fn({f}) ", .{fmtStringLiteral(s, null)});
22872282 try f.dg.renderFunctionSignature(
22882283 header_writer,
......@@ -2360,28 +2355,26 @@ pub fn genDecl(dg: *DeclGen, w: *Writer) Error!void {
23602355 const zcu = pt.zcu;
23612356 const ip = &zcu.intern_pool;
23622357 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)) {
2366 else => .{ true, false, .fromInterned(nav.status.fully_resolved.val) },
2367 .variable => |v| .{ false, v.is_threadlocal, .fromInterned(v.init) },
2368 .@"extern" => return,
2369 };
2360 if (ip.indexToKey(nav.resolved.?.value) == .@"extern") return;
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| {
23722365 try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)});
23732366 }
23742367
23752368 // 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";
23772370 if (a != .none and a.compareStrict(.gt, nav_ty.abiAlignment(zcu))) {
23782371 try w.print("zig_align({d}) ", .{a.toByteUnits().?});
23792372 }
23802373
23812374 try genDeclValue(dg, w, .{
23822375 .name = .{ .nav = dg.owner_nav.unwrap().? },
2383 .@"const" = is_const,
2384 .@"threadlocal" = is_threadlocal,
2376 .@"const" = nav.resolved.?.@"const",
2377 .@"threadlocal" = nav.resolved.?.@"threadlocal",
23852378 .init_val = init_val,
23862379 });
23872380}
......@@ -2393,19 +2386,18 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void {
23932386 const zcu = pt.zcu;
23942387 const ip = &zcu.intern_pool;
23952388 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)) {
2399 else => .{ true, false, .fromInterned(nav.status.fully_resolved.val) },
2400 .variable => |v| .{ false, v.is_threadlocal, .fromInterned(v.init) },
2391 const init_val: Value = switch (ip.indexToKey(nav.resolved.?.value)) {
2392 else => .fromInterned(nav.resolved.?.value),
24012393
24022394 .@"extern" => |@"extern"| switch (nav_ty.zigTypeTag(zcu)) {
24032395 .@"fn" => {
24042396 try w.writeAll("zig_extern ");
24052397 try dg.renderFunctionSignature(
24062398 w,
2407 Value.fromInterned(nav.status.fully_resolved.val),
2408 nav.status.fully_resolved.alignment,
2399 .fromInterned(nav.resolved.?.value),
2400 nav.resolved.?.@"align",
24092401 .forward_decl,
24102402 .{ .@"export" = .{
24112403 .main_name = nav.name,
......@@ -2422,15 +2414,15 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void {
24222414 .weak => try w.print("zig_extern zig_weak_linkage zig_visibility({t}) ", .{@"extern".visibility}),
24232415 .link_once => return dg.fail("TODO: CBE: implement linkonce linkage?", .{}),
24242416 }
2425 if (@"extern".is_threadlocal and !dg.mod.single_threaded) {
2417 if (nav.resolved.?.@"threadlocal" and !dg.mod.single_threaded) {
24262418 try w.writeAll("zig_threadlocal ");
24272419 }
24282420 try dg.renderTypeAndName(
24292421 w,
2430 .fromInterned(nav.typeOf(ip)),
2422 .fromInterned(nav.resolved.?.type),
24312423 .{ .nav = dg.owner_nav.unwrap().? },
2432 .{ .@"const" = @"extern".is_const },
2433 nav.getAlignment(),
2424 .{ .@"const" = nav.resolved.?.@"const" },
2425 nav.resolved.?.@"align",
24342426 );
24352427 try w.writeAll(";\n");
24362428 return;
......@@ -2439,15 +2431,15 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void {
24392431 };
24402432
24412433 // 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";
24432435 if (a != .none and a.compareStrict(.gt, nav_ty.abiAlignment(zcu))) {
24442436 try w.print("zig_align({d}) ", .{a.toByteUnits().?});
24452437 }
24462438
24472439 try genDeclValueFwd(dg, w, .{
24482440 .name = .{ .nav = dg.owner_nav.unwrap().? },
2449 .@"const" = is_const,
2450 .@"threadlocal" = is_threadlocal,
2441 .@"const" = nav.resolved.?.@"const",
2442 .@"threadlocal" = nav.resolved.?.@"threadlocal",
24512443 .init_val = init_val,
24522444 });
24532445}
......@@ -2514,11 +2506,9 @@ pub fn genExports(dg: *DeclGen, w: *Writer, exported: Zcu.Exported, export_indic
25142506 );
25152507 try w.writeAll(";\n");
25162508 };
2517 const is_const = switch (ip.indexToKey(exported_val.toIntern())) {
2518 .func => unreachable,
2519 .@"extern" => |@"extern"| @"extern".is_const,
2520 .variable => false,
2521 else => true,
2509 const is_const = switch (exported) {
2510 .nav => |nav| ip.getNav(nav).resolved.?.@"const",
2511 .uav => true,
25222512 };
25232513 for (export_indices) |export_index| {
25242514 const @"export" = export_index.ptr(zcu);
src/codegen/c/type.zig-1
......@@ -990,7 +990,6 @@ pub const CType = union(enum) {
990990 // values, not types
991991 .undef,
992992 .simple_value,
993 .variable,
994993 .@"extern",
995994 .func,
996995 .int,
src/codegen/llvm.zig+27-34
......@@ -1279,7 +1279,7 @@ pub const Object = struct {
12791279 } }, &o.builder);
12801280 }
12811281
1282 if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |section|
1282 if (nav.resolved.?.@"linksection".toSlice(ip)) |section|
12831283 function_index.setSection(try o.builder.string(section), &o.builder);
12841284
12851285 var deinit_wip = true;
......@@ -1487,7 +1487,7 @@ pub const Object = struct {
14871487 const file = try o.getDebugFile(pt, file_scope);
14881488
14891489 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";
14911491 const debug_decl_type = try o.getDebugType(pt, fn_ty);
14921492
14931493 const subprogram = try o.builder.debugSubprogram(
......@@ -1662,7 +1662,7 @@ pub const Object = struct {
16621662 .elf, .wasm => break :coff_export_flags,
16631663 .coff => |*coff| coff,
16641664 };
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;
16661666 const flags = &coff.lld_export_flags;
16671667 for (export_indices) |export_index| {
16681668 const name = export_index.ptr(zcu).opts.name;
......@@ -2677,7 +2677,7 @@ pub const Object = struct {
26772677 const gpa = o.gpa;
26782678 const nav = ip.getNav(nav_index);
26792679 const owner_mod = zcu.navFileScope(nav_index).mod.?;
2680 const ty: Type = .fromInterned(nav.typeOf(ip));
2680 const ty: Type = .fromInterned(nav.resolved.?.type);
26812681 const gop = try o.nav_map.getOrPut(gpa, nav_index);
26822682 if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function;
26832683
......@@ -2692,7 +2692,7 @@ pub const Object = struct {
26922692 const function_index = try o.builder.addFunction(
26932693 try o.lowerType(pt, ty),
26942694 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),
26962696 );
26972697 gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
26982698
......@@ -2809,8 +2809,8 @@ pub const Object = struct {
28092809 }
28102810 }
28112811
2812 if (nav.getAlignment() != .none)
2813 function_index.setAlignment(nav.getAlignment().toLlvm(), &o.builder);
2812 if (nav.resolved.?.@"align" != .none)
2813 function_index.setAlignment(nav.resolved.?.@"align".toLlvm(), &o.builder);
28142814
28152815 // Function attributes that are independent of analysis results of the function body.
28162816 try o.addCommonFnAttributes(
......@@ -2951,15 +2951,12 @@ pub const Object = struct {
29512951 const zcu = pt.zcu;
29522952 const ip = &zcu.intern_pool;
29532953 const nav = ip.getNav(nav_index);
2954 const linkage: std.builtin.GlobalLinkage, const visibility: Builder.Visibility, const is_threadlocal, const is_dll_import = switch (nav.status) {
2955 .unresolved => unreachable,
2956 .fully_resolved => |r| switch (ip.indexToKey(r.val)) {
2957 .variable => |variable| .{ .internal, .default, variable.is_threadlocal, false },
2958 .@"extern" => |@"extern"| .{ @"extern".linkage, .fromSymbolVisibility(@"extern".visibility), @"extern".is_threadlocal, @"extern".is_dll_import },
2959 else => .{ .internal, .default, false, false },
2954 const linkage: std.builtin.GlobalLinkage, const visibility: Builder.Visibility, const is_dll_import: bool = switch (nav.resolved.?.value) {
2955 .none => .{ .internal, .default, false }, // this is a source declaration which is *not* marked `extern`
2956 else => |val| switch (ip.indexToKey(val)) {
2957 else => .{ .internal, .default, false },
2958 .@"extern" => |e| .{ e.linkage, .fromSymbolVisibility(e.visibility), e.is_dll_import },
29602959 },
2961 // This means it's a source declaration which is not `extern`!
2962 .type_resolved => |r| .{ .internal, .default, r.is_threadlocal, false },
29632960 };
29642961
29652962 const variable_index = try o.builder.addVariable(
......@@ -2968,8 +2965,8 @@ pub const Object = struct {
29682965 .strong, .weak => nav.name,
29692966 .link_once => unreachable,
29702967 }.toSlice(ip)),
2971 try o.lowerType(pt, Type.fromInterned(nav.typeOf(ip))),
2972 toLlvmGlobalAddressSpace(nav.getAddrspace(), zcu.getTarget()),
2968 try o.lowerType(pt, .fromInterned(nav.resolved.?.type)),
2969 toLlvmGlobalAddressSpace(nav.resolved.?.@"addrspace", zcu.getTarget()),
29732970 );
29742971 gop.value_ptr.* = variable_index.ptrConst(&o.builder).global;
29752972
......@@ -2987,7 +2984,7 @@ pub const Object = struct {
29872984 .link_once => unreachable,
29882985 }, &o.builder);
29892986 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)
29912988 variable_index.setThreadLocal(.generaldynamic, &o.builder);
29922989 if (is_dll_import) variable_index.setDllStorageClass(.dllimport, &o.builder);
29932990 },
......@@ -3422,7 +3419,6 @@ pub const Object = struct {
34223419 // values, not types
34233420 .undef,
34243421 .simple_value,
3425 .variable,
34263422 .@"extern",
34273423 .func,
34283424 .int,
......@@ -3553,9 +3549,7 @@ pub const Object = struct {
35533549 .false => .false,
35543550 .true => .true,
35553551 },
3556 .variable,
3557 .enum_literal,
3558 => unreachable, // non-runtime values
3552 .enum_literal => unreachable, // non-runtime value
35593553 .@"extern" => |@"extern"| {
35603554 const function_index = try o.resolveLlvmFunction(pt, @"extern".owner_nav);
35613555 return function_index.ptrConst(&o.builder).global.toConst();
......@@ -4131,7 +4125,7 @@ pub const Object = struct {
41314125
41324126 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);
41354129 const ptr_ty = try pt.navPtrType(nav_index);
41364130
41374131 if (nav.getExtern(ip) == null and !nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
......@@ -4145,7 +4139,7 @@ pub const Object = struct {
41454139
41464140 const llvm_val = try o.builder.convConst(
41474141 llvm_global.toConst(),
4148 try o.builder.ptrType(toLlvmAddressSpace(nav.getAddrspace(), zcu.getTarget())),
4142 try o.builder.ptrType(toLlvmAddressSpace(nav.resolved.?.@"addrspace", zcu.getTarget())),
41494143 );
41504144
41514145 return o.builder.convConst(llvm_val, try o.lowerType(pt, ptr_ty));
......@@ -4398,14 +4392,13 @@ pub const NavGen = struct {
43984392 const ip = &zcu.intern_pool;
43994393 const nav_index = ng.nav_index;
44004394 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)) {
4404 .variable => |variable| .{ .none, .internal, .default, variable.is_threadlocal, false, false, variable.init, variable.owner_nav },
4405 .@"extern" => |@"extern"| .{ @"extern".lib_name, @"extern".linkage, .fromSymbolVisibility(@"extern".visibility), @"extern".is_threadlocal, @"extern".is_dll_import, @"extern".is_const, .none, @"extern".owner_nav },
4406 else => .{ .none, .internal, .default, false, false, true, resolved.val, nav_index },
4397 const lib_name, const linkage, const visibility: Builder.Visibility, const is_dll_import, const init_val, const owner_nav = switch (ip.indexToKey(resolved.value)) {
4398 else => .{ .none, .internal, .default, false, resolved.value, nav_index },
4399 .@"extern" => |e| .{ e.lib_name, e.linkage, .fromSymbolVisibility(e.visibility), e.is_dll_import, .none, e.owner_nav },
44074400 };
4408 const ty = Type.fromInterned(nav.typeOf(ip));
4401 const ty: Type = .fromInterned(nav.resolved.?.type);
44094402
44104403 if (linkage != .internal and ip.isFunctionType(ty.toIntern())) {
44114404 const function_index = try o.resolveLlvmFunction(pt, owner_nav);
......@@ -4448,7 +4441,7 @@ pub const NavGen = struct {
44484441 variable_index.setAlignment(zcu.navAlignment(nav_index).toLlvm(), &o.builder);
44494442 if (resolved.@"linksection".toSlice(ip)) |section|
44504443 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);
44524445 try variable_index.setInitializer(switch (init_val) {
44534446 .none => .no_init,
44544447 else => try o.lowerValue(pt, init_val),
......@@ -4457,7 +4450,7 @@ pub const NavGen = struct {
44574450
44584451 const file_scope = zcu.navFileScopeIndex(nav_index);
44594452 const mod = zcu.fileByIndex(file_scope).mod.?;
4460 if (is_threadlocal and !mod.single_threaded)
4453 if (resolved.@"threadlocal" and !mod.single_threaded)
44614454 variable_index.setThreadLocal(.generaldynamic, &o.builder);
44624455
44634456 const line_number = zcu.navSrcLine(nav_index) + 1;
......@@ -5475,7 +5468,7 @@ pub const FuncGen = struct {
54755468 _ = try self.wip.retVoid();
54765469 return;
54775470 }
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)).?;
54795472 if (!ret_ty.hasRuntimeBits(zcu)) {
54805473 if (Type.fromInterned(fn_info.return_type).isError(zcu)) {
54815474 // Functions with an empty error set are emitted with an error code
......@@ -5540,7 +5533,7 @@ pub const FuncGen = struct {
55405533 const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
55415534 const ptr_ty = self.typeOf(un_op);
55425535 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)).?;
55445537 if (!ret_ty.hasRuntimeBits(zcu)) {
55455538 if (Type.fromInterned(fn_info.return_type).isError(zcu)) {
55465539 // 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 {
256256 .global => {
257257 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");
260260 assert(storage_class != .generic); // These should be instance globals
261261
262262 const ty_id = try cg.resolveType(ty, .indirect);
......@@ -314,64 +314,47 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void {
314314 try cg.module.debugName(result_id, nav.fqn.toSlice(ip));
315315 },
316316 .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
324317 const ty_id = try cg.resolveType(ty, .indirect);
325318 const ptr_ty_id = try cg.module.ptrType(ty_id, .function);
326319
327 if (maybe_init_val) |init_val| {
328 // TODO: Combine with resolveAnonDecl?
329 const void_ty_id = try cg.resolveType(.void, .direct);
330 const initializer_proto_ty_id = try cg.module.functionType(void_ty_id, &.{});
331
332 const initializer_id = cg.module.allocId();
333 try cg.prologue.emit(gpa, .OpFunction, .{
334 .id_result_type = try cg.resolveType(.void, .direct),
335 .id_result = initializer_id,
336 .function_control = .{},
337 .function_type = initializer_proto_ty_id,
338 });
320 // TODO: Combine with resolveAnonDecl?
321 const void_ty_id = try cg.resolveType(.void, .direct);
322 const initializer_proto_ty_id = try cg.module.functionType(void_ty_id, &.{});
339323
340 const root_block_id = cg.module.allocId();
341 try cg.prologue.emit(gpa, .OpLabel, .{
342 .id_result = root_block_id,
343 });
344 cg.block_label = root_block_id;
324 const initializer_id = cg.module.allocId();
325 try cg.prologue.emit(gpa, .OpFunction, .{
326 .id_result_type = try cg.resolveType(.void, .direct),
327 .id_result = initializer_id,
328 .function_control = .{},
329 .function_type = initializer_proto_ty_id,
330 });
345331
346 const val_id = try cg.constant(ty, init_val, .indirect);
347 try cg.body.emit(gpa, .OpStore, .{
348 .pointer = result_id,
349 .object = val_id,
350 });
332 const root_block_id = cg.module.allocId();
333 try cg.prologue.emit(gpa, .OpLabel, .{
334 .id_result = root_block_id,
335 });
336 cg.block_label = root_block_id;
351337
352 try cg.body.emit(gpa, .OpReturn, {});
353 try cg.body.emit(gpa, .OpFunctionEnd, {});
354 try cg.module.sections.functions.append(gpa, cg.prologue);
355 try cg.module.sections.functions.append(gpa, cg.body);
338 const val_id = try cg.constant(ty, val, .indirect);
339 try cg.body.emit(gpa, .OpStore, .{
340 .pointer = result_id,
341 .object = val_id,
342 });
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, .{
360 .id_result_type = ptr_ty_id,
361 .id_result = result_id,
362 .set = try cg.module.importInstructionSet(.zig),
363 .instruction = .{ .inst = @intFromEnum(spec.Zig.InvocationGlobal) },
364 .id_ref_4 = &.{initializer_id},
365 });
366 } else {
367 try cg.module.sections.globals.emit(gpa, .OpExtInst, .{
368 .id_result_type = ptr_ty_id,
369 .id_result = result_id,
370 .set = try cg.module.importInstructionSet(.zig),
371 .instruction = .{ .inst = @intFromEnum(spec.Zig.InvocationGlobal) },
372 .id_ref_4 = &.{},
373 });
374 }
349 try cg.module.debugNameFmt(initializer_id, "initializer of {f}", .{nav.fqn.fmt(ip)});
350
351 try cg.module.sections.globals.emit(gpa, .OpExtInst, .{
352 .id_result_type = ptr_ty_id,
353 .id_result = result_id,
354 .set = try cg.module.importInstructionSet(.zig),
355 .instruction = .{ .inst = @intFromEnum(spec.Zig.InvocationGlobal) },
356 .id_ref_4 = &.{initializer_id},
357 });
375358 },
376359 }
377360
......@@ -810,7 +793,6 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id {
810793
811794 .undef => unreachable, // handled above
812795
813 .variable,
814796 .@"extern",
815797 .func,
816798 .enum_literal,
......@@ -1170,12 +1152,11 @@ fn constantNavRef(cg: *CodeGen, ty: Type, nav_index: InternPool.Nav.Index) !Id {
11701152 const ip = &zcu.intern_pool;
11711153 const ty_id = try cg.resolveType(ty, .direct);
11721154 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) {
1176 .unresolved => unreachable,
1177 .type_resolved => {}, // this is not a function or extern
1178 .fully_resolved => |r| switch (ip.indexToKey(r.val)) {
1157 switch (nav.resolved.?.value) {
1158 .none => {}, // this is not a function or extern
1159 else => |value| switch (ip.indexToKey(value)) {
11791160 .func => {
11801161 // TODO: Properly lower function pointers. For now we are going to hack around it and
11811162 // 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 {
11961177 const spv_decl_result_id = spv_decl.result_id;
11971178 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");
12001181 try cg.addFunctionDep(spv_decl_index, storage_class);
12011182
12021183 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
252252 if (!entry.found_existing) {
253253 const nav = ip.getNav(nav_index);
254254 // 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))
256256 .func
257 else switch (nav.getAddrspace()) {
257 else switch (nav.resolved.?.@"addrspace") {
258258 .generic => .invocation_global,
259259 else => .global,
260260 };
src/codegen/wasm/CodeGen.zig+1-2
......@@ -575,7 +575,7 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {
575575 .nav_ref => |nav_ref| {
576576 const zcu = cg.pt.zcu;
577577 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") {
579579 assert(nav_ref.offset == 0);
580580 try cg.mir_indirect_function_set.put(cg.gpa, nav_ref.nav_index, {});
581581 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 {
44014401 else => unreachable,
44024402 } },
44034403 },
4404 .variable,
44054404 .@"extern",
44064405 .func,
44074406 .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:
970970 const ip = &zcu.intern_pool;
971971 const gpa = comp.gpa;
972972 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;
974974 assert(!ip.isFunctionType(nav_ty));
975975
976976 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 {
173046173046 .runtime_nav_ptr => {
173047173047 const ty_nav = air_datas[@intFromEnum(inst)].ty_nav;
173048173048 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
173051173051 if (is_threadlocal) switch (cg.target.ofmt) {
173052173052 .elf => if (cg.mod.pic) {
......@@ -179146,7 +179146,7 @@ fn genSetMem(
179146179146 .off = disp,
179147179147 }).compare(.gte, src_align),
179148179148 .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),
179150179150 .uav => |uav| Type.fromInterned(uav.orig_ty).ptrAlignment(zcu).compare(.gte, src_align),
179151179151 })).write(self, .{
179152179152 .base = base,
src/codegen/x86_64/Emit.zig+16-23
......@@ -115,33 +115,26 @@ pub fn emitMir(emit: *Emit) Error!void {
115115 return error.EmitFail;
116116 },
117117 };
118 break :target switch (ip.getNav(nav).status) {
119 .unresolved => unreachable,
120 .type_resolved => |type_resolved| .{
118 const resolved_nav = ip.getNav(nav).resolved.?;
119 if (resolved_nav.value != .none) switch (ip.indexToKey(resolved_nav.value)) {
120 .@"extern" => |@"extern"| break :target .{
121121 .index = sym_index,
122 .is_extern = false,
123 .type = if (type_resolved.is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol,
124 },
125 .fully_resolved => |fully_resolved| switch (ip.indexToKey(fully_resolved.val)) {
126 .@"extern" => |@"extern"| .{
127 .index = sym_index,
128 .is_extern = switch (@"extern".visibility) {
129 .default => true,
130 .hidden, .protected => false,
131 },
132 .type = if (@"extern".is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol,
133 .force_pcrel_direct = switch (@"extern".relocation) {
134 .any => false,
135 .pcrel => true,
136 },
122 .is_extern = switch (@"extern".visibility) {
123 .default => true,
124 .hidden, .protected => false,
137125 },
138 .variable => |variable| .{
139 .index = sym_index,
140 .is_extern = false,
141 .type = if (variable.is_threadlocal and comp.config.any_non_single_threaded) .tlv else .symbol,
126 .type = if (resolved_nav.@"threadlocal" and comp.config.any_non_single_threaded) .tlv else .symbol,
127 .force_pcrel_direct = switch (@"extern".relocation) {
128 .any => false,
129 .pcrel => true,
142130 },
143 else => .{ .index = sym_index, .is_extern = false, .type = .symbol },
144131 },
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,
145138 };
146139 },
147140 .uav => |uav| .{
src/link.zig+1-1
......@@ -781,7 +781,7 @@ pub const File = struct {
781781 fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateNavError!void {
782782 assert(base.comp.zcu.?.llvm_object == null);
783783 const nav = pt.zcu.intern_pool.getNav(nav_index);
784 assert(nav.status == .fully_resolved);
784 assert(nav.resolved.?.value != .none);
785785 switch (base.tag) {
786786 .lld => unreachable,
787787 .plan9 => unreachable,
src/link/C.zig+7-6
......@@ -534,11 +534,11 @@ pub fn updateNav(
534534 const ip = &zcu.intern_pool;
535535
536536 const nav = ip.getNav(nav_index);
537 switch (ip.indexToKey(nav.status.fully_resolved.val)) {
537 switch (ip.indexToKey(nav.resolved.?.value)) {
538538 .func => return,
539539 .@"extern" => {},
540540 else => {
541 const nav_ty: Type = .fromInterned(nav.typeOf(ip));
541 const nav_ty: Type = .fromInterned(nav.resolved.?.type);
542542 if (!nav_ty.hasRuntimeBits(zcu)) {
543543 if (c.navs.fetchSwapRemove(nav_index)) |kv| {
544544 var old_rendered = kv.value;
......@@ -762,7 +762,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
762762 {
763763 const unit_references = try zcu.resolveReferences();
764764 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;
766766 const check_unit: ?InternPool.AnalUnit = switch (ip.indexToKey(nav_val)) {
767767 else => .wrap(.{ .nav_val = nav }),
768768 .func => .wrap(.{ .func = nav_val }),
......@@ -1092,8 +1092,9 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog
10921092 // NAV forward declarations
10931093 for (need_navs.keys()) |nav| {
10941094 if (c.exported_navs.contains(nav)) continue; // the export was the declaration
1095 if (ip.getNav(nav).getExtern(ip)) |e| {
1096 if (export_names.contains(e.name)) continue;
1095 switch (ip.indexToKey(ip.getNav(nav).resolved.?.value)) {
1096 .@"extern" => |e| if (export_names.contains(e.name)) continue,
1097 else => {},
10971098 }
10981099 const fwd_decl = c.navs.getPtr(nav).?.fwd_decl;
10991100 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
12001201 const code = c.navs.getPtr(nav).?.code;
12011202 if (code.len == 0) continue;
12021203 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";
12041205 f.appendBufAssumeCapacity(if (is_extern) "zig_extern " else "static ");
12051206 }
12061207 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
12261226fn navSection(
12271227 coff: *Coff,
12281228 zcu: *Zcu,
1229 nav_fr: @FieldType(@FieldType(InternPool.Nav, "status"), "fully_resolved"),
1229 nav_resolved: @typeInfo(@FieldType(InternPool.Nav, "resolved")).optional.child,
12301230) !Symbol.Index {
12311231 const ip = &zcu.intern_pool;
12321232 const default: String, const attributes: ObjectSectionAttributes =
1233 switch (ip.indexToKey(nav_fr.val)) {
1234 else => .{ .@".rdata", .{ .read = true } },
1235 .variable => |variable| if (variable.is_threadlocal and
1236 coff.base.comp.config.any_non_single_threaded)
1237 .{ .@".tls$", .{ .read = true, .write = true } }
1238 else
1239 .{ .@".data", .{ .read = true, .write = true } },
1240 .@"extern" => |@"extern"| if (@"extern".is_threadlocal and
1241 coff.base.comp.config.any_non_single_threaded)
1242 .{ .@".tls$", .{ .read = true, .write = true } }
1243 else if (ip.isFunctionType(@"extern".ty))
1244 .{ .@".text", .{ .read = true, .execute = true } }
1245 else if (@"extern".is_const)
1246 .{ .@".rdata", .{ .read = true } }
1247 else
1248 .{ .@".data", .{ .read = true, .write = true } },
1249 .func => .{ .@".text", .{ .read = true, .execute = true } },
1233 if (nav_resolved.@"threadlocal" and coff.base.comp.config.any_non_single_threaded) .{
1234 .@".tls$", .{ .read = true, .write = true },
1235 } else if (ip.isFunctionType(nav_resolved.type)) .{
1236 .@".text", .{ .read = true, .execute = true },
1237 } else if (nav_resolved.@"const") .{
1238 .@".rdata", .{ .read = true },
1239 } else .{
1240 .@".data", .{ .read = true, .write = true },
12501241 };
1242
12511243 return (try coff.objectSectionMapIndex(
1252 (try coff.getOrPutOptionalString(nav_fr.@"linksection".toSlice(ip))).unwrap() orelse default,
1253 switch (nav_fr.@"linksection") {
1244 (try coff.getOrPutOptionalString(nav_resolved.@"linksection".toSlice(ip))).unwrap() orelse default,
1245 switch (nav_resolved.@"linksection") {
12541246 .none => coff.mf.flags.block_size,
1255 else => switch (nav_fr.alignment) {
1256 .none => Type.fromInterned(ip.typeOf(nav_fr.val)).abiAlignment(zcu),
1247 else => switch (nav_resolved.@"align") {
1248 .none => Type.fromInterned(ip.typeOf(nav_resolved.value)).abiAlignment(zcu),
12571249 else => |alignment| alignment,
12581250 }.toStdMem(),
12591251 },
......@@ -1536,20 +1528,15 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
15361528 const ip = &zcu.intern_pool;
15371529
15381530 const nav = ip.getNav(nav_index);
1539 const nav_val = nav.status.fully_resolved.val;
1540 const nav_init = switch (ip.indexToKey(nav_val)) {
1541 else => nav_val,
1542 .variable => |variable| variable.init,
1543 .@"extern", .func => .none,
1544 };
1545 if (nav_init == .none or !Type.fromInterned(ip.typeOf(nav_init)).hasRuntimeBits(zcu)) return;
1531 if (ip.indexToKey(nav.resolved.?.value) == .@"extern") return;
1532 if (!Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) return;
15461533
15471534 const nmi = try coff.navMapIndex(zcu, nav_index);
15481535 const si = nmi.symbol(coff);
15491536 const ni = ni: {
15501537 switch (si.get(coff).ni) {
15511538 .none => {
1552 const sec_si = try coff.navSection(zcu, nav.status.fully_resolved);
1539 const sec_si = try coff.navSection(zcu, nav.resolved.?);
15531540 try coff.nodes.ensureUnusedCapacity(gpa, 1);
15541541 const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{
15551542 .alignment = zcu.navAlignment(nav_index).toStdMem(),
......@@ -1576,7 +1563,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
15761563 &coff.base,
15771564 pt,
15781565 zcu.navSrcLoc(nav_index),
1579 .fromInterned(nav_init),
1566 .fromInterned(nav.resolved.?.value),
15801567 &nw.interface,
15811568 .{ .atom_index = @intFromEnum(si) },
15821569 ) catch |err| switch (err) {
......@@ -1587,7 +1574,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde
15871574 si.applyLocationRelocs(coff);
15881575 }
15891576
1590 if (nav.status.fully_resolved.@"linksection".unwrap()) |_| {
1577 if (nav.resolved.?.@"linksection".unwrap()) |_| {
15911578 try ni.resize(&coff.mf, gpa, si.get(coff).size);
15921579 var parent_ni = ni;
15931580 while (true) {
......@@ -1674,12 +1661,12 @@ fn updateFuncInner(
16741661 const ni = ni: {
16751662 switch (si.get(coff).ni) {
16761663 .none => {
1677 const sec_si = try coff.navSection(zcu, nav.status.fully_resolved);
1664 const sec_si = try coff.navSection(zcu, nav.resolved.?);
16781665 try coff.nodes.ensureUnusedCapacity(gpa, 1);
16791666 const mod = zcu.navFileScope(func.owner_nav).mod.?;
16801667 const target = &mod.resolved_target.result;
16811668 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") {
16831670 .none => switch (mod.optimize_mode) {
16841671 .Debug,
16851672 .ReleaseSafe,
src/link/Dwarf.zig+8-11
......@@ -2681,7 +2681,7 @@ fn initWipNavInner(
26812681 } else try wip_nav.infoExprLoc(.{ .addr_reloc = sym_index });
26822682 },
26832683 .syntax => switch (ip.isFunctionType(@"extern".ty)) {
2684 false => continue :nav_val .{ .variable = undefined },
2684 false => continue :nav_val .{ .undef = @"extern".ty },
26852685 true => {
26862686 const func_type = ip.indexToKey(@"extern".ty).func_type;
26872687 const diw = &wip_nav.debug_info.writer;
......@@ -2777,7 +2777,7 @@ fn initWipNavInner(
27772777 wip_nav.func_high_pc = @intCast(diw.end);
27782778 try diw.writeInt(u32, 0, dwarf.endian);
27792779 const target = &mod.resolved_target.result;
2780 try diw.writeUleb128(switch (nav.status.fully_resolved.alignment) {
2780 try diw.writeUleb128(switch (nav.resolved.?.@"align") {
27812781 .none => target_info.defaultFunctionAlignment(target),
27822782 else => |a| a.maxStrict(target_info.minFunctionAlignment(target)),
27832783 }.toByteUnits().?);
......@@ -2845,7 +2845,7 @@ fn initWipNavInner(
28452845 .@"const" => {
28462846 const const_ty_reloc_index = try wip_nav.refForward();
28472847 try wip_nav.infoExprLoc(loc);
2848 try diw.writeUleb128(nav.status.fully_resolved.alignment.toByteUnits() orelse
2848 try diw.writeUleb128(nav.resolved.?.@"align".toByteUnits() orelse
28492849 ty.abiAlignment(zcu).toByteUnits().?);
28502850 try diw.writeByte(@intFromBool(decl.linkage != .normal));
28512851 wip_nav.finishForward(const_ty_reloc_index);
......@@ -2855,7 +2855,7 @@ fn initWipNavInner(
28552855 .@"var" => {
28562856 try wip_nav.refType(ty);
28572857 try wip_nav.infoExprLoc(loc);
2858 try diw.writeUleb128(nav.status.fully_resolved.alignment.toByteUnits() orelse
2858 try diw.writeUleb128(nav.resolved.?.@"align".toByteUnits() orelse
28592859 ty.abiAlignment(zcu).toByteUnits().?);
28602860 try diw.writeByte(@intFromBool(decl.linkage != .normal));
28612861 },
......@@ -3028,10 +3028,10 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
30283028 const zcu = pt.zcu;
30293029 const ip = &zcu.intern_pool;
30303030 const nav_src_loc = zcu.navSrcLoc(nav_index);
3031 const nav_val = zcu.navValue(nav_index);
30323031
30333032 const nav = ip.getNav(nav_index);
30343033 const inst_info = nav.srcInst(ip).resolveFull(ip).?;
3034 const nav_val: Value = .fromInterned(nav.resolved.?.value);
30353035 const file = zcu.fileByIndex(inst_info.file);
30363036 const decl = file.zir.?.getDeclaration(inst_info.inst);
30373037 log.debug("updateComptimeNav({s}:{d}:{d} %{d} = {f})", .{
......@@ -3127,9 +3127,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
31273127 .aggregate,
31283128 .un,
31293129 .bitpack,
3130 => .@"const",
3131
3132 .variable => .@"var",
3130 => if (nav.resolved.?.@"const") .@"const" else .@"var",
31333131
31343132 .@"extern" => unreachable,
31353133
......@@ -3210,7 +3208,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
32103208 const nav_ty = nav_val.typeOf(zcu);
32113209 try wip_nav.refType(nav_ty);
32123210 try wip_nav.blockValue(nav_src_loc, nav_val);
3213 try diw.writeUleb128(nav.status.fully_resolved.alignment.toByteUnits() orelse
3211 try diw.writeUleb128(nav.resolved.?.@"align".toByteUnits() orelse
32143212 nav_ty.abiAlignment(zcu).toByteUnits().?);
32153213 try diw.writeByte(@intFromBool(decl.linkage != .normal));
32163214 },
......@@ -3240,7 +3238,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
32403238 .@"extern", .@"export" => nav.name,
32413239 }.toSlice(ip));
32423240 const nav_ty_reloc_index = try wip_nav.refForward();
3243 try diw.writeUleb128(nav.status.fully_resolved.alignment.toByteUnits() orelse
3241 try diw.writeUleb128(nav.resolved.?.@"align".toByteUnits() orelse
32443242 nav_ty.abiAlignment(zcu).toByteUnits().?);
32453243 try diw.writeByte(@intFromBool(decl.linkage != .normal));
32463244 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
42814279 try wip_nav.refType(.null);
42824280 },
42834281 },
4284 .variable => unreachable, // not a value
42854282 .int => |int| {
42864283 try wip_nav.bigIntConstValue(.{
42874284 .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
11131113 if (!gop.found_existing) {
11141114 const symbol_index = try self.newSymbolWithAtom(gpa, 0);
11151115 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) {
11171117 sym.flags.is_tls = true;
11181118 }
11191119 gop.value_ptr.* = .{ .symbol_index = symbol_index };
......@@ -1143,9 +1143,10 @@ fn getNavShdrIndex(
11431143 const gpa = elf_file.base.comp.gpa;
11441144 const ptr_size = elf_file.ptrWidthBytes();
11451145 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);
11471148 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"| {
11491150 const section_name = @"linksection".toSlice(ip);
11501151 if (elf_file.sectionByName(section_name)) |osec| {
11511152 if (is_func) {
......@@ -1258,13 +1259,8 @@ fn getNavShdrIndex(
12581259 self.text_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".text"), osec);
12591260 return osec;
12601261 }
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 };
12661262 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) {
12681264 const is_bss = !has_relocs and for (code) |byte| {
12691265 if (byte != 0) break false;
12701266 } else true;
......@@ -1291,7 +1287,7 @@ fn getNavShdrIndex(
12911287 self.tdata_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".tdata"), osec);
12921288 return osec;
12931289 }
1294 if (is_const) {
1290 if (nav.resolved.?.@"const") {
12951291 if (self.data_relro_index) |symbol_index|
12961292 return self.symbol(symbol_index).outputShndx(elf_file).?;
12971293 const osec = try elf_file.addSection(.{
......@@ -1303,7 +1299,7 @@ fn getNavShdrIndex(
13031299 self.data_relro_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".data.rel.ro"), osec);
13041300 return osec;
13051301 }
1306 if (nav_init != .none and Value.fromInterned(nav_init).isUndef(zcu))
1302 if (nav_val.isUndef(zcu))
13071303 return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) {
13081304 .Debug, .ReleaseSafe => {
13091305 if (self.data_index) |symbol_index|
......@@ -1378,7 +1374,7 @@ fn updateNavCode(
13781374
13791375 const mod = zcu.navFileScope(nav_index).mod.?;
13801376 const target = &mod.resolved_target.result;
1381 const required_alignment = switch (nav.status.fully_resolved.alignment) {
1377 const required_alignment = switch (nav.resolved.?.@"align") {
13821378 .none => switch (mod.optimize_mode) {
13831379 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),
13841380 .ReleaseSmall => target_util.minFunctionAlignment(target),
......@@ -1647,16 +1643,17 @@ pub fn updateNav(
16471643
16481644 log.debug("updateNav {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
16491645
1650 const nav_init = switch (ip.indexToKey(nav.status.fully_resolved.val)) {
1651 .func => .none,
1652 .variable => |variable| variable.init,
1646 switch (ip.indexToKey(nav.resolved.?.value)) {
1647 else => {},
16531648 .@"extern" => |@"extern"| {
16541649 const sym_index = try self.getGlobalSymbol(
16551650 elf_file,
16561651 nav.name.toSlice(ip),
16571652 @"extern".lib_name.toSlice(ip),
16581653 );
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 }
16601657 if (self.dwarf) |*dwarf| {
16611658 var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index);
16621659 defer debug_wip_nav.deinit();
......@@ -1668,10 +1665,9 @@ pub fn updateNav(
16681665 }
16691666 return;
16701667 },
1671 else => nav.status.fully_resolved.val,
1672 };
1668 }
16731669
1674 if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) {
1670 if (Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) {
16751671 const sym_index = try self.getOrCreateMetadataForNav(zcu, nav_index);
16761672 self.symbol(sym_index).atom(elf_file).?.freeRelocs(self);
16771673
......@@ -1685,7 +1681,7 @@ pub fn updateNav(
16851681 &elf_file.base,
16861682 pt,
16871683 zcu.navSrcLoc(nav_index),
1688 Value.fromInterned(nav_init),
1684 .fromInterned(nav.resolved.?.value),
16891685 &aw.writer,
16901686 .{ .atom_index = sym_index },
16911687 ) catch |err| switch (err) {
src/link/Elf2.zig+19-41
......@@ -1876,32 +1876,15 @@ pub fn globalSymbol(elf: *Elf, opts: struct {
18761876
18771877fn navType(
18781878 ip: *const InternPool,
1879 nav_status: @FieldType(InternPool.Nav, "status"),
1879 nav_resolved: @typeInfo(@FieldType(InternPool.Nav, "resolved")).optional.child,
18801880 any_non_single_threaded: bool,
18811881) std.elf.STT {
1882 return switch (nav_status) {
1883 .unresolved => unreachable,
1884 .type_resolved => |tr| if (any_non_single_threaded and tr.is_threadlocal)
1885 .TLS
1886 else if (ip.isFunctionType(tr.type))
1887 .FUNC
1888 else
1889 .OBJECT,
1890 .fully_resolved => |fr| switch (ip.indexToKey(fr.val)) {
1891 else => .OBJECT,
1892 .variable => |variable| if (any_non_single_threaded and variable.is_threadlocal)
1893 .TLS
1894 else
1895 .OBJECT,
1896 .@"extern" => |@"extern"| if (any_non_single_threaded and @"extern".is_threadlocal)
1897 .TLS
1898 else if (ip.isFunctionType(@"extern".ty))
1899 .FUNC
1900 else
1901 .OBJECT,
1902 .func => .FUNC,
1903 },
1904 };
1882 return if (any_non_single_threaded and nav_resolved.@"threadlocal")
1883 .TLS
1884 else if (ip.isFunctionType(nav_resolved.type))
1885 .FUNC
1886 else
1887 .OBJECT;
19051888}
19061889fn namedSection(elf: *const Elf, name: []const u8) ?Symbol.Index {
19071890 if (std.mem.eql(u8, name, ".rodata") or
......@@ -1917,13 +1900,13 @@ fn namedSection(elf: *const Elf, name: []const u8) ?Symbol.Index {
19171900fn navSection(
19181901 elf: *Elf,
19191902 ip: *const InternPool,
1920 nav_fr: @FieldType(@FieldType(InternPool.Nav, "status"), "fully_resolved"),
1903 nav_resolved: @typeInfo(@FieldType(InternPool.Nav, "resolved")).optional.child,
19211904) Symbol.Index {
1922 if (nav_fr.@"linksection".toSlice(ip)) |@"linksection"|
1905 if (nav_resolved.@"linksection".toSlice(ip)) |@"linksection"|
19231906 if (elf.namedSection(@"linksection")) |si| return si;
19241907 return switch (navType(
19251908 ip,
1926 .{ .fully_resolved = nav_fr },
1909 nav_resolved,
19271910 elf.base.comp.config.any_non_single_threaded,
19281911 )) {
19291912 else => unreachable,
......@@ -1940,7 +1923,7 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.NavM
19401923 const nav_gop = try elf.navs.getOrPut(gpa, nav_index);
19411924 if (!nav_gop.found_existing) nav_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{
19421925 .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),
19441927 });
19451928 return @enumFromInt(nav_gop.index);
19461929}
......@@ -1950,7 +1933,7 @@ pub fn navSymbol(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol.
19501933 if (nav.getExtern(ip)) |@"extern"| return elf.globalSymbol(.{
19511934 .name = @"extern".name.toSlice(ip),
19521935 .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),
19541937 .bind = switch (@"extern".linkage) {
19551938 .internal => .LOCAL,
19561939 .strong => .GLOBAL,
......@@ -2889,13 +2872,8 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
28892872 const ip = &zcu.intern_pool;
28902873
28912874 const nav = ip.getNav(nav_index);
2892 const nav_val = nav.status.fully_resolved.val;
2893 const nav_init = switch (ip.indexToKey(nav_val)) {
2894 else => nav_val,
2895 .variable => |variable| variable.init,
2896 .@"extern", .func => .none,
2897 };
2898 if (nav_init == .none or !Type.fromInterned(ip.typeOf(nav_init)).hasRuntimeBits(zcu)) return;
2875 if (ip.indexToKey(nav.resolved.?.value) == .@"extern") return;
2876 if (!Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) return;
28992877
29002878 const nmi = try elf.navMapIndex(zcu, nav_index);
29012879 const si = nmi.symbol(elf);
......@@ -2904,7 +2882,7 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
29042882 switch (sym.ni) {
29052883 .none => {
29062884 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.?);
29082886 const ni = try elf.mf.addLastChildNode(gpa, sec_si.node(elf), .{
29092887 .alignment = zcu.navAlignment(nav_index).toStdMem(),
29102888 .moved = true,
......@@ -2930,7 +2908,7 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index)
29302908 &elf.base,
29312909 pt,
29322910 zcu.navSrcLoc(nav_index),
2933 .fromInterned(nav_init),
2911 .fromInterned(nav.resolved.?.value),
29342912 &nw.interface,
29352913 .{ .atom_index = @intFromEnum(si) },
29362914 ) catch |err| switch (err) {
......@@ -3021,11 +2999,11 @@ fn updateFuncInner(
30212999 switch (sym.ni) {
30223000 .none => {
30233001 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.?);
30253003 const mod = zcu.navFileScope(func.owner_nav).mod.?;
30263004 const target = &mod.resolved_target.result;
30273005 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") {
30293007 .none => switch (mod.optimize_mode) {
30303008 .Debug,
30313009 .ReleaseSafe,
......@@ -3677,7 +3655,7 @@ fn updateExportsInner(
36773655 const exported_si: Symbol.Index, const @"type": std.elf.STT = switch (exported) {
36783656 .nav => |nav| .{
36793657 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),
36813659 },
36823660 .uav => |uav| .{ @enumFromInt(switch (try elf.lowerUav(
36833661 pt,
src/link/MachO/ZigObject.zig+13-19
......@@ -877,15 +877,14 @@ pub fn updateNav(
877877 const ip = &zcu.intern_pool;
878878 const nav = ip.getNav(nav_index);
879879
880 const nav_init = switch (ip.indexToKey(nav.status.fully_resolved.val)) {
881 .func => .none,
882 .variable => |variable| variable.init,
880 switch (ip.indexToKey(nav.resolved.?.value)) {
881 else => {},
883882 .@"extern" => |@"extern"| {
884883 // Extern variable gets a __got entry only
885884 const name = @"extern".name.toSlice(ip);
886885 const lib_name = @"extern".lib_name.toSlice(ip);
887886 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;
889888 if (self.dwarf) |*dwarf| {
890889 var debug_wip_nav = try dwarf.initWipNav(pt, nav_index, sym_index);
891890 defer debug_wip_nav.deinit();
......@@ -897,10 +896,9 @@ pub fn updateNav(
897896 }
898897 return;
899898 },
900 else => nav.status.fully_resolved.val,
901 };
899 }
902900
903 if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) {
901 if (Type.fromInterned(nav.resolved.?.type).hasRuntimeBits(zcu)) {
904902 const sym_index = try self.getOrCreateMetadataForNav(macho_file, nav_index);
905903 self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file);
906904
......@@ -914,7 +912,7 @@ pub fn updateNav(
914912 &macho_file.base,
915913 pt,
916914 zcu.navSrcLoc(nav_index),
917 Value.fromInterned(nav_init),
915 .fromInterned(nav.resolved.?.value),
918916 &aw.writer,
919917 .{ .atom_index = sym_index },
920918 ) catch |err| switch (err) {
......@@ -959,7 +957,7 @@ fn updateNavCode(
959957
960958 const mod = zcu.navFileScope(nav_index).mod.?;
961959 const target = &mod.resolved_target.result;
962 const required_alignment = switch (nav.status.fully_resolved.alignment) {
960 const required_alignment = switch (nav.resolved.?.@"align") {
963961 .none => switch (mod.optimize_mode) {
964962 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),
965963 .ReleaseSmall => target_util.minFunctionAlignment(target),
......@@ -1167,14 +1165,10 @@ fn getNavOutputSection(
11671165) error{OutOfMemory}!u8 {
11681166 _ = self;
11691167 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);
11711170 if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) return macho_file.zig_text_sect_index.?;
1172 const is_const, const is_threadlocal, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
1173 .variable => |variable| .{ false, variable.is_threadlocal, variable.init },
1174 .@"extern" => |@"extern"| .{ @"extern".is_const, @"extern".is_threadlocal, .none },
1175 else => .{ true, false, nav_val.toIntern() },
1176 };
1177 if (is_threadlocal and macho_file.base.comp.config.any_non_single_threaded) {
1171 if (nav.resolved.?.@"threadlocal" and macho_file.base.comp.config.any_non_single_threaded) {
11781172 for (code) |byte| {
11791173 if (byte != 0) break;
11801174 } else return macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection(
......@@ -1188,8 +1182,8 @@ fn getNavOutputSection(
11881182 .{ .flags = macho.S_THREAD_LOCAL_REGULAR },
11891183 );
11901184 }
1191 if (is_const) return macho_file.zig_const_sect_index.?;
1192 if (nav_init != .none and Value.fromInterned(nav_init).isUndef(zcu))
1185 if (nav.resolved.?.@"const") return macho_file.zig_const_sect_index.?;
1186 if (nav_val.isUndef(zcu))
11931187 return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) {
11941188 .Debug, .ReleaseSafe => macho_file.zig_data_sect_index.?,
11951189 .ReleaseFast, .ReleaseSmall => macho_file.zig_bss_sect_index.?,
......@@ -1550,7 +1544,7 @@ fn isThreadlocal(macho_file: *MachO, nav_index: InternPool.Nav.Index) bool {
15501544 if (!macho_file.base.comp.config.any_non_single_threaded)
15511545 return false;
15521546 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";
15541548}
15551549
15561550fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index {
src/link/SpirV.zig+1-1
......@@ -189,7 +189,7 @@ pub fn updateExports(
189189 @panic("TODO: implement Linker linker code for exporting a constant value");
190190 },
191191 };
192 const nav_ty = ip.getNav(nav_index).typeOf(ip);
192 const nav_ty = ip.getNav(nav_index).resolved.?.type;
193193 const target = zcu.getTarget();
194194 if (ip.isFunctionType(nav_ty)) {
195195 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) {
420420 const zcu = wasm.base.comp.zcu.?;
421421 const ip = &zcu.intern_pool;
422422 const nav = ip.getNav(nav_index);
423 return fromIpIndex(wasm, nav.status.fully_resolved.val);
423 return fromIpIndex(wasm, nav.resolved.?.value);
424424 }
425425
426426 pub fn fromTagNameType(wasm: *const Wasm, tag_type: InternPool.Index) OutputFunctionIndex {
......@@ -1022,7 +1022,7 @@ pub const FunctionImport = extern struct {
10221022 pub fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) Resolution {
10231023 const zcu = wasm.base.comp.zcu.?;
10241024 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);
10261026 }
10271027
10281028 pub fn fromZcuFunc(wasm: *const Wasm, i: ZcuFunc.Index) Resolution {
......@@ -1885,7 +1885,7 @@ pub const DataSegmentId = enum(u32) {
18851885 const zcu = wasm.base.comp.zcu.?;
18861886 const ip = &zcu.intern_pool;
18871887 const nav = ip.getNav(i.key(wasm).*);
1888 if (nav.isThreadlocal(ip)) return .tls;
1888 if (nav.resolved.?.@"threadlocal") return .tls;
18891889 const code = i.value(wasm).code;
18901890 return if (code.off == .none) .zero else .data;
18911891 },
......@@ -1908,7 +1908,7 @@ pub const DataSegmentId = enum(u32) {
19081908 const zcu = wasm.base.comp.zcu.?;
19091909 const ip = &zcu.intern_pool;
19101910 const nav = ip.getNav(i.key(wasm).*);
1911 return nav.isThreadlocal(ip);
1911 return nav.resolved.?.@"threadlocal";
19121912 },
19131913 };
19141914 }
......@@ -1934,7 +1934,7 @@ pub const DataSegmentId = enum(u32) {
19341934 const zcu = wasm.base.comp.zcu.?;
19351935 const ip = &zcu.intern_pool;
19361936 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)) {
19381938 .tls => ".tdata",
19391939 .data => ".data",
19401940 .zero => ".bss",
......@@ -1962,9 +1962,9 @@ pub const DataSegmentId = enum(u32) {
19621962 const zcu = wasm.base.comp.zcu.?;
19631963 const ip = &zcu.intern_pool;
19641964 const nav = ip.getNav(i.key(wasm).*);
1965 const explicit = nav.getAlignment();
1965 const explicit = nav.resolved.?.@"align";
19661966 if (explicit != .none) return explicit;
1967 const ty: Zcu.Type = .fromInterned(nav.typeOf(ip));
1967 const ty: Zcu.Type = .fromInterned(nav.resolved.?.type);
19681968 const result = ty.abiAlignment(zcu);
19691969 assert(result != .none);
19701970 return result;
......@@ -2269,7 +2269,7 @@ pub const ZcuImportIndex = enum(u32) {
22692269 const zcu = wasm.base.comp.zcu.?;
22702270 const ip = &zcu.intern_pool;
22712271 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";
22732273 const name_slice = ext.name.toSlice(ip);
22742274 return wasm.getExistingString(name_slice).?;
22752275 }
......@@ -2278,7 +2278,7 @@ pub const ZcuImportIndex = enum(u32) {
22782278 const zcu = wasm.base.comp.zcu.?;
22792279 const ip = &zcu.intern_pool;
22802280 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";
22822282 const lib_name = ext.lib_name.toSlice(ip) orelse return .none;
22832283 return wasm.getExistingString(lib_name).?.toOptional();
22842284 }
......@@ -2289,7 +2289,7 @@ pub const ZcuImportIndex = enum(u32) {
22892289 const zcu = comp.zcu.?;
22902290 const ip = &zcu.intern_pool;
22912291 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";
22932293 const fn_info = zcu.typeToFunc(.fromInterned(ext.ty)).?;
22942294 return getExistingFunctionType(wasm, fn_info.cc, fn_info.param_types.get(ip), .fromInterned(fn_info.return_type), target).?;
22952295 }
......@@ -2381,7 +2381,7 @@ pub const FunctionImportId = enum(u32) {
23812381 .zcu_import => |i| {
23822382 const zcu = wasm.base.comp.zcu.?;
23832383 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";
23852385 return ext.linkage != .weak and ext.lib_name != .none;
23862386 },
23872387 };
......@@ -3288,7 +3288,8 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
32883288 const is_obj = comp.config.output_mode == .Obj;
32893289 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 => {},
32923293 .func => return, // global const which is a function alias
32933294 .@"extern" => |ext| {
32943295 if (is_obj) {
......@@ -3302,7 +3303,7 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
33023303 try wasm.function_imports.ensureUnusedCapacity(gpa, 1);
33033304 try wasm.data_imports.ensureUnusedCapacity(gpa, 1);
33043305 const zcu_import = wasm.addZcuImportReserved(ext.owner_nav);
3305 if (ip.isFunctionType(nav.typeOf(ip))) {
3306 if (ip.isFunctionType(nav.resolved.?.type)) {
33063307 wasm.function_imports.putAssumeCapacity(name, .fromZcuImport(zcu_import, wasm));
33073308 // Ensure there is a corresponding function type table entry.
33083309 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
33123313 }
33133314 return;
33143315 },
3315 .variable => |variable| .{ variable.init, variable.owner_nav },
3316 else => .{ nav.status.fully_resolved.val, nav_index },
3317 };
3318 //log.debug("updateNav {f} {d}", .{ nav.fqn.fmt(ip), chased_nav_index });
3319 assert(!wasm.imports.contains(chased_nav_index));
3316 }
3317 //log.debug("updateNav {f} {d}", .{ nav.fqn.fmt(ip), nav_index });
3318 assert(!wasm.imports.contains(nav_index));
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)) {
33223321 if (is_obj) {
3323 assert(!wasm.navs_obj.contains(chased_nav_index));
3322 assert(!wasm.navs_obj.contains(nav_index));
33243323 } else {
3325 assert(!wasm.navs_exe.contains(chased_nav_index));
3324 assert(!wasm.navs_exe.contains(nav_index));
33263325 }
33273326 return;
33283327 }
33293328
33303329 if (is_obj) {
33313330 const zcu_data_starts: ZcuDataStarts = .initObj(wasm);
3332 const navs_i = try refNavObj(wasm, chased_nav_index);
3333 const zcu_data = try lowerZcuData(wasm, pt, nav_init);
3331 const navs_i = try refNavObj(wasm, nav_index);
3332 const zcu_data = try lowerZcuData(wasm, pt, nav.resolved.?.value);
33343333 navs_i.value(wasm).* = zcu_data;
33353334 try zcu_data_starts.finishObj(wasm, pt);
33363335 } else {
33373336 const zcu_data_starts: ZcuDataStarts = .initExe(wasm);
3338 const navs_i = try refNavExe(wasm, chased_nav_index);
3339 const zcu_data = try lowerZcuData(wasm, pt, nav_init);
3337 const navs_i = try refNavExe(wasm, nav_index);
3338 const zcu_data = try lowerZcuData(wasm, pt, nav.resolved.?.value);
33403339 navs_i.value(wasm).code = zcu_data.code;
33413340 try zcu_data_starts.finishExe(wasm, pt);
33423341 }
......@@ -4173,9 +4172,8 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 {
41734172 }
41744173 const zcu = comp.zcu.?;
41754174 const ip = &zcu.intern_pool;
4176 const nav = ip.getNav(nav_index);
4177 if (nav.getResolvedExtern(ip)) |ext| {
4178 if (wasm.getExistingString(ext.name.toSlice(ip))) |symbol_name| {
4175 switch (ip.indexToKey(ip.getNav(nav_index).resolved.?.value)) {
4176 .@"extern" => |ext| if (wasm.getExistingString(ext.name.toSlice(ip))) |symbol_name| {
41794177 if (wasm.object_data_imports.getPtr(symbol_name)) |import| {
41804178 switch (import.resolution.unpack(wasm)) {
41814179 .unresolved => unreachable,
......@@ -4195,7 +4193,8 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 {
41954193 .nav_obj => @panic("TODO"),
41964194 }
41974195 }
4198 }
4196 },
4197 else => {},
41994198 }
42004199 // Otherwise it's a zero bit type; any address will do.
42014200 return 0;
src/link/Wasm/Flush.zig+1-1
......@@ -211,7 +211,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
211211 }
212212
213213 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)) {
215215 log.debug("flush export '{s}' nav={d}", .{ nav_export.name.slice(wasm), nav_export.nav_index });
216216 const function_index = Wasm.FunctionIndex.fromIpNav(wasm, nav_export.nav_index).?;
217217 const explicit = f.missing_exports.swapRemove(nav_export.name);
src/print_value.zig-1
......@@ -74,7 +74,6 @@ pub fn print(
7474 .@"unreachable",
7575 => try writer.writeAll(@tagName(simple_value)),
7676 },
77 .variable => try writer.writeAll("(variable)"),
7877 .@"extern" => |e| try writer.print("(extern '{f}')", .{e.name.fmt(ip)}),
7978 .func => |func| try writer.print("(function '{f}')", .{ip.getNav(func.owner_nav).name.fmt(ip)}),
8079 .int => |int| switch (int.storage) {