Merge pull request #10740 from ziglang/stage2-float-arithmetic
stage2: add more float arithmetic and f80 support
This commit is contained in:
@@ -339,7 +339,7 @@ pub fn __addxf3(a: f80, b: f80) callconv(.C) f80 {
|
||||
// If partial cancellation occurred, we need to left-shift the result
|
||||
// and adjust the exponent:
|
||||
if (a_int < int_bit << 3) {
|
||||
const shift = @intCast(i32, @clz(u80, a_int)) - @intCast(i32, @clz(u80, int_bit << 3));
|
||||
const shift = @intCast(i32, @clz(u80, a_int)) - @intCast(i32, @clz(u80, @as(u80, int_bit) << 3));
|
||||
a_int <<= @intCast(u7, shift);
|
||||
a_exp -= shift;
|
||||
}
|
||||
|
||||
@@ -2601,8 +2601,8 @@ fn varDecl(
|
||||
|
||||
var resolve_inferred_alloc: Zir.Inst.Ref = .none;
|
||||
var opt_type_inst: Zir.Inst.Ref = .none;
|
||||
if (var_decl.ast.type_node != 0) {
|
||||
const type_inst = try typeExpr(gz, &init_scope.base, var_decl.ast.type_node);
|
||||
if (type_node != 0) {
|
||||
const type_inst = try typeExpr(gz, &init_scope.base, type_node);
|
||||
opt_type_inst = type_inst;
|
||||
if (align_inst == .none) {
|
||||
init_scope.instructions_top = gz.instructions.items.len;
|
||||
@@ -2683,7 +2683,7 @@ fn varDecl(
|
||||
const src_inst = gz.instructions.items[src];
|
||||
if (zir_tags[src_inst] == .store_to_block_ptr) {
|
||||
if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) {
|
||||
if (var_decl.ast.type_node != 0) {
|
||||
if (type_node != 0) {
|
||||
zir_tags[src_inst] = .store;
|
||||
} else {
|
||||
zir_tags[src_inst] = .store_to_inferred_ptr;
|
||||
@@ -8409,10 +8409,11 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
|
||||
.c_ushort_type,
|
||||
.comptime_float_type,
|
||||
.comptime_int_type,
|
||||
.f128_type,
|
||||
.f16_type,
|
||||
.f32_type,
|
||||
.f64_type,
|
||||
.f80_type,
|
||||
.f128_type,
|
||||
.i16_type,
|
||||
.i32_type,
|
||||
.i64_type,
|
||||
@@ -8648,10 +8649,11 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
|
||||
.c_ulong_type,
|
||||
.c_ulonglong_type,
|
||||
.c_ushort_type,
|
||||
.f128_type,
|
||||
.f16_type,
|
||||
.f32_type,
|
||||
.f64_type,
|
||||
.f80_type,
|
||||
.f128_type,
|
||||
.i16_type,
|
||||
.i32_type,
|
||||
.i64_type,
|
||||
|
||||
24
src/Sema.zig
24
src/Sema.zig
@@ -8188,7 +8188,7 @@ fn analyzeArithmetic(
|
||||
} else {
|
||||
return sema.addConstant(
|
||||
scalar_type,
|
||||
try lhs_val.floatAdd(rhs_val, scalar_type, sema.arena),
|
||||
try lhs_val.floatAdd(rhs_val, scalar_type, sema.arena, target),
|
||||
);
|
||||
}
|
||||
} else break :rs .{ .src = rhs_src, .air_tag = .add };
|
||||
@@ -8281,7 +8281,7 @@ fn analyzeArithmetic(
|
||||
} else {
|
||||
return sema.addConstant(
|
||||
scalar_type,
|
||||
try lhs_val.floatSub(rhs_val, scalar_type, sema.arena),
|
||||
try lhs_val.floatSub(rhs_val, scalar_type, sema.arena, target),
|
||||
);
|
||||
}
|
||||
} else break :rs .{ .src = rhs_src, .air_tag = .sub };
|
||||
@@ -8397,7 +8397,7 @@ fn analyzeArithmetic(
|
||||
} else {
|
||||
return sema.addConstant(
|
||||
scalar_type,
|
||||
try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena),
|
||||
try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena, target),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@@ -8472,7 +8472,7 @@ fn analyzeArithmetic(
|
||||
} else {
|
||||
return sema.addConstant(
|
||||
scalar_type,
|
||||
try lhs_val.floatDivTrunc(rhs_val, scalar_type, sema.arena),
|
||||
try lhs_val.floatDivTrunc(rhs_val, scalar_type, sema.arena, target),
|
||||
);
|
||||
}
|
||||
} else break :rs .{ .src = rhs_src, .air_tag = .div_trunc };
|
||||
@@ -8535,7 +8535,7 @@ fn analyzeArithmetic(
|
||||
} else {
|
||||
return sema.addConstant(
|
||||
scalar_type,
|
||||
try lhs_val.floatDivFloor(rhs_val, scalar_type, sema.arena),
|
||||
try lhs_val.floatDivFloor(rhs_val, scalar_type, sema.arena, target),
|
||||
);
|
||||
}
|
||||
} else break :rs .{ .src = rhs_src, .air_tag = .div_floor };
|
||||
@@ -8587,7 +8587,7 @@ fn analyzeArithmetic(
|
||||
// TODO: emit compile error if there is a remainder
|
||||
return sema.addConstant(
|
||||
scalar_type,
|
||||
try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena),
|
||||
try lhs_val.floatDiv(rhs_val, scalar_type, sema.arena, target),
|
||||
);
|
||||
}
|
||||
} else break :rs .{ .src = rhs_src, .air_tag = .div_exact };
|
||||
@@ -8642,7 +8642,7 @@ fn analyzeArithmetic(
|
||||
} else {
|
||||
return sema.addConstant(
|
||||
scalar_type,
|
||||
try lhs_val.floatMul(rhs_val, scalar_type, sema.arena),
|
||||
try lhs_val.floatMul(rhs_val, scalar_type, sema.arena, target),
|
||||
);
|
||||
}
|
||||
} else break :rs .{ .src = lhs_src, .air_tag = .mul };
|
||||
@@ -8798,7 +8798,7 @@ fn analyzeArithmetic(
|
||||
}
|
||||
return sema.addConstant(
|
||||
scalar_type,
|
||||
try lhs_val.floatRem(rhs_val, sema.arena),
|
||||
try lhs_val.floatRem(rhs_val, scalar_type, sema.arena, target),
|
||||
);
|
||||
} else {
|
||||
return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
|
||||
@@ -8859,7 +8859,7 @@ fn analyzeArithmetic(
|
||||
if (maybe_rhs_val) |rhs_val| {
|
||||
return sema.addConstant(
|
||||
scalar_type,
|
||||
try lhs_val.floatRem(rhs_val, sema.arena),
|
||||
try lhs_val.floatRem(rhs_val, scalar_type, sema.arena, target),
|
||||
);
|
||||
} else break :rs .{ .src = rhs_src, .air_tag = .rem };
|
||||
} else break :rs .{ .src = lhs_src, .air_tag = .rem };
|
||||
@@ -8916,7 +8916,7 @@ fn analyzeArithmetic(
|
||||
if (maybe_rhs_val) |rhs_val| {
|
||||
return sema.addConstant(
|
||||
scalar_type,
|
||||
try lhs_val.floatMod(rhs_val, sema.arena),
|
||||
try lhs_val.floatMod(rhs_val, scalar_type, sema.arena, target),
|
||||
);
|
||||
} else break :rs .{ .src = rhs_src, .air_tag = .mod };
|
||||
} else break :rs .{ .src = lhs_src, .air_tag = .mod };
|
||||
@@ -14196,12 +14196,12 @@ fn coerce(
|
||||
.Float, .ComptimeFloat => switch (inst_ty.zigTypeTag()) {
|
||||
.ComptimeFloat => {
|
||||
const val = try sema.resolveConstValue(block, inst_src, inst);
|
||||
const result_val = try val.floatCast(sema.arena, dest_ty);
|
||||
const result_val = try val.floatCast(sema.arena, dest_ty, target);
|
||||
return try sema.addConstant(dest_ty, result_val);
|
||||
},
|
||||
.Float => {
|
||||
if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| {
|
||||
const result_val = try val.floatCast(sema.arena, dest_ty);
|
||||
const result_val = try val.floatCast(sema.arena, dest_ty, target);
|
||||
if (!val.eql(result_val, dest_ty)) {
|
||||
return sema.fail(
|
||||
block,
|
||||
|
||||
@@ -9432,11 +9432,14 @@ static void define_builtin_types(CodeGen *g) {
|
||||
if (target_has_f80(g->zig_target)) {
|
||||
entry->llvm_type = LLVMX86FP80Type();
|
||||
} else {
|
||||
// We use i128 here instead of x86_fp80 because on targets such as arm,
|
||||
// LLVM will give "ERROR: Cannot select" for any instructions involving
|
||||
// the x86_fp80 type.
|
||||
entry->llvm_type = get_int_type(g, false, 128)->llvm_type;
|
||||
}
|
||||
entry->size_in_bits = 8 * 16;
|
||||
entry->abi_size = 16;
|
||||
entry->abi_align = 16;
|
||||
entry->abi_size = 16; // matches LLVMABISizeOfType(LLVMX86FP80Type())
|
||||
entry->abi_align = 16; // matches LLVMABIAlignmentOfType(LLVMX86FP80Type())
|
||||
buf_init_from_str(&entry->name, "f80");
|
||||
entry->data.floating.bit_count = 80;
|
||||
|
||||
|
||||
270
src/value.zig
270
src/value.zig
@@ -138,6 +138,7 @@ pub const Value = extern union {
|
||||
float_16,
|
||||
float_32,
|
||||
float_64,
|
||||
float_80,
|
||||
float_128,
|
||||
enum_literal,
|
||||
/// A specific enum tag, indicated by the field index (declaration order).
|
||||
@@ -295,6 +296,7 @@ pub const Value = extern union {
|
||||
.float_16 => Payload.Float_16,
|
||||
.float_32 => Payload.Float_32,
|
||||
.float_64 => Payload.Float_64,
|
||||
.float_80 => Payload.Float_80,
|
||||
.float_128 => Payload.Float_128,
|
||||
.@"error" => Payload.Error,
|
||||
.inferred_alloc => Payload.InferredAlloc,
|
||||
@@ -546,6 +548,7 @@ pub const Value = extern union {
|
||||
.float_16 => return self.copyPayloadShallow(arena, Payload.Float_16),
|
||||
.float_32 => return self.copyPayloadShallow(arena, Payload.Float_32),
|
||||
.float_64 => return self.copyPayloadShallow(arena, Payload.Float_64),
|
||||
.float_80 => return self.copyPayloadShallow(arena, Payload.Float_80),
|
||||
.float_128 => return self.copyPayloadShallow(arena, Payload.Float_128),
|
||||
.enum_literal => {
|
||||
const payload = self.castTag(.enum_literal).?;
|
||||
@@ -733,6 +736,7 @@ pub const Value = extern union {
|
||||
.float_16 => return out_stream.print("{}", .{val.castTag(.float_16).?.data}),
|
||||
.float_32 => return out_stream.print("{}", .{val.castTag(.float_32).?.data}),
|
||||
.float_64 => return out_stream.print("{}", .{val.castTag(.float_64).?.data}),
|
||||
.float_80 => return out_stream.print("{}", .{val.castTag(.float_80).?.data}),
|
||||
.float_128 => return out_stream.print("{}", .{val.castTag(.float_128).?.data}),
|
||||
.@"error" => return out_stream.print("error.{s}", .{val.castTag(.@"error").?.data.name}),
|
||||
// TODO to print this it should be error{ Set, Items }!T(val), but we need the type for that
|
||||
@@ -1029,6 +1033,11 @@ pub const Value = extern union {
|
||||
}
|
||||
|
||||
pub fn writeToMemory(val: Value, ty: Type, target: Target, buffer: []u8) void {
|
||||
if (val.isUndef()) {
|
||||
const size = @intCast(usize, ty.abiSize(target));
|
||||
std.mem.set(u8, buffer[0..size], 0xaa);
|
||||
return;
|
||||
}
|
||||
switch (ty.zigTypeTag()) {
|
||||
.Int => {
|
||||
var bigint_buffer: BigIntSpace = undefined;
|
||||
@@ -1064,6 +1073,14 @@ pub const Value = extern union {
|
||||
buf_off += elem_size;
|
||||
}
|
||||
},
|
||||
.Struct => {
|
||||
const fields = ty.structFields().values();
|
||||
const field_vals = val.castTag(.@"struct").?.data;
|
||||
for (fields) |field, i| {
|
||||
const off = @intCast(usize, ty.structFieldOffset(i, target));
|
||||
writeToMemory(field_vals[i], field.ty, target, buffer[off..]);
|
||||
}
|
||||
},
|
||||
else => @panic("TODO implement writeToMemory for more types"),
|
||||
}
|
||||
}
|
||||
@@ -1083,6 +1100,7 @@ pub const Value = extern union {
|
||||
16 => return Value.Tag.float_16.create(arena, floatReadFromMemory(f16, target, buffer)),
|
||||
32 => return Value.Tag.float_32.create(arena, floatReadFromMemory(f32, target, buffer)),
|
||||
64 => return Value.Tag.float_64.create(arena, floatReadFromMemory(f64, target, buffer)),
|
||||
80 => return Value.Tag.float_80.create(arena, floatReadFromMemory(f80, target, buffer)),
|
||||
128 => return Value.Tag.float_128.create(arena, floatReadFromMemory(f128, target, buffer)),
|
||||
else => unreachable,
|
||||
},
|
||||
@@ -1100,6 +1118,12 @@ pub const Value = extern union {
|
||||
}
|
||||
|
||||
fn floatReadFromMemory(comptime F: type, target: Target, buffer: []const u8) F {
|
||||
if (F == f80) {
|
||||
// TODO: use std.math.F80Repr?
|
||||
const int = std.mem.readInt(u128, buffer[0..16], target.cpu.arch.endian());
|
||||
// TODO shouldn't this be a bitcast from u80 to f80 instead of u128 to f80?
|
||||
return @bitCast(F, int);
|
||||
}
|
||||
const Int = @Type(.{ .Int = .{
|
||||
.signedness = .unsigned,
|
||||
.bits = @typeInfo(F).Float.bits,
|
||||
@@ -1114,12 +1138,23 @@ pub const Value = extern union {
|
||||
.float_16 => @floatCast(T, val.castTag(.float_16).?.data),
|
||||
.float_32 => @floatCast(T, val.castTag(.float_32).?.data),
|
||||
.float_64 => @floatCast(T, val.castTag(.float_64).?.data),
|
||||
.float_80 => @floatCast(T, val.castTag(.float_80).?.data),
|
||||
.float_128 => @floatCast(T, val.castTag(.float_128).?.data),
|
||||
|
||||
.zero => 0,
|
||||
.one => 1,
|
||||
.int_u64 => @intToFloat(T, val.castTag(.int_u64).?.data),
|
||||
.int_i64 => @intToFloat(T, val.castTag(.int_i64).?.data),
|
||||
.int_u64 => {
|
||||
if (T == f80) {
|
||||
@panic("TODO we can't lower this properly on non-x86 llvm backend yet");
|
||||
}
|
||||
return @intToFloat(T, val.castTag(.int_u64).?.data);
|
||||
},
|
||||
.int_i64 => {
|
||||
if (T == f80) {
|
||||
@panic("TODO we can't lower this properly on non-x86 llvm backend yet");
|
||||
}
|
||||
return @intToFloat(T, val.castTag(.int_i64).?.data);
|
||||
},
|
||||
|
||||
.int_big_positive => @floatCast(T, bigIntToFloat(val.castTag(.int_big_positive).?.data, true)),
|
||||
.int_big_negative => @floatCast(T, bigIntToFloat(val.castTag(.int_big_negative).?.data, false)),
|
||||
@@ -1367,14 +1402,13 @@ pub const Value = extern union {
|
||||
|
||||
/// Converts an integer or a float to a float. May result in a loss of information.
|
||||
/// Caller can find out by equality checking the result against the operand.
|
||||
pub fn floatCast(self: Value, arena: Allocator, dest_ty: Type) !Value {
|
||||
switch (dest_ty.tag()) {
|
||||
.f16 => return Value.Tag.float_16.create(arena, self.toFloat(f16)),
|
||||
.f32 => return Value.Tag.float_32.create(arena, self.toFloat(f32)),
|
||||
.f64 => return Value.Tag.float_64.create(arena, self.toFloat(f64)),
|
||||
.f128, .comptime_float, .c_longdouble => {
|
||||
return Value.Tag.float_128.create(arena, self.toFloat(f128));
|
||||
},
|
||||
pub fn floatCast(self: Value, arena: Allocator, dest_ty: Type, target: Target) !Value {
|
||||
switch (dest_ty.floatBits(target)) {
|
||||
16 => return Value.Tag.float_16.create(arena, self.toFloat(f16)),
|
||||
32 => return Value.Tag.float_32.create(arena, self.toFloat(f32)),
|
||||
64 => return Value.Tag.float_64.create(arena, self.toFloat(f64)),
|
||||
80 => return Value.Tag.float_80.create(arena, self.toFloat(f80)),
|
||||
128 => return Value.Tag.float_128.create(arena, self.toFloat(f128)),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
@@ -1389,8 +1423,10 @@ pub const Value = extern union {
|
||||
.float_16 => @rem(self.castTag(.float_16).?.data, 1) != 0,
|
||||
.float_32 => @rem(self.castTag(.float_32).?.data, 1) != 0,
|
||||
.float_64 => @rem(self.castTag(.float_64).?.data, 1) != 0,
|
||||
// .float_128 => @rem(self.castTag(.float_128).?.data, 1) != 0,
|
||||
.float_128 => @panic("TODO lld: error: undefined symbol: fmodl"),
|
||||
//.float_80 => @rem(self.castTag(.float_80).?.data, 1) != 0,
|
||||
.float_80 => @panic("TODO implement __remx in compiler-rt"),
|
||||
//.float_128 => @rem(self.castTag(.float_128).?.data, 1) != 0,
|
||||
.float_128 => @panic("TODO implement fmodl in compiler-rt"),
|
||||
|
||||
else => unreachable,
|
||||
};
|
||||
@@ -1408,6 +1444,7 @@ pub const Value = extern union {
|
||||
.float_16 => self.castTag(.float_16).?.data == 0,
|
||||
.float_32 => self.castTag(.float_32).?.data == 0,
|
||||
.float_64 => self.castTag(.float_64).?.data == 0,
|
||||
.float_80 => self.castTag(.float_80).?.data == 0,
|
||||
.float_128 => self.castTag(.float_128).?.data == 0,
|
||||
|
||||
.int_big_positive => self.castTag(.int_big_positive).?.asBigInt().eqZero(),
|
||||
@@ -1440,6 +1477,7 @@ pub const Value = extern union {
|
||||
.float_16 => std.math.order(lhs.castTag(.float_16).?.data, 0),
|
||||
.float_32 => std.math.order(lhs.castTag(.float_32).?.data, 0),
|
||||
.float_64 => std.math.order(lhs.castTag(.float_64).?.data, 0),
|
||||
.float_80 => std.math.order(lhs.castTag(.float_80).?.data, 0),
|
||||
.float_128 => std.math.order(lhs.castTag(.float_128).?.data, 0),
|
||||
|
||||
else => unreachable,
|
||||
@@ -1471,6 +1509,7 @@ pub const Value = extern union {
|
||||
.float_16 => return std.math.order(lhs.castTag(.float_16).?.data, rhs.castTag(.float_16).?.data),
|
||||
.float_32 => return std.math.order(lhs.castTag(.float_32).?.data, rhs.castTag(.float_32).?.data),
|
||||
.float_64 => return std.math.order(lhs.castTag(.float_64).?.data, rhs.castTag(.float_64).?.data),
|
||||
.float_80 => return std.math.order(lhs.castTag(.float_80).?.data, rhs.castTag(.float_80).?.data),
|
||||
.float_128 => return std.math.order(lhs.castTag(.float_128).?.data, rhs.castTag(.float_128).?.data),
|
||||
else => unreachable,
|
||||
};
|
||||
@@ -2139,6 +2178,7 @@ pub const Value = extern union {
|
||||
.float_16,
|
||||
.float_32,
|
||||
.float_64,
|
||||
.float_80,
|
||||
.float_128,
|
||||
=> true,
|
||||
else => false,
|
||||
@@ -2174,6 +2214,9 @@ pub const Value = extern union {
|
||||
16 => return Value.Tag.float_16.create(arena, @intToFloat(f16, x)),
|
||||
32 => return Value.Tag.float_32.create(arena, @intToFloat(f32, x)),
|
||||
64 => return Value.Tag.float_64.create(arena, @intToFloat(f64, x)),
|
||||
// We can't lower this properly on non-x86 llvm backends yet
|
||||
//80 => return Value.Tag.float_80.create(arena, @intToFloat(f80, x)),
|
||||
80 => @panic("TODO f80 intToFloat"),
|
||||
128 => return Value.Tag.float_128.create(arena, @intToFloat(f128, x)),
|
||||
else => unreachable,
|
||||
}
|
||||
@@ -2184,6 +2227,7 @@ pub const Value = extern union {
|
||||
16 => return Value.Tag.float_16.create(arena, @floatCast(f16, float)),
|
||||
32 => return Value.Tag.float_32.create(arena, @floatCast(f32, float)),
|
||||
64 => return Value.Tag.float_64.create(arena, @floatCast(f64, float)),
|
||||
80 => return Value.Tag.float_80.create(arena, @floatCast(f80, float)),
|
||||
128 => return Value.Tag.float_128.create(arena, float),
|
||||
else => unreachable,
|
||||
}
|
||||
@@ -2281,7 +2325,7 @@ pub const Value = extern union {
|
||||
}
|
||||
|
||||
if (ty.isAnyFloat()) {
|
||||
return floatAdd(lhs, rhs, ty, arena);
|
||||
return floatAdd(lhs, rhs, ty, arena, target);
|
||||
}
|
||||
|
||||
const overflow_result = try intAddWithOverflow(lhs, rhs, ty, arena, target);
|
||||
@@ -2371,7 +2415,7 @@ pub const Value = extern union {
|
||||
}
|
||||
|
||||
if (ty.isAnyFloat()) {
|
||||
return floatSub(lhs, rhs, ty, arena);
|
||||
return floatSub(lhs, rhs, ty, arena, target);
|
||||
}
|
||||
|
||||
const overflow_result = try intSubWithOverflow(lhs, rhs, ty, arena, target);
|
||||
@@ -2454,7 +2498,7 @@ pub const Value = extern union {
|
||||
}
|
||||
|
||||
if (ty.isAnyFloat()) {
|
||||
return floatMul(lhs, rhs, ty, arena);
|
||||
return floatMul(lhs, rhs, ty, arena, target);
|
||||
}
|
||||
|
||||
const overflow_result = try intMulWithOverflow(lhs, rhs, ty, arena, target);
|
||||
@@ -2753,23 +2797,84 @@ pub const Value = extern union {
|
||||
.float_16 => std.math.isNan(val.castTag(.float_16).?.data),
|
||||
.float_32 => std.math.isNan(val.castTag(.float_32).?.data),
|
||||
.float_64 => std.math.isNan(val.castTag(.float_64).?.data),
|
||||
.float_80 => std.math.isNan(val.castTag(.float_80).?.data),
|
||||
.float_128 => std.math.isNan(val.castTag(.float_128).?.data),
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn floatRem(lhs: Value, rhs: Value, allocator: Allocator) !Value {
|
||||
_ = lhs;
|
||||
_ = rhs;
|
||||
_ = allocator;
|
||||
@panic("TODO implement Value.floatRem");
|
||||
pub fn floatRem(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {
|
||||
switch (float_type.floatBits(target)) {
|
||||
16 => {
|
||||
const lhs_val = lhs.toFloat(f16);
|
||||
const rhs_val = rhs.toFloat(f16);
|
||||
return Value.Tag.float_16.create(arena, @rem(lhs_val, rhs_val));
|
||||
},
|
||||
32 => {
|
||||
const lhs_val = lhs.toFloat(f32);
|
||||
const rhs_val = rhs.toFloat(f32);
|
||||
return Value.Tag.float_32.create(arena, @rem(lhs_val, rhs_val));
|
||||
},
|
||||
64 => {
|
||||
const lhs_val = lhs.toFloat(f64);
|
||||
const rhs_val = rhs.toFloat(f64);
|
||||
return Value.Tag.float_64.create(arena, @rem(lhs_val, rhs_val));
|
||||
},
|
||||
80 => {
|
||||
if (true) {
|
||||
@panic("TODO implement compiler_rt __remx");
|
||||
}
|
||||
const lhs_val = lhs.toFloat(f80);
|
||||
const rhs_val = rhs.toFloat(f80);
|
||||
return Value.Tag.float_80.create(arena, @rem(lhs_val, rhs_val));
|
||||
},
|
||||
128 => {
|
||||
if (true) {
|
||||
@panic("TODO implement compiler_rt fmodl");
|
||||
}
|
||||
const lhs_val = lhs.toFloat(f128);
|
||||
const rhs_val = rhs.toFloat(f128);
|
||||
return Value.Tag.float_128.create(arena, @rem(lhs_val, rhs_val));
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn floatMod(lhs: Value, rhs: Value, allocator: Allocator) !Value {
|
||||
_ = lhs;
|
||||
_ = rhs;
|
||||
_ = allocator;
|
||||
@panic("TODO implement Value.floatMod");
|
||||
pub fn floatMod(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {
|
||||
switch (float_type.floatBits(target)) {
|
||||
16 => {
|
||||
const lhs_val = lhs.toFloat(f16);
|
||||
const rhs_val = rhs.toFloat(f16);
|
||||
return Value.Tag.float_16.create(arena, @mod(lhs_val, rhs_val));
|
||||
},
|
||||
32 => {
|
||||
const lhs_val = lhs.toFloat(f32);
|
||||
const rhs_val = rhs.toFloat(f32);
|
||||
return Value.Tag.float_32.create(arena, @mod(lhs_val, rhs_val));
|
||||
},
|
||||
64 => {
|
||||
const lhs_val = lhs.toFloat(f64);
|
||||
const rhs_val = rhs.toFloat(f64);
|
||||
return Value.Tag.float_64.create(arena, @mod(lhs_val, rhs_val));
|
||||
},
|
||||
80 => {
|
||||
if (true) {
|
||||
@panic("TODO implement compiler_rt __modx");
|
||||
}
|
||||
const lhs_val = lhs.toFloat(f80);
|
||||
const rhs_val = rhs.toFloat(f80);
|
||||
return Value.Tag.float_80.create(arena, @mod(lhs_val, rhs_val));
|
||||
},
|
||||
128 => {
|
||||
if (true) {
|
||||
@panic("TODO implement compiler_rt fmodl");
|
||||
}
|
||||
const lhs_val = lhs.toFloat(f128);
|
||||
const rhs_val = rhs.toFloat(f128);
|
||||
return Value.Tag.float_128.create(arena, @mod(lhs_val, rhs_val));
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn intMul(lhs: Value, rhs: Value, allocator: Allocator) !Value {
|
||||
@@ -2929,24 +3034,30 @@ pub const Value = extern union {
|
||||
rhs: Value,
|
||||
float_type: Type,
|
||||
arena: Allocator,
|
||||
target: Target,
|
||||
) !Value {
|
||||
switch (float_type.tag()) {
|
||||
.f16 => {
|
||||
switch (float_type.floatBits(target)) {
|
||||
16 => {
|
||||
const lhs_val = lhs.toFloat(f16);
|
||||
const rhs_val = rhs.toFloat(f16);
|
||||
return Value.Tag.float_16.create(arena, lhs_val + rhs_val);
|
||||
},
|
||||
.f32 => {
|
||||
32 => {
|
||||
const lhs_val = lhs.toFloat(f32);
|
||||
const rhs_val = rhs.toFloat(f32);
|
||||
return Value.Tag.float_32.create(arena, lhs_val + rhs_val);
|
||||
},
|
||||
.f64 => {
|
||||
64 => {
|
||||
const lhs_val = lhs.toFloat(f64);
|
||||
const rhs_val = rhs.toFloat(f64);
|
||||
return Value.Tag.float_64.create(arena, lhs_val + rhs_val);
|
||||
},
|
||||
.f128, .comptime_float, .c_longdouble => {
|
||||
80 => {
|
||||
const lhs_val = lhs.toFloat(f80);
|
||||
const rhs_val = rhs.toFloat(f80);
|
||||
return Value.Tag.float_80.create(arena, lhs_val + rhs_val);
|
||||
},
|
||||
128 => {
|
||||
const lhs_val = lhs.toFloat(f128);
|
||||
const rhs_val = rhs.toFloat(f128);
|
||||
return Value.Tag.float_128.create(arena, lhs_val + rhs_val);
|
||||
@@ -2960,24 +3071,30 @@ pub const Value = extern union {
|
||||
rhs: Value,
|
||||
float_type: Type,
|
||||
arena: Allocator,
|
||||
target: Target,
|
||||
) !Value {
|
||||
switch (float_type.tag()) {
|
||||
.f16 => {
|
||||
switch (float_type.floatBits(target)) {
|
||||
16 => {
|
||||
const lhs_val = lhs.toFloat(f16);
|
||||
const rhs_val = rhs.toFloat(f16);
|
||||
return Value.Tag.float_16.create(arena, lhs_val - rhs_val);
|
||||
},
|
||||
.f32 => {
|
||||
32 => {
|
||||
const lhs_val = lhs.toFloat(f32);
|
||||
const rhs_val = rhs.toFloat(f32);
|
||||
return Value.Tag.float_32.create(arena, lhs_val - rhs_val);
|
||||
},
|
||||
.f64 => {
|
||||
64 => {
|
||||
const lhs_val = lhs.toFloat(f64);
|
||||
const rhs_val = rhs.toFloat(f64);
|
||||
return Value.Tag.float_64.create(arena, lhs_val - rhs_val);
|
||||
},
|
||||
.f128, .comptime_float, .c_longdouble => {
|
||||
80 => {
|
||||
const lhs_val = lhs.toFloat(f80);
|
||||
const rhs_val = rhs.toFloat(f80);
|
||||
return Value.Tag.float_80.create(arena, lhs_val - rhs_val);
|
||||
},
|
||||
128 => {
|
||||
const lhs_val = lhs.toFloat(f128);
|
||||
const rhs_val = rhs.toFloat(f128);
|
||||
return Value.Tag.float_128.create(arena, lhs_val - rhs_val);
|
||||
@@ -2991,24 +3108,33 @@ pub const Value = extern union {
|
||||
rhs: Value,
|
||||
float_type: Type,
|
||||
arena: Allocator,
|
||||
target: Target,
|
||||
) !Value {
|
||||
switch (float_type.tag()) {
|
||||
.f16 => {
|
||||
switch (float_type.floatBits(target)) {
|
||||
16 => {
|
||||
const lhs_val = lhs.toFloat(f16);
|
||||
const rhs_val = rhs.toFloat(f16);
|
||||
return Value.Tag.float_16.create(arena, lhs_val / rhs_val);
|
||||
},
|
||||
.f32 => {
|
||||
32 => {
|
||||
const lhs_val = lhs.toFloat(f32);
|
||||
const rhs_val = rhs.toFloat(f32);
|
||||
return Value.Tag.float_32.create(arena, lhs_val / rhs_val);
|
||||
},
|
||||
.f64 => {
|
||||
64 => {
|
||||
const lhs_val = lhs.toFloat(f64);
|
||||
const rhs_val = rhs.toFloat(f64);
|
||||
return Value.Tag.float_64.create(arena, lhs_val / rhs_val);
|
||||
},
|
||||
.f128, .comptime_float, .c_longdouble => {
|
||||
80 => {
|
||||
if (true) {
|
||||
@panic("TODO implement compiler_rt __divxf3");
|
||||
}
|
||||
const lhs_val = lhs.toFloat(f80);
|
||||
const rhs_val = rhs.toFloat(f80);
|
||||
return Value.Tag.float_80.create(arena, lhs_val / rhs_val);
|
||||
},
|
||||
128 => {
|
||||
const lhs_val = lhs.toFloat(f128);
|
||||
const rhs_val = rhs.toFloat(f128);
|
||||
return Value.Tag.float_128.create(arena, lhs_val / rhs_val);
|
||||
@@ -3022,24 +3148,33 @@ pub const Value = extern union {
|
||||
rhs: Value,
|
||||
float_type: Type,
|
||||
arena: Allocator,
|
||||
target: Target,
|
||||
) !Value {
|
||||
switch (float_type.tag()) {
|
||||
.f16 => {
|
||||
switch (float_type.floatBits(target)) {
|
||||
16 => {
|
||||
const lhs_val = lhs.toFloat(f16);
|
||||
const rhs_val = rhs.toFloat(f16);
|
||||
return Value.Tag.float_16.create(arena, @divFloor(lhs_val, rhs_val));
|
||||
},
|
||||
.f32 => {
|
||||
32 => {
|
||||
const lhs_val = lhs.toFloat(f32);
|
||||
const rhs_val = rhs.toFloat(f32);
|
||||
return Value.Tag.float_32.create(arena, @divFloor(lhs_val, rhs_val));
|
||||
},
|
||||
.f64 => {
|
||||
64 => {
|
||||
const lhs_val = lhs.toFloat(f64);
|
||||
const rhs_val = rhs.toFloat(f64);
|
||||
return Value.Tag.float_64.create(arena, @divFloor(lhs_val, rhs_val));
|
||||
},
|
||||
.f128, .comptime_float, .c_longdouble => {
|
||||
80 => {
|
||||
if (true) {
|
||||
@panic("TODO implement compiler_rt __floorx");
|
||||
}
|
||||
const lhs_val = lhs.toFloat(f80);
|
||||
const rhs_val = rhs.toFloat(f80);
|
||||
return Value.Tag.float_80.create(arena, @divFloor(lhs_val, rhs_val));
|
||||
},
|
||||
128 => {
|
||||
const lhs_val = lhs.toFloat(f128);
|
||||
const rhs_val = rhs.toFloat(f128);
|
||||
return Value.Tag.float_128.create(arena, @divFloor(lhs_val, rhs_val));
|
||||
@@ -3053,24 +3188,33 @@ pub const Value = extern union {
|
||||
rhs: Value,
|
||||
float_type: Type,
|
||||
arena: Allocator,
|
||||
target: Target,
|
||||
) !Value {
|
||||
switch (float_type.tag()) {
|
||||
.f16 => {
|
||||
switch (float_type.floatBits(target)) {
|
||||
16 => {
|
||||
const lhs_val = lhs.toFloat(f16);
|
||||
const rhs_val = rhs.toFloat(f16);
|
||||
return Value.Tag.float_16.create(arena, @divTrunc(lhs_val, rhs_val));
|
||||
},
|
||||
.f32 => {
|
||||
32 => {
|
||||
const lhs_val = lhs.toFloat(f32);
|
||||
const rhs_val = rhs.toFloat(f32);
|
||||
return Value.Tag.float_32.create(arena, @divTrunc(lhs_val, rhs_val));
|
||||
},
|
||||
.f64 => {
|
||||
64 => {
|
||||
const lhs_val = lhs.toFloat(f64);
|
||||
const rhs_val = rhs.toFloat(f64);
|
||||
return Value.Tag.float_64.create(arena, @divTrunc(lhs_val, rhs_val));
|
||||
},
|
||||
.f128, .comptime_float, .c_longdouble => {
|
||||
80 => {
|
||||
if (true) {
|
||||
@panic("TODO implement compiler_rt __truncx");
|
||||
}
|
||||
const lhs_val = lhs.toFloat(f80);
|
||||
const rhs_val = rhs.toFloat(f80);
|
||||
return Value.Tag.float_80.create(arena, @divTrunc(lhs_val, rhs_val));
|
||||
},
|
||||
128 => {
|
||||
const lhs_val = lhs.toFloat(f128);
|
||||
const rhs_val = rhs.toFloat(f128);
|
||||
return Value.Tag.float_128.create(arena, @divTrunc(lhs_val, rhs_val));
|
||||
@@ -3084,24 +3228,33 @@ pub const Value = extern union {
|
||||
rhs: Value,
|
||||
float_type: Type,
|
||||
arena: Allocator,
|
||||
target: Target,
|
||||
) !Value {
|
||||
switch (float_type.tag()) {
|
||||
.f16 => {
|
||||
switch (float_type.floatBits(target)) {
|
||||
16 => {
|
||||
const lhs_val = lhs.toFloat(f16);
|
||||
const rhs_val = rhs.toFloat(f16);
|
||||
return Value.Tag.float_16.create(arena, lhs_val * rhs_val);
|
||||
},
|
||||
.f32 => {
|
||||
32 => {
|
||||
const lhs_val = lhs.toFloat(f32);
|
||||
const rhs_val = rhs.toFloat(f32);
|
||||
return Value.Tag.float_32.create(arena, lhs_val * rhs_val);
|
||||
},
|
||||
.f64 => {
|
||||
64 => {
|
||||
const lhs_val = lhs.toFloat(f64);
|
||||
const rhs_val = rhs.toFloat(f64);
|
||||
return Value.Tag.float_64.create(arena, lhs_val * rhs_val);
|
||||
},
|
||||
.f128, .comptime_float, .c_longdouble => {
|
||||
80 => {
|
||||
if (true) {
|
||||
@panic("TODO implement compiler_rt __mulxf3");
|
||||
}
|
||||
const lhs_val = lhs.toFloat(f80);
|
||||
const rhs_val = rhs.toFloat(f80);
|
||||
return Value.Tag.float_80.create(arena, lhs_val * rhs_val);
|
||||
},
|
||||
128 => {
|
||||
const lhs_val = lhs.toFloat(f128);
|
||||
const rhs_val = rhs.toFloat(f128);
|
||||
return Value.Tag.float_128.create(arena, lhs_val * rhs_val);
|
||||
@@ -3250,6 +3403,13 @@ pub const Value = extern union {
|
||||
data: f64,
|
||||
};
|
||||
|
||||
pub const Float_80 = struct {
|
||||
pub const base_tag = Tag.float_80;
|
||||
|
||||
base: Payload = .{ .tag = base_tag },
|
||||
data: f80,
|
||||
};
|
||||
|
||||
pub const Float_128 = struct {
|
||||
pub const base_tag = Tag.float_128;
|
||||
|
||||
|
||||
@@ -768,8 +768,6 @@ test "shift left/right on u0 operand" {
|
||||
}
|
||||
|
||||
test "comptime float rem int" {
|
||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||
|
||||
comptime {
|
||||
var x = @as(f32, 1) % 2;
|
||||
try expect(x == 1.0);
|
||||
|
||||
Reference in New Issue
Block a user