libc: implement common abs for various integer sizes (#23893)

* libc: implement common `abs` for various integer sizes

* libc: move imaxabs to inttypes.zig and don't use cInclude

* libc: delete `fabs` c implementations because already implemented in compiler_rt

* libc: export functions depending on the target libc

Previously all the functions that were exported were handled equally,
though some may exist and some not inside the same file. Moving the
checks inside the file allows handling different functions differently

* remove empty ifs in inttypes

Co-authored-by: Alex Rønne Petersen <alex@alexrp.com>

* remove empty ifs in stdlib

Co-authored-by: Alex Rønne Petersen <alex@alexrp.com>

* libc: use `@abs` for the absolute value calculation

---------

Co-authored-by: Alex Rønne Petersen <alex@alexrp.com>
This commit is contained in:
David 2025-05-21 00:57:38 +02:00 committed by GitHub
parent a63f7875f4
commit 55848363fd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
42 changed files with 65 additions and 428 deletions

View File

@ -14,6 +14,9 @@ else
std.debug.no_panic;
comptime {
_ = @import("c/inttypes.zig");
_ = @import("c/stdlib.zig");
if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
// Files specific to musl and wasi-libc.
_ = @import("c/string.zig");

20
lib/c/inttypes.zig Normal file
View File

@ -0,0 +1,20 @@
const std = @import("std");
const common = @import("common.zig");
const builtin = @import("builtin");
const intmax_t = std.c.intmax_t;
comptime {
if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
// Functions specific to musl and wasi-libc.
@export(&imaxabs, .{ .name = "imaxabs", .linkage = common.linkage, .visibility = common.visibility });
}
}
fn imaxabs(a: intmax_t) callconv(.c) intmax_t {
return @intCast(@abs(a));
}
test imaxabs {
const val: intmax_t = -10;
try std.testing.expectEqual(10, imaxabs(val));
}

39
lib/c/stdlib.zig Normal file
View File

@ -0,0 +1,39 @@
const std = @import("std");
const common = @import("common.zig");
const builtin = @import("builtin");
comptime {
if (builtin.target.isMuslLibC() or builtin.target.isWasiLibC()) {
// Functions specific to musl and wasi-libc.
@export(&abs, .{ .name = "abs", .linkage = common.linkage, .visibility = common.visibility });
@export(&labs, .{ .name = "labs", .linkage = common.linkage, .visibility = common.visibility });
@export(&llabs, .{ .name = "llabs", .linkage = common.linkage, .visibility = common.visibility });
}
}
fn abs(a: c_int) callconv(.c) c_int {
return @intCast(@abs(a));
}
fn labs(a: c_long) callconv(.c) c_long {
return @intCast(@abs(a));
}
fn llabs(a: c_longlong) callconv(.c) c_longlong {
return @intCast(@abs(a));
}
test abs {
const val: c_int = -10;
try std.testing.expectEqual(10, abs(val));
}
test labs {
const val: c_long = -10;
try std.testing.expectEqual(10, labs(val));
}
test llabs {
const val: c_longlong = -10;
try std.testing.expectEqual(10, llabs(val));
}

View File

@ -1,18 +0,0 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
float fabsf (float x);
float
fabsf (float x)
{
#if defined(__x86_64__) || defined(_AMD64_) || defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_)
return __builtin_fabsf (x);
#elif defined(__i386__) || defined(_X86_)
float res = 0.0F;
asm volatile ("fabs;" : "=t" (res) : "0" (x));
return res;
#endif /* defined(__x86_64__) || defined(_AMD64_) || defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) */
}

View File

@ -1,18 +0,0 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
long double fabsl (long double x);
long double
fabsl (long double x)
{
#if defined(__x86_64__) || defined(_AMD64_) || defined(__i386__) || defined(_X86_)
long double res = 0.0L;
asm volatile ("fabs;" : "=t" (res) : "0" (x));
return res;
#elif defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_)
return __builtin_fabsl (x);
#endif /* defined(__x86_64__) || defined(_AMD64_) || defined(__i386__) || defined(_X86_) */
}

View File

@ -1,7 +0,0 @@
#include <math.h>
double fabs(double x)
{
__asm__ ("fabs %d0, %d1" : "=w"(x) : "w"(x));
return x;
}

View File

@ -1,7 +0,0 @@
#include <math.h>
float fabsf(float x)
{
__asm__ ("fabs %s0, %s1" : "=w"(x) : "w"(x));
return x;
}

View File

@ -1,15 +0,0 @@
#include <math.h>
#if __ARM_PCS_VFP && __ARM_FP&8
double fabs(double x)
{
__asm__ ("vabs.f64 %P0, %P1" : "=w"(x) : "w"(x));
return x;
}
#else
#include "../fabs.c"
#endif

View File

@ -1,15 +0,0 @@
#include <math.h>
#if __ARM_PCS_VFP && !BROKEN_VFP_ASM
float fabsf(float x)
{
__asm__ ("vabs.f32 %0, %1" : "=t"(x) : "t"(x));
return x;
}
#else
#include "../fabsf.c"
#endif

View File

@ -1,9 +0,0 @@
#include <math.h>
#include <stdint.h>
double fabs(double x)
{
union {double f; uint64_t i;} u = {x};
u.i &= -1ULL/2;
return u.f;
}

View File

@ -1,9 +0,0 @@
#include <math.h>
#include <stdint.h>
float fabsf(float x)
{
union {float f; uint32_t i;} u = {x};
u.i &= 0x7fffffff;
return u.f;
}

View File

@ -1,15 +0,0 @@
#include "libm.h"
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
long double fabsl(long double x)
{
return fabs(x);
}
#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
long double fabsl(long double x)
{
union ldshape u = {x};
u.i.se &= 0x7fff;
return u.f;
}
#endif

View File

@ -1,7 +0,0 @@
#include <math.h>
double fabs(double x)
{
__asm__ ("fabs" : "+t"(x));
return x;
}

View File

@ -1,7 +0,0 @@
#include <math.h>
float fabsf(float x)
{
__asm__ ("fabs" : "+t"(x));
return x;
}

View File

@ -1,7 +0,0 @@
#include <math.h>
long double fabsl(long double x)
{
__asm__ ("fabs" : "+t"(x));
return x;
}

View File

@ -1,16 +0,0 @@
#if !defined(__mips_soft_float) && defined(__mips_abs2008)
#include <math.h>
double fabs(double x)
{
double r;
__asm__("abs.d %0,%1" : "=f"(r) : "f"(x));
return r;
}
#else
#include "../fabs.c"
#endif

View File

@ -1,16 +0,0 @@
#if !defined(__mips_soft_float) && defined(__mips_abs2008)
#include <math.h>
float fabsf(float x)
{
float r;
__asm__("abs.s %0,%1" : "=f"(r) : "f"(x));
return r;
}
#else
#include "../fabsf.c"
#endif

View File

@ -1,15 +0,0 @@
#include <math.h>
#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__) || defined(BROKEN_PPC_D_ASM)
#include "../fabs.c"
#else
double fabs(double x)
{
__asm__ ("fabs %0, %1" : "=d"(x) : "d"(x));
return x;
}
#endif

View File

@ -1,15 +0,0 @@
#include <math.h>
#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__)
#include "../fabsf.c"
#else
float fabsf(float x)
{
__asm__ ("fabs %0, %1" : "=f"(x) : "f"(x));
return x;
}
#endif

View File

@ -1,7 +0,0 @@
#include <math.h>
double fabs(double x)
{
__asm__ ("fabs %0, %1" : "=d"(x) : "d"(x));
return x;
}

View File

@ -1,7 +0,0 @@
#include <math.h>
float fabsf(float x)
{
__asm__ ("fabs %0, %1" : "=f"(x) : "f"(x));
return x;
}

View File

@ -1,15 +0,0 @@
#include <math.h>
#if __riscv_flen >= 64
double fabs(double x)
{
__asm__ ("fabs.d %0, %1" : "=f"(x) : "f"(x));
return x;
}
#else
#include "../fabs.c"
#endif

View File

@ -1,15 +0,0 @@
#include <math.h>
#if __riscv_flen >= 32
float fabsf(float x)
{
__asm__ ("fabs.s %0, %1" : "=f"(x) : "f"(x));
return x;
}
#else
#include "../fabsf.c"
#endif

View File

@ -1,15 +0,0 @@
#include <math.h>
#if __riscv_flen >= 64
double fabs(double x)
{
__asm__ ("fabs.d %0, %1" : "=f"(x) : "f"(x));
return x;
}
#else
#include "../fabs.c"
#endif

View File

@ -1,15 +0,0 @@
#include <math.h>
#if __riscv_flen >= 32
float fabsf(float x)
{
__asm__ ("fabs.s %0, %1" : "=f"(x) : "f"(x));
return x;
}
#else
#include "../fabsf.c"
#endif

View File

@ -1,15 +0,0 @@
#include <math.h>
#if defined(__HTM__) || __ARCH__ >= 9
double fabs(double x)
{
__asm__ ("lpdbr %0, %1" : "=f"(x) : "f"(x));
return x;
}
#else
#include "../fabs.c"
#endif

View File

@ -1,15 +0,0 @@
#include <math.h>
#if defined(__HTM__) || __ARCH__ >= 9
float fabsf(float x)
{
__asm__ ("lpebr %0, %1" : "=f"(x) : "f"(x));
return x;
}
#else
#include "../fabsf.c"
#endif

View File

@ -1,15 +0,0 @@
#include <math.h>
#if defined(__HTM__) || __ARCH__ >= 9
long double fabsl(long double x)
{
__asm__ ("lpxbr %0, %1" : "=f"(x) : "f"(x));
return x;
}
#else
#include "../fabsl.c"
#endif

View File

@ -1,9 +0,0 @@
.global fabs
.type fabs,@function
fabs:
xor %eax,%eax
dec %rax
shr %rax
movq %rax,%xmm1
andpd %xmm1,%xmm0
ret

View File

@ -1,7 +0,0 @@
.global fabsf
.type fabsf,@function
fabsf:
mov $0x7fffffff,%eax
movq %rax,%xmm1
andps %xmm1,%xmm0
ret

View File

@ -1,6 +0,0 @@
.global fabsl
.type fabsl,@function
fabsl:
fldt 8(%esp)
fabs
ret

View File

@ -1,10 +0,0 @@
#include <math.h>
double fabs(double x)
{
double t;
__asm__ ("pcmpeqd %0, %0" : "=x"(t)); // t = ~0
__asm__ ("psrlq $1, %0" : "+x"(t)); // t >>= 1
__asm__ ("andps %1, %0" : "+x"(x) : "x"(t)); // x &= t
return x;
}

View File

@ -1,10 +0,0 @@
#include <math.h>
float fabsf(float x)
{
float t;
__asm__ ("pcmpeqd %0, %0" : "=x"(t)); // t = ~0
__asm__ ("psrld $1, %0" : "+x"(t)); // t >>= 1
__asm__ ("andps %1, %0" : "+x"(x) : "x"(t)); // x &= t
return x;
}

View File

@ -1,7 +0,0 @@
#include <math.h>
long double fabsl(long double x)
{
__asm__ ("fabs" : "+t"(x));
return x;
}

View File

@ -1,6 +0,0 @@
#include <stdlib.h>
int abs(int a)
{
return a>0 ? a : -a;
}

View File

@ -1,6 +0,0 @@
#include <inttypes.h>
intmax_t imaxabs(intmax_t a)
{
return a>0 ? a : -a;
}

View File

@ -1,6 +0,0 @@
#include <stdlib.h>
long labs(long a)
{
return a>0 ? a : -a;
}

View File

@ -1,6 +0,0 @@
#include <stdlib.h>
long long llabs(long long a)
{
return a>0 ? a : -a;
}

View File

@ -10822,6 +10822,9 @@ else
b: c_longdouble,
};
pub const intmax_t = i64;
pub const uintmax_t = u64;
pub extern "c" fn pthread_getthreadid_np() c_int;
pub extern "c" fn pthread_set_name_np(thread: pthread_t, name: [*:0]const u8) void;
pub extern "c" fn pthread_get_name_np(thread: pthread_t, name: [*:0]u8, len: usize) void;

View File

@ -574,7 +574,6 @@ const mingw32_generic_src = [_][]const u8{
"gdtoa" ++ path.sep_str ++ "sum.c",
"gdtoa" ++ path.sep_str ++ "ulp.c",
"math" ++ path.sep_str ++ "coshl.c",
"math" ++ path.sep_str ++ "fabsl.c",
"math" ++ path.sep_str ++ "fp_consts.c",
"math" ++ path.sep_str ++ "fp_constsf.c",
"math" ++ path.sep_str ++ "fp_constsl.c",
@ -946,7 +945,6 @@ const mingw32_x86_src = [_][]const u8{
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "sinl_internal.S",
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "tanl.S",
// ucrtbase
"math" ++ path.sep_str ++ "fabsf.c",
"math" ++ path.sep_str ++ "nextafterl.c",
"math" ++ path.sep_str ++ "nexttoward.c",
"math" ++ path.sep_str ++ "nexttowardf.c",

View File

@ -825,8 +825,6 @@ const src_files = [_][]const u8{
"musl/src/malloc/replaced.c",
"musl/src/math/aarch64/ceil.c",
"musl/src/math/aarch64/ceilf.c",
"musl/src/math/aarch64/fabs.c",
"musl/src/math/aarch64/fabsf.c",
"musl/src/math/aarch64/floor.c",
"musl/src/math/aarch64/floorf.c",
"musl/src/math/aarch64/fma.c",
@ -859,8 +857,6 @@ const src_files = [_][]const u8{
"musl/src/math/acoshf.c",
"musl/src/math/acoshl.c",
"musl/src/math/acosl.c",
"musl/src/math/arm/fabs.c",
"musl/src/math/arm/fabsf.c",
"musl/src/math/arm/fma.c",
"musl/src/math/arm/fmaf.c",
"musl/src/math/arm/sqrt.c",
@ -917,9 +913,6 @@ const src_files = [_][]const u8{
"musl/src/math/expm1l.c",
"musl/src/math/__expo2.c",
"musl/src/math/__expo2f.c",
"musl/src/math/fabs.c",
"musl/src/math/fabsf.c",
"musl/src/math/fabsl.c",
"musl/src/math/fdim.c",
"musl/src/math/fdimf.c",
"musl/src/math/fdiml.c",
@ -968,9 +961,6 @@ const src_files = [_][]const u8{
"musl/src/math/i386/exp_ld.s",
"musl/src/math/i386/expl.s",
"musl/src/math/i386/expm1l.s",
"musl/src/math/i386/fabs.c",
"musl/src/math/i386/fabsf.c",
"musl/src/math/i386/fabsl.c",
"musl/src/math/i386/floorf.s",
"musl/src/math/i386/floorl.s",
"musl/src/math/i386/floor.s",
@ -1083,8 +1073,6 @@ const src_files = [_][]const u8{
"musl/src/math/__math_uflowf.c",
"musl/src/math/__math_xflow.c",
"musl/src/math/__math_xflowf.c",
"musl/src/math/mips/fabs.c",
"musl/src/math/mips/fabsf.c",
"musl/src/math/mips/sqrt.c",
"musl/src/math/mips/sqrtf.c",
"musl/src/math/modf.c",
@ -1107,8 +1095,6 @@ const src_files = [_][]const u8{
"musl/src/math/pow_data.c",
"musl/src/math/powerpc64/ceil.c",
"musl/src/math/powerpc64/ceilf.c",
"musl/src/math/powerpc64/fabs.c",
"musl/src/math/powerpc64/fabsf.c",
"musl/src/math/powerpc64/floor.c",
"musl/src/math/powerpc64/floorf.c",
"musl/src/math/powerpc64/fma.c",
@ -1127,8 +1113,6 @@ const src_files = [_][]const u8{
"musl/src/math/powerpc64/sqrtf.c",
"musl/src/math/powerpc64/trunc.c",
"musl/src/math/powerpc64/truncf.c",
"musl/src/math/powerpc/fabs.c",
"musl/src/math/powerpc/fabsf.c",
"musl/src/math/powerpc/fma.c",
"musl/src/math/powerpc/fmaf.c",
"musl/src/math/powerpc/sqrt.c",
@ -1151,8 +1135,6 @@ const src_files = [_][]const u8{
"musl/src/math/rintl.c",
"musl/src/math/riscv32/copysign.c",
"musl/src/math/riscv32/copysignf.c",
"musl/src/math/riscv32/fabs.c",
"musl/src/math/riscv32/fabsf.c",
"musl/src/math/riscv32/fma.c",
"musl/src/math/riscv32/fmaf.c",
"musl/src/math/riscv32/fmax.c",
@ -1163,8 +1145,6 @@ const src_files = [_][]const u8{
"musl/src/math/riscv32/sqrtf.c",
"musl/src/math/riscv64/copysign.c",
"musl/src/math/riscv64/copysignf.c",
"musl/src/math/riscv64/fabs.c",
"musl/src/math/riscv64/fabsf.c",
"musl/src/math/riscv64/fma.c",
"musl/src/math/riscv64/fmaf.c",
"musl/src/math/riscv64/fmax.c",
@ -1179,9 +1159,6 @@ const src_files = [_][]const u8{
"musl/src/math/s390x/ceil.c",
"musl/src/math/s390x/ceilf.c",
"musl/src/math/s390x/ceill.c",
"musl/src/math/s390x/fabs.c",
"musl/src/math/s390x/fabsf.c",
"musl/src/math/s390x/fabsl.c",
"musl/src/math/s390x/floor.c",
"musl/src/math/s390x/floorf.c",
"musl/src/math/s390x/floorl.c",
@ -1255,9 +1232,6 @@ const src_files = [_][]const u8{
"musl/src/math/x32/exp2l.s",
"musl/src/math/x32/expl.s",
"musl/src/math/x32/expm1l.s",
"musl/src/math/x32/fabsf.s",
"musl/src/math/x32/fabsl.s",
"musl/src/math/x32/fabs.s",
"musl/src/math/x32/floorl.s",
"musl/src/math/x32/fma.c",
"musl/src/math/x32/fmaf.c",
@ -1287,9 +1261,6 @@ const src_files = [_][]const u8{
"musl/src/math/x86_64/exp2l.s",
"musl/src/math/x86_64/expl.s",
"musl/src/math/x86_64/expm1l.s",
"musl/src/math/x86_64/fabs.c",
"musl/src/math/x86_64/fabsf.c",
"musl/src/math/x86_64/fabsl.c",
"musl/src/math/x86_64/floorl.s",
"musl/src/math/x86_64/fma.c",
"musl/src/math/x86_64/fmaf.c",
@ -1809,7 +1780,6 @@ const src_files = [_][]const u8{
"musl/src/stdio/vwscanf.c",
"musl/src/stdio/wprintf.c",
"musl/src/stdio/wscanf.c",
"musl/src/stdlib/abs.c",
"musl/src/stdlib/atof.c",
"musl/src/stdlib/atoi.c",
"musl/src/stdlib/atol.c",
@ -1819,11 +1789,8 @@ const src_files = [_][]const u8{
"musl/src/stdlib/ecvt.c",
"musl/src/stdlib/fcvt.c",
"musl/src/stdlib/gcvt.c",
"musl/src/stdlib/imaxabs.c",
"musl/src/stdlib/imaxdiv.c",
"musl/src/stdlib/labs.c",
"musl/src/stdlib/ldiv.c",
"musl/src/stdlib/llabs.c",
"musl/src/stdlib/lldiv.c",
"musl/src/stdlib/qsort.c",
"musl/src/stdlib/qsort_nr.c",

View File

@ -751,7 +751,6 @@ const libc_top_half_src_files = [_][]const u8{
"musl/src/math/expm1.c",
"musl/src/math/expm1f.c",
"musl/src/math/expm1l.c",
"musl/src/math/fabsl.c",
"musl/src/math/fdim.c",
"musl/src/math/fdimf.c",
"musl/src/math/fdiml.c",
@ -1024,7 +1023,6 @@ const libc_top_half_src_files = [_][]const u8{
"musl/src/stdio/vwscanf.c",
"musl/src/stdio/wprintf.c",
"musl/src/stdio/wscanf.c",
"musl/src/stdlib/abs.c",
"musl/src/stdlib/atof.c",
"musl/src/stdlib/atoi.c",
"musl/src/stdlib/atol.c",
@ -1034,11 +1032,8 @@ const libc_top_half_src_files = [_][]const u8{
"musl/src/stdlib/ecvt.c",
"musl/src/stdlib/fcvt.c",
"musl/src/stdlib/gcvt.c",
"musl/src/stdlib/imaxabs.c",
"musl/src/stdlib/imaxdiv.c",
"musl/src/stdlib/labs.c",
"musl/src/stdlib/ldiv.c",
"musl/src/stdlib/llabs.c",
"musl/src/stdlib/lldiv.c",
"musl/src/stdlib/qsort.c",
"musl/src/stdlib/qsort_nr.c",