authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-06 22:41:43-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-02-06 22:41:43-05:00
log069dd01ce4ced3cb9664e4f1e09be753cb3ed476
tree4e32e8efde362d928e204335d8582788d1355b35
parent53e6c719efe5073307ee58436b17ee80f574b984
parenteb82fdf96c3392ec9eabacbaa98c976f9ccd264e
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10740 from ziglang/stage2-float-arithmetic

stage2: add more float arithmetic and f80 support

6 files changed, 240 insertions(+), 77 deletions(-)

lib/std/special/compiler_rt/addXf3.zig+1-1
......@@ -339,7 +339,7 @@ pub fn __addxf3(a: f80, b: f80) callconv(.C) f80 {
339339 // If partial cancellation occurred, we need to left-shift the result
340340 // and adjust the exponent:
341341 if (a_int < int_bit << 3) {
342 const shift = @intCast(i32, @clz(u80, a_int)) - @intCast(i32, @clz(u80, int_bit << 3));
342 const shift = @intCast(i32, @clz(u80, a_int)) - @intCast(i32, @clz(u80, @as(u80, int_bit) << 3));
343343 a_int <<= @intCast(u7, shift);
344344 a_exp -= shift;
345345 }
src/AstGen.zig+7-5
......@@ -2601,8 +2601,8 @@ fn varDecl(
26012601
26022602 var resolve_inferred_alloc: Zir.Inst.Ref = .none;
26032603 var opt_type_inst: Zir.Inst.Ref = .none;
2604 if (var_decl.ast.type_node != 0) {
2605 const type_inst = try typeExpr(gz, &init_scope.base, var_decl.ast.type_node);
2604 if (type_node != 0) {
2605 const type_inst = try typeExpr(gz, &init_scope.base, type_node);
26062606 opt_type_inst = type_inst;
26072607 if (align_inst == .none) {
26082608 init_scope.instructions_top = gz.instructions.items.len;
......@@ -2683,7 +2683,7 @@ fn varDecl(
26832683 const src_inst = gz.instructions.items[src];
26842684 if (zir_tags[src_inst] == .store_to_block_ptr) {
26852685 if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) {
2686 if (var_decl.ast.type_node != 0) {
2686 if (type_node != 0) {
26872687 zir_tags[src_inst] = .store;
26882688 } else {
26892689 zir_tags[src_inst] = .store_to_inferred_ptr;
......@@ -8409,10 +8409,11 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
84098409 .c_ushort_type,
84108410 .comptime_float_type,
84118411 .comptime_int_type,
8412 .f128_type,
84138412 .f16_type,
84148413 .f32_type,
84158414 .f64_type,
8415 .f80_type,
8416 .f128_type,
84168417 .i16_type,
84178418 .i32_type,
84188419 .i64_type,
......@@ -8648,10 +8649,11 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
86488649 .c_ulong_type,
86498650 .c_ulonglong_type,
86508651 .c_ushort_type,
8651 .f128_type,
86528652 .f16_type,
86538653 .f32_type,
86548654 .f64_type,
8655 .f80_type,
8656 .f128_type,
86558657 .i16_type,
86568658 .i32_type,
86578659 .i64_type,
src/Sema.zig+12-12
......@@ -8188,7 +8188,7 @@ fn analyzeArithmetic(
81888188 } else {
81898189 return sema.addConstant(
81908190 scalar_type,
8191 try lhs_val.floatAdd(rhs_val, scalar_type, sema.arena),
8191 try lhs_val.floatAdd(rhs_val, scalar_type, sema.arena, target),
81928192 );
81938193 }
81948194 } else break :rs .{ .src = rhs_src, .air_tag = .add };
......@@ -8281,7 +8281,7 @@ fn analyzeArithmetic(
82818281 } else {
82828282 return sema.addConstant(
82838283 scalar_type,
8284 try lhs_val.floatSub(rhs_val, scalar_type, sema.arena),
8284 try lhs_val.floatSub(rhs_val, scalar_type, sema.arena, target),
82858285 );
82868286 }
82878287 } else break :rs .{ .src = rhs_src, .air_tag = .sub };
......@@ -8397,7 +8397,7 @@ fn analyzeArithmetic(
83978397 } else {
83988398 return sema.addConstant(
83998399 scalar_type,
8400 try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena),
8400 try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena, target),
84018401 );
84028402 }
84038403 } else {
......@@ -8472,7 +8472,7 @@ fn analyzeArithmetic(
84728472 } else {
84738473 return sema.addConstant(
84748474 scalar_type,
8475 try lhs_val.floatDivTrunc(rhs_val, scalar_type, sema.arena),
8475 try lhs_val.floatDivTrunc(rhs_val, scalar_type, sema.arena, target),
84768476 );
84778477 }
84788478 } else break :rs .{ .src = rhs_src, .air_tag = .div_trunc };
......@@ -8535,7 +8535,7 @@ fn analyzeArithmetic(
85358535 } else {
85368536 return sema.addConstant(
85378537 scalar_type,
8538 try lhs_val.floatDivFloor(rhs_val, scalar_type, sema.arena),
8538 try lhs_val.floatDivFloor(rhs_val, scalar_type, sema.arena, target),
85398539 );
85408540 }
85418541 } else break :rs .{ .src = rhs_src, .air_tag = .div_floor };
......@@ -8587,7 +8587,7 @@ fn analyzeArithmetic(
85878587 // TODO: emit compile error if there is a remainder
85888588 return sema.addConstant(
85898589 scalar_type,
8590 try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena),
8590 try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena, target),
85918591 );
85928592 }
85938593 } else break :rs .{ .src = rhs_src, .air_tag = .div_exact };
......@@ -8642,7 +8642,7 @@ fn analyzeArithmetic(
86428642 } else {
86438643 return sema.addConstant(
86448644 scalar_type,
8645 try lhs_val.floatMul(rhs_val, scalar_type, sema.arena),
8645 try lhs_val.floatMul(rhs_val, scalar_type, sema.arena, target),
86468646 );
86478647 }
86488648 } else break :rs .{ .src = lhs_src, .air_tag = .mul };
......@@ -8798,7 +8798,7 @@ fn analyzeArithmetic(
87988798 }
87998799 return sema.addConstant(
88008800 scalar_type,
8801 try lhs_val.floatRem(rhs_val, sema.arena),
8801 try lhs_val.floatRem(rhs_val, scalar_type, sema.arena, target),
88028802 );
88038803 } else {
88048804 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
......@@ -8859,7 +8859,7 @@ fn analyzeArithmetic(
88598859 if (maybe_rhs_val) |rhs_val| {
88608860 return sema.addConstant(
88618861 scalar_type,
8862 try lhs_val.floatRem(rhs_val, sema.arena),
8862 try lhs_val.floatRem(rhs_val, scalar_type, sema.arena, target),
88638863 );
88648864 } else break :rs .{ .src = rhs_src, .air_tag = .rem };
88658865 } else break :rs .{ .src = lhs_src, .air_tag = .rem };
......@@ -8916,7 +8916,7 @@ fn analyzeArithmetic(
89168916 if (maybe_rhs_val) |rhs_val| {
89178917 return sema.addConstant(
89188918 scalar_type,
8919 try lhs_val.floatMod(rhs_val, sema.arena),
8919 try lhs_val.floatMod(rhs_val, scalar_type, sema.arena, target),
89208920 );
89218921 } else break :rs .{ .src = rhs_src, .air_tag = .mod };
89228922 } else break :rs .{ .src = lhs_src, .air_tag = .mod };
......@@ -14196,12 +14196,12 @@ fn coerce(
1419614196 .Float, .ComptimeFloat => switch (inst_ty.zigTypeTag()) {
1419714197 .ComptimeFloat => {
1419814198 const val = try sema.resolveConstValue(block, inst_src, inst);
14199 const result_val = try val.floatCast(sema.arena, dest_ty);
14199 const result_val = try val.floatCast(sema.arena, dest_ty, target);
1420014200 return try sema.addConstant(dest_ty, result_val);
1420114201 },
1420214202 .Float => {
1420314203 if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| {
14204 const result_val = try val.floatCast(sema.arena, dest_ty);
14204 const result_val = try val.floatCast(sema.arena, dest_ty, target);
1420514205 if (!val.eql(result_val, dest_ty)) {
1420614206 return sema.fail(
1420714207 block,
src/stage1/codegen.cpp+5-2
......@@ -9432,11 +9432,14 @@ static void define_builtin_types(CodeGen *g) {
94329432 if (target_has_f80(g->zig_target)) {
94339433 entry->llvm_type = LLVMX86FP80Type();
94349434 } else {
9435 // We use i128 here instead of x86_fp80 because on targets such as arm,
9436 // LLVM will give "ERROR: Cannot select" for any instructions involving
9437 // the x86_fp80 type.
94359438 entry->llvm_type = get_int_type(g, false, 128)->llvm_type;
94369439 }
94379440 entry->size_in_bits = 8 * 16;
9438 entry->abi_size = 16;
9439 entry->abi_align = 16;
9441 entry->abi_size = 16; // matches LLVMABISizeOfType(LLVMX86FP80Type())
9442 entry->abi_align = 16; // matches LLVMABIAlignmentOfType(LLVMX86FP80Type())
94409443 buf_init_from_str(&entry->name, "f80");
94419444 entry->data.floating.bit_count = 80;
94429445
src/value.zig+215-55
......@@ -138,6 +138,7 @@ pub const Value = extern union {
138138 float_16,
139139 float_32,
140140 float_64,
141 float_80,
141142 float_128,
142143 enum_literal,
143144 /// A specific enum tag, indicated by the field index (declaration order).
......@@ -295,6 +296,7 @@ pub const Value = extern union {
295296 .float_16 => Payload.Float_16,
296297 .float_32 => Payload.Float_32,
297298 .float_64 => Payload.Float_64,
299 .float_80 => Payload.Float_80,
298300 .float_128 => Payload.Float_128,
299301 .@"error" => Payload.Error,
300302 .inferred_alloc => Payload.InferredAlloc,
......@@ -546,6 +548,7 @@ pub const Value = extern union {
546548 .float_16 => return self.copyPayloadShallow(arena, Payload.Float_16),
547549 .float_32 => return self.copyPayloadShallow(arena, Payload.Float_32),
548550 .float_64 => return self.copyPayloadShallow(arena, Payload.Float_64),
551 .float_80 => return self.copyPayloadShallow(arena, Payload.Float_80),
549552 .float_128 => return self.copyPayloadShallow(arena, Payload.Float_128),
550553 .enum_literal => {
551554 const payload = self.castTag(.enum_literal).?;
......@@ -733,6 +736,7 @@ pub const Value = extern union {
733736 .float_16 => return out_stream.print("{}", .{val.castTag(.float_16).?.data}),
734737 .float_32 => return out_stream.print("{}", .{val.castTag(.float_32).?.data}),
735738 .float_64 => return out_stream.print("{}", .{val.castTag(.float_64).?.data}),
739 .float_80 => return out_stream.print("{}", .{val.castTag(.float_80).?.data}),
736740 .float_128 => return out_stream.print("{}", .{val.castTag(.float_128).?.data}),
737741 .@"error" => return out_stream.print("error.{s}", .{val.castTag(.@"error").?.data.name}),
738742 // TODO to print this it should be error{ Set, Items }!T(val), but we need the type for that
......@@ -1029,6 +1033,11 @@ pub const Value = extern union {
10291033 }
10301034
10311035 pub fn writeToMemory(val: Value, ty: Type, target: Target, buffer: []u8) void {
1036 if (val.isUndef()) {
1037 const size = @intCast(usize, ty.abiSize(target));
1038 std.mem.set(u8, buffer[0..size], 0xaa);
1039 return;
1040 }
10321041 switch (ty.zigTypeTag()) {
10331042 .Int => {
10341043 var bigint_buffer: BigIntSpace = undefined;
......@@ -1064,6 +1073,14 @@ pub const Value = extern union {
10641073 buf_off += elem_size;
10651074 }
10661075 },
1076 .Struct => {
1077 const fields = ty.structFields().values();
1078 const field_vals = val.castTag(.@"struct").?.data;
1079 for (fields) |field, i| {
1080 const off = @intCast(usize, ty.structFieldOffset(i, target));
1081 writeToMemory(field_vals[i], field.ty, target, buffer[off..]);
1082 }
1083 },
10671084 else => @panic("TODO implement writeToMemory for more types"),
10681085 }
10691086 }
......@@ -1083,6 +1100,7 @@ pub const Value = extern union {
10831100 16 => return Value.Tag.float_16.create(arena, floatReadFromMemory(f16, target, buffer)),
10841101 32 => return Value.Tag.float_32.create(arena, floatReadFromMemory(f32, target, buffer)),
10851102 64 => return Value.Tag.float_64.create(arena, floatReadFromMemory(f64, target, buffer)),
1103 80 => return Value.Tag.float_80.create(arena, floatReadFromMemory(f80, target, buffer)),
10861104 128 => return Value.Tag.float_128.create(arena, floatReadFromMemory(f128, target, buffer)),
10871105 else => unreachable,
10881106 },
......@@ -1100,6 +1118,12 @@ pub const Value = extern union {
11001118 }
11011119
11021120 fn floatReadFromMemory(comptime F: type, target: Target, buffer: []const u8) F {
1121 if (F == f80) {
1122 // TODO: use std.math.F80Repr?
1123 const int = std.mem.readInt(u128, buffer[0..16], target.cpu.arch.endian());
1124 // TODO shouldn't this be a bitcast from u80 to f80 instead of u128 to f80?
1125 return @bitCast(F, int);
1126 }
11031127 const Int = @Type(.{ .Int = .{
11041128 .signedness = .unsigned,
11051129 .bits = @typeInfo(F).Float.bits,
......@@ -1114,12 +1138,23 @@ pub const Value = extern union {
11141138 .float_16 => @floatCast(T, val.castTag(.float_16).?.data),
11151139 .float_32 => @floatCast(T, val.castTag(.float_32).?.data),
11161140 .float_64 => @floatCast(T, val.castTag(.float_64).?.data),
1141 .float_80 => @floatCast(T, val.castTag(.float_80).?.data),
11171142 .float_128 => @floatCast(T, val.castTag(.float_128).?.data),
11181143
11191144 .zero => 0,
11201145 .one => 1,
1121 .int_u64 => @intToFloat(T, val.castTag(.int_u64).?.data),
1122 .int_i64 => @intToFloat(T, val.castTag(.int_i64).?.data),
1146 .int_u64 => {
1147 if (T == f80) {
1148 @panic("TODO we can't lower this properly on non-x86 llvm backend yet");
1149 }
1150 return @intToFloat(T, val.castTag(.int_u64).?.data);
1151 },
1152 .int_i64 => {
1153 if (T == f80) {
1154 @panic("TODO we can't lower this properly on non-x86 llvm backend yet");
1155 }
1156 return @intToFloat(T, val.castTag(.int_i64).?.data);
1157 },
11231158
11241159 .int_big_positive => @floatCast(T, bigIntToFloat(val.castTag(.int_big_positive).?.data, true)),
11251160 .int_big_negative => @floatCast(T, bigIntToFloat(val.castTag(.int_big_negative).?.data, false)),
......@@ -1367,14 +1402,13 @@ pub const Value = extern union {
13671402
13681403 /// Converts an integer or a float to a float. May result in a loss of information.
13691404 /// Caller can find out by equality checking the result against the operand.
1370 pub fn floatCast(self: Value, arena: Allocator, dest_ty: Type) !Value {
1371 switch (dest_ty.tag()) {
1372 .f16 => return Value.Tag.float_16.create(arena, self.toFloat(f16)),
1373 .f32 => return Value.Tag.float_32.create(arena, self.toFloat(f32)),
1374 .f64 => return Value.Tag.float_64.create(arena, self.toFloat(f64)),
1375 .f128, .comptime_float, .c_longdouble => {
1376 return Value.Tag.float_128.create(arena, self.toFloat(f128));
1377 },
1405 pub fn floatCast(self: Value, arena: Allocator, dest_ty: Type, target: Target) !Value {
1406 switch (dest_ty.floatBits(target)) {
1407 16 => return Value.Tag.float_16.create(arena, self.toFloat(f16)),
1408 32 => return Value.Tag.float_32.create(arena, self.toFloat(f32)),
1409 64 => return Value.Tag.float_64.create(arena, self.toFloat(f64)),
1410 80 => return Value.Tag.float_80.create(arena, self.toFloat(f80)),
1411 128 => return Value.Tag.float_128.create(arena, self.toFloat(f128)),
13781412 else => unreachable,
13791413 }
13801414 }
......@@ -1389,8 +1423,10 @@ pub const Value = extern union {
13891423 .float_16 => @rem(self.castTag(.float_16).?.data, 1) != 0,
13901424 .float_32 => @rem(self.castTag(.float_32).?.data, 1) != 0,
13911425 .float_64 => @rem(self.castTag(.float_64).?.data, 1) != 0,
1392 // .float_128 => @rem(self.castTag(.float_128).?.data, 1) != 0,
1393 .float_128 => @panic("TODO lld: error: undefined symbol: fmodl"),
1426 //.float_80 => @rem(self.castTag(.float_80).?.data, 1) != 0,
1427 .float_80 => @panic("TODO implement __remx in compiler-rt"),
1428 //.float_128 => @rem(self.castTag(.float_128).?.data, 1) != 0,
1429 .float_128 => @panic("TODO implement fmodl in compiler-rt"),
13941430
13951431 else => unreachable,
13961432 };
......@@ -1408,6 +1444,7 @@ pub const Value = extern union {
14081444 .float_16 => self.castTag(.float_16).?.data == 0,
14091445 .float_32 => self.castTag(.float_32).?.data == 0,
14101446 .float_64 => self.castTag(.float_64).?.data == 0,
1447 .float_80 => self.castTag(.float_80).?.data == 0,
14111448 .float_128 => self.castTag(.float_128).?.data == 0,
14121449
14131450 .int_big_positive => self.castTag(.int_big_positive).?.asBigInt().eqZero(),
......@@ -1440,6 +1477,7 @@ pub const Value = extern union {
14401477 .float_16 => std.math.order(lhs.castTag(.float_16).?.data, 0),
14411478 .float_32 => std.math.order(lhs.castTag(.float_32).?.data, 0),
14421479 .float_64 => std.math.order(lhs.castTag(.float_64).?.data, 0),
1480 .float_80 => std.math.order(lhs.castTag(.float_80).?.data, 0),
14431481 .float_128 => std.math.order(lhs.castTag(.float_128).?.data, 0),
14441482
14451483 else => unreachable,
......@@ -1471,6 +1509,7 @@ pub const Value = extern union {
14711509 .float_16 => return std.math.order(lhs.castTag(.float_16).?.data, rhs.castTag(.float_16).?.data),
14721510 .float_32 => return std.math.order(lhs.castTag(.float_32).?.data, rhs.castTag(.float_32).?.data),
14731511 .float_64 => return std.math.order(lhs.castTag(.float_64).?.data, rhs.castTag(.float_64).?.data),
1512 .float_80 => return std.math.order(lhs.castTag(.float_80).?.data, rhs.castTag(.float_80).?.data),
14741513 .float_128 => return std.math.order(lhs.castTag(.float_128).?.data, rhs.castTag(.float_128).?.data),
14751514 else => unreachable,
14761515 };
......@@ -2139,6 +2178,7 @@ pub const Value = extern union {
21392178 .float_16,
21402179 .float_32,
21412180 .float_64,
2181 .float_80,
21422182 .float_128,
21432183 => true,
21442184 else => false,
......@@ -2174,6 +2214,9 @@ pub const Value = extern union {
21742214 16 => return Value.Tag.float_16.create(arena, @intToFloat(f16, x)),
21752215 32 => return Value.Tag.float_32.create(arena, @intToFloat(f32, x)),
21762216 64 => return Value.Tag.float_64.create(arena, @intToFloat(f64, x)),
2217 // We can't lower this properly on non-x86 llvm backends yet
2218 //80 => return Value.Tag.float_80.create(arena, @intToFloat(f80, x)),
2219 80 => @panic("TODO f80 intToFloat"),
21772220 128 => return Value.Tag.float_128.create(arena, @intToFloat(f128, x)),
21782221 else => unreachable,
21792222 }
......@@ -2184,6 +2227,7 @@ pub const Value = extern union {
21842227 16 => return Value.Tag.float_16.create(arena, @floatCast(f16, float)),
21852228 32 => return Value.Tag.float_32.create(arena, @floatCast(f32, float)),
21862229 64 => return Value.Tag.float_64.create(arena, @floatCast(f64, float)),
2230 80 => return Value.Tag.float_80.create(arena, @floatCast(f80, float)),
21872231 128 => return Value.Tag.float_128.create(arena, float),
21882232 else => unreachable,
21892233 }
......@@ -2281,7 +2325,7 @@ pub const Value = extern union {
22812325 }
22822326
22832327 if (ty.isAnyFloat()) {
2284 return floatAdd(lhs, rhs, ty, arena);
2328 return floatAdd(lhs, rhs, ty, arena, target);
22852329 }
22862330
22872331 const overflow_result = try intAddWithOverflow(lhs, rhs, ty, arena, target);
......@@ -2371,7 +2415,7 @@ pub const Value = extern union {
23712415 }
23722416
23732417 if (ty.isAnyFloat()) {
2374 return floatSub(lhs, rhs, ty, arena);
2418 return floatSub(lhs, rhs, ty, arena, target);
23752419 }
23762420
23772421 const overflow_result = try intSubWithOverflow(lhs, rhs, ty, arena, target);
......@@ -2454,7 +2498,7 @@ pub const Value = extern union {
24542498 }
24552499
24562500 if (ty.isAnyFloat()) {
2457 return floatMul(lhs, rhs, ty, arena);
2501 return floatMul(lhs, rhs, ty, arena, target);
24582502 }
24592503
24602504 const overflow_result = try intMulWithOverflow(lhs, rhs, ty, arena, target);
......@@ -2753,23 +2797,84 @@ pub const Value = extern union {
27532797 .float_16 => std.math.isNan(val.castTag(.float_16).?.data),
27542798 .float_32 => std.math.isNan(val.castTag(.float_32).?.data),
27552799 .float_64 => std.math.isNan(val.castTag(.float_64).?.data),
2800 .float_80 => std.math.isNan(val.castTag(.float_80).?.data),
27562801 .float_128 => std.math.isNan(val.castTag(.float_128).?.data),
27572802 else => false,
27582803 };
27592804 }
27602805
2761 pub fn floatRem(lhs: Value, rhs: Value, allocator: Allocator) !Value {
2762 _ = lhs;
2763 _ = rhs;
2764 _ = allocator;
2765 @panic("TODO implement Value.floatRem");
2806 pub fn floatRem(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {
2807 switch (float_type.floatBits(target)) {
2808 16 => {
2809 const lhs_val = lhs.toFloat(f16);
2810 const rhs_val = rhs.toFloat(f16);
2811 return Value.Tag.float_16.create(arena, @rem(lhs_val, rhs_val));
2812 },
2813 32 => {
2814 const lhs_val = lhs.toFloat(f32);
2815 const rhs_val = rhs.toFloat(f32);
2816 return Value.Tag.float_32.create(arena, @rem(lhs_val, rhs_val));
2817 },
2818 64 => {
2819 const lhs_val = lhs.toFloat(f64);
2820 const rhs_val = rhs.toFloat(f64);
2821 return Value.Tag.float_64.create(arena, @rem(lhs_val, rhs_val));
2822 },
2823 80 => {
2824 if (true) {
2825 @panic("TODO implement compiler_rt __remx");
2826 }
2827 const lhs_val = lhs.toFloat(f80);
2828 const rhs_val = rhs.toFloat(f80);
2829 return Value.Tag.float_80.create(arena, @rem(lhs_val, rhs_val));
2830 },
2831 128 => {
2832 if (true) {
2833 @panic("TODO implement compiler_rt fmodl");
2834 }
2835 const lhs_val = lhs.toFloat(f128);
2836 const rhs_val = rhs.toFloat(f128);
2837 return Value.Tag.float_128.create(arena, @rem(lhs_val, rhs_val));
2838 },
2839 else => unreachable,
2840 }
27662841 }
27672842
2768 pub fn floatMod(lhs: Value, rhs: Value, allocator: Allocator) !Value {
2769 _ = lhs;
2770 _ = rhs;
2771 _ = allocator;
2772 @panic("TODO implement Value.floatMod");
2843 pub fn floatMod(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {
2844 switch (float_type.floatBits(target)) {
2845 16 => {
2846 const lhs_val = lhs.toFloat(f16);
2847 const rhs_val = rhs.toFloat(f16);
2848 return Value.Tag.float_16.create(arena, @mod(lhs_val, rhs_val));
2849 },
2850 32 => {
2851 const lhs_val = lhs.toFloat(f32);
2852 const rhs_val = rhs.toFloat(f32);
2853 return Value.Tag.float_32.create(arena, @mod(lhs_val, rhs_val));
2854 },
2855 64 => {
2856 const lhs_val = lhs.toFloat(f64);
2857 const rhs_val = rhs.toFloat(f64);
2858 return Value.Tag.float_64.create(arena, @mod(lhs_val, rhs_val));
2859 },
2860 80 => {
2861 if (true) {
2862 @panic("TODO implement compiler_rt __modx");
2863 }
2864 const lhs_val = lhs.toFloat(f80);
2865 const rhs_val = rhs.toFloat(f80);
2866 return Value.Tag.float_80.create(arena, @mod(lhs_val, rhs_val));
2867 },
2868 128 => {
2869 if (true) {
2870 @panic("TODO implement compiler_rt fmodl");
2871 }
2872 const lhs_val = lhs.toFloat(f128);
2873 const rhs_val = rhs.toFloat(f128);
2874 return Value.Tag.float_128.create(arena, @mod(lhs_val, rhs_val));
2875 },
2876 else => unreachable,
2877 }
27732878 }
27742879
27752880 pub fn intMul(lhs: Value, rhs: Value, allocator: Allocator) !Value {
......@@ -2929,24 +3034,30 @@ pub const Value = extern union {
29293034 rhs: Value,
29303035 float_type: Type,
29313036 arena: Allocator,
3037 target: Target,
29323038 ) !Value {
2933 switch (float_type.tag()) {
2934 .f16 => {
3039 switch (float_type.floatBits(target)) {
3040 16 => {
29353041 const lhs_val = lhs.toFloat(f16);
29363042 const rhs_val = rhs.toFloat(f16);
29373043 return Value.Tag.float_16.create(arena, lhs_val + rhs_val);
29383044 },
2939 .f32 => {
3045 32 => {
29403046 const lhs_val = lhs.toFloat(f32);
29413047 const rhs_val = rhs.toFloat(f32);
29423048 return Value.Tag.float_32.create(arena, lhs_val + rhs_val);
29433049 },
2944 .f64 => {
3050 64 => {
29453051 const lhs_val = lhs.toFloat(f64);
29463052 const rhs_val = rhs.toFloat(f64);
29473053 return Value.Tag.float_64.create(arena, lhs_val + rhs_val);
29483054 },
2949 .f128, .comptime_float, .c_longdouble => {
3055 80 => {
3056 const lhs_val = lhs.toFloat(f80);
3057 const rhs_val = rhs.toFloat(f80);
3058 return Value.Tag.float_80.create(arena, lhs_val + rhs_val);
3059 },
3060 128 => {
29503061 const lhs_val = lhs.toFloat(f128);
29513062 const rhs_val = rhs.toFloat(f128);
29523063 return Value.Tag.float_128.create(arena, lhs_val + rhs_val);
......@@ -2960,24 +3071,30 @@ pub const Value = extern union {
29603071 rhs: Value,
29613072 float_type: Type,
29623073 arena: Allocator,
3074 target: Target,
29633075 ) !Value {
2964 switch (float_type.tag()) {
2965 .f16 => {
3076 switch (float_type.floatBits(target)) {
3077 16 => {
29663078 const lhs_val = lhs.toFloat(f16);
29673079 const rhs_val = rhs.toFloat(f16);
29683080 return Value.Tag.float_16.create(arena, lhs_val - rhs_val);
29693081 },
2970 .f32 => {
3082 32 => {
29713083 const lhs_val = lhs.toFloat(f32);
29723084 const rhs_val = rhs.toFloat(f32);
29733085 return Value.Tag.float_32.create(arena, lhs_val - rhs_val);
29743086 },
2975 .f64 => {
3087 64 => {
29763088 const lhs_val = lhs.toFloat(f64);
29773089 const rhs_val = rhs.toFloat(f64);
29783090 return Value.Tag.float_64.create(arena, lhs_val - rhs_val);
29793091 },
2980 .f128, .comptime_float, .c_longdouble => {
3092 80 => {
3093 const lhs_val = lhs.toFloat(f80);
3094 const rhs_val = rhs.toFloat(f80);
3095 return Value.Tag.float_80.create(arena, lhs_val - rhs_val);
3096 },
3097 128 => {
29813098 const lhs_val = lhs.toFloat(f128);
29823099 const rhs_val = rhs.toFloat(f128);
29833100 return Value.Tag.float_128.create(arena, lhs_val - rhs_val);
......@@ -2991,24 +3108,33 @@ pub const Value = extern union {
29913108 rhs: Value,
29923109 float_type: Type,
29933110 arena: Allocator,
3111 target: Target,
29943112 ) !Value {
2995 switch (float_type.tag()) {
2996 .f16 => {
3113 switch (float_type.floatBits(target)) {
3114 16 => {
29973115 const lhs_val = lhs.toFloat(f16);
29983116 const rhs_val = rhs.toFloat(f16);
29993117 return Value.Tag.float_16.create(arena, lhs_val / rhs_val);
30003118 },
3001 .f32 => {
3119 32 => {
30023120 const lhs_val = lhs.toFloat(f32);
30033121 const rhs_val = rhs.toFloat(f32);
30043122 return Value.Tag.float_32.create(arena, lhs_val / rhs_val);
30053123 },
3006 .f64 => {
3124 64 => {
30073125 const lhs_val = lhs.toFloat(f64);
30083126 const rhs_val = rhs.toFloat(f64);
30093127 return Value.Tag.float_64.create(arena, lhs_val / rhs_val);
30103128 },
3011 .f128, .comptime_float, .c_longdouble => {
3129 80 => {
3130 if (true) {
3131 @panic("TODO implement compiler_rt __divxf3");
3132 }
3133 const lhs_val = lhs.toFloat(f80);
3134 const rhs_val = rhs.toFloat(f80);
3135 return Value.Tag.float_80.create(arena, lhs_val / rhs_val);
3136 },
3137 128 => {
30123138 const lhs_val = lhs.toFloat(f128);
30133139 const rhs_val = rhs.toFloat(f128);
30143140 return Value.Tag.float_128.create(arena, lhs_val / rhs_val);
......@@ -3022,24 +3148,33 @@ pub const Value = extern union {
30223148 rhs: Value,
30233149 float_type: Type,
30243150 arena: Allocator,
3151 target: Target,
30253152 ) !Value {
3026 switch (float_type.tag()) {
3027 .f16 => {
3153 switch (float_type.floatBits(target)) {
3154 16 => {
30283155 const lhs_val = lhs.toFloat(f16);
30293156 const rhs_val = rhs.toFloat(f16);
30303157 return Value.Tag.float_16.create(arena, @divFloor(lhs_val, rhs_val));
30313158 },
3032 .f32 => {
3159 32 => {
30333160 const lhs_val = lhs.toFloat(f32);
30343161 const rhs_val = rhs.toFloat(f32);
30353162 return Value.Tag.float_32.create(arena, @divFloor(lhs_val, rhs_val));
30363163 },
3037 .f64 => {
3164 64 => {
30383165 const lhs_val = lhs.toFloat(f64);
30393166 const rhs_val = rhs.toFloat(f64);
30403167 return Value.Tag.float_64.create(arena, @divFloor(lhs_val, rhs_val));
30413168 },
3042 .f128, .comptime_float, .c_longdouble => {
3169 80 => {
3170 if (true) {
3171 @panic("TODO implement compiler_rt __floorx");
3172 }
3173 const lhs_val = lhs.toFloat(f80);
3174 const rhs_val = rhs.toFloat(f80);
3175 return Value.Tag.float_80.create(arena, @divFloor(lhs_val, rhs_val));
3176 },
3177 128 => {
30433178 const lhs_val = lhs.toFloat(f128);
30443179 const rhs_val = rhs.toFloat(f128);
30453180 return Value.Tag.float_128.create(arena, @divFloor(lhs_val, rhs_val));
......@@ -3053,24 +3188,33 @@ pub const Value = extern union {
30533188 rhs: Value,
30543189 float_type: Type,
30553190 arena: Allocator,
3191 target: Target,
30563192 ) !Value {
3057 switch (float_type.tag()) {
3058 .f16 => {
3193 switch (float_type.floatBits(target)) {
3194 16 => {
30593195 const lhs_val = lhs.toFloat(f16);
30603196 const rhs_val = rhs.toFloat(f16);
30613197 return Value.Tag.float_16.create(arena, @divTrunc(lhs_val, rhs_val));
30623198 },
3063 .f32 => {
3199 32 => {
30643200 const lhs_val = lhs.toFloat(f32);
30653201 const rhs_val = rhs.toFloat(f32);
30663202 return Value.Tag.float_32.create(arena, @divTrunc(lhs_val, rhs_val));
30673203 },
3068 .f64 => {
3204 64 => {
30693205 const lhs_val = lhs.toFloat(f64);
30703206 const rhs_val = rhs.toFloat(f64);
30713207 return Value.Tag.float_64.create(arena, @divTrunc(lhs_val, rhs_val));
30723208 },
3073 .f128, .comptime_float, .c_longdouble => {
3209 80 => {
3210 if (true) {
3211 @panic("TODO implement compiler_rt __truncx");
3212 }
3213 const lhs_val = lhs.toFloat(f80);
3214 const rhs_val = rhs.toFloat(f80);
3215 return Value.Tag.float_80.create(arena, @divTrunc(lhs_val, rhs_val));
3216 },
3217 128 => {
30743218 const lhs_val = lhs.toFloat(f128);
30753219 const rhs_val = rhs.toFloat(f128);
30763220 return Value.Tag.float_128.create(arena, @divTrunc(lhs_val, rhs_val));
......@@ -3084,24 +3228,33 @@ pub const Value = extern union {
30843228 rhs: Value,
30853229 float_type: Type,
30863230 arena: Allocator,
3231 target: Target,
30873232 ) !Value {
3088 switch (float_type.tag()) {
3089 .f16 => {
3233 switch (float_type.floatBits(target)) {
3234 16 => {
30903235 const lhs_val = lhs.toFloat(f16);
30913236 const rhs_val = rhs.toFloat(f16);
30923237 return Value.Tag.float_16.create(arena, lhs_val * rhs_val);
30933238 },
3094 .f32 => {
3239 32 => {
30953240 const lhs_val = lhs.toFloat(f32);
30963241 const rhs_val = rhs.toFloat(f32);
30973242 return Value.Tag.float_32.create(arena, lhs_val * rhs_val);
30983243 },
3099 .f64 => {
3244 64 => {
31003245 const lhs_val = lhs.toFloat(f64);
31013246 const rhs_val = rhs.toFloat(f64);
31023247 return Value.Tag.float_64.create(arena, lhs_val * rhs_val);
31033248 },
3104 .f128, .comptime_float, .c_longdouble => {
3249 80 => {
3250 if (true) {
3251 @panic("TODO implement compiler_rt __mulxf3");
3252 }
3253 const lhs_val = lhs.toFloat(f80);
3254 const rhs_val = rhs.toFloat(f80);
3255 return Value.Tag.float_80.create(arena, lhs_val * rhs_val);
3256 },
3257 128 => {
31053258 const lhs_val = lhs.toFloat(f128);
31063259 const rhs_val = rhs.toFloat(f128);
31073260 return Value.Tag.float_128.create(arena, lhs_val * rhs_val);
......@@ -3250,6 +3403,13 @@ pub const Value = extern union {
32503403 data: f64,
32513404 };
32523405
3406 pub const Float_80 = struct {
3407 pub const base_tag = Tag.float_80;
3408
3409 base: Payload = .{ .tag = base_tag },
3410 data: f80,
3411 };
3412
32533413 pub const Float_128 = struct {
32543414 pub const base_tag = Tag.float_128;
32553415
test/behavior/math.zig-2
......@@ -768,8 +768,6 @@ test "shift left/right on u0 operand" {
768768}
769769
770770test "comptime float rem int" {
771 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
772
773771 comptime {
774772 var x = @as(f32, 1) % 2;
775773 try expect(x == 1.0);