aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Schmidt <john.schmidt.h@gmail.com>2022-02-04 20:21:15 +0100
committerAndrew Kelley <andrew@ziglang.org>2022-02-09 20:29:41 -0500
commit7f0cf395aa74eb5ea250bd28f7525b3036790a6a (patch)
treee2faf4e4a19836331d3e47180438fab4db4fb178 /src
parent44b5fdf3266f11607313bc9990a876b5a7f9e174 (diff)
downloadzig-7f0cf395aa74eb5ea250bd28f7525b3036790a6a.tar.gz
zig-7f0cf395aa74eb5ea250bd28f7525b3036790a6a.zip
stage2: implement all builtin floatops for f{16,32,64}
- Merge `floatop.zig` and `floatop_stage1.zig` since most tests now pass on stage2. - Add more behavior tests for a bunch of functions.
Diffstat (limited to 'src')
-rw-r--r--src/Air.zig53
-rw-r--r--src/Liveness.zig12
-rw-r--r--src/Sema.zig24
-rw-r--r--src/arch/aarch64/CodeGen.zig15
-rw-r--r--src/arch/arm/CodeGen.zig15
-rw-r--r--src/arch/riscv64/CodeGen.zig15
-rw-r--r--src/arch/wasm/CodeGen.zig12
-rw-r--r--src/arch/x86_64/CodeGen.zig15
-rw-r--r--src/codegen/c.zig21
-rw-r--r--src/codegen/llvm.zig18
-rw-r--r--src/print_air.zig12
-rw-r--r--src/value.zig384
12 files changed, 568 insertions, 28 deletions
diff --git a/src/Air.zig b/src/Air.zig
index a044dd6294..623da26255 100644
--- a/src/Air.zig
+++ b/src/Air.zig
@@ -237,9 +237,45 @@ pub const Inst = struct {
/// Uses the `ty_op` field.
popcount,
- /// Computes the square root of a floating point number.
+ /// Square root of a floating point number.
/// Uses the `un_op` field.
sqrt,
+ /// Sine a floating point number.
+ /// Uses the `un_op` field.
+ sin,
+ /// Cosine a floating point number.
+ /// Uses the `un_op` field.
+ cos,
+ /// Base e exponential of a floating point number.
+ /// Uses the `un_op` field.
+ exp,
+ /// Base 2 exponential of a floating point number.
+ /// Uses the `un_op` field.
+ exp2,
+ /// Natural (base e) logarithm of a floating point number.
+ /// Uses the `un_op` field.
+ log,
+ /// Base 2 logarithm of a floating point number.
+ /// Uses the `un_op` field.
+ log2,
+ /// Base 10 logarithm of a floating point number.
+ /// Uses the `un_op` field.
+ log10,
+ /// Aboslute value of a floating point number.
+ /// Uses the `un_op` field.
+ fabs,
+ /// Floor: rounds a floating pointer number down to the nearest integer.
+ /// Uses the `un_op` field.
+ floor,
+ /// Ceiling: rounds a floating pointer number up to the nearest integer.
+ /// Uses the `un_op` field.
+ ceil,
+ /// Rounds a floating pointer number to the nearest integer.
+ /// Uses the `un_op` field.
+ round,
+ /// Rounds a floating pointer number to the nearest integer towards zero.
+ /// Uses the `un_op` field.
+ trunc_float,
/// `<`. Result type is always bool.
/// Uses the `bin_op` field.
@@ -754,7 +790,20 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
.max,
=> return air.typeOf(datas[inst].bin_op.lhs),
- .sqrt => return air.typeOf(datas[inst].un_op),
+ .sqrt,
+ .sin,
+ .cos,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .fabs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float,
+ => return air.typeOf(datas[inst].un_op),
.cmp_lt,
.cmp_lte,
diff --git a/src/Liveness.zig b/src/Liveness.zig
index bed7de1507..12ba63fc00 100644
--- a/src/Liveness.zig
+++ b/src/Liveness.zig
@@ -339,6 +339,18 @@ fn analyzeInst(
.tag_name,
.error_name,
.sqrt,
+ .sin,
+ .cos,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .fabs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float,
=> {
const operand = inst_datas[inst].un_op;
return trackOperands(a, new_set, inst, main_tomb, .{ operand, .none, .none });
diff --git a/src/Sema.zig b/src/Sema.zig
index 4ff535d86e..4d38c6b7f7 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -747,18 +747,18 @@ fn analyzeBodyInner(
.ctz => try sema.zirClzCtz(block, inst, .ctz, Value.ctz),
.sqrt => try sema.zirUnaryMath(block, inst, .sqrt, Value.sqrt),
- .sin => @panic("TODO"),
- .cos => @panic("TODO"),
- .exp => @panic("TODO"),
- .exp2 => @panic("TODO"),
- .log => @panic("TODO"),
- .log2 => @panic("TODO"),
- .log10 => @panic("TODO"),
- .fabs => @panic("TODO"),
- .floor => @panic("TODO"),
- .ceil => @panic("TODO"),
- .trunc => @panic("TODO"),
- .round => @panic("TODO"),
+ .sin => try sema.zirUnaryMath(block, inst, .sin, Value.sin),
+ .cos => try sema.zirUnaryMath(block, inst, .cos, Value.cos),
+ .exp => try sema.zirUnaryMath(block, inst, .exp, Value.exp),
+ .exp2 => try sema.zirUnaryMath(block, inst, .exp2, Value.exp2),
+ .log => try sema.zirUnaryMath(block, inst, .log, Value.log),
+ .log2 => try sema.zirUnaryMath(block, inst, .log2, Value.log2),
+ .log10 => try sema.zirUnaryMath(block, inst, .log10, Value.log10),
+ .fabs => try sema.zirUnaryMath(block, inst, .fabs, Value.fabs),
+ .floor => try sema.zirUnaryMath(block, inst, .floor, Value.floor),
+ .ceil => try sema.zirUnaryMath(block, inst, .ceil, Value.ceil),
+ .round => try sema.zirUnaryMath(block, inst, .round, Value.round),
+ .trunc => try sema.zirUnaryMath(block, inst, .trunc_float, Value.trunc),
.error_set_decl => try sema.zirErrorSetDecl(block, inst, .parent),
.error_set_decl_anon => try sema.zirErrorSetDecl(block, inst, .anon),
diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig
index d0413af02f..42f2c66df1 100644
--- a/src/arch/aarch64/CodeGen.zig
+++ b/src/arch/aarch64/CodeGen.zig
@@ -528,7 +528,20 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.max => try self.airMax(inst),
.slice => try self.airSlice(inst),
- .sqrt => try self.airUnaryMath(inst),
+ .sqrt,
+ .sin,
+ .cos,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .fabs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float
+ => try self.airUnaryMath(inst),
.add_with_overflow => try self.airAddWithOverflow(inst),
.sub_with_overflow => try self.airSubWithOverflow(inst),
diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig
index 2116717cd1..711e2a96f0 100644
--- a/src/arch/arm/CodeGen.zig
+++ b/src/arch/arm/CodeGen.zig
@@ -520,7 +520,20 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.max => try self.airMax(inst),
.slice => try self.airSlice(inst),
- .sqrt => try self.airUnaryMath(inst),
+ .sqrt,
+ .sin,
+ .cos,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .fabs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float,
+ => try self.airUnaryMath(inst),
.add_with_overflow => try self.airAddWithOverflow(inst),
.sub_with_overflow => try self.airSubWithOverflow(inst),
diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig
index ce5dc39bf8..09ca92f229 100644
--- a/src/arch/riscv64/CodeGen.zig
+++ b/src/arch/riscv64/CodeGen.zig
@@ -507,7 +507,20 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.max => try self.airMax(inst),
.slice => try self.airSlice(inst),
- .sqrt => try self.airUnaryMath(inst),
+ .sqrt,
+ .sin,
+ .cos,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .fabs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float,
+ => try self.airUnaryMath(inst),
.add_with_overflow => try self.airAddWithOverflow(inst),
.sub_with_overflow => try self.airSubWithOverflow(inst),
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig
index 5186f0231b..b0c24be03b 100644
--- a/src/arch/wasm/CodeGen.zig
+++ b/src/arch/wasm/CodeGen.zig
@@ -1679,6 +1679,18 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.unwrap_errunion_err_ptr,
.sqrt,
+ .sin,
+ .cos,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .fabs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float,
.ptr_slice_len_ptr,
.ptr_slice_ptr_ptr,
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index de8f907dea..d78245b094 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -599,7 +599,20 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.max => try self.airMax(inst),
.slice => try self.airSlice(inst),
- .sqrt => try self.airUnaryMath(inst),
+ .sqrt,
+ .sin,
+ .cos,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .fabs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float,
+ => try self.airUnaryMath(inst),
.add_with_overflow => try self.airAddWithOverflow(inst),
.sub_with_overflow => try self.airSubWithOverflow(inst),
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index fc3848df21..5d7bdcee55 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -1446,7 +1446,20 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
.mul_sat => try airSatOp(f, inst, "muls_"),
.shl_sat => try airSatOp(f, inst, "shls_"),
- .sqrt => try airSqrt(f, inst),
+ .sqrt,
+ .sin,
+ .cos,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .fabs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float,
+ => |tag| return f.fail("TODO: C backend: implement unary op for tag '{s}'", .{@tagName(tag)}),
.add_with_overflow => try airAddWithOverflow(f, inst),
.sub_with_overflow => try airSubWithOverflow(f, inst),
@@ -3395,12 +3408,6 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
return CValue.none;
}
-fn airSqrt(f: *Function, inst: Air.Inst.Index) !CValue {
- _ = f;
- _ = inst;
- return f.fail("TODO: C backend: implement sqrt", .{});
-}
-
fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {
return switch (order) {
.Unordered => "memory_order_relaxed",
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 5a2c21eece..9c9bf0d0f2 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -2050,7 +2050,19 @@ pub const FuncGen = struct {
.shr => try self.airShr(inst, false),
.shr_exact => try self.airShr(inst, true),
- .sqrt => try self.airSqrt(inst),
+ .sqrt => try self.airUnaryOp(inst, "llvm.sqrt"),
+ .sin => try self.airUnaryOp(inst, "llvm.sin"),
+ .cos => try self.airUnaryOp(inst, "llvm.cos"),
+ .exp => try self.airUnaryOp(inst, "llvm.exp"),
+ .exp2 => try self.airUnaryOp(inst, "llvm.exp2"),
+ .log => try self.airUnaryOp(inst, "llvm.log"),
+ .log2 => try self.airUnaryOp(inst, "llvm.log2"),
+ .log10 => try self.airUnaryOp(inst, "llvm.log10"),
+ .fabs => try self.airUnaryOp(inst, "llvm.fabs"),
+ .floor => try self.airUnaryOp(inst, "llvm.floor"),
+ .ceil => try self.airUnaryOp(inst, "llvm.ceil"),
+ .round => try self.airUnaryOp(inst, "llvm.round"),
+ .trunc_float => try self.airUnaryOp(inst, "llvm.trunc"),
.cmp_eq => try self.airCmp(inst, .eq),
.cmp_gt => try self.airCmp(inst, .gt),
@@ -4213,7 +4225,7 @@ pub const FuncGen = struct {
}
}
- fn airSqrt(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airUnaryOp(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*const llvm.Value {
if (self.liveness.isUnused(inst)) return null;
const un_op = self.air.instructions.items(.data)[inst].un_op;
@@ -4221,7 +4233,7 @@ pub const FuncGen = struct {
const operand_ty = self.air.typeOf(un_op);
const operand_llvm_ty = try self.dg.llvmType(operand_ty);
- const fn_val = self.getIntrinsic("llvm.sqrt", &.{operand_llvm_ty});
+ const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty});
const params = [_]*const llvm.Value{operand};
return self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, "");
diff --git a/src/print_air.zig b/src/print_air.zig
index 341e736b91..bcadf31e74 100644
--- a/src/print_air.zig
+++ b/src/print_air.zig
@@ -159,6 +159,18 @@ const Writer = struct {
.tag_name,
.error_name,
.sqrt,
+ .sin,
+ .cos,
+ .exp,
+ .exp2,
+ .log,
+ .log2,
+ .log10,
+ .fabs,
+ .floor,
+ .ceil,
+ .round,
+ .trunc_float,
=> try w.writeUnOp(s, inst),
.breakpoint,
diff --git a/src/value.zig b/src/value.zig
index 9e1f4c0ed6..33a75e08bb 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -3308,6 +3308,390 @@ pub const Value = extern union {
}
}
+ pub fn sin(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @sin(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @sin(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @sin(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt sin for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @sin(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt sin for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @sin(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn cos(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @cos(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @cos(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @cos(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt cos for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @cos(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt cos for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @cos(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn exp(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @exp(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @exp(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @exp(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt exp for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @exp(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt exp for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @exp(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn exp2(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @exp2(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @exp2(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @exp2(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt exp2 for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @exp2(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt exp2 for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @exp2(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn log(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @log(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @log(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @log(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt log for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @log(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt log for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @log(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn log2(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @log2(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @log2(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @log2(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt log2 for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @log2(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt log2 for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @log2(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn log10(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @log10(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @log10(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @log10(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt log10 for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @log10(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt log10 for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @log10(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn fabs(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @fabs(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @fabs(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @fabs(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt fabs for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @fabs(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt fabs for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @fabs(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn floor(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @floor(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @floor(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @floor(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt floor for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @floor(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt floor for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @floor(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn ceil(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @ceil(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @ceil(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @ceil(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt ceil for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @ceil(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt ceil for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @ceil(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn round(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @round(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @round(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @round(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt round for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @round(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt round for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @round(f));
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn trunc(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
+ switch (float_type.floatBits(target)) {
+ 16 => {
+ const f = val.toFloat(f16);
+ return Value.Tag.float_16.create(arena, @trunc(f));
+ },
+ 32 => {
+ const f = val.toFloat(f32);
+ return Value.Tag.float_32.create(arena, @trunc(f));
+ },
+ 64 => {
+ const f = val.toFloat(f64);
+ return Value.Tag.float_64.create(arena, @trunc(f));
+ },
+ 80 => {
+ if (true) {
+ @panic("TODO implement compiler_rt trunc for f80");
+ }
+ const f = val.toFloat(f80);
+ return Value.Tag.float_80.create(arena, @trunc(f));
+ },
+ 128 => {
+ if (true) {
+ @panic("TODO implement compiler_rt trunc for f128");
+ }
+ const f = val.toFloat(f128);
+ return Value.Tag.float_128.create(arena, @trunc(f));
+ },
+ else => unreachable,
+ }
+ }
+
/// This type is not copyable since it may contain pointers to its inner data.
pub const Payload = struct {
tag: Tag,