mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Make more functions friendly to Address Sanitizer
This commit is contained in:
parent
3ab76b2312
commit
cbfd4ccd1e
70 changed files with 1267 additions and 291 deletions
8
Makefile
8
Makefile
|
@ -199,6 +199,7 @@ include test/test.mk
|
|||
OBJS = $(foreach x,$(PKGS),$($(x)_OBJS))
|
||||
SRCS = $(foreach x,$(PKGS),$($(x)_SRCS))
|
||||
HDRS = $(foreach x,$(PKGS),$($(x)_HDRS))
|
||||
INCS = $(foreach x,$(PKGS),$($(x)_INCS))
|
||||
BINS = $(foreach x,$(PKGS),$($(x)_BINS))
|
||||
TESTS = $(foreach x,$(PKGS),$($(x)_TESTS))
|
||||
CHECKS = $(foreach x,$(PKGS),$($(x)_CHECKS))
|
||||
|
@ -215,10 +216,10 @@ o/$(MODE)/.x:
|
|||
o/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x)))
|
||||
|
||||
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(HDRS),$(file >>$@,$(x)))
|
||||
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(HDRS) $(INCS),$(file >>$@,$(x)))
|
||||
|
||||
o/$(MODE)/depend: o/$(MODE)/.x o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt $(SRCS) $(HDRS)
|
||||
o/$(MODE)/depend: o/$(MODE)/.x o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt $(SRCS) $(HDRS) $(INCS)
|
||||
@build/mkdeps -o $@ -r o/$(MODE)/ o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
|
||||
|
||||
TAGS: o/$(MODE)/srcs.txt $(SRCS)
|
||||
|
@ -351,6 +352,7 @@ o/cosmopolitan.html: \
|
|||
~/.cosmo.mk:
|
||||
$(SRCS):
|
||||
$(HDRS):
|
||||
$(INCS):
|
||||
.DEFAULT:
|
||||
@echo >&2
|
||||
@echo NOTE: deleting o/$(MODE)/depend because of an unspecified prerequisite: $@ >&2
|
||||
|
|
|
@ -33,6 +33,7 @@ APELINK = \
|
|||
|
||||
APE_FILES := $(wildcard ape/*.*)
|
||||
APE_HDRS = $(filter %.h,$(APE_FILES))
|
||||
APE_INCS = $(filter %.inc,$(APE_FILES))
|
||||
APE_SRCS = $(filter %.S,$(APE_FILES))
|
||||
APE_OBJS = $(APE_SRCS:%.S=o/$(MODE)/%.o)
|
||||
APE_DEPS = $(APE_LIB)
|
||||
|
|
|
@ -37,6 +37,8 @@ export LC_ALL=C
|
|||
MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit
|
||||
|
||||
GZME=
|
||||
ASAN=
|
||||
UBSAN=
|
||||
PLAT="${1%% *}"
|
||||
FDIAGNOSTIC_COLOR=
|
||||
CCNAME=${CCNAME:-gcc}
|
||||
|
@ -87,11 +89,21 @@ for x; do
|
|||
set -- "$@" "$x" -Wa,-msse2avx -D__MNO_VZEROUPPER__
|
||||
;;
|
||||
-fsanitize=address)
|
||||
set -- "$@" "$x" -D__FSANITIZE_ADDRESS__
|
||||
ASAN="$x -D__FSANITIZE_ADDRESS__"
|
||||
;;
|
||||
-fsanitize=undefined)
|
||||
set -- "$@" "$x" -D__FSANITIZE_UNDEFINED__
|
||||
COUNTERMAND="$COUNTERMAND -fno-data-sections" # sqlite.o
|
||||
# UBSAN w/ -fdata-sections exceeds ELF's 65,280 section limit
|
||||
UBSAN="$x -fno-data-sections"
|
||||
;;
|
||||
-fno-sanitize=address)
|
||||
ASAN=
|
||||
;;
|
||||
-fno-sanitize=ubsan)
|
||||
UBSAN=
|
||||
;;
|
||||
-fno-sanitize=all)
|
||||
ASAN=
|
||||
UBSAN=
|
||||
;;
|
||||
-mnop-mcount)
|
||||
if [ "$CCNAME" = "gcc" ] && [ "$CCVERSION" -ge 6 ]; then
|
||||
|
@ -256,7 +268,7 @@ else
|
|||
done
|
||||
fi
|
||||
|
||||
set -- "$@" -no-canonical-prefixes $FDIAGNOSTIC_COLOR $COUNTERMAND
|
||||
set -- "$@" -no-canonical-prefixes $FDIAGNOSTIC_COLOR $ASAN $UBSAN $COUNTERMAND
|
||||
|
||||
if [ "$SILENT" = "0" ]; then
|
||||
printf "%s\n" "$*" >&2
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
|
||||
#if [ -x "o/$MODE/tool/build/mkdeps.com" ]; then
|
||||
# set -- "o/$MODE/tool/build/mkdeps.com" "$@"
|
||||
#else
|
||||
if [ -x "o/$MODE/tool/build/mkdeps.com" ]; then
|
||||
set -- "o/$MODE/tool/build/mkdeps.com" "$@"
|
||||
else
|
||||
if [ ! -x o/build/bootstrap/mkdeps.com ]; then
|
||||
mkdir -p o/build/bootstrap &&
|
||||
cp -a build/bootstrap/mkdeps.com \
|
||||
o/build/bootstrap/mkdeps.com || exit
|
||||
fi
|
||||
set -- o/build/bootstrap/mkdeps.com "$@"
|
||||
#fi
|
||||
fi
|
||||
|
||||
if [ "$SILENT" = "0" ]; then
|
||||
printf "%s\n" "$*" >&2
|
||||
|
|
|
@ -24,9 +24,10 @@ DSP_CORE_A_CHECKS = \
|
|||
$(DSP_CORE_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
|
||||
DSP_CORE_A_DIRECTDEPS = \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_MEM \
|
||||
LIBC_INTRIN \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_STR \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_STUBS
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ DSP_SCALE_A_DIRECTDEPS = \
|
|||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_STUBS \
|
||||
LIBC_TIME \
|
||||
|
|
|
@ -8,6 +8,7 @@ LIBC_ALG = $(LIBC_ALG_A_DEPS) $(LIBC_ALG_A)
|
|||
LIBC_ALG_A = o/$(MODE)/libc/alg/alg.a
|
||||
LIBC_ALG_A_FILES := $(wildcard libc/alg/*)
|
||||
LIBC_ALG_A_HDRS = $(filter %.h,$(LIBC_ALG_A_FILES))
|
||||
LIBC_ALG_A_INCS = $(filter %.inc,$(LIBC_ALG_A_FILES))
|
||||
LIBC_ALG_A_SRCS_S = $(filter %.S,$(LIBC_ALG_A_FILES))
|
||||
LIBC_ALG_A_SRCS_C = $(filter %.c,$(LIBC_ALG_A_FILES))
|
||||
|
||||
|
@ -51,6 +52,7 @@ o/$(MODE)/libc/alg/critbit0.o: \
|
|||
LIBC_ALG_LIBS = $(foreach x,$(LIBC_ALG_ARTIFACTS),$($(x)))
|
||||
LIBC_ALG_SRCS = $(foreach x,$(LIBC_ALG_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_ALG_HDRS = $(foreach x,$(LIBC_ALG_ARTIFACTS),$($(x)_HDRS))
|
||||
LIBC_ALG_INCS = $(foreach x,$(LIBC_ALG_ARTIFACTS),$($(x)_INCS))
|
||||
LIBC_ALG_CHECKS = $(foreach x,$(LIBC_ALG_ARTIFACTS),$($(x)_CHECKS))
|
||||
LIBC_ALG_OBJS = $(foreach x,$(LIBC_ALG_ARTIFACTS),$($(x)_OBJS))
|
||||
$(LIBC_ALG_OBJS): $(BUILD_FILES) libc/alg/alg.mk
|
||||
|
|
|
@ -21,6 +21,7 @@ LIBC_CALLS_A_FILES := \
|
|||
$(wildcard libc/calls/struct/*) \
|
||||
$(wildcard libc/calls/*)
|
||||
LIBC_CALLS_A_HDRS = $(filter %.h,$(LIBC_CALLS_A_FILES))
|
||||
LIBC_CALLS_A_INCS = $(filter %.inc,$(LIBC_CALLS_A_FILES))
|
||||
LIBC_CALLS_A_SRCS_S = $(filter %.S,$(LIBC_CALLS_A_FILES))
|
||||
LIBC_CALLS_A_SRCS_C = $(filter %.c,$(LIBC_CALLS_A_FILES))
|
||||
|
||||
|
@ -86,6 +87,7 @@ o/$(MODE)/libc/calls/mkntenvblock.o: \
|
|||
LIBC_CALLS_LIBS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)))
|
||||
LIBC_CALLS_SRCS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_CALLS_HDRS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_HDRS))
|
||||
LIBC_CALLS_INCS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_INCS))
|
||||
LIBC_CALLS_BINS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_BINS))
|
||||
LIBC_CALLS_CHECKS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_CHECKS))
|
||||
LIBC_CALLS_OBJS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_OBJS))
|
||||
|
|
|
@ -25,13 +25,14 @@ int32_t dup3$sysv(int32_t oldfd, int32_t newfd, int flags) {
|
|||
static bool once, demodernize;
|
||||
int olderr, fd;
|
||||
if (!once) {
|
||||
once = true;
|
||||
olderr = errno;
|
||||
fd = __dup3$sysv(oldfd, newfd, flags);
|
||||
if ((fd == -1 && errno == ENOSYS) || fd == __NR_dup3_linux) {
|
||||
demodernize = true;
|
||||
once = true;
|
||||
errno = olderr;
|
||||
} else {
|
||||
once = true;
|
||||
return fd;
|
||||
}
|
||||
} else if (!demodernize) {
|
||||
|
|
|
@ -29,9 +29,9 @@ forceinline typeof(PrefetchVirtualMemory) *GetPrefetchVirtualMemory(void) {
|
|||
static bool once;
|
||||
static typeof(PrefetchVirtualMemory) *PrefetchVirtualMemory_;
|
||||
if (!once) {
|
||||
once = true;
|
||||
PrefetchVirtualMemory_ = /* win8.1+ */
|
||||
GetProcAddressModule("Kernel32.dll", "PrefetchVirtualMemory");
|
||||
once = true;
|
||||
}
|
||||
return PrefetchVirtualMemory_;
|
||||
}
|
||||
|
@ -40,9 +40,9 @@ forceinline typeof(OfferVirtualMemory) *GetOfferVirtualMemory(void) {
|
|||
static bool once;
|
||||
static typeof(OfferVirtualMemory) *OfferVirtualMemory_;
|
||||
if (!once) {
|
||||
once = true;
|
||||
OfferVirtualMemory_ = /* win8.1+ */
|
||||
GetProcAddressModule("Kernel32.dll", "OfferVirtualMemory");
|
||||
once = true;
|
||||
}
|
||||
return OfferVirtualMemory_;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
|
@ -55,19 +56,21 @@ static long double MeasureNanosPerCycle(void) {
|
|||
}
|
||||
|
||||
static void InitTime(void) {
|
||||
g_now.cpn = MeasureNanosPerCycle();
|
||||
g_now.r0 = dtime(CLOCK_REALTIME);
|
||||
g_now.k0 = rdtsc();
|
||||
g_now.once = true;
|
||||
struct Now now;
|
||||
now.cpn = MeasureNanosPerCycle();
|
||||
now.r0 = dtime(CLOCK_REALTIME);
|
||||
now.k0 = rdtsc();
|
||||
now.once = true;
|
||||
memcpy(&g_now, &now, sizeof(now));
|
||||
}
|
||||
|
||||
long double converttickstonanos(uint64_t ticks) {
|
||||
long double ConvertTicksToNanos(uint64_t ticks) {
|
||||
if (!g_now.once) InitTime();
|
||||
return ticks * g_now.cpn; /* pico scale */
|
||||
}
|
||||
|
||||
long double converttickstoseconds(uint64_t ticks) {
|
||||
return 1 / 1e9 * converttickstonanos(ticks);
|
||||
static long double ConvertTicksToSeconds(uint64_t ticks) {
|
||||
return 1 / 1e9 * ConvertTicksToNanos(ticks);
|
||||
}
|
||||
|
||||
long double nowl$sys(void) {
|
||||
|
@ -78,5 +81,5 @@ long double nowl$art(void) {
|
|||
uint64_t ticks;
|
||||
if (!g_now.once) InitTime();
|
||||
ticks = unsignedsubtract(rdtsc(), g_now.k0);
|
||||
return g_now.r0 + converttickstoseconds(ticks);
|
||||
return g_now.r0 + ConvertTicksToSeconds(ticks);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ LIBC_FMT = $(LIBC_FMT_A_DEPS) $(LIBC_FMT_A)
|
|||
LIBC_FMT_A = o/$(MODE)/libc/fmt/fmt.a
|
||||
LIBC_FMT_A_FILES := $(wildcard libc/fmt/*)
|
||||
LIBC_FMT_A_HDRS = $(filter %.h,$(LIBC_FMT_A_FILES))
|
||||
LIBC_FMT_A_INCS = $(filter %.inc,$(LIBC_FMT_A_FILES))
|
||||
LIBC_FMT_A_SRCS_S = $(filter %.S,$(LIBC_FMT_A_FILES))
|
||||
LIBC_FMT_A_SRCS_C = $(filter %.c,$(LIBC_FMT_A_FILES))
|
||||
|
||||
|
@ -75,6 +76,7 @@ o/$(MODE)/libc/fmt/itoa128radix10.greg.o: \
|
|||
LIBC_FMT_LIBS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)))
|
||||
LIBC_FMT_SRCS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_FMT_HDRS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)_HDRS))
|
||||
LIBC_FMT_INCS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)_INCS))
|
||||
LIBC_FMT_CHECKS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)_CHECKS))
|
||||
LIBC_FMT_OBJS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)_OBJS))
|
||||
$(LIBC_FMT_OBJS): $(BUILD_FILES) libc/fmt/fmt.mk
|
||||
|
|
|
@ -331,7 +331,7 @@ typedef uint64_t uintmax_t;
|
|||
|
||||
#ifndef nullterminated
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__sentinel__) || __GNUC__ >= 4)
|
||||
(__has_attribute(__sentinel__) || __GNUC__ + 0 >= 4)
|
||||
#define nullterminated(x) __attribute__((__sentinel__ x))
|
||||
#else
|
||||
#define nullterminated(x)
|
||||
|
|
|
@ -154,6 +154,13 @@ static void *__asan_repstosb(void *di, int al, size_t cx) {
|
|||
return di;
|
||||
}
|
||||
|
||||
static void *__asan_repmovsb(void *di, void *si, size_t cx) {
|
||||
asm("rep movsb"
|
||||
: "=D"(di), "=S"(si), "=c"(cx), "=m"(*(char(*)[cx])di)
|
||||
: "0"(di), "1"(si), "2"(cx), "m"(*(char(*)[cx])si));
|
||||
return di;
|
||||
}
|
||||
|
||||
static void *__asan_memset(void *p, int c, size_t n) {
|
||||
char *b;
|
||||
size_t i;
|
||||
|
@ -264,14 +271,18 @@ static void *__asan_mempcpy(void *dst, const void *src, size_t n) {
|
|||
__builtin_memcpy(d + n - 8, &b, 8);
|
||||
return d + n;
|
||||
default:
|
||||
i = 0;
|
||||
do {
|
||||
__builtin_memcpy(&a, s + i, 8);
|
||||
asm volatile("" ::: "memory");
|
||||
__builtin_memcpy(d + i, &a, 8);
|
||||
} while ((i += 8) + 8 <= n);
|
||||
for (; i < n; ++i) d[i] = s[i];
|
||||
return d + i;
|
||||
if (n <= 64) {
|
||||
i = 0;
|
||||
do {
|
||||
__builtin_memcpy(&a, s + i, 8);
|
||||
asm volatile("" ::: "memory");
|
||||
__builtin_memcpy(d + i, &a, 8);
|
||||
} while ((i += 8) + 8 <= n);
|
||||
for (; i < n; ++i) d[i] = s[i];
|
||||
return d + i;
|
||||
} else {
|
||||
return __asan_repmovsb(d, s, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,16 +291,6 @@ static void *__asan_memcpy(void *dst, const void *src, size_t n) {
|
|||
return dst;
|
||||
}
|
||||
|
||||
static void *__asan_memrchr(void *p, int c, size_t n) {
|
||||
uint8_t *b;
|
||||
for (c &= 0xff, b = p; n--;) {
|
||||
if (b[n] == c) {
|
||||
return b + n;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static size_t __asan_int2hex(uint64_t x, char b[17], uint8_t k) {
|
||||
int i;
|
||||
char *p;
|
||||
|
@ -455,8 +456,6 @@ static wontreturn void __asan_report_heap_fault(void *addr, long c) {
|
|||
char *p, ibuf[21], buf[256];
|
||||
p = __asan_report_start(buf);
|
||||
p = __asan_stpcpy(p, __asan_dscribe_heap_poison(c));
|
||||
p = __asan_stpcpy(p, " ");
|
||||
p = __asan_mempcpy(p, ibuf, __asan_int2str(c, ibuf));
|
||||
p = __asan_stpcpy(p, " at 0x");
|
||||
p = __asan_mempcpy(p, ibuf, __asan_int2hex((intptr_t)addr, ibuf, 48));
|
||||
p = __asan_stpcpy(p, " shadow 0x");
|
||||
|
@ -709,7 +708,9 @@ void __asan_map_shadow(uintptr_t p, size_t n) {
|
|||
int i, x, a, b;
|
||||
struct DirectMap sm;
|
||||
struct MemoryIntervals *m;
|
||||
if (0x7fff8000 <= p && p < 0x100080000000) {
|
||||
if ((0x7fff8000 <= p && p < 0x100080000000) ||
|
||||
(0x7fff8000 <= p + n && p + n < 0x100080000000) ||
|
||||
(p < 0x7fff8000 && 0x100080000000 <= p + n)) {
|
||||
__asan_die("asan error: mmap can't shadow a shadow\r\n");
|
||||
}
|
||||
m = weaken(_mmi);
|
||||
|
|
|
@ -46,7 +46,8 @@ $(LIBC_INTRIN_A_OBJS): \
|
|||
|
||||
o/$(MODE)/libc/intrin/asan.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-mgeneral-regs-only
|
||||
-mgeneral-regs-only \
|
||||
-O2
|
||||
|
||||
LIBC_INTRIN_LIBS = $(foreach x,$(LIBC_INTRIN_ARTIFACTS),$($(x)))
|
||||
LIBC_INTRIN_HDRS = $(foreach x,$(LIBC_INTRIN_ARTIFACTS),$($(x)_HDRS))
|
||||
|
|
|
@ -29,6 +29,6 @@
|
|||
void(psrldq)(uint8_t b[16], const uint8_t a[16], unsigned long n) {
|
||||
unsigned i;
|
||||
if (n > 16) n = 16;
|
||||
memcpy(b, a + n, 16 - n);
|
||||
memset(b + (16 - n), 0, n);
|
||||
__builtin_memcpy(b, a + n, 16 - n);
|
||||
__builtin_memset(b + (16 - n), 0, n);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
PKGS += LIBC
|
||||
|
||||
LIBC_HDRS = $(filter %.h,$(LIBC_FILES))
|
||||
LIBC_INCS = $(filter %.inc,$(LIBC_FILES))
|
||||
LIBC_FILES := $(wildcard libc/*)
|
||||
LIBC_CHECKS = $(LIBC_HDRS:%=o/$(MODE)/%.ok)
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
|
||||
/ Half size of level 3 cache in bytes.
|
||||
.initbss 202,_init_kHalfCache3
|
||||
/ Half size of level 3 cache in bytes.
|
||||
kHalfCache3:
|
||||
.quad 0
|
||||
.endobj kHalfCache3,globl
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern long kHalfCache3;
|
||||
|
||||
void imapxlatab(void *);
|
||||
void insertionsort(int32_t *, size_t);
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ LIBC_NEXGEN32E = $(LIBC_NEXGEN32E_A_DEPS) $(LIBC_NEXGEN32E_A)
|
|||
LIBC_NEXGEN32E_A = o/$(MODE)/libc/nexgen32e/nexgen32e.a
|
||||
LIBC_NEXGEN32E_A_FILES := $(wildcard libc/nexgen32e/*)
|
||||
LIBC_NEXGEN32E_A_HDRS = $(filter %.h,$(LIBC_NEXGEN32E_A_FILES))
|
||||
LIBC_NEXGEN32E_A_INCS = $(filter %.inc,$(LIBC_NEXGEN32E_A_FILES))
|
||||
LIBC_NEXGEN32E_A_SRCS_A = $(filter %.s,$(LIBC_NEXGEN32E_A_FILES))
|
||||
LIBC_NEXGEN32E_A_SRCS_S = $(filter %.S,$(LIBC_NEXGEN32E_A_FILES))
|
||||
LIBC_NEXGEN32E_A_SRCS_C = $(filter %.c,$(LIBC_NEXGEN32E_A_FILES))
|
||||
|
@ -49,6 +50,7 @@ o/$(MODE)/libc/nexgen32e/tinystrncmp.ncabi.o: \
|
|||
LIBC_NEXGEN32E_LIBS = $(foreach x,$(LIBC_NEXGEN32E_ARTIFACTS),$($(x)))
|
||||
LIBC_NEXGEN32E_SRCS = $(foreach x,$(LIBC_NEXGEN32E_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_NEXGEN32E_HDRS = $(foreach x,$(LIBC_NEXGEN32E_ARTIFACTS),$($(x)_HDRS))
|
||||
LIBC_NEXGEN32E_INCS = $(foreach x,$(LIBC_NEXGEN32E_ARTIFACTS),$($(x)_INCS))
|
||||
LIBC_NEXGEN32E_CHECKS = $(foreach x,$(LIBC_NEXGEN32E_ARTIFACTS),$($(x)_CHECKS))
|
||||
LIBC_NEXGEN32E_OBJS = $(foreach x,$(LIBC_NEXGEN32E_ARTIFACTS),$($(x)_OBJS))
|
||||
$(LIBC_NEXGEN32E_OBJS): $(BUILD_FILES) libc/nexgen32e/nexgen32e.mk
|
||||
|
|
|
@ -21,71 +21,6 @@
|
|||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
/ Returns pointer to first instance of character.
|
||||
/
|
||||
/ @param rdi is a non-null NUL-terminated string pointer
|
||||
/ @param esi is the search byte
|
||||
/ @return rax points to character, or to NUL byte if not found
|
||||
/ @note this won't return NULL if search character is NUL
|
||||
strchrnul:
|
||||
.leafprologue
|
||||
.profilable
|
||||
or $-1,%r9
|
||||
jmp 0f
|
||||
.endfn strchrnul,globl
|
||||
|
||||
/ Returns pointer to first instance of character, the BSD way.
|
||||
/
|
||||
/ @param rdi is a non-null NUL-terminated string pointer
|
||||
/ @param esi is the search byte
|
||||
/ @return rax points to first result, or NULL if not found
|
||||
/ @note this won't return NULL if search character is NUL
|
||||
index: nop
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn index,globl
|
||||
|
||||
/ Returns pointer to first instance of character.
|
||||
/
|
||||
/ @param rdi is a non-null NUL-terminated string pointer
|
||||
/ @param esi is the search byte
|
||||
/ @return rax points to first result, or NULL if not found
|
||||
/ @note this won't return NULL if search character is NUL
|
||||
/ @asyncsignalsafe
|
||||
strchr: .leafprologue
|
||||
.profilable
|
||||
xor %r9d,%r9d
|
||||
0: movzbl %sil,%edx
|
||||
or $-1,%rsi
|
||||
xor %r8,%r8
|
||||
jmp strsak
|
||||
.endfn strchr,globl
|
||||
|
||||
/ Returns pointer to first instance of character in range.
|
||||
/
|
||||
/ @param rdi is a non-null pointer to memory
|
||||
/ @param esi is the search byte
|
||||
/ @return rax points to byte if found, or else undefined behavior
|
||||
rawmemchr:
|
||||
or $-1,%rdx
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn rawmemchr,globl
|
||||
|
||||
/ Returns pointer to first instance of character in range.
|
||||
/
|
||||
/ @param rdi is a non-null pointer to memory
|
||||
/ @param esi is the search byte
|
||||
/ @param rdx is length of memory in bytes
|
||||
/ @return rax points to byte if found or NULL
|
||||
/ @asyncsignalsafe
|
||||
memchr: .leafprologue
|
||||
.profilable
|
||||
xchg %rsi,%rdx
|
||||
mov %dl,%dh
|
||||
xor %r8,%r8
|
||||
xor %r10,%r10
|
||||
jmp strsak
|
||||
.endfn memchr,globl
|
||||
|
||||
/ Returns length of NUL-terminated string w/ security blankets.
|
||||
/
|
||||
/ This is like strnlen() except it'll return 0 if (1) RDI is NULL
|
||||
|
@ -102,24 +37,13 @@ strnlen_s:
|
|||
test %rdi,%rdi
|
||||
jnz 0f
|
||||
.leafepilogue
|
||||
.endfn strnlen_s,globl
|
||||
|
||||
/ Returns length of NUL-terminated memory, with limit.
|
||||
/
|
||||
/ @param rdi is non-null memory
|
||||
/ @param rsi is the maximum number of bytes to consider
|
||||
/ @return rax is the number of bytes, excluding the NUL
|
||||
/ @asyncsignalsafe
|
||||
strnlen:.leafprologue
|
||||
.profilable
|
||||
or $-1,%r10
|
||||
0: xor %edx,%edx
|
||||
mov %rdi,%r8
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn strnlen,globl
|
||||
.endfn strnlen_s,globl
|
||||
|
||||
/ Swiss army knife of string character scanning.
|
||||
/ Fourteen fast functions in one.
|
||||
/ Used to be fourteen fast functions in one.
|
||||
/
|
||||
/ @param rdi is non-null string memory
|
||||
/ @param rsi is max number of bytes to consider
|
||||
|
|
|
@ -5,6 +5,7 @@ PKGS += LIBC_NT
|
|||
|
||||
LIBC_NT_LIBS = $(foreach x,$(LIBC_NT_ARTIFACTS),$($(x)))
|
||||
LIBC_NT_HDRS = $(foreach x,$(LIBC_NT_ARTIFACTS),$($(x)_HDRS))
|
||||
LIBC_NT_INCS = $(foreach x,$(LIBC_NT_ARTIFACTS),$($(x)_INCS))
|
||||
LIBC_NT_SRCS = $(foreach x,$(LIBC_NT_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_NT_OBJS = $(foreach x,$(LIBC_NT_ARTIFACTS),$($(x)_OBJS))
|
||||
LIBC_NT_CHECKS = $(foreach x,$(LIBC_NT_ARTIFACTS),$($(x)_CHECKS))
|
||||
|
@ -22,9 +23,8 @@ LIBC_NT_A_FILES := \
|
|||
$(wildcard libc/nt/nt/*.*) \
|
||||
$(wildcard libc/nt/*)
|
||||
|
||||
LIBC_NT_A_HDRS = \
|
||||
$(filter %.h,$(LIBC_NT_A_FILES))
|
||||
|
||||
LIBC_NT_A_HDRS = $(filter %.h,$(LIBC_NT_A_FILES))
|
||||
LIBC_NT_A_INCS = $(filter %.inc,$(LIBC_NT_A_FILES))
|
||||
LIBC_NT_A_CHECKS = $(patsubst %,o/$(MODE)/%.ok,$(filter %.h,$(LIBC_NT_A_HDRS)))
|
||||
|
||||
#───────────────────────────────────────────────────────────────────────────────
|
||||
|
|
|
@ -8,6 +8,7 @@ LIBC_SOCK = $(LIBC_SOCK_A_DEPS) $(LIBC_SOCK_A)
|
|||
LIBC_SOCK_A = o/$(MODE)/libc/sock/sock.a
|
||||
LIBC_SOCK_A_FILES := $(wildcard libc/sock/*)
|
||||
LIBC_SOCK_A_HDRS = $(filter %.h,$(LIBC_SOCK_A_FILES))
|
||||
LIBC_SOCK_A_INCS = $(filter %.inc,$(LIBC_SOCK_A_FILES))
|
||||
LIBC_SOCK_A_SRCS = $(filter %.c,$(LIBC_SOCK_A_FILES))
|
||||
|
||||
LIBC_SOCK_A_OBJS = \
|
||||
|
@ -31,6 +32,7 @@ LIBC_SOCK_A_DIRECTDEPS = \
|
|||
LIBC_NT_WS2_32 \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_SYSV
|
||||
|
@ -49,6 +51,7 @@ $(LIBC_SOCK_A).pkg: \
|
|||
LIBC_SOCK_LIBS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)))
|
||||
LIBC_SOCK_SRCS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_SOCK_HDRS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)_HDRS))
|
||||
LIBC_SOCK_INCS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)_INCS))
|
||||
LIBC_SOCK_CHECKS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)_CHECKS))
|
||||
LIBC_SOCK_OBJS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)_OBJS))
|
||||
$(LIBC_SOCK_OBJS): $(BUILD_FILES) libc/sock/sock.mk
|
||||
|
|
|
@ -27,7 +27,7 @@ STATIC_YOINK("_init_g_stderr");
|
|||
FILE *stderr;
|
||||
|
||||
hidden FILE g_stderr;
|
||||
hidden unsigned char g_stderr_buf[BUFSIZ] forcealign(PAGESIZE);
|
||||
hidden unsigned char g_stderr_buf[BUFSIZ];
|
||||
|
||||
static textstartup void _init_g_stderr2() {
|
||||
_fflushregister(stderr);
|
||||
|
|
|
@ -27,7 +27,7 @@ STATIC_YOINK("_init_g_stdin");
|
|||
FILE *stdin;
|
||||
|
||||
hidden FILE g_stdin;
|
||||
hidden unsigned char g_stdin_buf[BUFSIZ] forcealign(PAGESIZE);
|
||||
hidden unsigned char g_stdin_buf[BUFSIZ];
|
||||
|
||||
static textstartup void g_stdin_init() {
|
||||
_fflushregister(stdin);
|
||||
|
|
|
@ -30,7 +30,7 @@ STATIC_YOINK("_init_g_stdout");
|
|||
FILE *stdout;
|
||||
|
||||
hidden FILE g_stdout;
|
||||
hidden unsigned char g_stdout_buf[BUFSIZ] forcealign(PAGESIZE);
|
||||
hidden unsigned char g_stdout_buf[BUFSIZ];
|
||||
|
||||
static textstartup void _init_g_stdout2() {
|
||||
struct FILE *sf;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
|
@ -18,12 +18,14 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
void *tinymemccpy(void *dst, const void *src, int termchar, size_t limit) {
|
||||
size_t i;
|
||||
unsigned char *d;
|
||||
const unsigned char *s;
|
||||
for (termchar &= 0xff, d = dst, s = src, i = 0; i < limit; ++i) {
|
||||
if ((d[i] = s[i]) == termchar) return d + i + 1;
|
||||
}
|
||||
return NULL;
|
||||
/**
|
||||
* Returns pointer to first instance of character, the BSD way.
|
||||
*
|
||||
* @param s is a NUL-terminated string
|
||||
* @param is masked with 255 as byte to search for
|
||||
* @return is pointer to first instance of c or NULL if not found,
|
||||
* noting that c being NUL will return a pointer to terminator
|
||||
*/
|
||||
char *index(const char *s, int c) {
|
||||
return strchr(s, c);
|
||||
}
|
|
@ -18,8 +18,14 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static noasan uint64_t UncheckedAlignedRead64(unsigned char *p) {
|
||||
return (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
|
||||
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies at most 𝑛 bytes from 𝑠 to 𝑑 until 𝑐 is encountered.
|
||||
* Copies at most N bytes from SRC to DST until 𝑐 is encountered.
|
||||
*
|
||||
* This is little-known C Standard Library approach, dating back to the
|
||||
* Fourth Edition of System Five, for copying a C strings to fixed-width
|
||||
|
@ -39,17 +45,46 @@
|
|||
* char cstrbuf[16];
|
||||
* snprintf(cstrbuf, sizeof(cstrbuf), "%s", CSTR);
|
||||
*
|
||||
* @return 𝑑 + idx(𝑐) + 1, or NULL if 𝑐 ∉ 𝑠₀․․ₙ₋₁
|
||||
* @note 𝑑 and 𝑠 can't overlap
|
||||
* @param c is search character and is masked with 255
|
||||
* @return DST + idx(c) + 1, or NULL if 𝑐 ∉ 𝑠₀․․ₙ₋₁
|
||||
* @note DST and SRC can't overlap
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
void *memccpy(void *d, const void *s, int c, size_t n) {
|
||||
const char *p, *pe;
|
||||
p = s;
|
||||
if ((pe = memchr(p, c, n))) {
|
||||
return mempcpy(d, s, pe - p + 1);
|
||||
} else {
|
||||
memcpy(d, s, n);
|
||||
return NULL;
|
||||
void *memccpy(void *dst, const void *src, int c, size_t n) {
|
||||
size_t i;
|
||||
uint64_t v, w;
|
||||
unsigned char *d;
|
||||
unsigned char *pd;
|
||||
const unsigned char *s;
|
||||
i = 0;
|
||||
d = dst;
|
||||
s = src;
|
||||
c &= 255;
|
||||
v = 0x0101010101010101 * c;
|
||||
for (; (uintptr_t)(s + i) & 7; ++i) {
|
||||
if (i == n) return NULL;
|
||||
if ((d[i] = s[i]) == c) return d + i + 1;
|
||||
}
|
||||
for (; i + 8 <= n; i += 8) {
|
||||
w = UncheckedAlignedRead64(s + i);
|
||||
if (~(w ^ v) & ((w ^ v) - 0x0101010101010101) & 0x8080808080808080) {
|
||||
break;
|
||||
} else {
|
||||
pd = d + i;
|
||||
pd[0] = (w >> 000) & 255;
|
||||
pd[1] = (w >> 010) & 255;
|
||||
pd[2] = (w >> 020) & 255;
|
||||
pd[3] = (w >> 030) & 255;
|
||||
pd[4] = (w >> 040) & 255;
|
||||
pd[5] = (w >> 050) & 255;
|
||||
pd[6] = (w >> 060) & 255;
|
||||
pd[7] = (w >> 070) & 255;
|
||||
}
|
||||
}
|
||||
for (; i < n; ++i) {
|
||||
if ((d[i] = s[i]) == c) {
|
||||
return d + i + 1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
47
libc/str/memchr.c
Normal file
47
libc/str/memchr.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Returns pointer to first instance of character.
|
||||
*
|
||||
* @param m is memory to search
|
||||
* @param c is search byte which is masked with 255
|
||||
* @param n is byte length of p
|
||||
* @return is pointer to first instance of c or NULL if not found
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
void *memchr(const void *m, int c, size_t n) {
|
||||
uint64_t v, w;
|
||||
const unsigned char *p, *pe;
|
||||
c &= 255;
|
||||
v = 0x0101010101010101 * c;
|
||||
for (p = (const unsigned char *)m, pe = p + n; p + 8 <= pe; p += 8) {
|
||||
w = (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
|
||||
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
|
||||
if ((w = ~(w ^ v) & ((w ^ v) - 0x0101010101010101) & 0x8080808080808080)) {
|
||||
return p + ((unsigned)__builtin_ctzll(w) >> 3);
|
||||
}
|
||||
}
|
||||
for (; p < pe; ++p) {
|
||||
if (*p == c) return p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
160
libc/str/memmove-pure.c
Normal file
160
libc/str/memmove-pure.c
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
typedef long long xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
|
||||
|
||||
/**
|
||||
* Copies memory.
|
||||
*
|
||||
* DST and SRC may overlap.
|
||||
*
|
||||
* @param dst is destination
|
||||
* @param src is memory to copy
|
||||
* @param n is number of bytes to copy
|
||||
* @return dst
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
void *memmove$pure(void *dst, const void *src, size_t n) {
|
||||
size_t i;
|
||||
xmm_t v, w;
|
||||
char *d, *r;
|
||||
const char *s;
|
||||
uint64_t a, b;
|
||||
d = dst;
|
||||
s = src;
|
||||
switch (n) {
|
||||
case 9 ... 15:
|
||||
__builtin_memcpy(&a, s, 8);
|
||||
__builtin_memcpy(&b, s + n - 8, 8);
|
||||
__builtin_memcpy(d, &a, 8);
|
||||
__builtin_memcpy(d + n - 8, &b, 8);
|
||||
return d;
|
||||
case 5 ... 7:
|
||||
__builtin_memcpy(&a, s, 4);
|
||||
__builtin_memcpy(&b, s + n - 4, 4);
|
||||
__builtin_memcpy(d, &a, 4);
|
||||
__builtin_memcpy(d + n - 4, &b, 4);
|
||||
return d;
|
||||
case 17 ... 32:
|
||||
__builtin_memcpy(&v, s, 16);
|
||||
__builtin_memcpy(&w, s + n - 16, 16);
|
||||
__builtin_memcpy(d, &v, 16);
|
||||
__builtin_memcpy(d + n - 16, &w, 16);
|
||||
return d;
|
||||
case 16:
|
||||
__builtin_memcpy(&v, s, 16);
|
||||
__builtin_memcpy(d, &v, 16);
|
||||
return d;
|
||||
case 0:
|
||||
return d;
|
||||
case 1:
|
||||
*d = *s;
|
||||
return d;
|
||||
case 8:
|
||||
__builtin_memcpy(&a, s, 8);
|
||||
__builtin_memcpy(d, &a, 8);
|
||||
return d;
|
||||
case 4:
|
||||
__builtin_memcpy(&a, s, 4);
|
||||
__builtin_memcpy(d, &a, 4);
|
||||
return d;
|
||||
case 2:
|
||||
__builtin_memcpy(&a, s, 2);
|
||||
__builtin_memcpy(d, &a, 2);
|
||||
return d;
|
||||
case 3:
|
||||
__builtin_memcpy(&a, s, 2);
|
||||
__builtin_memcpy(&b, s + 1, 2);
|
||||
__builtin_memcpy(d, &a, 2);
|
||||
__builtin_memcpy(d + 1, &b, 2);
|
||||
return d;
|
||||
default:
|
||||
r = d;
|
||||
if (d > s) {
|
||||
do {
|
||||
n -= 32;
|
||||
__builtin_memcpy(&v, s + n, 16);
|
||||
__builtin_memcpy(&w, s + n + 16, 16);
|
||||
__builtin_memcpy(d + n, &v, 16);
|
||||
__builtin_memcpy(d + n + 16, &w, 16);
|
||||
} while (n >= 32);
|
||||
} else {
|
||||
i = 0;
|
||||
do {
|
||||
__builtin_memcpy(&v, s + i, 16);
|
||||
__builtin_memcpy(&w, s + i + 16, 16);
|
||||
__builtin_memcpy(d + i, &v, 16);
|
||||
__builtin_memcpy(d + i + 16, &w, 16);
|
||||
} while ((i += 32) + 32 <= n);
|
||||
d += i;
|
||||
s += i;
|
||||
n -= i;
|
||||
}
|
||||
switch (n) {
|
||||
case 0:
|
||||
return r;
|
||||
case 17 ... 31:
|
||||
__builtin_memcpy(&v, s, 16);
|
||||
__builtin_memcpy(&w, s + n - 16, 16);
|
||||
__builtin_memcpy(d, &v, 16);
|
||||
__builtin_memcpy(d + n - 16, &w, 16);
|
||||
return r;
|
||||
case 9 ... 15:
|
||||
__builtin_memcpy(&a, s, 8);
|
||||
__builtin_memcpy(&b, s + n - 8, 8);
|
||||
__builtin_memcpy(d, &a, 8);
|
||||
__builtin_memcpy(d + n - 8, &b, 8);
|
||||
return r;
|
||||
case 5 ... 7:
|
||||
__builtin_memcpy(&a, s, 4);
|
||||
__builtin_memcpy(&b, s + n - 4, 4);
|
||||
__builtin_memcpy(d, &a, 4);
|
||||
__builtin_memcpy(d + n - 4, &b, 4);
|
||||
return r;
|
||||
case 16:
|
||||
__builtin_memcpy(&v, s, 16);
|
||||
__builtin_memcpy(d, &v, 16);
|
||||
return r;
|
||||
case 8:
|
||||
__builtin_memcpy(&a, s, 8);
|
||||
__builtin_memcpy(d, &a, 8);
|
||||
return r;
|
||||
case 4:
|
||||
__builtin_memcpy(&a, s, 4);
|
||||
__builtin_memcpy(d, &a, 4);
|
||||
return r;
|
||||
case 1:
|
||||
*d = *s;
|
||||
return r;
|
||||
case 2:
|
||||
__builtin_memcpy(&a, s, 2);
|
||||
__builtin_memcpy(d, &a, 2);
|
||||
return r;
|
||||
case 3:
|
||||
__builtin_memcpy(&a, s, 2);
|
||||
__builtin_memcpy(&b, s + 1, 2);
|
||||
__builtin_memcpy(d, &a, 2);
|
||||
__builtin_memcpy(d + 1, &b, 2);
|
||||
return r;
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
}
|
100
libc/str/memset-pure.c
Normal file
100
libc/str/memset-pure.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Sets memory.
|
||||
*
|
||||
* @param p is memory address
|
||||
* @param c is masked with 255 and used as repeated byte
|
||||
* @param n is byte length
|
||||
* @return p
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
void *memset$pure(void *p, int c, size_t n) {
|
||||
char *b;
|
||||
uint64_t x;
|
||||
b = p;
|
||||
x = 0x0101010101010101 * (c & 0xff);
|
||||
switch (n) {
|
||||
case 0:
|
||||
return p;
|
||||
case 1:
|
||||
__builtin_memcpy(b, &x, 1);
|
||||
return p;
|
||||
case 2:
|
||||
__builtin_memcpy(b, &x, 2);
|
||||
return p;
|
||||
case 3:
|
||||
__builtin_memcpy(b, &x, 2);
|
||||
__builtin_memcpy(b + 1, &x, 2);
|
||||
return p;
|
||||
case 4:
|
||||
__builtin_memcpy(b, &x, 4);
|
||||
return p;
|
||||
case 5 ... 7:
|
||||
__builtin_memcpy(b, &x, 4);
|
||||
__builtin_memcpy(b + n - 4, &x, 4);
|
||||
return p;
|
||||
case 8:
|
||||
__builtin_memcpy(b, &x, 8);
|
||||
return p;
|
||||
case 9 ... 16:
|
||||
__builtin_memcpy(b, &x, 8);
|
||||
__builtin_memcpy(b + n - 8, &x, 8);
|
||||
return p;
|
||||
default:
|
||||
do {
|
||||
n -= 16;
|
||||
__builtin_memcpy(b + n, &x, 8);
|
||||
asm volatile("" ::: "memory");
|
||||
__builtin_memcpy(b + n + 8, &x, 8);
|
||||
} while (n >= 16);
|
||||
switch (n) {
|
||||
case 0:
|
||||
return p;
|
||||
case 1:
|
||||
__builtin_memcpy(b, &x, 1);
|
||||
return p;
|
||||
case 2:
|
||||
__builtin_memcpy(b, &x, 2);
|
||||
return p;
|
||||
case 3:
|
||||
__builtin_memcpy(b, &x, 2);
|
||||
__builtin_memcpy(b + 1, &x, 2);
|
||||
return p;
|
||||
case 4:
|
||||
__builtin_memcpy(b, &x, 4);
|
||||
return p;
|
||||
case 5 ... 7:
|
||||
__builtin_memcpy(b, &x, 4);
|
||||
__builtin_memcpy(b + n - 4, &x, 4);
|
||||
return p;
|
||||
case 8:
|
||||
__builtin_memcpy(b, &x, 8);
|
||||
return p;
|
||||
case 9 ... 15:
|
||||
__builtin_memcpy(b, &x, 8);
|
||||
__builtin_memcpy(b + n - 8, &x, 8);
|
||||
return p;
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
}
|
53
libc/str/rawmemchr.c
Normal file
53
libc/str/rawmemchr.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static noasan uint64_t UncheckedAlignedRead64(unsigned char *p) {
|
||||
return (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
|
||||
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pointer to first instance of character.
|
||||
*
|
||||
* @param m is memory to search
|
||||
* @param c is search byte which is masked with 255
|
||||
* @return is pointer to first instance of c
|
||||
*/
|
||||
void *rawmemchr(const void *m, int c) {
|
||||
uint64_t v, w;
|
||||
const unsigned char *s;
|
||||
s = m;
|
||||
c &= 255;
|
||||
v = 0x0101010101010101 * c;
|
||||
for (; (uintptr_t)s & 7; ++s) {
|
||||
if (*s == c) return s;
|
||||
}
|
||||
for (;; s += 8) {
|
||||
w = UncheckedAlignedRead64(s);
|
||||
if ((w = ~(w ^ v) & ((w ^ v) - 0x0101010101010101) & 0x8080808080808080)) {
|
||||
s += (unsigned)__builtin_ctzll(w) >> 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(*s == c);
|
||||
return s;
|
||||
}
|
|
@ -90,7 +90,6 @@ void *memeqmask(void *, const void *, const void *, size_t) memcpyesque;
|
|||
size_t strlen(const char *) strlenesque;
|
||||
size_t strnlen(const char *, size_t) strlenesque;
|
||||
size_t strnlen_s(const char *, size_t);
|
||||
size_t strlen$pure(const char *) strlenesque;
|
||||
char *strchr(const char *, int) strlenesque;
|
||||
char *index(const char *, int) strlenesque;
|
||||
void *memchr(const void *, int, size_t) strlenesque;
|
||||
|
@ -246,8 +245,8 @@ char *strsignal(int) returnsnonnull libcesque;
|
|||
│ cosmopolitan § strings » optimizations ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#define __memcpy_isgoodsize(SIZE) \
|
||||
(__builtin_constant_p(SIZE) && ((SIZE) <= __BIGGEST_ALIGNMENT__ * 2 && \
|
||||
#define __memcpy_isgoodsize(SIZE) \
|
||||
(__builtin_constant_p(SIZE) && ((SIZE) <= __BIGGEST_ALIGNMENT__ && \
|
||||
__builtin_popcountl((unsigned)(SIZE)) == 1))
|
||||
|
||||
#define __memset_isgoodsize(SIZE) \
|
||||
|
@ -361,15 +360,44 @@ char *strsignal(int) returnsnonnull libcesque;
|
|||
})
|
||||
|
||||
#endif /* hosted/sse2/unbloat */
|
||||
#ifdef __FSANITIZE_ADDRESS__
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § strings » address sanitizer ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
void *memset$pure(void *, int, size_t) memcpyesque;
|
||||
void *memmove$pure(void *, const void *, size_t) memcpyesque;
|
||||
size_t strlen$pure(const char *) strlenesque;
|
||||
size_t strcspn$pure(const char *, const char *) strlenesque;
|
||||
#if defined(__FSANITIZE_ADDRESS__)
|
||||
|
||||
#define strcspn(STR, REJECT) strcspn$pure(STR, REJECT)
|
||||
|
||||
#ifdef strlen
|
||||
#undef strlen
|
||||
#endif
|
||||
#define strlen(s) strlen$pure(s)
|
||||
#define strlen(STR) \
|
||||
(__builtin_constant_p(STR) ? __builtin_strlen(STR) : strlen$pure(STR))
|
||||
|
||||
#undef memset
|
||||
#define memset(DST, CHAR, SIZE) \
|
||||
(__memcpy_isgoodsize(SIZE) ? __builtin_memset(DST, CHAR, SIZE) \
|
||||
: memset$pure(DST, CHAR, SIZE))
|
||||
|
||||
#undef memmove
|
||||
#define memmove(DST, SRC, SIZE) \
|
||||
(__memcpy_isgoodsize(SIZE) ? __builtin_memmove(DST, SRC, SIZE) \
|
||||
: memmove$pure(DST, SRC, SIZE))
|
||||
|
||||
#undef memcpy
|
||||
#define memcpy(DST, SRC, SIZE) \
|
||||
(__memcpy_isgoodsize(SIZE) ? __builtin_memcpy(DST, SRC, SIZE) \
|
||||
: memmove$pure(DST, SRC, SIZE))
|
||||
|
||||
#undef mempcpy
|
||||
#define mempcpy(DST, SRC, SIZE) \
|
||||
(__memcpy_isgoodsize(SIZE) ? __builtin_mempcpy(DST, SRC, SIZE) : ({ \
|
||||
void *DsT = (DST); \
|
||||
size_t SiZe = (SIZE); \
|
||||
memmove$pure(DsT, SRC, SiZe); \
|
||||
(void *)((char *)DsT + SiZe); \
|
||||
}))
|
||||
|
||||
#endif /* __FSANITIZE_ADDRESS__ */
|
||||
#endif /* __GNUC__ && !__STRICT_ANSI__ */
|
||||
|
|
|
@ -8,6 +8,7 @@ LIBC_STR = $(LIBC_STR_A_DEPS) $(LIBC_STR_A)
|
|||
LIBC_STR_A = o/$(MODE)/libc/str/str.a
|
||||
LIBC_STR_A_FILES := $(wildcard libc/str/*)
|
||||
LIBC_STR_A_HDRS = $(filter %.h,$(LIBC_STR_A_FILES))
|
||||
LIBC_STR_A_INCS = $(filter %.inc,$(LIBC_STR_A_FILES))
|
||||
LIBC_STR_A_SRCS_A = $(filter %.s,$(LIBC_STR_A_FILES))
|
||||
LIBC_STR_A_SRCS_S = $(filter %.S,$(LIBC_STR_A_FILES))
|
||||
LIBC_STR_A_SRCS_C = $(filter %.c,$(LIBC_STR_A_FILES))
|
||||
|
@ -49,6 +50,7 @@ o/$(MODE)/libc/str/memmem.o: \
|
|||
LIBC_STR_LIBS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)))
|
||||
LIBC_STR_SRCS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_STR_HDRS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_HDRS))
|
||||
LIBC_STR_INCS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_INCS))
|
||||
LIBC_STR_BINS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_BINS))
|
||||
LIBC_STR_CHECKS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_CHECKS))
|
||||
LIBC_STR_OBJS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_OBJS))
|
||||
|
|
69
libc/str/strchr.c
Normal file
69
libc/str/strchr.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
noasan static const unsigned char *strchr$x64(const unsigned char *p,
|
||||
uint64_t c) {
|
||||
unsigned a, b;
|
||||
uint64_t w, x, y;
|
||||
for (c *= 0x0101010101010101;; p += 8) {
|
||||
w = (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
|
||||
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
|
||||
if ((x = ~(w ^ c) & ((w ^ c) - 0x0101010101010101) & 0x8080808080808080) |
|
||||
(y = ~w & (w - 0x0101010101010101) & 0x8080808080808080)) {
|
||||
if (x) {
|
||||
a = __builtin_ctzll(x);
|
||||
if (y) {
|
||||
b = __builtin_ctzll(y);
|
||||
if (a <= b) {
|
||||
return p + (a >> 3);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
return p + (a >> 3);
|
||||
}
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pointer to first instance of character.
|
||||
*
|
||||
* @param s is a NUL-terminated string
|
||||
* @param c is masked with 255 as byte to search for
|
||||
* @return pointer to first instance of c or NULL if not found
|
||||
* noting that if c is NUL we return pointer to terminator
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
char *strchr(const char *s, int c) {
|
||||
char *r;
|
||||
for (c &= 0xff; (uintptr_t)s & 7; ++s) {
|
||||
if ((*s & 0xff) == c) return s;
|
||||
if (!*s) return NULL;
|
||||
}
|
||||
r = (char *)strchr$x64((const unsigned char *)s, c);
|
||||
assert(!r || *r || !c);
|
||||
return r;
|
||||
}
|
69
libc/str/strchrnul.c
Normal file
69
libc/str/strchrnul.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
noasan static const unsigned char *strchrnul$x64(const unsigned char *p,
|
||||
uint64_t c) {
|
||||
unsigned a, b;
|
||||
uint64_t w, x, y;
|
||||
for (c *= 0x0101010101010101;; p += 8) {
|
||||
w = (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
|
||||
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
|
||||
if ((x = ~(w ^ c) & ((w ^ c) - 0x0101010101010101) & 0x8080808080808080) |
|
||||
(y = ~w & (w - 0x0101010101010101) & 0x8080808080808080)) {
|
||||
if (x) {
|
||||
a = __builtin_ctzll(x);
|
||||
if (y) {
|
||||
b = __builtin_ctzll(y);
|
||||
if (a <= b) {
|
||||
return p + (a >> 3);
|
||||
} else {
|
||||
return p + (b >> 3);
|
||||
}
|
||||
} else {
|
||||
return p + (a >> 3);
|
||||
}
|
||||
} else {
|
||||
b = __builtin_ctzll(y);
|
||||
return p + (b >> 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pointer to first instance of character.
|
||||
*
|
||||
* @param s is a NUL-terminated string
|
||||
* @param c is masked with 255 as byte to search for
|
||||
* @return pointer to first instance of c, or pointer to
|
||||
* NUL terminator if c is not found
|
||||
*/
|
||||
char *strchrnul(const char *s, int c) {
|
||||
char *r;
|
||||
for (c &= 0xff; (uintptr_t)s & 7; ++s) {
|
||||
if ((*s & 0xff) == c) return s;
|
||||
if (!*s) return s;
|
||||
}
|
||||
r = (char *)strchrnul$x64((const unsigned char *)s, c);
|
||||
assert((*r & 0xff) == c || !*r);
|
||||
return r;
|
||||
}
|
|
@ -18,6 +18,12 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static inline noasan uint64_t UncheckedAlignedRead64(unsigned char *p) {
|
||||
return (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
|
||||
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares NUL-terminated strings.
|
||||
*
|
||||
|
@ -28,7 +34,25 @@
|
|||
*/
|
||||
int strcmp(const char *a, const char *b) {
|
||||
size_t i = 0;
|
||||
uint64_t v, w, d;
|
||||
if (a == b) return 0;
|
||||
while (a[i] == b[i] && b[i]) ++i;
|
||||
return (a[i] & 0xff) - (b[i] & 0xff);
|
||||
if (((uintptr_t)a & 7) == ((uintptr_t)b & 7)) {
|
||||
for (; (uintptr_t)a & 7; ++i) {
|
||||
if (a[i] != b[i] || !b[i]) {
|
||||
return (a[i] & 0xff) - (b[i] & 0xff);
|
||||
}
|
||||
}
|
||||
for (;; i += 8) {
|
||||
v = UncheckedAlignedRead64(a + i);
|
||||
w = UncheckedAlignedRead64(b + i);
|
||||
w = (v ^ w) | (~v & (v - 0x0101010101010101) & 0x8080808080808080);
|
||||
if (w) {
|
||||
i += (unsigned)__builtin_ctzll(w) >> 3;
|
||||
return (a[i] & 0xff) - (b[i] & 0xff);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (a[i] == b[i] && b[i]) ++i;
|
||||
return (a[i] & 0xff) - (b[i] & 0xff);
|
||||
}
|
||||
}
|
||||
|
|
62
libc/str/strcspn-pure.c
Normal file
62
libc/str/strcspn-pure.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/pcmpeqb.h"
|
||||
#include "libc/intrin/pmovmskb.h"
|
||||
#include "libc/intrin/pshufd.h"
|
||||
#include "libc/intrin/punpcklbw.h"
|
||||
#include "libc/intrin/punpcklwd.h"
|
||||
#include "libc/nexgen32e/hascharacter.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#define V(p) (void *)(p)
|
||||
|
||||
/**
|
||||
* Returns prefix length, consisting of chars not in reject.
|
||||
* a.k.a. Return index of first byte that's in charset.
|
||||
*
|
||||
* @param reject is nul-terminated character set
|
||||
* @see strspn(), strtok_r()
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
size_t strcspn$pure(const char *s, const char *reject) {
|
||||
size_t i, n;
|
||||
unsigned m;
|
||||
char cv[16], sv[16];
|
||||
if ((n = strlen(reject)) < 16) {
|
||||
memset(sv, 0, 16);
|
||||
memcpy(sv, reject, n);
|
||||
for (i = 0;; ++i) {
|
||||
cv[0] = s[i];
|
||||
punpcklbw(V(cv), V(cv), V(cv));
|
||||
punpcklwd(V(cv), V(cv), V(cv));
|
||||
pshufd(V(cv), V(cv), 0);
|
||||
pcmpeqb(V(cv), V(cv), V(sv));
|
||||
if ((m = pmovmskb(V(cv)))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
for (i = 0; s[i]; ++i) {
|
||||
if (HasCharacter(s[i], reject)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
|
@ -16,35 +16,35 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
noasan static const char *strlen$pure$x64(const char *p) {
|
||||
static noasan size_t strlen$pure$x64(const char *s, size_t i) {
|
||||
uint64_t w;
|
||||
const unsigned char *p;
|
||||
for (;;) {
|
||||
w = *(uint64_t *)p;
|
||||
if (~w & (w - 0x0101010101010101) & 0x8080808080808080) {
|
||||
break;
|
||||
p = (const unsigned char *)s + i;
|
||||
w = (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
|
||||
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
|
||||
if ((w = ~w & (w - 0x0101010101010101) & 0x8080808080808080)) {
|
||||
return i + ((unsigned)__builtin_ctzll(w) >> 3);
|
||||
} else {
|
||||
p += 8;
|
||||
i += 8;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns length of NUL-terminated string.
|
||||
*/
|
||||
size_t strlen$pure(const char *s) {
|
||||
const char *p;
|
||||
p = s;
|
||||
while ((uintptr_t)p & 7) {
|
||||
if (*p) {
|
||||
++p;
|
||||
} else {
|
||||
return p - s;
|
||||
}
|
||||
size_t i;
|
||||
for (i = 0; (uintptr_t)(s + i) & 7; ++i) {
|
||||
if (!s[i]) return i;
|
||||
}
|
||||
p = strlen$pure$x64(p);
|
||||
while (*p) ++p;
|
||||
return p - s;
|
||||
i = strlen$pure$x64(s, i);
|
||||
assert(!i || s[0]);
|
||||
assert(!s[i]);
|
||||
return i;
|
||||
}
|
||||
|
|
57
libc/str/strnlen.c
Normal file
57
libc/str/strnlen.c
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static noasan size_t strnlen$x64(const char *s, size_t n, size_t i) {
|
||||
uint64_t w;
|
||||
const unsigned char *p;
|
||||
for (; i + 8 < n; i += 8) {
|
||||
p = (const unsigned char *)s + i;
|
||||
w = (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
|
||||
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
|
||||
if ((w = ~w & (w - 0x0101010101010101) & 0x8080808080808080)) {
|
||||
i += (unsigned)__builtin_ctzll(w) >> 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns length of NUL-terminated string w/ limit.
|
||||
*
|
||||
* @param s is string
|
||||
* @param n is max length
|
||||
* @return byte length
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
size_t strnlen(const char *s, size_t n) {
|
||||
size_t i;
|
||||
for (i = 0; (uintptr_t)(s + i) & 7; ++i) {
|
||||
if (i == n || !s[i]) return i;
|
||||
}
|
||||
i = strnlen$x64(s, n, i);
|
||||
for (;; ++i) {
|
||||
if (i == n || !s[i]) break;
|
||||
}
|
||||
assert(i == n || (i < n && !s[i]));
|
||||
return i;
|
||||
}
|
|
@ -5,6 +5,7 @@ PKGS += LIBC_SYSV
|
|||
LIBC_SYSV_LIBS = $(foreach x,$(LIBC_SYSV_ARTIFACTS),$($(x)_A))
|
||||
LIBC_SYSV_ARCHIVES = $(foreach x,$(LIBC_SYSV_ARTIFACTS),$($(x)_A))
|
||||
LIBC_SYSV_HDRS = $(foreach x,$(LIBC_SYSV_ARTIFACTS),$($(x)_HDRS))
|
||||
LIBC_SYSV_INCS = $(foreach x,$(LIBC_SYSV_ARTIFACTS),$($(x)_INCS))
|
||||
LIBC_SYSV_BINS = $(foreach x,$(LIBC_SYSV_ARTIFACTS),$($(x)_BINS))
|
||||
LIBC_SYSV_CHECKS = $(foreach x,$(LIBC_SYSV_ARTIFACTS),$($(x)_CHECKS))
|
||||
LIBC_SYSV_OBJS = $(foreach x,$(LIBC_SYSV_ARTIFACTS),$($(x)_OBJS))
|
||||
|
@ -20,6 +21,7 @@ LIBC_SYSV = \
|
|||
LIBC_SYSV_ARTIFACTS += LIBC_SYSV_A
|
||||
LIBC_SYSV_A = o/$(MODE)/libc/sysv/sysv.a
|
||||
LIBC_SYSV_A_HDRS = $(filter %.h,$(LIBC_SYSV_A_FILES))
|
||||
LIBC_SYSV_A_INCS = $(filter %.inc,$(LIBC_SYSV_A_FILES))
|
||||
LIBC_SYSV_A_SRCS_A = $(filter %.s,$(LIBC_SYSV_A_FILES))
|
||||
LIBC_SYSV_A_SRCS_S = $(filter %.S,$(LIBC_SYSV_A_FILES))
|
||||
LIBC_SYSV_A_CHECKS = $(LIBC_SYSV_A).pkg
|
||||
|
|
|
@ -27,8 +27,8 @@ STATIC_YOINK("strnwidth");
|
|||
|
||||
void __testlib_ezbenchreport(const char *form, uint64_t c1, uint64_t c2) {
|
||||
uint64_t ns1, ns2;
|
||||
ns1 = rintl(converttickstonanos(c1));
|
||||
ns2 = rintl(converttickstonanos(c2));
|
||||
ns1 = rintl(ConvertTicksToNanos(c1));
|
||||
ns2 = rintl(ConvertTicksToNanos(c2));
|
||||
(fprintf)(stderr,
|
||||
VEIL("r", "%-30s l: %,10lu𝑐 %,10lu𝑛𝑠 m: %,10lu𝑐 %,10lu𝑛𝑠\n"),
|
||||
form, c1, ns1, c2, ns2);
|
||||
|
|
|
@ -60,8 +60,7 @@ int futimesat(int, const char *, const struct timeval[2]);
|
|||
long double dtime(int);
|
||||
long double dsleep(long double);
|
||||
extern long double (*nowl)(void);
|
||||
long double converttickstonanos(uint64_t);
|
||||
long double converttickstoseconds(uint64_t);
|
||||
long double ConvertTicksToNanos(uint64_t);
|
||||
|
||||
double difftime(int64_t, int64_t) nothrow pureconst;
|
||||
|
||||
|
|
|
@ -80,11 +80,12 @@ prpppppppppppppoooooooonnnnnnnnnnnnnnnooooooooppppppppppppptp\
|
|||
pppppppppppppppppppoooooooooooooooooooooooppppppppppppppppppp";
|
||||
|
||||
TEST(gyarados, testIdentityDifference) {
|
||||
static unsigned char A[1][32][62];
|
||||
static unsigned char B[1][32][62];
|
||||
static unsigned char A[1][32][61];
|
||||
static unsigned char B[1][32][61];
|
||||
ASSERT_EQ(sizeof(A), strlen(kDieWelle));
|
||||
memcpy(A, kDieWelle, sizeof(A));
|
||||
EzGyarados(1, 32, 61, B, 1, 32, 61, A, 0, 1, 32, 61, 32, 61, 1, 1, 0, 0);
|
||||
AbsoluteDifference(32, 62, B[0], 32, 62, B[0], 32, 62, A[0]);
|
||||
AbsoluteDifference(32, 61, B[0], 32, 61, B[0], 32, 61, A[0]);
|
||||
EXPECT_STREQ(u"\n\
|
||||
\n\
|
||||
\n\
|
||||
|
|
|
@ -26,6 +26,7 @@ TEST_LIBC_CRYPTO_DIRECTDEPS = \
|
|||
LIBC_INTRIN \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_TESTLIB
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ TEST_LIBC_MEM_DIRECTDEPS = \
|
|||
LIBC_RAND \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_TESTLIB
|
||||
|
|
|
@ -17,77 +17,117 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
#define N 256
|
||||
#define S 7
|
||||
#define N 65
|
||||
#define S 1
|
||||
|
||||
long i, j, n;
|
||||
char *b1, *b2;
|
||||
char *b0, *b1, *b2;
|
||||
|
||||
noinline char *PosixMemmove(char *dst, const char *src, size_t n) {
|
||||
char *tmp;
|
||||
tmp = malloc(n);
|
||||
memcpy(tmp, src, n);
|
||||
memcpy(dst, tmp, n);
|
||||
free(tmp);
|
||||
return dst;
|
||||
}
|
||||
|
||||
TEST(memmove, overlapping) {
|
||||
for (i = 0; i < N; i += S) {
|
||||
for (j = 10; j < N; j += S) {
|
||||
b1 = malloc(N);
|
||||
b2 = malloc(N);
|
||||
n = min(N - i, N - j);
|
||||
memcpy(b2, b1 + i, n);
|
||||
ASSERT_EQ(b1 + j, memmove(b1 + j, b1 + i, n));
|
||||
ASSERT_EQ(0, memcmp(b1 + j, b2, n));
|
||||
free(b2);
|
||||
free(b1);
|
||||
for (j = 0; j < N; j += S) {
|
||||
for (n = MIN(N - i, N - j) + 1; n--;) {
|
||||
b0 = rngset(malloc(N), N, rand64, -1);
|
||||
b1 = memcpy(malloc(N), b0, N);
|
||||
b2 = memcpy(malloc(N), b0, N);
|
||||
ASSERT_EQ(b1 + j, memmove(b1 + j, b1 + i, n));
|
||||
ASSERT_EQ(b2 + j, PosixMemmove(b2 + j, b2 + i, n));
|
||||
ASSERT_EQ(0, memcmp(b1, b2, N),
|
||||
"j=%ld i=%ld n=%ld\n"
|
||||
"\t%#.*s data\n"
|
||||
"\t%#.*s memmove\n"
|
||||
"\t%#.*s posix",
|
||||
j, i, n, n, b0, n, b1, n, b2);
|
||||
free(b2);
|
||||
free(b1);
|
||||
free(b0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(memmove$pure, overlapping) {
|
||||
for (i = 0; i < N; i += S) {
|
||||
for (j = 0; j < N; j += S) {
|
||||
for (n = MIN(N - i, N - j) + 1; n--;) {
|
||||
b0 = rngset(malloc(N), N, rand64, -1);
|
||||
b1 = memcpy(malloc(N), b0, N);
|
||||
b2 = memcpy(malloc(N), b0, N);
|
||||
ASSERT_EQ(b1 + j, memmove$pure(b1 + j, b1 + i, n));
|
||||
ASSERT_EQ(b2 + j, PosixMemmove(b2 + j, b2 + i, n));
|
||||
ASSERT_EQ(0, memcmp(b1, b2, N),
|
||||
"j=%ld i=%ld n=%ld\n"
|
||||
"\t%#.*s data\n"
|
||||
"\t%#.*s memmove\n"
|
||||
"\t%#.*s posix",
|
||||
j, i, n, n, b0, n, b1, n, b2);
|
||||
free(b2);
|
||||
free(b1);
|
||||
free(b0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(memcpy, overlapping) {
|
||||
for (i = 0; i < N; i += S) {
|
||||
for (j = 0; j < N; j += S) {
|
||||
for (n = MIN(N - i, N - j) + 1; n--;) {
|
||||
if (j <= i) {
|
||||
b0 = rngset(malloc(N), N, rand64, -1);
|
||||
b1 = memcpy(malloc(N), b0, N);
|
||||
b2 = memcpy(malloc(N), b0, N);
|
||||
ASSERT_EQ(b1 + j, memcpy(b1 + j, b1 + i, n));
|
||||
ASSERT_EQ(b2 + j, PosixMemmove(b2 + j, b2 + i, n));
|
||||
ASSERT_EQ(0, memcmp(b1, b2, N),
|
||||
"j=%ld i=%ld n=%ld\n"
|
||||
"\t%#.*s data\n"
|
||||
"\t%#.*s memmove\n"
|
||||
"\t%#.*s posix",
|
||||
j, i, n, n, b0, n, b1, n, b2);
|
||||
free(b2);
|
||||
free(b1);
|
||||
free(b0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(memmove, overlappingDirect) {
|
||||
for (i = 0; i < N; i += S) {
|
||||
for (j = 10; j < N; j += S) {
|
||||
b1 = malloc(N);
|
||||
b2 = malloc(N);
|
||||
n = min(N - i, N - j);
|
||||
memcpy(b2, b1 + i, n);
|
||||
ASSERT_EQ(b1 + j, (memmove)(b1 + j, b1 + i, n));
|
||||
ASSERT_EQ(0, memcmp(b1 + j, b2, n));
|
||||
free(b2);
|
||||
free(b1);
|
||||
for (j = 0; j < N; j += S) {
|
||||
for (n = MIN(N - i, N - j) + 1; n--;) {
|
||||
b0 = rngset(malloc(N), N, rand64, -1);
|
||||
b1 = memcpy(malloc(N), b0, N);
|
||||
b2 = memcpy(malloc(N), b0, N);
|
||||
ASSERT_EQ(b1 + j, (memmove)(b1 + j, b1 + i, n));
|
||||
ASSERT_EQ(b2 + j, PosixMemmove(b2 + j, b2 + i, n));
|
||||
ASSERT_EQ(0, memcmp(b1, b2, N),
|
||||
"j=%ld i=%ld n=%ld\n"
|
||||
"\t%#.*s data\n"
|
||||
"\t%#.*s memmove\n"
|
||||
"\t%#.*s posix",
|
||||
j, i, n, n, b0, n, b1, n, b2);
|
||||
free(b2);
|
||||
free(b1);
|
||||
free(b0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *MoveMemory(char *dst, const char *src, size_t n) {
|
||||
size_t i;
|
||||
for (i = 0; i < n; ++i) {
|
||||
dst[i] = src[i];
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
TEST(memmove, overlappingBackwards_isGenerallySafe) {
|
||||
char buf[32];
|
||||
strcpy(buf, "abcdefghijklmnopqrstuvwxyz");
|
||||
ASSERT_STREQ("cdefghijklmnopqrstuvwxyzyz", MoveMemory(buf, buf + 2, 24));
|
||||
strcpy(buf, "abcdefghijklmnopqrstuvwxyz");
|
||||
ASSERT_STREQ("cdefghijklmnopqrstuvwxyzyz", memmove(buf, buf + 2, 24));
|
||||
strcpy(buf, "abcdefghijklmnopqrstuvwxyz");
|
||||
ASSERT_STREQ("cdefghijklmnopqrstuvwxyzyz", memcpy(buf, buf + 2, 24));
|
||||
}
|
||||
|
||||
TEST(memmove, overlappingForwards_avoidsRunLengthDecodeBehavior) {
|
||||
volatile char buf[32];
|
||||
strcpy(buf, "abc");
|
||||
MoveMemory(buf + 1, buf, 2);
|
||||
ASSERT_STREQ("aaa", buf);
|
||||
strcpy(buf, "abc");
|
||||
(memmove)(buf + 1, buf, 2);
|
||||
ASSERT_STREQ("aab", buf);
|
||||
strcpy(buf, "abcdefghijklmnopqrstuvwxyz");
|
||||
MoveMemory(buf + 2, buf, 24);
|
||||
ASSERT_STREQ("ababababababababababababab", buf);
|
||||
strcpy(buf, "abcdefghijklmnopqrstuvwxyz");
|
||||
memmove(buf + 2, buf, 24);
|
||||
ASSERT_STREQ("ababcdefghijklmnopqrstuvwx", buf);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ TEST_LIBC_SOCK_DIRECTDEPS = \
|
|||
LIBC_RUNTIME \
|
||||
LIBC_SOCK \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_TESTLIB \
|
||||
|
|
|
@ -23,7 +23,15 @@
|
|||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
void *memccpy2(void *, const void *, int, size_t);
|
||||
void *memccpy$pure(void *d, const void *s, int c, size_t n) {
|
||||
size_t i;
|
||||
unsigned char *x;
|
||||
const unsigned char *y;
|
||||
for (c &= 0xff, x = d, y = s, i = 0; i < n; ++i) {
|
||||
if ((x[i] = y[i]) == c) return x + i + 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TEST(memccpy, testStringCopy) {
|
||||
char buf[16];
|
||||
|
@ -49,7 +57,7 @@ TEST(memccpy, memcpy) {
|
|||
b2 = calloc(1, n);
|
||||
b3 = calloc(1, n);
|
||||
rngset(b1, n, rand64, -1);
|
||||
e1 = tinymemccpy(b2, b1, 31337, n);
|
||||
e1 = memccpy$pure(b2, b1, 31337, n);
|
||||
e2 = memccpy(b3, b1, 31337, n);
|
||||
n1 = e1 ? e1 - b2 : n;
|
||||
n2 = e2 ? e2 - b3 : n;
|
||||
|
|
|
@ -18,38 +18,54 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(memcpy, memcpy) {
|
||||
TEST(memcpy, test) {
|
||||
char *b1, *b2;
|
||||
for (unsigned n = 0; n < 1026; ++n) {
|
||||
b1 = malloc(n);
|
||||
b2 = malloc(n);
|
||||
ASSERT_EQ(b1, memcpy(b1, b2, n));
|
||||
rngset(b1, n, rand64, -1);
|
||||
rngset(b2, n, rand64, -1);
|
||||
ASSERT_EQ(b1, memcpy(b1, b2, n), "%ld\n\t%#.*s\n\t%#.*s", n, n, b1, n, b2);
|
||||
ASSERT_EQ(0, memcmp(b1, b2, n));
|
||||
free(b2);
|
||||
free(b1);
|
||||
}
|
||||
for (unsigned n = kHalfCache3 - 1; n < kHalfCache3 + 2; ++n) {
|
||||
b1 = malloc(n);
|
||||
b2 = malloc(n);
|
||||
rngset(b1, n, rand64, -1);
|
||||
rngset(b2, n, rand64, -1);
|
||||
ASSERT_EQ(b1, memcpy(b1, b2, n), "%ld\n\t%#.*s\n\t%#.*s", n, n, b1, n, b2);
|
||||
ASSERT_EQ(0, memcmp(b1, b2, n));
|
||||
free(b2);
|
||||
free(b1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(memcpy, memcpyDirect) {
|
||||
TEST(mempcpy, test) {
|
||||
char *b1, *b2;
|
||||
for (unsigned n = 0; n < 1026; ++n) {
|
||||
b1 = malloc(n);
|
||||
b2 = malloc(n);
|
||||
ASSERT_EQ(b1, (memcpy)(b1, b2, n));
|
||||
rngset(b1, n, rand64, -1);
|
||||
rngset(b2, n, rand64, -1);
|
||||
ASSERT_EQ(b1 + n, mempcpy(b1, b2, n));
|
||||
ASSERT_EQ(0, memcmp(b1, b2, n));
|
||||
free(b2);
|
||||
free(b1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(memcpy, mempcpy) {
|
||||
char *b1, *b2;
|
||||
for (unsigned n = 0; n < 1026; ++n) {
|
||||
for (unsigned n = kHalfCache3 - 1; n < kHalfCache3 + 2; ++n) {
|
||||
b1 = malloc(n);
|
||||
b2 = malloc(n);
|
||||
rngset(b1, n, rand64, -1);
|
||||
rngset(b2, n, rand64, -1);
|
||||
ASSERT_EQ(b1 + n, mempcpy(b1, b2, n));
|
||||
ASSERT_EQ(0, memcmp(b1, b2, n));
|
||||
free(b2);
|
||||
|
@ -57,11 +73,49 @@ TEST(memcpy, mempcpy) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST(memcpy, mempcpyDirect) {
|
||||
TEST(memcpy, direct) {
|
||||
char *b1, *b2;
|
||||
for (unsigned n = 0; n < 1026; ++n) {
|
||||
b1 = malloc(n);
|
||||
b2 = malloc(n);
|
||||
rngset(b1, n, rand64, -1);
|
||||
rngset(b2, n, rand64, -1);
|
||||
ASSERT_EQ(b1, (memcpy)(b1, b2, n), "%ld\n\t%#.*s\n\t%#.*s", n, n, b1, n,
|
||||
b2);
|
||||
ASSERT_EQ(0, memcmp(b1, b2, n));
|
||||
free(b2);
|
||||
free(b1);
|
||||
}
|
||||
for (unsigned n = kHalfCache3 - 1; n < kHalfCache3 + 2; ++n) {
|
||||
b1 = malloc(n);
|
||||
b2 = malloc(n);
|
||||
rngset(b1, n, rand64, -1);
|
||||
rngset(b2, n, rand64, -1);
|
||||
ASSERT_EQ(b1, (memcpy)(b1, b2, n), "%ld\n\t%#.*s\n\t%#.*s", n, n, b1, n,
|
||||
b2);
|
||||
ASSERT_EQ(0, memcmp(b1, b2, n));
|
||||
free(b2);
|
||||
free(b1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(mempcpy, direct) {
|
||||
char *b1, *b2;
|
||||
for (unsigned n = 0; n < 1026; ++n) {
|
||||
b1 = malloc(n);
|
||||
b2 = malloc(n);
|
||||
rngset(b1, n, rand64, -1);
|
||||
rngset(b2, n, rand64, -1);
|
||||
ASSERT_EQ(b1 + n, (mempcpy)(b1, b2, n));
|
||||
ASSERT_EQ(0, memcmp(b1, b2, n));
|
||||
free(b2);
|
||||
free(b1);
|
||||
}
|
||||
for (unsigned n = kHalfCache3 - 1; n < kHalfCache3 + 2; ++n) {
|
||||
b1 = malloc(n);
|
||||
b2 = malloc(n);
|
||||
rngset(b1, n, rand64, -1);
|
||||
rngset(b2, n, rand64, -1);
|
||||
ASSERT_EQ(b1 + n, (mempcpy)(b1, b2, n));
|
||||
ASSERT_EQ(0, memcmp(b1, b2, n));
|
||||
free(b2);
|
||||
|
@ -105,3 +159,44 @@ TEST(memcpy, testBackwardsOverlap3) {
|
|||
EXPECT_EQ('C', c[1]);
|
||||
free(c);
|
||||
}
|
||||
|
||||
void *MemCpy(void *, const void *, size_t);
|
||||
|
||||
#define B(F, N) \
|
||||
do { \
|
||||
char *d = rngset(malloc(N), N, rand64, -1); \
|
||||
char *s = rngset(malloc(N), N, rand64, -1); \
|
||||
EZBENCH2(#F " " #N, donothing, \
|
||||
EXPROPRIATE(F(VEIL("r", d), VEIL("r", s), N))); \
|
||||
free(d); \
|
||||
free(s); \
|
||||
} while (0)
|
||||
|
||||
#define BB(N) \
|
||||
do { \
|
||||
B(memmove$pure, N); \
|
||||
B(memcpy, N); \
|
||||
B(MemCpy, N); \
|
||||
fprintf(stderr, "\n"); \
|
||||
} while (0)
|
||||
|
||||
BENCH(memcpy, bench) {
|
||||
BB(0);
|
||||
BB(1);
|
||||
BB(2);
|
||||
BB(3);
|
||||
BB(7);
|
||||
BB(8);
|
||||
BB(15);
|
||||
BB(16);
|
||||
BB(31);
|
||||
BB(32);
|
||||
BB(63);
|
||||
BB(64);
|
||||
BB(255);
|
||||
BB(256);
|
||||
BB(1023);
|
||||
BB(1024);
|
||||
BB(PAGESIZE);
|
||||
BB(FRAMESIZE);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,10 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(strchr, blank) {
|
||||
|
@ -66,3 +69,99 @@ TEST(strchrnul, notFound_returnsPointerToNulByte) {
|
|||
EXPECT_STREQ("", strchrnul(buf, 'z'));
|
||||
EXPECT_EQ(&buf[2], strchrnul(buf, 'z'));
|
||||
}
|
||||
|
||||
char *strchr$pure(const char *s, int c) {
|
||||
char *r;
|
||||
for (c &= 0xff;; ++s) {
|
||||
if ((*s & 0xff) == c) return (char *)s;
|
||||
if (!*s) return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(strchr, fuzz) {
|
||||
char *p;
|
||||
int i, j;
|
||||
p = calloc(1, 64);
|
||||
for (i = -2; i < 257; ++i) {
|
||||
for (j = 0; j < 17; ++j) {
|
||||
rngset(p, 63, rand64, -1);
|
||||
ASSERT_EQ(strchr(p + j, i), strchr$pure(p + j, i));
|
||||
}
|
||||
}
|
||||
free(p);
|
||||
}
|
||||
|
||||
BENCH(strchr, bench) {
|
||||
EZBENCH2("strchr 0", donothing, EXPROPRIATE(strchr(VEIL("r", ""), 0)));
|
||||
EZBENCH2("strchr 5", donothing, EXPROPRIATE(strchr(VEIL("r", "hello"), 'o')));
|
||||
EZBENCH2("strchr 8", donothing,
|
||||
EXPROPRIATE(strchr(VEIL("r", "hellzzzo"), 'o')));
|
||||
EZBENCH2("strchr 17", donothing,
|
||||
EXPROPRIATE(strchr(VEIL("r", "hellzzzhellzzzeeo"), 'o')));
|
||||
EZBENCH2("strchr 34", donothing,
|
||||
EXPROPRIATE(
|
||||
strchr(VEIL("r", "hellzzzhellzzzeeAhellzzzhellzzzeeo"), 'o')));
|
||||
}
|
||||
|
||||
char *memchr$pure(const char *m, int c, size_t n) {
|
||||
const unsigned char *p, *pe;
|
||||
for (c &= 0xff, p = (const unsigned char *)m, pe = p + n; p < pe; ++p) {
|
||||
if (*p == c) return p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TEST(memchr, fuzz) {
|
||||
char *p;
|
||||
int i, j;
|
||||
p = malloc(64);
|
||||
for (i = -2; i < 257; ++i) {
|
||||
for (j = 0; j < 17; ++j) {
|
||||
rngset(p, 64, rand64, -1);
|
||||
ASSERT_EQ(memchr(p + j, i, 64 - j), memchr$pure(p + j, i, 64 - j));
|
||||
}
|
||||
}
|
||||
free(p);
|
||||
}
|
||||
|
||||
char *strchrnul$pure(const char *s, int c) {
|
||||
char *r;
|
||||
for (c &= 0xff;; ++s) {
|
||||
if ((*s & 0xff) == c) return (char *)s;
|
||||
if (!*s) return s;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(strchrnul, fuzz) {
|
||||
char *p;
|
||||
int i, j;
|
||||
p = calloc(1, 64);
|
||||
for (i = -2; i < 257; ++i) {
|
||||
for (j = 0; j < 17; ++j) {
|
||||
rngset(p, 63, rand64, -1);
|
||||
ASSERT_EQ(strchrnul(p + j, i), strchrnul$pure(p + j, i));
|
||||
}
|
||||
}
|
||||
free(p);
|
||||
}
|
||||
|
||||
void *rawmemchr$pure(const void *m, int c) {
|
||||
const unsigned char *s;
|
||||
for (c &= 255, s = m;; ++s) {
|
||||
if (*s == c) return s;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(rawmemchr, fuzz) {
|
||||
char *p;
|
||||
int i, j;
|
||||
p = malloc(64);
|
||||
for (i = -2; i < 257; ++i) {
|
||||
for (j = 0; j < 17; ++j) {
|
||||
rngset(p, 63, rand64, -1);
|
||||
p[63] = i;
|
||||
ASSERT_EQ(rawmemchr(p + j, i), rawmemchr$pure(p + j, i));
|
||||
}
|
||||
}
|
||||
free(p);
|
||||
}
|
||||
|
|
|
@ -19,8 +19,10 @@
|
|||
#include "libc/bits/bits.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/nexgen32e/tinystrlen.internal.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
@ -30,6 +32,8 @@ char16_t u16[] = u"utf16 ☻";
|
|||
wchar_t u32[] = L"utf32 ☻";
|
||||
|
||||
TEST(strlen, usageExample_c11) {
|
||||
_Alignas(16) char ugh[] = "eeeeeeeeeeeeeee\017";
|
||||
EXPECT_EQ(1, strlen$pure(ugh + 15));
|
||||
EXPECT_EQ(6 + 3, strlen(u8));
|
||||
EXPECT_EQ(7, strlen16(u16));
|
||||
EXPECT_EQ(7, wcslen(u32));
|
||||
|
@ -143,7 +147,7 @@ TEST(strlen, fuzz) {
|
|||
b = rngset(calloc(1, n), n - 1, rand64, -1);
|
||||
n1 = strlen(b);
|
||||
n2 = strlen$pure(b);
|
||||
ASSERT_EQ(n1, n2);
|
||||
ASSERT_EQ(n1, n2, "%#.*s", n, b);
|
||||
n1 = strlen(b + 1);
|
||||
n2 = strlen$pure(b + 1);
|
||||
ASSERT_EQ(n1, n2);
|
||||
|
@ -166,8 +170,14 @@ BENCH(strlen, bench) {
|
|||
EZBENCH2("strlen$pure 8", donothing, strlen$pure_("1234567"));
|
||||
EZBENCH2("strlen 9", donothing, strlen_("12345678"));
|
||||
EZBENCH2("strlen$pure 9", donothing, strlen$pure_("12345678"));
|
||||
EZBENCH2("strlen 11", donothing, strlen_("12345678aa"));
|
||||
EZBENCH2("strlen$pure 11", donothing, strlen$pure_("12345678aa"));
|
||||
EZBENCH2("strlen 13", donothing, strlen_("12345678aabb"));
|
||||
EZBENCH2("strlen$pure 13", donothing, strlen$pure_("12345678aabb"));
|
||||
EZBENCH2("strlen 16", donothing, strlen_("123456781234567"));
|
||||
EZBENCH2("strlen$pure 16", donothing, strlen$pure_("123456781234567"));
|
||||
EZBENCH2("strlen 17", donothing, strlen_("123456781234567e"));
|
||||
EZBENCH2("strlen$pure 17", donothing, strlen$pure_("123456781234567e"));
|
||||
EZBENCH2("strlen 1023", donothing, strlen_(b));
|
||||
EZBENCH2("strlen$pure 1023", donothing, strlen$pure_(b));
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ TEST_LIBC_TINYMATH_DIRECTDEPS = \
|
|||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_TESTLIB \
|
||||
LIBC_TINYMATH \
|
||||
|
|
2
third_party/compiler_rt/compiler_rt.mk
vendored
2
third_party/compiler_rt/compiler_rt.mk
vendored
|
@ -10,6 +10,7 @@ THIRD_PARTY_COMPILER_RT_A_FILES := \
|
|||
$(wildcard third_party/compiler_rt/*) \
|
||||
$(wildcard third_party/compiler_rt/nexgen32e/*)
|
||||
THIRD_PARTY_COMPILER_RT_A_HDRS = $(filter %.h,$(THIRD_PARTY_COMPILER_RT_A_FILES))
|
||||
THIRD_PARTY_COMPILER_RT_A_INCS = $(filter %.inc,$(THIRD_PARTY_COMPILER_RT_A_FILES))
|
||||
THIRD_PARTY_COMPILER_RT_A_SRCS_S = $(filter %.S,$(THIRD_PARTY_COMPILER_RT_A_FILES))
|
||||
THIRD_PARTY_COMPILER_RT_A_SRCS_C = $(filter %.c,$(THIRD_PARTY_COMPILER_RT_A_FILES))
|
||||
|
||||
|
@ -51,6 +52,7 @@ $(THIRD_PARTY_COMPILER_RT_A_OBJS): \
|
|||
THIRD_PARTY_COMPILER_RT_LIBS = $(foreach x,$(THIRD_PARTY_COMPILER_RT_ARTIFACTS),$($(x)))
|
||||
THIRD_PARTY_COMPILER_RT_SRCS = $(foreach x,$(THIRD_PARTY_COMPILER_RT_ARTIFACTS),$($(x)_SRCS))
|
||||
THIRD_PARTY_COMPILER_RT_HDRS = $(foreach x,$(THIRD_PARTY_COMPILER_RT_ARTIFACTS),$($(x)_HDRS))
|
||||
THIRD_PARTY_COMPILER_RT_INCS = $(foreach x,$(THIRD_PARTY_COMPILER_RT_ARTIFACTS),$($(x)_INCS))
|
||||
THIRD_PARTY_COMPILER_RT_CHECKS = $(foreach x,$(THIRD_PARTY_COMPILER_RT_ARTIFACTS),$($(x)_CHECKS))
|
||||
THIRD_PARTY_COMPILER_RT_OBJS = $(foreach x,$(THIRD_PARTY_COMPILER_RT_ARTIFACTS),$($(x)_OBJS))
|
||||
|
||||
|
|
2
third_party/duktape/duktape.mk
vendored
2
third_party/duktape/duktape.mk
vendored
|
@ -8,6 +8,7 @@ THIRD_PARTY_DUKTAPE = $(THIRD_PARTY_DUKTAPE_A_DEPS) $(THIRD_PARTY_DUKTAPE_A)
|
|||
THIRD_PARTY_DUKTAPE_A = o/$(MODE)/third_party/duktape/duktape.a
|
||||
THIRD_PARTY_DUKTAPE_A_FILES := $(wildcard third_party/duktape/*)
|
||||
THIRD_PARTY_DUKTAPE_A_HDRS = $(filter %.h,$(THIRD_PARTY_DUKTAPE_A_FILES))
|
||||
THIRD_PARTY_DUKTAPE_A_INCS = $(filter %.inc,$(THIRD_PARTY_DUKTAPE_A_FILES))
|
||||
THIRD_PARTY_DUKTAPE_A_SRCS_A = $(filter %.s,$(THIRD_PARTY_DUKTAPE_A_FILES))
|
||||
THIRD_PARTY_DUKTAPE_A_SRCS_S = $(filter %.S,$(THIRD_PARTY_DUKTAPE_A_FILES))
|
||||
THIRD_PARTY_DUKTAPE_A_SRCS_C = $(filter %.c,$(THIRD_PARTY_DUKTAPE_A_FILES))
|
||||
|
@ -60,6 +61,7 @@ o/dbg/third_party/duktape/duk_js_executor.o: \
|
|||
THIRD_PARTY_DUKTAPE_LIBS = $(foreach x,$(THIRD_PARTY_DUKTAPE_ARTIFACTS),$($(x)))
|
||||
THIRD_PARTY_DUKTAPE_SRCS = $(foreach x,$(THIRD_PARTY_DUKTAPE_ARTIFACTS),$($(x)_SRCS))
|
||||
THIRD_PARTY_DUKTAPE_HDRS = $(foreach x,$(THIRD_PARTY_DUKTAPE_ARTIFACTS),$($(x)_HDRS))
|
||||
THIRD_PARTY_DUKTAPE_INCS = $(foreach x,$(THIRD_PARTY_DUKTAPE_ARTIFACTS),$($(x)_INCS))
|
||||
THIRD_PARTY_DUKTAPE_BINS = $(foreach x,$(THIRD_PARTY_DUKTAPE_ARTIFACTS),$($(x)_BINS))
|
||||
THIRD_PARTY_DUKTAPE_CHECKS = $(foreach x,$(THIRD_PARTY_DUKTAPE_ARTIFACTS),$($(x)_CHECKS))
|
||||
THIRD_PARTY_DUKTAPE_OBJS = $(foreach x,$(THIRD_PARTY_DUKTAPE_ARTIFACTS),$($(x)_OBJS))
|
||||
|
|
2
third_party/gdtoa/gdtoa.mk
vendored
2
third_party/gdtoa/gdtoa.mk
vendored
|
@ -8,6 +8,7 @@ THIRD_PARTY_GDTOA = $(THIRD_PARTY_GDTOA_A_DEPS) $(THIRD_PARTY_GDTOA_A)
|
|||
THIRD_PARTY_GDTOA_A = o/$(MODE)/third_party/gdtoa/gdtoa.a
|
||||
THIRD_PARTY_GDTOA_A_FILES := $(wildcard third_party/gdtoa/*)
|
||||
THIRD_PARTY_GDTOA_A_HDRS = $(filter %.h,$(THIRD_PARTY_GDTOA_A_FILES))
|
||||
THIRD_PARTY_GDTOA_A_INCS = $(filter %.inc,$(THIRD_PARTY_GDTOA_A_FILES))
|
||||
THIRD_PARTY_GDTOA_A_SRCS_S = $(filter %.S,$(THIRD_PARTY_GDTOA_A_FILES))
|
||||
THIRD_PARTY_GDTOA_A_SRCS_C = $(filter %.c,$(THIRD_PARTY_GDTOA_A_FILES))
|
||||
|
||||
|
@ -54,6 +55,7 @@ $(THIRD_PARTY_GDTOA_A_OBJS): \
|
|||
THIRD_PARTY_GDTOA_LIBS = $(foreach x,$(THIRD_PARTY_GDTOA_ARTIFACTS),$($(x)))
|
||||
THIRD_PARTY_GDTOA_SRCS = $(foreach x,$(THIRD_PARTY_GDTOA_ARTIFACTS),$($(x)_SRCS))
|
||||
THIRD_PARTY_GDTOA_HDRS = $(foreach x,$(THIRD_PARTY_GDTOA_ARTIFACTS),$($(x)_HDRS))
|
||||
THIRD_PARTY_GDTOA_INCS = $(foreach x,$(THIRD_PARTY_GDTOA_ARTIFACTS),$($(x)_INCS))
|
||||
THIRD_PARTY_GDTOA_CHECKS = $(foreach x,$(THIRD_PARTY_GDTOA_ARTIFACTS),$($(x)_CHECKS))
|
||||
THIRD_PARTY_GDTOA_OBJS = $(foreach x,$(THIRD_PARTY_GDTOA_ARTIFACTS),$($(x)_OBJS))
|
||||
$(THIRD_PARTY_GDTOA_OBJS): $(BUILD_FILES) third_party/gdtoa/gdtoa.mk
|
||||
|
|
6
third_party/lemon/lemon.mk
vendored
6
third_party/lemon/lemon.mk
vendored
|
@ -1,6 +1,12 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
|
||||
PKGS += THIRD_PARTY_LEMON
|
||||
THIRD_PARTY_LEMON_FILES := $(wildcard third_party/lemon/*)
|
||||
THIRD_PARTY_LEMON_HDRS = $(filter %.h,$(THIRD_PARTY_LEMON_FILES))
|
||||
THIRD_PARTY_LEMON_INCS = $(filter %.inc,$(THIRD_PARTY_LEMON_FILES))
|
||||
THIRD_PARTY_LEMON_SRCS = $(filter %.c,$(THIRD_PARTY_LEMON_FILES))
|
||||
|
||||
LEMON = $(MKDIR) $(@D) && ACTION="LEMON $@" build/do $(THIRD_PARTY_LEMON)
|
||||
|
||||
THIRD_PARTY_LEMON = o/$(MODE)/third_party/lemon/lemon.com.dbg
|
||||
|
|
12
third_party/lz4cli/bench.c
vendored
12
third_party/lz4cli/bench.c
vendored
|
@ -36,8 +36,8 @@
|
|||
/* *************************************
|
||||
* Includes
|
||||
***************************************/
|
||||
#include "platform.h" /* Compiler options */
|
||||
#include "util.h" /* UTIL_GetFileSize, UTIL_sleep */
|
||||
#include "third_party/lz4cli/platform.h" /* Compiler options */
|
||||
#include "third_party/lz4cli/util.h" /* UTIL_GetFileSize, UTIL_sleep */
|
||||
#include "libc/mem/mem.h" /* malloc, free */
|
||||
#include "libc/str/str.h" /* memset */
|
||||
#include "libc/stdio/stdio.h" /* fprintf, fopen, ftello */
|
||||
|
@ -46,17 +46,17 @@
|
|||
#include "libc/bits/initializer.internal.h"
|
||||
#include "libc/runtime/runtime.h" /* assert */
|
||||
|
||||
#include "datagen.h" /* RDG_genBuffer */
|
||||
#include "xxhash.h"
|
||||
#include "third_party/lz4cli/datagen.h" /* RDG_genBuffer */
|
||||
#include "third_party/lz4cli/xxhash.h"
|
||||
|
||||
|
||||
#include "lz4.h"
|
||||
#include "third_party/lz4cli/lz4.h"
|
||||
#define COMPRESSOR0 LZ4_compress_local
|
||||
static int LZ4_compress_local(const char* src, char* dst, int srcSize, int dstSize, int clevel) {
|
||||
int const acceleration = (clevel < 0) ? -clevel + 1 : 1;
|
||||
return LZ4_compress_fast(src, dst, srcSize, dstSize, acceleration);
|
||||
}
|
||||
#include "lz4hc.h"
|
||||
#include "third_party/lz4cli/lz4hc.h"
|
||||
#define COMPRESSOR1 LZ4_compress_HC
|
||||
#define DEFAULTCOMPRESSOR COMPRESSOR0
|
||||
#define LZ4_isError(errcode) (errcode==0)
|
||||
|
|
4
third_party/lz4cli/datagen.c
vendored
4
third_party/lz4cli/datagen.c
vendored
|
@ -27,8 +27,8 @@
|
|||
/**************************************
|
||||
* Includes
|
||||
**************************************/
|
||||
#include "platform.h" /* Compiler options, SET_BINARY_MODE */
|
||||
#include "util.h" /* U32 */
|
||||
#include "third_party/lz4cli/platform.h" /* Compiler options, SET_BINARY_MODE */
|
||||
#include "third_party/lz4cli/util.h" /* U32 */
|
||||
#include "libc/mem/mem.h" /* malloc */
|
||||
#include "libc/stdio/stdio.h" /* FILE, fwrite */
|
||||
#include "libc/str/str.h" /* memcpy */
|
||||
|
|
2
third_party/lz4cli/lz4.c
vendored
2
third_party/lz4cli/lz4.c
vendored
|
@ -94,7 +94,7 @@
|
|||
**************************************/
|
||||
#define LZ4_STATIC_LINKING_ONLY
|
||||
#define LZ4_DISABLE_DEPRECATE_WARNINGS /* due to LZ4_decompress_safe_withPrefix64k */
|
||||
#include "lz4.h"
|
||||
#include "third_party/lz4cli/lz4.h"
|
||||
/* see also "memory routines" below */
|
||||
|
||||
|
||||
|
|
12
third_party/lz4cli/lz4cli.c
vendored
12
third_party/lz4cli/lz4cli.c
vendored
|
@ -36,17 +36,17 @@ asm(".include \"third_party/lz4cli/COPYING\"");
|
|||
/****************************
|
||||
* Includes
|
||||
*****************************/
|
||||
#include "platform.h" /* Compiler options, IS_CONSOLE */
|
||||
#include "util.h" /* UTIL_HAS_CREATEFILELIST, UTIL_createFileList */
|
||||
#include "third_party/lz4cli/platform.h" /* Compiler options, IS_CONSOLE */
|
||||
#include "third_party/lz4cli/util.h" /* UTIL_HAS_CREATEFILELIST, UTIL_createFileList */
|
||||
#include "libc/stdio/stdio.h" /* fprintf, getchar */
|
||||
#include "libc/mem/mem.h" /* exit, calloc, free */
|
||||
#include "libc/str/str.h" /* strcmp, strlen */
|
||||
#include "bench.h" /* BMK_benchFile, BMK_SetNbIterations, BMK_SetBlocksize, BMK_SetPause */
|
||||
#include "lz4io.h" /* LZ4IO_compressFilename, LZ4IO_decompressFilename, LZ4IO_compressMultipleFilenames */
|
||||
#include "lz4hc.h" /* LZ4HC_CLEVEL_MAX */
|
||||
#include "third_party/lz4cli/bench.h" /* BMK_benchFile, BMK_SetNbIterations, BMK_SetBlocksize, BMK_SetPause */
|
||||
#include "third_party/lz4cli/lz4io.h" /* LZ4IO_compressFilename, LZ4IO_decompressFilename, LZ4IO_compressMultipleFilenames */
|
||||
#include "third_party/lz4cli/lz4hc.h" /* LZ4HC_CLEVEL_MAX */
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "lz4.h" /* LZ4_VERSION_STRING */
|
||||
#include "third_party/lz4cli/lz4.h" /* LZ4_VERSION_STRING */
|
||||
|
||||
|
||||
/*****************************
|
||||
|
|
4
third_party/lz4cli/lz4cli.mk
vendored
4
third_party/lz4cli/lz4cli.mk
vendored
|
@ -13,6 +13,10 @@
|
|||
|
||||
PKGS += THIRD_PARTY_LZ4CLI
|
||||
|
||||
THIRD_PARTY_LZ4CLI_FILES := $(wildcard third_party/lz4cli/*)
|
||||
THIRD_PARTY_LZ4CLI_SRCS = $(filter %.c,$(THIRD_PARTY_LZ4CLI_FILES))
|
||||
THIRD_PARTY_LZ4CLI_HDRS = $(filter %.h,$(THIRD_PARTY_LZ4CLI_FILES))
|
||||
|
||||
THIRD_PARTY_LZ4CLI = \
|
||||
o/$(MODE)/third_party/lz4cli/lz4cli.com
|
||||
|
||||
|
|
4
third_party/lz4cli/lz4hc.c
vendored
4
third_party/lz4cli/lz4hc.c
vendored
|
@ -51,7 +51,7 @@
|
|||
|
||||
/*=== Dependency ===*/
|
||||
#define LZ4_HC_STATIC_LINKING_ONLY
|
||||
#include "lz4hc.h"
|
||||
#include "third_party/lz4cli/lz4hc.h"
|
||||
|
||||
|
||||
/*=== Common LZ4 definitions ===*/
|
||||
|
@ -63,7 +63,7 @@
|
|||
#endif
|
||||
|
||||
#define LZ4_COMMONDEFS_ONLY
|
||||
#include "lz4.c" /* LZ4_count, constants, mem */
|
||||
#include "third_party/lz4cli/lz4.c" /* LZ4_count, constants, mem */
|
||||
|
||||
|
||||
/*=== Constants ===*/
|
||||
|
|
2
third_party/lz4cli/lz4hc.h
vendored
2
third_party/lz4cli/lz4hc.h
vendored
|
@ -41,7 +41,7 @@ extern "C" {
|
|||
|
||||
/* --- Dependency --- */
|
||||
/* note : lz4hc requires lz4.h/lz4.c for compilation */
|
||||
#include "lz4.h" /* stddef, LZ4LIB_API, LZ4_DEPRECATED */
|
||||
#include "third_party/lz4cli/lz4.h" /* stddef, LZ4LIB_API, LZ4_DEPRECATED */
|
||||
|
||||
|
||||
/* --- Useful constants --- */
|
||||
|
|
2
third_party/lz4cli/xxhash.c
vendored
2
third_party/lz4cli/xxhash.c
vendored
|
@ -106,7 +106,7 @@ static void XXH_free (void* p) { free(p); }
|
|||
static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); }
|
||||
|
||||
#define XXH_STATIC_LINKING_ONLY
|
||||
#include "xxhash.h"
|
||||
#include "third_party/lz4cli/xxhash.h"
|
||||
|
||||
|
||||
/* *************************************
|
||||
|
|
2
third_party/lz4cli/xxhash.h
vendored
2
third_party/lz4cli/xxhash.h
vendored
|
@ -280,7 +280,7 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src
|
|||
#endif
|
||||
|
||||
# ifdef XXH_PRIVATE_API
|
||||
# include "xxhash.c" /* include xxhash function bodies as `static`, for inlining */
|
||||
# include "third_party/lz4cli/xxhash.c" /* include xxhash function bodies as `static`, for inlining */
|
||||
# endif
|
||||
|
||||
#endif /* XXH_STATIC_LINKING_ONLY */
|
||||
|
|
1
third_party/regex/regex.mk
vendored
1
third_party/regex/regex.mk
vendored
|
@ -8,6 +8,7 @@ THIRD_PARTY_REGEX = $(THIRD_PARTY_REGEX_A_DEPS) $(THIRD_PARTY_REGEX_A)
|
|||
THIRD_PARTY_REGEX_A = o/$(MODE)/third_party/regex/regex.a
|
||||
THIRD_PARTY_REGEX_A_FILES := $(wildcard third_party/regex/*)
|
||||
THIRD_PARTY_REGEX_A_HDRS = $(filter %.h,$(THIRD_PARTY_REGEX_A_FILES))
|
||||
THIRD_PARTY_REGEX_A_INCS = $(filter %.inc,$(THIRD_PARTY_REGEX_A_FILES))
|
||||
THIRD_PARTY_REGEX_A_SRCS = $(filter %.c,$(THIRD_PARTY_REGEX_A_FILES))
|
||||
|
||||
THIRD_PARTY_REGEX_A_OBJS = \
|
||||
|
|
|
@ -245,6 +245,10 @@ static long rombase;
|
|||
static long codesize;
|
||||
static int64_t opstart;
|
||||
static int64_t mapsstart;
|
||||
static uint64_t readaddr;
|
||||
static uint64_t readsize;
|
||||
static uint64_t writeaddr;
|
||||
static uint64_t writesize;
|
||||
static int64_t framesstart;
|
||||
static int64_t breakpointsstart;
|
||||
static uint64_t last_opcount;
|
||||
|
@ -424,6 +428,10 @@ static void OnSigBusted(void) {
|
|||
longjmp(onbusted, 1);
|
||||
}
|
||||
|
||||
static bool IsShadow(int64_t v) {
|
||||
return 0x7fff8000 <= v && v < 0x100080000000;
|
||||
}
|
||||
|
||||
static int VirtualBing(int64_t v) {
|
||||
int rc;
|
||||
uint8_t *p;
|
||||
|
@ -446,7 +454,7 @@ static int VirtualShadow(int64_t v) {
|
|||
int rc;
|
||||
char *p;
|
||||
jmp_buf busted;
|
||||
if (0x7fff8000 <= v && v < 0x100080000000) return -2;
|
||||
if (IsShadow(v)) return -2;
|
||||
onbusted = busted;
|
||||
if ((p = FindReal(m, (v >> 3) + 0x7fff8000))) {
|
||||
if (!setjmp(busted)) {
|
||||
|
@ -1171,11 +1179,12 @@ static void DrawSse(struct Panel *p) {
|
|||
}
|
||||
|
||||
static void ScrollMemoryView(struct Panel *p, struct MemoryView *v, int64_t a) {
|
||||
long i, n;
|
||||
long i, n, w;
|
||||
w = DUMPWIDTH * (1ull << v->zoom);
|
||||
n = p->bottom - p->top;
|
||||
i = a / (DUMPWIDTH * (1ull << v->zoom));
|
||||
i = a / w;
|
||||
if (!(v->start <= i && i < v->start + n)) {
|
||||
v->start = i;
|
||||
v->start = i - n / 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1194,8 +1203,8 @@ static void ZoomMemoryView(struct MemoryView *v, long y, long x, int dy) {
|
|||
|
||||
static void ScrollMemoryViews(void) {
|
||||
ScrollMemoryView(&pan.code, &codeview, GetIp());
|
||||
ScrollMemoryView(&pan.readdata, &readview, m->readaddr);
|
||||
ScrollMemoryView(&pan.writedata, &writeview, m->writeaddr);
|
||||
ScrollMemoryView(&pan.readdata, &readview, readaddr);
|
||||
ScrollMemoryView(&pan.writedata, &writeview, writeaddr);
|
||||
ScrollMemoryView(&pan.stack, &stackview, GetSp());
|
||||
}
|
||||
|
||||
|
@ -1299,9 +1308,9 @@ static void DrawMemoryUnzoomed(struct Panel *p, struct MemoryView *view,
|
|||
if (sc > 7) {
|
||||
x = 129; /* PURPLE: shadow corruption */
|
||||
} else if (sc == kAsanHeapFree) {
|
||||
x = 17; /* NAVYBLUE: heap freed */
|
||||
x = 20; /* BLUE: heap freed */
|
||||
} else if (sc == kAsanRelocated) {
|
||||
x = 18; /* DARKBLUE: heap relocated */
|
||||
x = 16; /* BLACK: heap relocated */
|
||||
} else if (sc == kAsanHeapUnderrun || sc == kAsanAllocaUnderrun) {
|
||||
x = 53; /* RED+PURPLETINGE: heap underrun */
|
||||
} else if (sc == kAsanHeapOverrun || sc == kAsanAllocaOverrun) {
|
||||
|
@ -1309,7 +1318,7 @@ static void DrawMemoryUnzoomed(struct Panel *p, struct MemoryView *view,
|
|||
} else if (sc < 0) {
|
||||
x = 52; /* RED: uncategorized invalid */
|
||||
} else if (sc > 0 && (k & 7) >= sc) {
|
||||
x = 54; /* REDPURP: invalid address (skew) */
|
||||
x = 88; /* BRIGHTRED: invalid address (skew) */
|
||||
} else if (!sc || (sc > 0 && (k & 7) < sc)) {
|
||||
x = 22; /* GREEN: valid address */
|
||||
} else {
|
||||
|
@ -1529,6 +1538,14 @@ static void PreventBufferbloat(void) {
|
|||
|
||||
static void Redraw(void) {
|
||||
int i, j;
|
||||
if (!IsShadow(m->readaddr) && !IsShadow(m->readaddr + m->readsize)) {
|
||||
readaddr = m->readaddr;
|
||||
readsize = m->readsize;
|
||||
}
|
||||
if (!IsShadow(m->writeaddr) && !IsShadow(m->writeaddr + m->writesize)) {
|
||||
writeaddr = m->writeaddr;
|
||||
writesize = m->writesize;
|
||||
}
|
||||
ScrollOp(&pan.disassembly, GetDisIndex());
|
||||
if (last_opcount) {
|
||||
ips = unsignedsubtract(opcount, last_opcount) / (nowl() - last_seconds);
|
||||
|
@ -1555,9 +1572,8 @@ static void Redraw(void) {
|
|||
DrawFrames(&pan.frames);
|
||||
DrawBreakpoints(&pan.breakpoints);
|
||||
DrawMemory(&pan.code, &codeview, GetIp(), GetIp() + m->xedd->length);
|
||||
DrawMemory(&pan.readdata, &readview, m->readaddr, m->readaddr + m->readsize);
|
||||
DrawMemory(&pan.writedata, &writeview, m->writeaddr,
|
||||
m->writeaddr + m->writesize);
|
||||
DrawMemory(&pan.readdata, &readview, readaddr, readaddr + readsize);
|
||||
DrawMemory(&pan.writedata, &writeview, writeaddr, writeaddr + writesize);
|
||||
DrawMemory(&pan.stack, &stackview, GetSp(), GetSp() + GetPointerWidth());
|
||||
DrawStatus(&pan.status);
|
||||
PreventBufferbloat();
|
||||
|
|
|
@ -1011,6 +1011,10 @@ static int OpMkdir(struct Machine *m, int64_t path, int mode) {
|
|||
return mkdir(LoadStr(m, path), mode);
|
||||
}
|
||||
|
||||
static int OpMkdirat(struct Machine *m, int dirfd, int64_t path, int mode) {
|
||||
return mkdirat(XlatAfd(m, dirfd), LoadStr(m, path), mode);
|
||||
}
|
||||
|
||||
static int OpMknod(struct Machine *m, int64_t path, uint32_t mode,
|
||||
uint64_t dev) {
|
||||
return mknod(LoadStr(m, path), mode, dev);
|
||||
|
@ -1024,10 +1028,20 @@ static int OpUnlink(struct Machine *m, int64_t path) {
|
|||
return unlink(LoadStr(m, path));
|
||||
}
|
||||
|
||||
static int OpUnlinkat(struct Machine *m, int dirfd, int64_t path, int flags) {
|
||||
return unlinkat(XlatAfd(m, dirfd), LoadStr(m, path), XlatAtf(flags));
|
||||
}
|
||||
|
||||
static int OpRename(struct Machine *m, int64_t src, int64_t dst) {
|
||||
return rename(LoadStr(m, src), LoadStr(m, dst));
|
||||
}
|
||||
|
||||
static int OpRenameat(struct Machine *m, int srcdirfd, int64_t src,
|
||||
int dstdirfd, int64_t dst) {
|
||||
return renameat(XlatAfd(m, srcdirfd), LoadStr(m, src), XlatAfd(m, dstdirfd),
|
||||
LoadStr(m, dst));
|
||||
}
|
||||
|
||||
static int OpTruncate(struct Machine *m, int64_t path, uint64_t length) {
|
||||
return truncate(LoadStr(m, path), length);
|
||||
}
|
||||
|
@ -1384,12 +1398,12 @@ void OpSyscall(struct Machine *m, uint32_t rde) {
|
|||
SYSCALL(0x0DD, OpFadvise(m, di, si, dx, r0));
|
||||
SYSCALL(0x0E4, OpClockGettime(m, di, si));
|
||||
SYSCALL(0x101, OpOpenat(m, di, si, dx, r0));
|
||||
SYSCALL(0x102, mkdirat(XlatAfd(m, di), P(si), dx));
|
||||
SYSCALL(0x102, OpMkdirat(m, di, si, dx));
|
||||
SYSCALL(0x104, fchownat(XlatAfd(m, di), P(si), dx, r0, XlatAtf(r8)));
|
||||
SYSCALL(0x105, futimesat(XlatAfd(m, di), P(si), P(dx)));
|
||||
SYSCALL(0x106, OpFstatat(m, di, si, dx, r0));
|
||||
SYSCALL(0x107, unlinkat(XlatAfd(m, di), P(si), XlatAtf(dx)));
|
||||
SYSCALL(0x108, renameat(XlatAfd(m, di), P(si), XlatAfd(m, dx), P(r0)));
|
||||
SYSCALL(0x107, OpUnlinkat(m, di, si, dx));
|
||||
SYSCALL(0x108, OpRenameat(m, di, si, dx, r0));
|
||||
SYSCALL(0x10D, OpFaccessat(m, di, si, dx, r0));
|
||||
SYSCALL(0x113, splice(di, P(si), dx, P(r0), r8, XlatAtf(r9)));
|
||||
SYSCALL(0x115, sync_file_range(di, si, dx, XlatAtf(r0)));
|
||||
|
|
|
@ -259,6 +259,8 @@
|
|||
"__builtin_lrintf"
|
||||
"__builtin_lrintl"
|
||||
"__builtin_memcpy"
|
||||
"__builtin_mempcpy"
|
||||
"__builtin_memmove"
|
||||
"__builtin_memcmp"
|
||||
"__builtin_memset"
|
||||
"__builtin_strlen"))
|
||||
|
|
Loading…
Reference in a new issue