diff options
Diffstat (limited to 'src/value.zig')
| -rw-r--r-- | src/value.zig | 67 |
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); } |
