From e77ca6af7083da6723dfeb83d3788ebf7012c64e Mon Sep 17 00:00:00 2001 From: Vexu Date: Mon, 20 Jul 2020 18:11:40 +0300 Subject: [PATCH] stage2: add float values --- src-self-hosted/value.zig | 161 ++++++++++++++++++++++++++++++++++---- 1 file changed, 144 insertions(+), 17 deletions(-) diff --git a/src-self-hosted/value.zig b/src-self-hosted/value.zig index a3e1daa383..ec69e9bc17 100644 --- a/src-self-hosted/value.zig +++ b/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