mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 05:20:34 +00:00
Sema: optimize value resolution
This commit is contained in:
parent
6b56f4ff0b
commit
d7bd4f339c
@ -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 {
|
||||
|
||||
57
src/Sema.zig
57
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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user