| author | |
| committer | |
| log | 7f4bd247c7735ccf277c9bba42222e014cacf856 |
| tree | b47acb0631fc101995b03dd415efe587cec9738b |
| parent | a1b607acb5c1e9dd03760efd7078185e7628b29d |
| signature |
Sema now tracks dependencies appropriately. Early logic in Zcu for
resolving outdated decls/functions is in place. The setup used does not
support `usingnamespace`; compilations using this construct are not yet
supported by this incremental compilation model.5 files changed, 537 insertions(+), 57 deletions(-)
src/Compilation.zig+29-1| ... | ... | @@ -2807,6 +2807,13 @@ const Header = extern struct { |
| 2807 | 2807 | limbs_len: u32, |
| 2808 | 2808 | string_bytes_len: u32, |
| 2809 | 2809 | tracked_insts_len: u32, |
| 2810 | src_hash_deps_len: u32, | |
| 2811 | decl_val_deps_len: u32, | |
| 2812 | namespace_deps_len: u32, | |
| 2813 | namespace_name_deps_len: u32, | |
| 2814 | first_dependency_len: u32, | |
| 2815 | dep_entries_len: u32, | |
| 2816 | free_dep_entries_len: u32, | |
| 2810 | 2817 | }, |
| 2811 | 2818 | }; |
| 2812 | 2819 | |
| ... | ... | @@ -2814,7 +2821,7 @@ const Header = extern struct { |
| 2814 | 2821 | /// saved, such as the target and most CLI flags. A cache hit will only occur |
| 2815 | 2822 | /// when subsequent compiler invocations use the same set of flags. |
| 2816 | 2823 | pub fn saveState(comp: *Compilation) !void { |
| 2817 | var bufs_list: [7]std.os.iovec_const = undefined; | |
| 2824 | var bufs_list: [19]std.os.iovec_const = undefined; | |
| 2818 | 2825 | var bufs_len: usize = 0; |
| 2819 | 2826 | |
| 2820 | 2827 | const lf = comp.bin_file orelse return; |
| ... | ... | @@ -2828,6 +2835,13 @@ pub fn saveState(comp: *Compilation) !void { |
| 2828 | 2835 | .limbs_len = @intCast(ip.limbs.items.len), |
| 2829 | 2836 | .string_bytes_len = @intCast(ip.string_bytes.items.len), |
| 2830 | 2837 | .tracked_insts_len = @intCast(ip.tracked_insts.count()), |
| 2838 | .src_hash_deps_len = @intCast(ip.src_hash_deps.count()), | |
| 2839 | .decl_val_deps_len = @intCast(ip.decl_val_deps.count()), | |
| 2840 | .namespace_deps_len = @intCast(ip.namespace_deps.count()), | |
| 2841 | .namespace_name_deps_len = @intCast(ip.namespace_name_deps.count()), | |
| 2842 | .first_dependency_len = @intCast(ip.first_dependency.count()), | |
| 2843 | .dep_entries_len = @intCast(ip.dep_entries.items.len), | |
| 2844 | .free_dep_entries_len = @intCast(ip.free_dep_entries.items.len), | |
| 2831 | 2845 | }, |
| 2832 | 2846 | }; |
| 2833 | 2847 | addBuf(&bufs_list, &bufs_len, mem.asBytes(&header)); |
| ... | ... | @@ -2838,6 +2852,20 @@ pub fn saveState(comp: *Compilation) !void { |
| 2838 | 2852 | addBuf(&bufs_list, &bufs_len, ip.string_bytes.items); |
| 2839 | 2853 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.tracked_insts.keys())); |
| 2840 | 2854 | |
| 2855 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.src_hash_deps.keys())); | |
| 2856 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.src_hash_deps.values())); | |
| 2857 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.decl_val_deps.keys())); | |
| 2858 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.decl_val_deps.values())); | |
| 2859 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.namespace_deps.keys())); | |
| 2860 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.namespace_deps.values())); | |
| 2861 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.namespace_name_deps.keys())); | |
| 2862 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.namespace_name_deps.values())); | |
| 2863 | ||
| 2864 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.first_dependency.keys())); | |
| 2865 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.first_dependency.values())); | |
| 2866 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.dep_entries.items)); | |
| 2867 | addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.free_dep_entries.items)); | |
| 2868 | ||
| 2841 | 2869 | // TODO: compilation errors |
| 2842 | 2870 | // TODO: files |
| 2843 | 2871 | // TODO: namespaces |
src/InternPool.zig+278-11| ... | ... | @@ -58,6 +58,38 @@ string_table: std.HashMapUnmanaged( |
| 58 | 58 | /// persists across incremental updates. |
| 59 | 59 | tracked_insts: std.AutoArrayHashMapUnmanaged(TrackedInst, void) = .{}, |
| 60 | 60 | |
| 61 | /// Dependencies on the source code hash associated with a ZIR instruction. | |
| 62 | /// * For a `declaration`, this is the entire declaration body. | |
| 63 | /// * For a `struct_decl`, `union_decl`, etc, this is the source of the fields (but not declarations). | |
| 64 | /// * For a `func`, this is the source of the full function signature. | |
| 65 | /// These are also invalidated if tracking fails for this instruction. | |
| 66 | /// Value is index into `dep_entries` of the first dependency on this hash. | |
| 67 | src_hash_deps: std.AutoArrayHashMapUnmanaged(TrackedInst.Index, DepEntry.Index) = .{}, | |
| 68 | /// Dependencies on the value of a Decl. | |
| 69 | /// Value is index into `dep_entries` of the first dependency on this Decl value. | |
| 70 | decl_val_deps: std.AutoArrayHashMapUnmanaged(DeclIndex, DepEntry.Index) = .{}, | |
| 71 | /// Dependencies on the full set of names in a ZIR namespace. | |
| 72 | /// Key refers to a `struct_decl`, `union_decl`, etc. | |
| 73 | /// Value is index into `dep_entries` of the first dependency on this namespace. | |
| 74 | namespace_deps: std.AutoArrayHashMapUnmanaged(TrackedInst.Index, DepEntry.Index) = .{}, | |
| 75 | /// Dependencies on the (non-)existence of some name in a namespace. | |
| 76 | /// Value is index into `dep_entries` of the first dependency on this name. | |
| 77 | namespace_name_deps: std.AutoArrayHashMapUnmanaged(NamespaceNameKey, DepEntry.Index) = .{}, | |
| 78 | ||
| 79 | /// Given a `Depender`, points to an entry in `dep_entries` whose `depender` | |
| 80 | /// matches. The `next_dependee` field can be used to iterate all such entries | |
| 81 | /// and remove them from the corresponding lists. | |
| 82 | first_dependency: std.AutoArrayHashMapUnmanaged(Depender, DepEntry.Index) = .{}, | |
| 83 | ||
| 84 | /// Stores dependency information. The hashmaps declared above are used to look | |
| 85 | /// up entries in this list as required. This is not stored in `extra` so that | |
| 86 | /// we can use `free_dep_entries` to track free indices, since dependencies are | |
| 87 | /// removed frequently. | |
| 88 | dep_entries: std.ArrayListUnmanaged(DepEntry) = .{}, | |
| 89 | /// Stores unused indices in `dep_entries` which can be reused without a full | |
| 90 | /// garbage collection pass. | |
| 91 | free_dep_entries: std.ArrayListUnmanaged(DepEntry.Index) = .{}, | |
| 92 | ||
| 61 | 93 | pub const TrackedInst = extern struct { |
| 62 | 94 | path_digest: Cache.BinDigest, |
| 63 | 95 | inst: Zir.Inst.Index, |
| ... | ... | @@ -70,6 +102,19 @@ pub const TrackedInst = extern struct { |
| 70 | 102 | pub fn resolve(i: TrackedInst.Index, ip: *const InternPool) Zir.Inst.Index { |
| 71 | 103 | return ip.tracked_insts.keys()[@intFromEnum(i)].inst; |
| 72 | 104 | } |
| 105 | pub fn toOptional(i: TrackedInst.Index) Optional { | |
| 106 | return @enumFromInt(@intFromEnum(i)); | |
| 107 | } | |
| 108 | pub const Optional = enum(u32) { | |
| 109 | none = std.math.maxInt(u32), | |
| 110 | _, | |
| 111 | pub fn unwrap(opt: Optional) ?TrackedInst.Index { | |
| 112 | return switch (opt) { | |
| 113 | .none => null, | |
| 114 | _ => @enumFromInt(@intFromEnum(opt)), | |
| 115 | }; | |
| 116 | } | |
| 117 | }; | |
| 73 | 118 | }; |
| 74 | 119 | }; |
| 75 | 120 | |
| ... | ... | @@ -82,6 +127,202 @@ pub fn trackZir(ip: *InternPool, gpa: Allocator, file: *Module.File, inst: Zir.I |
| 82 | 127 | return @enumFromInt(gop.index); |
| 83 | 128 | } |
| 84 | 129 | |
| 130 | /// Reperesents the "source" of a dependency edge, i.e. either a Decl or a | |
| 131 | /// runtime function (represented as an InternPool index). | |
| 132 | /// MSB is 0 for a Decl, 1 for a function. | |
| 133 | pub const Depender = enum(u32) { | |
| 134 | _, | |
| 135 | pub const Unwrapped = union(enum) { | |
| 136 | decl: DeclIndex, | |
| 137 | func: InternPool.Index, | |
| 138 | }; | |
| 139 | pub fn unwrap(dep: Depender) Unwrapped { | |
| 140 | const tag: u1 = @truncate(@intFromEnum(dep) >> 31); | |
| 141 | const val: u31 = @truncate(@intFromEnum(dep)); | |
| 142 | return switch (tag) { | |
| 143 | 0 => .{ .decl = @enumFromInt(val) }, | |
| 144 | 1 => .{ .func = @enumFromInt(val) }, | |
| 145 | }; | |
| 146 | } | |
| 147 | pub fn wrap(raw: Unwrapped) Depender { | |
| 148 | return @enumFromInt(switch (raw) { | |
| 149 | .decl => |decl| @intFromEnum(decl), | |
| 150 | .func => |func| (1 << 31) | @intFromEnum(func), | |
| 151 | }); | |
| 152 | } | |
| 153 | pub fn toOptional(dep: Depender) Optional { | |
| 154 | return @enumFromInt(@intFromEnum(dep)); | |
| 155 | } | |
| 156 | pub const Optional = enum(u32) { | |
| 157 | none = std.math.maxInt(u32), | |
| 158 | _, | |
| 159 | pub fn unwrap(opt: Optional) ?Depender { | |
| 160 | return switch (opt) { | |
| 161 | .none => null, | |
| 162 | _ => @enumFromInt(@intFromEnum(opt)), | |
| 163 | }; | |
| 164 | } | |
| 165 | }; | |
| 166 | }; | |
| 167 | ||
| 168 | pub const Dependee = union(enum) { | |
| 169 | src_hash: TrackedInst.Index, | |
| 170 | decl_val: DeclIndex, | |
| 171 | namespace: TrackedInst.Index, | |
| 172 | namespace_name: NamespaceNameKey, | |
| 173 | }; | |
| 174 | ||
| 175 | pub fn removeDependenciesForDepender(ip: *InternPool, gpa: Allocator, depender: Depender) void { | |
| 176 | var opt_idx = (ip.first_dependency.fetchSwapRemove(depender) orelse return).value.toOptional(); | |
| 177 | ||
| 178 | while (opt_idx.unwrap()) |idx| { | |
| 179 | const dep = ip.dep_entries.items[@intFromEnum(idx)]; | |
| 180 | opt_idx = dep.next_dependee; | |
| 181 | ||
| 182 | const prev_idx = dep.prev.unwrap() orelse { | |
| 183 | // This entry is the start of a list in some `*_deps`. | |
| 184 | // We cannot easily remove this mapping, so this must remain as a dummy entry. | |
| 185 | ip.dep_entries.items[@intFromEnum(idx)].depender = .none; | |
| 186 | continue; | |
| 187 | }; | |
| 188 | ||
| 189 | ip.dep_entries.items[@intFromEnum(prev_idx)].next = dep.next; | |
| 190 | if (dep.next.unwrap()) |next_idx| { | |
| 191 | ip.dep_entries.items[@intFromEnum(next_idx)].prev = dep.prev; | |
| 192 | } | |
| 193 | ||
| 194 | ip.free_dep_entries.append(gpa, idx) catch { | |
| 195 | // This memory will be reclaimed on the next garbage collection. | |
| 196 | // Thus, we do not need to propagate this error. | |
| 197 | }; | |
| 198 | } | |
| 199 | } | |
| 200 | ||
| 201 | pub const DependencyIterator = struct { | |
| 202 | ip: *const InternPool, | |
| 203 | next_entry: DepEntry.Index.Optional, | |
| 204 | pub fn next(it: *DependencyIterator) ?Depender { | |
| 205 | const idx = it.next_entry.unwrap() orelse return null; | |
| 206 | const entry = it.ip.dep_entries.items[@intFromEnum(idx)]; | |
| 207 | it.next_entry = entry.next; | |
| 208 | return entry.depender.unwrap().?; | |
| 209 | } | |
| 210 | }; | |
| 211 | ||
| 212 | pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyIterator { | |
| 213 | const first_entry = switch (dependee) { | |
| 214 | .src_hash => |x| ip.src_hash_deps.get(x), | |
| 215 | .decl_val => |x| ip.decl_val_deps.get(x), | |
| 216 | .namespace => |x| ip.namespace_deps.get(x), | |
| 217 | .namespace_name => |x| ip.namespace_name_deps.get(x), | |
| 218 | } orelse return .{ | |
| 219 | .ip = ip, | |
| 220 | .next_entry = .none, | |
| 221 | }; | |
| 222 | if (ip.dep_entries.items[@intFromEnum(first_entry)].depender == .none) return .{ | |
| 223 | .ip = ip, | |
| 224 | .next_entry = .none, | |
| 225 | }; | |
| 226 | return .{ | |
| 227 | .ip = ip, | |
| 228 | .next_entry = first_entry.toOptional(), | |
| 229 | }; | |
| 230 | } | |
| 231 | ||
| 232 | pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: Depender, dependee: Dependee) Allocator.Error!void { | |
| 233 | const first_depender_dep: DepEntry.Index.Optional = if (ip.first_dependency.get(depender)) |idx| dep: { | |
| 234 | // The entry already exists, so there is capacity to overwrite it later. | |
| 235 | break :dep idx.toOptional(); | |
| 236 | } else none: { | |
| 237 | // Ensure there is capacity available to add this dependency later. | |
| 238 | try ip.first_dependency.ensureUnusedCapacity(gpa, 1); | |
| 239 | break :none .none; | |
| 240 | }; | |
| 241 | ||
| 242 | // We're very likely to need space for a new entry - reserve it now to avoid | |
| 243 | // the need for error cleanup logic. | |
| 244 | if (ip.free_dep_entries.items.len == 0) { | |
| 245 | try ip.dep_entries.ensureUnusedCapacity(gpa, 1); | |
| 246 | } | |
| 247 | ||
| 248 | // This block should allocate an entry and prepend it to the relevant `*_deps` list. | |
| 249 | // The `next` field should be correctly initialized; all other fields may be undefined. | |
| 250 | const new_index: DepEntry.Index = switch (dependee) { | |
| 251 | inline else => |dependee_payload, tag| new_index: { | |
| 252 | const gop = try switch (tag) { | |
| 253 | .src_hash => ip.src_hash_deps, | |
| 254 | .decl_val => ip.decl_val_deps, | |
| 255 | .namespace => ip.namespace_deps, | |
| 256 | .namespace_name => ip.namespace_name_deps, | |
| 257 | }.getOrPut(gpa, dependee_payload); | |
| 258 | ||
| 259 | if (gop.found_existing and ip.dep_entries.items[@intFromEnum(gop.value_ptr.*)].depender == .none) { | |
| 260 | // Dummy entry, so we can reuse it rather than allocating a new one! | |
| 261 | ip.dep_entries.items[@intFromEnum(gop.value_ptr.*)].next = .none; | |
| 262 | break :new_index gop.value_ptr.*; | |
| 263 | } | |
| 264 | ||
| 265 | // Prepend a new dependency. | |
| 266 | const new_index: DepEntry.Index, const ptr = if (ip.free_dep_entries.popOrNull()) |new_index| new: { | |
| 267 | break :new .{ new_index, &ip.dep_entries.items[@intFromEnum(new_index)] }; | |
| 268 | } else .{ @enumFromInt(ip.dep_entries.items.len), ip.dep_entries.addOneAssumeCapacity() }; | |
| 269 | ptr.next = if (gop.found_existing) gop.value_ptr.*.toOptional() else .none; | |
| 270 | gop.value_ptr.* = new_index; | |
| 271 | break :new_index new_index; | |
| 272 | }, | |
| 273 | }; | |
| 274 | ||
| 275 | ip.dep_entries.items[@intFromEnum(new_index)].depender = depender.toOptional(); | |
| 276 | ip.dep_entries.items[@intFromEnum(new_index)].prev = .none; | |
| 277 | ip.dep_entries.items[@intFromEnum(new_index)].next_dependee = first_depender_dep; | |
| 278 | ip.first_dependency.putAssumeCapacity(depender, new_index); | |
| 279 | } | |
| 280 | ||
| 281 | /// String is the name whose existence the dependency is on. | |
| 282 | /// DepEntry.Index refers to the first such dependency. | |
| 283 | pub const NamespaceNameKey = struct { | |
| 284 | /// The instruction (`struct_decl` etc) which owns the namespace in question. | |
| 285 | namespace: TrackedInst.Index, | |
| 286 | /// The name whose existence the dependency is on. | |
| 287 | name: NullTerminatedString, | |
| 288 | }; | |
| 289 | ||
| 290 | pub const DepEntry = extern struct { | |
| 291 | /// If null, this is a dummy entry - all other fields are `undefined`. It is | |
| 292 | /// the first and only entry in one of `intern_pool.*_deps`, and does not | |
| 293 | /// appear in any list by `first_dependency`, but is not in | |
| 294 | /// `free_dep_entries` since `*_deps` stores a reference to it. | |
| 295 | depender: Depender.Optional, | |
| 296 | /// Index into `dep_entries` forming a doubly linked list of all dependencies on this dependee. | |
| 297 | /// Used to iterate all dependers for a given dependee during an update. | |
| 298 | /// null if this is the end of the list. | |
| 299 | next: DepEntry.Index.Optional, | |
| 300 | /// The other link for `next`. | |
| 301 | /// null if this is the start of the list. | |
| 302 | prev: DepEntry.Index.Optional, | |
| 303 | /// Index into `dep_entries` forming a singly linked list of dependencies *of* `depender`. | |
| 304 | /// Used to efficiently remove all `DepEntry`s for a single `depender` when it is re-analyzed. | |
| 305 | /// null if this is the end of the list. | |
| 306 | next_dependee: DepEntry.Index.Optional, | |
| 307 | ||
| 308 | pub const Index = enum(u32) { | |
| 309 | _, | |
| 310 | pub fn toOptional(dep: DepEntry.Index) Optional { | |
| 311 | return @enumFromInt(@intFromEnum(dep)); | |
| 312 | } | |
| 313 | pub const Optional = enum(u32) { | |
| 314 | none = std.math.maxInt(u32), | |
| 315 | _, | |
| 316 | pub fn unwrap(opt: Optional) ?DepEntry.Index { | |
| 317 | return switch (opt) { | |
| 318 | .none => null, | |
| 319 | _ => @enumFromInt(@intFromEnum(opt)), | |
| 320 | }; | |
| 321 | } | |
| 322 | }; | |
| 323 | }; | |
| 324 | }; | |
| 325 | ||
| 85 | 326 | const FieldMap = std.ArrayHashMapUnmanaged(void, void, std.array_hash_map.AutoContext(void), false); |
| 86 | 327 | |
| 87 | 328 | const builtin = @import("builtin"); |
| ... | ... | @@ -428,6 +669,7 @@ pub const Key = union(enum) { |
| 428 | 669 | decl: DeclIndex, |
| 429 | 670 | /// Represents the declarations inside this opaque. |
| 430 | 671 | namespace: NamespaceIndex, |
| 672 | zir_index: TrackedInst.Index.Optional, | |
| 431 | 673 | }; |
| 432 | 674 | |
| 433 | 675 | /// Although packed structs and non-packed structs are encoded differently, |
| ... | ... | @@ -440,7 +682,7 @@ pub const Key = union(enum) { |
| 440 | 682 | /// `none` when the struct has no declarations. |
| 441 | 683 | namespace: OptionalNamespaceIndex, |
| 442 | 684 | /// Index of the struct_decl ZIR instruction. |
| 443 | zir_index: TrackedInst.Index, | |
| 685 | zir_index: TrackedInst.Index.Optional, | |
| 444 | 686 | layout: std.builtin.Type.ContainerLayout, |
| 445 | 687 | field_names: NullTerminatedString.Slice, |
| 446 | 688 | field_types: Index.Slice, |
| ... | ... | @@ -684,7 +926,7 @@ pub const Key = union(enum) { |
| 684 | 926 | } |
| 685 | 927 | |
| 686 | 928 | /// Asserts the struct is not packed. |
| 687 | pub fn setZirIndex(s: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index) void { | |
| 929 | pub fn setZirIndex(s: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void { | |
| 688 | 930 | assert(s.layout != .Packed); |
| 689 | 931 | const field_index = std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?; |
| 690 | 932 | ip.extra.items[s.extra_index + field_index] = @intFromEnum(new_zir_index); |
| ... | ... | @@ -800,7 +1042,7 @@ pub const Key = union(enum) { |
| 800 | 1042 | flags: Tag.TypeUnion.Flags, |
| 801 | 1043 | /// The enum that provides the list of field names and values. |
| 802 | 1044 | enum_tag_ty: Index, |
| 803 | zir_index: TrackedInst.Index, | |
| 1045 | zir_index: TrackedInst.Index.Optional, | |
| 804 | 1046 | |
| 805 | 1047 | /// The returned pointer expires with any addition to the `InternPool`. |
| 806 | 1048 | pub fn flagsPtr(self: @This(), ip: *const InternPool) *Tag.TypeUnion.Flags { |
| ... | ... | @@ -889,6 +1131,7 @@ pub const Key = union(enum) { |
| 889 | 1131 | /// This is ignored by `get` but will be provided by `indexToKey` when |
| 890 | 1132 | /// a value map exists. |
| 891 | 1133 | values_map: OptionalMapIndex = .none, |
| 1134 | zir_index: TrackedInst.Index.Optional, | |
| 892 | 1135 | |
| 893 | 1136 | pub const TagMode = enum { |
| 894 | 1137 | /// The integer tag type was auto-numbered by zig. |
| ... | ... | @@ -953,6 +1196,7 @@ pub const Key = union(enum) { |
| 953 | 1196 | tag_mode: EnumType.TagMode, |
| 954 | 1197 | /// This may be updated via `setTagType` later. |
| 955 | 1198 | tag_ty: Index = .none, |
| 1199 | zir_index: TrackedInst.Index.Optional, | |
| 956 | 1200 | |
| 957 | 1201 | pub fn toEnumType(self: @This()) EnumType { |
| 958 | 1202 | return .{ |
| ... | ... | @@ -962,6 +1206,7 @@ pub const Key = union(enum) { |
| 962 | 1206 | .tag_mode = self.tag_mode, |
| 963 | 1207 | .names = .{ .start = 0, .len = 0 }, |
| 964 | 1208 | .values = .{ .start = 0, .len = 0 }, |
| 1209 | .zir_index = self.zir_index, | |
| 965 | 1210 | }; |
| 966 | 1211 | } |
| 967 | 1212 | |
| ... | ... | @@ -1909,7 +2154,7 @@ pub const UnionType = struct { |
| 1909 | 2154 | /// If this slice has length 0 it means all elements are `none`. |
| 1910 | 2155 | field_aligns: Alignment.Slice, |
| 1911 | 2156 | /// Index of the union_decl ZIR instruction. |
| 1912 | zir_index: TrackedInst.Index, | |
| 2157 | zir_index: TrackedInst.Index.Optional, | |
| 1913 | 2158 | /// Index into extra array of the `flags` field. |
| 1914 | 2159 | flags_index: u32, |
| 1915 | 2160 | /// Copied from `enum_tag_ty`. |
| ... | ... | @@ -2003,10 +2248,10 @@ pub const UnionType = struct { |
| 2003 | 2248 | } |
| 2004 | 2249 | |
| 2005 | 2250 | /// This does not mutate the field of UnionType. |
| 2006 | pub fn setZirIndex(self: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index) void { | |
| 2251 | pub fn setZirIndex(self: @This(), ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void { | |
| 2007 | 2252 | const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?; |
| 2008 | 2253 | const zir_index_field_index = std.meta.fieldIndex(Tag.TypeUnion, "zir_index").?; |
| 2009 | const ptr: *TrackedInst.Index = | |
| 2254 | const ptr: *TrackedInst.Index.Optional = | |
| 2010 | 2255 | @ptrCast(&ip.extra.items[self.flags_index - flags_field_index + zir_index_field_index]); |
| 2011 | 2256 | ptr.* = new_zir_index; |
| 2012 | 2257 | } |
| ... | ... | @@ -3099,7 +3344,7 @@ pub const Tag = enum(u8) { |
| 3099 | 3344 | namespace: NamespaceIndex, |
| 3100 | 3345 | /// The enum that provides the list of field names and values. |
| 3101 | 3346 | tag_ty: Index, |
| 3102 | zir_index: TrackedInst.Index, | |
| 3347 | zir_index: TrackedInst.Index.Optional, | |
| 3103 | 3348 | |
| 3104 | 3349 | pub const Flags = packed struct(u32) { |
| 3105 | 3350 | runtime_tag: UnionType.RuntimeTag, |
| ... | ... | @@ -3121,7 +3366,7 @@ pub const Tag = enum(u8) { |
| 3121 | 3366 | /// 2. init: Index for each fields_len // if tag is type_struct_packed_inits |
| 3122 | 3367 | pub const TypeStructPacked = struct { |
| 3123 | 3368 | decl: DeclIndex, |
| 3124 | zir_index: TrackedInst.Index, | |
| 3369 | zir_index: TrackedInst.Index.Optional, | |
| 3125 | 3370 | fields_len: u32, |
| 3126 | 3371 | namespace: OptionalNamespaceIndex, |
| 3127 | 3372 | backing_int_ty: Index, |
| ... | ... | @@ -3168,7 +3413,7 @@ pub const Tag = enum(u8) { |
| 3168 | 3413 | /// 7. field_offset: u32 // for each field in declared order, undef until layout_resolved |
| 3169 | 3414 | pub const TypeStruct = struct { |
| 3170 | 3415 | decl: DeclIndex, |
| 3171 | zir_index: TrackedInst.Index, | |
| 3416 | zir_index: TrackedInst.Index.Optional, | |
| 3172 | 3417 | fields_len: u32, |
| 3173 | 3418 | flags: Flags, |
| 3174 | 3419 | size: u32, |
| ... | ... | @@ -3523,6 +3768,7 @@ pub const EnumExplicit = struct { |
| 3523 | 3768 | /// If this is `none`, it means the trailing tag values are absent because |
| 3524 | 3769 | /// they are auto-numbered. |
| 3525 | 3770 | values_map: OptionalMapIndex, |
| 3771 | zir_index: TrackedInst.Index.Optional, | |
| 3526 | 3772 | }; |
| 3527 | 3773 | |
| 3528 | 3774 | /// Trailing: |
| ... | ... | @@ -3538,6 +3784,7 @@ pub const EnumAuto = struct { |
| 3538 | 3784 | fields_len: u32, |
| 3539 | 3785 | /// Maps field names to declaration index. |
| 3540 | 3786 | names_map: MapIndex, |
| 3787 | zir_index: TrackedInst.Index.Optional, | |
| 3541 | 3788 | }; |
| 3542 | 3789 | |
| 3543 | 3790 | pub const PackedU64 = packed struct(u64) { |
| ... | ... | @@ -3759,6 +4006,16 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { |
| 3759 | 4006 | |
| 3760 | 4007 | ip.tracked_insts.deinit(gpa); |
| 3761 | 4008 | |
| 4009 | ip.src_hash_deps.deinit(gpa); | |
| 4010 | ip.decl_val_deps.deinit(gpa); | |
| 4011 | ip.namespace_deps.deinit(gpa); | |
| 4012 | ip.namespace_name_deps.deinit(gpa); | |
| 4013 | ||
| 4014 | ip.first_dependency.deinit(gpa); | |
| 4015 | ||
| 4016 | ip.dep_entries.deinit(gpa); | |
| 4017 | ip.free_dep_entries.deinit(gpa); | |
| 4018 | ||
| 3762 | 4019 | ip.* = undefined; |
| 3763 | 4020 | } |
| 3764 | 4021 | |
| ... | ... | @@ -3885,6 +4142,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 3885 | 4142 | .tag_mode = .auto, |
| 3886 | 4143 | .names_map = enum_auto.data.names_map.toOptional(), |
| 3887 | 4144 | .values_map = .none, |
| 4145 | .zir_index = enum_auto.data.zir_index, | |
| 3888 | 4146 | } }; |
| 3889 | 4147 | }, |
| 3890 | 4148 | .type_enum_explicit => ip.indexToKeyEnum(data, .explicit), |
| ... | ... | @@ -4493,6 +4751,7 @@ fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMo |
| 4493 | 4751 | .tag_mode = tag_mode, |
| 4494 | 4752 | .names_map = enum_explicit.data.names_map.toOptional(), |
| 4495 | 4753 | .values_map = enum_explicit.data.values_map, |
| 4754 | .zir_index = enum_explicit.data.zir_index, | |
| 4496 | 4755 | } }; |
| 4497 | 4756 | } |
| 4498 | 4757 | |
| ... | ... | @@ -5329,7 +5588,7 @@ pub const UnionTypeInit = struct { |
| 5329 | 5588 | flags: Tag.TypeUnion.Flags, |
| 5330 | 5589 | decl: DeclIndex, |
| 5331 | 5590 | namespace: NamespaceIndex, |
| 5332 | zir_index: TrackedInst.Index, | |
| 5591 | zir_index: TrackedInst.Index.Optional, | |
| 5333 | 5592 | fields_len: u32, |
| 5334 | 5593 | enum_tag_ty: Index, |
| 5335 | 5594 | /// May have length 0 which leaves the values unset until later. |
| ... | ... | @@ -5401,7 +5660,7 @@ pub const StructTypeInit = struct { |
| 5401 | 5660 | decl: DeclIndex, |
| 5402 | 5661 | namespace: OptionalNamespaceIndex, |
| 5403 | 5662 | layout: std.builtin.Type.ContainerLayout, |
| 5404 | zir_index: TrackedInst.Index, | |
| 5663 | zir_index: TrackedInst.Index.Optional, | |
| 5405 | 5664 | fields_len: u32, |
| 5406 | 5665 | known_non_opv: bool, |
| 5407 | 5666 | requires_comptime: RequiresComptime, |
| ... | ... | @@ -6264,6 +6523,7 @@ fn getIncompleteEnumAuto( |
| 6264 | 6523 | .int_tag_type = int_tag_type, |
| 6265 | 6524 | .names_map = names_map, |
| 6266 | 6525 | .fields_len = enum_type.fields_len, |
| 6526 | .zir_index = enum_type.zir_index, | |
| 6267 | 6527 | }); |
| 6268 | 6528 | |
| 6269 | 6529 | ip.items.appendAssumeCapacity(.{ |
| ... | ... | @@ -6314,6 +6574,7 @@ fn getIncompleteEnumExplicit( |
| 6314 | 6574 | .fields_len = enum_type.fields_len, |
| 6315 | 6575 | .names_map = names_map, |
| 6316 | 6576 | .values_map = values_map, |
| 6577 | .zir_index = enum_type.zir_index, | |
| 6317 | 6578 | }); |
| 6318 | 6579 | |
| 6319 | 6580 | ip.items.appendAssumeCapacity(.{ |
| ... | ... | @@ -6339,6 +6600,7 @@ pub const GetEnumInit = struct { |
| 6339 | 6600 | names: []const NullTerminatedString, |
| 6340 | 6601 | values: []const Index, |
| 6341 | 6602 | tag_mode: Key.EnumType.TagMode, |
| 6603 | zir_index: TrackedInst.Index.Optional, | |
| 6342 | 6604 | }; |
| 6343 | 6605 | |
| 6344 | 6606 | pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Error!Index { |
| ... | ... | @@ -6355,6 +6617,7 @@ pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Erro |
| 6355 | 6617 | .tag_mode = undefined, |
| 6356 | 6618 | .names_map = undefined, |
| 6357 | 6619 | .values_map = undefined, |
| 6620 | .zir_index = undefined, | |
| 6358 | 6621 | }, |
| 6359 | 6622 | }, adapter); |
| 6360 | 6623 | if (gop.found_existing) return @enumFromInt(gop.index); |
| ... | ... | @@ -6380,6 +6643,7 @@ pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Erro |
| 6380 | 6643 | .int_tag_type = ini.tag_ty, |
| 6381 | 6644 | .names_map = names_map, |
| 6382 | 6645 | .fields_len = fields_len, |
| 6646 | .zir_index = ini.zir_index, | |
| 6383 | 6647 | }), |
| 6384 | 6648 | }); |
| 6385 | 6649 | ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names)); |
| ... | ... | @@ -6416,6 +6680,7 @@ pub fn finishGetEnum( |
| 6416 | 6680 | .fields_len = fields_len, |
| 6417 | 6681 | .names_map = names_map, |
| 6418 | 6682 | .values_map = values_map, |
| 6683 | .zir_index = ini.zir_index, | |
| 6419 | 6684 | }), |
| 6420 | 6685 | }); |
| 6421 | 6686 | ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names)); |
| ... | ... | @@ -6507,6 +6772,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 { |
| 6507 | 6772 | OptionalNullTerminatedString, |
| 6508 | 6773 | Tag.TypePointer.VectorIndex, |
| 6509 | 6774 | TrackedInst.Index, |
| 6775 | TrackedInst.Index.Optional, | |
| 6510 | 6776 | => @intFromEnum(@field(extra, field.name)), |
| 6511 | 6777 | |
| 6512 | 6778 | u32, |
| ... | ... | @@ -6583,6 +6849,7 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct |
| 6583 | 6849 | OptionalNullTerminatedString, |
| 6584 | 6850 | Tag.TypePointer.VectorIndex, |
| 6585 | 6851 | TrackedInst.Index, |
| 6852 | TrackedInst.Index.Optional, | |
| 6586 | 6853 | => @enumFromInt(int32), |
| 6587 | 6854 | |
| 6588 | 6855 | u32, |
src/Module.zig+140-37| ... | ... | @@ -149,6 +149,10 @@ error_limit: ErrorInt, |
| 149 | 149 | /// previous analysis. |
| 150 | 150 | generation: u32 = 0, |
| 151 | 151 | |
| 152 | /// Value is the number of PO dependencies of this Depender. | |
| 153 | potentially_outdated: std.AutoArrayHashMapUnmanaged(InternPool.Depender, u32) = .{}, | |
| 154 | outdated: std.AutoArrayHashMapUnmanaged(InternPool.Depender, void) = .{}, | |
| 155 | ||
| 152 | 156 | stage1_flags: packed struct { |
| 153 | 157 | have_winmain: bool = false, |
| 154 | 158 | have_wwinmain: bool = false, |
| ... | ... | @@ -680,14 +684,6 @@ pub const Decl = struct { |
| 680 | 684 | return mod.namespacePtr(decl.src_namespace).file_scope; |
| 681 | 685 | } |
| 682 | 686 | |
| 683 | pub fn removeDependant(decl: *Decl, other: Decl.Index) void { | |
| 684 | assert(decl.dependants.swapRemove(other)); | |
| 685 | } | |
| 686 | ||
| 687 | pub fn removeDependency(decl: *Decl, other: Decl.Index) void { | |
| 688 | assert(decl.dependencies.swapRemove(other)); | |
| 689 | } | |
| 690 | ||
| 691 | 687 | pub fn getExternDecl(decl: Decl, mod: *Module) OptionalIndex { |
| 692 | 688 | assert(decl.has_tv); |
| 693 | 689 | return switch (mod.intern_pool.indexToKey(decl.val.toIntern())) { |
| ... | ... | @@ -838,14 +834,6 @@ pub const File = struct { |
| 838 | 834 | /// undefined until `zir_loaded == true`. |
| 839 | 835 | path_digest: Cache.BinDigest = undefined, |
| 840 | 836 | |
| 841 | /// Used by change detection algorithm, after astgen, contains the | |
| 842 | /// set of decls that existed in the previous ZIR but not in the new one. | |
| 843 | deleted_decls: ArrayListUnmanaged(Decl.Index) = .{}, | |
| 844 | /// Used by change detection algorithm, after astgen, contains the | |
| 845 | /// set of decls that existed both in the previous ZIR and in the new one, | |
| 846 | /// but their source code has been modified. | |
| 847 | outdated_decls: ArrayListUnmanaged(Decl.Index) = .{}, | |
| 848 | ||
| 849 | 837 | /// The most recent successful ZIR for this file, with no errors. |
| 850 | 838 | /// This is only populated when a previously successful ZIR |
| 851 | 839 | /// newly introduces compile errors during an update. When ZIR is |
| ... | ... | @@ -898,8 +886,6 @@ pub const File = struct { |
| 898 | 886 | gpa.free(file.sub_file_path); |
| 899 | 887 | file.unload(gpa); |
| 900 | 888 | } |
| 901 | file.deleted_decls.deinit(gpa); | |
| 902 | file.outdated_decls.deinit(gpa); | |
| 903 | 889 | file.references.deinit(gpa); |
| 904 | 890 | if (file.root_decl.unwrap()) |root_decl| { |
| 905 | 891 | mod.destroyDecl(root_decl); |
| ... | ... | @@ -2498,6 +2484,8 @@ pub fn deinit(zcu: *Zcu) void { |
| 2498 | 2484 | |
| 2499 | 2485 | zcu.global_error_set.deinit(gpa); |
| 2500 | 2486 | |
| 2487 | zcu.potentially_outdated.deinit(gpa); | |
| 2488 | ||
| 2501 | 2489 | zcu.test_functions.deinit(gpa); |
| 2502 | 2490 | |
| 2503 | 2491 | for (zcu.global_assembly.values()) |s| { |
| ... | ... | @@ -2856,27 +2844,18 @@ pub fn astGenFile(mod: *Module, file: *File) !void { |
| 2856 | 2844 | } |
| 2857 | 2845 | |
| 2858 | 2846 | if (file.prev_zir) |prev_zir| { |
| 2859 | // Iterate over all Namespace objects contained within this File, looking at the | |
| 2860 | // previous and new ZIR together and update the references to point | |
| 2861 | // to the new one. For example, Decl name, Decl zir_decl_index, and Namespace | |
| 2862 | // decl_table keys need to get updated to point to the new memory, even if the | |
| 2863 | // underlying source code is unchanged. | |
| 2864 | // We do not need to hold any locks at this time because all the Decl and Namespace | |
| 2865 | // objects being touched are specific to this File, and the only other concurrent | |
| 2866 | // tasks are touching other File objects. | |
| 2867 | 2847 | try updateZirRefs(mod, file, prev_zir.*); |
| 2868 | // At this point, `file.outdated_decls` and `file.deleted_decls` are populated, | |
| 2869 | // and semantic analysis will deal with them properly. | |
| 2870 | 2848 | // No need to keep previous ZIR. |
| 2871 | 2849 | prev_zir.deinit(gpa); |
| 2872 | 2850 | gpa.destroy(prev_zir); |
| 2873 | 2851 | file.prev_zir = null; |
| 2874 | } else if (file.root_decl.unwrap()) |root_decl| { | |
| 2875 | // This is an update, but it is the first time the File has succeeded | |
| 2876 | // ZIR. We must mark it outdated since we have already tried to | |
| 2877 | // semantically analyze it. | |
| 2878 | try file.outdated_decls.resize(gpa, 1); | |
| 2879 | file.outdated_decls.items[0] = root_decl; | |
| 2852 | } | |
| 2853 | ||
| 2854 | if (file.root_decl.unwrap()) |root_decl| { | |
| 2855 | // The root of this file must be re-analyzed, since the file has changed. | |
| 2856 | comp.mutex.lock(); | |
| 2857 | defer comp.mutex.unlock(); | |
| 2858 | try mod.outdated.put(gpa, InternPool.Depender.wrap(.{ .decl = root_decl }), {}); | |
| 2880 | 2859 | } |
| 2881 | 2860 | } |
| 2882 | 2861 | |
| ... | ... | @@ -2950,25 +2929,142 @@ fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File) |
| 2950 | 2929 | return zir; |
| 2951 | 2930 | } |
| 2952 | 2931 | |
| 2932 | /// This is called from the AstGen thread pool, so must acquire | |
| 2933 | /// the Compilation mutex when acting on shared state. | |
| 2953 | 2934 | fn updateZirRefs(zcu: *Module, file: *File, old_zir: Zir) !void { |
| 2954 | 2935 | const gpa = zcu.gpa; |
| 2936 | const new_zir = file.zir; | |
| 2955 | 2937 | |
| 2956 | 2938 | var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}; |
| 2957 | 2939 | defer inst_map.deinit(gpa); |
| 2958 | 2940 | |
| 2959 | try mapOldZirToNew(gpa, old_zir, file.zir, &inst_map); | |
| 2941 | try mapOldZirToNew(gpa, old_zir, new_zir, &inst_map); | |
| 2942 | ||
| 2943 | const old_tag = old_zir.instructions.items(.tag); | |
| 2944 | const old_data = old_zir.instructions.items(.data); | |
| 2960 | 2945 | |
| 2961 | 2946 | // TODO: this should be done after all AstGen workers complete, to avoid |
| 2962 | 2947 | // iterating over this full set for every updated file. |
| 2963 | for (zcu.intern_pool.tracked_insts.keys()) |*ti| { | |
| 2948 | for (zcu.intern_pool.tracked_insts.keys(), 0..) |*ti, idx_raw| { | |
| 2949 | const ti_idx: InternPool.TrackedInst.Index = @enumFromInt(idx_raw); | |
| 2964 | 2950 | if (!std.mem.eql(u8, &ti.path_digest, &file.path_digest)) continue; |
| 2951 | const old_inst = ti.inst; | |
| 2965 | 2952 | ti.inst = inst_map.get(ti.inst) orelse { |
| 2966 | // TODO: invalidate this `TrackedInst` via the dependency mechanism | |
| 2953 | // Tracking failed for this instruction. Invalidate associated `src_hash` deps. | |
| 2954 | zcu.comp.mutex.lock(); | |
| 2955 | defer zcu.comp.mutex.unlock(); | |
| 2956 | try zcu.markDependeeOutdated(.{ .src_hash = ti_idx }); | |
| 2967 | 2957 | continue; |
| 2968 | 2958 | }; |
| 2959 | ||
| 2960 | // If this is a `struct_decl` etc, we must invalidate any outdated namespace dependencies. | |
| 2961 | const has_namespace = switch (old_tag[@intFromEnum(old_inst)]) { | |
| 2962 | .extended => switch (old_data[@intFromEnum(old_inst)].extended.opcode) { | |
| 2963 | .struct_decl, .union_decl, .opaque_decl, .enum_decl => true, | |
| 2964 | else => false, | |
| 2965 | }, | |
| 2966 | else => false, | |
| 2967 | }; | |
| 2968 | if (!has_namespace) continue; | |
| 2969 | ||
| 2970 | var old_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{}; | |
| 2971 | defer old_names.deinit(zcu.gpa); | |
| 2972 | { | |
| 2973 | var it = old_zir.declIterator(old_inst); | |
| 2974 | while (it.next()) |decl_inst| { | |
| 2975 | const decl_name = old_zir.getDeclaration(decl_inst)[0].name; | |
| 2976 | switch (decl_name) { | |
| 2977 | .@"comptime", .@"usingnamespace", .unnamed_test, .decltest => continue, | |
| 2978 | _ => if (decl_name.isNamedTest(old_zir)) continue, | |
| 2979 | } | |
| 2980 | const name_zir = decl_name.toString(old_zir).?; | |
| 2981 | const name_ip = try zcu.intern_pool.getOrPutString( | |
| 2982 | zcu.gpa, | |
| 2983 | old_zir.nullTerminatedString(name_zir), | |
| 2984 | ); | |
| 2985 | try old_names.put(zcu.gpa, name_ip, {}); | |
| 2986 | } | |
| 2987 | } | |
| 2988 | var any_change = false; | |
| 2989 | { | |
| 2990 | var it = new_zir.declIterator(ti.inst); | |
| 2991 | while (it.next()) |decl_inst| { | |
| 2992 | const decl_name = old_zir.getDeclaration(decl_inst)[0].name; | |
| 2993 | switch (decl_name) { | |
| 2994 | .@"comptime", .@"usingnamespace", .unnamed_test, .decltest => continue, | |
| 2995 | _ => if (decl_name.isNamedTest(old_zir)) continue, | |
| 2996 | } | |
| 2997 | const name_zir = decl_name.toString(old_zir).?; | |
| 2998 | const name_ip = try zcu.intern_pool.getOrPutString( | |
| 2999 | zcu.gpa, | |
| 3000 | old_zir.nullTerminatedString(name_zir), | |
| 3001 | ); | |
| 3002 | if (!old_names.swapRemove(name_ip)) continue; | |
| 3003 | // Name added | |
| 3004 | any_change = true; | |
| 3005 | zcu.comp.mutex.lock(); | |
| 3006 | defer zcu.comp.mutex.unlock(); | |
| 3007 | try zcu.markDependeeOutdated(.{ .namespace_name = .{ | |
| 3008 | .namespace = ti_idx, | |
| 3009 | .name = name_ip, | |
| 3010 | } }); | |
| 3011 | } | |
| 3012 | } | |
| 3013 | // The only elements remaining in `old_names` now are any names which were removed. | |
| 3014 | for (old_names.keys()) |name_ip| { | |
| 3015 | any_change = true; | |
| 3016 | zcu.comp.mutex.lock(); | |
| 3017 | defer zcu.comp.mutex.unlock(); | |
| 3018 | try zcu.markDependeeOutdated(.{ .namespace_name = .{ | |
| 3019 | .namespace = ti_idx, | |
| 3020 | .name = name_ip, | |
| 3021 | } }); | |
| 3022 | } | |
| 3023 | ||
| 3024 | if (any_change) { | |
| 3025 | zcu.comp.mutex.lock(); | |
| 3026 | defer zcu.comp.mutex.unlock(); | |
| 3027 | try zcu.markDependeeOutdated(.{ .namespace = ti_idx }); | |
| 3028 | } | |
| 3029 | } | |
| 3030 | } | |
| 3031 | ||
| 3032 | pub fn markDependeeOutdated(zcu: *Zcu, dependee: InternPool.Dependee) !void { | |
| 3033 | var it = zcu.intern_pool.dependencyIterator(dependee); | |
| 3034 | while (it.next()) |depender| { | |
| 3035 | if (zcu.outdated.contains(depender)) continue; | |
| 3036 | const was_po = zcu.potentially_outdated.swapRemove(depender); | |
| 3037 | try zcu.outdated.putNoClobber(zcu.gpa, depender, {}); | |
| 3038 | // If this is a Decl and was not previously PO, we must recursively | |
| 3039 | // mark dependencies on its tyval as PO. | |
| 3040 | if (was_po) switch (depender.unwrap()) { | |
| 3041 | .decl => |decl_index| try zcu.markDeclDependenciesPotentiallyOutdated(decl_index), | |
| 3042 | .func => {}, | |
| 3043 | }; | |
| 2969 | 3044 | } |
| 2970 | 3045 | } |
| 2971 | 3046 | |
| 3047 | /// Given a Decl which is newly outdated or PO, mark all dependers which depend | |
| 3048 | /// on its tyval as PO. | |
| 3049 | fn markDeclDependenciesPotentiallyOutdated(zcu: *Zcu, decl_index: Decl.Index) !void { | |
| 3050 | var it = zcu.intern_pool.dependencyIterator(.{ .decl_val = decl_index }); | |
| 3051 | while (it.next()) |po| { | |
| 3052 | if (zcu.potentially_outdated.getPtr(po)) |n| { | |
| 3053 | // There is now one more PO dependency. | |
| 3054 | n.* += 1; | |
| 3055 | continue; | |
| 3056 | } | |
| 3057 | try zcu.potentially_outdated.putNoClobber(zcu.gpa, po, 1); | |
| 3058 | // If this ia a Decl, we must recursively mark dependencies | |
| 3059 | // on its tyval as PO. | |
| 3060 | switch (po.unwrap()) { | |
| 3061 | .decl => |po_decl| try zcu.markDeclDependenciesPotentiallyOutdated(po_decl), | |
| 3062 | .func => {}, | |
| 3063 | } | |
| 3064 | } | |
| 3065 | // TODO: repeat the above for `decl_ty` dependencies when they are introduced | |
| 3066 | } | |
| 3067 | ||
| 2972 | 3068 | pub fn mapOldZirToNew( |
| 2973 | 3069 | gpa: Allocator, |
| 2974 | 3070 | old_zir: Zir, |
| ... | ... | @@ -3535,6 +3631,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3535 | 3631 | break :blk .none; |
| 3536 | 3632 | }; |
| 3537 | 3633 | |
| 3634 | mod.intern_pool.removeDependenciesForDepender(gpa, InternPool.Depender.wrap(.{ .decl = decl_index })); | |
| 3635 | ||
| 3538 | 3636 | decl.analysis = .in_progress; |
| 3539 | 3637 | |
| 3540 | 3638 | var analysis_arena = std.heap.ArenaAllocator.init(gpa); |
| ... | ... | @@ -3564,6 +3662,9 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 3564 | 3662 | }; |
| 3565 | 3663 | defer sema.deinit(); |
| 3566 | 3664 | |
| 3665 | // Every Decl has a dependency on its own source. | |
| 3666 | try sema.declareDependency(.{ .src_hash = try ip.trackZir(sema.gpa, decl.getFileScope(mod), decl.zir_decl_index.unwrap().?) }); | |
| 3667 | ||
| 3567 | 3668 | assert(!mod.declIsRoot(decl_index)); |
| 3568 | 3669 | |
| 3569 | 3670 | var block_scope: Sema.Block = .{ |
| ... | ... | @@ -4362,6 +4463,8 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato |
| 4362 | 4463 | const decl_index = func.owner_decl; |
| 4363 | 4464 | const decl = mod.declPtr(decl_index); |
| 4364 | 4465 | |
| 4466 | mod.intern_pool.removeDependenciesForDepender(gpa, InternPool.Depender.wrap(.{ .func = func_index })); | |
| 4467 | ||
| 4365 | 4468 | var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa); |
| 4366 | 4469 | defer comptime_mutable_decls.deinit(); |
| 4367 | 4470 |
src/Sema.zig+78-8| ... | ... | @@ -2748,7 +2748,7 @@ pub fn getStructType( |
| 2748 | 2748 | const ty = try ip.getStructType(gpa, .{ |
| 2749 | 2749 | .decl = decl, |
| 2750 | 2750 | .namespace = namespace.toOptional(), |
| 2751 | .zir_index = tracked_inst, | |
| 2751 | .zir_index = tracked_inst.toOptional(), | |
| 2752 | 2752 | .layout = small.layout, |
| 2753 | 2753 | .known_non_opv = small.known_non_opv, |
| 2754 | 2754 | .is_tuple = small.is_tuple, |
| ... | ... | @@ -2789,6 +2789,12 @@ fn zirStructDecl( |
| 2789 | 2789 | new_decl.owns_tv = true; |
| 2790 | 2790 | errdefer mod.abortAnonDecl(new_decl_index); |
| 2791 | 2791 | |
| 2792 | try ip.addDependency( | |
| 2793 | sema.gpa, | |
| 2794 | InternPool.Depender.wrap(.{ .decl = new_decl_index }), | |
| 2795 | .{ .src_hash = try ip.trackZir(sema.gpa, block.getFileScope(mod), inst) }, | |
| 2796 | ); | |
| 2797 | ||
| 2792 | 2798 | const new_namespace_index = try mod.createNamespace(.{ |
| 2793 | 2799 | .parent = block.namespace.toOptional(), |
| 2794 | 2800 | .ty = undefined, |
| ... | ... | @@ -2973,6 +2979,12 @@ fn zirEnumDecl( |
| 2973 | 2979 | new_decl.owns_tv = true; |
| 2974 | 2980 | errdefer if (!done) mod.abortAnonDecl(new_decl_index); |
| 2975 | 2981 | |
| 2982 | try mod.intern_pool.addDependency( | |
| 2983 | sema.gpa, | |
| 2984 | InternPool.Depender.wrap(.{ .decl = new_decl_index }), | |
| 2985 | .{ .src_hash = try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst) }, | |
| 2986 | ); | |
| 2987 | ||
| 2976 | 2988 | const new_namespace_index = try mod.createNamespace(.{ |
| 2977 | 2989 | .parent = block.namespace.toOptional(), |
| 2978 | 2990 | .ty = undefined, |
| ... | ... | @@ -3008,6 +3020,7 @@ fn zirEnumDecl( |
| 3008 | 3020 | .auto |
| 3009 | 3021 | else |
| 3010 | 3022 | .explicit, |
| 3023 | .zir_index = (try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst)).toOptional(), | |
| 3011 | 3024 | }); |
| 3012 | 3025 | if (sema.builtin_type_target_index != .none) { |
| 3013 | 3026 | mod.intern_pool.resolveBuiltinType(sema.builtin_type_target_index, incomplete_enum.index); |
| ... | ... | @@ -3225,6 +3238,12 @@ fn zirUnionDecl( |
| 3225 | 3238 | new_decl.owns_tv = true; |
| 3226 | 3239 | errdefer mod.abortAnonDecl(new_decl_index); |
| 3227 | 3240 | |
| 3241 | try mod.intern_pool.addDependency( | |
| 3242 | sema.gpa, | |
| 3243 | InternPool.Depender.wrap(.{ .decl = new_decl_index }), | |
| 3244 | .{ .src_hash = try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst) }, | |
| 3245 | ); | |
| 3246 | ||
| 3228 | 3247 | const new_namespace_index = try mod.createNamespace(.{ |
| 3229 | 3248 | .parent = block.namespace.toOptional(), |
| 3230 | 3249 | .ty = undefined, |
| ... | ... | @@ -3254,7 +3273,7 @@ fn zirUnionDecl( |
| 3254 | 3273 | }, |
| 3255 | 3274 | .decl = new_decl_index, |
| 3256 | 3275 | .namespace = new_namespace_index, |
| 3257 | .zir_index = try mod.intern_pool.trackZir(gpa, block.getFileScope(mod), inst), | |
| 3276 | .zir_index = (try mod.intern_pool.trackZir(gpa, block.getFileScope(mod), inst)).toOptional(), | |
| 3258 | 3277 | .fields_len = fields_len, |
| 3259 | 3278 | .enum_tag_ty = .none, |
| 3260 | 3279 | .field_types = &.{}, |
| ... | ... | @@ -3318,6 +3337,12 @@ fn zirOpaqueDecl( |
| 3318 | 3337 | new_decl.owns_tv = true; |
| 3319 | 3338 | errdefer mod.abortAnonDecl(new_decl_index); |
| 3320 | 3339 | |
| 3340 | try mod.intern_pool.addDependency( | |
| 3341 | sema.gpa, | |
| 3342 | InternPool.Depender.wrap(.{ .decl = new_decl_index }), | |
| 3343 | .{ .src_hash = try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst) }, | |
| 3344 | ); | |
| 3345 | ||
| 3321 | 3346 | const new_namespace_index = try mod.createNamespace(.{ |
| 3322 | 3347 | .parent = block.namespace.toOptional(), |
| 3323 | 3348 | .ty = undefined, |
| ... | ... | @@ -3329,6 +3354,7 @@ fn zirOpaqueDecl( |
| 3329 | 3354 | const opaque_ty = try mod.intern(.{ .opaque_type = .{ |
| 3330 | 3355 | .decl = new_decl_index, |
| 3331 | 3356 | .namespace = new_namespace_index, |
| 3357 | .zir_index = (try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst)).toOptional(), | |
| 3332 | 3358 | } }); |
| 3333 | 3359 | // TODO: figure out InternPool removals for incremental compilation |
| 3334 | 3360 | //errdefer mod.intern_pool.remove(opaque_ty); |
| ... | ... | @@ -7890,6 +7916,8 @@ fn instantiateGenericCall( |
| 7890 | 7916 | const generic_owner_func = mod.intern_pool.indexToKey(generic_owner).func; |
| 7891 | 7917 | const generic_owner_ty_info = mod.typeToFunc(Type.fromInterned(generic_owner_func.ty)).?; |
| 7892 | 7918 | |
| 7919 | try sema.declareDependency(.{ .src_hash = generic_owner_func.zir_body_inst }); | |
| 7920 | ||
| 7893 | 7921 | // Even though there may already be a generic instantiation corresponding |
| 7894 | 7922 | // to this callsite, we must evaluate the expressions of the generic |
| 7895 | 7923 | // function signature with the values of the callsite plugged in. |
| ... | ... | @@ -13594,6 +13622,12 @@ fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 13594 | 13622 | }); |
| 13595 | 13623 | |
| 13596 | 13624 | try sema.checkNamespaceType(block, lhs_src, container_type); |
| 13625 | if (container_type.typeDeclInst(mod)) |type_decl_inst| { | |
| 13626 | try sema.declareDependency(.{ .namespace_name = .{ | |
| 13627 | .namespace = type_decl_inst, | |
| 13628 | .name = decl_name, | |
| 13629 | } }); | |
| 13630 | } | |
| 13597 | 13631 | |
| 13598 | 13632 | const namespace = container_type.getNamespaceIndex(mod).unwrap() orelse |
| 13599 | 13633 | return .bool_false; |
| ... | ... | @@ -17447,6 +17481,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17447 | 17481 | const type_info_ty = try sema.getBuiltinType("Type"); |
| 17448 | 17482 | const type_info_tag_ty = type_info_ty.unionTagType(mod).?; |
| 17449 | 17483 | |
| 17484 | if (ty.typeDeclInst(mod)) |type_decl_inst| { | |
| 17485 | try sema.declareDependency(.{ .namespace = type_decl_inst }); | |
| 17486 | } | |
| 17487 | ||
| 17450 | 17488 | switch (ty.zigTypeTag(mod)) { |
| 17451 | 17489 | .Type, |
| 17452 | 17490 | .Void, |
| ... | ... | @@ -21313,6 +21351,7 @@ fn zirReify( |
| 21313 | 21351 | else |
| 21314 | 21352 | .explicit, |
| 21315 | 21353 | .tag_ty = int_tag_ty.toIntern(), |
| 21354 | .zir_index = .none, | |
| 21316 | 21355 | }); |
| 21317 | 21356 | // TODO: figure out InternPool removals for incremental compilation |
| 21318 | 21357 | //errdefer ip.remove(incomplete_enum.index); |
| ... | ... | @@ -21410,6 +21449,7 @@ fn zirReify( |
| 21410 | 21449 | const opaque_ty = try mod.intern(.{ .opaque_type = .{ |
| 21411 | 21450 | .decl = new_decl_index, |
| 21412 | 21451 | .namespace = new_namespace_index, |
| 21452 | .zir_index = .none, | |
| 21413 | 21453 | } }); |
| 21414 | 21454 | // TODO: figure out InternPool removals for incremental compilation |
| 21415 | 21455 | //errdefer ip.remove(opaque_ty); |
| ... | ... | @@ -21628,7 +21668,7 @@ fn zirReify( |
| 21628 | 21668 | .namespace = new_namespace_index, |
| 21629 | 21669 | .enum_tag_ty = enum_tag_ty, |
| 21630 | 21670 | .fields_len = fields_len, |
| 21631 | .zir_index = try ip.trackZir(gpa, block.getFileScope(mod), inst), // TODO: should reified types be handled differently? | |
| 21671 | .zir_index = .none, | |
| 21632 | 21672 | .flags = .{ |
| 21633 | 21673 | .layout = layout, |
| 21634 | 21674 | .status = .have_field_types, |
| ... | ... | @@ -21796,7 +21836,7 @@ fn reifyStruct( |
| 21796 | 21836 | const ty = try ip.getStructType(gpa, .{ |
| 21797 | 21837 | .decl = new_decl_index, |
| 21798 | 21838 | .namespace = .none, |
| 21799 | .zir_index = try mod.intern_pool.trackZir(gpa, block.getFileScope(mod), inst), // TODO: should reified types be handled differently? | |
| 21839 | .zir_index = .none, | |
| 21800 | 21840 | .layout = layout, |
| 21801 | 21841 | .known_non_opv = false, |
| 21802 | 21842 | .fields_len = fields_len, |
| ... | ... | @@ -26416,6 +26456,7 @@ fn prepareSimplePanic(sema: *Sema, block: *Block) !void { |
| 26416 | 26456 | // owns the function. |
| 26417 | 26457 | try sema.ensureDeclAnalyzed(decl_index); |
| 26418 | 26458 | const tv = try mod.declPtr(decl_index).typedValue(); |
| 26459 | try sema.declareDependency(.{ .decl_val = decl_index }); | |
| 26419 | 26460 | assert(tv.ty.zigTypeTag(mod) == .Fn); |
| 26420 | 26461 | assert(try sema.fnHasRuntimeBits(tv.ty)); |
| 26421 | 26462 | const func_index = tv.val.toIntern(); |
| ... | ... | @@ -26837,6 +26878,13 @@ fn fieldVal( |
| 26837 | 26878 | const val = (try sema.resolveDefinedValue(block, object_src, dereffed_type)).?; |
| 26838 | 26879 | const child_type = val.toType(); |
| 26839 | 26880 | |
| 26881 | if (child_type.typeDeclInst(mod)) |type_decl_inst| { | |
| 26882 | try sema.declareDependency(.{ .namespace_name = .{ | |
| 26883 | .namespace = type_decl_inst, | |
| 26884 | .name = field_name, | |
| 26885 | } }); | |
| 26886 | } | |
| 26887 | ||
| 26840 | 26888 | switch (try child_type.zigTypeTagOrPoison(mod)) { |
| 26841 | 26889 | .ErrorSet => { |
| 26842 | 26890 | switch (ip.indexToKey(child_type.toIntern())) { |
| ... | ... | @@ -27060,6 +27108,13 @@ fn fieldPtr( |
| 27060 | 27108 | const val = (sema.resolveDefinedValue(block, src, inner) catch unreachable).?; |
| 27061 | 27109 | const child_type = val.toType(); |
| 27062 | 27110 | |
| 27111 | if (child_type.typeDeclInst(mod)) |type_decl_inst| { | |
| 27112 | try sema.declareDependency(.{ .namespace_name = .{ | |
| 27113 | .namespace = type_decl_inst, | |
| 27114 | .name = field_name, | |
| 27115 | } }); | |
| 27116 | } | |
| 27117 | ||
| 27063 | 27118 | switch (child_type.zigTypeTag(mod)) { |
| 27064 | 27119 | .ErrorSet => { |
| 27065 | 27120 | switch (ip.indexToKey(child_type.toIntern())) { |
| ... | ... | @@ -31129,6 +31184,7 @@ fn beginComptimePtrLoad( |
| 31129 | 31184 | const is_mutable = ptr.addr == .mut_decl; |
| 31130 | 31185 | const decl = mod.declPtr(decl_index); |
| 31131 | 31186 | const decl_tv = try decl.typedValue(); |
| 31187 | try sema.declareDependency(.{ .decl_val = decl_index }); | |
| 31132 | 31188 | if (decl.val.getVariable(mod) != null) return error.RuntimeLoad; |
| 31133 | 31189 | |
| 31134 | 31190 | const layout_defined = decl.ty.hasWellDefinedLayout(mod); |
| ... | ... | @@ -32382,6 +32438,8 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn |
| 32382 | 32438 | |
| 32383 | 32439 | const decl = mod.declPtr(decl_index); |
| 32384 | 32440 | const decl_tv = try decl.typedValue(); |
| 32441 | // TODO: if this is a `decl_ref`, only depend on decl type | |
| 32442 | try sema.declareDependency(.{ .decl_val = decl_index }); | |
| 32385 | 32443 | const ptr_ty = try sema.ptrType(.{ |
| 32386 | 32444 | .child = decl_tv.ty.toIntern(), |
| 32387 | 32445 | .flags = .{ |
| ... | ... | @@ -35678,7 +35736,7 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp |
| 35678 | 35736 | break :blk accumulator; |
| 35679 | 35737 | }; |
| 35680 | 35738 | |
| 35681 | const zir_index = struct_type.zir_index.resolve(ip); | |
| 35739 | const zir_index = struct_type.zir_index.unwrap().?.resolve(ip); | |
| 35682 | 35740 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; |
| 35683 | 35741 | assert(extended.opcode == .struct_decl); |
| 35684 | 35742 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| ... | ... | @@ -36443,7 +36501,7 @@ fn semaStructFields( |
| 36443 | 36501 | const decl = mod.declPtr(decl_index); |
| 36444 | 36502 | const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace; |
| 36445 | 36503 | const zir = mod.namespacePtr(namespace_index).file_scope.zir; |
| 36446 | const zir_index = struct_type.zir_index.resolve(ip); | |
| 36504 | const zir_index = struct_type.zir_index.unwrap().?.resolve(ip); | |
| 36447 | 36505 | |
| 36448 | 36506 | const fields_len, const small, var extra_index = structZirInfo(zir, zir_index); |
| 36449 | 36507 | |
| ... | ... | @@ -36714,7 +36772,7 @@ fn semaStructFieldInits( |
| 36714 | 36772 | const decl = mod.declPtr(decl_index); |
| 36715 | 36773 | const namespace_index = struct_type.namespace.unwrap() orelse decl.src_namespace; |
| 36716 | 36774 | const zir = mod.namespacePtr(namespace_index).file_scope.zir; |
| 36717 | const zir_index = struct_type.zir_index.resolve(ip); | |
| 36775 | const zir_index = struct_type.zir_index.unwrap().?.resolve(ip); | |
| 36718 | 36776 | const fields_len, const small, var extra_index = structZirInfo(zir, zir_index); |
| 36719 | 36777 | |
| 36720 | 36778 | var comptime_mutable_decls = std.ArrayList(InternPool.DeclIndex).init(gpa); |
| ... | ... | @@ -36863,7 +36921,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un |
| 36863 | 36921 | const ip = &mod.intern_pool; |
| 36864 | 36922 | const decl_index = union_type.decl; |
| 36865 | 36923 | const zir = mod.namespacePtr(union_type.namespace).file_scope.zir; |
| 36866 | const zir_index = union_type.zir_index.resolve(ip); | |
| 36924 | const zir_index = union_type.zir_index.unwrap().?.resolve(ip); | |
| 36867 | 36925 | const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; |
| 36868 | 36926 | assert(extended.opcode == .union_decl); |
| 36869 | 36927 | const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); |
| ... | ... | @@ -37307,6 +37365,7 @@ fn generateUnionTagTypeNumbered( |
| 37307 | 37365 | .names = enum_field_names, |
| 37308 | 37366 | .values = enum_field_vals, |
| 37309 | 37367 | .tag_mode = .explicit, |
| 37368 | .zir_index = .none, | |
| 37310 | 37369 | }); |
| 37311 | 37370 | |
| 37312 | 37371 | new_decl.ty = Type.type; |
| ... | ... | @@ -37357,6 +37416,7 @@ fn generateUnionTagTypeSimple( |
| 37357 | 37416 | .names = enum_field_names, |
| 37358 | 37417 | .values = &.{}, |
| 37359 | 37418 | .tag_mode = .auto, |
| 37419 | .zir_index = .none, | |
| 37360 | 37420 | }); |
| 37361 | 37421 | |
| 37362 | 37422 | const new_decl = mod.declPtr(new_decl_index); |
| ... | ... | @@ -38870,3 +38930,13 @@ fn ptrType(sema: *Sema, info: InternPool.Key.PtrType) CompileError!Type { |
| 38870 | 38930 | } |
| 38871 | 38931 | return sema.mod.ptrType(info); |
| 38872 | 38932 | } |
| 38933 | ||
| 38934 | pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void { | |
| 38935 | const depender = InternPool.Depender.wrap( | |
| 38936 | if (sema.owner_func_index != .none) | |
| 38937 | .{ .func = sema.owner_func_index } | |
| 38938 | else | |
| 38939 | .{ .decl = sema.owner_decl_index }, | |
| 38940 | ); | |
| 38941 | try sema.mod.intern_pool.addDependency(sema.gpa, depender, dependee); | |
| 38942 | } |
src/type.zig+12| ... | ... | @@ -4,6 +4,7 @@ const Value = @import("value.zig").Value; |
| 4 | 4 | const assert = std.debug.assert; |
| 5 | 5 | const Target = std.Target; |
| 6 | 6 | const Module = @import("Module.zig"); |
| 7 | const Zcu = Module; | |
| 7 | 8 | const log = std.log.scoped(.Type); |
| 8 | 9 | const target_util = @import("target.zig"); |
| 9 | 10 | const TypedValue = @import("TypedValue.zig"); |
| ... | ... | @@ -3228,6 +3229,17 @@ pub const Type = struct { |
| 3228 | 3229 | }; |
| 3229 | 3230 | } |
| 3230 | 3231 | |
| 3232 | pub fn typeDeclInst(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index { | |
| 3233 | return switch (zcu.intern_pool.indexToKey(ty.toIntern())) { | |
| 3234 | inline .struct_type, | |
| 3235 | .union_type, | |
| 3236 | .enum_type, | |
| 3237 | .opaque_type, | |
| 3238 | => |info| info.zir_index.unwrap(), | |
| 3239 | else => null, | |
| 3240 | }; | |
| 3241 | } | |
| 3242 | ||
| 3231 | 3243 | pub const @"u1": Type = .{ .ip_index = .u1_type }; |
| 3232 | 3244 | pub const @"u8": Type = .{ .ip_index = .u8_type }; |
| 3233 | 3245 | pub const @"u16": Type = .{ .ip_index = .u16_type }; |