aboutsummaryrefslogtreecommitdiff
path: root/src/value.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-05-04 21:40:35 -0700
committerAndrew Kelley <andrew@ziglang.org>2023-06-10 20:42:28 -0700
commit6ab8b6f8b273356ce248a075b6a0657bfea33c79 (patch)
treecf0ea8802bc77376a38a4cfa25c6e9413d5b3fc0 /src/value.zig
parent773fabf3610629c8974b59ed6fbd27050b7e505b (diff)
downloadzig-6ab8b6f8b273356ce248a075b6a0657bfea33c79.tar.gz
zig-6ab8b6f8b273356ce248a075b6a0657bfea33c79.zip
stage2: move undef, unreach, null values to InternPool
Diffstat (limited to 'src/value.zig')
-rw-r--r--src/value.zig494
1 files changed, 254 insertions, 240 deletions
diff --git a/src/value.zig b/src/value.zig
index 6f7210c884..f1d706aa09 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -33,13 +33,10 @@ pub const Value = struct {
// Keep in sync with tools/stage2_pretty_printers_common.py
pub const Tag = enum(usize) {
// The first section of this enum are tags that require no payload.
- undef,
zero,
one,
- unreachable_value,
/// The only possible value for a particular type, which is stored externally.
the_only_possible_value,
- null_value,
empty_struct_value,
empty_array, // See last_no_payload_tag below.
@@ -132,14 +129,11 @@ pub const Value = struct {
pub fn Type(comptime t: Tag) type {
return switch (t) {
- .undef,
.zero,
.one,
- .unreachable_value,
.the_only_possible_value,
.empty_struct_value,
.empty_array,
- .null_value,
=> @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"),
.int_big_positive,
@@ -287,13 +281,10 @@ pub const Value = struct {
.legacy = .{ .tag_if_small_enough = self.legacy.tag_if_small_enough },
};
} else switch (self.legacy.ptr_otherwise.tag) {
- .undef,
.zero,
.one,
- .unreachable_value,
.the_only_possible_value,
.empty_array,
- .null_value,
.empty_struct_value,
=> unreachable,
@@ -522,7 +513,7 @@ pub const Value = struct {
) !void {
comptime assert(fmt.len == 0);
if (start_val.ip_index != .none) {
- try out_stream.print("(interned {d})", .{@enumToInt(start_val.ip_index)});
+ try out_stream.print("(interned: {})", .{start_val.ip_index});
return;
}
var val = start_val;
@@ -534,11 +525,8 @@ pub const Value = struct {
.@"union" => {
return out_stream.writeAll("(union value)");
},
- .null_value => return out_stream.writeAll("null"),
- .undef => return out_stream.writeAll("undefined"),
.zero => return out_stream.writeAll("0"),
.one => return out_stream.writeAll("1"),
- .unreachable_value => return out_stream.writeAll("unreachable"),
.the_only_possible_value => return out_stream.writeAll("(the only possible value)"),
.ty => return val.castTag(.ty).?.data.dump("", options, out_stream),
.lazy_align => {
@@ -811,8 +799,9 @@ pub const Value = struct {
switch (val.ip_index) {
.bool_false => return BigIntMutable.init(&space.limbs, 0).toConst(),
.bool_true => return BigIntMutable.init(&space.limbs, 1).toConst(),
+ .undef => unreachable,
+ .null_value => return BigIntMutable.init(&space.limbs, 0).toConst(),
.none => switch (val.tag()) {
- .null_value,
.zero,
.the_only_possible_value, // i0, u0
=> return BigIntMutable.init(&space.limbs, 0).toConst(),
@@ -832,8 +821,6 @@ pub const Value = struct {
.int_big_positive => return val.castTag(.int_big_positive).?.asBigInt(),
.int_big_negative => return val.castTag(.int_big_negative).?.asBigInt(),
- .undef => unreachable,
-
.lazy_align => {
const ty = val.castTag(.lazy_align).?.data;
if (opt_sema) |sema| {
@@ -880,6 +867,7 @@ pub const Value = struct {
switch (val.ip_index) {
.bool_false => return 0,
.bool_true => return 1,
+ .undef => unreachable,
.none => switch (val.tag()) {
.zero,
.the_only_possible_value, // i0, u0
@@ -892,8 +880,6 @@ pub const Value = struct {
.int_big_positive => return val.castTag(.int_big_positive).?.asBigInt().to(u64) catch null,
.int_big_negative => return val.castTag(.int_big_negative).?.asBigInt().to(u64) catch null,
- .undef => unreachable,
-
.lazy_align => {
const ty = val.castTag(.lazy_align).?.data;
if (opt_sema) |sema| {
@@ -913,9 +899,9 @@ pub const Value = struct {
else => return null,
},
- else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
- .int => |int| return int.big_int.to(u64) catch null,
- else => unreachable,
+ else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
+ .int => |int| int.big_int.to(u64) catch null,
+ else => null,
},
}
}
@@ -930,6 +916,7 @@ pub const Value = struct {
switch (val.ip_index) {
.bool_false => return 0,
.bool_true => return 1,
+ .undef => unreachable,
.none => switch (val.tag()) {
.zero,
.the_only_possible_value, // i0, u0
@@ -951,7 +938,6 @@ pub const Value = struct {
return @intCast(i64, ty.abiSize(mod));
},
- .undef => unreachable,
else => unreachable,
},
else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
@@ -2032,8 +2018,7 @@ pub const Value = struct {
const a_tag = a.tag();
const b_tag = b.tag();
if (a_tag == b_tag) switch (a_tag) {
- .undef => return true,
- .null_value, .the_only_possible_value, .empty_struct_value => return true,
+ .the_only_possible_value, .empty_struct_value => return true,
.enum_literal => {
const a_name = a.castTag(.enum_literal).?.data;
const b_name = b.castTag(.enum_literal).?.data;
@@ -2162,9 +2147,7 @@ pub const Value = struct {
return eqlAdvanced(a_union.val, active_field_ty, b_union.val, active_field_ty, mod, opt_sema);
},
else => {},
- } else if (b_tag == .null_value or b_tag == .@"error") {
- return false;
- } else if (a_tag == .undef or b_tag == .undef) {
+ } else if (b_tag == .@"error") {
return false;
}
@@ -2283,7 +2266,7 @@ pub const Value = struct {
if (a_nan) return true;
return a_float == b_float;
},
- .Optional => if (a_tag != .null_value and b_tag == .opt_payload) {
+ .Optional => if (b_tag == .opt_payload) {
var sub_pl: Payload.SubValue = .{
.base = .{ .tag = b.tag() },
.data = a,
@@ -2301,7 +2284,7 @@ pub const Value = struct {
},
else => {},
}
- if (a_tag == .null_value or a_tag == .@"error") return false;
+ if (a_tag == .@"error") return false;
return (try orderAdvanced(a, b, mod, opt_sema)).compare(.eq);
}
@@ -2642,7 +2625,6 @@ pub const Value = struct {
.zero,
.one,
- .null_value,
.int_u64,
.int_i64,
.int_big_positive,
@@ -2717,102 +2699,108 @@ pub const Value = struct {
arena: ?Allocator,
buffer: *ElemValueBuffer,
) error{OutOfMemory}!Value {
- switch (val.tag()) {
- // This is the case of accessing an element of an undef array.
+ switch (val.ip_index) {
.undef => return Value.undef,
- .empty_array => unreachable, // out of bounds array index
- .empty_struct_value => unreachable, // out of bounds array index
+ .none => switch (val.tag()) {
+ // This is the case of accessing an element of an undef array.
+ .empty_array => unreachable, // out of bounds array index
+ .empty_struct_value => unreachable, // out of bounds array index
- .empty_array_sentinel => {
- assert(index == 0); // The only valid index for an empty array with sentinel.
- return val.castTag(.empty_array_sentinel).?.data;
- },
+ .empty_array_sentinel => {
+ assert(index == 0); // The only valid index for an empty array with sentinel.
+ return val.castTag(.empty_array_sentinel).?.data;
+ },
- .bytes => {
- const byte = val.castTag(.bytes).?.data[index];
- if (arena) |a| {
- return Tag.int_u64.create(a, byte);
- } else {
- buffer.* = .{
- .base = .{ .tag = .int_u64 },
- .data = byte,
- };
- return initPayload(&buffer.base);
- }
- },
- .str_lit => {
- const str_lit = val.castTag(.str_lit).?.data;
- const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
- const byte = bytes[index];
- if (arena) |a| {
- return Tag.int_u64.create(a, byte);
- } else {
- buffer.* = .{
- .base = .{ .tag = .int_u64 },
- .data = byte,
- };
- return initPayload(&buffer.base);
- }
- },
+ .bytes => {
+ const byte = val.castTag(.bytes).?.data[index];
+ if (arena) |a| {
+ return Tag.int_u64.create(a, byte);
+ } else {
+ buffer.* = .{
+ .base = .{ .tag = .int_u64 },
+ .data = byte,
+ };
+ return initPayload(&buffer.base);
+ }
+ },
+ .str_lit => {
+ const str_lit = val.castTag(.str_lit).?.data;
+ const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
+ const byte = bytes[index];
+ if (arena) |a| {
+ return Tag.int_u64.create(a, byte);
+ } else {
+ buffer.* = .{
+ .base = .{ .tag = .int_u64 },
+ .data = byte,
+ };
+ return initPayload(&buffer.base);
+ }
+ },
- // No matter the index; all the elements are the same!
- .repeated => return val.castTag(.repeated).?.data,
+ // No matter the index; all the elements are the same!
+ .repeated => return val.castTag(.repeated).?.data,
- .aggregate => return val.castTag(.aggregate).?.data[index],
- .slice => return val.castTag(.slice).?.data.ptr.elemValueAdvanced(mod, index, arena, buffer),
+ .aggregate => return val.castTag(.aggregate).?.data[index],
+ .slice => return val.castTag(.slice).?.data.ptr.elemValueAdvanced(mod, index, arena, buffer),
- .decl_ref => return mod.declPtr(val.castTag(.decl_ref).?.data).val.elemValueAdvanced(mod, index, arena, buffer),
- .decl_ref_mut => return mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val.elemValueAdvanced(mod, index, arena, buffer),
- .comptime_field_ptr => return val.castTag(.comptime_field_ptr).?.data.field_val.elemValueAdvanced(mod, index, arena, buffer),
- .elem_ptr => {
- const data = val.castTag(.elem_ptr).?.data;
- return data.array_ptr.elemValueAdvanced(mod, index + data.index, arena, buffer);
- },
- .field_ptr => {
- const data = val.castTag(.field_ptr).?.data;
- if (data.container_ptr.pointerDecl()) |decl_index| {
- const container_decl = mod.declPtr(decl_index);
- const field_type = data.container_ty.structFieldType(data.field_index);
- const field_val = container_decl.val.fieldValue(field_type, mod, data.field_index);
- return field_val.elemValueAdvanced(mod, index, arena, buffer);
- } else unreachable;
- },
+ .decl_ref => return mod.declPtr(val.castTag(.decl_ref).?.data).val.elemValueAdvanced(mod, index, arena, buffer),
+ .decl_ref_mut => return mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val.elemValueAdvanced(mod, index, arena, buffer),
+ .comptime_field_ptr => return val.castTag(.comptime_field_ptr).?.data.field_val.elemValueAdvanced(mod, index, arena, buffer),
+ .elem_ptr => {
+ const data = val.castTag(.elem_ptr).?.data;
+ return data.array_ptr.elemValueAdvanced(mod, index + data.index, arena, buffer);
+ },
+ .field_ptr => {
+ const data = val.castTag(.field_ptr).?.data;
+ if (data.container_ptr.pointerDecl()) |decl_index| {
+ const container_decl = mod.declPtr(decl_index);
+ const field_type = data.container_ty.structFieldType(data.field_index);
+ const field_val = container_decl.val.fieldValue(field_type, mod, data.field_index);
+ return field_val.elemValueAdvanced(mod, index, arena, buffer);
+ } else unreachable;
+ },
- // The child type of arrays which have only one possible value need
- // to have only one possible value itself.
- .the_only_possible_value => return val,
+ // The child type of arrays which have only one possible value need
+ // to have only one possible value itself.
+ .the_only_possible_value => return val,
- .opt_payload_ptr => return val.castTag(.opt_payload_ptr).?.data.container_ptr.elemValueAdvanced(mod, index, arena, buffer),
- .eu_payload_ptr => return val.castTag(.eu_payload_ptr).?.data.container_ptr.elemValueAdvanced(mod, index, arena, buffer),
+ .opt_payload_ptr => return val.castTag(.opt_payload_ptr).?.data.container_ptr.elemValueAdvanced(mod, index, arena, buffer),
+ .eu_payload_ptr => return val.castTag(.eu_payload_ptr).?.data.container_ptr.elemValueAdvanced(mod, index, arena, buffer),
- .opt_payload => return val.castTag(.opt_payload).?.data.elemValueAdvanced(mod, index, arena, buffer),
- .eu_payload => return val.castTag(.eu_payload).?.data.elemValueAdvanced(mod, index, arena, buffer),
+ .opt_payload => return val.castTag(.opt_payload).?.data.elemValueAdvanced(mod, index, arena, buffer),
+ .eu_payload => return val.castTag(.eu_payload).?.data.elemValueAdvanced(mod, index, arena, buffer),
+ else => unreachable,
+ },
else => unreachable,
}
}
/// Returns true if a Value is backed by a variable
pub fn isVariable(val: Value, mod: *Module) bool {
- return switch (val.tag()) {
- .slice => val.castTag(.slice).?.data.ptr.isVariable(mod),
- .comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isVariable(mod),
- .elem_ptr => val.castTag(.elem_ptr).?.data.array_ptr.isVariable(mod),
- .field_ptr => val.castTag(.field_ptr).?.data.container_ptr.isVariable(mod),
- .eu_payload_ptr => val.castTag(.eu_payload_ptr).?.data.container_ptr.isVariable(mod),
- .opt_payload_ptr => val.castTag(.opt_payload_ptr).?.data.container_ptr.isVariable(mod),
- .decl_ref => {
- const decl = mod.declPtr(val.castTag(.decl_ref).?.data);
- assert(decl.has_tv);
- return decl.val.isVariable(mod);
- },
- .decl_ref_mut => {
- const decl = mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index);
- assert(decl.has_tv);
- return decl.val.isVariable(mod);
- },
+ return switch (val.ip_index) {
+ .none => switch (val.tag()) {
+ .slice => val.castTag(.slice).?.data.ptr.isVariable(mod),
+ .comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isVariable(mod),
+ .elem_ptr => val.castTag(.elem_ptr).?.data.array_ptr.isVariable(mod),
+ .field_ptr => val.castTag(.field_ptr).?.data.container_ptr.isVariable(mod),
+ .eu_payload_ptr => val.castTag(.eu_payload_ptr).?.data.container_ptr.isVariable(mod),
+ .opt_payload_ptr => val.castTag(.opt_payload_ptr).?.data.container_ptr.isVariable(mod),
+ .decl_ref => {
+ const decl = mod.declPtr(val.castTag(.decl_ref).?.data);
+ assert(decl.has_tv);
+ return decl.val.isVariable(mod);
+ },
+ .decl_ref_mut => {
+ const decl = mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index);
+ assert(decl.has_tv);
+ return decl.val.isVariable(mod);
+ },
- .variable => true,
+ .variable => true,
+ else => false,
+ },
else => false,
};
}
@@ -2878,39 +2866,46 @@ pub const Value = struct {
}
pub fn fieldValue(val: Value, ty: Type, mod: *const Module, index: usize) Value {
- switch (val.tag()) {
- .aggregate => {
- const field_values = val.castTag(.aggregate).?.data;
- return field_values[index];
- },
- .@"union" => {
- const payload = val.castTag(.@"union").?.data;
- // TODO assert the tag is correct
- return payload.val;
- },
+ switch (val.ip_index) {
+ .undef => return Value.undef,
+ .none => switch (val.tag()) {
+ .aggregate => {
+ const field_values = val.castTag(.aggregate).?.data;
+ return field_values[index];
+ },
+ .@"union" => {
+ const payload = val.castTag(.@"union").?.data;
+ // TODO assert the tag is correct
+ return payload.val;
+ },
- .the_only_possible_value => return ty.onePossibleValue(mod).?,
+ .the_only_possible_value => return ty.onePossibleValue(mod).?,
- .empty_struct_value => {
- if (ty.isSimpleTupleOrAnonStruct()) {
- const tuple = ty.tupleFields();
- return tuple.values[index];
- }
- if (ty.structFieldValueComptime(mod, index)) |some| {
- return some;
- }
- unreachable;
- },
- .undef => return Value.undef,
+ .empty_struct_value => {
+ if (ty.isSimpleTupleOrAnonStruct()) {
+ const tuple = ty.tupleFields();
+ return tuple.values[index];
+ }
+ if (ty.structFieldValueComptime(mod, index)) |some| {
+ return some;
+ }
+ unreachable;
+ },
+ else => unreachable,
+ },
else => unreachable,
}
}
pub fn unionTag(val: Value) Value {
- switch (val.tag()) {
- .undef, .enum_field_index => return val,
- .@"union" => return val.castTag(.@"union").?.data.tag,
+ switch (val.ip_index) {
+ .undef => return val,
+ .none => switch (val.tag()) {
+ .enum_field_index => return val,
+ .@"union" => return val.castTag(.@"union").?.data.tag,
+ else => unreachable,
+ },
else => unreachable,
}
}
@@ -2946,15 +2941,15 @@ pub const Value = struct {
});
}
- pub fn isUndef(self: Value) bool {
- return self.tag() == .undef;
+ pub fn isUndef(val: Value) bool {
+ return val.ip_index == .undef;
}
/// TODO: check for cases such as array that is not marked undef but all the element
/// values are marked undef, or struct that is not marked undef but all fields are marked
/// undef, etc.
- pub fn isUndefDeep(self: Value) bool {
- return self.isUndef();
+ pub fn isUndefDeep(val: Value) bool {
+ return val.isUndef();
}
/// Returns true if any value contained in `self` is undefined.
@@ -2962,27 +2957,29 @@ pub const Value = struct {
/// values are marked undef, or struct that is not marked undef but all fields are marked
/// undef, etc.
pub fn anyUndef(self: Value, mod: *Module) bool {
- switch (self.tag()) {
- .slice => {
- const payload = self.castTag(.slice).?;
- const len = payload.data.len.toUnsignedInt(mod);
-
- var elem_value_buf: ElemValueBuffer = undefined;
- var i: usize = 0;
- while (i < len) : (i += 1) {
- const elem_val = payload.data.ptr.elemValueBuffer(mod, i, &elem_value_buf);
- if (elem_val.anyUndef(mod)) return true;
- }
- },
+ switch (self.ip_index) {
+ .undef => return true,
+ .none => switch (self.tag()) {
+ .slice => {
+ const payload = self.castTag(.slice).?;
+ const len = payload.data.len.toUnsignedInt(mod);
+
+ var elem_value_buf: ElemValueBuffer = undefined;
+ var i: usize = 0;
+ while (i < len) : (i += 1) {
+ const elem_val = payload.data.ptr.elemValueBuffer(mod, i, &elem_value_buf);
+ if (elem_val.anyUndef(mod)) return true;
+ }
+ },
- .aggregate => {
- const payload = self.castTag(.aggregate).?;
- for (payload.data) |val| {
- if (val.anyUndef(mod)) return true;
- }
+ .aggregate => {
+ const payload = self.castTag(.aggregate).?;
+ for (payload.data) |val| {
+ if (val.anyUndef(mod)) return true;
+ }
+ },
+ else => {},
},
-
- .undef => return true,
else => {},
}
@@ -2992,30 +2989,33 @@ pub const Value = struct {
/// Asserts the value is not undefined and not unreachable.
/// Integer value 0 is considered null because of C pointers.
pub fn isNull(self: Value, mod: *const Module) bool {
- return switch (self.tag()) {
+ return switch (self.ip_index) {
+ .undef => unreachable,
+ .unreachable_value => unreachable,
.null_value => true,
- .opt_payload => false,
+ .none => switch (self.tag()) {
+ .opt_payload => false,
- // If it's not one of those two tags then it must be a C pointer value,
- // in which case the value 0 is null and other values are non-null.
+ // If it's not one of those two tags then it must be a C pointer value,
+ // in which case the value 0 is null and other values are non-null.
- .zero,
- .the_only_possible_value,
- => true,
+ .zero,
+ .the_only_possible_value,
+ => true,
- .one => false,
+ .one => false,
- .int_u64,
- .int_i64,
- .int_big_positive,
- .int_big_negative,
- => self.orderAgainstZero(mod).compare(.eq),
+ .int_u64,
+ .int_i64,
+ .int_big_positive,
+ .int_big_negative,
+ => self.orderAgainstZero(mod).compare(.eq),
- .undef => unreachable,
- .unreachable_value => unreachable,
- .inferred_alloc => unreachable,
- .inferred_alloc_comptime => unreachable,
+ .inferred_alloc => unreachable,
+ .inferred_alloc_comptime => unreachable,
+ else => false,
+ },
else => false,
};
}
@@ -3025,18 +3025,21 @@ pub const Value = struct {
/// something is an error or not because it works without having to figure out the
/// string.
pub fn getError(self: Value) ?[]const u8 {
- return switch (self.tag()) {
- .@"error" => self.castTag(.@"error").?.data.name,
- .int_u64 => @panic("TODO"),
- .int_i64 => @panic("TODO"),
- .int_big_positive => @panic("TODO"),
- .int_big_negative => @panic("TODO"),
- .one => @panic("TODO"),
+ return switch (self.ip_index) {
.undef => unreachable,
.unreachable_value => unreachable,
- .inferred_alloc => unreachable,
- .inferred_alloc_comptime => unreachable,
+ .none => switch (self.tag()) {
+ .@"error" => self.castTag(.@"error").?.data.name,
+ .int_u64 => @panic("TODO"),
+ .int_i64 => @panic("TODO"),
+ .int_big_positive => @panic("TODO"),
+ .int_big_negative => @panic("TODO"),
+ .one => @panic("TODO"),
+ .inferred_alloc => unreachable,
+ .inferred_alloc_comptime => unreachable,
+ else => null,
+ },
else => null,
};
}
@@ -3044,13 +3047,16 @@ pub const Value = struct {
/// Assumes the type is an error union. Returns true if and only if the value is
/// the error union payload, not an error.
pub fn errorUnionIsPayload(val: Value) bool {
- return switch (val.tag()) {
- .eu_payload => true,
- else => false,
-
+ return switch (val.ip_index) {
.undef => unreachable,
- .inferred_alloc => unreachable,
- .inferred_alloc_comptime => unreachable,
+ .none => switch (val.tag()) {
+ .eu_payload => true,
+ else => false,
+
+ .inferred_alloc => unreachable,
+ .inferred_alloc_comptime => unreachable,
+ },
+ else => false,
};
}
@@ -3065,17 +3071,20 @@ pub const Value = struct {
/// Valid for all types. Asserts the value is not undefined.
pub fn isFloat(self: Value) bool {
- return switch (self.tag()) {
+ return switch (self.ip_index) {
.undef => unreachable,
- .inferred_alloc => unreachable,
- .inferred_alloc_comptime => unreachable,
+ .none => switch (self.tag()) {
+ .inferred_alloc => unreachable,
+ .inferred_alloc_comptime => unreachable,
- .float_16,
- .float_32,
- .float_64,
- .float_80,
- .float_128,
- => true,
+ .float_16,
+ .float_32,
+ .float_64,
+ .float_80,
+ .float_128,
+ => true,
+ else => false,
+ },
else => false,
};
}
@@ -3102,40 +3111,44 @@ pub const Value = struct {
pub fn intToFloatScalar(val: Value, arena: Allocator, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value {
const target = mod.getTarget();
- switch (val.tag()) {
- .undef, .zero, .one => return val,
- .the_only_possible_value => return Value.initTag(.zero), // for i0, u0
- .int_u64 => {
- return intToFloatInner(val.castTag(.int_u64).?.data, arena, float_ty, target);
- },
- .int_i64 => {
- return intToFloatInner(val.castTag(.int_i64).?.data, arena, float_ty, target);
- },
- .int_big_positive => {
- const limbs = val.castTag(.int_big_positive).?.data;
- const float = bigIntToFloat(limbs, true);
- return floatToValue(float, arena, float_ty, target);
- },
- .int_big_negative => {
- const limbs = val.castTag(.int_big_negative).?.data;
- const float = bigIntToFloat(limbs, false);
- return floatToValue(float, arena, float_ty, target);
- },
- .lazy_align => {
- const ty = val.castTag(.lazy_align).?.data;
- if (opt_sema) |sema| {
- return intToFloatInner((try ty.abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar, arena, float_ty, target);
- } else {
- return intToFloatInner(ty.abiAlignment(mod), arena, float_ty, target);
- }
- },
- .lazy_size => {
- const ty = val.castTag(.lazy_size).?.data;
- if (opt_sema) |sema| {
- return intToFloatInner((try ty.abiSizeAdvanced(mod, .{ .sema = sema })).scalar, arena, float_ty, target);
- } else {
- return intToFloatInner(ty.abiSize(mod), arena, float_ty, target);
- }
+ switch (val.ip_index) {
+ .undef => return val,
+ .none => switch (val.tag()) {
+ .zero, .one => return val,
+ .the_only_possible_value => return Value.initTag(.zero), // for i0, u0
+ .int_u64 => {
+ return intToFloatInner(val.castTag(.int_u64).?.data, arena, float_ty, target);
+ },
+ .int_i64 => {
+ return intToFloatInner(val.castTag(.int_i64).?.data, arena, float_ty, target);
+ },
+ .int_big_positive => {
+ const limbs = val.castTag(.int_big_positive).?.data;
+ const float = bigIntToFloat(limbs, true);
+ return floatToValue(float, arena, float_ty, target);
+ },
+ .int_big_negative => {
+ const limbs = val.castTag(.int_big_negative).?.data;
+ const float = bigIntToFloat(limbs, false);
+ return floatToValue(float, arena, float_ty, target);
+ },
+ .lazy_align => {
+ const ty = val.castTag(.lazy_align).?.data;
+ if (opt_sema) |sema| {
+ return intToFloatInner((try ty.abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar, arena, float_ty, target);
+ } else {
+ return intToFloatInner(ty.abiAlignment(mod), arena, float_ty, target);
+ }
+ },
+ .lazy_size => {
+ const ty = val.castTag(.lazy_size).?.data;
+ if (opt_sema) |sema| {
+ return intToFloatInner((try ty.abiSizeAdvanced(mod, .{ .sema = sema })).scalar, arena, float_ty, target);
+ } else {
+ return intToFloatInner(ty.abiSize(mod), arena, float_ty, target);
+ }
+ },
+ else => unreachable,
},
else => unreachable,
}
@@ -3381,7 +3394,7 @@ pub const Value = struct {
arena: Allocator,
mod: *Module,
) !Value {
- if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
+ if (lhs.isUndef() or rhs.isUndef()) return Value.undef;
if (ty.zigTypeTag(mod) == .ComptimeInt) {
return intMul(lhs, rhs, ty, arena, mod);
@@ -3492,7 +3505,7 @@ pub const Value = struct {
/// operands must be integers; handles undefined.
pub fn bitwiseNotScalar(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
- if (val.isUndef()) return Value.initTag(.undef);
+ if (val.isUndef()) return Value.undef;
const info = ty.intInfo(mod);
@@ -3532,7 +3545,7 @@ pub const Value = struct {
/// operands must be integers; handles undefined.
pub fn bitwiseAndScalar(lhs: Value, rhs: Value, arena: Allocator, mod: *Module) !Value {
- if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
+ if (lhs.isUndef() or rhs.isUndef()) return Value.undef;
// TODO is this a performance issue? maybe we should try the operation without
// resorting to BigInt first.
@@ -3568,7 +3581,7 @@ pub const Value = struct {
/// operands must be integers; handles undefined.
pub fn bitwiseNandScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
- if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
+ if (lhs.isUndef() or rhs.isUndef()) return Value.undef;
const anded = try bitwiseAnd(lhs, rhs, ty, arena, mod);
@@ -3598,7 +3611,7 @@ pub const Value = struct {
/// operands must be integers; handles undefined.
pub fn bitwiseOrScalar(lhs: Value, rhs: Value, arena: Allocator, mod: *Module) !Value {
- if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
+ if (lhs.isUndef() or rhs.isUndef()) return Value.undef;
// TODO is this a performance issue? maybe we should try the operation without
// resorting to BigInt first.
@@ -3633,7 +3646,7 @@ pub const Value = struct {
/// operands must be integers; handles undefined.
pub fn bitwiseXorScalar(lhs: Value, rhs: Value, arena: Allocator, mod: *Module) !Value {
- if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
+ if (lhs.isUndef() or rhs.isUndef()) return Value.undef;
// TODO is this a performance issue? maybe we should try the operation without
// resorting to BigInt first.
@@ -5393,11 +5406,12 @@ pub const Value = struct {
.ip_index = .none,
.legacy = .{ .ptr_otherwise = &negative_one_payload.base },
};
- pub const undef = initTag(.undef);
+ pub const undef: Value = .{ .ip_index = .undef, .legacy = undefined };
pub const @"void": Value = .{ .ip_index = .void_value, .legacy = undefined };
- pub const @"null" = initTag(.null_value);
+ pub const @"null": Value = .{ .ip_index = .null_value, .legacy = undefined };
pub const @"false": Value = .{ .ip_index = .bool_false, .legacy = undefined };
pub const @"true": Value = .{ .ip_index = .bool_true, .legacy = undefined };
+ pub const @"unreachable": Value = .{ .ip_index = .unreachable_value, .legacy = undefined };
pub const generic_poison: Value = .{ .ip_index = .generic_poison, .legacy = undefined };
pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type, .legacy = undefined };