Commit e77ca6af70
Changed files (1)
src-self-hosted
src-self-hosted/value.zig
@@ -80,6 +80,11 @@ pub const Value = extern union {
elem_ptr,
bytes,
repeated, // the value is a value repeated some number of times
+ float,
+ float_16,
+ float_32,
+ float_64,
+ float_128,
pub const last_no_payload_tag = Tag.bool_false;
pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
@@ -213,6 +218,10 @@ pub const Value = extern union {
};
return Value{ .ptr_otherwise = &new_payload.base };
},
+ .float_16 => return self.copyPayloadShallow(allocator, Payload.Float_16),
+ .float_32 => return self.copyPayloadShallow(allocator, Payload.Float_32),
+ .float_64 => return self.copyPayloadShallow(allocator, Payload.Float_64),
+ .float_128, .float => return self.copyPayloadShallow(allocator, Payload.Float_128),
}
}
@@ -300,6 +309,10 @@ pub const Value = extern union {
try out_stream.writeAll("(repeated) ");
val = val.cast(Payload.Repeated).?.val;
},
+ .float_16 => return out_stream.print("{}", .{val.cast(Payload.Float_16).?.val}),
+ .float_32 => return out_stream.print("{}", .{val.cast(Payload.Float_32).?.val}),
+ .float_64 => return out_stream.print("{}", .{val.cast(Payload.Float_64).?.val}),
+ .float_128, .float => return out_stream.print("{}", .{val.cast(Payload.Float_128).?.val}),
};
}
@@ -380,6 +393,11 @@ pub const Value = extern union {
.elem_ptr,
.bytes,
.repeated,
+ .float,
+ .float_16,
+ .float_32,
+ .float_64,
+ .float_128,
=> unreachable,
};
}
@@ -435,6 +453,11 @@ pub const Value = extern union {
.bytes,
.undef,
.repeated,
+ .float,
+ .float_16,
+ .float_32,
+ .float_64,
+ .float_128,
=> unreachable,
.the_one_possible_value, // An integer with one possible value is always zero.
@@ -502,6 +525,11 @@ pub const Value = extern union {
.bytes,
.undef,
.repeated,
+ .float,
+ .float_16,
+ .float_32,
+ .float_64,
+ .float_128,
=> unreachable,
.zero,
@@ -518,6 +546,25 @@ pub const Value = extern union {
}
}
+ pub fn toBool(self: Value) bool {
+ return switch (self.tag()) {
+ .bool_true => true,
+ .bool_false, .zero => false,
+ else => unreachable,
+ };
+ }
+
+ /// Asserts that the value is a float.
+ pub fn toF128(self: Value) f128 {
+ return switch (self.tag()) {
+ .float_16 => self.cast(Payload.Float_16).?.val,
+ .float_32 => self.cast(Payload.Float_32).?.val,
+ .float_64 => self.cast(Payload.Float_64).?.val,
+ .float_128, .float => self.cast(Payload.Float_128).?.val,
+ else => unreachable,
+ };
+ }
+
/// 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 {
@@ -570,6 +617,11 @@ pub const Value = extern union {
.bytes,
.undef,
.repeated,
+ .float,
+ .float_16,
+ .float_32,
+ .float_64,
+ .float_128,
=> unreachable,
.the_one_possible_value, // an integer with one possible value is always zero
@@ -642,6 +694,11 @@ pub const Value = extern union {
.elem_ptr,
.bytes,
.repeated,
+ .float,
+ .float_16,
+ .float_32,
+ .float_64,
+ .float_128,
=> unreachable,
.zero,
@@ -762,11 +819,17 @@ pub const Value = extern union {
=> unreachable,
.zero => false,
+
+ .float_16 => @rem(self.cast(Payload.Float_16).?.val, 1) != 0,
+ .float_32 => @rem(self.cast(Payload.Float_32).?.val, 1) != 0,
+ .float_64 => @rem(self.cast(Payload.Float_64).?.val, 1) != 0,
+ // .float_128, .float => @rem(self.cast(Payload.Float_128).?.val, 1) != 0,
+ .float_128, .float => @panic("TODO lld: error: undefined symbol: fmodl"),
};
}
pub fn orderAgainstZero(lhs: Value) std.math.Order {
- switch (lhs.tag()) {
+ return switch (lhs.tag()) {
.ty,
.u8_type,
.i8_type,
@@ -820,15 +883,20 @@ pub const Value = extern union {
.zero,
.the_one_possible_value, // an integer with one possible value is always zero
.bool_false,
- => return .eq,
+ => .eq,
- .bool_true => return .gt,
+ .bool_true => .gt,
- .int_u64 => return std.math.order(lhs.cast(Payload.Int_u64).?.int, 0),
- .int_i64 => return std.math.order(lhs.cast(Payload.Int_i64).?.int, 0),
- .int_big_positive => return lhs.cast(Payload.IntBigPositive).?.asBigInt().orderAgainstScalar(0),
- .int_big_negative => return lhs.cast(Payload.IntBigNegative).?.asBigInt().orderAgainstScalar(0),
- }
+ .int_u64 => std.math.order(lhs.cast(Payload.Int_u64).?.int, 0),
+ .int_i64 => std.math.order(lhs.cast(Payload.Int_i64).?.int, 0),
+ .int_big_positive => lhs.cast(Payload.IntBigPositive).?.asBigInt().orderAgainstScalar(0),
+ .int_big_negative => lhs.cast(Payload.IntBigNegative).?.asBigInt().orderAgainstScalar(0),
+
+ .float_16 => std.math.order(lhs.cast(Payload.Float_16).?.val, 0),
+ .float_32 => std.math.order(lhs.cast(Payload.Float_32).?.val, 0),
+ .float_64 => std.math.order(lhs.cast(Payload.Float_64).?.val, 0),
+ .float_128, .float => std.math.order(lhs.cast(Payload.Float_128).?.val, 0),
+ };
}
/// Asserts the value is comparable.
@@ -840,7 +908,24 @@ pub const Value = extern union {
if (lhs_is_zero) return rhs.orderAgainstZero().invert();
if (rhs_is_zero) return lhs.orderAgainstZero();
- // TODO floats
+ const lhs_float = lhs.isFloat();
+ const rhs_float = rhs.isFloat();
+ if (lhs_float and rhs_float) {
+ if (lhs_tag == rhs_tag) {
+ return switch (lhs.tag()) {
+ .float_16 => return std.math.order(lhs.cast(Payload.Float_16).?.val, rhs.cast(Payload.Float_16).?.val),
+ .float_32 => return std.math.order(lhs.cast(Payload.Float_32).?.val, rhs.cast(Payload.Float_32).?.val),
+ .float_64 => return std.math.order(lhs.cast(Payload.Float_64).?.val, rhs.cast(Payload.Float_64).?.val),
+ .float_128, .float => return std.math.order(lhs.cast(Payload.Float_128).?.val, rhs.cast(Payload.Float_128).?.val),
+ else => unreachable,
+ };
+ }
+ }
+ if (lhs_float or rhs_float) {
+ const lhs_f128 = lhs.toF128();
+ const rhs_f128 = rhs.toF128();
+ return std.math.order(lhs_f128, rhs_f128);
+ }
var lhs_bigint_space: BigIntSpace = undefined;
var rhs_bigint_space: BigIntSpace = undefined;
@@ -864,14 +949,6 @@ pub const Value = extern union {
return compare(a, .eq, b);
}
- pub fn toBool(self: Value) bool {
- return switch (self.tag()) {
- .bool_true => true,
- .bool_false, .zero => false,
- else => unreachable,
- };
- }
-
/// Asserts the value is a pointer and dereferences it.
/// Returns error.AnalysisFail if the pointer points to a Decl that failed semantic analysis.
pub fn pointerDeref(self: Value, allocator: *Allocator) error{ AnalysisFail, OutOfMemory }!Value {
@@ -928,6 +1005,11 @@ pub const Value = extern union {
.bytes,
.undef,
.repeated,
+ .float,
+ .float_16,
+ .float_32,
+ .float_64,
+ .float_128,
=> unreachable,
.the_one_possible_value => Value.initTag(.the_one_possible_value),
@@ -999,6 +1081,11 @@ pub const Value = extern union {
.elem_ptr,
.ref_val,
.decl_ref,
+ .float,
+ .float_16,
+ .float_32,
+ .float_64,
+ .float_128,
=> unreachable,
.bytes => {
@@ -1085,6 +1172,11 @@ pub const Value = extern union {
.elem_ptr,
.bytes,
.repeated,
+ .float,
+ .float_16,
+ .float_32,
+ .float_64,
+ .float_128,
=> false,
.undef => unreachable,
@@ -1092,6 +1184,21 @@ pub const Value = extern union {
};
}
+ /// Valid for all types. Asserts the value is not undefined.
+ pub fn isFloat(self: Value) bool {
+ return switch (self.tag()) {
+ .undef => unreachable,
+
+ .float,
+ .float_16,
+ .float_32,
+ .float_64,
+ .float_128,
+ => true,
+ else => false,
+ };
+ }
+
/// This type is not copyable since it may contain pointers to its inner data.
pub const Payload = struct {
tag: Tag,
@@ -1168,6 +1275,26 @@ pub const Value = extern union {
/// is stored externally.
val: Value,
};
+
+ pub const Float_16 = struct {
+ base: Payload = .{ .tag = .float_16 },
+ val: f16,
+ };
+
+ pub const Float_32 = struct {
+ base: Payload = .{ .tag = .float_32 },
+ val: f32,
+ };
+
+ pub const Float_64 = struct {
+ base: Payload = .{ .tag = .float_64 },
+ val: f64,
+ };
+
+ pub const Float_128 = struct {
+ base: Payload = .{ .tag = .float_128 },
+ val: f128,
+ };
};
/// Big enough to fit any non-BigInt value