authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-30 17:23:14-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-06 19:27:54-07:00
log287ff4ab58f8af70383b6e334c7c862c8b8fbeec
tree6c4e9281e86886fe58075e78dd332b74cf640e7d
parentfd1284ebd07ded1c67bbaff4c14f093051e56f59

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.

4 files changed, 178 insertions(+), 69 deletions(-)

src/AstGen.zig+4-2
...@@ -8409,10 +8409,11 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In...@@ -8409,10 +8409,11 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
8409 .c_ushort_type,8409 .c_ushort_type,
8410 .comptime_float_type,8410 .comptime_float_type,
8411 .comptime_int_type,8411 .comptime_int_type,
8412 .f128_type,
8413 .f16_type,8412 .f16_type,
8414 .f32_type,8413 .f32_type,
8415 .f64_type,8414 .f64_type,
8415 .f80_type,
8416 .f128_type,
8416 .i16_type,8417 .i16_type,
8417 .i32_type,8418 .i32_type,
8418 .i64_type,8419 .i64_type,
...@@ -8648,10 +8649,11 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {...@@ -8648,10 +8649,11 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
8648 .c_ulong_type,8649 .c_ulong_type,
8649 .c_ulonglong_type,8650 .c_ulonglong_type,
8650 .c_ushort_type,8651 .c_ushort_type,
8651 .f128_type,
8652 .f16_type,8652 .f16_type,
8653 .f32_type,8653 .f32_type,
8654 .f64_type,8654 .f64_type,
8655 .f80_type,
8656 .f128_type,
8655 .i16_type,8657 .i16_type,
8656 .i32_type,8658 .i32_type,
8657 .i64_type,8659 .i64_type,
src/Sema.zig+12-12
...@@ -8187,7 +8187,7 @@ fn analyzeArithmetic(...@@ -8187,7 +8187,7 @@ fn analyzeArithmetic(
8187 } else {8187 } else {
8188 return sema.addConstant(8188 return sema.addConstant(
8189 scalar_type,8189 scalar_type,
8190 try lhs_val.floatAdd(rhs_val, scalar_type, sema.arena),8190 try lhs_val.floatAdd(rhs_val, scalar_type, sema.arena, target),
8191 );8191 );
8192 }8192 }
8193 } else break :rs .{ .src = rhs_src, .air_tag = .add };8193 } else break :rs .{ .src = rhs_src, .air_tag = .add };
...@@ -8280,7 +8280,7 @@ fn analyzeArithmetic(...@@ -8280,7 +8280,7 @@ fn analyzeArithmetic(
8280 } else {8280 } else {
8281 return sema.addConstant(8281 return sema.addConstant(
8282 scalar_type,8282 scalar_type,
8283 try lhs_val.floatSub(rhs_val, scalar_type, sema.arena),8283 try lhs_val.floatSub(rhs_val, scalar_type, sema.arena, target),
8284 );8284 );
8285 }8285 }
8286 } else break :rs .{ .src = rhs_src, .air_tag = .sub };8286 } else break :rs .{ .src = rhs_src, .air_tag = .sub };
...@@ -8396,7 +8396,7 @@ fn analyzeArithmetic(...@@ -8396,7 +8396,7 @@ fn analyzeArithmetic(
8396 } else {8396 } else {
8397 return sema.addConstant(8397 return sema.addConstant(
8398 scalar_type,8398 scalar_type,
8399 try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena),8399 try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena, target),
8400 );8400 );
8401 }8401 }
8402 } else {8402 } else {
...@@ -8471,7 +8471,7 @@ fn analyzeArithmetic(...@@ -8471,7 +8471,7 @@ fn analyzeArithmetic(
8471 } else {8471 } else {
8472 return sema.addConstant(8472 return sema.addConstant(
8473 scalar_type,8473 scalar_type,
8474 try lhs_val.floatDivTrunc(rhs_val, scalar_type, sema.arena),8474 try lhs_val.floatDivTrunc(rhs_val, scalar_type, sema.arena, target),
8475 );8475 );
8476 }8476 }
8477 } else break :rs .{ .src = rhs_src, .air_tag = .div_trunc };8477 } else break :rs .{ .src = rhs_src, .air_tag = .div_trunc };
...@@ -8534,7 +8534,7 @@ fn analyzeArithmetic(...@@ -8534,7 +8534,7 @@ fn analyzeArithmetic(
8534 } else {8534 } else {
8535 return sema.addConstant(8535 return sema.addConstant(
8536 scalar_type,8536 scalar_type,
8537 try lhs_val.floatDivFloor(rhs_val, scalar_type, sema.arena),8537 try lhs_val.floatDivFloor(rhs_val, scalar_type, sema.arena, target),
8538 );8538 );
8539 }8539 }
8540 } else break :rs .{ .src = rhs_src, .air_tag = .div_floor };8540 } else break :rs .{ .src = rhs_src, .air_tag = .div_floor };
...@@ -8586,7 +8586,7 @@ fn analyzeArithmetic(...@@ -8586,7 +8586,7 @@ fn analyzeArithmetic(
8586 // TODO: emit compile error if there is a remainder8586 // TODO: emit compile error if there is a remainder
8587 return sema.addConstant(8587 return sema.addConstant(
8588 scalar_type,8588 scalar_type,
8589 try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena),8589 try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena, target),
8590 );8590 );
8591 }8591 }
8592 } else break :rs .{ .src = rhs_src, .air_tag = .div_exact };8592 } else break :rs .{ .src = rhs_src, .air_tag = .div_exact };
...@@ -8641,7 +8641,7 @@ fn analyzeArithmetic(...@@ -8641,7 +8641,7 @@ fn analyzeArithmetic(
8641 } else {8641 } else {
8642 return sema.addConstant(8642 return sema.addConstant(
8643 scalar_type,8643 scalar_type,
8644 try lhs_val.floatMul(rhs_val, scalar_type, sema.arena),8644 try lhs_val.floatMul(rhs_val, scalar_type, sema.arena, target),
8645 );8645 );
8646 }8646 }
8647 } else break :rs .{ .src = lhs_src, .air_tag = .mul };8647 } else break :rs .{ .src = lhs_src, .air_tag = .mul };
...@@ -8797,7 +8797,7 @@ fn analyzeArithmetic(...@@ -8797,7 +8797,7 @@ fn analyzeArithmetic(
8797 }8797 }
8798 return sema.addConstant(8798 return sema.addConstant(
8799 scalar_type,8799 scalar_type,
8800 try lhs_val.floatRem(rhs_val, sema.arena),8800 try lhs_val.floatRem(rhs_val, scalar_type, sema.arena, target),
8801 );8801 );
8802 } else {8802 } else {
8803 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);8803 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
...@@ -8858,7 +8858,7 @@ fn analyzeArithmetic(...@@ -8858,7 +8858,7 @@ fn analyzeArithmetic(
8858 if (maybe_rhs_val) |rhs_val| {8858 if (maybe_rhs_val) |rhs_val| {
8859 return sema.addConstant(8859 return sema.addConstant(
8860 scalar_type,8860 scalar_type,
8861 try lhs_val.floatRem(rhs_val, sema.arena),8861 try lhs_val.floatRem(rhs_val, scalar_type, sema.arena, target),
8862 );8862 );
8863 } else break :rs .{ .src = rhs_src, .air_tag = .rem };8863 } else break :rs .{ .src = rhs_src, .air_tag = .rem };
8864 } else break :rs .{ .src = lhs_src, .air_tag = .rem };8864 } else break :rs .{ .src = lhs_src, .air_tag = .rem };
...@@ -8915,7 +8915,7 @@ fn analyzeArithmetic(...@@ -8915,7 +8915,7 @@ fn analyzeArithmetic(
8915 if (maybe_rhs_val) |rhs_val| {8915 if (maybe_rhs_val) |rhs_val| {
8916 return sema.addConstant(8916 return sema.addConstant(
8917 scalar_type,8917 scalar_type,
8918 try lhs_val.floatMod(rhs_val, sema.arena),8918 try lhs_val.floatMod(rhs_val, scalar_type, sema.arena, target),
8919 );8919 );
8920 } else break :rs .{ .src = rhs_src, .air_tag = .mod };8920 } else break :rs .{ .src = rhs_src, .air_tag = .mod };
8921 } else break :rs .{ .src = lhs_src, .air_tag = .mod };8921 } else break :rs .{ .src = lhs_src, .air_tag = .mod };
...@@ -14195,12 +14195,12 @@ fn coerce(...@@ -14195,12 +14195,12 @@ fn coerce(
14195 .Float, .ComptimeFloat => switch (inst_ty.zigTypeTag()) {14195 .Float, .ComptimeFloat => switch (inst_ty.zigTypeTag()) {
14196 .ComptimeFloat => {14196 .ComptimeFloat => {
14197 const val = try sema.resolveConstValue(block, inst_src, inst);14197 const val = try sema.resolveConstValue(block, inst_src, inst);
14198 const result_val = try val.floatCast(sema.arena, dest_ty);14198 const result_val = try val.floatCast(sema.arena, dest_ty, target);
14199 return try sema.addConstant(dest_ty, result_val);14199 return try sema.addConstant(dest_ty, result_val);
14200 },14200 },
14201 .Float => {14201 .Float => {
14202 if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| {14202 if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| {
14203 const result_val = try val.floatCast(sema.arena, dest_ty);14203 const result_val = try val.floatCast(sema.arena, dest_ty, target);
14204 if (!val.eql(result_val, dest_ty)) {14204 if (!val.eql(result_val, dest_ty)) {
14205 return sema.fail(14205 return sema.fail(
14206 block,14206 block,
src/value.zig+162-53
...@@ -138,6 +138,7 @@ pub const Value = extern union {...@@ -138,6 +138,7 @@ pub const Value = extern union {
138 float_16,138 float_16,
139 float_32,139 float_32,
140 float_64,140 float_64,
141 float_80,
141 float_128,142 float_128,
142 enum_literal,143 enum_literal,
143 /// A specific enum tag, indicated by the field index (declaration order).144 /// A specific enum tag, indicated by the field index (declaration order).
...@@ -295,6 +296,7 @@ pub const Value = extern union {...@@ -295,6 +296,7 @@ pub const Value = extern union {
295 .float_16 => Payload.Float_16,296 .float_16 => Payload.Float_16,
296 .float_32 => Payload.Float_32,297 .float_32 => Payload.Float_32,
297 .float_64 => Payload.Float_64,298 .float_64 => Payload.Float_64,
299 .float_80 => Payload.Float_80,
298 .float_128 => Payload.Float_128,300 .float_128 => Payload.Float_128,
299 .@"error" => Payload.Error,301 .@"error" => Payload.Error,
300 .inferred_alloc => Payload.InferredAlloc,302 .inferred_alloc => Payload.InferredAlloc,
...@@ -546,6 +548,7 @@ pub const Value = extern union {...@@ -546,6 +548,7 @@ pub const Value = extern union {
546 .float_16 => return self.copyPayloadShallow(arena, Payload.Float_16),548 .float_16 => return self.copyPayloadShallow(arena, Payload.Float_16),
547 .float_32 => return self.copyPayloadShallow(arena, Payload.Float_32),549 .float_32 => return self.copyPayloadShallow(arena, Payload.Float_32),
548 .float_64 => return self.copyPayloadShallow(arena, Payload.Float_64),550 .float_64 => return self.copyPayloadShallow(arena, Payload.Float_64),
551 .float_80 => return self.copyPayloadShallow(arena, Payload.Float_80),
549 .float_128 => return self.copyPayloadShallow(arena, Payload.Float_128),552 .float_128 => return self.copyPayloadShallow(arena, Payload.Float_128),
550 .enum_literal => {553 .enum_literal => {
551 const payload = self.castTag(.enum_literal).?;554 const payload = self.castTag(.enum_literal).?;
...@@ -733,6 +736,7 @@ pub const Value = extern union {...@@ -733,6 +736,7 @@ pub const Value = extern union {
733 .float_16 => return out_stream.print("{}", .{val.castTag(.float_16).?.data}),736 .float_16 => return out_stream.print("{}", .{val.castTag(.float_16).?.data}),
734 .float_32 => return out_stream.print("{}", .{val.castTag(.float_32).?.data}),737 .float_32 => return out_stream.print("{}", .{val.castTag(.float_32).?.data}),
735 .float_64 => return out_stream.print("{}", .{val.castTag(.float_64).?.data}),738 .float_64 => return out_stream.print("{}", .{val.castTag(.float_64).?.data}),
739 .float_80 => return out_stream.print("{}", .{val.castTag(.float_80).?.data}),
736 .float_128 => return out_stream.print("{}", .{val.castTag(.float_128).?.data}),740 .float_128 => return out_stream.print("{}", .{val.castTag(.float_128).?.data}),
737 .@"error" => return out_stream.print("error.{s}", .{val.castTag(.@"error").?.data.name}),741 .@"error" => return out_stream.print("error.{s}", .{val.castTag(.@"error").?.data.name}),
738 // TODO to print this it should be error{ Set, Items }!T(val), but we need the type for that742 // 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 {...@@ -1083,6 +1087,7 @@ pub const Value = extern union {
1083 16 => return Value.Tag.float_16.create(arena, floatReadFromMemory(f16, target, buffer)),1087 16 => return Value.Tag.float_16.create(arena, floatReadFromMemory(f16, target, buffer)),
1084 32 => return Value.Tag.float_32.create(arena, floatReadFromMemory(f32, target, buffer)),1088 32 => return Value.Tag.float_32.create(arena, floatReadFromMemory(f32, target, buffer)),
1085 64 => return Value.Tag.float_64.create(arena, floatReadFromMemory(f64, target, buffer)),1089 64 => return Value.Tag.float_64.create(arena, floatReadFromMemory(f64, target, buffer)),
1090 80 => return Value.Tag.float_80.create(arena, floatReadFromMemory(f80, target, buffer)),
1086 128 => return Value.Tag.float_128.create(arena, floatReadFromMemory(f128, target, buffer)),1091 128 => return Value.Tag.float_128.create(arena, floatReadFromMemory(f128, target, buffer)),
1087 else => unreachable,1092 else => unreachable,
1088 },1093 },
...@@ -1100,6 +1105,12 @@ pub const Value = extern union {...@@ -1100,6 +1105,12 @@ pub const Value = extern union {
1100 }1105 }
11011106
1102 fn floatReadFromMemory(comptime F: type, target: Target, buffer: []const u8) F {1107 fn floatReadFromMemory(comptime F: type, target: Target, buffer: []const u8) F {
1108 if (F == f80) {
1109 // TODO: use std.math.F80Repr
1110 const big_int = std.mem.readInt(u128, buffer[0..16], target.cpu.arch.endian());
1111 const int = @truncate(u80, big_int);
1112 return @bitCast(F, int);
1113 }
1103 const Int = @Type(.{ .Int = .{1114 const Int = @Type(.{ .Int = .{
1104 .signedness = .unsigned,1115 .signedness = .unsigned,
1105 .bits = @typeInfo(F).Float.bits,1116 .bits = @typeInfo(F).Float.bits,
...@@ -1114,6 +1125,7 @@ pub const Value = extern union {...@@ -1114,6 +1125,7 @@ pub const Value = extern union {
1114 .float_16 => @floatCast(T, val.castTag(.float_16).?.data),1125 .float_16 => @floatCast(T, val.castTag(.float_16).?.data),
1115 .float_32 => @floatCast(T, val.castTag(.float_32).?.data),1126 .float_32 => @floatCast(T, val.castTag(.float_32).?.data),
1116 .float_64 => @floatCast(T, val.castTag(.float_64).?.data),1127 .float_64 => @floatCast(T, val.castTag(.float_64).?.data),
1128 .float_80 => @floatCast(T, val.castTag(.float_80).?.data),
1117 .float_128 => @floatCast(T, val.castTag(.float_128).?.data),1129 .float_128 => @floatCast(T, val.castTag(.float_128).?.data),
11181130
1119 .zero => 0,1131 .zero => 0,
...@@ -1367,14 +1379,13 @@ pub const Value = extern union {...@@ -1367,14 +1379,13 @@ pub const Value = extern union {
13671379
1368 /// Converts an integer or a float to a float. May result in a loss of information.1380 /// Converts an integer or a float to a float. May result in a loss of information.
1369 /// Caller can find out by equality checking the result against the operand.1381 /// Caller can find out by equality checking the result against the operand.
1370 pub fn floatCast(self: Value, arena: Allocator, dest_ty: Type) !Value {1382 pub fn floatCast(self: Value, arena: Allocator, dest_ty: Type, target: Target) !Value {
1371 switch (dest_ty.tag()) {1383 switch (dest_ty.floatBits(target)) {
1372 .f16 => return Value.Tag.float_16.create(arena, self.toFloat(f16)),1384 16 => return Value.Tag.float_16.create(arena, self.toFloat(f16)),
1373 .f32 => return Value.Tag.float_32.create(arena, self.toFloat(f32)),1385 32 => return Value.Tag.float_32.create(arena, self.toFloat(f32)),
1374 .f64 => return Value.Tag.float_64.create(arena, self.toFloat(f64)),1386 64 => return Value.Tag.float_64.create(arena, self.toFloat(f64)),
1375 .f128, .comptime_float, .c_longdouble => {1387 80 => return Value.Tag.float_80.create(arena, self.toFloat(f80)),
1376 return Value.Tag.float_128.create(arena, self.toFloat(f128));1388 128 => return Value.Tag.float_128.create(arena, self.toFloat(f128)),
1377 },
1378 else => unreachable,1389 else => unreachable,
1379 }1390 }
1380 }1391 }
...@@ -1389,8 +1400,8 @@ pub const Value = extern union {...@@ -1389,8 +1400,8 @@ pub const Value = extern union {
1389 .float_16 => @rem(self.castTag(.float_16).?.data, 1) != 0,1400 .float_16 => @rem(self.castTag(.float_16).?.data, 1) != 0,
1390 .float_32 => @rem(self.castTag(.float_32).?.data, 1) != 0,1401 .float_32 => @rem(self.castTag(.float_32).?.data, 1) != 0,
1391 .float_64 => @rem(self.castTag(.float_64).?.data, 1) != 0,1402 .float_64 => @rem(self.castTag(.float_64).?.data, 1) != 0,
1392 // .float_128 => @rem(self.castTag(.float_128).?.data, 1) != 0,1403 .float_80 => @rem(self.castTag(.float_80).?.data, 1) != 0,
1393 .float_128 => @panic("TODO lld: error: undefined symbol: fmodl"),1404 .float_128 => @rem(self.castTag(.float_128).?.data, 1) != 0,
13941405
1395 else => unreachable,1406 else => unreachable,
1396 };1407 };
...@@ -1408,6 +1419,7 @@ pub const Value = extern union {...@@ -1408,6 +1419,7 @@ pub const Value = extern union {
1408 .float_16 => self.castTag(.float_16).?.data == 0,1419 .float_16 => self.castTag(.float_16).?.data == 0,
1409 .float_32 => self.castTag(.float_32).?.data == 0,1420 .float_32 => self.castTag(.float_32).?.data == 0,
1410 .float_64 => self.castTag(.float_64).?.data == 0,1421 .float_64 => self.castTag(.float_64).?.data == 0,
1422 .float_80 => self.castTag(.float_80).?.data == 0,
1411 .float_128 => self.castTag(.float_128).?.data == 0,1423 .float_128 => self.castTag(.float_128).?.data == 0,
14121424
1413 .int_big_positive => self.castTag(.int_big_positive).?.asBigInt().eqZero(),1425 .int_big_positive => self.castTag(.int_big_positive).?.asBigInt().eqZero(),
...@@ -1440,6 +1452,7 @@ pub const Value = extern union {...@@ -1440,6 +1452,7 @@ pub const Value = extern union {
1440 .float_16 => std.math.order(lhs.castTag(.float_16).?.data, 0),1452 .float_16 => std.math.order(lhs.castTag(.float_16).?.data, 0),
1441 .float_32 => std.math.order(lhs.castTag(.float_32).?.data, 0),1453 .float_32 => std.math.order(lhs.castTag(.float_32).?.data, 0),
1442 .float_64 => std.math.order(lhs.castTag(.float_64).?.data, 0),1454 .float_64 => std.math.order(lhs.castTag(.float_64).?.data, 0),
1455 .float_80 => std.math.order(lhs.castTag(.float_80).?.data, 0),
1443 .float_128 => std.math.order(lhs.castTag(.float_128).?.data, 0),1456 .float_128 => std.math.order(lhs.castTag(.float_128).?.data, 0),
14441457
1445 else => unreachable,1458 else => unreachable,
...@@ -1471,6 +1484,7 @@ pub const Value = extern union {...@@ -1471,6 +1484,7 @@ pub const Value = extern union {
1471 .float_16 => return std.math.order(lhs.castTag(.float_16).?.data, rhs.castTag(.float_16).?.data),1484 .float_16 => return std.math.order(lhs.castTag(.float_16).?.data, rhs.castTag(.float_16).?.data),
1472 .float_32 => return std.math.order(lhs.castTag(.float_32).?.data, rhs.castTag(.float_32).?.data),1485 .float_32 => return std.math.order(lhs.castTag(.float_32).?.data, rhs.castTag(.float_32).?.data),
1473 .float_64 => return std.math.order(lhs.castTag(.float_64).?.data, rhs.castTag(.float_64).?.data),1486 .float_64 => return std.math.order(lhs.castTag(.float_64).?.data, rhs.castTag(.float_64).?.data),
1487 .float_80 => return std.math.order(lhs.castTag(.float_80).?.data, rhs.castTag(.float_80).?.data),
1474 .float_128 => return std.math.order(lhs.castTag(.float_128).?.data, rhs.castTag(.float_128).?.data),1488 .float_128 => return std.math.order(lhs.castTag(.float_128).?.data, rhs.castTag(.float_128).?.data),
1475 else => unreachable,1489 else => unreachable,
1476 };1490 };
...@@ -2139,6 +2153,7 @@ pub const Value = extern union {...@@ -2139,6 +2153,7 @@ pub const Value = extern union {
2139 .float_16,2153 .float_16,
2140 .float_32,2154 .float_32,
2141 .float_64,2155 .float_64,
2156 .float_80,
2142 .float_128,2157 .float_128,
2143 => true,2158 => true,
2144 else => false,2159 else => false,
...@@ -2174,6 +2189,7 @@ pub const Value = extern union {...@@ -2174,6 +2189,7 @@ pub const Value = extern union {
2174 16 => return Value.Tag.float_16.create(arena, @intToFloat(f16, x)),2189 16 => return Value.Tag.float_16.create(arena, @intToFloat(f16, x)),
2175 32 => return Value.Tag.float_32.create(arena, @intToFloat(f32, x)),2190 32 => return Value.Tag.float_32.create(arena, @intToFloat(f32, x)),
2176 64 => return Value.Tag.float_64.create(arena, @intToFloat(f64, x)),2191 64 => return Value.Tag.float_64.create(arena, @intToFloat(f64, x)),
2192 80 => return Value.Tag.float_80.create(arena, @intToFloat(f80, x)),
2177 128 => return Value.Tag.float_128.create(arena, @intToFloat(f128, x)),2193 128 => return Value.Tag.float_128.create(arena, @intToFloat(f128, x)),
2178 else => unreachable,2194 else => unreachable,
2179 }2195 }
...@@ -2184,6 +2200,7 @@ pub const Value = extern union {...@@ -2184,6 +2200,7 @@ pub const Value = extern union {
2184 16 => return Value.Tag.float_16.create(arena, @floatCast(f16, float)),2200 16 => return Value.Tag.float_16.create(arena, @floatCast(f16, float)),
2185 32 => return Value.Tag.float_32.create(arena, @floatCast(f32, float)),2201 32 => return Value.Tag.float_32.create(arena, @floatCast(f32, float)),
2186 64 => return Value.Tag.float_64.create(arena, @floatCast(f64, float)),2202 64 => return Value.Tag.float_64.create(arena, @floatCast(f64, float)),
2203 80 => return Value.Tag.float_80.create(arena, @floatCast(f80, float)),
2187 128 => return Value.Tag.float_128.create(arena, float),2204 128 => return Value.Tag.float_128.create(arena, float),
2188 else => unreachable,2205 else => unreachable,
2189 }2206 }
...@@ -2281,7 +2298,7 @@ pub const Value = extern union {...@@ -2281,7 +2298,7 @@ pub const Value = extern union {
2281 }2298 }
22822299
2283 if (ty.isAnyFloat()) {2300 if (ty.isAnyFloat()) {
2284 return floatAdd(lhs, rhs, ty, arena);2301 return floatAdd(lhs, rhs, ty, arena, target);
2285 }2302 }
22862303
2287 const overflow_result = try intAddWithOverflow(lhs, rhs, ty, arena, target);2304 const overflow_result = try intAddWithOverflow(lhs, rhs, ty, arena, target);
...@@ -2371,7 +2388,7 @@ pub const Value = extern union {...@@ -2371,7 +2388,7 @@ pub const Value = extern union {
2371 }2388 }
23722389
2373 if (ty.isAnyFloat()) {2390 if (ty.isAnyFloat()) {
2374 return floatSub(lhs, rhs, ty, arena);2391 return floatSub(lhs, rhs, ty, arena, target);
2375 }2392 }
23762393
2377 const overflow_result = try intSubWithOverflow(lhs, rhs, ty, arena, target);2394 const overflow_result = try intSubWithOverflow(lhs, rhs, ty, arena, target);
...@@ -2454,7 +2471,7 @@ pub const Value = extern union {...@@ -2454,7 +2471,7 @@ pub const Value = extern union {
2454 }2471 }
24552472
2456 if (ty.isAnyFloat()) {2473 if (ty.isAnyFloat()) {
2457 return floatMul(lhs, rhs, ty, arena);2474 return floatMul(lhs, rhs, ty, arena, target);
2458 }2475 }
24592476
2460 const overflow_result = try intMulWithOverflow(lhs, rhs, ty, arena, target);2477 const overflow_result = try intMulWithOverflow(lhs, rhs, ty, arena, target);
...@@ -2753,23 +2770,72 @@ pub const Value = extern union {...@@ -2753,23 +2770,72 @@ pub const Value = extern union {
2753 .float_16 => std.math.isNan(val.castTag(.float_16).?.data),2770 .float_16 => std.math.isNan(val.castTag(.float_16).?.data),
2754 .float_32 => std.math.isNan(val.castTag(.float_32).?.data),2771 .float_32 => std.math.isNan(val.castTag(.float_32).?.data),
2755 .float_64 => std.math.isNan(val.castTag(.float_64).?.data),2772 .float_64 => std.math.isNan(val.castTag(.float_64).?.data),
2773 .float_80 => std.math.isNan(val.castTag(.float_80).?.data),
2756 .float_128 => std.math.isNan(val.castTag(.float_128).?.data),2774 .float_128 => std.math.isNan(val.castTag(.float_128).?.data),
2757 else => false,2775 else => false,
2758 };2776 };
2759 }2777 }
27602778
2761 pub fn floatRem(lhs: Value, rhs: Value, allocator: Allocator) !Value {2779 pub fn floatRem(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {
2762 _ = lhs;2780 switch (float_type.floatBits(target)) {
2763 _ = rhs;2781 16 => {
2764 _ = allocator;2782 const lhs_val = lhs.toFloat(f16);
2765 @panic("TODO implement Value.floatRem");2783 const rhs_val = rhs.toFloat(f16);
2784 return Value.Tag.float_16.create(arena, @rem(lhs_val, rhs_val));
2785 },
2786 32 => {
2787 const lhs_val = lhs.toFloat(f32);
2788 const rhs_val = rhs.toFloat(f32);
2789 return Value.Tag.float_32.create(arena, @rem(lhs_val, rhs_val));
2790 },
2791 64 => {
2792 const lhs_val = lhs.toFloat(f64);
2793 const rhs_val = rhs.toFloat(f64);
2794 return Value.Tag.float_64.create(arena, @rem(lhs_val, rhs_val));
2795 },
2796 80 => {
2797 const lhs_val = lhs.toFloat(f80);
2798 const rhs_val = rhs.toFloat(f80);
2799 return Value.Tag.float_80.create(arena, @rem(lhs_val, rhs_val));
2800 },
2801 128 => {
2802 const lhs_val = lhs.toFloat(f128);
2803 const rhs_val = rhs.toFloat(f128);
2804 return Value.Tag.float_128.create(arena, @rem(lhs_val, rhs_val));
2805 },
2806 else => unreachable,
2807 }
2766 }2808 }
27672809
2768 pub fn floatMod(lhs: Value, rhs: Value, allocator: Allocator) !Value {2810 pub fn floatMod(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {
2769 _ = lhs;2811 switch (float_type.floatBits(target)) {
2770 _ = rhs;2812 16 => {
2771 _ = allocator;2813 const lhs_val = lhs.toFloat(f16);
2772 @panic("TODO implement Value.floatMod");2814 const rhs_val = rhs.toFloat(f16);
2815 return Value.Tag.float_16.create(arena, @mod(lhs_val, rhs_val));
2816 },
2817 32 => {
2818 const lhs_val = lhs.toFloat(f32);
2819 const rhs_val = rhs.toFloat(f32);
2820 return Value.Tag.float_32.create(arena, @mod(lhs_val, rhs_val));
2821 },
2822 64 => {
2823 const lhs_val = lhs.toFloat(f64);
2824 const rhs_val = rhs.toFloat(f64);
2825 return Value.Tag.float_64.create(arena, @mod(lhs_val, rhs_val));
2826 },
2827 80 => {
2828 const lhs_val = lhs.toFloat(f80);
2829 const rhs_val = rhs.toFloat(f80);
2830 return Value.Tag.float_80.create(arena, @mod(lhs_val, rhs_val));
2831 },
2832 128 => {
2833 const lhs_val = lhs.toFloat(f128);
2834 const rhs_val = rhs.toFloat(f128);
2835 return Value.Tag.float_128.create(arena, @mod(lhs_val, rhs_val));
2836 },
2837 else => unreachable,
2838 }
2773 }2839 }
27742840
2775 pub fn intMul(lhs: Value, rhs: Value, allocator: Allocator) !Value {2841 pub fn intMul(lhs: Value, rhs: Value, allocator: Allocator) !Value {
...@@ -2929,24 +2995,30 @@ pub const Value = extern union {...@@ -2929,24 +2995,30 @@ pub const Value = extern union {
2929 rhs: Value,2995 rhs: Value,
2930 float_type: Type,2996 float_type: Type,
2931 arena: Allocator,2997 arena: Allocator,
2998 target: Target,
2932 ) !Value {2999 ) !Value {
2933 switch (float_type.tag()) {3000 switch (float_type.floatBits(target)) {
2934 .f16 => {3001 16 => {
2935 const lhs_val = lhs.toFloat(f16);3002 const lhs_val = lhs.toFloat(f16);
2936 const rhs_val = rhs.toFloat(f16);3003 const rhs_val = rhs.toFloat(f16);
2937 return Value.Tag.float_16.create(arena, lhs_val + rhs_val);3004 return Value.Tag.float_16.create(arena, lhs_val + rhs_val);
2938 },3005 },
2939 .f32 => {3006 32 => {
2940 const lhs_val = lhs.toFloat(f32);3007 const lhs_val = lhs.toFloat(f32);
2941 const rhs_val = rhs.toFloat(f32);3008 const rhs_val = rhs.toFloat(f32);
2942 return Value.Tag.float_32.create(arena, lhs_val + rhs_val);3009 return Value.Tag.float_32.create(arena, lhs_val + rhs_val);
2943 },3010 },
2944 .f64 => {3011 64 => {
2945 const lhs_val = lhs.toFloat(f64);3012 const lhs_val = lhs.toFloat(f64);
2946 const rhs_val = rhs.toFloat(f64);3013 const rhs_val = rhs.toFloat(f64);
2947 return Value.Tag.float_64.create(arena, lhs_val + rhs_val);3014 return Value.Tag.float_64.create(arena, lhs_val + rhs_val);
2948 },3015 },
2949 .f128, .comptime_float, .c_longdouble => {3016 80 => {
3017 const lhs_val = lhs.toFloat(f80);
3018 const rhs_val = rhs.toFloat(f80);
3019 return Value.Tag.float_80.create(arena, lhs_val + rhs_val);
3020 },
3021 128 => {
2950 const lhs_val = lhs.toFloat(f128);3022 const lhs_val = lhs.toFloat(f128);
2951 const rhs_val = rhs.toFloat(f128);3023 const rhs_val = rhs.toFloat(f128);
2952 return Value.Tag.float_128.create(arena, lhs_val + rhs_val);3024 return Value.Tag.float_128.create(arena, lhs_val + rhs_val);
...@@ -2960,24 +3032,30 @@ pub const Value = extern union {...@@ -2960,24 +3032,30 @@ pub const Value = extern union {
2960 rhs: Value,3032 rhs: Value,
2961 float_type: Type,3033 float_type: Type,
2962 arena: Allocator,3034 arena: Allocator,
3035 target: Target,
2963 ) !Value {3036 ) !Value {
2964 switch (float_type.tag()) {3037 switch (float_type.floatBits(target)) {
2965 .f16 => {3038 16 => {
2966 const lhs_val = lhs.toFloat(f16);3039 const lhs_val = lhs.toFloat(f16);
2967 const rhs_val = rhs.toFloat(f16);3040 const rhs_val = rhs.toFloat(f16);
2968 return Value.Tag.float_16.create(arena, lhs_val - rhs_val);3041 return Value.Tag.float_16.create(arena, lhs_val - rhs_val);
2969 },3042 },
2970 .f32 => {3043 32 => {
2971 const lhs_val = lhs.toFloat(f32);3044 const lhs_val = lhs.toFloat(f32);
2972 const rhs_val = rhs.toFloat(f32);3045 const rhs_val = rhs.toFloat(f32);
2973 return Value.Tag.float_32.create(arena, lhs_val - rhs_val);3046 return Value.Tag.float_32.create(arena, lhs_val - rhs_val);
2974 },3047 },
2975 .f64 => {3048 64 => {
2976 const lhs_val = lhs.toFloat(f64);3049 const lhs_val = lhs.toFloat(f64);
2977 const rhs_val = rhs.toFloat(f64);3050 const rhs_val = rhs.toFloat(f64);
2978 return Value.Tag.float_64.create(arena, lhs_val - rhs_val);3051 return Value.Tag.float_64.create(arena, lhs_val - rhs_val);
2979 },3052 },
2980 .f128, .comptime_float, .c_longdouble => {3053 80 => {
3054 const lhs_val = lhs.toFloat(f80);
3055 const rhs_val = rhs.toFloat(f80);
3056 return Value.Tag.float_80.create(arena, lhs_val - rhs_val);
3057 },
3058 128 => {
2981 const lhs_val = lhs.toFloat(f128);3059 const lhs_val = lhs.toFloat(f128);
2982 const rhs_val = rhs.toFloat(f128);3060 const rhs_val = rhs.toFloat(f128);
2983 return Value.Tag.float_128.create(arena, lhs_val - rhs_val);3061 return Value.Tag.float_128.create(arena, lhs_val - rhs_val);
...@@ -2991,24 +3069,30 @@ pub const Value = extern union {...@@ -2991,24 +3069,30 @@ pub const Value = extern union {
2991 rhs: Value,3069 rhs: Value,
2992 float_type: Type,3070 float_type: Type,
2993 arena: Allocator,3071 arena: Allocator,
3072 target: Target,
2994 ) !Value {3073 ) !Value {
2995 switch (float_type.tag()) {3074 switch (float_type.floatBits(target)) {
2996 .f16 => {3075 16 => {
2997 const lhs_val = lhs.toFloat(f16);3076 const lhs_val = lhs.toFloat(f16);
2998 const rhs_val = rhs.toFloat(f16);3077 const rhs_val = rhs.toFloat(f16);
2999 return Value.Tag.float_16.create(arena, lhs_val / rhs_val);3078 return Value.Tag.float_16.create(arena, lhs_val / rhs_val);
3000 },3079 },
3001 .f32 => {3080 32 => {
3002 const lhs_val = lhs.toFloat(f32);3081 const lhs_val = lhs.toFloat(f32);
3003 const rhs_val = rhs.toFloat(f32);3082 const rhs_val = rhs.toFloat(f32);
3004 return Value.Tag.float_32.create(arena, lhs_val / rhs_val);3083 return Value.Tag.float_32.create(arena, lhs_val / rhs_val);
3005 },3084 },
3006 .f64 => {3085 64 => {
3007 const lhs_val = lhs.toFloat(f64);3086 const lhs_val = lhs.toFloat(f64);
3008 const rhs_val = rhs.toFloat(f64);3087 const rhs_val = rhs.toFloat(f64);
3009 return Value.Tag.float_64.create(arena, lhs_val / rhs_val);3088 return Value.Tag.float_64.create(arena, lhs_val / rhs_val);
3010 },3089 },
3011 .f128, .comptime_float, .c_longdouble => {3090 80 => {
3091 const lhs_val = lhs.toFloat(f80);
3092 const rhs_val = rhs.toFloat(f80);
3093 return Value.Tag.float_80.create(arena, lhs_val / rhs_val);
3094 },
3095 128 => {
3012 const lhs_val = lhs.toFloat(f128);3096 const lhs_val = lhs.toFloat(f128);
3013 const rhs_val = rhs.toFloat(f128);3097 const rhs_val = rhs.toFloat(f128);
3014 return Value.Tag.float_128.create(arena, lhs_val / rhs_val);3098 return Value.Tag.float_128.create(arena, lhs_val / rhs_val);
...@@ -3022,24 +3106,30 @@ pub const Value = extern union {...@@ -3022,24 +3106,30 @@ pub const Value = extern union {
3022 rhs: Value,3106 rhs: Value,
3023 float_type: Type,3107 float_type: Type,
3024 arena: Allocator,3108 arena: Allocator,
3109 target: Target,
3025 ) !Value {3110 ) !Value {
3026 switch (float_type.tag()) {3111 switch (float_type.floatBits(target)) {
3027 .f16 => {3112 16 => {
3028 const lhs_val = lhs.toFloat(f16);3113 const lhs_val = lhs.toFloat(f16);
3029 const rhs_val = rhs.toFloat(f16);3114 const rhs_val = rhs.toFloat(f16);
3030 return Value.Tag.float_16.create(arena, @divFloor(lhs_val, rhs_val));3115 return Value.Tag.float_16.create(arena, @divFloor(lhs_val, rhs_val));
3031 },3116 },
3032 .f32 => {3117 32 => {
3033 const lhs_val = lhs.toFloat(f32);3118 const lhs_val = lhs.toFloat(f32);
3034 const rhs_val = rhs.toFloat(f32);3119 const rhs_val = rhs.toFloat(f32);
3035 return Value.Tag.float_32.create(arena, @divFloor(lhs_val, rhs_val));3120 return Value.Tag.float_32.create(arena, @divFloor(lhs_val, rhs_val));
3036 },3121 },
3037 .f64 => {3122 64 => {
3038 const lhs_val = lhs.toFloat(f64);3123 const lhs_val = lhs.toFloat(f64);
3039 const rhs_val = rhs.toFloat(f64);3124 const rhs_val = rhs.toFloat(f64);
3040 return Value.Tag.float_64.create(arena, @divFloor(lhs_val, rhs_val));3125 return Value.Tag.float_64.create(arena, @divFloor(lhs_val, rhs_val));
3041 },3126 },
3042 .f128, .comptime_float, .c_longdouble => {3127 80 => {
3128 const lhs_val = lhs.toFloat(f80);
3129 const rhs_val = rhs.toFloat(f80);
3130 return Value.Tag.float_80.create(arena, @divFloor(lhs_val, rhs_val));
3131 },
3132 128 => {
3043 const lhs_val = lhs.toFloat(f128);3133 const lhs_val = lhs.toFloat(f128);
3044 const rhs_val = rhs.toFloat(f128);3134 const rhs_val = rhs.toFloat(f128);
3045 return Value.Tag.float_128.create(arena, @divFloor(lhs_val, rhs_val));3135 return Value.Tag.float_128.create(arena, @divFloor(lhs_val, rhs_val));
...@@ -3053,24 +3143,30 @@ pub const Value = extern union {...@@ -3053,24 +3143,30 @@ pub const Value = extern union {
3053 rhs: Value,3143 rhs: Value,
3054 float_type: Type,3144 float_type: Type,
3055 arena: Allocator,3145 arena: Allocator,
3146 target: Target,
3056 ) !Value {3147 ) !Value {
3057 switch (float_type.tag()) {3148 switch (float_type.floatBits(target)) {
3058 .f16 => {3149 16 => {
3059 const lhs_val = lhs.toFloat(f16);3150 const lhs_val = lhs.toFloat(f16);
3060 const rhs_val = rhs.toFloat(f16);3151 const rhs_val = rhs.toFloat(f16);
3061 return Value.Tag.float_16.create(arena, @divTrunc(lhs_val, rhs_val));3152 return Value.Tag.float_16.create(arena, @divTrunc(lhs_val, rhs_val));
3062 },3153 },
3063 .f32 => {3154 32 => {
3064 const lhs_val = lhs.toFloat(f32);3155 const lhs_val = lhs.toFloat(f32);
3065 const rhs_val = rhs.toFloat(f32);3156 const rhs_val = rhs.toFloat(f32);
3066 return Value.Tag.float_32.create(arena, @divTrunc(lhs_val, rhs_val));3157 return Value.Tag.float_32.create(arena, @divTrunc(lhs_val, rhs_val));
3067 },3158 },
3068 .f64 => {3159 64 => {
3069 const lhs_val = lhs.toFloat(f64);3160 const lhs_val = lhs.toFloat(f64);
3070 const rhs_val = rhs.toFloat(f64);3161 const rhs_val = rhs.toFloat(f64);
3071 return Value.Tag.float_64.create(arena, @divTrunc(lhs_val, rhs_val));3162 return Value.Tag.float_64.create(arena, @divTrunc(lhs_val, rhs_val));
3072 },3163 },
3073 .f128, .comptime_float, .c_longdouble => {3164 80 => {
3165 const lhs_val = lhs.toFloat(f80);
3166 const rhs_val = rhs.toFloat(f80);
3167 return Value.Tag.float_80.create(arena, @divTrunc(lhs_val, rhs_val));
3168 },
3169 128 => {
3074 const lhs_val = lhs.toFloat(f128);3170 const lhs_val = lhs.toFloat(f128);
3075 const rhs_val = rhs.toFloat(f128);3171 const rhs_val = rhs.toFloat(f128);
3076 return Value.Tag.float_128.create(arena, @divTrunc(lhs_val, rhs_val));3172 return Value.Tag.float_128.create(arena, @divTrunc(lhs_val, rhs_val));
...@@ -3084,24 +3180,30 @@ pub const Value = extern union {...@@ -3084,24 +3180,30 @@ pub const Value = extern union {
3084 rhs: Value,3180 rhs: Value,
3085 float_type: Type,3181 float_type: Type,
3086 arena: Allocator,3182 arena: Allocator,
3183 target: Target,
3087 ) !Value {3184 ) !Value {
3088 switch (float_type.tag()) {3185 switch (float_type.floatBits(target)) {
3089 .f16 => {3186 16 => {
3090 const lhs_val = lhs.toFloat(f16);3187 const lhs_val = lhs.toFloat(f16);
3091 const rhs_val = rhs.toFloat(f16);3188 const rhs_val = rhs.toFloat(f16);
3092 return Value.Tag.float_16.create(arena, lhs_val * rhs_val);3189 return Value.Tag.float_16.create(arena, lhs_val * rhs_val);
3093 },3190 },
3094 .f32 => {3191 32 => {
3095 const lhs_val = lhs.toFloat(f32);3192 const lhs_val = lhs.toFloat(f32);
3096 const rhs_val = rhs.toFloat(f32);3193 const rhs_val = rhs.toFloat(f32);
3097 return Value.Tag.float_32.create(arena, lhs_val * rhs_val);3194 return Value.Tag.float_32.create(arena, lhs_val * rhs_val);
3098 },3195 },
3099 .f64 => {3196 64 => {
3100 const lhs_val = lhs.toFloat(f64);3197 const lhs_val = lhs.toFloat(f64);
3101 const rhs_val = rhs.toFloat(f64);3198 const rhs_val = rhs.toFloat(f64);
3102 return Value.Tag.float_64.create(arena, lhs_val * rhs_val);3199 return Value.Tag.float_64.create(arena, lhs_val * rhs_val);
3103 },3200 },
3104 .f128, .comptime_float, .c_longdouble => {3201 80 => {
3202 const lhs_val = lhs.toFloat(f80);
3203 const rhs_val = rhs.toFloat(f80);
3204 return Value.Tag.float_80.create(arena, lhs_val * rhs_val);
3205 },
3206 128 => {
3105 const lhs_val = lhs.toFloat(f128);3207 const lhs_val = lhs.toFloat(f128);
3106 const rhs_val = rhs.toFloat(f128);3208 const rhs_val = rhs.toFloat(f128);
3107 return Value.Tag.float_128.create(arena, lhs_val * rhs_val);3209 return Value.Tag.float_128.create(arena, lhs_val * rhs_val);
...@@ -3250,6 +3352,13 @@ pub const Value = extern union {...@@ -3250,6 +3352,13 @@ pub const Value = extern union {
3250 data: f64,3352 data: f64,
3251 };3353 };
32523354
3355 pub const Float_80 = struct {
3356 pub const base_tag = Tag.float_80;
3357
3358 base: Payload = .{ .tag = base_tag },
3359 data: f80,
3360 };
3361
3253 pub const Float_128 = struct {3362 pub const Float_128 = struct {
3254 pub const base_tag = Tag.float_128;3363 pub const base_tag = Tag.float_128;
32553364
test/behavior/math.zig-2
...@@ -768,8 +768,6 @@ test "shift left/right on u0 operand" {...@@ -768,8 +768,6 @@ test "shift left/right on u0 operand" {
768}768}
769769
770test "comptime float rem int" {770test "comptime float rem int" {
771 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
772
773 comptime {771 comptime {
774 var x = @as(f32, 1) % 2;772 var x = @as(f32, 1) % 2;
775 try expect(x == 1.0);773 try expect(x == 1.0);