aboutsummaryrefslogtreecommitdiff
path: root/src/value.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/value.zig')
-rw-r--r--src/value.zig67
1 files changed, 62 insertions, 5 deletions
diff --git a/src/value.zig b/src/value.zig
index 2c177f3e93..39cb1a4dbc 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -1225,7 +1225,7 @@ pub const Value = extern union {
/// Asserts the value is an integer and not undefined.
/// Returns the number of bits the value requires to represent stored in twos complement form.
- pub fn intBitCountTwosComp(self: Value) usize {
+ pub fn intBitCountTwosComp(self: Value, target: Target) usize {
switch (self.tag()) {
.zero,
.bool_false,
@@ -1244,6 +1244,15 @@ pub const Value = extern union {
.int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().bitCountTwosComp(),
.int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().bitCountTwosComp(),
+ .decl_ref_mut,
+ .extern_fn,
+ .decl_ref,
+ .function,
+ .variable,
+ .eu_payload_ptr,
+ .opt_payload_ptr,
+ => return target.cpu.arch.ptrBitWidth(),
+
else => {
var buffer: BigIntSpace = undefined;
return self.toBigInt(&buffer).bitCountTwosComp();
@@ -1333,6 +1342,20 @@ pub const Value = extern union {
return true;
},
+ .decl_ref_mut,
+ .extern_fn,
+ .decl_ref,
+ .function,
+ .variable,
+ => {
+ const info = ty.intInfo(target);
+ const ptr_bits = target.cpu.arch.ptrBitWidth();
+ return switch (info.signedness) {
+ .signed => info.bits > ptr_bits,
+ .unsigned => info.bits >= ptr_bits,
+ };
+ },
+
else => unreachable,
}
}
@@ -1397,6 +1420,11 @@ pub const Value = extern union {
.one,
.bool_true,
+ .decl_ref,
+ .decl_ref_mut,
+ .extern_fn,
+ .function,
+ .variable,
=> .gt,
.int_u64 => std.math.order(lhs.castTag(.int_u64).?.data, 0),
@@ -1417,10 +1445,18 @@ pub const Value = extern union {
pub fn order(lhs: Value, rhs: Value) std.math.Order {
const lhs_tag = lhs.tag();
const rhs_tag = rhs.tag();
- const lhs_is_zero = lhs_tag == .zero;
- const rhs_is_zero = rhs_tag == .zero;
- if (lhs_is_zero) return rhs.orderAgainstZero().invert();
- if (rhs_is_zero) return lhs.orderAgainstZero();
+ const lhs_against_zero = lhs.orderAgainstZero();
+ const rhs_against_zero = rhs.orderAgainstZero();
+ switch (lhs_against_zero) {
+ .lt => if (rhs_against_zero != .lt) return .lt,
+ .eq => return rhs_against_zero.invert(),
+ .gt => {},
+ }
+ switch (rhs_against_zero) {
+ .lt => if (lhs_against_zero != .lt) return .gt,
+ .eq => return lhs_against_zero,
+ .gt => {},
+ }
const lhs_float = lhs.isFloat();
const rhs_float = rhs.isFloat();
@@ -1451,6 +1487,27 @@ pub const Value = extern union {
/// Asserts the value is comparable. Does not take a type parameter because it supports
/// comparisons between heterogeneous types.
pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value) bool {
+ if (lhs.pointerDecl()) |lhs_decl| {
+ if (rhs.pointerDecl()) |rhs_decl| {
+ switch (op) {
+ .eq => return lhs_decl == rhs_decl,
+ .neq => return lhs_decl != rhs_decl,
+ else => {},
+ }
+ } else {
+ switch (op) {
+ .eq => return false,
+ .neq => return true,
+ else => {},
+ }
+ }
+ } else if (rhs.pointerDecl()) |_| {
+ switch (op) {
+ .eq => return false,
+ .neq => return true,
+ else => {},
+ }
+ }
return order(lhs, rhs).compare(op);
}