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 {...@@ -339,7 +339,7 @@ pub fn __addxf3(a: f80, b: f80) callconv(.C) f80 {
339 // If partial cancellation occurred, we need to left-shift the result339 // If partial cancellation occurred, we need to left-shift the result
340 // and adjust the exponent:340 // and adjust the exponent:
341 if (a_int < int_bit << 3) {341 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));
343 a_int <<= @intCast(u7, shift);343 a_int <<= @intCast(u7, shift);
344 a_exp -= shift;344 a_exp -= shift;
345 }345 }
src/AstGen.zig+7-5
...@@ -2601,8 +2601,8 @@ fn varDecl(...@@ -2601,8 +2601,8 @@ fn varDecl(
26012601
2602 var resolve_inferred_alloc: Zir.Inst.Ref = .none;2602 var resolve_inferred_alloc: Zir.Inst.Ref = .none;
2603 var opt_type_inst: Zir.Inst.Ref = .none;2603 var opt_type_inst: Zir.Inst.Ref = .none;
2604 if (var_decl.ast.type_node != 0) {2604 if (type_node != 0) {
2605 const type_inst = try typeExpr(gz, &init_scope.base, var_decl.ast.type_node);2605 const type_inst = try typeExpr(gz, &init_scope.base, type_node);
2606 opt_type_inst = type_inst;2606 opt_type_inst = type_inst;
2607 if (align_inst == .none) {2607 if (align_inst == .none) {
2608 init_scope.instructions_top = gz.instructions.items.len;2608 init_scope.instructions_top = gz.instructions.items.len;
...@@ -2683,7 +2683,7 @@ fn varDecl(...@@ -2683,7 +2683,7 @@ fn varDecl(
2683 const src_inst = gz.instructions.items[src];2683 const src_inst = gz.instructions.items[src];
2684 if (zir_tags[src_inst] == .store_to_block_ptr) {2684 if (zir_tags[src_inst] == .store_to_block_ptr) {
2685 if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) {2685 if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) {
2686 if (var_decl.ast.type_node != 0) {2686 if (type_node != 0) {
2687 zir_tags[src_inst] = .store;2687 zir_tags[src_inst] = .store;
2688 } else {2688 } else {
2689 zir_tags[src_inst] = .store_to_inferred_ptr;2689 zir_tags[src_inst] = .store_to_inferred_ptr;
...@@ -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
...@@ -8188,7 +8188,7 @@ fn analyzeArithmetic(...@@ -8188,7 +8188,7 @@ fn analyzeArithmetic(
8188 } else {8188 } else {
8189 return sema.addConstant(8189 return sema.addConstant(
8190 scalar_type,8190 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),
8192 );8192 );
8193 }8193 }
8194 } else break :rs .{ .src = rhs_src, .air_tag = .add };8194 } else break :rs .{ .src = rhs_src, .air_tag = .add };
...@@ -8281,7 +8281,7 @@ fn analyzeArithmetic(...@@ -8281,7 +8281,7 @@ fn analyzeArithmetic(
8281 } else {8281 } else {
8282 return sema.addConstant(8282 return sema.addConstant(
8283 scalar_type,8283 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),
8285 );8285 );
8286 }8286 }
8287 } else break :rs .{ .src = rhs_src, .air_tag = .sub };8287 } else break :rs .{ .src = rhs_src, .air_tag = .sub };
...@@ -8397,7 +8397,7 @@ fn analyzeArithmetic(...@@ -8397,7 +8397,7 @@ fn analyzeArithmetic(
8397 } else {8397 } else {
8398 return sema.addConstant(8398 return sema.addConstant(
8399 scalar_type,8399 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),
8401 );8401 );
8402 }8402 }
8403 } else {8403 } else {
...@@ -8472,7 +8472,7 @@ fn analyzeArithmetic(...@@ -8472,7 +8472,7 @@ fn analyzeArithmetic(
8472 } else {8472 } else {
8473 return sema.addConstant(8473 return sema.addConstant(
8474 scalar_type,8474 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),
8476 );8476 );
8477 }8477 }
8478 } else break :rs .{ .src = rhs_src, .air_tag = .div_trunc };8478 } else break :rs .{ .src = rhs_src, .air_tag = .div_trunc };
...@@ -8535,7 +8535,7 @@ fn analyzeArithmetic(...@@ -8535,7 +8535,7 @@ fn analyzeArithmetic(
8535 } else {8535 } else {
8536 return sema.addConstant(8536 return sema.addConstant(
8537 scalar_type,8537 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),
8539 );8539 );
8540 }8540 }
8541 } else break :rs .{ .src = rhs_src, .air_tag = .div_floor };8541 } else break :rs .{ .src = rhs_src, .air_tag = .div_floor };
...@@ -8587,7 +8587,7 @@ fn analyzeArithmetic(...@@ -8587,7 +8587,7 @@ fn analyzeArithmetic(
8587 // TODO: emit compile error if there is a remainder8587 // TODO: emit compile error if there is a remainder
8588 return sema.addConstant(8588 return sema.addConstant(
8589 scalar_type,8589 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),
8591 );8591 );
8592 }8592 }
8593 } else break :rs .{ .src = rhs_src, .air_tag = .div_exact };8593 } else break :rs .{ .src = rhs_src, .air_tag = .div_exact };
...@@ -8642,7 +8642,7 @@ fn analyzeArithmetic(...@@ -8642,7 +8642,7 @@ fn analyzeArithmetic(
8642 } else {8642 } else {
8643 return sema.addConstant(8643 return sema.addConstant(
8644 scalar_type,8644 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),
8646 );8646 );
8647 }8647 }
8648 } else break :rs .{ .src = lhs_src, .air_tag = .mul };8648 } else break :rs .{ .src = lhs_src, .air_tag = .mul };
...@@ -8798,7 +8798,7 @@ fn analyzeArithmetic(...@@ -8798,7 +8798,7 @@ fn analyzeArithmetic(
8798 }8798 }
8799 return sema.addConstant(8799 return sema.addConstant(
8800 scalar_type,8800 scalar_type,
8801 try lhs_val.floatRem(rhs_val, sema.arena),8801 try lhs_val.floatRem(rhs_val, scalar_type, sema.arena, target),
8802 );8802 );
8803 } else {8803 } else {
8804 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);8804 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
...@@ -8859,7 +8859,7 @@ fn analyzeArithmetic(...@@ -8859,7 +8859,7 @@ fn analyzeArithmetic(
8859 if (maybe_rhs_val) |rhs_val| {8859 if (maybe_rhs_val) |rhs_val| {
8860 return sema.addConstant(8860 return sema.addConstant(
8861 scalar_type,8861 scalar_type,
8862 try lhs_val.floatRem(rhs_val, sema.arena),8862 try lhs_val.floatRem(rhs_val, scalar_type, sema.arena, target),
8863 );8863 );
8864 } else break :rs .{ .src = rhs_src, .air_tag = .rem };8864 } else break :rs .{ .src = rhs_src, .air_tag = .rem };
8865 } else break :rs .{ .src = lhs_src, .air_tag = .rem };8865 } else break :rs .{ .src = lhs_src, .air_tag = .rem };
...@@ -8916,7 +8916,7 @@ fn analyzeArithmetic(...@@ -8916,7 +8916,7 @@ fn analyzeArithmetic(
8916 if (maybe_rhs_val) |rhs_val| {8916 if (maybe_rhs_val) |rhs_val| {
8917 return sema.addConstant(8917 return sema.addConstant(
8918 scalar_type,8918 scalar_type,
8919 try lhs_val.floatMod(rhs_val, sema.arena),8919 try lhs_val.floatMod(rhs_val, scalar_type, sema.arena, target),
8920 );8920 );
8921 } else break :rs .{ .src = rhs_src, .air_tag = .mod };8921 } else break :rs .{ .src = rhs_src, .air_tag = .mod };
8922 } else break :rs .{ .src = lhs_src, .air_tag = .mod };8922 } else break :rs .{ .src = lhs_src, .air_tag = .mod };
...@@ -14196,12 +14196,12 @@ fn coerce(...@@ -14196,12 +14196,12 @@ fn coerce(
14196 .Float, .ComptimeFloat => switch (inst_ty.zigTypeTag()) {14196 .Float, .ComptimeFloat => switch (inst_ty.zigTypeTag()) {
14197 .ComptimeFloat => {14197 .ComptimeFloat => {
14198 const val = try sema.resolveConstValue(block, inst_src, inst);14198 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);
14200 return try sema.addConstant(dest_ty, result_val);14200 return try sema.addConstant(dest_ty, result_val);
14201 },14201 },
14202 .Float => {14202 .Float => {
14203 if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| {14203 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);
14205 if (!val.eql(result_val, dest_ty)) {14205 if (!val.eql(result_val, dest_ty)) {
14206 return sema.fail(14206 return sema.fail(
14207 block,14207 block,
src/stage1/codegen.cpp+5-2
...@@ -9432,11 +9432,14 @@ static void define_builtin_types(CodeGen *g) {...@@ -9432,11 +9432,14 @@ static void define_builtin_types(CodeGen *g) {
9432 if (target_has_f80(g->zig_target)) {9432 if (target_has_f80(g->zig_target)) {
9433 entry->llvm_type = LLVMX86FP80Type();9433 entry->llvm_type = LLVMX86FP80Type();
9434 } else {9434 } 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.
9435 entry->llvm_type = get_int_type(g, false, 128)->llvm_type;9438 entry->llvm_type = get_int_type(g, false, 128)->llvm_type;
9436 }9439 }
9437 entry->size_in_bits = 8 * 16;9440 entry->size_in_bits = 8 * 16;
9438 entry->abi_size = 16;9441 entry->abi_size = 16; // matches LLVMABISizeOfType(LLVMX86FP80Type())
9439 entry->abi_align = 16;9442 entry->abi_align = 16; // matches LLVMABIAlignmentOfType(LLVMX86FP80Type())
9440 buf_init_from_str(&entry->name, "f80");9443 buf_init_from_str(&entry->name, "f80");
9441 entry->data.floating.bit_count = 80;9444 entry->data.floating.bit_count = 80;
94429445
src/value.zig+215-55
...@@ -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
...@@ -1029,6 +1033,11 @@ pub const Value = extern union {...@@ -1029,6 +1033,11 @@ pub const Value = extern union {
1029 }1033 }
10301034
1031 pub fn writeToMemory(val: Value, ty: Type, target: Target, buffer: []u8) void {1035 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 }
1032 switch (ty.zigTypeTag()) {1041 switch (ty.zigTypeTag()) {
1033 .Int => {1042 .Int => {
1034 var bigint_buffer: BigIntSpace = undefined;1043 var bigint_buffer: BigIntSpace = undefined;
...@@ -1064,6 +1073,14 @@ pub const Value = extern union {...@@ -1064,6 +1073,14 @@ pub const Value = extern union {
1064 buf_off += elem_size;1073 buf_off += elem_size;
1065 }1074 }
1066 },1075 },
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 },
1067 else => @panic("TODO implement writeToMemory for more types"),1084 else => @panic("TODO implement writeToMemory for more types"),
1068 }1085 }
1069 }1086 }
...@@ -1083,6 +1100,7 @@ pub const Value = extern union {...@@ -1083,6 +1100,7 @@ pub const Value = extern union {
1083 16 => return Value.Tag.float_16.create(arena, floatReadFromMemory(f16, target, buffer)),1100 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)),1101 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)),1102 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)),
1086 128 => return Value.Tag.float_128.create(arena, floatReadFromMemory(f128, target, buffer)),1104 128 => return Value.Tag.float_128.create(arena, floatReadFromMemory(f128, target, buffer)),
1087 else => unreachable,1105 else => unreachable,
1088 },1106 },
...@@ -1100,6 +1118,12 @@ pub const Value = extern union {...@@ -1100,6 +1118,12 @@ pub const Value = extern union {
1100 }1118 }
11011119
1102 fn floatReadFromMemory(comptime F: type, target: Target, buffer: []const u8) F {1120 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 }
1103 const Int = @Type(.{ .Int = .{1127 const Int = @Type(.{ .Int = .{
1104 .signedness = .unsigned,1128 .signedness = .unsigned,
1105 .bits = @typeInfo(F).Float.bits,1129 .bits = @typeInfo(F).Float.bits,
...@@ -1114,12 +1138,23 @@ pub const Value = extern union {...@@ -1114,12 +1138,23 @@ pub const Value = extern union {
1114 .float_16 => @floatCast(T, val.castTag(.float_16).?.data),1138 .float_16 => @floatCast(T, val.castTag(.float_16).?.data),
1115 .float_32 => @floatCast(T, val.castTag(.float_32).?.data),1139 .float_32 => @floatCast(T, val.castTag(.float_32).?.data),
1116 .float_64 => @floatCast(T, val.castTag(.float_64).?.data),1140 .float_64 => @floatCast(T, val.castTag(.float_64).?.data),
1141 .float_80 => @floatCast(T, val.castTag(.float_80).?.data),
1117 .float_128 => @floatCast(T, val.castTag(.float_128).?.data),1142 .float_128 => @floatCast(T, val.castTag(.float_128).?.data),
11181143
1119 .zero => 0,1144 .zero => 0,
1120 .one => 1,1145 .one => 1,
1121 .int_u64 => @intToFloat(T, val.castTag(.int_u64).?.data),1146 .int_u64 => {
1122 .int_i64 => @intToFloat(T, val.castTag(.int_i64).?.data),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
1124 .int_big_positive => @floatCast(T, bigIntToFloat(val.castTag(.int_big_positive).?.data, true)),1159 .int_big_positive => @floatCast(T, bigIntToFloat(val.castTag(.int_big_positive).?.data, true)),
1125 .int_big_negative => @floatCast(T, bigIntToFloat(val.castTag(.int_big_negative).?.data, false)),1160 .int_big_negative => @floatCast(T, bigIntToFloat(val.castTag(.int_big_negative).?.data, false)),
...@@ -1367,14 +1402,13 @@ pub const Value = extern union {...@@ -1367,14 +1402,13 @@ pub const Value = extern union {
13671402
1368 /// Converts an integer or a float to a float. May result in a loss of information.1403 /// 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.1404 /// Caller can find out by equality checking the result against the operand.
1370 pub fn floatCast(self: Value, arena: Allocator, dest_ty: Type) !Value {1405 pub fn floatCast(self: Value, arena: Allocator, dest_ty: Type, target: Target) !Value {
1371 switch (dest_ty.tag()) {1406 switch (dest_ty.floatBits(target)) {
1372 .f16 => return Value.Tag.float_16.create(arena, self.toFloat(f16)),1407 16 => return Value.Tag.float_16.create(arena, self.toFloat(f16)),
1373 .f32 => return Value.Tag.float_32.create(arena, self.toFloat(f32)),1408 32 => return Value.Tag.float_32.create(arena, self.toFloat(f32)),
1374 .f64 => return Value.Tag.float_64.create(arena, self.toFloat(f64)),1409 64 => return Value.Tag.float_64.create(arena, self.toFloat(f64)),
1375 .f128, .comptime_float, .c_longdouble => {1410 80 => return Value.Tag.float_80.create(arena, self.toFloat(f80)),
1376 return Value.Tag.float_128.create(arena, self.toFloat(f128));1411 128 => return Value.Tag.float_128.create(arena, self.toFloat(f128)),
1377 },
1378 else => unreachable,1412 else => unreachable,
1379 }1413 }
1380 }1414 }
...@@ -1389,8 +1423,10 @@ pub const Value = extern union {...@@ -1389,8 +1423,10 @@ pub const Value = extern union {
1389 .float_16 => @rem(self.castTag(.float_16).?.data, 1) != 0,1423 .float_16 => @rem(self.castTag(.float_16).?.data, 1) != 0,
1390 .float_32 => @rem(self.castTag(.float_32).?.data, 1) != 0,1424 .float_32 => @rem(self.castTag(.float_32).?.data, 1) != 0,
1391 .float_64 => @rem(self.castTag(.float_64).?.data, 1) != 0,1425 .float_64 => @rem(self.castTag(.float_64).?.data, 1) != 0,
1392 // .float_128 => @rem(self.castTag(.float_128).?.data, 1) != 0,1426 //.float_80 => @rem(self.castTag(.float_80).?.data, 1) != 0,
1393 .float_128 => @panic("TODO lld: error: undefined symbol: fmodl"),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
1395 else => unreachable,1431 else => unreachable,
1396 };1432 };
...@@ -1408,6 +1444,7 @@ pub const Value = extern union {...@@ -1408,6 +1444,7 @@ pub const Value = extern union {
1408 .float_16 => self.castTag(.float_16).?.data == 0,1444 .float_16 => self.castTag(.float_16).?.data == 0,
1409 .float_32 => self.castTag(.float_32).?.data == 0,1445 .float_32 => self.castTag(.float_32).?.data == 0,
1410 .float_64 => self.castTag(.float_64).?.data == 0,1446 .float_64 => self.castTag(.float_64).?.data == 0,
1447 .float_80 => self.castTag(.float_80).?.data == 0,
1411 .float_128 => self.castTag(.float_128).?.data == 0,1448 .float_128 => self.castTag(.float_128).?.data == 0,
14121449
1413 .int_big_positive => self.castTag(.int_big_positive).?.asBigInt().eqZero(),1450 .int_big_positive => self.castTag(.int_big_positive).?.asBigInt().eqZero(),
...@@ -1440,6 +1477,7 @@ pub const Value = extern union {...@@ -1440,6 +1477,7 @@ pub const Value = extern union {
1440 .float_16 => std.math.order(lhs.castTag(.float_16).?.data, 0),1477 .float_16 => std.math.order(lhs.castTag(.float_16).?.data, 0),
1441 .float_32 => std.math.order(lhs.castTag(.float_32).?.data, 0),1478 .float_32 => std.math.order(lhs.castTag(.float_32).?.data, 0),
1442 .float_64 => std.math.order(lhs.castTag(.float_64).?.data, 0),1479 .float_64 => std.math.order(lhs.castTag(.float_64).?.data, 0),
1480 .float_80 => std.math.order(lhs.castTag(.float_80).?.data, 0),
1443 .float_128 => std.math.order(lhs.castTag(.float_128).?.data, 0),1481 .float_128 => std.math.order(lhs.castTag(.float_128).?.data, 0),
14441482
1445 else => unreachable,1483 else => unreachable,
...@@ -1471,6 +1509,7 @@ pub const Value = extern union {...@@ -1471,6 +1509,7 @@ pub const Value = extern union {
1471 .float_16 => return std.math.order(lhs.castTag(.float_16).?.data, rhs.castTag(.float_16).?.data),1509 .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),1510 .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),1511 .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),
1474 .float_128 => return std.math.order(lhs.castTag(.float_128).?.data, rhs.castTag(.float_128).?.data),1513 .float_128 => return std.math.order(lhs.castTag(.float_128).?.data, rhs.castTag(.float_128).?.data),
1475 else => unreachable,1514 else => unreachable,
1476 };1515 };
...@@ -2139,6 +2178,7 @@ pub const Value = extern union {...@@ -2139,6 +2178,7 @@ pub const Value = extern union {
2139 .float_16,2178 .float_16,
2140 .float_32,2179 .float_32,
2141 .float_64,2180 .float_64,
2181 .float_80,
2142 .float_128,2182 .float_128,
2143 => true,2183 => true,
2144 else => false,2184 else => false,
...@@ -2174,6 +2214,9 @@ pub const Value = extern union {...@@ -2174,6 +2214,9 @@ pub const Value = extern union {
2174 16 => return Value.Tag.float_16.create(arena, @intToFloat(f16, x)),2214 16 => return Value.Tag.float_16.create(arena, @intToFloat(f16, x)),
2175 32 => return Value.Tag.float_32.create(arena, @intToFloat(f32, x)),2215 32 => return Value.Tag.float_32.create(arena, @intToFloat(f32, x)),
2176 64 => return Value.Tag.float_64.create(arena, @intToFloat(f64, x)),2216 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"),
2177 128 => return Value.Tag.float_128.create(arena, @intToFloat(f128, x)),2220 128 => return Value.Tag.float_128.create(arena, @intToFloat(f128, x)),
2178 else => unreachable,2221 else => unreachable,
2179 }2222 }
...@@ -2184,6 +2227,7 @@ pub const Value = extern union {...@@ -2184,6 +2227,7 @@ pub const Value = extern union {
2184 16 => return Value.Tag.float_16.create(arena, @floatCast(f16, float)),2227 16 => return Value.Tag.float_16.create(arena, @floatCast(f16, float)),
2185 32 => return Value.Tag.float_32.create(arena, @floatCast(f32, float)),2228 32 => return Value.Tag.float_32.create(arena, @floatCast(f32, float)),
2186 64 => return Value.Tag.float_64.create(arena, @floatCast(f64, float)),2229 64 => return Value.Tag.float_64.create(arena, @floatCast(f64, float)),
2230 80 => return Value.Tag.float_80.create(arena, @floatCast(f80, float)),
2187 128 => return Value.Tag.float_128.create(arena, float),2231 128 => return Value.Tag.float_128.create(arena, float),
2188 else => unreachable,2232 else => unreachable,
2189 }2233 }
...@@ -2281,7 +2325,7 @@ pub const Value = extern union {...@@ -2281,7 +2325,7 @@ pub const Value = extern union {
2281 }2325 }
22822326
2283 if (ty.isAnyFloat()) {2327 if (ty.isAnyFloat()) {
2284 return floatAdd(lhs, rhs, ty, arena);2328 return floatAdd(lhs, rhs, ty, arena, target);
2285 }2329 }
22862330
2287 const overflow_result = try intAddWithOverflow(lhs, rhs, ty, arena, target);2331 const overflow_result = try intAddWithOverflow(lhs, rhs, ty, arena, target);
...@@ -2371,7 +2415,7 @@ pub const Value = extern union {...@@ -2371,7 +2415,7 @@ pub const Value = extern union {
2371 }2415 }
23722416
2373 if (ty.isAnyFloat()) {2417 if (ty.isAnyFloat()) {
2374 return floatSub(lhs, rhs, ty, arena);2418 return floatSub(lhs, rhs, ty, arena, target);
2375 }2419 }
23762420
2377 const overflow_result = try intSubWithOverflow(lhs, rhs, ty, arena, target);2421 const overflow_result = try intSubWithOverflow(lhs, rhs, ty, arena, target);
...@@ -2454,7 +2498,7 @@ pub const Value = extern union {...@@ -2454,7 +2498,7 @@ pub const Value = extern union {
2454 }2498 }
24552499
2456 if (ty.isAnyFloat()) {2500 if (ty.isAnyFloat()) {
2457 return floatMul(lhs, rhs, ty, arena);2501 return floatMul(lhs, rhs, ty, arena, target);
2458 }2502 }
24592503
2460 const overflow_result = try intMulWithOverflow(lhs, rhs, ty, arena, target);2504 const overflow_result = try intMulWithOverflow(lhs, rhs, ty, arena, target);
...@@ -2753,23 +2797,84 @@ pub const Value = extern union {...@@ -2753,23 +2797,84 @@ pub const Value = extern union {
2753 .float_16 => std.math.isNan(val.castTag(.float_16).?.data),2797 .float_16 => std.math.isNan(val.castTag(.float_16).?.data),
2754 .float_32 => std.math.isNan(val.castTag(.float_32).?.data),2798 .float_32 => std.math.isNan(val.castTag(.float_32).?.data),
2755 .float_64 => std.math.isNan(val.castTag(.float_64).?.data),2799 .float_64 => std.math.isNan(val.castTag(.float_64).?.data),
2800 .float_80 => std.math.isNan(val.castTag(.float_80).?.data),
2756 .float_128 => std.math.isNan(val.castTag(.float_128).?.data),2801 .float_128 => std.math.isNan(val.castTag(.float_128).?.data),
2757 else => false,2802 else => false,
2758 };2803 };
2759 }2804 }
27602805
2761 pub fn floatRem(lhs: Value, rhs: Value, allocator: Allocator) !Value {2806 pub fn floatRem(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {
2762 _ = lhs;2807 switch (float_type.floatBits(target)) {
2763 _ = rhs;2808 16 => {
2764 _ = allocator;2809 const lhs_val = lhs.toFloat(f16);
2765 @panic("TODO implement Value.floatRem");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 }
2766 }2841 }
27672842
2768 pub fn floatMod(lhs: Value, rhs: Value, allocator: Allocator) !Value {2843 pub fn floatMod(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {
2769 _ = lhs;2844 switch (float_type.floatBits(target)) {
2770 _ = rhs;2845 16 => {
2771 _ = allocator;2846 const lhs_val = lhs.toFloat(f16);
2772 @panic("TODO implement Value.floatMod");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 }
2773 }2878 }
27742879
2775 pub fn intMul(lhs: Value, rhs: Value, allocator: Allocator) !Value {2880 pub fn intMul(lhs: Value, rhs: Value, allocator: Allocator) !Value {
...@@ -2929,24 +3034,30 @@ pub const Value = extern union {...@@ -2929,24 +3034,30 @@ pub const Value = extern union {
2929 rhs: Value,3034 rhs: Value,
2930 float_type: Type,3035 float_type: Type,
2931 arena: Allocator,3036 arena: Allocator,
3037 target: Target,
2932 ) !Value {3038 ) !Value {
2933 switch (float_type.tag()) {3039 switch (float_type.floatBits(target)) {
2934 .f16 => {3040 16 => {
2935 const lhs_val = lhs.toFloat(f16);3041 const lhs_val = lhs.toFloat(f16);
2936 const rhs_val = rhs.toFloat(f16);3042 const rhs_val = rhs.toFloat(f16);
2937 return Value.Tag.float_16.create(arena, lhs_val + rhs_val);3043 return Value.Tag.float_16.create(arena, lhs_val + rhs_val);
2938 },3044 },
2939 .f32 => {3045 32 => {
2940 const lhs_val = lhs.toFloat(f32);3046 const lhs_val = lhs.toFloat(f32);
2941 const rhs_val = rhs.toFloat(f32);3047 const rhs_val = rhs.toFloat(f32);
2942 return Value.Tag.float_32.create(arena, lhs_val + rhs_val);3048 return Value.Tag.float_32.create(arena, lhs_val + rhs_val);
2943 },3049 },
2944 .f64 => {3050 64 => {
2945 const lhs_val = lhs.toFloat(f64);3051 const lhs_val = lhs.toFloat(f64);
2946 const rhs_val = rhs.toFloat(f64);3052 const rhs_val = rhs.toFloat(f64);
2947 return Value.Tag.float_64.create(arena, lhs_val + rhs_val);3053 return Value.Tag.float_64.create(arena, lhs_val + rhs_val);
2948 },3054 },
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 => {
2950 const lhs_val = lhs.toFloat(f128);3061 const lhs_val = lhs.toFloat(f128);
2951 const rhs_val = rhs.toFloat(f128);3062 const rhs_val = rhs.toFloat(f128);
2952 return Value.Tag.float_128.create(arena, lhs_val + rhs_val);3063 return Value.Tag.float_128.create(arena, lhs_val + rhs_val);
...@@ -2960,24 +3071,30 @@ pub const Value = extern union {...@@ -2960,24 +3071,30 @@ pub const Value = extern union {
2960 rhs: Value,3071 rhs: Value,
2961 float_type: Type,3072 float_type: Type,
2962 arena: Allocator,3073 arena: Allocator,
3074 target: Target,
2963 ) !Value {3075 ) !Value {
2964 switch (float_type.tag()) {3076 switch (float_type.floatBits(target)) {
2965 .f16 => {3077 16 => {
2966 const lhs_val = lhs.toFloat(f16);3078 const lhs_val = lhs.toFloat(f16);
2967 const rhs_val = rhs.toFloat(f16);3079 const rhs_val = rhs.toFloat(f16);
2968 return Value.Tag.float_16.create(arena, lhs_val - rhs_val);3080 return Value.Tag.float_16.create(arena, lhs_val - rhs_val);
2969 },3081 },
2970 .f32 => {3082 32 => {
2971 const lhs_val = lhs.toFloat(f32);3083 const lhs_val = lhs.toFloat(f32);
2972 const rhs_val = rhs.toFloat(f32);3084 const rhs_val = rhs.toFloat(f32);
2973 return Value.Tag.float_32.create(arena, lhs_val - rhs_val);3085 return Value.Tag.float_32.create(arena, lhs_val - rhs_val);
2974 },3086 },
2975 .f64 => {3087 64 => {
2976 const lhs_val = lhs.toFloat(f64);3088 const lhs_val = lhs.toFloat(f64);
2977 const rhs_val = rhs.toFloat(f64);3089 const rhs_val = rhs.toFloat(f64);
2978 return Value.Tag.float_64.create(arena, lhs_val - rhs_val);3090 return Value.Tag.float_64.create(arena, lhs_val - rhs_val);
2979 },3091 },
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 => {
2981 const lhs_val = lhs.toFloat(f128);3098 const lhs_val = lhs.toFloat(f128);
2982 const rhs_val = rhs.toFloat(f128);3099 const rhs_val = rhs.toFloat(f128);
2983 return Value.Tag.float_128.create(arena, lhs_val - rhs_val);3100 return Value.Tag.float_128.create(arena, lhs_val - rhs_val);
...@@ -2991,24 +3108,33 @@ pub const Value = extern union {...@@ -2991,24 +3108,33 @@ pub const Value = extern union {
2991 rhs: Value,3108 rhs: Value,
2992 float_type: Type,3109 float_type: Type,
2993 arena: Allocator,3110 arena: Allocator,
3111 target: Target,
2994 ) !Value {3112 ) !Value {
2995 switch (float_type.tag()) {3113 switch (float_type.floatBits(target)) {
2996 .f16 => {3114 16 => {
2997 const lhs_val = lhs.toFloat(f16);3115 const lhs_val = lhs.toFloat(f16);
2998 const rhs_val = rhs.toFloat(f16);3116 const rhs_val = rhs.toFloat(f16);
2999 return Value.Tag.float_16.create(arena, lhs_val / rhs_val);3117 return Value.Tag.float_16.create(arena, lhs_val / rhs_val);
3000 },3118 },
3001 .f32 => {3119 32 => {
3002 const lhs_val = lhs.toFloat(f32);3120 const lhs_val = lhs.toFloat(f32);
3003 const rhs_val = rhs.toFloat(f32);3121 const rhs_val = rhs.toFloat(f32);
3004 return Value.Tag.float_32.create(arena, lhs_val / rhs_val);3122 return Value.Tag.float_32.create(arena, lhs_val / rhs_val);
3005 },3123 },
3006 .f64 => {3124 64 => {
3007 const lhs_val = lhs.toFloat(f64);3125 const lhs_val = lhs.toFloat(f64);
3008 const rhs_val = rhs.toFloat(f64);3126 const rhs_val = rhs.toFloat(f64);
3009 return Value.Tag.float_64.create(arena, lhs_val / rhs_val);3127 return Value.Tag.float_64.create(arena, lhs_val / rhs_val);
3010 },3128 },
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 => {
3012 const lhs_val = lhs.toFloat(f128);3138 const lhs_val = lhs.toFloat(f128);
3013 const rhs_val = rhs.toFloat(f128);3139 const rhs_val = rhs.toFloat(f128);
3014 return Value.Tag.float_128.create(arena, lhs_val / rhs_val);3140 return Value.Tag.float_128.create(arena, lhs_val / rhs_val);
...@@ -3022,24 +3148,33 @@ pub const Value = extern union {...@@ -3022,24 +3148,33 @@ pub const Value = extern union {
3022 rhs: Value,3148 rhs: Value,
3023 float_type: Type,3149 float_type: Type,
3024 arena: Allocator,3150 arena: Allocator,
3151 target: Target,
3025 ) !Value {3152 ) !Value {
3026 switch (float_type.tag()) {3153 switch (float_type.floatBits(target)) {
3027 .f16 => {3154 16 => {
3028 const lhs_val = lhs.toFloat(f16);3155 const lhs_val = lhs.toFloat(f16);
3029 const rhs_val = rhs.toFloat(f16);3156 const rhs_val = rhs.toFloat(f16);
3030 return Value.Tag.float_16.create(arena, @divFloor(lhs_val, rhs_val));3157 return Value.Tag.float_16.create(arena, @divFloor(lhs_val, rhs_val));
3031 },3158 },
3032 .f32 => {3159 32 => {
3033 const lhs_val = lhs.toFloat(f32);3160 const lhs_val = lhs.toFloat(f32);
3034 const rhs_val = rhs.toFloat(f32);3161 const rhs_val = rhs.toFloat(f32);
3035 return Value.Tag.float_32.create(arena, @divFloor(lhs_val, rhs_val));3162 return Value.Tag.float_32.create(arena, @divFloor(lhs_val, rhs_val));
3036 },3163 },
3037 .f64 => {3164 64 => {
3038 const lhs_val = lhs.toFloat(f64);3165 const lhs_val = lhs.toFloat(f64);
3039 const rhs_val = rhs.toFloat(f64);3166 const rhs_val = rhs.toFloat(f64);
3040 return Value.Tag.float_64.create(arena, @divFloor(lhs_val, rhs_val));3167 return Value.Tag.float_64.create(arena, @divFloor(lhs_val, rhs_val));
3041 },3168 },
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 => {
3043 const lhs_val = lhs.toFloat(f128);3178 const lhs_val = lhs.toFloat(f128);
3044 const rhs_val = rhs.toFloat(f128);3179 const rhs_val = rhs.toFloat(f128);
3045 return Value.Tag.float_128.create(arena, @divFloor(lhs_val, rhs_val));3180 return Value.Tag.float_128.create(arena, @divFloor(lhs_val, rhs_val));
...@@ -3053,24 +3188,33 @@ pub const Value = extern union {...@@ -3053,24 +3188,33 @@ pub const Value = extern union {
3053 rhs: Value,3188 rhs: Value,
3054 float_type: Type,3189 float_type: Type,
3055 arena: Allocator,3190 arena: Allocator,
3191 target: Target,
3056 ) !Value {3192 ) !Value {
3057 switch (float_type.tag()) {3193 switch (float_type.floatBits(target)) {
3058 .f16 => {3194 16 => {
3059 const lhs_val = lhs.toFloat(f16);3195 const lhs_val = lhs.toFloat(f16);
3060 const rhs_val = rhs.toFloat(f16);3196 const rhs_val = rhs.toFloat(f16);
3061 return Value.Tag.float_16.create(arena, @divTrunc(lhs_val, rhs_val));3197 return Value.Tag.float_16.create(arena, @divTrunc(lhs_val, rhs_val));
3062 },3198 },
3063 .f32 => {3199 32 => {
3064 const lhs_val = lhs.toFloat(f32);3200 const lhs_val = lhs.toFloat(f32);
3065 const rhs_val = rhs.toFloat(f32);3201 const rhs_val = rhs.toFloat(f32);
3066 return Value.Tag.float_32.create(arena, @divTrunc(lhs_val, rhs_val));3202 return Value.Tag.float_32.create(arena, @divTrunc(lhs_val, rhs_val));
3067 },3203 },
3068 .f64 => {3204 64 => {
3069 const lhs_val = lhs.toFloat(f64);3205 const lhs_val = lhs.toFloat(f64);
3070 const rhs_val = rhs.toFloat(f64);3206 const rhs_val = rhs.toFloat(f64);
3071 return Value.Tag.float_64.create(arena, @divTrunc(lhs_val, rhs_val));3207 return Value.Tag.float_64.create(arena, @divTrunc(lhs_val, rhs_val));
3072 },3208 },
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 => {
3074 const lhs_val = lhs.toFloat(f128);3218 const lhs_val = lhs.toFloat(f128);
3075 const rhs_val = rhs.toFloat(f128);3219 const rhs_val = rhs.toFloat(f128);
3076 return Value.Tag.float_128.create(arena, @divTrunc(lhs_val, rhs_val));3220 return Value.Tag.float_128.create(arena, @divTrunc(lhs_val, rhs_val));
...@@ -3084,24 +3228,33 @@ pub const Value = extern union {...@@ -3084,24 +3228,33 @@ pub const Value = extern union {
3084 rhs: Value,3228 rhs: Value,
3085 float_type: Type,3229 float_type: Type,
3086 arena: Allocator,3230 arena: Allocator,
3231 target: Target,
3087 ) !Value {3232 ) !Value {
3088 switch (float_type.tag()) {3233 switch (float_type.floatBits(target)) {
3089 .f16 => {3234 16 => {
3090 const lhs_val = lhs.toFloat(f16);3235 const lhs_val = lhs.toFloat(f16);
3091 const rhs_val = rhs.toFloat(f16);3236 const rhs_val = rhs.toFloat(f16);
3092 return Value.Tag.float_16.create(arena, lhs_val * rhs_val);3237 return Value.Tag.float_16.create(arena, lhs_val * rhs_val);
3093 },3238 },
3094 .f32 => {3239 32 => {
3095 const lhs_val = lhs.toFloat(f32);3240 const lhs_val = lhs.toFloat(f32);
3096 const rhs_val = rhs.toFloat(f32);3241 const rhs_val = rhs.toFloat(f32);
3097 return Value.Tag.float_32.create(arena, lhs_val * rhs_val);3242 return Value.Tag.float_32.create(arena, lhs_val * rhs_val);
3098 },3243 },
3099 .f64 => {3244 64 => {
3100 const lhs_val = lhs.toFloat(f64);3245 const lhs_val = lhs.toFloat(f64);
3101 const rhs_val = rhs.toFloat(f64);3246 const rhs_val = rhs.toFloat(f64);
3102 return Value.Tag.float_64.create(arena, lhs_val * rhs_val);3247 return Value.Tag.float_64.create(arena, lhs_val * rhs_val);
3103 },3248 },
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 => {
3105 const lhs_val = lhs.toFloat(f128);3258 const lhs_val = lhs.toFloat(f128);
3106 const rhs_val = rhs.toFloat(f128);3259 const rhs_val = rhs.toFloat(f128);
3107 return Value.Tag.float_128.create(arena, lhs_val * rhs_val);3260 return Value.Tag.float_128.create(arena, lhs_val * rhs_val);
...@@ -3250,6 +3403,13 @@ pub const Value = extern union {...@@ -3250,6 +3403,13 @@ pub const Value = extern union {
3250 data: f64,3403 data: f64,
3251 };3404 };
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
3253 pub const Float_128 = struct {3413 pub const Float_128 = struct {
3254 pub const base_tag = Tag.float_128;3414 pub const base_tag = Tag.float_128;
32553415
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);