aboutsummaryrefslogtreecommitdiff
path: root/src/value.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-01-24 20:38:56 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-01-24 21:53:57 -0700
commita2abbeef90bc3fa33acaf85902b4b97383999aaf (patch)
treeba7dfaf67adf2420ac40cbb765e01407387c399b /src/value.zig
parent8bb679bc6e25d1f7c08bb4e5e5272ae5f27aed47 (diff)
downloadzig-a2abbeef90bc3fa33acaf85902b4b97383999aaf.tar.gz
zig-a2abbeef90bc3fa33acaf85902b4b97383999aaf.zip
stage2: rework a lot of stuff
AstGen: * rename the known_has_bits flag to known_non_opv to make it better reflect what it actually means. * add a known_comptime_only flag. * make the flags take advantage of identifiers of primitives and the fact that zig has no shadowing. * correct the known_non_opv flag for function bodies. Sema: * Rename `hasCodeGenBits` to `hasRuntimeBits` to better reflect what it does. - This function got a bit more complicated in this commit because of the duality of function bodies: on one hand they have runtime bits, but on the other hand they require being comptime known. * WipAnonDecl now takes a LazySrcDecl parameter and performs the type resolutions that it needs during finish(). * Implement comptime `@ptrToInt`. Codegen: * Improved handling of lowering decl_ref; make it work for comptime-known ptr-to-int values. - This same change had to be made many different times; perhaps we should look into merging the implementations of `genTypedValue` across x86, arm, aarch64, and riscv.
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);
}