Commit 6bc6e47b15

Andrew Kelley <andrew@ziglang.org>
2022-06-30 09:02:00
stage2: lower float negation explicitly
Rather than lowering float negation as `0.0 - x`. * Add AIR instruction for float negation. * Add compiler-rt functions for f128, f80 negation closes #11853
1 parent 54454fd
lib/compiler_rt/common.zig
@@ -188,3 +188,15 @@ pub fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeIn
     significand.* <<= @intCast(std.math.Log2Int(Z), shift);
     return @as(i32, 1) - shift;
 }
+
+pub inline fn fneg(a: anytype) @TypeOf(a) {
+    const F = @TypeOf(a);
+    const bits = @typeInfo(F).Float.bits;
+    const U = @Type(.{ .Int = .{
+        .signedness = .unsigned,
+        .bits = bits,
+    } });
+    const sign_bit_mask = @as(U, 1) << (bits - 1);
+    const negated = @bitCast(U, a) ^ sign_bit_mask;
+    return @bitCast(F, negated);
+}
lib/compiler_rt/negdf2.zig
@@ -0,0 +1,19 @@
+const common = @import("./common.zig");
+
+pub const panic = common.panic;
+
+comptime {
+    if (common.want_aeabi) {
+        @export(__aeabi_dneg, .{ .name = "__aeabi_dneg", .linkage = common.linkage });
+    } else {
+        @export(__negdf2, .{ .name = "__negdf2", .linkage = common.linkage });
+    }
+}
+
+fn __negdf2(a: f64) callconv(.C) f64 {
+    return common.fneg(a);
+}
+
+fn __aeabi_dneg(a: f64) callconv(.AAPCS) f64 {
+    return common.fneg(a);
+}
lib/compiler_rt/negsf2.zig
@@ -0,0 +1,19 @@
+const common = @import("./common.zig");
+
+pub const panic = common.panic;
+
+comptime {
+    if (common.want_aeabi) {
+        @export(__aeabi_fneg, .{ .name = "__aeabi_fneg", .linkage = common.linkage });
+    } else {
+        @export(__negsf2, .{ .name = "__negsf2", .linkage = common.linkage });
+    }
+}
+
+fn __negsf2(a: f32) callconv(.C) f32 {
+    return common.fneg(a);
+}
+
+fn __aeabi_fneg(a: f32) callconv(.AAPCS) f32 {
+    return common.fneg(a);
+}
lib/compiler_rt/negtf2.zig
@@ -0,0 +1,11 @@
+const common = @import("./common.zig");
+
+pub const panic = common.panic;
+
+comptime {
+    @export(__negtf2, .{ .name = "__negtf2", .linkage = common.linkage });
+}
+
+fn __negtf2(a: f128) callconv(.C) f128 {
+    return common.fneg(a);
+}
lib/compiler_rt/negXf2.zig
@@ -1,42 +0,0 @@
-const std = @import("std");
-const builtin = @import("builtin");
-const common = @import("common.zig");
-
-pub const panic = common.panic;
-
-comptime {
-    if (common.want_aeabi) {
-        @export(__aeabi_fneg, .{ .name = "__aeabi_fneg", .linkage = common.linkage });
-        @export(__aeabi_dneg, .{ .name = "__aeabi_dneg", .linkage = common.linkage });
-    } else {
-        @export(__negsf2, .{ .name = "__negsf2", .linkage = common.linkage });
-        @export(__negdf2, .{ .name = "__negdf2", .linkage = common.linkage });
-    }
-}
-
-pub fn __negsf2(a: f32) callconv(.C) f32 {
-    return negXf2(f32, a);
-}
-
-fn __aeabi_fneg(a: f32) callconv(.AAPCS) f32 {
-    return negXf2(f32, a);
-}
-
-pub fn __negdf2(a: f64) callconv(.C) f64 {
-    return negXf2(f64, a);
-}
-
-fn __aeabi_dneg(a: f64) callconv(.AAPCS) f64 {
-    return negXf2(f64, a);
-}
-
-inline fn negXf2(comptime T: type, a: T) T {
-    const Z = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
-
-    const significandBits = std.math.floatMantissaBits(T);
-    const exponentBits = std.math.floatExponentBits(T);
-
-    const signBit = (@as(Z, 1) << (significandBits + exponentBits));
-
-    return @bitCast(T, @bitCast(Z, a) ^ signBit);
-}
lib/compiler_rt/negxf2.zig
@@ -0,0 +1,11 @@
+const common = @import("./common.zig");
+
+pub const panic = common.panic;
+
+comptime {
+    @export(__negxf2, .{ .name = "__negxf2", .linkage = common.linkage });
+}
+
+fn __negxf2(a: f80) callconv(.C) f80 {
+    return common.fneg(a);
+}
lib/std/math/copysign.zig
@@ -13,7 +13,6 @@ pub fn copysign(magnitude: anytype, sign: @TypeOf(magnitude)) @TypeOf(magnitude)
 }
 
 test "math.copysign" {
-    if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
     inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| {
         try expect(copysign(@as(T, 1.0), @as(T, 1.0)) == 1.0);
         try expect(copysign(@as(T, 2.0), @as(T, -2.0)) == -2.0);
lib/std/math/signbit.zig
@@ -10,7 +10,6 @@ pub fn signbit(x: anytype) bool {
 }
 
 test "math.signbit" {
-    if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
     inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| {
         try expect(!signbit(@as(T, 0.0)));
         try expect(!signbit(@as(T, 1.0)));
lib/std/fmt.zig
@@ -2225,7 +2225,6 @@ test "float.scientific.precision" {
 }
 
 test "float.special" {
-    if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
     try expectFmt("f64: nan", "f64: {}", .{math.nan_f64});
     // negative nan is not defined by IEE 754,
     // and ARM thus normalizes it to positive nan
@@ -2237,7 +2236,6 @@ test "float.special" {
 }
 
 test "float.hexadecimal.special" {
-    if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
     try expectFmt("f64: nan", "f64: {x}", .{math.nan_f64});
     // negative nan is not defined by IEE 754,
     // and ARM thus normalizes it to positive nan
lib/compiler_rt.zig
@@ -4,12 +4,13 @@ comptime {
     _ = @import("compiler_rt/atomics.zig");
 
     _ = @import("compiler_rt/addf3.zig");
-    _ = @import("compiler_rt/adddf3.zig");
     _ = @import("compiler_rt/addsf3.zig");
+    _ = @import("compiler_rt/adddf3.zig");
     _ = @import("compiler_rt/addtf3.zig");
     _ = @import("compiler_rt/addxf3.zig");
-    _ = @import("compiler_rt/subdf3.zig");
+
     _ = @import("compiler_rt/subsf3.zig");
+    _ = @import("compiler_rt/subdf3.zig");
     _ = @import("compiler_rt/subtf3.zig");
     _ = @import("compiler_rt/subxf3.zig");
 
@@ -19,6 +20,11 @@ comptime {
     _ = @import("compiler_rt/multf3.zig");
     _ = @import("compiler_rt/mulxf3.zig");
 
+    _ = @import("compiler_rt/negsf2.zig");
+    _ = @import("compiler_rt/negdf2.zig");
+    _ = @import("compiler_rt/negtf2.zig");
+    _ = @import("compiler_rt/negxf2.zig");
+
     _ = @import("compiler_rt/comparef.zig");
     _ = @import("compiler_rt/cmpsf2.zig");
     _ = @import("compiler_rt/cmpdf2.zig");
@@ -172,8 +178,6 @@ comptime {
     _ = @import("compiler_rt/mulo.zig");
     _ = @import("compiler_rt/cmp.zig");
 
-    _ = @import("compiler_rt/negXf2.zig");
-
     _ = @import("compiler_rt/os_version_check.zig");
     _ = @import("compiler_rt/emutls.zig");
     _ = @import("compiler_rt/arm.zig");
src/arch/aarch64/CodeGen.zig
@@ -582,7 +582,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
             .floor,
             .ceil,
             .round,
-            .trunc_float
+            .trunc_float,
+            .neg,
             => try self.airUnaryMath(inst),
 
             .add_with_overflow => try self.airOverflow(inst),
src/arch/arm/CodeGen.zig
@@ -596,6 +596,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
             .ceil,
             .round,
             .trunc_float,
+            .neg,
             => try self.airUnaryMath(inst),
 
             .add_with_overflow => try self.airOverflow(inst),
src/arch/riscv64/CodeGen.zig
@@ -516,6 +516,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
             .ceil,
             .round,
             .trunc_float,
+            .neg,
             => try self.airUnaryMath(inst),
 
             .add_with_overflow => try self.airAddWithOverflow(inst),
src/arch/sparc64/CodeGen.zig
@@ -529,6 +529,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
             .ceil,
             .round,
             .trunc_float,
+            .neg,
             => @panic("TODO try self.airUnaryMath(inst)"),
 
             .add_with_overflow => try self.airAddSubWithOverflow(inst),
src/arch/wasm/CodeGen.zig
@@ -1607,6 +1607,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
         .log10,
         .fabs,
         .round,
+        .neg,
 
         .cmpxchg_weak,
         .cmpxchg_strong,
src/arch/x86_64/CodeGen.zig
@@ -605,6 +605,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
             .ceil,
             .round,
             .trunc_float,
+            .neg,
             => try self.airUnaryMath(inst),
 
             .add_with_overflow => try self.airAddSubShlWithOverflow(inst),
src/codegen/llvm/bindings.zig
@@ -549,6 +549,9 @@ pub const Builder = opaque {
     pub const buildFSub = LLVMBuildFSub;
     extern fn LLVMBuildFSub(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
 
+    pub const buildFNeg = LLVMBuildFNeg;
+    extern fn LLVMBuildFNeg(*const Builder, V: *const Value, Name: [*:0]const u8) *const Value;
+
     pub const buildSub = LLVMBuildSub;
     extern fn LLVMBuildSub(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
 
src/codegen/c.zig
@@ -1755,6 +1755,8 @@ 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_"),
 
+            .neg => try airNeg(f, inst),
+
             .sqrt,
             .sin,
             .cos,
@@ -4098,6 +4100,20 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
     return local;
 }
 
+fn airNeg(f: *Function, inst: Air.Inst.Index) !CValue {
+    if (f.liveness.isUnused(inst)) return CValue.none;
+
+    const un_op = f.air.instructions.items(.data)[inst].un_op;
+    const writer = f.object.writer();
+    const inst_ty = f.air.typeOfIndex(inst);
+    const operand = try f.resolveInst(un_op);
+    const local = try f.allocLocal(inst_ty, .Const);
+    try writer.writeAll("-");
+    try f.writeCValue(writer, operand);
+    try writer.writeAll(";\n");
+    return local;
+}
+
 fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
     if (f.liveness.isUnused(inst)) return CValue.none;
     const pl_op = f.air.instructions.items(.data)[inst].pl_op;
src/codegen/llvm.zig
@@ -4019,6 +4019,7 @@ pub const FuncGen = struct {
                 .ceil         => try self.airUnaryOp(inst, .ceil),
                 .round        => try self.airUnaryOp(inst, .round),
                 .trunc_float  => try self.airUnaryOp(inst, .trunc),
+                .neg          => try self.airUnaryOp(inst, .neg),
 
                 .cmp_eq  => try self.airCmp(inst, .eq),
                 .cmp_gt  => try self.airCmp(inst, .gt),
@@ -6545,13 +6546,14 @@ pub const FuncGen = struct {
         fabs,
         floor,
         fma,
+        fmax,
+        fmin,
+        fmod,
         log,
         log10,
         log2,
-        fmax,
-        fmin,
         mul,
-        fmod,
+        neg,
         round,
         sin,
         sqrt,
@@ -6584,6 +6586,7 @@ pub const FuncGen = struct {
         var fn_name_buf: [64]u8 = undefined;
         const strat: FloatOpStrat = if (intrinsics_allowed) switch (op) {
             // Some operations are dedicated LLVM instructions, not available as intrinsics
+            .neg => return self.builder.buildFNeg(params[0], ""),
             .add => return self.builder.buildFAdd(params[0], params[1], ""),
             .sub => return self.builder.buildFSub(params[0], params[1], ""),
             .mul => return self.builder.buildFMul(params[0], params[1], ""),
@@ -6595,6 +6598,11 @@ pub const FuncGen = struct {
         } else b: {
             const float_bits = scalar_ty.floatBits(target);
             break :b switch (op) {
+                .neg => FloatOpStrat{
+                    .libc = std.fmt.bufPrintZ(&fn_name_buf, "__neg{s}f2", .{
+                        compilerRtFloatAbbrev(float_bits),
+                    }) catch unreachable,
+                },
                 .add, .sub, .div, .mul => FloatOpStrat{
                     .libc = std.fmt.bufPrintZ(&fn_name_buf, "__{s}{s}f3", .{
                         @tagName(op), compilerRtFloatAbbrev(float_bits),
src/Air.zig
@@ -288,6 +288,11 @@ pub const Inst = struct {
         /// Rounds a floating pointer number to the nearest integer towards zero.
         /// Uses the `un_op` field.
         trunc_float,
+        /// Float negation. This affects the sign of zero, inf, and NaN, which is impossible
+        /// to do with sub. Integers are not allowed and must be represented with sub with
+        /// LHS of zero.
+        /// Uses the `un_op` field.
+        neg,
 
         /// `<`. Result type is always bool.
         /// Uses the `bin_op` field.
@@ -970,6 +975,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
         .ceil,
         .round,
         .trunc_float,
+        .neg,
         => return air.typeOf(datas[inst].un_op),
 
         .cmp_lt,
src/Liveness.zig
@@ -287,6 +287,7 @@ pub fn categorizeOperand(
         .ceil,
         .round,
         .trunc_float,
+        .neg,
         .cmp_lt_errors_len,
         => {
             const o = air_datas[inst].un_op;
@@ -834,6 +835,7 @@ fn analyzeInst(
         .ceil,
         .round,
         .trunc_float,
+        .neg,
         .cmp_lt_errors_len,
         .set_err_return_trace,
         => {
src/print_air.zig
@@ -168,6 +168,7 @@ const Writer = struct {
             .ceil,
             .round,
             .trunc_float,
+            .neg,
             .cmp_lt_errors_len,
             .set_err_return_trace,
             => try w.writeUnOp(s, inst),
src/Sema.zig
@@ -10070,12 +10070,14 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
     }
 
     if (rhs_scalar_ty.isAnyFloat()) {
-        // We handle comptime negation here to ensure negative zero is represented in the bits.
+        // We handle float negation here to ensure negative zero is represented in the bits.
         if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| {
             if (rhs_val.isUndef()) return sema.addConstUndef(rhs_ty);
             const target = sema.mod.getTarget();
             return sema.addConstant(rhs_ty, try rhs_val.floatNeg(rhs_ty, sema.arena, target));
         }
+        try sema.requireRuntimeBlock(block, rhs_src);
+        return block.addUnOp(.neg, rhs);
     }
 
     const lhs = if (rhs_ty.zigTypeTag() == .Vector)
test/behavior/floatop.zig
@@ -574,6 +574,7 @@ test "negation f32" {
     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
 
     const S = struct {
         fn doTheTest() !void {
@@ -593,6 +594,8 @@ test "negation f64" {
     if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
 
     const S = struct {
         fn doTheTest() !void {
@@ -707,3 +710,103 @@ test "comptime_float zero divided by zero produces zero" {
 
     try expect((0.0 / 0.0) == 0.0);
 }
+
+test "nan negation f16" {
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
+
+    const nan_comptime = comptime math.nan(f16);
+    const neg_nan_comptime = -nan_comptime;
+
+    var nan_runtime = math.nan(f16);
+    const neg_nan_runtime = -nan_runtime;
+
+    try expect(!math.signbit(nan_runtime));
+    try expect(math.signbit(neg_nan_runtime));
+
+    try expect(!math.signbit(nan_comptime));
+    try expect(math.signbit(neg_nan_comptime));
+}
+
+test "nan negation f32" {
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
+
+    const nan_comptime = comptime math.nan(f32);
+    const neg_nan_comptime = -nan_comptime;
+
+    var nan_runtime = math.nan(f32);
+    const neg_nan_runtime = -nan_runtime;
+
+    try expect(!math.signbit(nan_runtime));
+    try expect(math.signbit(neg_nan_runtime));
+
+    try expect(!math.signbit(nan_comptime));
+    try expect(math.signbit(neg_nan_comptime));
+}
+
+test "nan negation f64" {
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
+
+    const nan_comptime = comptime math.nan(f64);
+    const neg_nan_comptime = -nan_comptime;
+
+    var nan_runtime = math.nan(f64);
+    const neg_nan_runtime = -nan_runtime;
+
+    try expect(!math.signbit(nan_runtime));
+    try expect(math.signbit(neg_nan_runtime));
+
+    try expect(!math.signbit(nan_comptime));
+    try expect(math.signbit(neg_nan_comptime));
+}
+
+test "nan negation f128" {
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
+
+    const nan_comptime = comptime math.nan(f128);
+    const neg_nan_comptime = -nan_comptime;
+
+    var nan_runtime = math.nan(f128);
+    const neg_nan_runtime = -nan_runtime;
+
+    try expect(!math.signbit(nan_runtime));
+    try expect(math.signbit(neg_nan_runtime));
+
+    try expect(!math.signbit(nan_comptime));
+    try expect(math.signbit(neg_nan_comptime));
+}
+
+test "nan negation f80" {
+    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
+
+    const nan_comptime = comptime math.nan(f80);
+    const neg_nan_comptime = -nan_comptime;
+
+    var nan_runtime = math.nan(f80);
+    const neg_nan_runtime = -nan_runtime;
+
+    try expect(!math.signbit(nan_runtime));
+    try expect(math.signbit(neg_nan_runtime));
+
+    try expect(!math.signbit(nan_comptime));
+    try expect(math.signbit(neg_nan_comptime));
+}
CMakeLists.txt
@@ -608,7 +608,6 @@ set(ZIG_STAGE2_SOURCES
     "${CMAKE_SOURCE_DIR}/lib/compiler_rt/multf3.zig"
     "${CMAKE_SOURCE_DIR}/lib/compiler_rt/multi3.zig"
     "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulxf3.zig"
-    "${CMAKE_SOURCE_DIR}/lib/compiler_rt/negXf2.zig"
     "${CMAKE_SOURCE_DIR}/lib/compiler_rt/negXi2.zig"
     "${CMAKE_SOURCE_DIR}/lib/compiler_rt/negv.zig"
     "${CMAKE_SOURCE_DIR}/lib/compiler_rt/os_version_check.zig"
@@ -623,11 +622,15 @@ set(ZIG_STAGE2_SOURCES
     "${CMAKE_SOURCE_DIR}/lib/compiler_rt/sincos.zig"
     "${CMAKE_SOURCE_DIR}/lib/compiler_rt/sqrt.zig"
     "${CMAKE_SOURCE_DIR}/lib/compiler_rt/stack_probe.zig"
-    "${CMAKE_SOURCE_DIR}/lib/compiler_rt/subdf3.zig"
     "${CMAKE_SOURCE_DIR}/lib/compiler_rt/subo.zig"
     "${CMAKE_SOURCE_DIR}/lib/compiler_rt/subsf3.zig"
+    "${CMAKE_SOURCE_DIR}/lib/compiler_rt/subdf3.zig"
     "${CMAKE_SOURCE_DIR}/lib/compiler_rt/subtf3.zig"
     "${CMAKE_SOURCE_DIR}/lib/compiler_rt/subxf3.zig"
+    "${CMAKE_SOURCE_DIR}/lib/compiler_rt/negsf2.zig"
+    "${CMAKE_SOURCE_DIR}/lib/compiler_rt/negdf2.zig"
+    "${CMAKE_SOURCE_DIR}/lib/compiler_rt/negtf2.zig"
+    "${CMAKE_SOURCE_DIR}/lib/compiler_rt/negxf2.zig"
     "${CMAKE_SOURCE_DIR}/lib/compiler_rt/tan.zig"
     "${CMAKE_SOURCE_DIR}/lib/compiler_rt/trig.zig"
     "${CMAKE_SOURCE_DIR}/lib/compiler_rt/trunc.zig"