mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
Fix Clang support
The amalgamated release is now confirmed to be working with Clang, including its integrated assembler. Fixes #41
This commit is contained in:
parent
e06c90fafc
commit
d7733579d3
103 changed files with 384 additions and 359 deletions
|
@ -24,7 +24,7 @@
|
||||||
/ @param rdi points to nonempty array
|
/ @param rdi points to nonempty array
|
||||||
/ @param rsi is item count divisible by 16
|
/ @param rsi is item count divisible by 16
|
||||||
/ @note needs avx2 (haswell+)
|
/ @note needs avx2 (haswell+)
|
||||||
windex$avx2:
|
windex_avx2:
|
||||||
push %rbp
|
push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
.profilable
|
.profilable
|
||||||
|
@ -64,7 +64,7 @@ windex$avx2:
|
||||||
5: vzeroupper
|
5: vzeroupper
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
.endfn windex$avx2,globl
|
.endfn windex_avx2,globl
|
||||||
|
|
||||||
.rodata.cst32
|
.rodata.cst32
|
||||||
.Lidx: .short 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
.Lidx: .short 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include "dsp/tty/tty.h"
|
#include "dsp/tty/tty.h"
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
|
|
||||||
unsigned windex$k8(short *a, size_t n) {
|
unsigned windex_k8(short *a, size_t n) {
|
||||||
unsigned short min, res, i;
|
unsigned short min, res, i;
|
||||||
res = 0;
|
res = 0;
|
||||||
min = a[0];
|
min = a[0];
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
/ @param rdi points to nonempty array
|
/ @param rdi points to nonempty array
|
||||||
/ @param esi is 16-byte aligned 8+ / 8 multiple array item count
|
/ @param esi is 16-byte aligned 8+ / 8 multiple array item count
|
||||||
/ @note needs sse4 (nehalem+)
|
/ @note needs sse4 (nehalem+)
|
||||||
windex$sse4:
|
windex_sse4:
|
||||||
push %rbp
|
push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
.profilable
|
.profilable
|
||||||
|
@ -54,7 +54,7 @@ windex$sse4:
|
||||||
movzwl -32(%rbp,%rax,2),%eax
|
movzwl -32(%rbp,%rax,2),%eax
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
.endfn windex$sse4,globl
|
.endfn windex_sse4,globl
|
||||||
|
|
||||||
.rodata.cst16
|
.rodata.cst16
|
||||||
.Lidx: .short 0,1,2,3,4,5,6,7
|
.Lidx: .short 0,1,2,3,4,5,6,7
|
||||||
|
|
|
@ -27,14 +27,14 @@ windex: .quad 0
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 300,_init_windex
|
.init.start 300,_init_windex
|
||||||
ezlea windex$avx2,ax
|
ezlea windex_avx2,ax
|
||||||
#if !X86_NEED(AVX2)
|
#if !X86_NEED(AVX2)
|
||||||
ezlea windex$sse4,dx
|
ezlea windex_sse4,dx
|
||||||
testb X86_HAVE(AVX2)+kCpuids(%rip)
|
testb X86_HAVE(AVX2)+kCpuids(%rip)
|
||||||
cmovz %rdx,%rax
|
cmovz %rdx,%rax
|
||||||
#endif /* AVX2 */
|
#endif /* AVX2 */
|
||||||
#if !X86_NEED(SSE4_2)
|
#if !X86_NEED(SSE4_2)
|
||||||
ezlea windex$k8,dx
|
ezlea windex_k8,dx
|
||||||
testb X86_HAVE(SSE4_2)+kCpuids(%rip)
|
testb X86_HAVE(SSE4_2)+kCpuids(%rip)
|
||||||
cmovz %rdx,%rax
|
cmovz %rdx,%rax
|
||||||
#endif /* SSE4 */
|
#endif /* SSE4 */
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "libc/sysv/consts/s.h"
|
#include "libc/sysv/consts/s.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
int fstat$metal(int fd, struct stat *st) {
|
int fstat_metal(int fd, struct stat *st) {
|
||||||
if (fd < 0) return einval();
|
if (fd < 0) return einval();
|
||||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
|
if (fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
|
||||||
memset(st, 0, sizeof(*st));
|
memset(st, 0, sizeof(*st));
|
||||||
|
|
|
@ -35,7 +35,7 @@ int fstat(int fd, struct stat *st) {
|
||||||
if (!IsMetal()) {
|
if (!IsMetal()) {
|
||||||
return sys_fstat(fd, st);
|
return sys_fstat(fd, st);
|
||||||
} else {
|
} else {
|
||||||
return fstat$metal(fd, st);
|
return fstat_metal(fd, st);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||||
|
|
|
@ -290,14 +290,14 @@ unsigned __wincrash_nt(struct NtExceptionPointers *);
|
||||||
│ cosmopolitan § syscalls » metal ─╬─│┼
|
│ cosmopolitan § syscalls » metal ─╬─│┼
|
||||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||||
|
|
||||||
int fstat$metal(int, struct stat *);
|
int fstat_metal(int, struct stat *);
|
||||||
|
|
||||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||||
│ cosmopolitan § syscalls » drivers ─╬─│┼
|
│ cosmopolitan § syscalls » drivers ─╬─│┼
|
||||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||||
|
|
||||||
ssize_t readv$serial(struct Fd *, const struct iovec *, int) hidden;
|
ssize_t readv_serial(struct Fd *, const struct iovec *, int) hidden;
|
||||||
ssize_t writev$serial(struct Fd *, const struct iovec *, int) hidden;
|
ssize_t writev_serial(struct Fd *, const struct iovec *, int) hidden;
|
||||||
|
|
||||||
#undef sigset
|
#undef sigset
|
||||||
#undef i32
|
#undef i32
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
int ioctl$default(int fd, uint64_t request, void *memory) {
|
int ioctl_default(int fd, uint64_t request, void *memory) {
|
||||||
int rc;
|
int rc;
|
||||||
int64_t handle;
|
int64_t handle;
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include "libc/sysv/consts/termios.h"
|
#include "libc/sysv/consts/termios.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
textwindows int ioctl$sys_tcgets_nt(int ignored, struct termios *tio) {
|
textwindows int ioctl_tcgets_nt(int ignored, struct termios *tio) {
|
||||||
int64_t in, out;
|
int64_t in, out;
|
||||||
bool32 inok, outok;
|
bool32 inok, outok;
|
||||||
uint32_t inmode, outmode;
|
uint32_t inmode, outmode;
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
#include "libc/calls/termios.internal.h"
|
#include "libc/calls/termios.internal.h"
|
||||||
#include "libc/sysv/consts/termios.h"
|
#include "libc/sysv/consts/termios.h"
|
||||||
|
|
||||||
int ioctl$sys_tcgets_nt(int, struct termios *);
|
int ioctl_tcgets_nt(int, struct termios *) hidden;
|
||||||
|
|
||||||
static int ioctl$sys_tcgets(int fd, struct termios *tio) {
|
static int ioctl_tcgets_sysv(int fd, struct termios *tio) {
|
||||||
int rc;
|
int rc;
|
||||||
union metatermios t;
|
union metatermios t;
|
||||||
if ((rc = sys_ioctl(fd, TCGETS, &t)) != -1) {
|
if ((rc = sys_ioctl(fd, TCGETS, &t)) != -1) {
|
||||||
|
@ -39,10 +39,10 @@ static int ioctl$sys_tcgets(int fd, struct termios *tio) {
|
||||||
* @see ioctl(fd, TCGETS, tio) dispatches here
|
* @see ioctl(fd, TCGETS, tio) dispatches here
|
||||||
* @see ioctl(fd, TIOCGETA, tio) dispatches here
|
* @see ioctl(fd, TIOCGETA, tio) dispatches here
|
||||||
*/
|
*/
|
||||||
int ioctl$tcgets(int fd, struct termios *tio) {
|
int ioctl_tcgets(int fd, struct termios *tio) {
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
return ioctl$sys_tcgets(fd, tio);
|
return ioctl_tcgets_sysv(fd, tio);
|
||||||
} else {
|
} else {
|
||||||
return ioctl$sys_tcgets_nt(fd, tio);
|
return ioctl_tcgets_nt(fd, tio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "libc/sysv/consts/termios.h"
|
#include "libc/sysv/consts/termios.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
textwindows int ioctl$sys_tcsets_nt(int ignored, uint64_t request,
|
textwindows int ioctl_tcsets_nt(int ignored, uint64_t request,
|
||||||
const struct termios *tio) {
|
const struct termios *tio) {
|
||||||
int64_t in, out;
|
int64_t in, out;
|
||||||
bool32 inok, outok;
|
bool32 inok, outok;
|
||||||
|
|
|
@ -22,9 +22,9 @@
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/sysv/consts/termios.h"
|
#include "libc/sysv/consts/termios.h"
|
||||||
|
|
||||||
int ioctl$sys_tcsets_nt(int, uint64_t, const struct termios *);
|
int ioctl_tcsets_nt(int, uint64_t, const struct termios *);
|
||||||
|
|
||||||
static int ioctl$sys_tcsets(int fd, uint64_t request,
|
static int ioctl_tcsets_sysv(int fd, uint64_t request,
|
||||||
const struct termios *tio) {
|
const struct termios *tio) {
|
||||||
union metatermios t;
|
union metatermios t;
|
||||||
return sys_ioctl(fd, request, termios2host(&t, tio));
|
return sys_ioctl(fd, request, termios2host(&t, tio));
|
||||||
|
@ -37,10 +37,10 @@ static int ioctl$sys_tcsets(int fd, uint64_t request,
|
||||||
* @see ioctl(fd, TCSETS{,W,F}, tio) dispatches here
|
* @see ioctl(fd, TCSETS{,W,F}, tio) dispatches here
|
||||||
* @see ioctl(fd, TIOCGETA{,W,F}, tio) dispatches here
|
* @see ioctl(fd, TIOCGETA{,W,F}, tio) dispatches here
|
||||||
*/
|
*/
|
||||||
int ioctl$tcsets(int fd, uint64_t request, const struct termios *tio) {
|
int ioctl_tcsets(int fd, uint64_t request, const struct termios *tio) {
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
return ioctl$sys_tcsets(fd, request, tio);
|
return ioctl_tcsets_sysv(fd, request, tio);
|
||||||
} else {
|
} else {
|
||||||
return ioctl$sys_tcsets_nt(fd, request, tio);
|
return ioctl_tcsets_nt(fd, request, tio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
textwindows int ioctl$sys_tiocgwinsz_nt(int fd, struct winsize *ws) {
|
textwindows int ioctl_tiocgwinsz_nt(int fd, struct winsize *ws) {
|
||||||
int i, fds[3];
|
int i, fds[3];
|
||||||
uint32_t mode;
|
uint32_t mode;
|
||||||
struct NtConsoleScreenBufferInfoEx sbinfo;
|
struct NtConsoleScreenBufferInfoEx sbinfo;
|
||||||
|
|
|
@ -21,17 +21,17 @@
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/sysv/consts/termios.h"
|
#include "libc/sysv/consts/termios.h"
|
||||||
|
|
||||||
int ioctl$sys_tiocgwinsz_nt(int, struct winsize *);
|
int ioctl_tiocgwinsz_nt(int, struct winsize *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns width and height of terminal.
|
* Returns width and height of terminal.
|
||||||
*
|
*
|
||||||
* @see ioctl(fd, TIOCGWINSZ, ws) dispatches here
|
* @see ioctl(fd, TIOCGWINSZ, ws) dispatches here
|
||||||
*/
|
*/
|
||||||
int ioctl$tiocgwinsz(int fd, struct winsize *ws) {
|
int ioctl_tiocgwinsz(int fd, struct winsize *ws) {
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
return sys_ioctl(fd, TIOCGWINSZ, ws);
|
return sys_ioctl(fd, TIOCGWINSZ, ws);
|
||||||
} else {
|
} else {
|
||||||
return ioctl$sys_tiocgwinsz_nt(fd, ws);
|
return ioctl_tiocgwinsz_nt(fd, ws);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
textwindows int ioctl$sys_tiocswinsz_nt(int fd, const struct winsize *ws) {
|
textwindows int ioctl_tiocswinsz_nt(int fd, const struct winsize *ws) {
|
||||||
uint32_t mode;
|
uint32_t mode;
|
||||||
struct NtCoord coord;
|
struct NtCoord coord;
|
||||||
if (!ws) return efault();
|
if (!ws) return efault();
|
||||||
|
|
|
@ -21,17 +21,17 @@
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/sysv/consts/termios.h"
|
#include "libc/sysv/consts/termios.h"
|
||||||
|
|
||||||
int ioctl$sys_tiocswinsz_nt(int, const struct winsize *);
|
int ioctl_tiocswinsz_nt(int, const struct winsize *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns width and height of terminal.
|
* Returns width and height of terminal.
|
||||||
*
|
*
|
||||||
* @see ioctl(fd, TIOCSWINSZ, ws) dispatches here
|
* @see ioctl(fd, TIOCSWINSZ, ws) dispatches here
|
||||||
*/
|
*/
|
||||||
int ioctl$tiocswinsz(int fd, const struct winsize *ws) {
|
int ioctl_tiocswinsz(int fd, const struct winsize *ws) {
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
return sys_ioctl(fd, TIOCSWINSZ, ws);
|
return sys_ioctl(fd, TIOCSWINSZ, ws);
|
||||||
} else {
|
} else {
|
||||||
return ioctl$sys_tiocswinsz_nt(fd, ws);
|
return ioctl_tiocswinsz_nt(fd, ws);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,5 +29,5 @@
|
||||||
*/
|
*/
|
||||||
int(ioctl)(int fd, uint64_t request, void *memory) {
|
int(ioctl)(int fd, uint64_t request, void *memory) {
|
||||||
__IOCTL_DISPATCH(EQUAL, fd, request, memory);
|
__IOCTL_DISPATCH(EQUAL, fd, request, memory);
|
||||||
return ioctl$default(fd, request, memory);
|
return ioctl_default(fd, request, memory);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,31 +16,31 @@ int ioctl(int, uint64_t, void *);
|
||||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||||
|
|
||||||
#define ioctl(FD, REQUEST, MEMORY) ioctl$dispatch(FD, REQUEST, MEMORY)
|
#define ioctl(FD, REQUEST, MEMORY) ioctl_dispatch(FD, REQUEST, MEMORY)
|
||||||
|
|
||||||
#define __IOCTL_DISPATCH(CMP, FD, REQUEST, MEMORY) \
|
#define __IOCTL_DISPATCH(CMP, FD, REQUEST, MEMORY) \
|
||||||
do { \
|
do { \
|
||||||
if (CMP(request, TIOCGWINSZ)) return ioctl$tiocgwinsz(FD, MEMORY); \
|
if (CMP(request, TIOCGWINSZ)) return ioctl_tiocgwinsz(FD, MEMORY); \
|
||||||
if (CMP(request, TIOCSWINSZ)) return ioctl$tiocswinsz(FD, MEMORY); \
|
if (CMP(request, TIOCSWINSZ)) return ioctl_tiocswinsz(FD, MEMORY); \
|
||||||
if (CMP(request, TCGETS)) return ioctl$tcgets(FD, MEMORY); \
|
if (CMP(request, TCGETS)) return ioctl_tcgets(FD, MEMORY); \
|
||||||
if (CMP(request, TCSETS)) return ioctl$tcsets(FD, REQUEST, MEMORY); \
|
if (CMP(request, TCSETS)) return ioctl_tcsets(FD, REQUEST, MEMORY); \
|
||||||
if (CMP(request, TCSETSW)) return ioctl$tcsets(FD, REQUEST, MEMORY); \
|
if (CMP(request, TCSETSW)) return ioctl_tcsets(FD, REQUEST, MEMORY); \
|
||||||
if (CMP(request, TCSETSF)) return ioctl$tcsets(FD, REQUEST, MEMORY); \
|
if (CMP(request, TCSETSF)) return ioctl_tcsets(FD, REQUEST, MEMORY); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
int ioctl$tcgets(int, void *);
|
int ioctl_tcgets(int, void *);
|
||||||
int ioctl$sys_tcgets_nt(int, void *);
|
int ioctl_tcgets_nt(int, void *);
|
||||||
int ioctl$tcsets(int, uint64_t, void *);
|
int ioctl_tcsets(int, uint64_t, void *);
|
||||||
int ioctl$sys_tcsets_nt(int, uint64_t, void *);
|
int ioctl_tcsets_nt(int, uint64_t, void *);
|
||||||
int ioctl$tiocgwinsz(int, void *);
|
int ioctl_tiocgwinsz(int, void *);
|
||||||
int ioctl$sys_tiocgwinsz_nt(int, void *);
|
int ioctl_tiocgwinsz_nt(int, void *);
|
||||||
int ioctl$tiocswinsz(int, void *);
|
int ioctl_tiocswinsz(int, void *);
|
||||||
int ioctl$sys_tiocswinsz_nt(int, void *);
|
int ioctl_tiocswinsz_nt(int, void *);
|
||||||
int ioctl$default(int, uint64_t, void *);
|
int ioctl_default(int, uint64_t, void *);
|
||||||
|
|
||||||
forceinline int ioctl$dispatch(int fd, uint64_t request, void *memory) {
|
forceinline int ioctl_dispatch(int fd, uint64_t request, void *memory) {
|
||||||
__IOCTL_DISPATCH(EQUIVALENT, fd, request, memory);
|
__IOCTL_DISPATCH(EQUIVALENT, fd, request, memory);
|
||||||
return ioctl$default(fd, request, memory);
|
return ioctl_default(fd, request, memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* GNUC && !ANSI */
|
#endif /* GNUC && !ANSI */
|
||||||
|
|
|
@ -73,11 +73,11 @@ static long double ConvertTicksToSeconds(uint64_t ticks) {
|
||||||
return 1 / 1e9 * ConvertTicksToNanos(ticks);
|
return 1 / 1e9 * ConvertTicksToNanos(ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
long double nowl$sys(void) {
|
long double nowl_sys(void) {
|
||||||
return dtime(CLOCK_REALTIME);
|
return dtime(CLOCK_REALTIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
long double nowl$art(void) {
|
long double nowl_art(void) {
|
||||||
uint64_t ticks;
|
uint64_t ticks;
|
||||||
if (!g_now.once) InitTime();
|
if (!g_now.once) InitTime();
|
||||||
ticks = unsignedsubtract(rdtsc(), g_now.k0);
|
ticks = unsignedsubtract(rdtsc(), g_now.k0);
|
||||||
|
|
|
@ -29,8 +29,8 @@ nowl: .quad 0
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 202,_init_nowl
|
.init.start 202,_init_nowl
|
||||||
ezlea nowl$sys,ax
|
ezlea nowl_sys,ax
|
||||||
ezlea nowl$art,cx
|
ezlea nowl_art,cx
|
||||||
testb X86_HAVE(INVTSC)+kCpuids(%rip)
|
testb X86_HAVE(INVTSC)+kCpuids(%rip)
|
||||||
cmovnz %rcx,%rax
|
cmovnz %rcx,%rax
|
||||||
stosq
|
stosq
|
||||||
|
|
|
@ -35,8 +35,8 @@
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
static textwindows int64_t sys_open_nt$impl(int dirfd, const char *path,
|
static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path,
|
||||||
uint32_t flags, int32_t mode) {
|
uint32_t flags, int32_t mode) {
|
||||||
uint32_t br;
|
uint32_t br;
|
||||||
int64_t handle;
|
int64_t handle;
|
||||||
char16_t path16[PATH_MAX];
|
char16_t path16[PATH_MAX];
|
||||||
|
@ -76,19 +76,19 @@ static textwindows int64_t sys_open_nt$impl(int dirfd, const char *path,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static textwindows ssize_t sys_open_nt$console(int dirfd,
|
static textwindows ssize_t sys_open_nt_console(int dirfd,
|
||||||
const struct NtMagicPaths *mp,
|
const struct NtMagicPaths *mp,
|
||||||
uint32_t flags, int32_t mode,
|
uint32_t flags, int32_t mode,
|
||||||
size_t fd) {
|
size_t fd) {
|
||||||
if (GetFileType(g_fds.p[STDIN_FILENO].handle) == kNtFileTypeChar &&
|
if (GetFileType(g_fds.p[STDIN_FILENO].handle) == kNtFileTypeChar &&
|
||||||
GetFileType(g_fds.p[STDOUT_FILENO].handle) == kNtFileTypeChar) {
|
GetFileType(g_fds.p[STDOUT_FILENO].handle) == kNtFileTypeChar) {
|
||||||
g_fds.p[fd].handle = g_fds.p[STDIN_FILENO].handle;
|
g_fds.p[fd].handle = g_fds.p[STDIN_FILENO].handle;
|
||||||
g_fds.p[fd].extra = g_fds.p[STDOUT_FILENO].handle;
|
g_fds.p[fd].extra = g_fds.p[STDOUT_FILENO].handle;
|
||||||
} else if ((g_fds.p[fd].handle = sys_open_nt$impl(
|
} else if ((g_fds.p[fd].handle = sys_open_nt_impl(
|
||||||
dirfd, mp->conin, (flags & ~O_ACCMODE) | O_RDONLY, mode)) !=
|
dirfd, mp->conin, (flags & ~O_ACCMODE) | O_RDONLY, mode)) !=
|
||||||
-1) {
|
-1) {
|
||||||
g_fds.p[fd].extra =
|
g_fds.p[fd].extra = sys_open_nt_impl(dirfd, mp->conout,
|
||||||
sys_open_nt$impl(dirfd, mp->conout, (flags & ~O_ACCMODE) | O_WRONLY, mode);
|
(flags & ~O_ACCMODE) | O_WRONLY, mode);
|
||||||
assert(g_fds.p[fd].extra != -1);
|
assert(g_fds.p[fd].extra != -1);
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -98,10 +98,10 @@ static textwindows ssize_t sys_open_nt$console(int dirfd,
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static textwindows ssize_t sys_open_nt$file(int dirfd, const char *file,
|
static textwindows ssize_t sys_open_nt_file(int dirfd, const char *file,
|
||||||
uint32_t flags, int32_t mode,
|
uint32_t flags, int32_t mode,
|
||||||
size_t fd) {
|
size_t fd) {
|
||||||
if ((g_fds.p[fd].handle = sys_open_nt$impl(dirfd, file, flags, mode)) != -1) {
|
if ((g_fds.p[fd].handle = sys_open_nt_impl(dirfd, file, flags, mode)) != -1) {
|
||||||
g_fds.p[fd].kind = kFdFile;
|
g_fds.p[fd].kind = kFdFile;
|
||||||
g_fds.p[fd].flags = flags;
|
g_fds.p[fd].flags = flags;
|
||||||
return fd;
|
return fd;
|
||||||
|
@ -111,14 +111,14 @@ static textwindows ssize_t sys_open_nt$file(int dirfd, const char *file,
|
||||||
}
|
}
|
||||||
|
|
||||||
textwindows ssize_t sys_open_nt(int dirfd, const char *file, uint32_t flags,
|
textwindows ssize_t sys_open_nt(int dirfd, const char *file, uint32_t flags,
|
||||||
int32_t mode) {
|
int32_t mode) {
|
||||||
int fd;
|
int fd;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
if ((fd = __reservefd()) == -1) return -1;
|
if ((fd = __reservefd()) == -1) return -1;
|
||||||
if ((flags & O_ACCMODE) == O_RDWR && !strcmp(file, kNtMagicPaths.devtty)) {
|
if ((flags & O_ACCMODE) == O_RDWR && !strcmp(file, kNtMagicPaths.devtty)) {
|
||||||
rc = sys_open_nt$console(dirfd, &kNtMagicPaths, flags, mode, fd);
|
rc = sys_open_nt_console(dirfd, &kNtMagicPaths, flags, mode, fd);
|
||||||
} else {
|
} else {
|
||||||
rc = sys_open_nt$file(dirfd, file, flags, mode, fd);
|
rc = sys_open_nt_file(dirfd, file, flags, mode, fd);
|
||||||
}
|
}
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
__releasefd(fd);
|
__releasefd(fd);
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
static struct OpenAnon { int count; } g_openanon;
|
static struct OpenAnon { int count; } g_openanon;
|
||||||
|
|
||||||
static void openanon$genpath(const char *name, struct OpenAnon *state,
|
static void openanon_genpath(const char *name, struct OpenAnon *state,
|
||||||
char pathbuf[hasatleast PATH_MAX]) {
|
char pathbuf[hasatleast PATH_MAX]) {
|
||||||
char c;
|
char c;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
@ -55,11 +55,11 @@ static void openanon$genpath(const char *name, struct OpenAnon *state,
|
||||||
assert(p < pe);
|
assert(p < pe);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int openanon$impl(const char *name, unsigned flags,
|
static int openanon_impl(const char *name, unsigned flags,
|
||||||
struct OpenAnon *state,
|
struct OpenAnon *state,
|
||||||
char pathbuf[hasatleast PATH_MAX]) {
|
char pathbuf[hasatleast PATH_MAX]) {
|
||||||
int fd;
|
int fd;
|
||||||
openanon$genpath(name, state, pathbuf);
|
openanon_genpath(name, state, pathbuf);
|
||||||
flags |= O_RDWR | O_CREAT | O_EXCL | O_TRUNC;
|
flags |= O_RDWR | O_CREAT | O_EXCL | O_TRUNC;
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
if ((fd = sys_openat(AT_FDCWD, pathbuf, flags, 0600)) != -1) {
|
if ((fd = sys_openat(AT_FDCWD, pathbuf, flags, 0600)) != -1) {
|
||||||
|
@ -95,5 +95,5 @@ static int openanon$impl(const char *name, unsigned flags,
|
||||||
*/
|
*/
|
||||||
int openanon(char *name, unsigned flags) {
|
int openanon(char *name, unsigned flags) {
|
||||||
char pathbuf[PATH_MAX];
|
char pathbuf[PATH_MAX];
|
||||||
return openanon$impl(name, flags, &g_openanon, pathbuf);
|
return openanon_impl(name, flags, &g_openanon, pathbuf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ static int GetFirstIov(struct iovec *iov, int iovlen) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t readv$serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
|
ssize_t readv_serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
|
||||||
size_t i, j, got = 0;
|
size_t i, j, got = 0;
|
||||||
if ((i = GetFirstIov(iov, iovlen)) != -1) {
|
if ((i = GetFirstIov(iov, iovlen)) != -1) {
|
||||||
while (!IsDataAvailable(fd)) asm("pause");
|
while (!IsDataAvailable(fd)) asm("pause");
|
||||||
|
|
|
@ -37,7 +37,7 @@ ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
|
||||||
return weaken(__zipos_read)(
|
return weaken(__zipos_read)(
|
||||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
|
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
|
||||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
|
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
|
||||||
return readv$serial(&g_fds.p[fd], iov, iovlen);
|
return readv_serial(&g_fds.p[fd], iov, iovlen);
|
||||||
} else if (!IsWindows()) {
|
} else if (!IsWindows()) {
|
||||||
return sys_readv(fd, iov, iovlen);
|
return sys_readv(fd, iov, iovlen);
|
||||||
} else if (fd < g_fds.n &&
|
} else if (fd < g_fds.n &&
|
||||||
|
|
|
@ -32,16 +32,16 @@ int posix_openpt(int) nodiscard;
|
||||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||||
|
|
||||||
#define tcsetattr(FD, OPT, TIO) tcsetattr$dispatch(FD, OPT, TIO)
|
#define tcsetattr(FD, OPT, TIO) tcsetattr_dispatch(FD, OPT, TIO)
|
||||||
forceinline int tcsetattr$dispatch(int fd, int opt, const struct termios *tio) {
|
forceinline int tcsetattr_dispatch(int fd, int opt, const struct termios *tio) {
|
||||||
if (EQUIVALENT(opt, TCSANOW)) return ioctl(fd, TCSETS, (void *)tio);
|
if (EQUIVALENT(opt, TCSANOW)) return ioctl(fd, TCSETS, (void *)tio);
|
||||||
if (EQUIVALENT(opt, TCSADRAIN)) return ioctl(fd, TCSETSW, (void *)tio);
|
if (EQUIVALENT(opt, TCSADRAIN)) return ioctl(fd, TCSETSW, (void *)tio);
|
||||||
if (EQUIVALENT(opt, TCSAFLUSH)) return ioctl(fd, TCSETSF, (void *)tio);
|
if (EQUIVALENT(opt, TCSAFLUSH)) return ioctl(fd, TCSETSF, (void *)tio);
|
||||||
return (tcsetattr)(fd, opt, tio);
|
return (tcsetattr)(fd, opt, tio);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define tcgetattr(FD, TIO) tcgetattr$dispatch(FD, TIO)
|
#define tcgetattr(FD, TIO) tcgetattr_dispatch(FD, TIO)
|
||||||
forceinline int tcgetattr$dispatch(int fd, const struct termios *tio) {
|
forceinline int tcgetattr_dispatch(int fd, const struct termios *tio) {
|
||||||
return ioctl(fd, TCGETS, (void *)tio);
|
return ioctl(fd, TCGETS, (void *)tio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/nexgen32e/uart.internal.h"
|
#include "libc/nexgen32e/uart.internal.h"
|
||||||
|
|
||||||
ssize_t writev$serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
|
ssize_t writev_serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
|
||||||
size_t i, j, wrote = 0;
|
size_t i, j, wrote = 0;
|
||||||
for (i = 0; i < iovlen; ++i) {
|
for (i = 0; i < iovlen; ++i) {
|
||||||
for (j = 0; j < iov[i].iov_len; ++j) {
|
for (j = 0; j < iov[i].iov_len; ++j) {
|
||||||
|
|
|
@ -40,7 +40,7 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
||||||
return weaken(__zipos_write)(
|
return weaken(__zipos_write)(
|
||||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
|
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
|
||||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
|
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
|
||||||
return writev$serial(&g_fds.p[fd], iov, iovlen);
|
return writev_serial(&g_fds.p[fd], iov, iovlen);
|
||||||
} else if (!IsWindows()) {
|
} else if (!IsWindows()) {
|
||||||
return sys_writev(fd, iov, iovlen);
|
return sys_writev(fd, iov, iovlen);
|
||||||
} else if (fd < g_fds.n &&
|
} else if (fd < g_fds.n &&
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "libc/crypto/rijndael.h"
|
#include "libc/crypto/rijndael.h"
|
||||||
#include "libc/nexgen32e/x86feature.h"
|
#include "libc/nexgen32e/x86feature.h"
|
||||||
|
|
||||||
forceinline aes_block_t rijndael$westmere(uint32_t n, aes_block_t x,
|
forceinline aes_block_t rijndael_westmere(uint32_t n, aes_block_t x,
|
||||||
const struct Rijndael *ctx) {
|
const struct Rijndael *ctx) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
x ^= ctx->rk[0].xmm;
|
x ^= ctx->rk[0].xmm;
|
||||||
|
@ -31,7 +31,7 @@ forceinline aes_block_t rijndael$westmere(uint32_t n, aes_block_t x,
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
static noinline aes_block_t rijndael$pure(uint32_t n, aes_block_t x,
|
static noinline aes_block_t rijndael_pure(uint32_t n, aes_block_t x,
|
||||||
const struct Rijndael *ctx) {
|
const struct Rijndael *ctx) {
|
||||||
uint32_t i, j;
|
uint32_t i, j;
|
||||||
__v16qu b1, b2;
|
__v16qu b1, b2;
|
||||||
|
@ -65,8 +65,8 @@ static noinline aes_block_t rijndael$pure(uint32_t n, aes_block_t x,
|
||||||
*/
|
*/
|
||||||
aes_block_t rijndael(uint32_t n, aes_block_t x, const struct Rijndael *ctx) {
|
aes_block_t rijndael(uint32_t n, aes_block_t x, const struct Rijndael *ctx) {
|
||||||
if (X86_HAVE(AES)) {
|
if (X86_HAVE(AES)) {
|
||||||
return rijndael$westmere(n, x, ctx);
|
return rijndael_westmere(n, x, ctx);
|
||||||
} else {
|
} else {
|
||||||
return rijndael$pure(n, x, ctx);
|
return rijndael_pure(n, x, ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "libc/crypto/rijndael.h"
|
#include "libc/crypto/rijndael.h"
|
||||||
#include "libc/nexgen32e/x86feature.h"
|
#include "libc/nexgen32e/x86feature.h"
|
||||||
|
|
||||||
forceinline aes_block_t unrijndael$westmere(uint32_t n, aes_block_t x,
|
forceinline aes_block_t unrijndael_westmere(uint32_t n, aes_block_t x,
|
||||||
const struct Rijndael *ctx) {
|
const struct Rijndael *ctx) {
|
||||||
x ^= ctx->rk[n--].xmm;
|
x ^= ctx->rk[n--].xmm;
|
||||||
do {
|
do {
|
||||||
|
@ -30,7 +30,7 @@ forceinline aes_block_t unrijndael$westmere(uint32_t n, aes_block_t x,
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
static noinline aes_block_t unrijndael$pure(uint32_t n, aes_block_t x,
|
static noinline aes_block_t unrijndael_pure(uint32_t n, aes_block_t x,
|
||||||
const struct Rijndael *ctx) {
|
const struct Rijndael *ctx) {
|
||||||
uint32_t j;
|
uint32_t j;
|
||||||
__v16qu b1, b2;
|
__v16qu b1, b2;
|
||||||
|
@ -57,8 +57,8 @@ static noinline aes_block_t unrijndael$pure(uint32_t n, aes_block_t x,
|
||||||
*/
|
*/
|
||||||
aes_block_t unrijndael(uint32_t n, aes_block_t x, const struct Rijndael *ctx) {
|
aes_block_t unrijndael(uint32_t n, aes_block_t x, const struct Rijndael *ctx) {
|
||||||
if (X86_HAVE(AES)) {
|
if (X86_HAVE(AES)) {
|
||||||
return unrijndael$westmere(n, x, ctx);
|
return unrijndael_westmere(n, x, ctx);
|
||||||
} else {
|
} else {
|
||||||
return unrijndael$pure(n, x, ctx);
|
return unrijndael_pure(n, x, ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "libc/crypto/rijndael.h"
|
#include "libc/crypto/rijndael.h"
|
||||||
#include "libc/nexgen32e/x86feature.h"
|
#include "libc/nexgen32e/x86feature.h"
|
||||||
|
|
||||||
static void unrijndaelinit$westmere(struct Rijndael *ctx, uint32_t n,
|
static void unrijndaelinit_westmere(struct Rijndael *ctx, uint32_t n,
|
||||||
aes_block_t k1, aes_block_t k2) {
|
aes_block_t k1, aes_block_t k2) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
aes_block_t x;
|
aes_block_t x;
|
||||||
|
@ -36,7 +36,7 @@ static void unrijndaelinit$westmere(struct Rijndael *ctx, uint32_t n,
|
||||||
XMM_DESTROY(x);
|
XMM_DESTROY(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
static relegated noinline void unrijndaelinit$pure(struct Rijndael *ctx,
|
static relegated noinline void unrijndaelinit_pure(struct Rijndael *ctx,
|
||||||
uint32_t n, aes_block_t k1,
|
uint32_t n, aes_block_t k1,
|
||||||
aes_block_t k2) {
|
aes_block_t k2) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
@ -62,8 +62,8 @@ static relegated noinline void unrijndaelinit$pure(struct Rijndael *ctx,
|
||||||
void unrijndaelinit(struct Rijndael *ctx, uint32_t n, aes_block_t k1,
|
void unrijndaelinit(struct Rijndael *ctx, uint32_t n, aes_block_t k1,
|
||||||
aes_block_t k2) {
|
aes_block_t k2) {
|
||||||
if (X86_HAVE(AES)) {
|
if (X86_HAVE(AES)) {
|
||||||
return unrijndaelinit$westmere(ctx, n, k1, k2);
|
return unrijndaelinit_westmere(ctx, n, k1, k2);
|
||||||
} else {
|
} else {
|
||||||
return unrijndaelinit$pure(ctx, n, k1, k2);
|
return unrijndaelinit_pure(ctx, n, k1, k2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,17 +66,17 @@
|
||||||
#define SFLINK(FMT) FMT
|
#define SFLINK(FMT) FMT
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
__asm__(".section .yoink\n\t"
|
__asm__(".section .yoink\n\t"
|
||||||
"nop\tntoa(%rip)\n\t"
|
"nopl\tntoa(%rip)\n\t"
|
||||||
"nop\tftoa(%rip)\n\t"
|
"nopl\tftoa(%rip)\n\t"
|
||||||
"nop\tkCp437(%rip)\n\t"
|
"nopl\tkCp437(%rip)\n\t"
|
||||||
"nop\tstrerror(%rip)\n\t"
|
"nopl\tstrerror(%rip)\n\t"
|
||||||
"nop\tstrnwidth(%rip)\n\t"
|
"nopl\tstrnwidth(%rip)\n\t"
|
||||||
"nop\tstrnwidth16(%rip)\n\t"
|
"nopl\tstrnwidth16(%rip)\n\t"
|
||||||
"nop\twcsnwidth(%rip)\n\t"
|
"nopl\twcsnwidth(%rip)\n\t"
|
||||||
"nop\tmalloc(%rip)\n\t"
|
"nopl\tmalloc(%rip)\n\t"
|
||||||
"nop\tcalloc(%rip)\n\t"
|
"nopl\tcalloc(%rip)\n\t"
|
||||||
"nop\tfree_s(%rip)\n\t"
|
"nopl\tfree_s(%rip)\n\t"
|
||||||
"nop\t__grow(%rip)\n\t"
|
"nopl\t__grow(%rip)\n\t"
|
||||||
".previous");
|
".previous");
|
||||||
#else
|
#else
|
||||||
#include "libc/fmt/palandprintf.internal.h"
|
#include "libc/fmt/palandprintf.internal.h"
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
#include "libc/mem/hook/hook.h"
|
#include "libc/mem/hook/hook.internal.h"
|
||||||
#include "libc/nt/enum/version.h"
|
#include "libc/nt/enum/version.h"
|
||||||
#include "libc/nt/runtime.h"
|
#include "libc/nt/runtime.h"
|
||||||
#include "libc/runtime/directmap.h"
|
#include "libc/runtime/directmap.h"
|
||||||
|
@ -711,15 +711,15 @@ void *__asan_get_current_fake_stack(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void __asan_install_malloc_hooks(void) {
|
void __asan_install_malloc_hooks(void) {
|
||||||
HOOK(hook$free, __asan_free);
|
HOOK(hook_free, __asan_free);
|
||||||
HOOK(hook$malloc, __asan_malloc);
|
HOOK(hook_malloc, __asan_malloc);
|
||||||
HOOK(hook$calloc, __asan_calloc);
|
HOOK(hook_calloc, __asan_calloc);
|
||||||
HOOK(hook$valloc, __asan_valloc);
|
HOOK(hook_valloc, __asan_valloc);
|
||||||
HOOK(hook$pvalloc, __asan_pvalloc);
|
HOOK(hook_pvalloc, __asan_pvalloc);
|
||||||
HOOK(hook$realloc, __asan_realloc);
|
HOOK(hook_realloc, __asan_realloc);
|
||||||
HOOK(hook$memalign, __asan_memalign);
|
HOOK(hook_memalign, __asan_memalign);
|
||||||
HOOK(hook$malloc_trim, __asan_malloc_trim);
|
HOOK(hook_malloc_trim, __asan_malloc_trim);
|
||||||
HOOK(hook$malloc_usable_size, __asan_malloc_usable_size);
|
HOOK(hook_malloc_usable_size, __asan_malloc_usable_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool __asan_is_mapped(int x) {
|
static bool __asan_is_mapped(int x) {
|
||||||
|
@ -813,9 +813,9 @@ textstartup void __asan_init(int argc, char **argv, char **envp,
|
||||||
REQUIRE(MAP_ANONYMOUS);
|
REQUIRE(MAP_ANONYMOUS);
|
||||||
REQUIRE(FindMemoryInterval);
|
REQUIRE(FindMemoryInterval);
|
||||||
REQUIRE(TrackMemoryInterval);
|
REQUIRE(TrackMemoryInterval);
|
||||||
if (weaken(hook$malloc) || weaken(hook$calloc) || weaken(hook$realloc) ||
|
if (weaken(hook_malloc) || weaken(hook_calloc) || weaken(hook_realloc) ||
|
||||||
weaken(hook$pvalloc) || weaken(hook$valloc) || weaken(hook$free) ||
|
weaken(hook_pvalloc) || weaken(hook_valloc) || weaken(hook_free) ||
|
||||||
weaken(hook$malloc_usable_size)) {
|
weaken(hook_malloc_usable_size)) {
|
||||||
REQUIRE(dlmemalign);
|
REQUIRE(dlmemalign);
|
||||||
REQUIRE(dlmalloc_usable_size);
|
REQUIRE(dlmalloc_usable_size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,5 +27,5 @@
|
||||||
/ @return rax is memory address, or NULL w/ errno
|
/ @return rax is memory address, or NULL w/ errno
|
||||||
/ @note overreliance on memalign is a sure way to fragment space
|
/ @note overreliance on memalign is a sure way to fragment space
|
||||||
/ @see dlcalloc()
|
/ @see dlcalloc()
|
||||||
calloc: jmp *hook$calloc(%rip)
|
calloc: jmp *hook_calloc(%rip)
|
||||||
.endfn calloc,globl
|
.endfn calloc,globl
|
||||||
|
|
|
@ -81,5 +81,5 @@ _ZdaPv:
|
||||||
.endfn _ZdaPv,weak
|
.endfn _ZdaPv,weak
|
||||||
_ZdlPv:
|
_ZdlPv:
|
||||||
/ operator delete(void*)
|
/ operator delete(void*)
|
||||||
jmp *hook$free(%rip)
|
jmp *hook_free(%rip)
|
||||||
.endfn _ZdlPv,weak
|
.endfn _ZdlPv,weak
|
||||||
|
|
|
@ -44,5 +44,5 @@ _Znwm:
|
||||||
test %rdi,%rdi
|
test %rdi,%rdi
|
||||||
jne 1f
|
jne 1f
|
||||||
mov $1,%edi
|
mov $1,%edi
|
||||||
1: jmp *hook$malloc(%rip)
|
1: jmp *hook_malloc(%rip)
|
||||||
.endfn _Znwm,weak
|
.endfn _Znwm,weak
|
||||||
|
|
|
@ -49,5 +49,5 @@ _ZnamSt11align_val_t:
|
||||||
cmp %rax,%rsi
|
cmp %rax,%rsi
|
||||||
cmovb %rax,%rsi
|
cmovb %rax,%rsi
|
||||||
xchg %rdi,%rsi
|
xchg %rdi,%rsi
|
||||||
jmp *hook$memalign(%rip)
|
jmp *hook_memalign(%rip)
|
||||||
.endfn _ZnamSt11align_val_t,weak
|
.endfn _ZnamSt11align_val_t,weak
|
||||||
|
|
|
@ -29,5 +29,5 @@
|
||||||
/
|
/
|
||||||
/ @param rdi is allocation address, which may be NULL
|
/ @param rdi is allocation address, which may be NULL
|
||||||
/ @see dlfree()
|
/ @see dlfree()
|
||||||
free: jmp *hook$free(%rip)
|
free: jmp *hook_free(%rip)
|
||||||
.endfn free,globl
|
.endfn free,globl
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
.initbss 202,_init_calloc
|
.initbss 202,_init_calloc
|
||||||
hook$calloc:
|
hook_calloc:
|
||||||
.quad 0
|
.quad 0
|
||||||
.endobj hook$calloc,globl,hidden
|
.endobj hook_calloc,globl,hidden
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 202,_init_calloc
|
.init.start 202,_init_calloc
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
.initbss 202,_init_free
|
.initbss 202,_init_free
|
||||||
hook$free:
|
hook_free:
|
||||||
.quad 0
|
.quad 0
|
||||||
.endobj hook$free,globl,hidden
|
.endobj hook_free,globl,hidden
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 202,_init_free
|
.init.start 202,_init_free
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_MEM_HOOK_HOOK_H_
|
|
||||||
#define COSMOPOLITAN_LIBC_MEM_HOOK_HOOK_H_
|
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
|
||||||
COSMOPOLITAN_C_START_
|
|
||||||
|
|
||||||
extern void (*hook$free)(void *);
|
|
||||||
extern void *(*hook$malloc)(size_t);
|
|
||||||
extern void *(*hook$calloc)(size_t, size_t);
|
|
||||||
extern void *(*hook$memalign)(size_t, size_t);
|
|
||||||
extern void *(*hook$realloc)(void *, size_t);
|
|
||||||
extern void *(*hook$realloc_in_place)(void *, size_t);
|
|
||||||
extern void *(*hook$valloc)(size_t);
|
|
||||||
extern void *(*hook$pvalloc)(size_t);
|
|
||||||
extern int (*hook$malloc_trim)(size_t);
|
|
||||||
extern size_t (*hook$malloc_usable_size)(const void *);
|
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
|
||||||
#endif /* COSMOPOLITAN_LIBC_MEM_HOOK_HOOK_H_ */
|
|
19
libc/mem/hook/hook.internal.h
Normal file
19
libc/mem/hook/hook.internal.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef COSMOPOLITAN_LIBC_MEM_HOOK_HOOK_H_
|
||||||
|
#define COSMOPOLITAN_LIBC_MEM_HOOK_HOOK_H_
|
||||||
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
extern void (*hook_free)(void *);
|
||||||
|
extern void *(*hook_malloc)(size_t);
|
||||||
|
extern void *(*hook_calloc)(size_t, size_t);
|
||||||
|
extern void *(*hook_memalign)(size_t, size_t);
|
||||||
|
extern void *(*hook_realloc)(void *, size_t);
|
||||||
|
extern void *(*hook_realloc_in_place)(void *, size_t);
|
||||||
|
extern void *(*hook_valloc)(size_t);
|
||||||
|
extern void *(*hook_pvalloc)(size_t);
|
||||||
|
extern int (*hook_malloc_trim)(size_t);
|
||||||
|
extern size_t (*hook_malloc_usable_size)(const void *);
|
||||||
|
|
||||||
|
COSMOPOLITAN_C_END_
|
||||||
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
#endif /* COSMOPOLITAN_LIBC_MEM_HOOK_HOOK_H_ */
|
|
@ -20,9 +20,9 @@
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
.initbss 202,_init_malloc
|
.initbss 202,_init_malloc
|
||||||
hook$malloc:
|
hook_malloc:
|
||||||
.quad 0
|
.quad 0
|
||||||
.endobj hook$malloc,globl,hidden
|
.endobj hook_malloc,globl,hidden
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 202,_init_malloc
|
.init.start 202,_init_malloc
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
.initbss 202,_init_malloc_trim
|
.initbss 202,_init_malloc_trim
|
||||||
hook$malloc_trim:
|
hook_malloc_trim:
|
||||||
.quad 0
|
.quad 0
|
||||||
.endobj hook$malloc_trim,globl,hidden
|
.endobj hook_malloc_trim,globl,hidden
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 202,_init_malloc_trim
|
.init.start 202,_init_malloc_trim
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
.initbss 202,_init_malloc_usable_size
|
.initbss 202,_init_malloc_usable_size
|
||||||
hook$malloc_usable_size:
|
hook_malloc_usable_size:
|
||||||
.quad 0
|
.quad 0
|
||||||
.endobj hook$malloc_usable_size,globl,hidden
|
.endobj hook_malloc_usable_size,globl,hidden
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 202,_init_malloc_usable_size
|
.init.start 202,_init_malloc_usable_size
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
.initbss 202,_init_memalign
|
.initbss 202,_init_memalign
|
||||||
hook$memalign:
|
hook_memalign:
|
||||||
.quad 0
|
.quad 0
|
||||||
.endobj hook$memalign,globl,hidden
|
.endobj hook_memalign,globl,hidden
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 202,_init_memalign
|
.init.start 202,_init_memalign
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
.initbss 202,_init_posix_memalign
|
.initbss 202,_init_posix_memalign
|
||||||
hook$posix_memalign:
|
hook_posix_memalign:
|
||||||
.quad 0
|
.quad 0
|
||||||
.endobj hook$posix_memalign,globl,hidden
|
.endobj hook_posix_memalign,globl,hidden
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 202,_init_posix_memalign
|
.init.start 202,_init_posix_memalign
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
.initbss 202,_init_pvalloc
|
.initbss 202,_init_pvalloc
|
||||||
hook$pvalloc:
|
hook_pvalloc:
|
||||||
.quad 0
|
.quad 0
|
||||||
.endobj hook$pvalloc,globl,hidden
|
.endobj hook_pvalloc,globl,hidden
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 202,_init_pvalloc
|
.init.start 202,_init_pvalloc
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
.initbss 202,_init_realloc
|
.initbss 202,_init_realloc
|
||||||
hook$realloc:
|
hook_realloc:
|
||||||
.quad 0
|
.quad 0
|
||||||
.endobj hook$realloc,globl,hidden
|
.endobj hook_realloc,globl,hidden
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 202,_init_realloc
|
.init.start 202,_init_realloc
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
.initbss 202,_init_realloc_in_place
|
.initbss 202,_init_realloc_in_place
|
||||||
hook$realloc_in_place:
|
hook_realloc_in_place:
|
||||||
.quad 0
|
.quad 0
|
||||||
.endobj hook$realloc_in_place,globl,hidden
|
.endobj hook_realloc_in_place,globl,hidden
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 202,_init_realloc_in_place
|
.init.start 202,_init_realloc_in_place
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
.initbss 202,_init_valloc
|
.initbss 202,_init_valloc
|
||||||
hook$valloc:
|
hook_valloc:
|
||||||
.quad 0
|
.quad 0
|
||||||
.endobj hook$valloc,globl,hidden
|
.endobj hook_valloc,globl,hidden
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 202,_init_valloc
|
.init.start 202,_init_valloc
|
||||||
|
|
|
@ -36,5 +36,5 @@
|
||||||
/ @return new memory, or NULL w/ errno
|
/ @return new memory, or NULL w/ errno
|
||||||
/ @note malloc(0) → malloc(32)
|
/ @note malloc(0) → malloc(32)
|
||||||
/ @see dlmalloc()
|
/ @see dlmalloc()
|
||||||
malloc: jmp *hook$malloc(%rip)
|
malloc: jmp *hook_malloc(%rip)
|
||||||
.endfn malloc,globl
|
.endfn malloc,globl
|
||||||
|
|
|
@ -23,5 +23,5 @@
|
||||||
/ @param rdi specifies bytes of memory to leave available
|
/ @param rdi specifies bytes of memory to leave available
|
||||||
/ @return 1 if it actually released any memory, else 0
|
/ @return 1 if it actually released any memory, else 0
|
||||||
malloc_trim:
|
malloc_trim:
|
||||||
jmp *hook$malloc_trim(%rip)
|
jmp *hook_malloc_trim(%rip)
|
||||||
.endfn malloc_trim,globl
|
.endfn malloc_trim,globl
|
||||||
|
|
|
@ -37,5 +37,5 @@
|
||||||
/ @return rax is total number of bytes
|
/ @return rax is total number of bytes
|
||||||
/ @see dlmalloc_usable_size()
|
/ @see dlmalloc_usable_size()
|
||||||
malloc_usable_size:
|
malloc_usable_size:
|
||||||
jmp *hook$malloc_usable_size(%rip)
|
jmp *hook_malloc_usable_size(%rip)
|
||||||
.endfn malloc_usable_size,globl
|
.endfn malloc_usable_size,globl
|
||||||
|
|
|
@ -35,5 +35,5 @@
|
||||||
/ @note overreliance on memalign is a sure way to fragment space
|
/ @note overreliance on memalign is a sure way to fragment space
|
||||||
/ @see dlmemalign()
|
/ @see dlmemalign()
|
||||||
memalign:
|
memalign:
|
||||||
jmp *hook$memalign(%rip)
|
jmp *hook_memalign(%rip)
|
||||||
.endfn memalign,globl
|
.endfn memalign,globl
|
||||||
|
|
|
@ -32,5 +32,5 @@
|
||||||
/ @param rdx is size_t size
|
/ @param rdx is size_t size
|
||||||
/ @return eax
|
/ @return eax
|
||||||
posix_memalign:
|
posix_memalign:
|
||||||
jmp *hook$posix_memalign(%rip)
|
jmp *hook_posix_memalign(%rip)
|
||||||
.endfn posix_memalign,globl
|
.endfn posix_memalign,globl
|
||||||
|
|
|
@ -26,5 +26,5 @@
|
||||||
/ @param rdi is number of bytes needed
|
/ @param rdi is number of bytes needed
|
||||||
/ @return rax is memory address, or NULL w/ errno
|
/ @return rax is memory address, or NULL w/ errno
|
||||||
/ @see dlpvalloc()
|
/ @see dlpvalloc()
|
||||||
pvalloc:jmp *hook$pvalloc(%rip)
|
pvalloc:jmp *hook_pvalloc(%rip)
|
||||||
.endfn pvalloc,globl
|
.endfn pvalloc,globl
|
||||||
|
|
|
@ -55,5 +55,5 @@
|
||||||
/ @note realloc(p≠0, n=0) → free(p)
|
/ @note realloc(p≠0, n=0) → free(p)
|
||||||
/ @see dlrealloc()
|
/ @see dlrealloc()
|
||||||
realloc:
|
realloc:
|
||||||
jmp *hook$realloc(%rip)
|
jmp *hook_realloc(%rip)
|
||||||
.endfn realloc,globl
|
.endfn realloc,globl
|
||||||
|
|
|
@ -34,5 +34,5 @@
|
||||||
/ @return rax is result, or NULL w/ errno
|
/ @return rax is result, or NULL w/ errno
|
||||||
/ @see dlrealloc_in_place()
|
/ @see dlrealloc_in_place()
|
||||||
realloc_in_place:
|
realloc_in_place:
|
||||||
jmp *hook$realloc_in_place(%rip)
|
jmp *hook_realloc_in_place(%rip)
|
||||||
.endfn realloc_in_place,globl
|
.endfn realloc_in_place,globl
|
||||||
|
|
|
@ -25,5 +25,5 @@
|
||||||
/ @param rdi is number of bytes needed
|
/ @param rdi is number of bytes needed
|
||||||
/ @return rax is memory address, or NULL w/ errno
|
/ @return rax is memory address, or NULL w/ errno
|
||||||
/ @see dlvalloc()
|
/ @see dlvalloc()
|
||||||
valloc: jmp *hook$valloc(%rip)
|
valloc: jmp *hook_valloc(%rip)
|
||||||
.endfn valloc,globl
|
.endfn valloc,globl
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
/ @see “Fast CRC Computation for Generic Polynomials Using
|
/ @see “Fast CRC Computation for Generic Polynomials Using
|
||||||
/ PCLMULQDQ Instruction” V. Gopal, E. Ozturk, et al.,
|
/ PCLMULQDQ Instruction” V. Gopal, E. Ozturk, et al.,
|
||||||
/ 2009, intel.ly/2ySEwL0
|
/ 2009, intel.ly/2ySEwL0
|
||||||
crc32$pclmul:
|
crc32_pclmul:
|
||||||
.leafprologue
|
.leafprologue
|
||||||
.profilable
|
.profilable
|
||||||
movdqu (%rsi),%xmm7
|
movdqu (%rsi),%xmm7
|
||||||
|
@ -136,7 +136,8 @@ crc32$pclmul:
|
||||||
pxor %xmm1,%xmm0
|
pxor %xmm1,%xmm0
|
||||||
pextrd $1,%xmm0,%eax
|
pextrd $1,%xmm0,%eax
|
||||||
.leafepilogue
|
.leafepilogue
|
||||||
.endfn crc32$pclmul,globl,hidden
|
.endfn crc32_pclmul,globl,hidden
|
||||||
|
.source __FILE__
|
||||||
|
|
||||||
/ Definitions of the bit-reflected domain constants k1,k2,k3, etc.
|
/ Definitions of the bit-reflected domain constants k1,k2,k3, etc.
|
||||||
/ and the CRC32+Barrett polynomials given at the end of the paper.
|
/ and the CRC32+Barrett polynomials given at the end of the paper.
|
||||||
|
@ -259,4 +260,3 @@ crc32$pclmul:
|
||||||
4194304 7.025 7.059 7.030 462
|
4194304 7.025 7.059 7.030 462
|
||||||
8388607 7.082 6.980 6.997 464
|
8388607 7.082 6.980 6.997 464
|
||||||
8388608 7.051 6.985 6.999 464 */
|
8388608 7.051 6.985 6.999 464 */
|
||||||
.source __FILE__
|
|
||||||
|
|
|
@ -6,9 +6,9 @@ COSMOPOLITAN_C_START_
|
||||||
void crc32init(uint32_t[hasatleast 256], uint32_t);
|
void crc32init(uint32_t[hasatleast 256], uint32_t);
|
||||||
uint32_t crc32_z(uint32_t, const void *, size_t);
|
uint32_t crc32_z(uint32_t, const void *, size_t);
|
||||||
extern uint32_t (*const crc32c)(uint32_t, const void *, size_t);
|
extern uint32_t (*const crc32c)(uint32_t, const void *, size_t);
|
||||||
uint32_t crc32c$pure(uint32_t, const void *, size_t) strlenesque hidden;
|
uint32_t crc32c_pure(uint32_t, const void *, size_t) strlenesque hidden;
|
||||||
uint32_t crc32c$sse42(uint32_t, const void *, size_t) strlenesque hidden;
|
uint32_t crc32c_sse42(uint32_t, const void *, size_t) strlenesque hidden;
|
||||||
uint32_t crc32$pclmul(uint32_t, const void *, size_t) hidden;
|
uint32_t crc32_pclmul(uint32_t, const void *, size_t) hidden;
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
/ @param rsi is number of elements in rdi
|
/ @param rsi is number of elements in rdi
|
||||||
/ @note public domain
|
/ @note public domain
|
||||||
/ @see en.wikipedia.org/wiki/Sorting_network
|
/ @see en.wikipedia.org/wiki/Sorting_network
|
||||||
djbsort$avx2:
|
djbsort_avx2:
|
||||||
push %rbp
|
push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
push %r15
|
push %r15
|
||||||
|
@ -275,7 +275,7 @@ djbsort$avx2:
|
||||||
call int32_sort_2power
|
call int32_sort_2power
|
||||||
lea (%r12,%rbx,4),%rdi
|
lea (%r12,%rbx,4),%rdi
|
||||||
mov %r14,%rsi
|
mov %r14,%rsi
|
||||||
call djbsort$avx2
|
call djbsort_avx2
|
||||||
.L175: mov %rbx,%r14
|
.L175: mov %rbx,%r14
|
||||||
mov %r13,%rsi
|
mov %r13,%rsi
|
||||||
mov %r12,%rdi
|
mov %r12,%rdi
|
||||||
|
@ -798,7 +798,7 @@ djbsort$avx2:
|
||||||
pop %r15
|
pop %r15
|
||||||
pop %rbp
|
pop %rbp
|
||||||
ret
|
ret
|
||||||
.endfn djbsort$avx2,globl,hidden
|
.endfn djbsort_avx2,globl,hidden
|
||||||
|
|
||||||
minmax_vector:
|
minmax_vector:
|
||||||
cmp $7,%rdx
|
cmp $7,%rdx
|
||||||
|
|
|
@ -27,7 +27,7 @@ typedef uint32_t vbitmask_t;
|
||||||
/**
|
/**
|
||||||
* Returns how many bytes the utf16 string would be as utf8.
|
* Returns how many bytes the utf16 string would be as utf8.
|
||||||
*/
|
*/
|
||||||
int strcmp$avx2(const char *s1, const char *s2) {
|
int strcmp_avx2(const char *s1, const char *s2) {
|
||||||
if (s1 == s2) return 0;
|
if (s1 == s2) return 0;
|
||||||
const unsigned char *p1 = (const unsigned char *)s1;
|
const unsigned char *p1 = (const unsigned char *)s1;
|
||||||
const unsigned char *p2 = (const unsigned char *)s2;
|
const unsigned char *p2 = (const unsigned char *)s2;
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "libc/nexgen32e/strstr.inc"
|
#include "libc/nexgen32e/strstr.inc"
|
||||||
|
|
||||||
/ TODO(jart): Fix me.
|
/ TODO(jart): Fix me.
|
||||||
strstr$sse42:
|
strstr_sse42:
|
||||||
.leafprologue
|
.leafprologue
|
||||||
mov %rdi,%rax
|
mov %rdi,%rax
|
||||||
xor %ecx,%ecx
|
xor %ecx,%ecx
|
||||||
|
@ -38,5 +38,5 @@ strstr$sse42:
|
||||||
jmp 5f # youtu.be/nVk1DjMtLWs
|
jmp 5f # youtu.be/nVk1DjMtLWs
|
||||||
4: xor %eax,%eax
|
4: xor %eax,%eax
|
||||||
5: .leafepilogue
|
5: .leafepilogue
|
||||||
.endfn strstr$sse42,globl,hidden
|
.endfn strstr_sse42,globl,hidden
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
|
@ -51,10 +51,10 @@ static textwindows ssize_t sendfile_linux2nt(int outfd, int infd,
|
||||||
static ssize_t sendfile_linux2netflix(int outfd, int infd,
|
static ssize_t sendfile_linux2netflix(int outfd, int infd,
|
||||||
int64_t *inout_opt_inoffset,
|
int64_t *inout_opt_inoffset,
|
||||||
size_t uptobytes) {
|
size_t uptobytes) {
|
||||||
int sendfile$netflix(int32_t infd, int32_t outfd, int64_t offset,
|
int sys_sendfile_netflix(int32_t infd, int32_t outfd, int64_t offset,
|
||||||
size_t nbytes, const void *opt_hdtr,
|
size_t nbytes, const void *opt_hdtr,
|
||||||
int64_t *out_opt_sbytes,
|
int64_t *out_opt_sbytes,
|
||||||
int32_t flags) asm("sys_sendfile") hidden;
|
int32_t flags) asm("sys_sendfile") hidden;
|
||||||
int rc;
|
int rc;
|
||||||
int64_t offset, sbytes;
|
int64_t offset, sbytes;
|
||||||
if (inout_opt_inoffset) {
|
if (inout_opt_inoffset) {
|
||||||
|
@ -62,8 +62,8 @@ static ssize_t sendfile_linux2netflix(int outfd, int infd,
|
||||||
} else if ((offset = sys_lseek(infd, 0, SEEK_CUR)) == -1) {
|
} else if ((offset = sys_lseek(infd, 0, SEEK_CUR)) == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ((rc = sendfile$netflix(infd, outfd, offset, uptobytes, NULL, &sbytes,
|
if ((rc = sys_sendfile_netflix(infd, outfd, offset, uptobytes, NULL, &sbytes,
|
||||||
0)) != -1) {
|
0)) != -1) {
|
||||||
if (inout_opt_inoffset) *inout_opt_inoffset += sbytes;
|
if (inout_opt_inoffset) *inout_opt_inoffset += sbytes;
|
||||||
return sbytes;
|
return sbytes;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -23,7 +23,7 @@ extern const uint32_t kCrc32cTab[256];
|
||||||
/**
|
/**
|
||||||
* Computes Castagnoli CRC-32 on old computers.
|
* Computes Castagnoli CRC-32 on old computers.
|
||||||
*/
|
*/
|
||||||
uint32_t crc32c$pure(uint32_t init, const void *data, size_t size) {
|
uint32_t crc32c_pure(uint32_t init, const void *data, size_t size) {
|
||||||
const unsigned char *p = data;
|
const unsigned char *p = data;
|
||||||
uint32_t h = init ^ 0xffffffff;
|
uint32_t h = init ^ 0xffffffff;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
@ -34,7 +34,7 @@ uint32_t crc32c$pure(uint32_t init, const void *data, size_t size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
bench_crc32c$pure for #c per n where c ≈ 0.293ns
|
bench_crc32c_pure for #c per n where c ≈ 0.293ns
|
||||||
N x1 x8 x64 mBps
|
N x1 x8 x64 mBps
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
1 4305.000 91.375 44.203 74
|
1 4305.000 91.375 44.203 74
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
* Hashes data with hardware acceleration at 10GBps.
|
* Hashes data with hardware acceleration at 10GBps.
|
||||||
* @note needs Nehalem+ c. 2008 or Bulldozer+ c. 2011
|
* @note needs Nehalem+ c. 2008 or Bulldozer+ c. 2011
|
||||||
*/
|
*/
|
||||||
optimizespeed uint32_t crc32c$sse42(uint32_t init, const void *data, size_t n) {
|
optimizespeed uint32_t crc32c_sse42(uint32_t init, const void *data, size_t n) {
|
||||||
const unsigned char *p = (const unsigned char *)data;
|
const unsigned char *p = (const unsigned char *)data;
|
||||||
const unsigned char *pe = (const unsigned char *)data + n;
|
const unsigned char *pe = (const unsigned char *)data + n;
|
||||||
uint32_t h = init ^ 0xffffffff;
|
uint32_t h = init ^ 0xffffffff;
|
||||||
|
@ -42,7 +42,7 @@ optimizespeed uint32_t crc32c$sse42(uint32_t init, const void *data, size_t n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
bench_crc32c$sse42 for #c per n where c ≈ 0.293ns
|
bench_crc32c_sse42 for #c per n where c ≈ 0.293ns
|
||||||
N x1 x8 x64 mBps
|
N x1 x8 x64 mBps
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
1 877.000 43.375 40.359 81
|
1 877.000 43.375 40.359 81
|
||||||
|
|
|
@ -34,8 +34,8 @@ crc32c: .quad 0
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 300,_init_crc32c
|
.init.start 300,_init_crc32c
|
||||||
ezlea crc32c$pure,ax
|
ezlea crc32c_pure,ax
|
||||||
ezlea crc32c$sse42,cx
|
ezlea crc32c_sse42,cx
|
||||||
testb X86_HAVE(SSE4_2)+kCpuids(%rip)
|
testb X86_HAVE(SSE4_2)+kCpuids(%rip)
|
||||||
cmovnz %rcx,%rax
|
cmovnz %rcx,%rax
|
||||||
stosq
|
stosq
|
||||||
|
|
|
@ -42,7 +42,7 @@ uint32_t crc32_z(uint32_t h, const void *data, size_t size) {
|
||||||
if (data) {
|
if (data) {
|
||||||
h ^= 0xffffffff;
|
h ^= 0xffffffff;
|
||||||
if (size >= 64 && X86_HAVE(PCLMUL)) {
|
if (size >= 64 && X86_HAVE(PCLMUL)) {
|
||||||
h = crc32$pclmul(h, data, size); /* 51x faster */
|
h = crc32_pclmul(h, data, size); /* 51x faster */
|
||||||
skip = rounddown(size, 16);
|
skip = rounddown(size, 16);
|
||||||
} else {
|
} else {
|
||||||
skip = 0;
|
skip = 0;
|
||||||
|
|
|
@ -20,14 +20,14 @@
|
||||||
#include "libc/nexgen32e/nexgen32e.h"
|
#include "libc/nexgen32e/nexgen32e.h"
|
||||||
#include "libc/nexgen32e/x86feature.h"
|
#include "libc/nexgen32e/x86feature.h"
|
||||||
|
|
||||||
void djbsort$avx2(int32_t *, long);
|
void djbsort_avx2(int32_t *, long);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* D.J. Bernstein's outrageously fast integer sorting algorithm.
|
* D.J. Bernstein's outrageously fast integer sorting algorithm.
|
||||||
*/
|
*/
|
||||||
void djbsort(int32_t *a, size_t n) {
|
void djbsort(int32_t *a, size_t n) {
|
||||||
if (X86_HAVE(AVX2)) {
|
if (X86_HAVE(AVX2)) {
|
||||||
djbsort$avx2(a, n);
|
djbsort_avx2(a, n);
|
||||||
} else {
|
} else {
|
||||||
insertionsort(a, n);
|
insertionsort(a, n);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "libc/nexgen32e/cachesize.h"
|
#include "libc/nexgen32e/cachesize.h"
|
||||||
#include "libc/nexgen32e/cpuid4.internal.h"
|
#include "libc/nexgen32e/cpuid4.internal.h"
|
||||||
|
|
||||||
static unsigned getcachesize$cpuid4(int type, int level) {
|
static unsigned getcachesize_cpuid4(int type, int level) {
|
||||||
unsigned i, k;
|
unsigned i, k;
|
||||||
static int once;
|
static int once;
|
||||||
static unsigned char kCacheKey[8];
|
static unsigned char kCacheKey[8];
|
||||||
|
@ -53,5 +53,5 @@ static unsigned getcachesize$cpuid4(int type, int level) {
|
||||||
unsigned getcachesize(int type, int level) {
|
unsigned getcachesize(int type, int level) {
|
||||||
assert(1 <= type && type <= 3);
|
assert(1 <= type && type <= 3);
|
||||||
assert(level >= 1);
|
assert(level >= 1);
|
||||||
return getcachesize$cpuid4(type, level);
|
return getcachesize_cpuid4(type, level);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,11 @@ nodebuginfo forceinline bool32 iscont(wint_t c) {
|
||||||
return (c & 0300) == 0200;
|
return (c & 0300) == 0200;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *strstr$sse42(const char *, const char *) strlenesque hidden;
|
char *strstr_sse42(const char *, const char *) strlenesque hidden;
|
||||||
char16_t *strstr16$sse42(const char16_t *, const char16_t *) strlenesque hidden;
|
char16_t *strstr16_sse42(const char16_t *, const char16_t *) strlenesque hidden;
|
||||||
void *memmem$sse42(const void *, size_t, const void *,
|
void *memmem_sse42(const void *, size_t, const void *,
|
||||||
size_t) strlenesque hidden;
|
size_t) strlenesque hidden;
|
||||||
void sha256$x86(uint32_t[hasatleast 8], const uint8_t[hasatleast 64],
|
void sha256_x86(uint32_t[hasatleast 8], const uint8_t[hasatleast 64],
|
||||||
uint32_t) hidden;
|
uint32_t) hidden;
|
||||||
|
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -31,7 +31,7 @@ typedef long long xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
|
||||||
* @return dst
|
* @return dst
|
||||||
* @asyncsignalsafe
|
* @asyncsignalsafe
|
||||||
*/
|
*/
|
||||||
void *memmove$pure(void *dst, const void *src, size_t n) {
|
void *memmove_pure(void *dst, const void *src, size_t n) {
|
||||||
size_t i;
|
size_t i;
|
||||||
xmm_t v, w;
|
xmm_t v, w;
|
||||||
char *d, *r;
|
char *d, *r;
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
* @return p
|
* @return p
|
||||||
* @asyncsignalsafe
|
* @asyncsignalsafe
|
||||||
*/
|
*/
|
||||||
void *memset$pure(void *p, int c, size_t n) {
|
void *memset_pure(void *p, int c, size_t n) {
|
||||||
char *b;
|
char *b;
|
||||||
uint64_t x;
|
uint64_t x;
|
||||||
b = p;
|
b = p;
|
||||||
|
|
|
@ -85,7 +85,7 @@ void sha256_update(struct Sha256Ctx *ctx, const uint8_t *data, size_t size) {
|
||||||
#if 0
|
#if 0
|
||||||
if (!IsTiny() && size >= 64 &&
|
if (!IsTiny() && size >= 64 &&
|
||||||
(X86_HAVE(SHA) && X86_HAVE(SSE4_1) && X86_HAVE(SSSE3))) {
|
(X86_HAVE(SHA) && X86_HAVE(SSE4_1) && X86_HAVE(SSSE3))) {
|
||||||
sha256$x86(ctx->state, data, size);
|
sha256_x86(ctx->state, data, size);
|
||||||
i += rounddown(size, 16);
|
i += rounddown(size, 16);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "libc/intrin/pmovmskb.h"
|
#include "libc/intrin/pmovmskb.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
static noasan size_t stpcpy$sse2(char *d, const char *s, size_t i) {
|
static noasan size_t stpcpy_sse2(char *d, const char *s, size_t i) {
|
||||||
uint8_t v1[16], v2[16], vz[16];
|
uint8_t v1[16], v2[16], vz[16];
|
||||||
for (;;) {
|
for (;;) {
|
||||||
memset(vz, 0, 16);
|
memset(vz, 0, 16);
|
||||||
|
@ -52,7 +52,7 @@ char *stpcpy(char *d, const char *s) {
|
||||||
return d + i;
|
return d + i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i = stpcpy$sse2(d, s, i);
|
i = stpcpy_sse2(d, s, i);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!(d[i] = s[i])) {
|
if (!(d[i] = s[i])) {
|
||||||
return d + i;
|
return d + i;
|
||||||
|
|
|
@ -363,39 +363,39 @@ char *strsignal(int) returnsnonnull libcesque;
|
||||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||||
│ cosmopolitan § strings » address sanitizer ─╬─│┼
|
│ cosmopolitan § strings » address sanitizer ─╬─│┼
|
||||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||||
void *memset$pure(void *, int, size_t) memcpyesque;
|
void *memset_pure(void *, int, size_t) memcpyesque;
|
||||||
void *memmove$pure(void *, const void *, size_t) memcpyesque;
|
void *memmove_pure(void *, const void *, size_t) memcpyesque;
|
||||||
size_t strlen$pure(const char *) strlenesque;
|
size_t strlen_pure(const char *) strlenesque;
|
||||||
size_t strcspn$pure(const char *, const char *) strlenesque;
|
size_t strcspn_pure(const char *, const char *) strlenesque;
|
||||||
#if defined(__FSANITIZE_ADDRESS__)
|
#if defined(__FSANITIZE_ADDRESS__)
|
||||||
|
|
||||||
#define strcspn(STR, REJECT) strcspn$pure(STR, REJECT)
|
#define strcspn(STR, REJECT) strcspn_pure(STR, REJECT)
|
||||||
|
|
||||||
#undef strlen
|
#undef strlen
|
||||||
#define strlen(STR) \
|
#define strlen(STR) \
|
||||||
(__builtin_constant_p(STR) ? __builtin_strlen(STR) : strlen$pure(STR))
|
(__builtin_constant_p(STR) ? __builtin_strlen(STR) : strlen_pure(STR))
|
||||||
|
|
||||||
#undef memset
|
#undef memset
|
||||||
#define memset(DST, CHAR, SIZE) \
|
#define memset(DST, CHAR, SIZE) \
|
||||||
(__memcpy_isgoodsize(SIZE) ? __builtin_memset(DST, CHAR, SIZE) \
|
(__memcpy_isgoodsize(SIZE) ? __builtin_memset(DST, CHAR, SIZE) \
|
||||||
: memset$pure(DST, CHAR, SIZE))
|
: memset_pure(DST, CHAR, SIZE))
|
||||||
|
|
||||||
#undef memmove
|
#undef memmove
|
||||||
#define memmove(DST, SRC, SIZE) \
|
#define memmove(DST, SRC, SIZE) \
|
||||||
(__memcpy_isgoodsize(SIZE) ? __builtin_memmove(DST, SRC, SIZE) \
|
(__memcpy_isgoodsize(SIZE) ? __builtin_memmove(DST, SRC, SIZE) \
|
||||||
: memmove$pure(DST, SRC, SIZE))
|
: memmove_pure(DST, SRC, SIZE))
|
||||||
|
|
||||||
#undef memcpy
|
#undef memcpy
|
||||||
#define memcpy(DST, SRC, SIZE) \
|
#define memcpy(DST, SRC, SIZE) \
|
||||||
(__memcpy_isgoodsize(SIZE) ? __builtin_memcpy(DST, SRC, SIZE) \
|
(__memcpy_isgoodsize(SIZE) ? __builtin_memcpy(DST, SRC, SIZE) \
|
||||||
: memmove$pure(DST, SRC, SIZE))
|
: memmove_pure(DST, SRC, SIZE))
|
||||||
|
|
||||||
#undef mempcpy
|
#undef mempcpy
|
||||||
#define mempcpy(DST, SRC, SIZE) \
|
#define mempcpy(DST, SRC, SIZE) \
|
||||||
(__memcpy_isgoodsize(SIZE) ? __builtin_mempcpy(DST, SRC, SIZE) : ({ \
|
(__memcpy_isgoodsize(SIZE) ? __builtin_mempcpy(DST, SRC, SIZE) : ({ \
|
||||||
void *DsT = (DST); \
|
void *DsT = (DST); \
|
||||||
size_t SiZe = (SIZE); \
|
size_t SiZe = (SIZE); \
|
||||||
memmove$pure(DsT, SRC, SiZe); \
|
memmove_pure(DsT, SRC, SiZe); \
|
||||||
(void *)((char *)DsT + SiZe); \
|
(void *)((char *)DsT + SiZe); \
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
noasan static const unsigned char *strchr$x64(const unsigned char *p,
|
noasan static const unsigned char *strchr_x64(const unsigned char *p,
|
||||||
uint64_t c) {
|
uint64_t c) {
|
||||||
unsigned a, b;
|
unsigned a, b;
|
||||||
uint64_t w, x, y;
|
uint64_t w, x, y;
|
||||||
|
@ -63,7 +63,7 @@ char *strchr(const char *s, int c) {
|
||||||
if ((*s & 0xff) == c) return s;
|
if ((*s & 0xff) == c) return s;
|
||||||
if (!*s) return NULL;
|
if (!*s) return NULL;
|
||||||
}
|
}
|
||||||
r = (char *)strchr$x64((const unsigned char *)s, c);
|
r = (char *)strchr_x64((const unsigned char *)s, c);
|
||||||
assert(!r || *r || !c);
|
assert(!r || *r || !c);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
noasan static const unsigned char *strchrnul$x64(const unsigned char *p,
|
noasan static const unsigned char *strchrnul_x64(const unsigned char *p,
|
||||||
uint64_t c) {
|
uint64_t c) {
|
||||||
unsigned a, b;
|
unsigned a, b;
|
||||||
uint64_t w, x, y;
|
uint64_t w, x, y;
|
||||||
|
@ -63,7 +63,7 @@ char *strchrnul(const char *s, int c) {
|
||||||
if ((*s & 0xff) == c) return s;
|
if ((*s & 0xff) == c) return s;
|
||||||
if (!*s) return s;
|
if (!*s) return s;
|
||||||
}
|
}
|
||||||
r = (char *)strchrnul$x64((const unsigned char *)s, c);
|
r = (char *)strchrnul_x64((const unsigned char *)s, c);
|
||||||
assert((*r & 0xff) == c || !*r);
|
assert((*r & 0xff) == c || !*r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "libc/intrin/pmovmskb.h"
|
#include "libc/intrin/pmovmskb.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
static noasan size_t strcpy$sse2(char *d, const char *s, size_t i) {
|
static noasan size_t strcpy_sse2(char *d, const char *s, size_t i) {
|
||||||
uint8_t v1[16], v2[16], vz[16];
|
uint8_t v1[16], v2[16], vz[16];
|
||||||
for (;;) {
|
for (;;) {
|
||||||
memset(vz, 0, 16);
|
memset(vz, 0, 16);
|
||||||
|
@ -52,7 +52,7 @@ char *strcpy(char *d, const char *s) {
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i = strcpy$sse2(d, s, i);
|
i = strcpy_sse2(d, s, i);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!(d[i] = s[i])) {
|
if (!(d[i] = s[i])) {
|
||||||
return d;
|
return d;
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
* @see strspn(), strtok_r()
|
* @see strspn(), strtok_r()
|
||||||
* @asyncsignalsafe
|
* @asyncsignalsafe
|
||||||
*/
|
*/
|
||||||
size_t strcspn$pure(const char *s, const char *reject) {
|
size_t strcspn_pure(const char *s, const char *reject) {
|
||||||
size_t i, n;
|
size_t i, n;
|
||||||
unsigned m;
|
unsigned m;
|
||||||
char cv[16], sv[16];
|
char cv[16], sv[16];
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
static noasan size_t strlen$pure$x64(const char *s, size_t i) {
|
static noasan size_t strlen_pure_x64(const char *s, size_t i) {
|
||||||
uint64_t w;
|
uint64_t w;
|
||||||
const unsigned char *p;
|
const unsigned char *p;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -38,12 +38,12 @@ static noasan size_t strlen$pure$x64(const char *s, size_t i) {
|
||||||
/**
|
/**
|
||||||
* Returns length of NUL-terminated string.
|
* Returns length of NUL-terminated string.
|
||||||
*/
|
*/
|
||||||
size_t strlen$pure(const char *s) {
|
size_t strlen_pure(const char *s) {
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; (uintptr_t)(s + i) & 7; ++i) {
|
for (i = 0; (uintptr_t)(s + i) & 7; ++i) {
|
||||||
if (!s[i]) return i;
|
if (!s[i]) return i;
|
||||||
}
|
}
|
||||||
i = strlen$pure$x64(s, i);
|
i = strlen_pure_x64(s, i);
|
||||||
assert(!i || s[0]);
|
assert(!i || s[0]);
|
||||||
assert(!s[i]);
|
assert(!s[i]);
|
||||||
return i;
|
return i;
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
static noasan size_t strnlen$x64(const char *s, size_t n, size_t i) {
|
static noasan size_t strnlen_x64(const char *s, size_t n, size_t i) {
|
||||||
uint64_t w;
|
uint64_t w;
|
||||||
const unsigned char *p;
|
const unsigned char *p;
|
||||||
for (; i + 8 < n; i += 8) {
|
for (; i + 8 < n; i += 8) {
|
||||||
|
@ -48,7 +48,7 @@ size_t strnlen(const char *s, size_t n) {
|
||||||
for (i = 0; (uintptr_t)(s + i) & 7; ++i) {
|
for (i = 0; (uintptr_t)(s + i) & 7; ++i) {
|
||||||
if (i == n || !s[i]) return i;
|
if (i == n || !s[i]) return i;
|
||||||
}
|
}
|
||||||
i = strnlen$x64(s, n, i);
|
i = strnlen_x64(s, n, i);
|
||||||
for (;; ++i) {
|
for (;; ++i) {
|
||||||
if (i == n || !s[i]) break;
|
if (i == n || !s[i]) break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
static const int16_t kDel16[8] = {127, 127, 127, 127, 127, 127, 127, 127};
|
static const int16_t kDel16[8] = {127, 127, 127, 127, 127, 127, 127, 127};
|
||||||
|
|
||||||
/* 10x speedup for ascii */
|
/* 10x speedup for ascii */
|
||||||
static noasan axdx_t tprecode16to8$sse2(char *dst, size_t dstsize,
|
static noasan axdx_t tprecode16to8_sse2(char *dst, size_t dstsize,
|
||||||
const char16_t *src, axdx_t r) {
|
const char16_t *src, axdx_t r) {
|
||||||
int16_t v1[8], v2[8], v3[8], vz[8];
|
int16_t v1[8], v2[8], v3[8], vz[8];
|
||||||
memset(vz, 0, 16);
|
memset(vz, 0, 16);
|
||||||
|
@ -63,7 +63,7 @@ axdx_t tprecode16to8(char *dst, size_t dstsize, const char16_t *src) {
|
||||||
r.dx = 0;
|
r.dx = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!IsTiny() && !((uintptr_t)(src + r.dx) & 15)) {
|
if (!IsTiny() && !((uintptr_t)(src + r.dx) & 15)) {
|
||||||
r = tprecode16to8$sse2(dst, dstsize, src, r);
|
r = tprecode16to8_sse2(dst, dstsize, src, r);
|
||||||
}
|
}
|
||||||
if (!(x = src[r.dx++])) break;
|
if (!(x = src[r.dx++])) break;
|
||||||
if (IsUtf16Cont(x)) continue;
|
if (IsUtf16Cont(x)) continue;
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "libc/str/utf16.h"
|
#include "libc/str/utf16.h"
|
||||||
|
|
||||||
/* 34x speedup for ascii */
|
/* 34x speedup for ascii */
|
||||||
static noasan axdx_t tprecode8to16$sse2(char16_t *dst, size_t dstsize,
|
static noasan axdx_t tprecode8to16_sse2(char16_t *dst, size_t dstsize,
|
||||||
const char *src, axdx_t r) {
|
const char *src, axdx_t r) {
|
||||||
uint8_t v1[16], v2[16], vz[16];
|
uint8_t v1[16], v2[16], vz[16];
|
||||||
memset(vz, 0, 16);
|
memset(vz, 0, 16);
|
||||||
|
@ -61,7 +61,7 @@ axdx_t tprecode8to16(char16_t *dst, size_t dstsize, const char *src) {
|
||||||
r.dx = 0;
|
r.dx = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!IsTiny() && !((uintptr_t)(src + r.dx) & 15)) {
|
if (!IsTiny() && !((uintptr_t)(src + r.dx) & 15)) {
|
||||||
tprecode8to16$sse2(dst, dstsize, src, r);
|
tprecode8to16_sse2(dst, dstsize, src, r);
|
||||||
}
|
}
|
||||||
x = src[r.dx++] & 0xff;
|
x = src[r.dx++] & 0xff;
|
||||||
if (ThomPikeCont(x)) continue;
|
if (ThomPikeCont(x)) continue;
|
||||||
|
|
|
@ -137,20 +137,20 @@ void TearDown(void);
|
||||||
|
|
||||||
#define ASSERT_BINEQ(WANT, GOT) \
|
#define ASSERT_BINEQ(WANT, GOT) \
|
||||||
_Generic((WANT)[0], char \
|
_Generic((WANT)[0], char \
|
||||||
: assertBinaryEquals$hex, default \
|
: assertBinaryEquals_hex, default \
|
||||||
: assertBinaryEquals$cp437)(FILIFU WANT, GOT, -1, #GOT, true)
|
: assertBinaryEquals_cp437)(FILIFU WANT, GOT, -1, #GOT, true)
|
||||||
#define ASSERT_BINNE(NOPE, GOT) \
|
#define ASSERT_BINNE(NOPE, GOT) \
|
||||||
_Generic((NOPE)[0], char \
|
_Generic((NOPE)[0], char \
|
||||||
: assertBinaryNotEquals$hex, default \
|
: assertBinaryNotEquals_hex, default \
|
||||||
: assertBinaryNotEquals$cp437)(FILIFU NOPE, GOT, -1, #GOT, true)
|
: assertBinaryNotEquals_cp437)(FILIFU NOPE, GOT, -1, #GOT, true)
|
||||||
#define ASSERT_BINEQN(WANT, GOT, N) \
|
#define ASSERT_BINEQN(WANT, GOT, N) \
|
||||||
_Generic((WANT)[0], char \
|
_Generic((WANT)[0], char \
|
||||||
: assertBinaryEquals$hex, default \
|
: assertBinaryEquals_hex, default \
|
||||||
: assertBinaryEquals$cp437)(FILIFU WANT, GOT, N, #GOT, true)
|
: assertBinaryEquals_cp437)(FILIFU WANT, GOT, N, #GOT, true)
|
||||||
#define ASSERT_BINNEN(NOPE, GOT, N) \
|
#define ASSERT_BINNEN(NOPE, GOT, N) \
|
||||||
_Generic((NOPE)[0], char \
|
_Generic((NOPE)[0], char \
|
||||||
: assertBinaryNotEquals$hex, default \
|
: assertBinaryNotEquals_hex, default \
|
||||||
: assertBinaryNotEquals$cp437)(FILIFU NOPE, GOT, -1, #GOT, true)
|
: assertBinaryNotEquals_cp437)(FILIFU NOPE, GOT, -1, #GOT, true)
|
||||||
|
|
||||||
#define ASSERT_FLOAT_EQ(WANT, GOT) \
|
#define ASSERT_FLOAT_EQ(WANT, GOT) \
|
||||||
assertLongDoubleEquals(FILIFU WANT, GOT, #GOT, true)
|
assertLongDoubleEquals(FILIFU WANT, GOT, #GOT, true)
|
||||||
|
@ -195,20 +195,20 @@ void TearDown(void);
|
||||||
|
|
||||||
#define EXPECT_BINEQ(WANT, GOT) \
|
#define EXPECT_BINEQ(WANT, GOT) \
|
||||||
_Generic((WANT)[0], char \
|
_Generic((WANT)[0], char \
|
||||||
: assertBinaryEquals$hex, default \
|
: assertBinaryEquals_hex, default \
|
||||||
: assertBinaryEquals$cp437)(FILIFU WANT, GOT, -1, #GOT, false)
|
: assertBinaryEquals_cp437)(FILIFU WANT, GOT, -1, #GOT, false)
|
||||||
#define EXPECT_BINNE(NOPE, GOT) \
|
#define EXPECT_BINNE(NOPE, GOT) \
|
||||||
_Generic((NOPE)[0], char \
|
_Generic((NOPE)[0], char \
|
||||||
: assertBinaryNotEquals$hex, default \
|
: assertBinaryNotEquals_hex, default \
|
||||||
: assertBinaryNotEquals$cp437)(FILIFU NOPE, GOT, -1, #GOT, false)
|
: assertBinaryNotEquals_cp437)(FILIFU NOPE, GOT, -1, #GOT, false)
|
||||||
#define EXPECT_BINEQN(WANT, GOT, N) \
|
#define EXPECT_BINEQN(WANT, GOT, N) \
|
||||||
_Generic((WANT)[0], char \
|
_Generic((WANT)[0], char \
|
||||||
: assertBinaryEquals$hex, default \
|
: assertBinaryEquals_hex, default \
|
||||||
: assertBinaryEquals$cp437)(FILIFU WANT, GOT, N, #GOT, false)
|
: assertBinaryEquals_cp437)(FILIFU WANT, GOT, N, #GOT, false)
|
||||||
#define EXPECT_BINNEN(NOPE, GOT, N) \
|
#define EXPECT_BINNEN(NOPE, GOT, N) \
|
||||||
_Generic((NOPE)[0], char \
|
_Generic((NOPE)[0], char \
|
||||||
: assertBinaryNotEquals$hex, default \
|
: assertBinaryNotEquals_hex, default \
|
||||||
: assertBinaryNotEquals$cp437)(FILIFU NOPE, GOT, -1, #GOT, false)
|
: assertBinaryNotEquals_cp437)(FILIFU NOPE, GOT, -1, #GOT, false)
|
||||||
|
|
||||||
#define EXPECT_FLOAT_EQ(WANT, GOT) \
|
#define EXPECT_FLOAT_EQ(WANT, GOT) \
|
||||||
assertLongDoubleEquals(FILIFU WANT, GOT, #GOT, false)
|
assertLongDoubleEquals(FILIFU WANT, GOT, #GOT, false)
|
||||||
|
@ -536,7 +536,7 @@ forceinline void assertContains(FILIFU_ARGS size_t cw, const char *needle,
|
||||||
testlib_onfail2(isfatal);
|
testlib_onfail2(isfatal);
|
||||||
}
|
}
|
||||||
|
|
||||||
forceinline void assertBinaryEquals$cp437(FILIFU_ARGS const char16_t *want,
|
forceinline void assertBinaryEquals_cp437(FILIFU_ARGS const char16_t *want,
|
||||||
const void *got, size_t n,
|
const void *got, size_t n,
|
||||||
const char *gotcode, bool isfatal) {
|
const char *gotcode, bool isfatal) {
|
||||||
++g_testlib_ran;
|
++g_testlib_ran;
|
||||||
|
@ -549,7 +549,7 @@ forceinline void assertBinaryEquals$cp437(FILIFU_ARGS const char16_t *want,
|
||||||
testlib_onfail2(isfatal);
|
testlib_onfail2(isfatal);
|
||||||
}
|
}
|
||||||
|
|
||||||
forceinline void assertBinaryEquals$hex(FILIFU_ARGS const char *want,
|
forceinline void assertBinaryEquals_hex(FILIFU_ARGS const char *want,
|
||||||
const void *got, size_t n,
|
const void *got, size_t n,
|
||||||
const char *gotcode, bool isfatal) {
|
const char *gotcode, bool isfatal) {
|
||||||
++g_testlib_ran;
|
++g_testlib_ran;
|
||||||
|
@ -562,7 +562,7 @@ forceinline void assertBinaryEquals$hex(FILIFU_ARGS const char *want,
|
||||||
testlib_onfail2(isfatal);
|
testlib_onfail2(isfatal);
|
||||||
}
|
}
|
||||||
|
|
||||||
forceinline void assertBinaryNotEquals$cp437(FILIFU_ARGS const char16_t *want,
|
forceinline void assertBinaryNotEquals_cp437(FILIFU_ARGS const char16_t *want,
|
||||||
const void *got, size_t n,
|
const void *got, size_t n,
|
||||||
const char *gotcode,
|
const char *gotcode,
|
||||||
bool isfatal) {
|
bool isfatal) {
|
||||||
|
@ -576,7 +576,7 @@ forceinline void assertBinaryNotEquals$cp437(FILIFU_ARGS const char16_t *want,
|
||||||
testlib_onfail2(isfatal);
|
testlib_onfail2(isfatal);
|
||||||
}
|
}
|
||||||
|
|
||||||
forceinline void assertBinaryNotEquals$hex(FILIFU_ARGS const char *want,
|
forceinline void assertBinaryNotEquals_hex(FILIFU_ARGS const char *want,
|
||||||
const void *got, size_t n,
|
const void *got, size_t n,
|
||||||
const char *gotcode, bool isfatal) {
|
const char *gotcode, bool isfatal) {
|
||||||
++g_testlib_ran;
|
++g_testlib_ran;
|
||||||
|
|
|
@ -34,7 +34,7 @@ STATIC_YOINK("ntoa");
|
||||||
* @fileoverview Timestamps in One True Format w/o toil.
|
* @fileoverview Timestamps in One True Format w/o toil.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static char *xiso8601$impl(struct timespec *opt_ts, int sswidth) {
|
static char *xiso8601_impl(struct timespec *opt_ts, int sswidth) {
|
||||||
char *p;
|
char *p;
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
@ -69,13 +69,13 @@ static char *xiso8601$impl(struct timespec *opt_ts, int sswidth) {
|
||||||
* Returns allocated string representation of nanosecond timestamp.
|
* Returns allocated string representation of nanosecond timestamp.
|
||||||
*/
|
*/
|
||||||
char *xiso8601ts(struct timespec *opt_ts) {
|
char *xiso8601ts(struct timespec *opt_ts) {
|
||||||
return xiso8601$impl(opt_ts, 9);
|
return xiso8601_impl(opt_ts, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns allocated string representation of microsecond timestamp.
|
* Returns allocated string representation of microsecond timestamp.
|
||||||
*/
|
*/
|
||||||
char *xiso8601tv(struct timeval *opt_tv) {
|
char *xiso8601tv(struct timeval *opt_tv) {
|
||||||
return xiso8601$impl(
|
return xiso8601_impl(
|
||||||
opt_tv ? &(struct timespec){opt_tv->tv_sec, opt_tv->tv_usec} : NULL, 6);
|
opt_tv ? &(struct timespec){opt_tv->tv_sec, opt_tv->tv_usec} : NULL, 6);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/consts/prot.h"
|
#include "libc/sysv/consts/prot.h"
|
||||||
|
|
||||||
static void *filecmp$mmap(int fd, size_t size) {
|
static void *filecmp_mmap(int fd, size_t size) {
|
||||||
return size ? mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0) : NULL;
|
return size ? mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,8 +49,8 @@ int filecmp(const char *pathname1, const char *pathname2) {
|
||||||
(fd2 = open(pathname2, O_RDONLY)) != -1 &&
|
(fd2 = open(pathname2, O_RDONLY)) != -1 &&
|
||||||
(size1 = getfiledescriptorsize(fd1)) != -1 &&
|
(size1 = getfiledescriptorsize(fd1)) != -1 &&
|
||||||
(size2 = getfiledescriptorsize(fd2)) != -1 &&
|
(size2 = getfiledescriptorsize(fd2)) != -1 &&
|
||||||
(addr1 = filecmp$mmap(fd1, size1)) != MAP_FAILED &&
|
(addr1 = filecmp_mmap(fd1, size1)) != MAP_FAILED &&
|
||||||
(addr2 = filecmp$mmap(fd2, size2)) != MAP_FAILED) {
|
(addr2 = filecmp_mmap(fd2, size2)) != MAP_FAILED) {
|
||||||
olderr = errno;
|
olderr = errno;
|
||||||
madvise(addr1, size1, MADV_WILLNEED | MADV_SEQUENTIAL);
|
madvise(addr1, size1, MADV_WILLNEED | MADV_SEQUENTIAL);
|
||||||
madvise(addr2, size2, MADV_WILLNEED | MADV_SEQUENTIAL);
|
madvise(addr2, size2, MADV_WILLNEED | MADV_SEQUENTIAL);
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "libc/testlib/ezbench.h"
|
#include "libc/testlib/ezbench.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
|
|
||||||
void addsw$pure(size_t n, short x[n][8], const short y[n][8]) {
|
void addsw_pure(size_t n, short x[n][8], const short y[n][8]) {
|
||||||
size_t i, j;
|
size_t i, j;
|
||||||
for (i = 0; i < n; ++i) {
|
for (i = 0; i < n; ++i) {
|
||||||
for (j = 0; j < 8; ++j) {
|
for (j = 0; j < 8; ++j) {
|
||||||
|
@ -94,7 +94,7 @@ void sad16x8n_sse2(void) {
|
||||||
sad16x8n(PLM_AUDIO_SAMPLES_PER_FRAME / 8, (void *)pcm1, (void *)pcm2);
|
sad16x8n(PLM_AUDIO_SAMPLES_PER_FRAME / 8, (void *)pcm1, (void *)pcm2);
|
||||||
}
|
}
|
||||||
void sad16x8n_pure(void) {
|
void sad16x8n_pure(void) {
|
||||||
addsw$pure(PLM_AUDIO_SAMPLES_PER_FRAME / 8, (void *)pcm1, (void *)pcm2);
|
addsw_pure(PLM_AUDIO_SAMPLES_PER_FRAME / 8, (void *)pcm1, (void *)pcm2);
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCH(sad16x8n, audioframe) {
|
BENCH(sad16x8n, audioframe) {
|
||||||
|
|
|
@ -28,9 +28,9 @@
|
||||||
#include "libc/testlib/ezbench.h"
|
#include "libc/testlib/ezbench.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
|
|
||||||
unsigned windex$k8(short *, size_t) hidden;
|
unsigned windex_k8(short *, size_t) hidden;
|
||||||
unsigned windex$avx2(short *, size_t) hidden;
|
unsigned windex_avx2(short *, size_t) hidden;
|
||||||
unsigned windex$sse4(short *, size_t) hidden;
|
unsigned windex_sse4(short *, size_t) hidden;
|
||||||
|
|
||||||
const short kW[64] forcealign(32) = {
|
const short kW[64] forcealign(32) = {
|
||||||
8281, 3883, 1365, 1786, 9006, 3681, 5563, 8013, 5787, 9063, 2923,
|
8281, 3883, 1365, 1786, 9006, 3681, 5563, 8013, 5787, 9063, 2923,
|
||||||
|
@ -78,9 +78,9 @@ TEST(windex, testRealWorldPicks) {
|
||||||
0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff,
|
0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff,
|
||||||
};
|
};
|
||||||
/* multiple valid answers are fine if it's deterministic */
|
/* multiple valid answers are fine if it's deterministic */
|
||||||
TestIt(windex$k8, 52, 21, ARRAYLEN(kPicks), kPicks);
|
TestIt(windex_k8, 52, 21, ARRAYLEN(kPicks), kPicks);
|
||||||
if (X86_HAVE(AVX2)) TestIt(windex$avx2, 78, 21, ARRAYLEN(kPicks), kPicks);
|
if (X86_HAVE(AVX2)) TestIt(windex_avx2, 78, 21, ARRAYLEN(kPicks), kPicks);
|
||||||
if (X86_HAVE(SSE4_2)) TestIt(windex$sse4, 80, 21, ARRAYLEN(kPicks), kPicks);
|
if (X86_HAVE(SSE4_2)) TestIt(windex_sse4, 80, 21, ARRAYLEN(kPicks), kPicks);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(windex, test) {
|
TEST(windex, test) {
|
||||||
|
@ -89,26 +89,26 @@ TEST(windex, test) {
|
||||||
TestIt(windex, 62, 7, ARRAYLEN(kW3), kW3);
|
TestIt(windex, 62, 7, ARRAYLEN(kW3), kW3);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(windex$avx2, test) {
|
TEST(windex_avx2, test) {
|
||||||
if (X86_HAVE(AVX2)) {
|
if (X86_HAVE(AVX2)) {
|
||||||
TestIt(windex$avx2, 13, 32, ARRAYLEN(kW), kW);
|
TestIt(windex_avx2, 13, 32, ARRAYLEN(kW), kW);
|
||||||
TestIt(windex$avx2, 1, 1, ARRAYLEN(kW2), kW2);
|
TestIt(windex_avx2, 1, 1, ARRAYLEN(kW2), kW2);
|
||||||
TestIt(windex$avx2, 62, 7, ARRAYLEN(kW3), kW3);
|
TestIt(windex_avx2, 62, 7, ARRAYLEN(kW3), kW3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(windex$sse4, test) {
|
TEST(windex_sse4, test) {
|
||||||
if (X86_HAVE(SSE4_2)) {
|
if (X86_HAVE(SSE4_2)) {
|
||||||
TestIt(windex$sse4, 13, 32, ARRAYLEN(kW), kW);
|
TestIt(windex_sse4, 13, 32, ARRAYLEN(kW), kW);
|
||||||
TestIt(windex$sse4, 1, 1, ARRAYLEN(kW2), kW2);
|
TestIt(windex_sse4, 1, 1, ARRAYLEN(kW2), kW2);
|
||||||
TestIt(windex$sse4, 62, 7, ARRAYLEN(kW3), kW3);
|
TestIt(windex_sse4, 62, 7, ARRAYLEN(kW3), kW3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(windex$k8, test) {
|
TEST(windex_k8, test) {
|
||||||
TestIt(windex$k8, 13, 32, ARRAYLEN(kW), kW);
|
TestIt(windex_k8, 13, 32, ARRAYLEN(kW), kW);
|
||||||
TestIt(windex$k8, 1, 1, ARRAYLEN(kW2), kW2);
|
TestIt(windex_k8, 1, 1, ARRAYLEN(kW2), kW2);
|
||||||
TestIt(windex$k8, 62, 7, ARRAYLEN(kW3), kW3);
|
TestIt(windex_k8, 62, 7, ARRAYLEN(kW3), kW3);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -116,16 +116,16 @@ TEST(windex$k8, test) {
|
||||||
BENCH(windex, bench) {
|
BENCH(windex, bench) {
|
||||||
EZBENCH(donothing, windex(kW, ARRAYLEN(kW)));
|
EZBENCH(donothing, windex(kW, ARRAYLEN(kW)));
|
||||||
}
|
}
|
||||||
BENCH(windex$k8, bench) {
|
BENCH(windex_k8, bench) {
|
||||||
EZBENCH(donothing, windex$k8(kW, ARRAYLEN(kW)));
|
EZBENCH(donothing, windex_k8(kW, ARRAYLEN(kW)));
|
||||||
}
|
}
|
||||||
BENCH(windex$avx2, bench) {
|
BENCH(windex_avx2, bench) {
|
||||||
if (X86_HAVE(AVX2)) {
|
if (X86_HAVE(AVX2)) {
|
||||||
EZBENCH(donothing, windex$avx2(kW, ARRAYLEN(kW)));
|
EZBENCH(donothing, windex_avx2(kW, ARRAYLEN(kW)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BENCH(windex$sse4, bench) {
|
BENCH(windex_sse4, bench) {
|
||||||
if (X86_HAVE(SSE4_2)) {
|
if (X86_HAVE(SSE4_2)) {
|
||||||
EZBENCH(donothing, windex$sse4(kW, ARRAYLEN(kW)));
|
EZBENCH(donothing, windex_sse4(kW, ARRAYLEN(kW)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include "libc/testlib/ezbench.h"
|
#include "libc/testlib/ezbench.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
|
|
||||||
void djbsort$avx2(int32_t *, long);
|
void djbsort_avx2(int32_t *, long);
|
||||||
|
|
||||||
size_t n;
|
size_t n;
|
||||||
int32_t *a, *b, *c;
|
int32_t *a, *b, *c;
|
||||||
|
@ -42,7 +42,7 @@ TEST(djbsort, test4) {
|
||||||
b = memcpy(gc(malloc(n * 4)), kA, n * 4);
|
b = memcpy(gc(malloc(n * 4)), kA, n * 4);
|
||||||
c = memcpy(gc(malloc(n * 4)), kA, n * 4);
|
c = memcpy(gc(malloc(n * 4)), kA, n * 4);
|
||||||
insertionsort(a, n);
|
insertionsort(a, n);
|
||||||
djbsort$avx2(b, n);
|
djbsort_avx2(b, n);
|
||||||
djbsort(c, n);
|
djbsort(c, n);
|
||||||
ASSERT_EQ(0, memcmp(a, b, n * 4));
|
ASSERT_EQ(0, memcmp(a, b, n * 4));
|
||||||
ASSERT_EQ(0, memcmp(a, c, n * 4));
|
ASSERT_EQ(0, memcmp(a, c, n * 4));
|
||||||
|
@ -72,7 +72,7 @@ TEST(djbsort, test64) {
|
||||||
djbsort(c, n);
|
djbsort(c, n);
|
||||||
ASSERT_EQ(0, memcmp(a, c, n * 4));
|
ASSERT_EQ(0, memcmp(a, c, n * 4));
|
||||||
if (X86_HAVE(AVX2)) {
|
if (X86_HAVE(AVX2)) {
|
||||||
djbsort$avx2(b, n);
|
djbsort_avx2(b, n);
|
||||||
ASSERT_EQ(0, memcmp(a, b, n * 4));
|
ASSERT_EQ(0, memcmp(a, b, n * 4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ TEST(crc32, testBigText) {
|
||||||
EXPECT_EQ(0xc7adc04f, crc32(0, hyperion, size));
|
EXPECT_EQ(0xc7adc04f, crc32(0, hyperion, size));
|
||||||
EXPECT_EQ(0xc7adc04f, crc32_z(0, hyperion, size));
|
EXPECT_EQ(0xc7adc04f, crc32_z(0, hyperion, size));
|
||||||
EXPECT_EQ(0xc7adc04f,
|
EXPECT_EQ(0xc7adc04f,
|
||||||
0xffffffffu ^ crc32$pclmul(0 ^ 0xffffffffu, hyperion, size));
|
0xffffffffu ^ crc32_pclmul(0 ^ 0xffffffffu, hyperion, size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ TEST(memmove$pure, overlapping) {
|
||||||
b0 = rngset(malloc(N), N, rand64, -1);
|
b0 = rngset(malloc(N), N, rand64, -1);
|
||||||
b1 = memcpy(malloc(N), b0, N);
|
b1 = memcpy(malloc(N), b0, N);
|
||||||
b2 = memcpy(malloc(N), b0, N);
|
b2 = memcpy(malloc(N), b0, N);
|
||||||
ASSERT_EQ(b1 + j, memmove$pure(b1 + j, b1 + i, n));
|
ASSERT_EQ(b1 + j, memmove_pure(b1 + j, b1 + i, n));
|
||||||
ASSERT_EQ(b2 + j, PosixMemmove(b2 + j, b2 + i, n));
|
ASSERT_EQ(b2 + j, PosixMemmove(b2 + j, b2 + i, n));
|
||||||
ASSERT_EQ(0, memcmp(b1, b2, N),
|
ASSERT_EQ(0, memcmp(b1, b2, N),
|
||||||
"j=%ld i=%ld n=%ld\n"
|
"j=%ld i=%ld n=%ld\n"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
int main() {
|
int main(int argc, char *argv[]) {
|
||||||
int rc;
|
int rc;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
f = fopen("/dev/null", "w");
|
f = fopen("/dev/null", "w");
|
||||||
fprintf(f, "hello world\n");
|
fprintf(f, "hello world %d\n", argc);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
rc = system("exit 42");
|
rc = system("exit 42");
|
||||||
CHECK_NE(-1, rc);
|
CHECK_NE(-1, rc);
|
||||||
|
|
|
@ -93,6 +93,31 @@ o/$(MODE)/test/libc/release/smokeansi.com.dbg: \
|
||||||
o/$(MODE)/ape/ape.o \
|
o/$(MODE)/ape/ape.o \
|
||||||
o/$(MODE)/cosmopolitan.a
|
o/$(MODE)/cosmopolitan.a
|
||||||
|
|
||||||
|
o/$(MODE)/test/libc/release/smokeclang.com.dbg: \
|
||||||
|
test/libc/release/smoke.c \
|
||||||
|
o/cosmopolitan.h \
|
||||||
|
o/$(MODE)/ape/ape.lds \
|
||||||
|
o/$(MODE)/libc/crt/crt.o \
|
||||||
|
o/$(MODE)/ape/ape.o \
|
||||||
|
o/$(MODE)/cosmopolitan.a
|
||||||
|
@ACTION=CLANG build/compile clang \
|
||||||
|
-o $@ \
|
||||||
|
-Os \
|
||||||
|
-static \
|
||||||
|
-no-pie \
|
||||||
|
-fno-pie \
|
||||||
|
-nostdlib \
|
||||||
|
-nostdinc \
|
||||||
|
-mno-red-zone \
|
||||||
|
-Wl,--gc-sections \
|
||||||
|
-Wl,-z,max-page-size=0x1000 \
|
||||||
|
-Wl,-T,o/$(MODE)/ape/ape.lds \
|
||||||
|
-include o/cosmopolitan.h \
|
||||||
|
test/libc/release/smoke.c \
|
||||||
|
o/$(MODE)/libc/crt/crt.o \
|
||||||
|
o/$(MODE)/ape/ape.o \
|
||||||
|
o/$(MODE)/cosmopolitan.a
|
||||||
|
|
||||||
.PHONY: o/$(MODE)/test/libc/release
|
.PHONY: o/$(MODE)/test/libc/release
|
||||||
o/$(MODE)/test/libc/release: \
|
o/$(MODE)/test/libc/release: \
|
||||||
o/$(MODE)/test/libc/release/smoke.com \
|
o/$(MODE)/test/libc/release/smoke.com \
|
||||||
|
|
|
@ -40,12 +40,12 @@ TEST(crc32c, test) {
|
||||||
strlen(hyperion) - strlen(FANATICS)));
|
strlen(hyperion) - strlen(FANATICS)));
|
||||||
}
|
}
|
||||||
|
|
||||||
FIXTURE(crc32c, pure) {
|
FIXTURE(crc32c, pure_) {
|
||||||
*(void **)(&crc32c) = (void *)crc32c$pure;
|
*(void **)(&crc32c) = (void *)crc32c_pure;
|
||||||
}
|
}
|
||||||
|
|
||||||
FIXTURE(crc32c, sse42) {
|
FIXTURE(crc32c, sse42_) {
|
||||||
if (X86_HAVE(SSE4_2)) {
|
if (X86_HAVE(SSE4_2)) {
|
||||||
*(void **)(&crc32c) = (void *)crc32c$sse42;
|
*(void **)(&crc32c) = (void *)crc32c_sse42;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include "libc/testlib/ezbench.h"
|
#include "libc/testlib/ezbench.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
|
|
||||||
void *memccpy$pure(void *d, const void *s, int c, size_t n) {
|
void *memccpy_pure(void *d, const void *s, int c, size_t n) {
|
||||||
size_t i;
|
size_t i;
|
||||||
unsigned char *x;
|
unsigned char *x;
|
||||||
const unsigned char *y;
|
const unsigned char *y;
|
||||||
|
@ -57,7 +57,7 @@ TEST(memccpy, memcpy) {
|
||||||
b2 = calloc(1, n);
|
b2 = calloc(1, n);
|
||||||
b3 = calloc(1, n);
|
b3 = calloc(1, n);
|
||||||
rngset(b1, n, rand64, -1);
|
rngset(b1, n, rand64, -1);
|
||||||
e1 = memccpy$pure(b2, b1, 31337, n);
|
e1 = memccpy_pure(b2, b1, 31337, n);
|
||||||
e2 = memccpy(b3, b1, 31337, n);
|
e2 = memccpy(b3, b1, 31337, n);
|
||||||
n1 = e1 ? e1 - b2 : n;
|
n1 = e1 ? e1 - b2 : n;
|
||||||
n2 = e2 ? e2 - b3 : n;
|
n2 = e2 ? e2 - b3 : n;
|
||||||
|
|
|
@ -174,7 +174,7 @@ void *MemCpy(void *, const void *, size_t);
|
||||||
|
|
||||||
#define BB(N) \
|
#define BB(N) \
|
||||||
do { \
|
do { \
|
||||||
B(memmove$pure, N); \
|
B(memmove_pure, N); \
|
||||||
B(memcpy, N); \
|
B(memcpy, N); \
|
||||||
B(MemCpy, N); \
|
B(MemCpy, N); \
|
||||||
fprintf(stderr, "\n"); \
|
fprintf(stderr, "\n"); \
|
||||||
|
|
|
@ -70,7 +70,7 @@ TEST(strchrnul, notFound_returnsPointerToNulByte) {
|
||||||
EXPECT_EQ(&buf[2], strchrnul(buf, 'z'));
|
EXPECT_EQ(&buf[2], strchrnul(buf, 'z'));
|
||||||
}
|
}
|
||||||
|
|
||||||
char *strchr$pure(const char *s, int c) {
|
char *strchr_pure(const char *s, int c) {
|
||||||
char *r;
|
char *r;
|
||||||
for (c &= 0xff;; ++s) {
|
for (c &= 0xff;; ++s) {
|
||||||
if ((*s & 0xff) == c) return (char *)s;
|
if ((*s & 0xff) == c) return (char *)s;
|
||||||
|
@ -85,7 +85,7 @@ TEST(strchr, fuzz) {
|
||||||
for (i = -2; i < 257; ++i) {
|
for (i = -2; i < 257; ++i) {
|
||||||
for (j = 0; j < 17; ++j) {
|
for (j = 0; j < 17; ++j) {
|
||||||
rngset(p, 63, rand64, -1);
|
rngset(p, 63, rand64, -1);
|
||||||
ASSERT_EQ(strchr(p + j, i), strchr$pure(p + j, i));
|
ASSERT_EQ(strchr(p + j, i), strchr_pure(p + j, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(p);
|
free(p);
|
||||||
|
@ -103,7 +103,7 @@ BENCH(strchr, bench) {
|
||||||
strchr(VEIL("r", "hellzzzhellzzzeeAhellzzzhellzzzeeo"), 'o')));
|
strchr(VEIL("r", "hellzzzhellzzzeeAhellzzzhellzzzeeo"), 'o')));
|
||||||
}
|
}
|
||||||
|
|
||||||
char *memchr$pure(const char *m, int c, size_t n) {
|
char *memchr_pure(const char *m, int c, size_t n) {
|
||||||
const unsigned char *p, *pe;
|
const unsigned char *p, *pe;
|
||||||
for (c &= 0xff, p = (const unsigned char *)m, pe = p + n; p < pe; ++p) {
|
for (c &= 0xff, p = (const unsigned char *)m, pe = p + n; p < pe; ++p) {
|
||||||
if (*p == c) return p;
|
if (*p == c) return p;
|
||||||
|
@ -118,13 +118,13 @@ TEST(memchr, fuzz) {
|
||||||
for (i = -2; i < 257; ++i) {
|
for (i = -2; i < 257; ++i) {
|
||||||
for (j = 0; j < 17; ++j) {
|
for (j = 0; j < 17; ++j) {
|
||||||
rngset(p, 64, rand64, -1);
|
rngset(p, 64, rand64, -1);
|
||||||
ASSERT_EQ(memchr(p + j, i, 64 - j), memchr$pure(p + j, i, 64 - j));
|
ASSERT_EQ(memchr(p + j, i, 64 - j), memchr_pure(p + j, i, 64 - j));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *strchrnul$pure(const char *s, int c) {
|
char *strchrnul_pure(const char *s, int c) {
|
||||||
char *r;
|
char *r;
|
||||||
for (c &= 0xff;; ++s) {
|
for (c &= 0xff;; ++s) {
|
||||||
if ((*s & 0xff) == c) return (char *)s;
|
if ((*s & 0xff) == c) return (char *)s;
|
||||||
|
@ -139,13 +139,13 @@ TEST(strchrnul, fuzz) {
|
||||||
for (i = -2; i < 257; ++i) {
|
for (i = -2; i < 257; ++i) {
|
||||||
for (j = 0; j < 17; ++j) {
|
for (j = 0; j < 17; ++j) {
|
||||||
rngset(p, 63, rand64, -1);
|
rngset(p, 63, rand64, -1);
|
||||||
ASSERT_EQ(strchrnul(p + j, i), strchrnul$pure(p + j, i));
|
ASSERT_EQ(strchrnul(p + j, i), strchrnul_pure(p + j, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *rawmemchr$pure(const void *m, int c) {
|
void *rawmemchr_pure(const void *m, int c) {
|
||||||
const unsigned char *s;
|
const unsigned char *s;
|
||||||
for (c &= 255, s = m;; ++s) {
|
for (c &= 255, s = m;; ++s) {
|
||||||
if (*s == c) return s;
|
if (*s == c) return s;
|
||||||
|
@ -160,7 +160,7 @@ TEST(rawmemchr, fuzz) {
|
||||||
for (j = 0; j < 17; ++j) {
|
for (j = 0; j < 17; ++j) {
|
||||||
rngset(p, 63, rand64, -1);
|
rngset(p, 63, rand64, -1);
|
||||||
p[63] = i;
|
p[63] = i;
|
||||||
ASSERT_EQ(rawmemchr(p + j, i), rawmemchr$pure(p + j, i));
|
ASSERT_EQ(rawmemchr(p + j, i), rawmemchr_pure(p + j, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(p);
|
free(p);
|
||||||
|
|
|
@ -485,14 +485,14 @@ TEST(wcsncmp, testTwosComplementBane) {
|
||||||
│ test/libc/str/strcmp_test.c § benchmarks ─╬─│┼
|
│ test/libc/str/strcmp_test.c § benchmarks ─╬─│┼
|
||||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||||
|
|
||||||
testonly noinline int strcmp$pure(const char *a, const char *b) {
|
testonly noinline int strcmp_pure(const char *a, const char *b) {
|
||||||
for (; *a == *b; a++, b++) {
|
for (; *a == *b; a++, b++) {
|
||||||
if (!*a) break;
|
if (!*a) break;
|
||||||
}
|
}
|
||||||
return (*a & 0xff) - (*b & 0xff);
|
return (*a & 0xff) - (*b & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
testonly noinline int strcasecmp$pure(const char *a, const char *b) {
|
testonly noinline int strcasecmp_pure(const char *a, const char *b) {
|
||||||
for (; *a && *b; a++, b++) {
|
for (; *a && *b; a++, b++) {
|
||||||
if (!(*a == *b || tolower(*a & 0xff) == tolower(*b & 0xff))) {
|
if (!(*a == *b || tolower(*a & 0xff) == tolower(*b & 0xff))) {
|
||||||
break;
|
break;
|
||||||
|
@ -542,38 +542,38 @@ BENCH(bench_00_strcmp, bench) {
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
EZBENCH2("strcmp [2 diff]", donothing,
|
EZBENCH2("strcmp [2 diff]", donothing,
|
||||||
EXPROPRIATE(strcmp(VEIL("r", "hi"), VEIL("r", "there"))));
|
EXPROPRIATE(strcmp(VEIL("r", "hi"), VEIL("r", "there"))));
|
||||||
EZBENCH2("strcmp$pure [2 diff]", donothing,
|
EZBENCH2("strcmp_pure [2 diff]", donothing,
|
||||||
EXPROPRIATE(strcmp$pure(VEIL("r", "hi"), VEIL("r", "there"))));
|
EXPROPRIATE(strcmp_pure(VEIL("r", "hi"), VEIL("r", "there"))));
|
||||||
|
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
EZBENCH2("strcmp [2 dupe]", randomize_buf2str_dupe(2, data, dupe),
|
EZBENCH2("strcmp [2 dupe]", randomize_buf2str_dupe(2, data, dupe),
|
||||||
EXPROPRIATE(strcmp(VEIL("r", data), VEIL("r", dupe))));
|
EXPROPRIATE(strcmp(VEIL("r", data), VEIL("r", dupe))));
|
||||||
EZBENCH2("strcmp$pure [2 dupe]", randomize_buf2str_dupe(2, data, dupe),
|
EZBENCH2("strcmp_pure [2 dupe]", randomize_buf2str_dupe(2, data, dupe),
|
||||||
EXPROPRIATE(strcmp$pure(VEIL("r", data), VEIL("r", dupe))));
|
EXPROPRIATE(strcmp_pure(VEIL("r", data), VEIL("r", dupe))));
|
||||||
|
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
EZBENCH2("strcmp [4 dupe]", randomize_buf2str_dupe(4, data, dupe),
|
EZBENCH2("strcmp [4 dupe]", randomize_buf2str_dupe(4, data, dupe),
|
||||||
EXPROPRIATE(strcmp(VEIL("r", data), VEIL("r", dupe))));
|
EXPROPRIATE(strcmp(VEIL("r", data), VEIL("r", dupe))));
|
||||||
EZBENCH2("strcmp$pure [4 dupe]", randomize_buf2str_dupe(4, data, dupe),
|
EZBENCH2("strcmp_pure [4 dupe]", randomize_buf2str_dupe(4, data, dupe),
|
||||||
EXPROPRIATE(strcmp$pure(VEIL("r", data), VEIL("r", dupe))));
|
EXPROPRIATE(strcmp_pure(VEIL("r", data), VEIL("r", dupe))));
|
||||||
|
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
EZBENCH2("strcmp [8 dupe]", randomize_buf2str_dupe(8, data, dupe),
|
EZBENCH2("strcmp [8 dupe]", randomize_buf2str_dupe(8, data, dupe),
|
||||||
EXPROPRIATE(strcmp(VEIL("r", data), VEIL("r", dupe))));
|
EXPROPRIATE(strcmp(VEIL("r", data), VEIL("r", dupe))));
|
||||||
EZBENCH2("strcmp$pure [8 dupe]", randomize_buf2str_dupe(8, data, dupe),
|
EZBENCH2("strcmp_pure [8 dupe]", randomize_buf2str_dupe(8, data, dupe),
|
||||||
EXPROPRIATE(strcmp$pure(VEIL("r", data), VEIL("r", dupe))));
|
EXPROPRIATE(strcmp_pure(VEIL("r", data), VEIL("r", dupe))));
|
||||||
|
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
EZBENCH2("strcmp [short dupe]", randomize_buf2str_dupe(size, data, dupe),
|
EZBENCH2("strcmp [short dupe]", randomize_buf2str_dupe(size, data, dupe),
|
||||||
EXPROPRIATE(strcmp(VEIL("r", data), VEIL("r", dupe))));
|
EXPROPRIATE(strcmp(VEIL("r", data), VEIL("r", dupe))));
|
||||||
EZBENCH2("strcmp$pure [short dupe]", randomize_buf2str_dupe(size, data, dupe),
|
EZBENCH2("strcmp_pure [short dupe]", randomize_buf2str_dupe(size, data, dupe),
|
||||||
EXPROPRIATE(strcmp$pure(VEIL("r", data), VEIL("r", dupe))));
|
EXPROPRIATE(strcmp_pure(VEIL("r", data), VEIL("r", dupe))));
|
||||||
|
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
EZBENCH2("strcmp [long dupe]", longstringislong_dupe(size, data, dupe),
|
EZBENCH2("strcmp [long dupe]", longstringislong_dupe(size, data, dupe),
|
||||||
EXPROPRIATE(strcmp(VEIL("r", data), VEIL("r", dupe))));
|
EXPROPRIATE(strcmp(VEIL("r", data), VEIL("r", dupe))));
|
||||||
EZBENCH2("strcmp$pure [long dupe]", longstringislong_dupe(size, data, dupe),
|
EZBENCH2("strcmp_pure [long dupe]", longstringislong_dupe(size, data, dupe),
|
||||||
EXPROPRIATE(strcmp$pure(VEIL("r", data), VEIL("r", dupe))));
|
EXPROPRIATE(strcmp_pure(VEIL("r", data), VEIL("r", dupe))));
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCH(bench_01_strcasecmp, bench) {
|
BENCH(bench_01_strcasecmp, bench) {
|
||||||
|
@ -591,14 +591,14 @@ BENCH(bench_01_strcasecmp, bench) {
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
EZBENCH2("strcasecmp [short dupe]", randomize_buf2str_dupe(size, data, dupe),
|
EZBENCH2("strcasecmp [short dupe]", randomize_buf2str_dupe(size, data, dupe),
|
||||||
EXPROPRIATE(strcasecmp(VEIL("r", data), VEIL("r", dupe))));
|
EXPROPRIATE(strcasecmp(VEIL("r", data), VEIL("r", dupe))));
|
||||||
EZBENCH2("strcasecmp$pure [short dupe]",
|
EZBENCH2("strcasecmp_pure [short dupe]",
|
||||||
randomize_buf2str_dupe(size, data, dupe),
|
randomize_buf2str_dupe(size, data, dupe),
|
||||||
EXPROPRIATE(strcasecmp$pure(VEIL("r", data), VEIL("r", dupe))));
|
EXPROPRIATE(strcasecmp_pure(VEIL("r", data), VEIL("r", dupe))));
|
||||||
|
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
EZBENCH2("strcasecmp [long dupe]", longstringislong_dupe(size, data, dupe),
|
EZBENCH2("strcasecmp [long dupe]", longstringislong_dupe(size, data, dupe),
|
||||||
EXPROPRIATE(strcasecmp(VEIL("r", data), VEIL("r", dupe))));
|
EXPROPRIATE(strcasecmp(VEIL("r", data), VEIL("r", dupe))));
|
||||||
EZBENCH2("strcasecmp$pure [long dupe]",
|
EZBENCH2("strcasecmp_pure [long dupe]",
|
||||||
longstringislong_dupe(size, data, dupe),
|
longstringislong_dupe(size, data, dupe),
|
||||||
EXPROPRIATE(strcasecmp$pure(VEIL("r", data), VEIL("r", dupe))));
|
EXPROPRIATE(strcasecmp_pure(VEIL("r", data), VEIL("r", dupe))));
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue