diff options
| author | John Schmidt <john.schmidt.h@gmail.com> | 2022-02-04 20:21:15 +0100 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-02-09 20:29:41 -0500 |
| commit | 7f0cf395aa74eb5ea250bd28f7525b3036790a6a (patch) | |
| tree | e2faf4e4a19836331d3e47180438fab4db4fb178 /src | |
| parent | 44b5fdf3266f11607313bc9990a876b5a7f9e174 (diff) | |
| download | zig-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.zig | 53 | ||||
| -rw-r--r-- | src/Liveness.zig | 12 | ||||
| -rw-r--r-- | src/Sema.zig | 24 | ||||
| -rw-r--r-- | src/arch/aarch64/CodeGen.zig | 15 | ||||
| -rw-r--r-- | src/arch/arm/CodeGen.zig | 15 | ||||
| -rw-r--r-- | src/arch/riscv64/CodeGen.zig | 15 | ||||
| -rw-r--r-- | src/arch/wasm/CodeGen.zig | 12 | ||||
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 15 | ||||
| -rw-r--r-- | src/codegen/c.zig | 21 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 18 | ||||
| -rw-r--r-- | src/print_air.zig | 12 | ||||
| -rw-r--r-- | src/value.zig | 384 |
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, ¶ms, 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, |
