diff --git a/src/InternPool.zig b/src/InternPool.zig index bece6dbc4a..f93539daf8 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -622,6 +622,8 @@ pub const Key = union(enum) { len: Index = .none, pub const Addr = union(enum) { + const Tag = @typeInfo(Addr).Union.tag_type.?; + decl: Module.Decl.Index, mut_decl: MutDecl, comptime_field: Index, @@ -5702,10 +5704,18 @@ pub fn isNoReturn(ip: *const InternPool, ty: Index) bool { }; } +pub fn isUndef(ip: *const InternPool, val: Index) bool { + return val == .undef or ip.items.items(.tag)[@intFromEnum(val)] == .undef; +} + pub fn isRuntimeValue(ip: *const InternPool, val: Index) bool { return ip.items.items(.tag)[@intFromEnum(val)] == .runtime_value; } +pub fn isVariable(ip: *const InternPool, val: Index) bool { + return ip.items.items(.tag)[@intFromEnum(val)] == .variable; +} + pub fn getBackingDecl(ip: *const InternPool, val: Index) Module.Decl.OptionalIndex { var base = @intFromEnum(val); while (true) { @@ -5730,6 +5740,29 @@ pub fn getBackingDecl(ip: *const InternPool, val: Index) Module.Decl.OptionalInd } } +pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.Addr.Tag { + var base = @intFromEnum(val); + while (true) { + switch (ip.items.items(.tag)[base]) { + .ptr_decl => return .decl, + .ptr_mut_decl => return .mut_decl, + .ptr_comptime_field => return .comptime_field, + .ptr_int => return .int, + inline .ptr_eu_payload, + .ptr_opt_payload, + .ptr_elem, + .ptr_field, + => |tag| base = ip.extra.items[ + ip.items.items(.data)[base] + std.meta.fieldIndex(tag.Payload(), "base").? + ], + inline .ptr_slice => |tag| base = ip.extra.items[ + ip.items.items(.data)[base] + std.meta.fieldIndex(tag.Payload(), "ptr").? + ], + else => return null, + } + } +} + /// This is a particularly hot function, so we operate directly on encodings /// rather than the more straightforward implementation of calling `indexToKey`. pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPoison}!std.builtin.TypeId { diff --git a/src/Sema.zig b/src/Sema.zig index cd8de504ff..761dacf547 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1898,13 +1898,10 @@ fn resolveConstMaybeUndefVal( reason: []const u8, ) CompileError!Value { if (try sema.resolveMaybeUndefValAllowVariables(inst)) |val| { - switch (val.toIntern()) { - .generic_poison => return error.GenericPoison, - else => switch (sema.mod.intern_pool.indexToKey(val.toIntern())) { - .variable => return sema.failWithNeededComptime(block, src, reason), - else => return val, - }, - } + if (val.isGenericPoison()) return error.GenericPoison; + if (sema.mod.intern_pool.isVariable(val.toIntern())) + return sema.failWithNeededComptime(block, src, reason); + return val; } return sema.failWithNeededComptime(block, src, reason); } @@ -1919,15 +1916,11 @@ fn resolveConstValue( reason: []const u8, ) CompileError!Value { if (try sema.resolveMaybeUndefValAllowVariables(air_ref)) |val| { - switch (val.toIntern()) { - .generic_poison => return error.GenericPoison, - .undef => return sema.failWithUseOfUndef(block, src), - else => switch (sema.mod.intern_pool.indexToKey(val.toIntern())) { - .undef => return sema.failWithUseOfUndef(block, src), - .variable => return sema.failWithNeededComptime(block, src, reason), - else => return val, - }, - } + if (val.isGenericPoison()) return error.GenericPoison; + if (val.isUndef(sema.mod)) return sema.failWithUseOfUndef(block, src); + if (sema.mod.intern_pool.isVariable(val.toIntern())) + return sema.failWithNeededComptime(block, src, reason); + return val; } return sema.failWithNeededComptime(block, src, reason); } @@ -1971,14 +1964,9 @@ fn resolveMaybeUndefVal( inst: Air.Inst.Ref, ) CompileError!?Value { const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null; - switch (val.ip_index) { - .generic_poison => return error.GenericPoison, - .none => return val, - else => switch (sema.mod.intern_pool.indexToKey(val.toIntern())) { - .variable => return null, - else => return val, - }, - } + if (val.isGenericPoison()) return error.GenericPoison; + if (val.ip_index != .none and sema.mod.intern_pool.isVariable(val.toIntern())) return null; + return val; } /// Value Tag `variable` causes this function to return `null`. @@ -2002,20 +1990,13 @@ fn resolveMaybeUndefValIntable( inst: Air.Inst.Ref, ) CompileError!?Value { const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null; - var check = val; - while (true) switch (check.ip_index) { - .generic_poison => return error.GenericPoison, - .none => break, - else => switch (sema.mod.intern_pool.indexToKey(check.toIntern())) { - .variable => return null, - .ptr => |ptr| switch (ptr.addr) { - .decl, .mut_decl, .comptime_field => return null, - .int => break, - .eu_payload, .opt_payload => |base| check = base.toValue(), - .elem, .field => |base_index| check = base_index.base.toValue(), - }, - else => break, - }, + if (val.isGenericPoison()) return error.GenericPoison; + if (val.ip_index == .none) return val; + if (sema.mod.intern_pool.isVariable(val.toIntern())) return null; + if (sema.mod.intern_pool.getBackingAddrTag(val.toIntern())) |addr| switch (addr) { + .decl, .mut_decl, .comptime_field => return null, + .int => {}, + .eu_payload, .opt_payload, .elem, .field => unreachable, }; return try sema.resolveLazyValue(val); } diff --git a/src/value.zig b/src/value.zig index 0a5131d3f8..573f0ca7e2 100644 --- a/src/value.zig +++ b/src/value.zig @@ -1991,12 +1991,7 @@ pub const Value = struct { } pub fn isUndef(val: Value, mod: *Module) bool { - if (val.ip_index == .none) return false; - return switch (mod.intern_pool.indexToKey(val.toIntern())) { - .undef => true, - .simple_value => |v| v == .undefined, - else => false, - }; + return val.ip_index != .none and mod.intern_pool.isUndef(val.toIntern()); } /// TODO: check for cases such as array that is not marked undef but all the element