diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-01-30 17:23:14 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-02-06 19:27:54 -0700 |
| commit | 287ff4ab58f8af70383b6e334c7c862c8b8fbeec (patch) | |
| tree | 6c4e9281e86886fe58075e78dd332b74cf640e7d /src/value.zig | |
| parent | fd1284ebd07ded1c67bbaff4c14f093051e56f59 (diff) | |
| download | zig-287ff4ab58f8af70383b6e334c7c862c8b8fbeec.tar.gz zig-287ff4ab58f8af70383b6e334c7c862c8b8fbeec.zip | |
stage2: add more float arithmetic and f80 support
AstGen: Fixed bug where f80 types in source were triggering illegal
behavior.
Value: handle f80 in floating point arithmetic functions.
Value: implement floatRem and floatMod
This commit introduces dependencies on compiler-rt that are not
implemented. Those are a prerequisite to merging this branch.
Diffstat (limited to 'src/value.zig')
| -rw-r--r-- | src/value.zig | 215 |
1 files changed, 162 insertions, 53 deletions
diff --git a/src/value.zig b/src/value.zig index e444e2daf1..18c8357b6b 100644 --- a/src/value.zig +++ b/src/value.zig @@ -138,6 +138,7 @@ pub const Value = extern union { float_16, float_32, float_64, + float_80, float_128, enum_literal, /// A specific enum tag, indicated by the field index (declaration order). @@ -295,6 +296,7 @@ pub const Value = extern union { .float_16 => Payload.Float_16, .float_32 => Payload.Float_32, .float_64 => Payload.Float_64, + .float_80 => Payload.Float_80, .float_128 => Payload.Float_128, .@"error" => Payload.Error, .inferred_alloc => Payload.InferredAlloc, @@ -546,6 +548,7 @@ pub const Value = extern union { .float_16 => return self.copyPayloadShallow(arena, Payload.Float_16), .float_32 => return self.copyPayloadShallow(arena, Payload.Float_32), .float_64 => return self.copyPayloadShallow(arena, Payload.Float_64), + .float_80 => return self.copyPayloadShallow(arena, Payload.Float_80), .float_128 => return self.copyPayloadShallow(arena, Payload.Float_128), .enum_literal => { const payload = self.castTag(.enum_literal).?; @@ -733,6 +736,7 @@ pub const Value = extern union { .float_16 => return out_stream.print("{}", .{val.castTag(.float_16).?.data}), .float_32 => return out_stream.print("{}", .{val.castTag(.float_32).?.data}), .float_64 => return out_stream.print("{}", .{val.castTag(.float_64).?.data}), + .float_80 => return out_stream.print("{}", .{val.castTag(.float_80).?.data}), .float_128 => return out_stream.print("{}", .{val.castTag(.float_128).?.data}), .@"error" => return out_stream.print("error.{s}", .{val.castTag(.@"error").?.data.name}), // TODO to print this it should be error{ Set, Items }!T(val), but we need the type for that @@ -1083,6 +1087,7 @@ pub const Value = extern union { 16 => return Value.Tag.float_16.create(arena, floatReadFromMemory(f16, target, buffer)), 32 => return Value.Tag.float_32.create(arena, floatReadFromMemory(f32, target, buffer)), 64 => return Value.Tag.float_64.create(arena, floatReadFromMemory(f64, target, buffer)), + 80 => return Value.Tag.float_80.create(arena, floatReadFromMemory(f80, target, buffer)), 128 => return Value.Tag.float_128.create(arena, floatReadFromMemory(f128, target, buffer)), else => unreachable, }, @@ -1100,6 +1105,12 @@ pub const Value = extern union { } fn floatReadFromMemory(comptime F: type, target: Target, buffer: []const u8) F { + if (F == f80) { + // TODO: use std.math.F80Repr + const big_int = std.mem.readInt(u128, buffer[0..16], target.cpu.arch.endian()); + const int = @truncate(u80, big_int); + return @bitCast(F, int); + } const Int = @Type(.{ .Int = .{ .signedness = .unsigned, .bits = @typeInfo(F).Float.bits, @@ -1114,6 +1125,7 @@ pub const Value = extern union { .float_16 => @floatCast(T, val.castTag(.float_16).?.data), .float_32 => @floatCast(T, val.castTag(.float_32).?.data), .float_64 => @floatCast(T, val.castTag(.float_64).?.data), + .float_80 => @floatCast(T, val.castTag(.float_80).?.data), .float_128 => @floatCast(T, val.castTag(.float_128).?.data), .zero => 0, @@ -1367,14 +1379,13 @@ pub const Value = extern union { /// Converts an integer or a float to a float. May result in a loss of information. /// Caller can find out by equality checking the result against the operand. - pub fn floatCast(self: Value, arena: Allocator, dest_ty: Type) !Value { - switch (dest_ty.tag()) { - .f16 => return Value.Tag.float_16.create(arena, self.toFloat(f16)), - .f32 => return Value.Tag.float_32.create(arena, self.toFloat(f32)), - .f64 => return Value.Tag.float_64.create(arena, self.toFloat(f64)), - .f128, .comptime_float, .c_longdouble => { - return Value.Tag.float_128.create(arena, self.toFloat(f128)); - }, + pub fn floatCast(self: Value, arena: Allocator, dest_ty: Type, target: Target) !Value { + switch (dest_ty.floatBits(target)) { + 16 => return Value.Tag.float_16.create(arena, self.toFloat(f16)), + 32 => return Value.Tag.float_32.create(arena, self.toFloat(f32)), + 64 => return Value.Tag.float_64.create(arena, self.toFloat(f64)), + 80 => return Value.Tag.float_80.create(arena, self.toFloat(f80)), + 128 => return Value.Tag.float_128.create(arena, self.toFloat(f128)), else => unreachable, } } @@ -1389,8 +1400,8 @@ pub const Value = extern union { .float_16 => @rem(self.castTag(.float_16).?.data, 1) != 0, .float_32 => @rem(self.castTag(.float_32).?.data, 1) != 0, .float_64 => @rem(self.castTag(.float_64).?.data, 1) != 0, - // .float_128 => @rem(self.castTag(.float_128).?.data, 1) != 0, - .float_128 => @panic("TODO lld: error: undefined symbol: fmodl"), + .float_80 => @rem(self.castTag(.float_80).?.data, 1) != 0, + .float_128 => @rem(self.castTag(.float_128).?.data, 1) != 0, else => unreachable, }; @@ -1408,6 +1419,7 @@ pub const Value = extern union { .float_16 => self.castTag(.float_16).?.data == 0, .float_32 => self.castTag(.float_32).?.data == 0, .float_64 => self.castTag(.float_64).?.data == 0, + .float_80 => self.castTag(.float_80).?.data == 0, .float_128 => self.castTag(.float_128).?.data == 0, .int_big_positive => self.castTag(.int_big_positive).?.asBigInt().eqZero(), @@ -1440,6 +1452,7 @@ pub const Value = extern union { .float_16 => std.math.order(lhs.castTag(.float_16).?.data, 0), .float_32 => std.math.order(lhs.castTag(.float_32).?.data, 0), .float_64 => std.math.order(lhs.castTag(.float_64).?.data, 0), + .float_80 => std.math.order(lhs.castTag(.float_80).?.data, 0), .float_128 => std.math.order(lhs.castTag(.float_128).?.data, 0), else => unreachable, @@ -1471,6 +1484,7 @@ pub const Value = extern union { .float_16 => return std.math.order(lhs.castTag(.float_16).?.data, rhs.castTag(.float_16).?.data), .float_32 => return std.math.order(lhs.castTag(.float_32).?.data, rhs.castTag(.float_32).?.data), .float_64 => return std.math.order(lhs.castTag(.float_64).?.data, rhs.castTag(.float_64).?.data), + .float_80 => return std.math.order(lhs.castTag(.float_80).?.data, rhs.castTag(.float_80).?.data), .float_128 => return std.math.order(lhs.castTag(.float_128).?.data, rhs.castTag(.float_128).?.data), else => unreachable, }; @@ -2139,6 +2153,7 @@ pub const Value = extern union { .float_16, .float_32, .float_64, + .float_80, .float_128, => true, else => false, @@ -2174,6 +2189,7 @@ pub const Value = extern union { 16 => return Value.Tag.float_16.create(arena, @intToFloat(f16, x)), 32 => return Value.Tag.float_32.create(arena, @intToFloat(f32, x)), 64 => return Value.Tag.float_64.create(arena, @intToFloat(f64, x)), + 80 => return Value.Tag.float_80.create(arena, @intToFloat(f80, x)), 128 => return Value.Tag.float_128.create(arena, @intToFloat(f128, x)), else => unreachable, } @@ -2184,6 +2200,7 @@ pub const Value = extern union { 16 => return Value.Tag.float_16.create(arena, @floatCast(f16, float)), 32 => return Value.Tag.float_32.create(arena, @floatCast(f32, float)), 64 => return Value.Tag.float_64.create(arena, @floatCast(f64, float)), + 80 => return Value.Tag.float_80.create(arena, @floatCast(f80, float)), 128 => return Value.Tag.float_128.create(arena, float), else => unreachable, } @@ -2281,7 +2298,7 @@ pub const Value = extern union { } if (ty.isAnyFloat()) { - return floatAdd(lhs, rhs, ty, arena); + return floatAdd(lhs, rhs, ty, arena, target); } const overflow_result = try intAddWithOverflow(lhs, rhs, ty, arena, target); @@ -2371,7 +2388,7 @@ pub const Value = extern union { } if (ty.isAnyFloat()) { - return floatSub(lhs, rhs, ty, arena); + return floatSub(lhs, rhs, ty, arena, target); } const overflow_result = try intSubWithOverflow(lhs, rhs, ty, arena, target); @@ -2454,7 +2471,7 @@ pub const Value = extern union { } if (ty.isAnyFloat()) { - return floatMul(lhs, rhs, ty, arena); + return floatMul(lhs, rhs, ty, arena, target); } const overflow_result = try intMulWithOverflow(lhs, rhs, ty, arena, target); @@ -2753,23 +2770,72 @@ pub const Value = extern union { .float_16 => std.math.isNan(val.castTag(.float_16).?.data), .float_32 => std.math.isNan(val.castTag(.float_32).?.data), .float_64 => std.math.isNan(val.castTag(.float_64).?.data), + .float_80 => std.math.isNan(val.castTag(.float_80).?.data), .float_128 => std.math.isNan(val.castTag(.float_128).?.data), else => false, }; } - pub fn floatRem(lhs: Value, rhs: Value, allocator: Allocator) !Value { - _ = lhs; - _ = rhs; - _ = allocator; - @panic("TODO implement Value.floatRem"); + pub fn floatRem(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value { + switch (float_type.floatBits(target)) { + 16 => { + const lhs_val = lhs.toFloat(f16); + const rhs_val = rhs.toFloat(f16); + return Value.Tag.float_16.create(arena, @rem(lhs_val, rhs_val)); + }, + 32 => { + const lhs_val = lhs.toFloat(f32); + const rhs_val = rhs.toFloat(f32); + return Value.Tag.float_32.create(arena, @rem(lhs_val, rhs_val)); + }, + 64 => { + const lhs_val = lhs.toFloat(f64); + const rhs_val = rhs.toFloat(f64); + return Value.Tag.float_64.create(arena, @rem(lhs_val, rhs_val)); + }, + 80 => { + const lhs_val = lhs.toFloat(f80); + const rhs_val = rhs.toFloat(f80); + return Value.Tag.float_80.create(arena, @rem(lhs_val, rhs_val)); + }, + 128 => { + const lhs_val = lhs.toFloat(f128); + const rhs_val = rhs.toFloat(f128); + return Value.Tag.float_128.create(arena, @rem(lhs_val, rhs_val)); + }, + else => unreachable, + } } - pub fn floatMod(lhs: Value, rhs: Value, allocator: Allocator) !Value { - _ = lhs; - _ = rhs; - _ = allocator; - @panic("TODO implement Value.floatMod"); + pub fn floatMod(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value { + switch (float_type.floatBits(target)) { + 16 => { + const lhs_val = lhs.toFloat(f16); + const rhs_val = rhs.toFloat(f16); + return Value.Tag.float_16.create(arena, @mod(lhs_val, rhs_val)); + }, + 32 => { + const lhs_val = lhs.toFloat(f32); + const rhs_val = rhs.toFloat(f32); + return Value.Tag.float_32.create(arena, @mod(lhs_val, rhs_val)); + }, + 64 => { + const lhs_val = lhs.toFloat(f64); + const rhs_val = rhs.toFloat(f64); + return Value.Tag.float_64.create(arena, @mod(lhs_val, rhs_val)); + }, + 80 => { + const lhs_val = lhs.toFloat(f80); + const rhs_val = rhs.toFloat(f80); + return Value.Tag.float_80.create(arena, @mod(lhs_val, rhs_val)); + }, + 128 => { + const lhs_val = lhs.toFloat(f128); + const rhs_val = rhs.toFloat(f128); + return Value.Tag.float_128.create(arena, @mod(lhs_val, rhs_val)); + }, + else => unreachable, + } } pub fn intMul(lhs: Value, rhs: Value, allocator: Allocator) !Value { @@ -2929,24 +2995,30 @@ pub const Value = extern union { rhs: Value, float_type: Type, arena: Allocator, + target: Target, ) !Value { - switch (float_type.tag()) { - .f16 => { + switch (float_type.floatBits(target)) { + 16 => { const lhs_val = lhs.toFloat(f16); const rhs_val = rhs.toFloat(f16); return Value.Tag.float_16.create(arena, lhs_val + rhs_val); }, - .f32 => { + 32 => { const lhs_val = lhs.toFloat(f32); const rhs_val = rhs.toFloat(f32); return Value.Tag.float_32.create(arena, lhs_val + rhs_val); }, - .f64 => { + 64 => { const lhs_val = lhs.toFloat(f64); const rhs_val = rhs.toFloat(f64); return Value.Tag.float_64.create(arena, lhs_val + rhs_val); }, - .f128, .comptime_float, .c_longdouble => { + 80 => { + const lhs_val = lhs.toFloat(f80); + const rhs_val = rhs.toFloat(f80); + return Value.Tag.float_80.create(arena, lhs_val + rhs_val); + }, + 128 => { const lhs_val = lhs.toFloat(f128); const rhs_val = rhs.toFloat(f128); return Value.Tag.float_128.create(arena, lhs_val + rhs_val); @@ -2960,24 +3032,30 @@ pub const Value = extern union { rhs: Value, float_type: Type, arena: Allocator, + target: Target, ) !Value { - switch (float_type.tag()) { - .f16 => { + switch (float_type.floatBits(target)) { + 16 => { const lhs_val = lhs.toFloat(f16); const rhs_val = rhs.toFloat(f16); return Value.Tag.float_16.create(arena, lhs_val - rhs_val); }, - .f32 => { + 32 => { const lhs_val = lhs.toFloat(f32); const rhs_val = rhs.toFloat(f32); return Value.Tag.float_32.create(arena, lhs_val - rhs_val); }, - .f64 => { + 64 => { const lhs_val = lhs.toFloat(f64); const rhs_val = rhs.toFloat(f64); return Value.Tag.float_64.create(arena, lhs_val - rhs_val); }, - .f128, .comptime_float, .c_longdouble => { + 80 => { + const lhs_val = lhs.toFloat(f80); + const rhs_val = rhs.toFloat(f80); + return Value.Tag.float_80.create(arena, lhs_val - rhs_val); + }, + 128 => { const lhs_val = lhs.toFloat(f128); const rhs_val = rhs.toFloat(f128); return Value.Tag.float_128.create(arena, lhs_val - rhs_val); @@ -2991,24 +3069,30 @@ pub const Value = extern union { rhs: Value, float_type: Type, arena: Allocator, + target: Target, ) !Value { - switch (float_type.tag()) { - .f16 => { + switch (float_type.floatBits(target)) { + 16 => { const lhs_val = lhs.toFloat(f16); const rhs_val = rhs.toFloat(f16); return Value.Tag.float_16.create(arena, lhs_val / rhs_val); }, - .f32 => { + 32 => { const lhs_val = lhs.toFloat(f32); const rhs_val = rhs.toFloat(f32); return Value.Tag.float_32.create(arena, lhs_val / rhs_val); }, - .f64 => { + 64 => { const lhs_val = lhs.toFloat(f64); const rhs_val = rhs.toFloat(f64); return Value.Tag.float_64.create(arena, lhs_val / rhs_val); }, - .f128, .comptime_float, .c_longdouble => { + 80 => { + const lhs_val = lhs.toFloat(f80); + const rhs_val = rhs.toFloat(f80); + return Value.Tag.float_80.create(arena, lhs_val / rhs_val); + }, + 128 => { const lhs_val = lhs.toFloat(f128); const rhs_val = rhs.toFloat(f128); return Value.Tag.float_128.create(arena, lhs_val / rhs_val); @@ -3022,24 +3106,30 @@ pub const Value = extern union { rhs: Value, float_type: Type, arena: Allocator, + target: Target, ) !Value { - switch (float_type.tag()) { - .f16 => { + switch (float_type.floatBits(target)) { + 16 => { const lhs_val = lhs.toFloat(f16); const rhs_val = rhs.toFloat(f16); return Value.Tag.float_16.create(arena, @divFloor(lhs_val, rhs_val)); }, - .f32 => { + 32 => { const lhs_val = lhs.toFloat(f32); const rhs_val = rhs.toFloat(f32); return Value.Tag.float_32.create(arena, @divFloor(lhs_val, rhs_val)); }, - .f64 => { + 64 => { const lhs_val = lhs.toFloat(f64); const rhs_val = rhs.toFloat(f64); return Value.Tag.float_64.create(arena, @divFloor(lhs_val, rhs_val)); }, - .f128, .comptime_float, .c_longdouble => { + 80 => { + const lhs_val = lhs.toFloat(f80); + const rhs_val = rhs.toFloat(f80); + return Value.Tag.float_80.create(arena, @divFloor(lhs_val, rhs_val)); + }, + 128 => { const lhs_val = lhs.toFloat(f128); const rhs_val = rhs.toFloat(f128); return Value.Tag.float_128.create(arena, @divFloor(lhs_val, rhs_val)); @@ -3053,24 +3143,30 @@ pub const Value = extern union { rhs: Value, float_type: Type, arena: Allocator, + target: Target, ) !Value { - switch (float_type.tag()) { - .f16 => { + switch (float_type.floatBits(target)) { + 16 => { const lhs_val = lhs.toFloat(f16); const rhs_val = rhs.toFloat(f16); return Value.Tag.float_16.create(arena, @divTrunc(lhs_val, rhs_val)); }, - .f32 => { + 32 => { const lhs_val = lhs.toFloat(f32); const rhs_val = rhs.toFloat(f32); return Value.Tag.float_32.create(arena, @divTrunc(lhs_val, rhs_val)); }, - .f64 => { + 64 => { const lhs_val = lhs.toFloat(f64); const rhs_val = rhs.toFloat(f64); return Value.Tag.float_64.create(arena, @divTrunc(lhs_val, rhs_val)); }, - .f128, .comptime_float, .c_longdouble => { + 80 => { + const lhs_val = lhs.toFloat(f80); + const rhs_val = rhs.toFloat(f80); + return Value.Tag.float_80.create(arena, @divTrunc(lhs_val, rhs_val)); + }, + 128 => { const lhs_val = lhs.toFloat(f128); const rhs_val = rhs.toFloat(f128); return Value.Tag.float_128.create(arena, @divTrunc(lhs_val, rhs_val)); @@ -3084,24 +3180,30 @@ pub const Value = extern union { rhs: Value, float_type: Type, arena: Allocator, + target: Target, ) !Value { - switch (float_type.tag()) { - .f16 => { + switch (float_type.floatBits(target)) { + 16 => { const lhs_val = lhs.toFloat(f16); const rhs_val = rhs.toFloat(f16); return Value.Tag.float_16.create(arena, lhs_val * rhs_val); }, - .f32 => { + 32 => { const lhs_val = lhs.toFloat(f32); const rhs_val = rhs.toFloat(f32); return Value.Tag.float_32.create(arena, lhs_val * rhs_val); }, - .f64 => { + 64 => { const lhs_val = lhs.toFloat(f64); const rhs_val = rhs.toFloat(f64); return Value.Tag.float_64.create(arena, lhs_val * rhs_val); }, - .f128, .comptime_float, .c_longdouble => { + 80 => { + const lhs_val = lhs.toFloat(f80); + const rhs_val = rhs.toFloat(f80); + return Value.Tag.float_80.create(arena, lhs_val * rhs_val); + }, + 128 => { const lhs_val = lhs.toFloat(f128); const rhs_val = rhs.toFloat(f128); return Value.Tag.float_128.create(arena, lhs_val * rhs_val); @@ -3250,6 +3352,13 @@ pub const Value = extern union { data: f64, }; + pub const Float_80 = struct { + pub const base_tag = Tag.float_80; + + base: Payload = .{ .tag = base_tag }, + data: f80, + }; + pub const Float_128 = struct { pub const base_tag = Tag.float_128; |
