mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Make minor improvements
This commit is contained in:
parent
04caf6f9ad
commit
95b142e4e5
95 changed files with 3818 additions and 2760 deletions
|
@ -74,6 +74,7 @@ static struct SamplingSolution *NewSamplingSolution(long n, long s) {
|
|||
ss->indices = xcalloc(n * s, sizeof(short));
|
||||
return ss;
|
||||
}
|
||||
|
||||
static bool IsNormalized(int n, double A[n]) {
|
||||
int i;
|
||||
double x;
|
||||
|
|
|
@ -144,6 +144,9 @@
|
|||
#include "third_party/gdtoa/gdtoa.h"
|
||||
#include "third_party/musl/passwd.h"
|
||||
|
||||
#define likely(expr) __builtin_expect(!!(expr), 1)
|
||||
#define unlikely(expr) __builtin_expect(!!(expr), 0)
|
||||
|
||||
#undef CEOF
|
||||
#undef rflag
|
||||
|
||||
|
|
|
@ -263,11 +263,12 @@ unsigned long hamming(unsigned long, unsigned long) pureconst;
|
|||
* @return LOCALVAR[0]
|
||||
* @see xchg()
|
||||
*/
|
||||
#define lockxchg(MEMORY, LOCALVAR) \
|
||||
({ \
|
||||
static_assert(typescompatible(typeof(*(MEMORY)), typeof(*(LOCALVAR)))); \
|
||||
asm("xchg\t%0,%1" : "+%m"(*(MEMORY)), "+r"(*(LOCALVAR))); \
|
||||
*(LOCALVAR); \
|
||||
#define lockxchg(MEMORY, LOCALVAR) \
|
||||
({ \
|
||||
_Static_assert( \
|
||||
__builtin_types_compatible_p(typeof(*(MEMORY)), typeof(*(LOCALVAR)))); \
|
||||
asm("xchg\t%0,%1" : "+%m"(*(MEMORY)), "+r"(*(LOCALVAR))); \
|
||||
*(LOCALVAR); \
|
||||
})
|
||||
|
||||
/**
|
||||
|
@ -376,7 +377,7 @@ unsigned long hamming(unsigned long, unsigned long) pureconst;
|
|||
#define __BitOp(OP, BIT, MEM) \
|
||||
({ \
|
||||
bool OldBit; \
|
||||
if (isconstant(BIT)) { \
|
||||
if (__builtin_constant_p(BIT)) { \
|
||||
asm(CFLAG_ASM(OP "%z1\t%2,%1") \
|
||||
: CFLAG_CONSTRAINT(OldBit), \
|
||||
"+m"((MEM)[(BIT) / (sizeof((MEM)[0]) * CHAR_BIT)]) \
|
||||
|
|
|
@ -8,39 +8,9 @@ uint32_t bswap_32(uint32_t) pureconst;
|
|||
uint32_t bswap_64(uint32_t) pureconst;
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
|
||||
#define bswap_16(U16) \
|
||||
(isconstant(U16) ? ((((U16)&0xff00) >> 010) | (((U16)&0x00ff) << 010)) : ({ \
|
||||
uint16_t Swapped16, Werd16 = (U16); \
|
||||
asm("xchg\t%b0,%h0" : "=Q"(Swapped16) : "0"(Werd16)); \
|
||||
Swapped16; \
|
||||
}))
|
||||
|
||||
#define bswap_32(U32) \
|
||||
(isconstant(U32) \
|
||||
? ((((U32)&0xff000000) >> 030) | (((U32)&0x000000ff) << 030) | \
|
||||
(((U32)&0x00ff0000) >> 010) | (((U32)&0x0000ff00) << 010)) \
|
||||
: ({ \
|
||||
uint32_t Swapped32, Werd32 = (U32); \
|
||||
asm("bswap\t%0" : "=r"(Swapped32) : "0"(Werd32)); \
|
||||
Swapped32; \
|
||||
}))
|
||||
|
||||
#define bswap_64(U64) \
|
||||
(isconstant(U64) ? ((((U64)&0xff00000000000000ul) >> 070) | \
|
||||
(((U64)&0x00000000000000fful) << 070) | \
|
||||
(((U64)&0x00ff000000000000ul) >> 050) | \
|
||||
(((U64)&0x000000000000ff00ul) << 050) | \
|
||||
(((U64)&0x0000ff0000000000ul) >> 030) | \
|
||||
(((U64)&0x0000000000ff0000ul) << 030) | \
|
||||
(((U64)&0x000000ff00000000ul) >> 010) | \
|
||||
(((U64)&0x00000000ff000000ul) << 010)) \
|
||||
: ({ \
|
||||
uint64_t Swapped64, Werd64 = (U64); \
|
||||
asm("bswap\t%0" : "=r"(Swapped64) : "0"(Werd64)); \
|
||||
Swapped64; \
|
||||
}))
|
||||
|
||||
#define bswap_16(x) __builtin_bswap16(x)
|
||||
#define bswap_32(x) __builtin_bswap32(x)
|
||||
#define bswap_64(x) __builtin_bswap64(x)
|
||||
#endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) */
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "libc/bits/popcnt.h"
|
||||
|
||||
uint64_t(popcnt)(uint64_t x) {
|
||||
uint32_t r;
|
||||
x = x - ((x >> 1) & 0x5555555555555555);
|
||||
x = ((x >> 2) & 0x3333333333333333) + (x & 0x3333333333333333);
|
||||
x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f;
|
||||
|
|
|
@ -8,7 +8,7 @@ unsigned long popcnt(unsigned long) pureconst;
|
|||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
#define popcnt(X) \
|
||||
(isconstant(X) ? __builtin_popcountll(X) : ({ \
|
||||
(__builtin_constant_p(X) ? __builtin_popcountll(X) : ({ \
|
||||
unsigned long Res, Pop = (X); \
|
||||
if (X86_HAVE(POPCNT)) { \
|
||||
asm("popcnt\t%1,%0" : "=r"(Res) : "r"(Pop) : "cc"); \
|
||||
|
|
|
@ -10,42 +10,44 @@
|
|||
#if !defined(__GNUC__) || defined(__STRICT_ANSI__)
|
||||
#define pushpop(x) (x)
|
||||
#else
|
||||
#define pushpop(x) \
|
||||
({ \
|
||||
typeof(x) Popped; \
|
||||
if (isconstant(x) && (TYPE_SIGNED(typeof(x)) ? (intptr_t)(x) + 128 < 256 \
|
||||
: (intptr_t)(x) < 128)) { \
|
||||
if (x) { \
|
||||
asm("push\t%1\n\t" \
|
||||
"pop\t%q0" \
|
||||
: "=r"(Popped) \
|
||||
: "ir"(x)); \
|
||||
} else { \
|
||||
asm("xor\t%k0,%k0" : "=r"(Popped)); \
|
||||
} \
|
||||
} else { \
|
||||
asm("" : "=r"(Popped) : "0"(x)); \
|
||||
} \
|
||||
Popped; \
|
||||
#define pushpop(x) \
|
||||
({ \
|
||||
typeof(x) Popped; \
|
||||
if (__builtin_constant_p(x) && \
|
||||
(TYPE_SIGNED(typeof(x)) ? (intptr_t)(x) + 128 < 256 \
|
||||
: (intptr_t)(x) < 128)) { \
|
||||
if (x) { \
|
||||
asm("push\t%1\n\t" \
|
||||
"pop\t%q0" \
|
||||
: "=r"(Popped) \
|
||||
: "ir"(x)); \
|
||||
} else { \
|
||||
asm("xor\t%k0,%k0" : "=r"(Popped)); \
|
||||
} \
|
||||
} else { \
|
||||
asm("" : "=r"(Popped) : "0"(x)); \
|
||||
} \
|
||||
Popped; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#if !defined(__GNUC__) || defined(__STRICT_ANSI__)
|
||||
#define pushmov(d, x) (*(d) = (x))
|
||||
#else
|
||||
#define pushmov(d, x) \
|
||||
({ \
|
||||
typeof(*(d)) Popped = (x); \
|
||||
if (isconstant(x) && (TYPE_SIGNED(typeof(x)) ? (intptr_t)(x) + 128 < 256 \
|
||||
: (intptr_t)(x) < 128)) { \
|
||||
asm("pushq\t%1\n\t" \
|
||||
"popq\t%0" \
|
||||
: "=m"(*(d)) \
|
||||
: "ir"(Popped)); \
|
||||
} else { \
|
||||
*(d) = Popped; \
|
||||
} \
|
||||
Popped; \
|
||||
#define pushmov(d, x) \
|
||||
({ \
|
||||
typeof(*(d)) Popped = (x); \
|
||||
if (__builtin_constant_p(x) && \
|
||||
(TYPE_SIGNED(typeof(x)) ? (intptr_t)(x) + 128 < 256 \
|
||||
: (intptr_t)(x) < 128)) { \
|
||||
asm("pushq\t%1\n\t" \
|
||||
"popq\t%0" \
|
||||
: "=m"(*(d)) \
|
||||
: "ir"(Popped)); \
|
||||
} else { \
|
||||
*(d) = Popped; \
|
||||
} \
|
||||
Popped; \
|
||||
})
|
||||
#endif
|
||||
|
||||
|
|
|
@ -227,9 +227,9 @@ uint32_t gettid(void) nosideeffect;
|
|||
uint32_t getuid(void) nosideeffect;
|
||||
uint32_t umask(int32_t);
|
||||
|
||||
#define getcwd(BUF, SIZE) \
|
||||
(isconstant(BUF) && (&(BUF)[0] == NULL) ? get_current_dir_name() \
|
||||
: getcwd(BUF, SIZE))
|
||||
#define getcwd(BUF, SIZE) \
|
||||
(__builtin_constant_p(BUF) && (&(BUF)[0] == NULL) ? get_current_dir_name() \
|
||||
: getcwd(BUF, SIZE))
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § system calls » formatting ─╬─│┼
|
||||
|
@ -249,7 +249,7 @@ void _init_wincrash(void);
|
|||
#define __SIGACTION(FN, SIG, ...) \
|
||||
({ \
|
||||
if (SupportsWindows()) { \
|
||||
if (isconstant(SIG)) { \
|
||||
if (__builtin_constant_p(SIG)) { \
|
||||
switch (SIG) { \
|
||||
case SIGINT: \
|
||||
case SIGQUIT: \
|
||||
|
|
|
@ -63,7 +63,7 @@ int clock_gettime(int clockid, struct timespec *out_ts) {
|
|||
return clock_gettime$sysv(clockid, out_ts);
|
||||
} else {
|
||||
int rc;
|
||||
static_assert(sizeof(struct timeval) == sizeof(struct timespec));
|
||||
_Static_assert(sizeof(struct timeval) == sizeof(struct timespec));
|
||||
if (out_ts) {
|
||||
out_ts->tv_sec = 0;
|
||||
out_ts->tv_nsec = 0;
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
#define kBufSize 1024
|
||||
#define kProcStatus "/proc/self/status"
|
||||
alignas(16) static const char kGdbPid[] = "TracerPid:\t";
|
||||
_Alignas(16) static const char kGdbPid[] = "TracerPid:\t";
|
||||
|
||||
/**
|
||||
* Determines if gdb, strace, windbg, etc. is controlling process.
|
||||
|
|
|
@ -121,11 +121,11 @@ static void sigaction$native2cosmo(union metasigaction *sa) {
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) {
|
||||
static_assert(sizeof(struct sigaction) > sizeof(struct sigaction$linux) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction$xnu_in) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction$xnu_out) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction$freebsd) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction$openbsd));
|
||||
_Static_assert(sizeof(struct sigaction) > sizeof(struct sigaction$linux) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction$xnu_in) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction$xnu_out) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction$freebsd) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction$openbsd));
|
||||
int rc, rva, oldrva;
|
||||
struct sigaction *ap, copy;
|
||||
if (!(0 < sig && sig < NSIG) || sig == SIGKILL || sig == SIGSTOP) {
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
|
||||
/**
|
||||
* Deletes file, the Cosmopolitan way.
|
||||
* Deletes file.
|
||||
*
|
||||
* The caller's variable is made NULL. Note that we define unlink(NULL)
|
||||
* as a no-op.
|
||||
|
|
|
@ -19,7 +19,6 @@ long labs(long) libcesque pureconst;
|
|||
long long llabs(long long) libcesque pureconst;
|
||||
char *ltpcpy(char *, long) paramsnonnull() libcesque nocallback;
|
||||
int llog10(unsigned long) libcesque pureconst;
|
||||
int unsleb128(const void *, size_t, int64_t *);
|
||||
int atoi(const char *) paramsnonnull() libcesque;
|
||||
long atol(const char *) paramsnonnull() libcesque;
|
||||
long long atoll(const char *) paramsnonnull() libcesque;
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
|
||||
#define ISDELIM(c) (c == '/' || c == '\\' || c == '.')
|
||||
|
||||
/**
|
||||
* Returns directory portion of path.
|
||||
* @param s is mutated
|
||||
*/
|
||||
char *dirname(char *s) {
|
||||
size_t i, n;
|
||||
if (!(n = strlen(s))) return s;
|
||||
|
|
11
libc/fmt/leb128.h
Normal file
11
libc/fmt/leb128.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_FMT_LEB128_H_
|
||||
#define COSMOPOLITAN_LIBC_FMT_LEB128_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
int sleb128(const void *, size_t, int128_t);
|
||||
int unsleb128(const void *, size_t, int128_t *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_FMT_LEB128_H_ */
|
|
@ -46,7 +46,7 @@
|
|||
#define ___PFLINK(FMT, FN, C) 1
|
||||
#else
|
||||
#define ___PFLINK(FMT, FN, C) \
|
||||
!isconstant(FMT) || ((FMT) && __builtin_##FN(FMT, C) != NULL)
|
||||
!__builtin_constant_p(FMT) || ((FMT) && __builtin_##FN(FMT, C) != NULL)
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ < 6
|
||||
|
|
39
libc/fmt/sleb128.c
Normal file
39
libc/fmt/sleb128.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/leb128.h"
|
||||
|
||||
/**
|
||||
* Encodes sleb-128 signed integer.
|
||||
*/
|
||||
int sleb128(const void *buf, size_t size, int128_t x) {
|
||||
int c;
|
||||
unsigned i;
|
||||
for (i = 0; i < size; ++i) {
|
||||
c = x & 0x7f;
|
||||
x >>= 7;
|
||||
if ((x == 0 && !(c & 0x40)) || (x == -1 && (c & 0x40))) {
|
||||
break;
|
||||
} else {
|
||||
c |= 0x80;
|
||||
}
|
||||
((char *)buf)[i] = c;
|
||||
}
|
||||
return i;
|
||||
}
|
|
@ -24,7 +24,7 @@
|
|||
* @see strerror_r()
|
||||
*/
|
||||
char *strerror(int err) {
|
||||
alignas(1) static char buf[512];
|
||||
_Alignas(1) static char buf[512];
|
||||
strerror_r(err, buf, sizeof(buf));
|
||||
return buf;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/leb128.h"
|
||||
|
||||
/**
|
||||
* Decodes a GNU-style varint from a buffer.
|
||||
|
@ -25,9 +25,9 @@
|
|||
* The GNU Assembler is able to encode numbers this way, since it's used
|
||||
* by the DWARF debug format.
|
||||
*/
|
||||
int unsleb128(const void *buf, size_t size, int64_t *out) {
|
||||
int unsleb128(const void *buf, size_t size, int128_t *out) {
|
||||
int b;
|
||||
int64_t r, w;
|
||||
int128_t r, w;
|
||||
unsigned char c;
|
||||
const unsigned char *p, *pe;
|
||||
pe = (p = buf) + size;
|
||||
|
|
|
@ -806,36 +806,6 @@ typedef uint64_t uintmax_t;
|
|||
do { \
|
||||
} while (0)
|
||||
|
||||
#ifndef likely
|
||||
#define likely(expr) __builtin_expect(!!(expr), 1)
|
||||
#endif
|
||||
|
||||
#ifndef unlikely
|
||||
#define unlikely(expr) __builtin_expect(!!(expr), 0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Evaluates ternary expression without type promotion.
|
||||
*/
|
||||
#ifndef chooseexpr
|
||||
#define chooseexpr(pred, a, b) __builtin_choose_expr(pred, a, b)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns true if expression can be evaluated at compile-time.
|
||||
*/
|
||||
#ifndef isconstant
|
||||
#define isconstant(expr) __builtin_constant_p(expr)
|
||||
#endif
|
||||
|
||||
#ifndef static_assert
|
||||
#define static_assert(expr) _Static_assert(expr, #expr)
|
||||
#endif
|
||||
|
||||
#ifndef typescompatible
|
||||
#define typescompatible(a, b) __builtin_types_compatible_p(a, b)
|
||||
#endif
|
||||
|
||||
#ifndef __STRICT_ANSI__
|
||||
#define testonly noinline _Section(".test")
|
||||
#define textstartup _Section(".text.startup") noinstrument
|
||||
|
@ -873,10 +843,6 @@ typedef uint64_t uintmax_t;
|
|||
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||
#endif
|
||||
|
||||
#ifndef alignas
|
||||
#define alignas(x) _Alignas(x)
|
||||
#endif
|
||||
|
||||
#ifndef _Section
|
||||
#ifndef __STRICT_ANSI__
|
||||
#define _Section(s) __attribute__((__section__(s)))
|
||||
|
@ -1029,15 +995,15 @@ typedef uint64_t uintmax_t;
|
|||
* Pulls another module, by symbol, into linkage.
|
||||
* @note nop is discarded by ape/ape.lds
|
||||
*/
|
||||
#define YOINK(SYMBOL) \
|
||||
do { \
|
||||
_Static_assert(!typescompatible(typeof(SYMBOL), char[]), \
|
||||
"Please YOINK(symbol), not YOINK(\"symbol\")"); \
|
||||
asm(".pushsection .yoink\n\t" \
|
||||
"nop\t%a0\n\t" \
|
||||
".popsection" \
|
||||
: /* no outputs */ \
|
||||
: "X"(SYMBOL)); \
|
||||
#define YOINK(SYMBOL) \
|
||||
do { \
|
||||
_Static_assert(!__builtin_types_compatible_p(typeof(SYMBOL), char[]), \
|
||||
"Please YOINK(symbol), not YOINK(\"symbol\")"); \
|
||||
asm(".pushsection .yoink\n\t" \
|
||||
"nop\t%a0\n\t" \
|
||||
".popsection" \
|
||||
: /* no outputs */ \
|
||||
: "X"(SYMBOL)); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,11 +10,12 @@ void mpsadbw(uint16_t[8], const uint8_t[16], const uint8_t[16], uint8_t);
|
|||
__intrin_xmm_t __mpsadbws(__intrin_xmm_t, __intrin_xmm_t);
|
||||
#define mpsadbw(C, B, A, I) \
|
||||
do { \
|
||||
if (likely(!IsModeDbg() && X86_NEED(SSE) && X86_HAVE(SSE4_1))) { \
|
||||
if (__builtin_expect(!IsModeDbg() && X86_NEED(SSE) && X86_HAVE(SSE4_1), \
|
||||
1)) { \
|
||||
__intrin_xmm_t *Xmm0 = (void *)(C); \
|
||||
const __intrin_xmm_t *Xmm1 = (const __intrin_xmm_t *)(B); \
|
||||
const __intrin_xmm_t *Xmm2 = (const __intrin_xmm_t *)(A); \
|
||||
if (isconstant(I)) { \
|
||||
if (__builtin_constant_p(I)) { \
|
||||
if (!X86_NEED(AVX)) { \
|
||||
asm("mpsadbw\t%2,%1,%0" \
|
||||
: "=x"(*Xmm0) \
|
||||
|
|
|
@ -9,35 +9,36 @@ void palignr(void *, const void *, const void *, unsigned long);
|
|||
|
||||
#if !defined(__STRICT_ANSI__) && !defined(__chibicc__)
|
||||
__intrin_xmm_t __palignrs(__intrin_xmm_t, __intrin_xmm_t);
|
||||
#define palignr(C, B, A, I) \
|
||||
do { \
|
||||
if (likely(!IsModeDbg() && X86_NEED(SSE) && X86_HAVE(SSSE3))) { \
|
||||
__intrin_xmm_t *Xmm0 = (void *)(C); \
|
||||
const __intrin_xmm_t *Xmm1 = (const __intrin_xmm_t *)(B); \
|
||||
const __intrin_xmm_t *Xmm2 = (const __intrin_xmm_t *)(A); \
|
||||
if (isconstant(I)) { \
|
||||
if (!X86_NEED(AVX)) { \
|
||||
asm("palignr\t%2,%1,%0" \
|
||||
: "=x"(*Xmm0) \
|
||||
: "x"(*Xmm2), "i"(I), "0"(*Xmm1)); \
|
||||
} else { \
|
||||
asm("vpalignr\t%3,%2,%1,%0" \
|
||||
: "=x"(*Xmm0) \
|
||||
: "x"(*Xmm1), "x"(*Xmm2), "i"(I)); \
|
||||
} \
|
||||
} else { \
|
||||
unsigned long Vimm = (I); \
|
||||
typeof(__palignrs) *Fn; \
|
||||
if (likely(Vimm < 32)) { \
|
||||
Fn = (typeof(__palignrs) *)((uintptr_t)&__palignrs + Vimm * 8); \
|
||||
*Xmm0 = Fn(*Xmm1, *Xmm2); \
|
||||
} else { \
|
||||
memset(Xmm0, 0, 16); \
|
||||
} \
|
||||
} \
|
||||
} else { \
|
||||
palignr(C, B, A, I); \
|
||||
} \
|
||||
#define palignr(C, B, A, I) \
|
||||
do { \
|
||||
if (__builtin_expect(!IsModeDbg() && X86_NEED(SSE) && X86_HAVE(SSSE3), \
|
||||
1)) { \
|
||||
__intrin_xmm_t *Xmm0 = (void *)(C); \
|
||||
const __intrin_xmm_t *Xmm1 = (const __intrin_xmm_t *)(B); \
|
||||
const __intrin_xmm_t *Xmm2 = (const __intrin_xmm_t *)(A); \
|
||||
if (__builtin_constant_p(I)) { \
|
||||
if (!X86_NEED(AVX)) { \
|
||||
asm("palignr\t%2,%1,%0" \
|
||||
: "=x"(*Xmm0) \
|
||||
: "x"(*Xmm2), "i"(I), "0"(*Xmm1)); \
|
||||
} else { \
|
||||
asm("vpalignr\t%3,%2,%1,%0" \
|
||||
: "=x"(*Xmm0) \
|
||||
: "x"(*Xmm1), "x"(*Xmm2), "i"(I)); \
|
||||
} \
|
||||
} else { \
|
||||
unsigned long Vimm = (I); \
|
||||
typeof(__palignrs) *Fn; \
|
||||
if (__builtin_expect(Vimm < 32, 1)) { \
|
||||
Fn = (typeof(__palignrs) *)((uintptr_t)&__palignrs + Vimm * 8); \
|
||||
*Xmm0 = Fn(*Xmm1, *Xmm2); \
|
||||
} else { \
|
||||
memset(Xmm0, 0, 16); \
|
||||
} \
|
||||
} \
|
||||
} else { \
|
||||
palignr(C, B, A, I); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
|
|
@ -8,27 +8,28 @@ void pslldq(uint8_t[16], const uint8_t[16], unsigned long);
|
|||
|
||||
#ifndef __STRICT_ANSI__
|
||||
__intrin_xmm_t __pslldqs(__intrin_xmm_t);
|
||||
#define pslldq(B, A, I) \
|
||||
do { \
|
||||
if (likely(!IsModeDbg() && X86_NEED(SSE) && X86_HAVE(SSE2))) { \
|
||||
__intrin_xmm_t *Xmm0 = (void *)(B); \
|
||||
const __intrin_xmm_t *Xmm1 = (const __intrin_xmm_t *)(A); \
|
||||
if (isconstant(I)) { \
|
||||
if (!X86_NEED(AVX)) { \
|
||||
asm("pslldq\t%1,%0" : "=x"(*Xmm0) : "i"(I), "0"(*Xmm1)); \
|
||||
} else { \
|
||||
asm("vpslldq\t%2,%1,%0" : "=x"(*Xmm0) : "x"(*Xmm1), "i"(I)); \
|
||||
} \
|
||||
} else { \
|
||||
unsigned long Vimm = (I); \
|
||||
typeof(__pslldqs) *Fn; \
|
||||
if (Vimm > 16) Vimm = 16; \
|
||||
Fn = (typeof(__pslldqs) *)((uintptr_t)&__pslldqs + Vimm * 8); \
|
||||
*Xmm0 = Fn(*Xmm1); \
|
||||
} \
|
||||
} else { \
|
||||
pslldq(B, A, I); \
|
||||
} \
|
||||
#define pslldq(B, A, I) \
|
||||
do { \
|
||||
if (__builtin_expect(!IsModeDbg() && X86_NEED(SSE) && X86_HAVE(SSE2), \
|
||||
1)) { \
|
||||
__intrin_xmm_t *Xmm0 = (void *)(B); \
|
||||
const __intrin_xmm_t *Xmm1 = (const __intrin_xmm_t *)(A); \
|
||||
if (__builtin_constant_p(I)) { \
|
||||
if (!X86_NEED(AVX)) { \
|
||||
asm("pslldq\t%1,%0" : "=x"(*Xmm0) : "i"(I), "0"(*Xmm1)); \
|
||||
} else { \
|
||||
asm("vpslldq\t%2,%1,%0" : "=x"(*Xmm0) : "x"(*Xmm1), "i"(I)); \
|
||||
} \
|
||||
} else { \
|
||||
unsigned long Vimm = (I); \
|
||||
typeof(__pslldqs) *Fn; \
|
||||
if (Vimm > 16) Vimm = 16; \
|
||||
Fn = (typeof(__pslldqs) *)((uintptr_t)&__pslldqs + Vimm * 8); \
|
||||
*Xmm0 = Fn(*Xmm1); \
|
||||
} \
|
||||
} else { \
|
||||
pslldq(B, A, I); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
|
|
@ -8,27 +8,28 @@ void psrldq(uint8_t[16], const uint8_t[16], unsigned long);
|
|||
|
||||
#ifndef __STRICT_ANSI__
|
||||
__intrin_xmm_t __psrldqs(__intrin_xmm_t);
|
||||
#define psrldq(B, A, I) \
|
||||
do { \
|
||||
if (likely(!IsModeDbg() && X86_NEED(SSE) && X86_HAVE(SSE2))) { \
|
||||
__intrin_xmm_t *Xmm0 = (void *)(B); \
|
||||
const __intrin_xmm_t *Xmm1 = (const __intrin_xmm_t *)(A); \
|
||||
if (isconstant(I)) { \
|
||||
if (!X86_NEED(AVX)) { \
|
||||
asm("psrldq\t%1,%0" : "=x"(*Xmm0) : "i"(I), "0"(*Xmm1)); \
|
||||
} else { \
|
||||
asm("vpsrldq\t%2,%1,%0" : "=x"(*Xmm0) : "x"(*Xmm1), "i"(I)); \
|
||||
} \
|
||||
} else { \
|
||||
unsigned long Vimm = (I); \
|
||||
typeof(__psrldqs) *Fn; \
|
||||
if (Vimm > 16) Vimm = 16; \
|
||||
Fn = (typeof(__psrldqs) *)((uintptr_t)&__psrldqs + Vimm * 8); \
|
||||
*Xmm0 = Fn(*Xmm1); \
|
||||
} \
|
||||
} else { \
|
||||
psrldq(B, A, I); \
|
||||
} \
|
||||
#define psrldq(B, A, I) \
|
||||
do { \
|
||||
if (__builtin_expect(!IsModeDbg() && X86_NEED(SSE) && X86_HAVE(SSE2), \
|
||||
1)) { \
|
||||
__intrin_xmm_t *Xmm0 = (void *)(B); \
|
||||
const __intrin_xmm_t *Xmm1 = (const __intrin_xmm_t *)(A); \
|
||||
if (__builtin_constant_p(I)) { \
|
||||
if (!X86_NEED(AVX)) { \
|
||||
asm("psrldq\t%1,%0" : "=x"(*Xmm0) : "i"(I), "0"(*Xmm1)); \
|
||||
} else { \
|
||||
asm("vpsrldq\t%2,%1,%0" : "=x"(*Xmm0) : "x"(*Xmm1), "i"(I)); \
|
||||
} \
|
||||
} else { \
|
||||
unsigned long Vimm = (I); \
|
||||
typeof(__psrldqs) *Fn; \
|
||||
if (Vimm > 16) Vimm = 16; \
|
||||
Fn = (typeof(__psrldqs) *)((uintptr_t)&__psrldqs + Vimm * 8); \
|
||||
*Xmm0 = Fn(*Xmm1); \
|
||||
} \
|
||||
} else { \
|
||||
psrldq(B, A, I); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
|
|
@ -56,8 +56,9 @@ bool isrunningundermake(void);
|
|||
|
||||
extern unsigned g_loglevel; /* log level for runtime check */
|
||||
|
||||
#define LOGGABLE(LEVEL) \
|
||||
((!isconstant(LEVEL) || (LEVEL) <= LOGGABLELEVEL) && (LEVEL) <= g_loglevel)
|
||||
#define LOGGABLE(LEVEL) \
|
||||
((!__builtin_constant_p(LEVEL) || (LEVEL) <= LOGGABLELEVEL) && \
|
||||
(LEVEL) <= g_loglevel)
|
||||
|
||||
#define LOGF(FMT, ...) \
|
||||
do { \
|
||||
|
|
|
@ -1,5 +1,24 @@
|
|||
/* clang-format off */
|
||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/relocations.h"
|
||||
/* clang-format off */
|
||||
|
||||
#if __MNO_VZEROUPPER__ + 0
|
||||
#define vzeroupper
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define alignas(x) _Alignas(x)
|
||||
#define static_assert(x) _Static_assert(x, #x)
|
||||
|
||||
#define ROUNDUP(X, K) (((X) + (K)-1) & -(K))
|
||||
#define ROUNDDOWN(X, K) ((X) & -(K))
|
||||
#define ABS(X) ((X) >= 0 ? (X) : -(X))
|
||||
|
@ -20,7 +23,7 @@
|
|||
#define MAX(X, Y) ((Y) < (X) ? (X) : (Y))
|
||||
#define PASTE(A, B) __PASTE(A, B)
|
||||
#define STRINGIFY(A) __STRINGIFY(A)
|
||||
#define EQUIVALENT(X, Y) (isconstant((X) == (Y)) && ((X) == (Y)))
|
||||
#define EQUIVALENT(X, Y) (__builtin_constant_p((X) == (Y)) && ((X) == (Y)))
|
||||
#define TYPE_BIT(type) (sizeof(type) * CHAR_BIT)
|
||||
#define TYPE_SIGNED(type) (((type)-1) < 0)
|
||||
#define TYPE_INTEGRAL(type) (((type)0.5) != 0.5)
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
|
||||
/ Shorthand notation for widely-acknowledged sections.
|
||||
.macro .rodata
|
||||
.section .rodata,"a",@progbits
|
||||
|
|
|
@ -5,7 +5,7 @@ COSMOPOLITAN_C_START_
|
|||
|
||||
void crc32init(uint32_t[hasatleast 256], uint32_t);
|
||||
uint32_t crc32_z(uint32_t, const void *, size_t);
|
||||
extern uint32_t (*const crc32c)(uint32_t, const void *, size_t) paramsnonnull();
|
||||
extern uint32_t (*const crc32c)(uint32_t, const void *, size_t);
|
||||
uint32_t crc32c$pure(uint32_t, const void *, size_t) strlenesque hidden;
|
||||
uint32_t crc32c$sse42(uint32_t, const void *, size_t) strlenesque hidden;
|
||||
uint32_t crc32$pclmul(uint32_t, const void *, size_t) hidden;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
* Hashes data with hardware acceleration at 10GBps.
|
||||
* @note needs Nehalem+ c. 2008 or Bulldozer+ c. 2011
|
||||
*/
|
||||
uint32_t crc32c$sse42(uint32_t init, const void *data, size_t n) {
|
||||
optimizespeed uint32_t crc32c$sse42(uint32_t init, const void *data, size_t n) {
|
||||
const unsigned char *p = (const unsigned char *)data;
|
||||
const unsigned char *pe = (const unsigned char *)data + n;
|
||||
uint32_t h = init ^ 0xffffffff;
|
||||
|
|
|
@ -1,467 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2014, Intel Corporation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
.ident "\n
|
||||
memmove (Licensed BSD-3)\n
|
||||
Copyright 2014 Intel Corporation"
|
||||
.include "libc/disclaimer.inc"
|
||||
|
||||
#ifndef L
|
||||
# define L(label) .L##label
|
||||
#endif
|
||||
|
||||
#ifndef SHARED_CACHE_SIZE_HALF
|
||||
#define SHARED_CACHE_SIZE_HALF (4 * 1024 * 1024)
|
||||
#endif
|
||||
|
||||
push %rbx
|
||||
push %rdx
|
||||
push %r8
|
||||
push %r9
|
||||
|
||||
/* Check whether we should copy backward or forward. */
|
||||
cmp %rsi, %rdi
|
||||
je L(mm_return)
|
||||
jg L(mm_len_0_or_more_backward)
|
||||
|
||||
/* Now do checks for lengths. We do [0..16], [0..32], [0..64], [0..128]
|
||||
separately. */
|
||||
cmp $16, %rdx
|
||||
jbe L(mm_len_0_16_bytes_forward)
|
||||
|
||||
cmp $32, %rdx
|
||||
ja L(mm_len_32_or_more_forward)
|
||||
|
||||
/* Copy [0..32] and return. */
|
||||
movdqu (%rsi), %xmm0
|
||||
movdqu -16(%rsi, %rdx), %xmm1
|
||||
movdqu %xmm0, (%rdi)
|
||||
movdqu %xmm1, -16(%rdi, %rdx)
|
||||
jmp L(mm_return)
|
||||
|
||||
L(mm_len_32_or_more_forward):
|
||||
cmp $64, %rdx
|
||||
ja L(mm_len_64_or_more_forward)
|
||||
|
||||
/* Copy [0..64] and return. */
|
||||
movdqu (%rsi), %xmm0
|
||||
movdqu 16(%rsi), %xmm1
|
||||
movdqu -16(%rsi, %rdx), %xmm2
|
||||
movdqu -32(%rsi, %rdx), %xmm3
|
||||
movdqu %xmm0, (%rdi)
|
||||
movdqu %xmm1, 16(%rdi)
|
||||
movdqu %xmm2, -16(%rdi, %rdx)
|
||||
movdqu %xmm3, -32(%rdi, %rdx)
|
||||
jmp L(mm_return)
|
||||
|
||||
L(mm_len_64_or_more_forward):
|
||||
cmp $128, %rdx
|
||||
ja L(mm_len_128_or_more_forward)
|
||||
|
||||
/* Copy [0..128] and return. */
|
||||
movdqu (%rsi), %xmm0
|
||||
movdqu 16(%rsi), %xmm1
|
||||
movdqu 32(%rsi), %xmm2
|
||||
movdqu 48(%rsi), %xmm3
|
||||
movdqu -64(%rsi, %rdx), %xmm4
|
||||
movdqu -48(%rsi, %rdx), %xmm5
|
||||
movdqu -32(%rsi, %rdx), %xmm6
|
||||
movdqu -16(%rsi, %rdx), %xmm7
|
||||
movdqu %xmm0, (%rdi)
|
||||
movdqu %xmm1, 16(%rdi)
|
||||
movdqu %xmm2, 32(%rdi)
|
||||
movdqu %xmm3, 48(%rdi)
|
||||
movdqu %xmm4, -64(%rdi, %rdx)
|
||||
movdqu %xmm5, -48(%rdi, %rdx)
|
||||
movdqu %xmm6, -32(%rdi, %rdx)
|
||||
movdqu %xmm7, -16(%rdi, %rdx)
|
||||
jmp L(mm_return)
|
||||
|
||||
L(mm_len_128_or_more_forward):
|
||||
/* Aligning the address of destination. */
|
||||
/* save first unaligned 64 bytes */
|
||||
movdqu (%rsi), %xmm0
|
||||
movdqu 16(%rsi), %xmm1
|
||||
movdqu 32(%rsi), %xmm2
|
||||
movdqu 48(%rsi), %xmm3
|
||||
|
||||
lea 64(%rdi), %r8
|
||||
and $-64, %r8 /* r8 now aligned to next 64 byte boundary */
|
||||
sub %rdi, %rsi /* rsi = src - dst = diff */
|
||||
|
||||
movdqu (%r8, %rsi), %xmm4
|
||||
movdqu 16(%r8, %rsi), %xmm5
|
||||
movdqu 32(%r8, %rsi), %xmm6
|
||||
movdqu 48(%r8, %rsi), %xmm7
|
||||
|
||||
movdqu %xmm0, (%rdi)
|
||||
movdqu %xmm1, 16(%rdi)
|
||||
movdqu %xmm2, 32(%rdi)
|
||||
movdqu %xmm3, 48(%rdi)
|
||||
movdqa %xmm4, (%r8)
|
||||
movaps %xmm5, 16(%r8)
|
||||
movaps %xmm6, 32(%r8)
|
||||
movaps %xmm7, 48(%r8)
|
||||
add $64, %r8
|
||||
|
||||
lea (%rdi, %rdx), %rbx
|
||||
and $-64, %rbx
|
||||
cmp %r8, %rbx
|
||||
jbe L(mm_copy_remaining_forward)
|
||||
|
||||
cmp $SHARED_CACHE_SIZE_HALF, %rdx
|
||||
jae L(mm_large_page_loop_forward)
|
||||
|
||||
.p2align 4
|
||||
L(mm_main_loop_forward):
|
||||
|
||||
prefetcht0 128(%r8, %rsi)
|
||||
|
||||
movdqu (%r8, %rsi), %xmm0
|
||||
movdqu 16(%r8, %rsi), %xmm1
|
||||
movdqu 32(%r8, %rsi), %xmm2
|
||||
movdqu 48(%r8, %rsi), %xmm3
|
||||
movdqa %xmm0, (%r8)
|
||||
movaps %xmm1, 16(%r8)
|
||||
movaps %xmm2, 32(%r8)
|
||||
movaps %xmm3, 48(%r8)
|
||||
lea 64(%r8), %r8
|
||||
cmp %r8, %rbx
|
||||
ja L(mm_main_loop_forward)
|
||||
|
||||
L(mm_copy_remaining_forward):
|
||||
add %rdi, %rdx
|
||||
sub %r8, %rdx
|
||||
/* We copied all up till %rdi position in the dst.
|
||||
In %rdx now is how many bytes are left to copy.
|
||||
Now we need to advance %r8. */
|
||||
lea (%r8, %rsi), %r9
|
||||
|
||||
L(mm_remaining_0_64_bytes_forward):
|
||||
cmp $32, %rdx
|
||||
ja L(mm_remaining_33_64_bytes_forward)
|
||||
cmp $16, %rdx
|
||||
ja L(mm_remaining_17_32_bytes_forward)
|
||||
test %rdx, %rdx
|
||||
.p2align 4,,2
|
||||
je L(mm_return)
|
||||
|
||||
cmpb $8, %dl
|
||||
ja L(mm_remaining_9_16_bytes_forward)
|
||||
cmpb $4, %dl
|
||||
.p2align 4,,5
|
||||
ja L(mm_remaining_5_8_bytes_forward)
|
||||
cmpb $2, %dl
|
||||
.p2align 4,,1
|
||||
ja L(mm_remaining_3_4_bytes_forward)
|
||||
movzbl -1(%r9,%rdx), %esi
|
||||
movzbl (%r9), %ebx
|
||||
movb %sil, -1(%r8,%rdx)
|
||||
movb %bl, (%r8)
|
||||
jmp L(mm_return)
|
||||
|
||||
L(mm_remaining_33_64_bytes_forward):
|
||||
movdqu (%r9), %xmm0
|
||||
movdqu 16(%r9), %xmm1
|
||||
movdqu -32(%r9, %rdx), %xmm2
|
||||
movdqu -16(%r9, %rdx), %xmm3
|
||||
movdqu %xmm0, (%r8)
|
||||
movdqu %xmm1, 16(%r8)
|
||||
movdqu %xmm2, -32(%r8, %rdx)
|
||||
movdqu %xmm3, -16(%r8, %rdx)
|
||||
jmp L(mm_return)
|
||||
|
||||
L(mm_remaining_17_32_bytes_forward):
|
||||
movdqu (%r9), %xmm0
|
||||
movdqu -16(%r9, %rdx), %xmm1
|
||||
movdqu %xmm0, (%r8)
|
||||
movdqu %xmm1, -16(%r8, %rdx)
|
||||
jmp L(mm_return)
|
||||
|
||||
L(mm_remaining_5_8_bytes_forward):
|
||||
movl (%r9), %esi
|
||||
movl -4(%r9,%rdx), %ebx
|
||||
movl %esi, (%r8)
|
||||
movl %ebx, -4(%r8,%rdx)
|
||||
jmp L(mm_return)
|
||||
|
||||
L(mm_remaining_9_16_bytes_forward):
|
||||
mov (%r9), %rsi
|
||||
mov -8(%r9, %rdx), %rbx
|
||||
mov %rsi, (%r8)
|
||||
mov %rbx, -8(%r8, %rdx)
|
||||
jmp L(mm_return)
|
||||
|
||||
L(mm_remaining_3_4_bytes_forward):
|
||||
movzwl -2(%r9,%rdx), %esi
|
||||
movzwl (%r9), %ebx
|
||||
movw %si, -2(%r8,%rdx)
|
||||
movw %bx, (%r8)
|
||||
jmp L(mm_return)
|
||||
|
||||
L(mm_len_0_16_bytes_forward):
|
||||
testb $24, %dl
|
||||
jne L(mm_len_9_16_bytes_forward)
|
||||
testb $4, %dl
|
||||
.p2align 4,,5
|
||||
jne L(mm_len_5_8_bytes_forward)
|
||||
test %rdx, %rdx
|
||||
.p2align 4,,2
|
||||
je L(mm_return)
|
||||
testb $2, %dl
|
||||
.p2align 4,,1
|
||||
jne L(mm_len_2_4_bytes_forward)
|
||||
movzbl -1(%rsi,%rdx), %ebx
|
||||
movzbl (%rsi), %esi
|
||||
movb %bl, -1(%rdi,%rdx)
|
||||
movb %sil, (%rdi)
|
||||
jmp L(mm_return)
|
||||
|
||||
L(mm_len_2_4_bytes_forward):
|
||||
movzwl -2(%rsi,%rdx), %ebx
|
||||
movzwl (%rsi), %esi
|
||||
movw %bx, -2(%rdi,%rdx)
|
||||
movw %si, (%rdi)
|
||||
jmp L(mm_return)
|
||||
|
||||
L(mm_len_5_8_bytes_forward):
|
||||
movl (%rsi), %ebx
|
||||
movl -4(%rsi,%rdx), %esi
|
||||
movl %ebx, (%rdi)
|
||||
movl %esi, -4(%rdi,%rdx)
|
||||
jmp L(mm_return)
|
||||
|
||||
L(mm_len_9_16_bytes_forward):
|
||||
mov (%rsi), %rbx
|
||||
mov -8(%rsi, %rdx), %rsi
|
||||
mov %rbx, (%rdi)
|
||||
mov %rsi, -8(%rdi, %rdx)
|
||||
jmp L(mm_return)
|
||||
|
||||
L(mm_recalc_len):
|
||||
/* Compute in %rdx how many bytes are left to copy after
|
||||
the main loop stops. */
|
||||
mov %rbx, %rdx
|
||||
sub %rdi, %rdx
|
||||
/* The code for copying backwards. */
|
||||
L(mm_len_0_or_more_backward):
|
||||
|
||||
/* Now do checks for lengths. We do [0..16], [16..32], [32..64], [64..128]
|
||||
separately. */
|
||||
cmp $16, %rdx
|
||||
jbe L(mm_len_0_16_bytes_backward)
|
||||
|
||||
cmp $32, %rdx
|
||||
ja L(mm_len_32_or_more_backward)
|
||||
|
||||
/* Copy [0..32] and return. */
|
||||
movdqu (%rsi), %xmm0
|
||||
movdqu -16(%rsi, %rdx), %xmm1
|
||||
movdqu %xmm0, (%rdi)
|
||||
movdqu %xmm1, -16(%rdi, %rdx)
|
||||
jmp L(mm_return)
|
||||
|
||||
L(mm_len_32_or_more_backward):
|
||||
cmp $64, %rdx
|
||||
ja L(mm_len_64_or_more_backward)
|
||||
|
||||
/* Copy [0..64] and return. */
|
||||
movdqu (%rsi), %xmm0
|
||||
movdqu 16(%rsi), %xmm1
|
||||
movdqu -16(%rsi, %rdx), %xmm2
|
||||
movdqu -32(%rsi, %rdx), %xmm3
|
||||
movdqu %xmm0, (%rdi)
|
||||
movdqu %xmm1, 16(%rdi)
|
||||
movdqu %xmm2, -16(%rdi, %rdx)
|
||||
movdqu %xmm3, -32(%rdi, %rdx)
|
||||
jmp L(mm_return)
|
||||
|
||||
L(mm_len_64_or_more_backward):
|
||||
cmp $128, %rdx
|
||||
ja L(mm_len_128_or_more_backward)
|
||||
|
||||
/* Copy [0..128] and return. */
|
||||
movdqu (%rsi), %xmm0
|
||||
movdqu 16(%rsi), %xmm1
|
||||
movdqu 32(%rsi), %xmm2
|
||||
movdqu 48(%rsi), %xmm3
|
||||
movdqu -64(%rsi, %rdx), %xmm4
|
||||
movdqu -48(%rsi, %rdx), %xmm5
|
||||
movdqu -32(%rsi, %rdx), %xmm6
|
||||
movdqu -16(%rsi, %rdx), %xmm7
|
||||
movdqu %xmm0, (%rdi)
|
||||
movdqu %xmm1, 16(%rdi)
|
||||
movdqu %xmm2, 32(%rdi)
|
||||
movdqu %xmm3, 48(%rdi)
|
||||
movdqu %xmm4, -64(%rdi, %rdx)
|
||||
movdqu %xmm5, -48(%rdi, %rdx)
|
||||
movdqu %xmm6, -32(%rdi, %rdx)
|
||||
movdqu %xmm7, -16(%rdi, %rdx)
|
||||
jmp L(mm_return)
|
||||
|
||||
L(mm_len_128_or_more_backward):
|
||||
/* Aligning the address of destination. We need to save
|
||||
16 bits from the source in order not to overwrite them. */
|
||||
|
||||
movdqu -16(%rsi, %rdx), %xmm0
|
||||
movdqu -32(%rsi, %rdx), %xmm1
|
||||
movdqu -48(%rsi, %rdx), %xmm2
|
||||
movdqu -64(%rsi, %rdx), %xmm3
|
||||
|
||||
lea (%rdi, %rdx), %r9
|
||||
and $-64, %r9 /* r9 = aligned dst */
|
||||
|
||||
mov %rsi, %r8
|
||||
sub %rdi, %r8 /* r8 = src - dst, diff */
|
||||
|
||||
movdqu -16(%r9, %r8), %xmm4
|
||||
movdqu -32(%r9, %r8), %xmm5
|
||||
movdqu -48(%r9, %r8), %xmm6
|
||||
movdqu -64(%r9, %r8), %xmm7
|
||||
|
||||
movdqu %xmm0, -16(%rdi, %rdx)
|
||||
movdqu %xmm1, -32(%rdi, %rdx)
|
||||
movdqu %xmm2, -48(%rdi, %rdx)
|
||||
movdqu %xmm3, -64(%rdi, %rdx)
|
||||
movdqa %xmm4, -16(%r9)
|
||||
movaps %xmm5, -32(%r9)
|
||||
movaps %xmm6, -48(%r9)
|
||||
movaps %xmm7, -64(%r9)
|
||||
lea -64(%r9), %r9
|
||||
|
||||
lea 64(%rdi), %rbx
|
||||
and $-64, %rbx
|
||||
|
||||
cmp %r9, %rbx
|
||||
jae L(mm_recalc_len)
|
||||
|
||||
cmp $SHARED_CACHE_SIZE_HALF, %rdx
|
||||
jae L(mm_large_page_loop_backward)
|
||||
|
||||
.p2align 4
|
||||
L(mm_main_loop_backward):
|
||||
|
||||
prefetcht0 -128(%r9, %r8)
|
||||
|
||||
movdqu -64(%r9, %r8), %xmm0
|
||||
movdqu -48(%r9, %r8), %xmm1
|
||||
movdqu -32(%r9, %r8), %xmm2
|
||||
movdqu -16(%r9, %r8), %xmm3
|
||||
movdqa %xmm0, -64(%r9)
|
||||
movaps %xmm1, -48(%r9)
|
||||
movaps %xmm2, -32(%r9)
|
||||
movaps %xmm3, -16(%r9)
|
||||
lea -64(%r9), %r9
|
||||
cmp %r9, %rbx
|
||||
jb L(mm_main_loop_backward)
|
||||
jmp L(mm_recalc_len)
|
||||
|
||||
/* Copy [0..16] and return. */
|
||||
L(mm_len_0_16_bytes_backward):
|
||||
testb $24, %dl
|
||||
jnz L(mm_len_9_16_bytes_backward)
|
||||
testb $4, %dl
|
||||
.p2align 4,,5
|
||||
jnz L(mm_len_5_8_bytes_backward)
|
||||
test %rdx, %rdx
|
||||
.p2align 4,,2
|
||||
je L(mm_return)
|
||||
testb $2, %dl
|
||||
.p2align 4,,1
|
||||
jne L(mm_len_3_4_bytes_backward)
|
||||
movzbl -1(%rsi,%rdx), %ebx
|
||||
movzbl (%rsi), %ecx
|
||||
movb %bl, -1(%rdi,%rdx)
|
||||
movb %cl, (%rdi)
|
||||
jmp L(mm_return)
|
||||
|
||||
L(mm_len_3_4_bytes_backward):
|
||||
movzwl -2(%rsi,%rdx), %ebx
|
||||
movzwl (%rsi), %ecx
|
||||
movw %bx, -2(%rdi,%rdx)
|
||||
movw %cx, (%rdi)
|
||||
jmp L(mm_return)
|
||||
|
||||
L(mm_len_9_16_bytes_backward):
|
||||
movl -4(%rsi,%rdx), %ebx
|
||||
movl -8(%rsi,%rdx), %ecx
|
||||
movl %ebx, -4(%rdi,%rdx)
|
||||
movl %ecx, -8(%rdi,%rdx)
|
||||
sub $8, %rdx
|
||||
jmp L(mm_len_0_16_bytes_backward)
|
||||
|
||||
L(mm_len_5_8_bytes_backward):
|
||||
movl (%rsi), %ebx
|
||||
movl -4(%rsi,%rdx), %ecx
|
||||
movl %ebx, (%rdi)
|
||||
movl %ecx, -4(%rdi,%rdx)
|
||||
|
||||
L(mm_return):
|
||||
pop %r9
|
||||
pop %r8
|
||||
pop %rdx
|
||||
pop %rbx
|
||||
pop %rbp
|
||||
ret
|
||||
|
||||
/* Big length copy forward part. */
|
||||
|
||||
.p2align 4
|
||||
L(mm_large_page_loop_forward):
|
||||
movdqu (%r8, %rsi), %xmm0
|
||||
movdqu 16(%r8, %rsi), %xmm1
|
||||
movdqu 32(%r8, %rsi), %xmm2
|
||||
movdqu 48(%r8, %rsi), %xmm3
|
||||
movntdq %xmm0, (%r8)
|
||||
movntdq %xmm1, 16(%r8)
|
||||
movntdq %xmm2, 32(%r8)
|
||||
movntdq %xmm3, 48(%r8)
|
||||
lea 64(%r8), %r8
|
||||
cmp %r8, %rbx
|
||||
ja L(mm_large_page_loop_forward)
|
||||
sfence
|
||||
jmp L(mm_copy_remaining_forward)
|
||||
|
||||
/* Big length copy backward part. */
|
||||
.p2align 4
|
||||
L(mm_large_page_loop_backward):
|
||||
movdqu -64(%r9, %r8), %xmm0
|
||||
movdqu -48(%r9, %r8), %xmm1
|
||||
movdqu -32(%r9, %r8), %xmm2
|
||||
movdqu -16(%r9, %r8), %xmm3
|
||||
movntdq %xmm0, -64(%r9)
|
||||
movntdq %xmm1, -48(%r9)
|
||||
movntdq %xmm2, -32(%r9)
|
||||
movntdq %xmm3, -16(%r9)
|
||||
lea -64(%r9), %r9
|
||||
cmp %r9, %rbx
|
||||
jb L(mm_large_page_loop_backward)
|
||||
sfence
|
||||
jmp L(mm_recalc_len)
|
52
libc/nexgen32e/strlen.S
Normal file
52
libc/nexgen32e/strlen.S
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
|
||||
/ Returns length of NUL-terminated string.
|
||||
/
|
||||
/ @param rdi is non-null NUL-terminated string pointer
|
||||
/ @return rax is number of bytes (excluding NUL)
|
||||
/ @clob ax,dx,cx,xmm3,xmm4
|
||||
/ @note h/t agner fog
|
||||
/ @asyncsignalsafe
|
||||
strlen: .leafprologue
|
||||
.profilable
|
||||
mov %rdi,%rax
|
||||
mov %edi,%ecx
|
||||
and $15,%ecx
|
||||
and $-16,%rax
|
||||
pxor %xmm4,%xmm4
|
||||
movdqa (%rax),%xmm3
|
||||
pcmpeqb %xmm4,%xmm3
|
||||
pmovmskb %xmm3,%edx
|
||||
shr %cl,%edx
|
||||
shl %cl,%edx
|
||||
bsf %edx,%edx
|
||||
jnz 2f
|
||||
1: lea 16(%rax),%rax
|
||||
movdqa (%rax),%xmm3
|
||||
pcmpeqb %xmm4,%xmm3
|
||||
pmovmskb %xmm3,%edx
|
||||
bsf %edx,%edx
|
||||
jz 1b
|
||||
2: add %rdx,%rax
|
||||
sub %rdi,%rax
|
||||
.leafepilogue
|
||||
.endfn strlen,globl
|
|
@ -42,8 +42,8 @@ int bind(int fd, const void *addr, uint32_t addrsize) {
|
|||
return bind$sysv(fd, addr, addrsize);
|
||||
} else {
|
||||
struct sockaddr_in$bsd addr2;
|
||||
static_assert(sizeof(struct sockaddr_in) ==
|
||||
sizeof(struct sockaddr_in$bsd));
|
||||
_Static_assert(sizeof(struct sockaddr_in) ==
|
||||
sizeof(struct sockaddr_in$bsd));
|
||||
memcpy(&addr2, addr, sizeof(struct sockaddr_in));
|
||||
sockaddr2bsd(&addr2);
|
||||
return bind$sysv(fd, &addr2, addrsize);
|
||||
|
|
|
@ -28,7 +28,8 @@ int connect$sysv(int fd, const void *addr, uint32_t addrsize) {
|
|||
return __connect$sysv(fd, addr, addrsize);
|
||||
} else {
|
||||
struct sockaddr_in$bsd addr2;
|
||||
static_assert(sizeof(struct sockaddr_in) == sizeof(struct sockaddr_in$bsd));
|
||||
_Static_assert(sizeof(struct sockaddr_in) ==
|
||||
sizeof(struct sockaddr_in$bsd));
|
||||
memcpy(&addr2, addr, sizeof(struct sockaddr_in));
|
||||
sockaddr2bsd(&addr2);
|
||||
return connect$sysv(fd, &addr2, addrsize);
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
*/
|
||||
ssize_t sendto(int fd, const void *buf, size_t size, uint32_t flags,
|
||||
const void *opt_addr, uint32_t addrsize) {
|
||||
static_assert(sizeof(struct sockaddr_in) == sizeof(struct sockaddr_in$bsd));
|
||||
_Static_assert(sizeof(struct sockaddr_in) == sizeof(struct sockaddr_in$bsd));
|
||||
if (!IsWindows()) {
|
||||
if (!IsBsd() || !opt_addr) {
|
||||
return sendto$sysv(fd, buf, size, flags, opt_addr, addrsize);
|
||||
|
|
|
@ -21,14 +21,8 @@
|
|||
#include "libc/stdio/internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
* Writes byte to stream.
|
||||
*
|
||||
* @return c (as unsigned char) if written or -1 w/ errno
|
||||
*/
|
||||
noinstrument int fputc(int c, FILE *f) {
|
||||
static noinline int __fputcg(int c, FILE *f) {
|
||||
if (f->beg < f->size) {
|
||||
c &= 0xff;
|
||||
f->buf[f->beg++] = c;
|
||||
if (f->beg == f->size || f->bufmode == _IONBF ||
|
||||
(f->bufmode == _IOLBF && c == '\n')) {
|
||||
|
@ -38,8 +32,22 @@ noinstrument int fputc(int c, FILE *f) {
|
|||
f->beg = 0;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
return c & 0xff;
|
||||
} else {
|
||||
return __fseteof(f);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes byte to stream.
|
||||
* @return c (as unsigned char) if written or -1 w/ errno
|
||||
* @see putc() if called within loop
|
||||
*/
|
||||
noinstrument int fputc(int c, FILE *f) {
|
||||
if (f->beg + 1 < f->size && f->bufmode == _IOFBF) {
|
||||
f->buf[f->beg++] = c;
|
||||
return c & 0xff;
|
||||
} else {
|
||||
return __fputcg(c, f);
|
||||
}
|
||||
}
|
||||
|
|
53
libc/stdio/fputcfb.c
Normal file
53
libc/stdio/fputcfb.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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdio/internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
static noinline int slowpath(int c, FILE *f) {
|
||||
if (f->beg < f->size) {
|
||||
c &= 0xff;
|
||||
f->buf[f->beg++] = c;
|
||||
if (f->beg == f->size) {
|
||||
if (f->writer) {
|
||||
if (f->writer(f) == -1) return -1;
|
||||
} else if (f->beg == f->size) {
|
||||
f->beg = 0;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
} else {
|
||||
return __fseteof(f);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes byte to stream.
|
||||
*
|
||||
* @return c (as unsigned char) if written or -1 w/ errno
|
||||
*/
|
||||
noinstrument int fputcfb(int c, FILE *f) {
|
||||
if (f->beg + 1 < f->size) {
|
||||
c &= 0xff;
|
||||
f->buf[f->beg++] = c;
|
||||
return c;
|
||||
} else {
|
||||
return slowpath(c, f);
|
||||
}
|
||||
}
|
|
@ -38,7 +38,7 @@ int fputs(const char *s, FILE *f) {
|
|||
int i, n, m;
|
||||
n = strlen(s);
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (fputc(s[i], f) == -1) {
|
||||
if (putc(s[i], f) == -1) {
|
||||
if (ferror(f) == EINTR) continue;
|
||||
if (feof(f)) errno = f->state = EPIPE;
|
||||
return -1;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "libc/str/internal.h"
|
||||
|
||||
/**
|
||||
* Reads data to stream.
|
||||
* Reads data from stream.
|
||||
*
|
||||
* @param stride specifies the size of individual items
|
||||
* @param count is the number of strides to fetch
|
||||
|
@ -36,7 +36,7 @@ size_t fread(void *buf, size_t stride, size_t count, FILE *f) {
|
|||
size_t i, n;
|
||||
unsigned char *p;
|
||||
for (n = stride * count, p = buf, i = 0; i < n; ++i) {
|
||||
if ((c = fgetc(f)) != -1) {
|
||||
if ((c = getc(f)) != -1) {
|
||||
p[i] = c & 0xff;
|
||||
} else if (!(i % stride)) {
|
||||
return i / stride;
|
||||
|
|
|
@ -19,5 +19,5 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdio/internal.h"
|
||||
|
||||
alignas(PAGESIZE) unsigned char g_stdoutbuf[BUFSIZ];
|
||||
alignas(PAGESIZE) unsigned char g_stderrbuf[BUFSIZ];
|
||||
_Alignas(PAGESIZE) unsigned char g_stdoutbuf[BUFSIZ];
|
||||
_Alignas(PAGESIZE) unsigned char g_stderrbuf[BUFSIZ];
|
||||
|
|
|
@ -100,8 +100,8 @@ int vfscanf(FILE *, const char *, va_list);
|
|||
│ cosmopolitan § standard i/o » optimizations ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#define putc(c, f) fputc(c, f)
|
||||
#define getc(f) (f->beg < f->end ? f->buf[f->beg++] : fgetc(f))
|
||||
#define putc(c, f) fputc(c, f)
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
#define printf(FMT, ...) (printf)(PFLINK(FMT), ##__VA_ARGS__)
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
* @param line is NULL-propagating
|
||||
* @see getline
|
||||
*/
|
||||
char *(chomp)(char *line) {
|
||||
char *chomp(char *line) {
|
||||
size_t i;
|
||||
for (i = strlen(line); i--;) {
|
||||
if (line[i] == '\r' || line[i] == '\n') {
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/str/utf16.h"
|
||||
|
||||
/**
|
||||
* Helps runtime decode UTF-16 with slightly smaller code size.
|
||||
*/
|
||||
wint_t DecodeNtsUtf16(const char16_t **s) {
|
||||
wint_t x, y;
|
||||
for (;;) {
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Converts ASCII hexadecimal character to integer case-insensitively.
|
||||
* @return integer or 0 if c ∉ [0-9A-Fa-f]
|
||||
*/
|
||||
int hextoint(int c) {
|
||||
if ('0' <= c && c <= '9') {
|
||||
return c - '0';
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Returns nonzero if c is printable ascii that isn't space.
|
||||
*/
|
||||
int isgraph(int c) {
|
||||
return 0x21 <= c && c <= 0x7E;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Returns nonzero if c is printable ascii including space.
|
||||
*/
|
||||
int isprint(int c) {
|
||||
return 0x20 <= c && c <= 0x7E;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Returns nonzero if c ∈ !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
|
||||
*/
|
||||
int ispunct(int c) {
|
||||
return (0x21 <= c && c <= 0x7E) && !('0' <= c && c <= '9') &&
|
||||
!('A' <= c && c <= 'Z') && !('a' <= c && c <= 'z');
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
compatfn int mbtowc(wchar_t *wc, const char *s, size_t n) {
|
||||
if (!s) return 0;
|
||||
alignas(8) char alt[ROUNDUP(MB_CUR_MAX, 8)];
|
||||
_Alignas(8) char alt[ROUNDUP(MB_CUR_MAX, 8)];
|
||||
if (n < MB_CUR_MAX) {
|
||||
memset(alt, 0, sizeof(alt));
|
||||
memcpy(alt, s, n);
|
||||
|
|
|
@ -233,37 +233,21 @@ int iswctype(wint_t, wctype_t) pureconst;
|
|||
|
||||
char *strsignal(int) returnsnonnull libcesque;
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § strings » optimizations ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
|
||||
#define explicit_bzero(STR, BYTES) \
|
||||
do { \
|
||||
void *Str; \
|
||||
size_t Bytes; \
|
||||
asm volatile("call\texplicit_bzero" \
|
||||
: "=D"(Str), "=S"(Bytes) \
|
||||
: "0"(STR), "1"(BYTES) \
|
||||
: "rax", "rcx", "rdx", "r8", "r9", "r10", "r11", "memory", \
|
||||
"cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); \
|
||||
} while (0)
|
||||
#define __memcpy_isgoodsize(SIZE) \
|
||||
(__builtin_constant_p(SIZE) && ((SIZE) <= __BIGGEST_ALIGNMENT__ * 2 && \
|
||||
__builtin_popcountl((unsigned)(SIZE)) == 1))
|
||||
|
||||
#ifdef UNBLOAT_STDARG
|
||||
#define __STR_XMM_CLOBBER
|
||||
#else
|
||||
#define __STR_XMM_CLOBBER "xmm3", "xmm4",
|
||||
#endif
|
||||
|
||||
#define __memcpy_isgoodsize(SIZE) \
|
||||
(isconstant(SIZE) && ((SIZE) <= __BIGGEST_ALIGNMENT__ * 2 && \
|
||||
__builtin_popcountl((unsigned)(SIZE)) == 1))
|
||||
|
||||
#define __memset_isgoodsize(SIZE) \
|
||||
(isconstant(SIZE) && (((SIZE) <= __BIGGEST_ALIGNMENT__ && \
|
||||
__builtin_popcountl((unsigned)(SIZE)) == 1) || \
|
||||
((SIZE) % __BIGGEST_ALIGNMENT__ == 0 && \
|
||||
(SIZE) / __BIGGEST_ALIGNMENT__ <= 3)))
|
||||
#define __memset_isgoodsize(SIZE) \
|
||||
(__builtin_constant_p(SIZE) && \
|
||||
(((SIZE) <= __BIGGEST_ALIGNMENT__ && \
|
||||
__builtin_popcountl((unsigned)(SIZE)) == 1) || \
|
||||
((SIZE) % __BIGGEST_ALIGNMENT__ == 0 && \
|
||||
(SIZE) / __BIGGEST_ALIGNMENT__ <= 3)))
|
||||
|
||||
#define memcpy(DEST, SRC, SIZE) \
|
||||
(__memcpy_isgoodsize(SIZE) ? __builtin_memcpy(DEST, SRC, SIZE) \
|
||||
|
@ -273,7 +257,18 @@ char *strsignal(int) returnsnonnull libcesque;
|
|||
(__memset_isgoodsize(SIZE) ? __builtin_memset(DEST, BYTE, SIZE) \
|
||||
: __memset(DEST, BYTE, SIZE))
|
||||
|
||||
#if defined(__STDC_HOSTED__) && (defined(__SSE2__) || defined(UNBLOAT_STDARG))
|
||||
#if defined(__STDC_HOSTED__) && defined(__SSE2__)
|
||||
|
||||
#define strlen(STR) \
|
||||
(__builtin_constant_p(STR) ? __builtin_strlen(STR) : ({ \
|
||||
size_t LeN; \
|
||||
const char *StR = (STR); \
|
||||
asm("call\tstrlen" \
|
||||
: "=a"(LeN) \
|
||||
: "D"(StR), "m"(*(char(*)[0x7fffffff])StR) \
|
||||
: "rcx", "rdx", "xmm3", "xmm4", "cc"); \
|
||||
LeN; \
|
||||
}))
|
||||
|
||||
#define memmove(DEST, SRC, SIZE) __memcpy("MemMove", (DEST), (SRC), (SIZE))
|
||||
|
||||
|
@ -291,7 +286,7 @@ char *strsignal(int) returnsnonnull libcesque;
|
|||
asm("call\t" FN \
|
||||
: "=m"(*(char(*)[SiZe])(DeSt)) \
|
||||
: "D"(DeSt), "S"(SrC), "d"(SiZe), "m"(*(const char(*)[SiZe])(SrC)) \
|
||||
: __STR_XMM_CLOBBER "rcx", "cc"); \
|
||||
: "xmm3", "xmm4", "rcx", "cc"); \
|
||||
DeSt; \
|
||||
})
|
||||
|
||||
|
@ -302,11 +297,22 @@ char *strsignal(int) returnsnonnull libcesque;
|
|||
asm("call\tMemSet" \
|
||||
: "=m"(*(char(*)[SiZe])(DeSt)) \
|
||||
: "D"(DeSt), "S"(BYTE), "d"(SiZe) \
|
||||
: __STR_XMM_CLOBBER "rcx", "cc"); \
|
||||
: "xmm3", "xmm4", "rcx", "cc"); \
|
||||
DeSt; \
|
||||
})
|
||||
|
||||
#else /* hosted/sse2/unbloat */
|
||||
#define explicit_bzero(STR, BYTES) \
|
||||
do { \
|
||||
void *Str; \
|
||||
size_t Bytes; \
|
||||
asm volatile("call\texplicit_bzero" \
|
||||
: "=D"(Str), "=S"(Bytes) \
|
||||
: "0"(STR), "1"(BYTES) \
|
||||
: "rax", "rcx", "rdx", "r8", "r9", "r10", "r11", "memory", \
|
||||
"cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); \
|
||||
} while (0)
|
||||
|
||||
#else /* hosted+sse2 */
|
||||
|
||||
#define mempcpy(DEST, SRC, SIZE) \
|
||||
({ \
|
||||
|
@ -347,7 +353,6 @@ char *strsignal(int) returnsnonnull libcesque;
|
|||
})
|
||||
|
||||
#endif /* hosted/sse2/unbloat */
|
||||
|
||||
#endif /* __GNUC__ && !__STRICT_ANSI__ */
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
|
@ -34,7 +35,7 @@ size_t strlcpy(char *d, const char *s, size_t n) {
|
|||
size_t slen, actual;
|
||||
slen = strlen(s);
|
||||
if (n) {
|
||||
actual = min(n, slen);
|
||||
actual = MIN(n, slen);
|
||||
memcpy(d, s, actual);
|
||||
d[actual] = '\0';
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
static const char kSig[4] = "SIG";
|
||||
static const char kUnknown[8] = "UNKNOWN";
|
||||
|
||||
alignas(1) static const char kStrSignals[][8] = {
|
||||
_Alignas(char) static const char kStrSignals[][8] = {
|
||||
"EXIT", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "BUS",
|
||||
"FPE", "KILL", "USR1", "SEGV", "USR2", "PIPE", "ALRM", "TERM",
|
||||
"STKFLT", "CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU", "URG",
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include "libc/nexgen32e/bsr.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
/* TODO(jart): DELETE? */
|
||||
|
||||
/**
|
||||
* Generic Thompson-Pike Varint Decoder.
|
||||
* @return number of bytes successfully consumed or -1 w/ errno
|
||||
|
@ -12,11 +14,11 @@
|
|||
forceinline int tpdecodecb(wint_t *out, int first,
|
||||
int get(void *arg, uint32_t i), void *arg) {
|
||||
uint32_t wc, cb, need, msb, j, i = 1;
|
||||
if (unlikely((wc = first) == -1)) return -1;
|
||||
while (unlikely((wc & 0b11000000) == 0b10000000)) {
|
||||
if (__builtin_expect((wc = first) == -1, 0)) return -1;
|
||||
while (__builtin_expect((wc & 0b11000000) == 0b10000000, 0)) {
|
||||
if ((wc = get(arg, i++)) == -1) return -1;
|
||||
}
|
||||
if (unlikely(!(0 <= wc && wc <= 0x7F))) {
|
||||
if (__builtin_expect(!(0 <= wc && wc <= 0x7F), 0)) {
|
||||
msb = wc < 252 ? bsr(~wc & 0xff) : 1;
|
||||
need = 7 - msb;
|
||||
wc &= ((1u << msb) - 1) | 0b00000011;
|
||||
|
@ -30,7 +32,7 @@ forceinline int tpdecodecb(wint_t *out, int first,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (likely(out)) *out = (wint_t)wc;
|
||||
if (__builtin_expect(!!out, 1)) *out = (wint_t)wc;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "libc/str/tpenc.h"
|
||||
#include "libc/str/tpencode.internal.h"
|
||||
|
||||
/* TODO: DELETE */
|
||||
|
||||
/**
|
||||
* Thompson-Pike Varint Encoder.
|
||||
*
|
||||
|
|
|
@ -11,13 +11,14 @@ COSMOPOLITAN_C_START_
|
|||
#define IsUcs2(wc) (((wc)&UTF16_MASK) != UTF16_MOAR)
|
||||
#define IsUtf16Cont(wc) (((wc)&UTF16_MASK) == UTF16_CONT)
|
||||
#define MergeUtf16(lo, hi) ((((lo)-0xD800) << 10) + ((hi)-0xDC00) + 0x10000)
|
||||
#define EncodeUtf16(wc) \
|
||||
(likely((0x0000 <= (wc) && (wc) <= 0xFFFF) || \
|
||||
(0xE000 <= (wc) && (wc) <= 0xFFFF)) \
|
||||
? (wc) \
|
||||
: 0x10000 <= (wc) && (wc) <= 0x10FFFF \
|
||||
? (((((wc)-0x10000) >> 10) + 0xD800) | \
|
||||
((((wc)-0x10000) & 1023) + 0xDC00) << 16) \
|
||||
#define EncodeUtf16(wc) \
|
||||
(__builtin_expect(((0x0000 <= (wc) && (wc) <= 0xFFFF) || \
|
||||
(0xE000 <= (wc) && (wc) <= 0xFFFF)), \
|
||||
1) \
|
||||
? (wc) \
|
||||
: 0x10000 <= (wc) && (wc) <= 0x10FFFF \
|
||||
? (((((wc)-0x10000) >> 10) + 0xD800) | \
|
||||
((((wc)-0x10000) & 1023) + 0xDC00) << 16) \
|
||||
: 0xFFFD)
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
#define __BENCH_ARRAY(S) \
|
||||
_Section(".piro.relo.sort.bench.2." #S ",\"aw\",@init_array #")
|
||||
|
||||
#define __TEST_PROTOTYPE(S, N, A, K) \
|
||||
testonly void S##_##N(void); \
|
||||
alignas(8) const void *const S##_##N##_ptr[] A(S) = {S##_##N}; \
|
||||
#define __TEST_PROTOTYPE(S, N, A, K) \
|
||||
testonly void S##_##N(void); \
|
||||
_Alignas(long) const void *const S##_##N##_ptr[] A(S) = {S##_##N}; \
|
||||
testonly K void S##_##N(void)
|
||||
|
||||
#define __TEST_SECTION(NAME, CONTENT) \
|
||||
|
|
|
@ -45,6 +45,7 @@ char *xstrdup(const char *) _XPNN _XMAL;
|
|||
char *xstrndup(const char *, size_t) _XPNN _XMAL;
|
||||
char *xstrcat(const char *, ...) paramsnonnull((1)) nullterminated() _XMAL;
|
||||
char *xstrmul(const char *, size_t) paramsnonnull((1)) _XMAL;
|
||||
char *xdirname(const char *) paramsnonnull() _XMAL;
|
||||
char *xjoinpaths(const char *, const char *) paramsnonnull() _XMAL;
|
||||
char *xinet_ntop(int, const void *) _XPNN _XMAL;
|
||||
|
||||
|
|
28
libc/x/xdirname.c
Normal file
28
libc/x/xdirname.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
/**
|
||||
* Returns directory portion of path.
|
||||
*/
|
||||
char *xdirname(const char *path) {
|
||||
return dirname(xstrdup(path));
|
||||
}
|
|
@ -22,14 +22,25 @@
|
|||
#include "libc/x/x.h"
|
||||
|
||||
/**
|
||||
* Joins paths.
|
||||
* Joins paths, e.g.
|
||||
*
|
||||
* "a" + "b" → "a/b"
|
||||
* "a/" + "b" → "a/b"
|
||||
* "a" + "b/" → "a/b/"
|
||||
* "a" + "/b" → "/b"
|
||||
* "." + "b" → "b"
|
||||
* "" + "b" → "b"
|
||||
*
|
||||
* @return newly allocated string of resulting path
|
||||
*/
|
||||
char *xjoinpaths(const char *path, const char *other) {
|
||||
if (!*other) {
|
||||
return xstrdup(path);
|
||||
} else if (startswith(other, "/") || strcmp(path, ".") == 0) {
|
||||
} else if (!*path) {
|
||||
return xstrdup(other);
|
||||
} else if (endswith(other, "/")) {
|
||||
} else if (startswith(other, "/") || !strcmp(path, ".")) {
|
||||
return xstrdup(other);
|
||||
} else if (endswith(path, "/")) {
|
||||
return xstrcat(path, other);
|
||||
} else {
|
||||
return xstrcat(path, '/', other);
|
||||
|
|
|
@ -44,13 +44,3 @@ TEST(basename, testWindows_isGrantedRespect) {
|
|||
EXPECT_STREQ("there", basename("hello\\there"));
|
||||
EXPECT_STREQ("yo", basename("hello\\there\\yo"));
|
||||
}
|
||||
|
||||
TEST(dirname, test) {
|
||||
EXPECT_STREQ("/usr", dirname(strdup("/usr/lib")));
|
||||
EXPECT_STREQ("usr", dirname(strdup("usr/lib")));
|
||||
EXPECT_STREQ("/", dirname(strdup("/usr/")));
|
||||
EXPECT_STREQ("/", dirname(strdup("/")));
|
||||
EXPECT_STREQ(".", dirname(strdup("hello")));
|
||||
EXPECT_STREQ(".", dirname(strdup(".")));
|
||||
EXPECT_STREQ(".", dirname(strdup("..")));
|
||||
}
|
||||
|
|
34
test/libc/fmt/dirname_test.c
Normal file
34
test/libc/fmt/dirname_test.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(dirname, test) {
|
||||
EXPECT_STREQ("/usr", dirname(gc(strdup("/usr/lib"))));
|
||||
EXPECT_STREQ("usr", dirname(gc(strdup("usr/lib"))));
|
||||
EXPECT_STREQ("/", dirname(gc(strdup("/usr/"))));
|
||||
EXPECT_STREQ("/", dirname(gc(strdup("/"))));
|
||||
EXPECT_STREQ(".", dirname(gc(strdup("hello"))));
|
||||
EXPECT_STREQ(".", dirname(gc(strdup("."))));
|
||||
EXPECT_STREQ(".", dirname(gc(strdup(".."))));
|
||||
}
|
33
test/libc/stdio/fputs_test.c
Normal file
33
test/libc/stdio/fputs_test.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/hyperion.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
BENCH(fputs, bench) {
|
||||
FILE *f;
|
||||
char *buf;
|
||||
buf = gc(malloc(kHyperionSize));
|
||||
EZBENCH2("fputs", f = fmemopen(buf, kHyperionSize, "r+"),
|
||||
fputs(kHyperion, f));
|
||||
}
|
36
test/libc/stdio/fread_test.c
Normal file
36
test/libc/stdio/fread_test.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/hyperion.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
BENCH(fputs, bench) {
|
||||
FILE *f;
|
||||
char *buf = gc(malloc(kHyperionSize));
|
||||
char *buf2 = gc(malloc(kHyperionSize));
|
||||
buf2 = gc(malloc(kHyperionSize));
|
||||
f = fmemopen(buf, kHyperionSize, "r+");
|
||||
ASSERT_EQ(kHyperionSize, fread(buf2, 1, kHyperionSize, f));
|
||||
EZBENCH2("fread", f = fmemopen(buf, kHyperionSize, "r+"),
|
||||
fread(buf2, 1, kHyperionSize, f));
|
||||
}
|
|
@ -17,34 +17,25 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/intrin/pcmpeqb.h"
|
||||
#include "libc/intrin/pmovmskb.h"
|
||||
#include "libc/nexgen32e/bsf.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
/**
|
||||
* Returns length of NUL-terminated string.
|
||||
*
|
||||
* @param s is non-null NUL-terminated string pointer
|
||||
* @return number of bytes (excluding NUL)
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
size_t strlen(const char *s) {
|
||||
const char *p;
|
||||
unsigned k, m;
|
||||
uint8_t v1[16], vz[16];
|
||||
k = (uintptr_t)s & 15;
|
||||
p = (const char *)((uintptr_t)s & -16);
|
||||
memset(vz, 0, 16);
|
||||
memcpy(v1, p, 16);
|
||||
pcmpeqb(v1, v1, vz);
|
||||
m = pmovmskb(v1) >> k << k;
|
||||
while (!m) {
|
||||
p += 16;
|
||||
memcpy(v1, p, 16);
|
||||
pcmpeqb(v1, v1, vz);
|
||||
m = pmovmskb(v1);
|
||||
}
|
||||
return p + bsf(m) - s;
|
||||
static unsigned Bsr(unsigned x) {
|
||||
static const char kDebruijn[32] = {
|
||||
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
|
||||
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31,
|
||||
};
|
||||
x |= x >> 1;
|
||||
x |= x >> 2;
|
||||
x |= x >> 4;
|
||||
x |= x >> 8;
|
||||
x |= x >> 16;
|
||||
x *= 0x07c4acdd;
|
||||
x >>= 27;
|
||||
return kDebruijn[x];
|
||||
}
|
||||
|
||||
TEST(bsr, test) {
|
||||
ASSERT_EQ(bsr(0xffffffff), Bsr(0xffffffff));
|
||||
}
|
|
@ -71,11 +71,15 @@ TEST(strnlen, testconst) {
|
|||
}
|
||||
|
||||
TEST(strlen, testnonconst) {
|
||||
/* this test case is a great example of why we need:
|
||||
"m"(*(char(*)[0x7fffffff])StR)
|
||||
rather than:
|
||||
"m"(*StR) */
|
||||
char buf[256];
|
||||
unsigned i;
|
||||
for (i = 0; i < 255; ++i) buf[i] = i + 1;
|
||||
for (i = 0; i < 250; ++i) buf[i] = i + 1;
|
||||
buf[i] = '\0';
|
||||
ASSERT_EQ(255, strlen(buf));
|
||||
ASSERT_EQ(250, strlen(buf));
|
||||
}
|
||||
|
||||
TEST(strnlen_s, null_ReturnsZero) {
|
||||
|
|
31
test/libc/x/xjoinpaths_test.c
Normal file
31
test/libc/x/xjoinpaths_test.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
TEST(xjoinpaths, test) {
|
||||
EXPECT_STREQ("", gc(xjoinpaths("", "")));
|
||||
EXPECT_STREQ("b", gc(xjoinpaths("", "b")));
|
||||
EXPECT_STREQ("a/b", gc(xjoinpaths("a", "b")));
|
||||
EXPECT_STREQ("a/b", gc(xjoinpaths("a/", "b")));
|
||||
EXPECT_STREQ("a/b/", gc(xjoinpaths("a", "b/")));
|
||||
EXPECT_STREQ("/b", gc(xjoinpaths("a", "/b")));
|
||||
EXPECT_STREQ("b", gc(xjoinpaths(".", "b")));
|
||||
}
|
|
@ -22,7 +22,7 @@
|
|||
#include "libc/testlib/testlib.h"
|
||||
#include "net/http/uri.h"
|
||||
|
||||
alignas(32) const char kWinsockIcoPngBase64[] = "\
|
||||
_Alignas(32) const char kWinsockIcoPngBase64[] = "\
|
||||
base64,iVBORw0KGgoAAAANSUhEUgAAAJcAAACXCAYAAAAYn8l5AAAABmJLR0QA/\
|
||||
wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4woLByMP6uwgW\
|
||||
QAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAMeSURBVHja7\
|
||||
|
|
1
third_party/chibicc/README.cosmo
vendored
1
third_party/chibicc/README.cosmo
vendored
|
@ -30,6 +30,7 @@ local bug fixes
|
|||
- fix 64-bit bug in generated code for struct bitfields
|
||||
- fix bug where last statement in statement expression couldn't have label
|
||||
- print_tokens (chibicc -E) now works in the case of adjacent string literals
|
||||
- make enums unsigned (like gcc) so we don't suffer the msvc enum bitfield bug
|
||||
|
||||
local changes
|
||||
|
||||
|
|
3858
third_party/chibicc/as.c
vendored
3858
third_party/chibicc/as.c
vendored
File diff suppressed because it is too large
Load diff
3
third_party/chibicc/asm.c
vendored
3
third_party/chibicc/asm.c
vendored
|
@ -679,8 +679,7 @@ static void StoreAsmOutputs(Asm *a) {
|
|||
println("\tmov\t%%%s,(%%rax)", kGreg[z][a->ops[i].reg]);
|
||||
} else {
|
||||
println("\tpush\t%%rbx");
|
||||
push();
|
||||
pop("%rbx");
|
||||
println("\tmov\t%%rax,%%rbx");
|
||||
gen_addr(a->ops[i].node);
|
||||
println("\tmov\t%%%s,(%%rax)", kGreg[z][3]);
|
||||
println("\tpop\t%%rbx");
|
||||
|
|
8
third_party/chibicc/chibicc.c
vendored
8
third_party/chibicc/chibicc.c
vendored
|
@ -41,6 +41,7 @@ static bool opt_c;
|
|||
static bool opt_cc1;
|
||||
static bool opt_hash_hash_hash;
|
||||
static bool opt_static;
|
||||
static bool opt_save_temps;
|
||||
static char *opt_MF;
|
||||
static char *opt_MT;
|
||||
static char *opt_o;
|
||||
|
@ -140,6 +141,7 @@ static char *quote_makefile(char *s) {
|
|||
|
||||
static void PrintMemoryUsage(void) {
|
||||
struct mallinfo mi;
|
||||
malloc_trim(0);
|
||||
mi = mallinfo();
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "allocated %,ld bytes of memory\n", mi.arena);
|
||||
|
@ -342,7 +344,7 @@ static char *replace_extn(char *tmpl, char *extn) {
|
|||
}
|
||||
|
||||
static void cleanup(void) {
|
||||
if (tmpfiles) {
|
||||
if (tmpfiles && !opt_save_temps) {
|
||||
for (int i = 0; tmpfiles[i]; i++) {
|
||||
unlink(tmpfiles[i]);
|
||||
}
|
||||
|
@ -350,7 +352,7 @@ static void cleanup(void) {
|
|||
}
|
||||
|
||||
static char *create_tmpfile(void) {
|
||||
char *path = xstrcat(kTmpPath, "chibicc-XXXXXX");
|
||||
char *path = xjoinpaths(kTmpPath, "chibicc-XXXXXX");
|
||||
int fd = mkstemp(path);
|
||||
if (fd == -1) error("mkstemp failed: %s", strerror(errno));
|
||||
close(fd);
|
||||
|
@ -383,6 +385,7 @@ static void run_subprocess(char **argv) {
|
|||
}
|
||||
}
|
||||
if (status != 0) {
|
||||
opt_save_temps = true;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -545,6 +548,7 @@ static void cc1(void) {
|
|||
static void assemble(char *input, char *output) {
|
||||
char *as = getenv("AS");
|
||||
if (!as || !*as) as = "as";
|
||||
/* as = "o//third_party/chibicc/as.com"; */
|
||||
StringArray arr = {};
|
||||
strarray_push(&arr, as);
|
||||
strarray_push(&arr, "-W");
|
||||
|
|
5
third_party/chibicc/chibicc.h
vendored
5
third_party/chibicc/chibicc.h
vendored
|
@ -16,6 +16,7 @@
|
|||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/bsf.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/nexgen32e/crc32.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/stdio/temp.h"
|
||||
|
@ -126,8 +127,8 @@ char *read_file(char *);
|
|||
int read_escaped_char(char **, char *);
|
||||
|
||||
#define UNREACHABLE() error("internal error at %s:%d", __FILE__, __LINE__)
|
||||
#define EQUAL(T, S) equal(T, S, strlen(S))
|
||||
#define CONSUME(R, T, S) consume(R, T, S, strlen(S))
|
||||
#define EQUAL(T, S) equal(T, S, sizeof(S) - 1)
|
||||
#define CONSUME(R, T, S) consume(R, T, S, sizeof(S) - 1)
|
||||
|
||||
//
|
||||
// preprocess.c
|
||||
|
|
13
third_party/chibicc/codegen.c
vendored
13
third_party/chibicc/codegen.c
vendored
|
@ -616,11 +616,9 @@ static bool has_flonum2(Type *ty) {
|
|||
static void push_struct(Type *ty) {
|
||||
int sz = ROUNDUP(ty->size, 8);
|
||||
println("\tsub\t$%d,%%rsp", sz);
|
||||
println("\tmov\t%%rsp,%%rdi");
|
||||
depth += sz / 8;
|
||||
for (int i = 0; i < ty->size; i++) {
|
||||
println("\tmov\t%d(%%rax),%%r10b", i);
|
||||
println("\tmov\t%%r10b,%d(%%rsp)", i);
|
||||
}
|
||||
gen_memcpy(ty->size);
|
||||
}
|
||||
|
||||
static void push_args2(Node *args, bool first_pass) {
|
||||
|
@ -781,7 +779,7 @@ static void copy_ret_buffer(Obj *var) {
|
|||
}
|
||||
} else {
|
||||
char *reg1 = (gp == 0) ? "%al" : "%dl";
|
||||
char *reg2 = (gp == 0) ? "%rax" : "%rdx";
|
||||
char *reg2 = (gp == 0) ? "%rax" : "%rdx"; /* TODO: isn't ax clobbered? */
|
||||
for (int i = 8; i < MIN(16, ty->size); i++) {
|
||||
println("\tmov\t%s,%d(%%rbp)", reg1, var->offset + i);
|
||||
println("\tshr\t$8,%s", reg2);
|
||||
|
@ -2241,7 +2239,7 @@ static void emit_data(Obj *prog) {
|
|||
}
|
||||
print_align(align);
|
||||
println("\t.type\t%s,@object", nameof(var));
|
||||
println("\t.size\t%s,%d", nameof(var), var->ty->size);
|
||||
/* println("\t.size\t%s,%d", nameof(var), var->ty->size); */
|
||||
println("%s:", nameof(var));
|
||||
if (var->init_data) {
|
||||
int pos = 0;
|
||||
|
@ -2425,7 +2423,7 @@ static void emit_text(Obj *prog) {
|
|||
emitlin("\tleave");
|
||||
emitlin("\tret");
|
||||
}
|
||||
println("\t.size\t%s,.-%s", nameof(fn), nameof(fn));
|
||||
/* println("\t.size\t%s,.-%s", nameof(fn), nameof(fn)); */
|
||||
if (fn->is_constructor) {
|
||||
emitlin("\t.section .ctors,\"aw\",@progbits");
|
||||
emitlin("\t.align\t8");
|
||||
|
@ -2448,6 +2446,7 @@ static void emit_staticasms(StaticAsm *a) {
|
|||
void codegen(Obj *prog, FILE *out) {
|
||||
output_stream = out;
|
||||
File **files = get_input_files();
|
||||
println("# -*- mode:unix-assembly -*-");
|
||||
for (int i = 0; files[i]; i++) {
|
||||
println("\t.file\t%d %`'s", files[i]->file_no, files[i]->name);
|
||||
}
|
||||
|
|
3
third_party/chibicc/hashmap.c
vendored
3
third_party/chibicc/hashmap.c
vendored
|
@ -35,8 +35,9 @@ static void rehash(HashMap *map) {
|
|||
map2.capacity = cap;
|
||||
for (int i = 0; i < map->capacity; i++) {
|
||||
HashEntry *ent = &map->buckets[i];
|
||||
if (ent->key && ent->key != TOMBSTONE)
|
||||
if (ent->key && ent->key != TOMBSTONE) {
|
||||
hashmap_put2(&map2, ent->key, ent->keylen, ent->val);
|
||||
}
|
||||
}
|
||||
assert(map2.used == nkeys);
|
||||
*map = map2;
|
||||
|
|
34
third_party/chibicc/hog.s
vendored
34
third_party/chibicc/hog.s
vendored
|
@ -1,34 +0,0 @@
|
|||
.globl _start
|
||||
_start: rep movsb
|
||||
/ add $333333,%rcx
|
||||
/ test %eax,(%rcx) # 85 0001
|
||||
push %r15
|
||||
pop %r15
|
||||
mov %al,%bl
|
||||
mov %eax,%ecx # 89 0301
|
||||
mov %ecx,%eax # 89 0310
|
||||
mov %ecx,(%rbx)
|
||||
mov (%rbx),%ecx
|
||||
mov %xmm0,%xmm1
|
||||
movb $1,(%rax)
|
||||
movl $1,(%rax)
|
||||
movl $1,0xffffff(%rax,%rbx,8)
|
||||
mov $1,%bl
|
||||
mov $123,%r8d
|
||||
/ mov %ebx,%r8d
|
||||
/ mov (%r8),%ebx
|
||||
/ mov %ebx,(%r8)
|
||||
/ movd %eax,%xmm0
|
||||
/ movdqa %xmm0,%xmm8
|
||||
/ movdqa %xmm8,%xmm1
|
||||
/ paddw %xmm8,%xmm1
|
||||
/ paddw %xmm1,%xmm8
|
||||
hlt
|
||||
ret $1
|
||||
|
||||
a: .asciz "ho","ggg"
|
||||
.align 8
|
||||
.section .text.yo
|
||||
.zero 1
|
||||
.byte 1
|
||||
.hidden doge
|
15
third_party/chibicc/parse.c
vendored
15
third_party/chibicc/parse.c
vendored
|
@ -16,6 +16,7 @@
|
|||
// So it is very easy to lookahead arbitrary number of tokens in this
|
||||
// parser.
|
||||
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "third_party/chibicc/chibicc.h"
|
||||
|
||||
typedef struct InitDesg InitDesg;
|
||||
|
@ -577,6 +578,8 @@ static Token *thing_attributes(Token *tok, void *arg) {
|
|||
error_tok(tok, "unknown function attribute");
|
||||
}
|
||||
|
||||
Token *to;
|
||||
|
||||
// declspec = ("void" | "_Bool" | "char" | "short" | "int" | "long"
|
||||
// | "typedef" | "static" | "extern" | "inline"
|
||||
// | "_Thread_local" | "__thread"
|
||||
|
@ -641,6 +644,7 @@ static Type *declspec(Token **rest, Token *tok, VarAttr *attr) {
|
|||
if (attr->is_typedef &&
|
||||
attr->is_static + attr->is_extern + attr->is_inline + attr->is_tls >
|
||||
1) {
|
||||
to = tok;
|
||||
error_tok(tok, "typedef may not be used together with static,"
|
||||
" extern, inline, __thread or _Thread_local");
|
||||
}
|
||||
|
@ -2577,8 +2581,9 @@ static Node *unary(Token **rest, Token *tok) {
|
|||
if (EQUAL(tok, "&")) {
|
||||
Node *lhs = cast(rest, tok->next);
|
||||
add_type(lhs);
|
||||
if (lhs->kind == ND_MEMBER && lhs->member->is_bitfield)
|
||||
if (lhs->kind == ND_MEMBER && lhs->member->is_bitfield) {
|
||||
error_tok(tok, "cannot take address of bitfield");
|
||||
}
|
||||
return new_unary(ND_ADDR, lhs, tok);
|
||||
}
|
||||
if (EQUAL(tok, "*")) {
|
||||
|
@ -2995,13 +3000,13 @@ static Node *primary(Token **rest, Token *tok) {
|
|||
if (node->ty->kind == TY_VLA) return new_var_node(node->ty->vla_size, tok);
|
||||
return new_ulong(node->ty->size, tok);
|
||||
}
|
||||
if (EQUAL(tok, "_Alignof") && EQUAL(tok->next, "(") &&
|
||||
is_typename(tok->next->next)) {
|
||||
if ((EQUAL(tok, "_Alignof") || EQUAL(tok, "__alignof__")) &&
|
||||
EQUAL(tok->next, "(") && is_typename(tok->next->next)) {
|
||||
Type *ty = typename(&tok, tok->next->next);
|
||||
*rest = skip(tok, ')');
|
||||
return new_ulong(ty->align, tok);
|
||||
}
|
||||
if (EQUAL(tok, "_Alignof")) {
|
||||
if (EQUAL(tok, "_Alignof") || EQUAL(tok, "__alignof__")) {
|
||||
Node *node = unary(rest, tok->next);
|
||||
add_type(node);
|
||||
return new_ulong(node->ty->align, tok);
|
||||
|
@ -3338,7 +3343,7 @@ static Token *function(Token *tok, Type *basety, VarAttr *attr) {
|
|||
fn->asmname = ConsumeStringLiteral(&tok, tok);
|
||||
tok = skip(tok, ')');
|
||||
}
|
||||
tok = attribute_list(tok, &attr, thing_attributes);
|
||||
tok = attribute_list(tok, attr, thing_attributes);
|
||||
if (CONSUME(&tok, tok, ";")) return tok;
|
||||
current_fn = fn;
|
||||
locals = NULL;
|
||||
|
|
2
third_party/chibicc/preprocess.c
vendored
2
third_party/chibicc/preprocess.c
vendored
|
@ -686,7 +686,7 @@ static char *detect_include_guard(Token *tok) {
|
|||
char *macro = strndup(tok->loc, tok->len);
|
||||
tok = tok->next;
|
||||
if (!is_hash(tok) || !EQUAL(tok->next, "define") ||
|
||||
!EQUAL(tok->next->next, macro))
|
||||
!equal(tok->next->next, macro, strlen(macro)))
|
||||
return NULL;
|
||||
// Read until the end of the file.
|
||||
while (tok->kind != TK_EOF) {
|
||||
|
|
23
third_party/chibicc/test/bitfield_test.c
vendored
23
third_party/chibicc/test/bitfield_test.c
vendored
|
@ -1,5 +1,7 @@
|
|||
#include "third_party/chibicc/test/test.h"
|
||||
|
||||
#define TYPE_SIGNED(type) (((type)-1) < 0)
|
||||
|
||||
struct {
|
||||
char a;
|
||||
int b : 5;
|
||||
|
@ -7,6 +9,27 @@ struct {
|
|||
} g45 = {1, 2, 3}, g46 = {};
|
||||
|
||||
int main() {
|
||||
|
||||
/* NOTE: Consistent w/ GCC (but MSVC would fail this) */
|
||||
ASSERT(1, 2 == ({
|
||||
struct {
|
||||
enum { a, b, c } e : 2;
|
||||
} x = {
|
||||
.e = 2,
|
||||
};
|
||||
x.e;
|
||||
}));
|
||||
|
||||
/* NOTE: GCC forbids typeof(bitfield). */
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
enum { a, b, c } e : 2;
|
||||
} x = {
|
||||
.e = 2,
|
||||
};
|
||||
TYPE_SIGNED(typeof(x.e));
|
||||
}));
|
||||
|
||||
ASSERT(4, sizeof(struct { int x : 1; }));
|
||||
ASSERT(8, sizeof(struct { long x : 1; }));
|
||||
|
||||
|
|
50
third_party/chibicc/test/dce_test.c
vendored
50
third_party/chibicc/test/dce_test.c
vendored
|
@ -1,42 +1,26 @@
|
|||
#include "third_party/chibicc/test/test.h"
|
||||
|
||||
int x;
|
||||
#define CRASH \
|
||||
({ \
|
||||
asm(".err"); \
|
||||
666; \
|
||||
})
|
||||
|
||||
int main(void) {
|
||||
|
||||
if (0) {
|
||||
asm(".error \"the assembler shall fail\"");
|
||||
return CRASH;
|
||||
}
|
||||
|
||||
x = 1 ? 777 : ({
|
||||
asm(".error \"the system is down\"");
|
||||
666;
|
||||
});
|
||||
ASSERT(777, x);
|
||||
if (1) {
|
||||
} else {
|
||||
return CRASH;
|
||||
}
|
||||
|
||||
x = 0;
|
||||
x = 777 ?: ({
|
||||
asm(".error \"the system is down\"");
|
||||
666;
|
||||
});
|
||||
|
||||
x = 0;
|
||||
x = __builtin_popcount(strlen("hihi")) == 1 ? 777 : ({
|
||||
asm(".error \"the system is down\"");
|
||||
666;
|
||||
});
|
||||
ASSERT(777, x);
|
||||
|
||||
x = 0;
|
||||
x = strpbrk("hihi", "ei") ? 777 : ({
|
||||
asm(".error \"the system is down!\"");
|
||||
666;
|
||||
});
|
||||
ASSERT(777, x);
|
||||
|
||||
x = 0;
|
||||
x = !__builtin_strpbrk("HELLO\n", "bxdinupo") ? 777 : ({
|
||||
asm(".error \"the system is down\"");
|
||||
666;
|
||||
});
|
||||
ASSERT(777, x);
|
||||
ASSERT(777, 777 ?: CRASH);
|
||||
ASSERT(777, 1 ? 777 : CRASH);
|
||||
ASSERT(777, 0 ? CRASH : 777);
|
||||
ASSERT(777, __builtin_popcount(__builtin_strlen("hihi")) == 1 ? 777 : CRASH);
|
||||
ASSERT(777, !__builtin_strpbrk("HELLO\n", "bxdinupo") ? 777 : CRASH);
|
||||
ASSERT(777, strpbrk("hihi", "ei") ? 777 : CRASH);
|
||||
}
|
||||
|
|
802
third_party/chibicc/test/initializer_test.c
vendored
802
third_party/chibicc/test/initializer_test.c
vendored
|
@ -1,802 +0,0 @@
|
|||
#include "third_party/chibicc/test/test.h"
|
||||
|
||||
char g3 = 3;
|
||||
short g4 = 4;
|
||||
int g5 = 5;
|
||||
long g6 = 6;
|
||||
int g9[3] = {0, 1, 2};
|
||||
struct {
|
||||
char a;
|
||||
int b;
|
||||
} g11[2] = {{1, 2}, {3, 4}};
|
||||
struct {
|
||||
int a[2];
|
||||
} g12[2] = {{{1, 2}}};
|
||||
union {
|
||||
int a;
|
||||
char b[8];
|
||||
} g13[2] = {0x01020304, 0x05060708};
|
||||
char g17[] = "foobar";
|
||||
char g18[10] = "foobar";
|
||||
char g19[3] = "foobar";
|
||||
char *g20 = g17 + 0;
|
||||
char *g21 = g17 + 3;
|
||||
char *g22 = &g17 - 3;
|
||||
char *g23[] = {g17 + 0, g17 + 3, g17 - 3};
|
||||
int g24 = 3;
|
||||
int *g25 = &g24;
|
||||
int g26[3] = {1, 2, 3};
|
||||
int *g27 = g26 + 1;
|
||||
int *g28 = &g11[1].a;
|
||||
long g29 = (long)(long)g26;
|
||||
struct {
|
||||
struct {
|
||||
int a[3];
|
||||
} a;
|
||||
} g30 = {{{1, 2, 3}}};
|
||||
int *g31 = g30.a.a;
|
||||
struct {
|
||||
int a[2];
|
||||
} g40[2] = {{1, 2}, 3, 4};
|
||||
struct {
|
||||
int a[2];
|
||||
} g41[2] = {1, 2, 3, 4};
|
||||
char g43[][4] = {'f', 'o', 'o', 0, 'b', 'a', 'r', 0};
|
||||
char *g44 = {"foo"};
|
||||
union {
|
||||
int a;
|
||||
char b[4];
|
||||
} g50 = {.b[2] = 0x12};
|
||||
union {
|
||||
int a;
|
||||
} g51[2] = {};
|
||||
|
||||
typedef char T60[];
|
||||
T60 g60 = {1, 2, 3};
|
||||
T60 g61 = {1, 2, 3, 4, 5, 6};
|
||||
|
||||
typedef struct {
|
||||
char a, b[];
|
||||
} T65;
|
||||
T65 g65 = {'f', 'o', 'o', 0};
|
||||
T65 g66 = {'f', 'o', 'o', 'b', 'a', 'r', 0};
|
||||
|
||||
int main() {
|
||||
ASSERT(1, ({
|
||||
int x[3] = {1, 2, 3};
|
||||
x[0];
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
int x[3] = {1, 2, 3};
|
||||
x[1];
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
int x[3] = {1, 2, 3};
|
||||
x[2];
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
int x[3] = {1, 2, 3};
|
||||
x[2];
|
||||
}));
|
||||
|
||||
ASSERT(2, ({
|
||||
int x[2][3] = {{1, 2, 3}, {4, 5, 6}};
|
||||
x[0][1];
|
||||
}));
|
||||
ASSERT(4, ({
|
||||
int x[2][3] = {{1, 2, 3}, {4, 5, 6}};
|
||||
x[1][0];
|
||||
}));
|
||||
ASSERT(6, ({
|
||||
int x[2][3] = {{1, 2, 3}, {4, 5, 6}};
|
||||
x[1][2];
|
||||
}));
|
||||
|
||||
ASSERT(0, ({
|
||||
int x[3] = {};
|
||||
x[0];
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
int x[3] = {};
|
||||
x[1];
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
int x[3] = {};
|
||||
x[2];
|
||||
}));
|
||||
|
||||
ASSERT(2, ({
|
||||
int x[2][3] = {{1, 2}};
|
||||
x[0][1];
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
int x[2][3] = {{1, 2}};
|
||||
x[1][0];
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
int x[2][3] = {{1, 2}};
|
||||
x[1][2];
|
||||
}));
|
||||
|
||||
ASSERT('a', ({
|
||||
char x[4] = "abc";
|
||||
x[0];
|
||||
}));
|
||||
ASSERT('c', ({
|
||||
char x[4] = "abc";
|
||||
x[2];
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
char x[4] = "abc";
|
||||
x[3];
|
||||
}));
|
||||
ASSERT('a', ({
|
||||
char x[2][4] = {"abc", "def"};
|
||||
x[0][0];
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
char x[2][4] = {"abc", "def"};
|
||||
x[0][3];
|
||||
}));
|
||||
ASSERT('d', ({
|
||||
char x[2][4] = {"abc", "def"};
|
||||
x[1][0];
|
||||
}));
|
||||
ASSERT('f', ({
|
||||
char x[2][4] = {"abc", "def"};
|
||||
x[1][2];
|
||||
}));
|
||||
|
||||
ASSERT(4, ({
|
||||
int x[] = {1, 2, 3, 4};
|
||||
x[3];
|
||||
}));
|
||||
ASSERT(16, ({
|
||||
int x[] = {1, 2, 3, 4};
|
||||
sizeof(x);
|
||||
}));
|
||||
ASSERT(4, ({
|
||||
char x[] = "foo";
|
||||
sizeof(x);
|
||||
}));
|
||||
|
||||
ASSERT(4, ({
|
||||
typedef char T[];
|
||||
T x = "foo";
|
||||
T y = "x";
|
||||
sizeof(x);
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
typedef char T[];
|
||||
T x = "foo";
|
||||
T y = "x";
|
||||
sizeof(y);
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
typedef char T[];
|
||||
T x = "x";
|
||||
T y = "foo";
|
||||
sizeof(x);
|
||||
}));
|
||||
ASSERT(4, ({
|
||||
typedef char T[];
|
||||
T x = "x";
|
||||
T y = "foo";
|
||||
sizeof(y);
|
||||
}));
|
||||
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
} x = {1, 2, 3};
|
||||
x.a;
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
} x = {1, 2, 3};
|
||||
x.b;
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
} x = {1, 2, 3};
|
||||
x.c;
|
||||
}));
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
} x = {1};
|
||||
x.a;
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
} x = {1};
|
||||
x.b;
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
} x = {1};
|
||||
x.c;
|
||||
}));
|
||||
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} x[2] = {{1, 2}, {3, 4}};
|
||||
x[0].a;
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} x[2] = {{1, 2}, {3, 4}};
|
||||
x[0].b;
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} x[2] = {{1, 2}, {3, 4}};
|
||||
x[1].a;
|
||||
}));
|
||||
ASSERT(4, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} x[2] = {{1, 2}, {3, 4}};
|
||||
x[1].b;
|
||||
}));
|
||||
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} x[2] = {{1, 2}};
|
||||
x[1].b;
|
||||
}));
|
||||
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} x = {};
|
||||
x.a;
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} x = {};
|
||||
x.b;
|
||||
}));
|
||||
|
||||
ASSERT(5, ({
|
||||
typedef struct {
|
||||
int a, b, c, d, e, f;
|
||||
} T;
|
||||
T x = {1, 2, 3, 4, 5, 6};
|
||||
T y;
|
||||
y = x;
|
||||
y.e;
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
typedef struct {
|
||||
int a, b;
|
||||
} T;
|
||||
T x = {1, 2};
|
||||
T y, z;
|
||||
z = y = x;
|
||||
z.b;
|
||||
}));
|
||||
|
||||
ASSERT(1, ({
|
||||
typedef struct {
|
||||
int a, b;
|
||||
} T;
|
||||
T x = {1, 2};
|
||||
T y = x;
|
||||
y.a;
|
||||
}));
|
||||
|
||||
ASSERT(4, ({
|
||||
union {
|
||||
int a;
|
||||
char b[4];
|
||||
} x = {0x01020304};
|
||||
x.b[0];
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
union {
|
||||
int a;
|
||||
char b[4];
|
||||
} x = {0x01020304};
|
||||
x.b[1];
|
||||
}));
|
||||
|
||||
ASSERT(0x01020304, ({
|
||||
union {
|
||||
struct {
|
||||
char a, b, c, d;
|
||||
} e;
|
||||
int f;
|
||||
} x = {{4, 3, 2, 1}};
|
||||
x.f;
|
||||
}));
|
||||
|
||||
ASSERT(3, g3);
|
||||
ASSERT(4, g4);
|
||||
ASSERT(5, g5);
|
||||
ASSERT(6, g6);
|
||||
|
||||
ASSERT(0, g9[0]);
|
||||
ASSERT(1, g9[1]);
|
||||
ASSERT(2, g9[2]);
|
||||
|
||||
ASSERT(1, g11[0].a);
|
||||
ASSERT(2, g11[0].b);
|
||||
ASSERT(3, g11[1].a);
|
||||
ASSERT(4, g11[1].b);
|
||||
|
||||
ASSERT(1, g12[0].a[0]);
|
||||
ASSERT(2, g12[0].a[1]);
|
||||
ASSERT(0, g12[1].a[0]);
|
||||
ASSERT(0, g12[1].a[1]);
|
||||
|
||||
ASSERT(4, g13[0].b[0]);
|
||||
ASSERT(3, g13[0].b[1]);
|
||||
ASSERT(8, g13[1].b[0]);
|
||||
ASSERT(7, g13[1].b[1]);
|
||||
|
||||
ASSERT(7, sizeof(g17));
|
||||
ASSERT(10, sizeof(g18));
|
||||
ASSERT(3, sizeof(g19));
|
||||
|
||||
ASSERT(0, memcmp(g17, "foobar", 7));
|
||||
ASSERT(0, memcmp(g18, "foobar\0\0\0", 10));
|
||||
ASSERT(0, memcmp(g19, "foo", 3));
|
||||
|
||||
ASSERT(0, strcmp(g20, "foobar"));
|
||||
ASSERT(0, strcmp(g21, "bar"));
|
||||
ASSERT(0, strcmp(g22 + 3, "foobar"));
|
||||
|
||||
ASSERT(0, strcmp(g23[0], "foobar"));
|
||||
ASSERT(0, strcmp(g23[1], "bar"));
|
||||
ASSERT(0, strcmp(g23[2] + 3, "foobar"));
|
||||
|
||||
ASSERT(3, g24);
|
||||
ASSERT(3, *g25);
|
||||
ASSERT(2, *g27);
|
||||
ASSERT(3, *g28);
|
||||
ASSERT(1, *(int *)g29);
|
||||
|
||||
ASSERT(1, g31[0]);
|
||||
ASSERT(2, g31[1]);
|
||||
ASSERT(3, g31[2]);
|
||||
|
||||
ASSERT(1, g40[0].a[0]);
|
||||
ASSERT(2, g40[0].a[1]);
|
||||
ASSERT(3, g40[1].a[0]);
|
||||
ASSERT(4, g40[1].a[1]);
|
||||
|
||||
ASSERT(1, g41[0].a[0]);
|
||||
ASSERT(2, g41[0].a[1]);
|
||||
ASSERT(3, g41[1].a[0]);
|
||||
ASSERT(4, g41[1].a[1]);
|
||||
|
||||
ASSERT(0, ({
|
||||
int x[2][3] = {0, 1, 2, 3, 4, 5};
|
||||
x[0][0];
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
int x[2][3] = {0, 1, 2, 3, 4, 5};
|
||||
x[1][0];
|
||||
}));
|
||||
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} x[2] = {0, 1, 2, 3};
|
||||
x[0].a;
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
struct {
|
||||
int a;
|
||||
int b;
|
||||
} x[2] = {0, 1, 2, 3};
|
||||
x[1].a;
|
||||
}));
|
||||
|
||||
ASSERT(0, strcmp(g43[0], "foo"));
|
||||
ASSERT(0, strcmp(g43[1], "bar"));
|
||||
ASSERT(0, strcmp(g44, "foo"));
|
||||
|
||||
ASSERT(3, ({
|
||||
int a[] = {
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
};
|
||||
a[2];
|
||||
}));
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
int a, b, c;
|
||||
} x = {
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
};
|
||||
x.a;
|
||||
}));
|
||||
ASSERT(1, ({
|
||||
union {
|
||||
int a;
|
||||
char b;
|
||||
} x = {
|
||||
1,
|
||||
};
|
||||
x.a;
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
enum {
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
};
|
||||
z;
|
||||
}));
|
||||
|
||||
ASSERT(3, sizeof(g60));
|
||||
ASSERT(6, sizeof(g61));
|
||||
|
||||
ASSERT(4, sizeof(g65));
|
||||
ASSERT(7, sizeof(g66));
|
||||
ASSERT(0, strcmp(g65.b, "oo"));
|
||||
ASSERT(0, strcmp(g66.b, "oobar"));
|
||||
|
||||
ASSERT(4, ({
|
||||
int x[3] = {1, 2, 3, [0] = 4, 5};
|
||||
x[0];
|
||||
}));
|
||||
ASSERT(5, ({
|
||||
int x[3] = {1, 2, 3, [0] = 4, 5};
|
||||
x[1];
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
int x[3] = {1, 2, 3, [0] = 4, 5};
|
||||
x[2];
|
||||
}));
|
||||
|
||||
ASSERT(10, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0][1] = 7, 8, [0] = 9, [0] = 10, 11, [1][0] = 12};
|
||||
x[0][0];
|
||||
}));
|
||||
ASSERT(11, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0][1] = 7, 8, [0] = 9, [0] = 10, 11, [1][0] = 12};
|
||||
x[0][1];
|
||||
}));
|
||||
ASSERT(8, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0][1] = 7, 8, [0] = 9, [0] = 10, 11, [1][0] = 12};
|
||||
x[0][2];
|
||||
}));
|
||||
ASSERT(12, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0][1] = 7, 8, [0] = 9, [0] = 10, 11, [1][0] = 12};
|
||||
x[1][0];
|
||||
}));
|
||||
ASSERT(5, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0][1] = 7, 8, [0] = 9, [0] = 10, 11, [1][0] = 12};
|
||||
x[1][1];
|
||||
}));
|
||||
ASSERT(6, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0][1] = 7, 8, [0] = 9, [0] = 10, 11, [1][0] = 12};
|
||||
x[1][2];
|
||||
}));
|
||||
|
||||
ASSERT(7, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0] = {7, 8}, 9, 10};
|
||||
x[0][0];
|
||||
}));
|
||||
ASSERT(8, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0] = {7, 8}, 9, 10};
|
||||
x[0][1];
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0] = {7, 8}, 9, 10};
|
||||
x[0][2];
|
||||
}));
|
||||
ASSERT(9, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0] = {7, 8}, 9, 10};
|
||||
x[1][0];
|
||||
}));
|
||||
ASSERT(10, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0] = {7, 8}, 9, 10};
|
||||
x[1][1];
|
||||
}));
|
||||
ASSERT(6, ({
|
||||
int x[2][3] = {1, 2, 3, 4, 5, 6, [0] = {7, 8}, 9, 10};
|
||||
x[1][2];
|
||||
}));
|
||||
|
||||
ASSERT(7, ((int[10]){[3] = 7})[3]);
|
||||
ASSERT(0, ((int[10]){[3] = 7})[4]);
|
||||
|
||||
ASSERT(10, ({
|
||||
char x[] = {[10 - 3] = 1, 2, 3};
|
||||
sizeof(x);
|
||||
}));
|
||||
ASSERT(20, ({
|
||||
char x[][2] = {[8][1] = 1, 2};
|
||||
sizeof(x);
|
||||
}));
|
||||
|
||||
ASSERT(3, sizeof(g60));
|
||||
ASSERT(6, sizeof(g61));
|
||||
|
||||
ASSERT(4, sizeof(g65));
|
||||
ASSERT(7, sizeof(g66));
|
||||
ASSERT(0, strcmp(g65.b, "oo"));
|
||||
ASSERT(0, strcmp(g66.b, "oobar"));
|
||||
|
||||
ASSERT(7, ((int[10]){[3] 7})[3]);
|
||||
ASSERT(0, ((int[10]){[3] 7})[4]);
|
||||
|
||||
ASSERT(4, ({
|
||||
struct {
|
||||
int a, b;
|
||||
} x = {1, 2, .b = 3, .a = 4};
|
||||
x.a;
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
struct {
|
||||
int a, b;
|
||||
} x = {1, 2, .b = 3, .a = 4};
|
||||
x.b;
|
||||
}));
|
||||
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
struct {
|
||||
int a, b;
|
||||
} c;
|
||||
} x = {.c = 1, 2};
|
||||
x.c.a;
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
struct {
|
||||
struct {
|
||||
int a, b;
|
||||
} c;
|
||||
} x = {.c = 1, 2};
|
||||
x.c.b;
|
||||
}));
|
||||
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
struct {
|
||||
int a, b;
|
||||
} c;
|
||||
} x = {.c.b = 1};
|
||||
x.c.a;
|
||||
}));
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
struct {
|
||||
int a, b;
|
||||
} c;
|
||||
} x = {.c.b = 1};
|
||||
x.c.b;
|
||||
}));
|
||||
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
int a[2];
|
||||
} x = {.a = 1, 2};
|
||||
x.a[0];
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
struct {
|
||||
int a[2];
|
||||
} x = {.a = 1, 2};
|
||||
x.a[1];
|
||||
}));
|
||||
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
int a[2];
|
||||
} x = {.a[1] = 1};
|
||||
x.a[0];
|
||||
}));
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
int a[2];
|
||||
} x = {.a[1] = 1};
|
||||
x.a[1];
|
||||
}));
|
||||
|
||||
ASSERT(3, ({
|
||||
struct {
|
||||
int a, b;
|
||||
} x[] = {
|
||||
[1].b = 1,
|
||||
2,
|
||||
[0] = 3,
|
||||
4,
|
||||
};
|
||||
x[0].a;
|
||||
}));
|
||||
ASSERT(4, ({
|
||||
struct {
|
||||
int a, b;
|
||||
} x[] = {
|
||||
[1].b = 1,
|
||||
2,
|
||||
[0] = 3,
|
||||
4,
|
||||
};
|
||||
x[0].b;
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
int a, b;
|
||||
} x[] = {
|
||||
[1].b = 1,
|
||||
2,
|
||||
[0] = 3,
|
||||
4,
|
||||
};
|
||||
x[1].a;
|
||||
}));
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
int a, b;
|
||||
} x[] = {
|
||||
[1].b = 1,
|
||||
2,
|
||||
[0] = 3,
|
||||
4,
|
||||
};
|
||||
x[1].b;
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
struct {
|
||||
int a, b;
|
||||
} x[] = {
|
||||
[1].b = 1,
|
||||
2,
|
||||
[0] = 3,
|
||||
4,
|
||||
};
|
||||
x[2].a;
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
struct {
|
||||
int a, b;
|
||||
} x[] = {
|
||||
[1].b = 1,
|
||||
2,
|
||||
[0] = 3,
|
||||
4,
|
||||
};
|
||||
x[2].b;
|
||||
}));
|
||||
|
||||
ASSERT(1, ({
|
||||
typedef struct {
|
||||
int a, b;
|
||||
} T;
|
||||
T x = {1, 2};
|
||||
T y[] = {x};
|
||||
y[0].a;
|
||||
}));
|
||||
ASSERT(2, ({
|
||||
typedef struct {
|
||||
int a, b;
|
||||
} T;
|
||||
T x = {1, 2};
|
||||
T y[] = {x};
|
||||
y[0].b;
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
typedef struct {
|
||||
int a, b;
|
||||
} T;
|
||||
T x = {1, 2};
|
||||
T y[] = {x, [0].b = 3};
|
||||
y[0].a;
|
||||
}));
|
||||
ASSERT(3, ({
|
||||
typedef struct {
|
||||
int a, b;
|
||||
} T;
|
||||
T x = {1, 2};
|
||||
T y[] = {x, [0].b = 3};
|
||||
y[0].b;
|
||||
}));
|
||||
|
||||
ASSERT(5, ((struct { int a, b, c; }){.c = 5}).c);
|
||||
ASSERT(0, ((struct { int a, b, c; }){.c = 5}).a);
|
||||
|
||||
ASSERT(0x00ff, ({
|
||||
union {
|
||||
unsigned short a;
|
||||
char b[2];
|
||||
} x = {.b[0] = 0xff};
|
||||
x.a;
|
||||
}));
|
||||
ASSERT(0xff00, ({
|
||||
union {
|
||||
unsigned short a;
|
||||
char b[2];
|
||||
} x = {.b[1] = 0xff};
|
||||
x.a;
|
||||
}));
|
||||
|
||||
ASSERT(0x00120000, g50.a);
|
||||
ASSERT(0, g51[0].a);
|
||||
ASSERT(0, g51[1].a);
|
||||
|
||||
ASSERT(1, ({
|
||||
struct {
|
||||
struct {
|
||||
int a;
|
||||
struct {
|
||||
int b;
|
||||
};
|
||||
};
|
||||
int c;
|
||||
} x = {1, 2, 3, .b = 4, 5};
|
||||
x.a;
|
||||
}));
|
||||
ASSERT(4, ({
|
||||
struct {
|
||||
struct {
|
||||
int a;
|
||||
struct {
|
||||
int b;
|
||||
};
|
||||
};
|
||||
int c;
|
||||
} x = {1, 2, 3, .b = 4, 5};
|
||||
x.b;
|
||||
}));
|
||||
ASSERT(5, ({
|
||||
struct {
|
||||
struct {
|
||||
int a;
|
||||
struct {
|
||||
int b;
|
||||
};
|
||||
};
|
||||
int c;
|
||||
} x = {1, 2, 3, .b = 4, 5};
|
||||
x.c;
|
||||
}));
|
||||
|
||||
ASSERT(16, ({
|
||||
char x[] = {[2 ... 10] = 'a', [7] = 'b', [15 ... 15] = 'c', [3 ... 5] = 'd'};
|
||||
sizeof(x);
|
||||
}));
|
||||
ASSERT(0, ({
|
||||
char x[] = {[2 ... 10] = 'a', [7] = 'b', [15 ... 15] = 'c', [3 ... 5] = 'd'};
|
||||
memcmp(x, "\0\0adddabaaa\0\0\0\0c", 16);
|
||||
}));
|
||||
|
||||
return 0;
|
||||
}
|
4
third_party/chibicc/test/sizeof_test.c
vendored
4
third_party/chibicc/test/sizeof_test.c
vendored
|
@ -109,5 +109,9 @@ int main() {
|
|||
|
||||
ASSERT(1, sizeof(main));
|
||||
|
||||
ASSERT(1, sizeof(""));
|
||||
ASSERT(2, sizeof("h"));
|
||||
ASSERT(6, sizeof("hello"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
2
third_party/chibicc/tokenize.c
vendored
2
third_party/chibicc/tokenize.c
vendored
|
@ -1,6 +1,6 @@
|
|||
#include "third_party/chibicc/chibicc.h"
|
||||
|
||||
#define LOOKINGAT(TOK, OP) (!memcmp(TOK, OP, strlen(OP)))
|
||||
#define LOOKINGAT(TOK, OP) (!memcmp(TOK, OP, sizeof(OP) - 1))
|
||||
|
||||
// Input file
|
||||
static File *current_file;
|
||||
|
|
4
third_party/chibicc/type.c
vendored
4
third_party/chibicc/type.c
vendored
|
@ -113,7 +113,9 @@ Type *vla_of(Type *base, Node *len) {
|
|||
}
|
||||
|
||||
Type *enum_type(void) {
|
||||
return new_type(TY_ENUM, 4, 4);
|
||||
Type *ty = new_type(TY_ENUM, 4, 4);
|
||||
ty->is_unsigned = true;
|
||||
return ty;
|
||||
}
|
||||
|
||||
Type *struct_type(void) {
|
||||
|
|
183
third_party/compiler_rt/clear_cache.c
vendored
183
third_party/compiler_rt/clear_cache.c
vendored
|
@ -1,183 +0,0 @@
|
|||
/* clang-format off */
|
||||
/* ===-- clear_cache.c - Implement __clear_cache ---------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
STATIC_YOINK("huge_compiler_rt_license");
|
||||
|
||||
#include "third_party/compiler_rt/int_lib.h"
|
||||
|
||||
#if __APPLE__
|
||||
#include <libkern/OSCacheControl.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
/* Forward declare Win32 APIs since the GCC mode driver does not handle the
|
||||
newer SDKs as well as needed. */
|
||||
uint32_t FlushInstructionCache(uintptr_t hProcess, void *lpBaseAddress,
|
||||
uintptr_t dwSize);
|
||||
uintptr_t GetCurrentProcess(void);
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(__mips__)
|
||||
#if defined(__ANDROID__) && defined(__LP64__)
|
||||
/*
|
||||
* clear_mips_cache - Invalidates instruction cache for Mips.
|
||||
*/
|
||||
static void clear_mips_cache(const void* Addr, size_t Size) {
|
||||
__asm__ volatile (
|
||||
".set push\n"
|
||||
".set noreorder\n"
|
||||
".set noat\n"
|
||||
"beq %[Size], $zero, 20f\n" /* If size == 0, branch around. */
|
||||
"nop\n"
|
||||
"daddu %[Size], %[Addr], %[Size]\n" /* Calculate end address + 1 */
|
||||
"rdhwr $v0, $1\n" /* Get step size for SYNCI.
|
||||
$1 is $HW_SYNCI_Step */
|
||||
"beq $v0, $zero, 20f\n" /* If no caches require
|
||||
synchronization, branch
|
||||
around. */
|
||||
"nop\n"
|
||||
"10:\n"
|
||||
"synci 0(%[Addr])\n" /* Synchronize all caches around
|
||||
address. */
|
||||
"daddu %[Addr], %[Addr], $v0\n" /* Add step size. */
|
||||
"sltu $at, %[Addr], %[Size]\n" /* Compare current with end
|
||||
address. */
|
||||
"bne $at, $zero, 10b\n" /* Branch if more to do. */
|
||||
"nop\n"
|
||||
"sync\n" /* Clear memory hazards. */
|
||||
"20:\n"
|
||||
"bal 30f\n"
|
||||
"nop\n"
|
||||
"30:\n"
|
||||
"daddiu $ra, $ra, 12\n" /* $ra has a value of $pc here.
|
||||
Add offset of 12 to point to the
|
||||
instruction after the last nop.
|
||||
*/
|
||||
"jr.hb $ra\n" /* Return, clearing instruction
|
||||
hazards. */
|
||||
"nop\n"
|
||||
".set pop\n"
|
||||
: [Addr] "+r"(Addr), [Size] "+r"(Size)
|
||||
:: "at", "ra", "v0", "memory"
|
||||
);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The compiler generates calls to __clear_cache() when creating
|
||||
* trampoline functions on the stack for use with nested functions.
|
||||
* It is expected to invalidate the instruction cache for the
|
||||
* specified range.
|
||||
*/
|
||||
|
||||
void __clear_cache(void *start, void *end) {
|
||||
#if __i386__ || __x86_64__ || defined(_M_IX86) || defined(_M_X64)
|
||||
/*
|
||||
* Intel processors have a unified instruction and data cache
|
||||
* so there is nothing to do
|
||||
*/
|
||||
#elif defined(_WIN32) && (defined(__arm__) || defined(__aarch64__))
|
||||
FlushInstructionCache(GetCurrentProcess(), start, end - start);
|
||||
#elif defined(__arm__) && !defined(__APPLE__)
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
struct arm_sync_icache_args arg;
|
||||
|
||||
arg.addr = (uintptr_t)start;
|
||||
arg.len = (uintptr_t)end - (uintptr_t)start;
|
||||
|
||||
sysarch(ARM_SYNC_ICACHE, &arg);
|
||||
#elif defined(__linux__)
|
||||
/*
|
||||
* We used to include asm/unistd.h for the __ARM_NR_cacheflush define, but
|
||||
* it also brought many other unused defines, as well as a dependency on
|
||||
* kernel headers to be installed.
|
||||
*
|
||||
* This value is stable at least since Linux 3.13 and should remain so for
|
||||
* compatibility reasons, warranting it's re-definition here.
|
||||
*/
|
||||
#define __ARM_NR_cacheflush 0x0f0002
|
||||
register int start_reg __asm("r0") = (int) (intptr_t) start;
|
||||
const register int end_reg __asm("r1") = (int) (intptr_t) end;
|
||||
const register int flags __asm("r2") = 0;
|
||||
const register int syscall_nr __asm("r7") = __ARM_NR_cacheflush;
|
||||
__asm __volatile("svc 0x0"
|
||||
: "=r"(start_reg)
|
||||
: "r"(syscall_nr), "r"(start_reg), "r"(end_reg),
|
||||
"r"(flags));
|
||||
assert(start_reg == 0 && "Cache flush syscall failed.");
|
||||
#else
|
||||
compilerrt_abort();
|
||||
#endif
|
||||
#elif defined(__linux__) && defined(__mips__)
|
||||
const uintptr_t start_int = (uintptr_t) start;
|
||||
const uintptr_t end_int = (uintptr_t) end;
|
||||
#if defined(__ANDROID__) && defined(__LP64__)
|
||||
// Call synci implementation for short address range.
|
||||
const uintptr_t address_range_limit = 256;
|
||||
if ((end_int - start_int) <= address_range_limit) {
|
||||
clear_mips_cache(start, (end_int - start_int));
|
||||
} else {
|
||||
syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE);
|
||||
}
|
||||
#else
|
||||
syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE);
|
||||
#endif
|
||||
#elif defined(__mips__) && defined(__OpenBSD__)
|
||||
cacheflush(start, (uintptr_t)end - (uintptr_t)start, BCACHE);
|
||||
#elif defined(__aarch64__) && !defined(__APPLE__)
|
||||
uint64_t xstart = (uint64_t)(uintptr_t) start;
|
||||
uint64_t xend = (uint64_t)(uintptr_t) end;
|
||||
uint64_t addr;
|
||||
|
||||
// Get Cache Type Info
|
||||
uint64_t ctr_el0;
|
||||
__asm __volatile("mrs %0, ctr_el0" : "=r"(ctr_el0));
|
||||
|
||||
/*
|
||||
* dc & ic instructions must use 64bit registers so we don't use
|
||||
* uintptr_t in case this runs in an IPL32 environment.
|
||||
*/
|
||||
const size_t dcache_line_size = 4 << ((ctr_el0 >> 16) & 15);
|
||||
for (addr = xstart & ~(dcache_line_size - 1); addr < xend;
|
||||
addr += dcache_line_size)
|
||||
__asm __volatile("dc cvau, %0" :: "r"(addr));
|
||||
__asm __volatile("dsb ish");
|
||||
|
||||
const size_t icache_line_size = 4 << ((ctr_el0 >> 0) & 15);
|
||||
for (addr = xstart & ~(icache_line_size - 1); addr < xend;
|
||||
addr += icache_line_size)
|
||||
__asm __volatile("ic ivau, %0" :: "r"(addr));
|
||||
__asm __volatile("isb sy");
|
||||
#elif defined (__powerpc64__)
|
||||
const size_t line_size = 32;
|
||||
const size_t len = (uintptr_t)end - (uintptr_t)start;
|
||||
|
||||
const uintptr_t mask = ~(line_size - 1);
|
||||
const uintptr_t start_line = ((uintptr_t)start) & mask;
|
||||
const uintptr_t end_line = ((uintptr_t)start + len + line_size - 1) & mask;
|
||||
|
||||
for (uintptr_t line = start_line; line < end_line; line += line_size)
|
||||
__asm__ volatile("dcbf 0, %0" : : "r"(line));
|
||||
__asm__ volatile("sync");
|
||||
|
||||
for (uintptr_t line = start_line; line < end_line; line += line_size)
|
||||
__asm__ volatile("icbi 0, %0" : : "r"(line));
|
||||
__asm__ volatile("isync");
|
||||
#else
|
||||
#if __APPLE__
|
||||
/* On Darwin, sys_icache_invalidate() provides this functionality */
|
||||
sys_icache_invalidate(start, end-start);
|
||||
#else
|
||||
compilerrt_abort();
|
||||
#endif
|
||||
#endif
|
||||
}
|
51
third_party/compiler_rt/trampoline_setup.c
vendored
51
third_party/compiler_rt/trampoline_setup.c
vendored
|
@ -1,51 +0,0 @@
|
|||
/* clang-format off */
|
||||
/* ===----- trampoline_setup.c - Implement __trampoline_setup -------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
STATIC_YOINK("huge_compiler_rt_license");
|
||||
|
||||
#include "third_party/compiler_rt/int_lib.h"
|
||||
|
||||
extern void __clear_cache(void* start, void* end);
|
||||
|
||||
/*
|
||||
* The ppc compiler generates calls to __trampoline_setup() when creating
|
||||
* trampoline functions on the stack for use with nested functions.
|
||||
* This function creates a custom 40-byte trampoline function on the stack
|
||||
* which loads r11 with a pointer to the outer function's locals
|
||||
* and then jumps to the target nested function.
|
||||
*/
|
||||
|
||||
#if __ppc__ && !defined(__powerpc64__)
|
||||
COMPILER_RT_ABI void
|
||||
__trampoline_setup(uint32_t* trampOnStack, int trampSizeAllocated,
|
||||
const void* realFunc, void* localsPtr)
|
||||
{
|
||||
/* should never happen, but if compiler did not allocate */
|
||||
/* enough space on stack for the trampoline, abort */
|
||||
if ( trampSizeAllocated < 40 )
|
||||
compilerrt_abort();
|
||||
|
||||
/* create trampoline */
|
||||
trampOnStack[0] = 0x7c0802a6; /* mflr r0 */
|
||||
trampOnStack[1] = 0x4800000d; /* bl Lbase */
|
||||
trampOnStack[2] = (uint32_t)realFunc;
|
||||
trampOnStack[3] = (uint32_t)localsPtr;
|
||||
trampOnStack[4] = 0x7d6802a6; /* Lbase: mflr r11 */
|
||||
trampOnStack[5] = 0x818b0000; /* lwz r12,0(r11) */
|
||||
trampOnStack[6] = 0x7c0803a6; /* mtlr r0 */
|
||||
trampOnStack[7] = 0x7d8903a6; /* mtctr r12 */
|
||||
trampOnStack[8] = 0x816b0004; /* lwz r11,4(r11) */
|
||||
trampOnStack[9] = 0x4e800420; /* bctr */
|
||||
|
||||
/* clear instruction cache */
|
||||
__clear_cache(trampOnStack, &trampOnStack[10]);
|
||||
}
|
||||
#endif /* __ppc__ && !defined(__powerpc64__) */
|
4
third_party/duktape/duk_config.h
vendored
4
third_party/duktape/duk_config.h
vendored
|
@ -800,8 +800,8 @@
|
|||
* because of bugs in gcc-4.4
|
||||
* (http://lists.debian.org/debian-gcc/2010/04/msg00000.html)
|
||||
*/
|
||||
#define DUK_LIKELY(x) likely(x)
|
||||
#define DUK_UNLIKELY(x) unlikely(x)
|
||||
#define DUK_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
#define DUK_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
#endif
|
||||
/* XXX: equivalent of clang __builtin_unpredictable? */
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@ TOOL_BUILD_DIRECTDEPS = \
|
|||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_TESTLIB \
|
||||
LIBC_TIME \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_UNICODE \
|
||||
|
|
|
@ -190,7 +190,10 @@ void elfwriter_close(struct ElfWriter *elf) {
|
|||
freeinterner(elf->strtab);
|
||||
free(elf->shdrs->p);
|
||||
free(elf->relas->p);
|
||||
for (i = 0; i < ARRAYLEN(elf->syms); ++i) free(elf->syms[i]->p);
|
||||
free(elf->path);
|
||||
for (i = 0; i < ARRAYLEN(elf->syms); ++i) {
|
||||
free(elf->syms[i]->p);
|
||||
}
|
||||
free(elf);
|
||||
}
|
||||
|
||||
|
@ -237,6 +240,14 @@ void elfwriter_finishsection(struct ElfWriter *elf) {
|
|||
if (elf->relas->j < elf->relas->i) MakeRelaSection(elf, section);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends symbol.
|
||||
*
|
||||
* This function should be called between elfwriter_startsection() and
|
||||
* elfwriter_finishsection(). If that's not possible, then this can be
|
||||
* called after elfwriter_open() and then elfwriter_setsection() can be
|
||||
* called later to fix-up the section id.
|
||||
*/
|
||||
struct ElfWriterSymRef elfwriter_appendsym(struct ElfWriter *elf,
|
||||
const char *name, int st_info,
|
||||
int st_other, size_t st_value,
|
||||
|
@ -247,6 +258,11 @@ struct ElfWriterSymRef elfwriter_appendsym(struct ElfWriter *elf,
|
|||
: kElfWriterSymGlobal);
|
||||
}
|
||||
|
||||
void elfwriter_setsection(struct ElfWriter *elf, struct ElfWriterSymRef sym,
|
||||
uint16_t st_shndx) {
|
||||
elf->syms[sym.slg]->p[sym.sym].st_shndx = st_shndx;
|
||||
}
|
||||
|
||||
struct ElfWriterSymRef elfwriter_linksym(struct ElfWriter *elf,
|
||||
const char *name, int st_info,
|
||||
int st_other) {
|
||||
|
|
|
@ -61,6 +61,7 @@ struct ElfWriterSymRef elfwriter_linksym(struct ElfWriter *, const char *, int,
|
|||
struct ElfWriterSymRef elfwriter_appendsym(struct ElfWriter *, const char *,
|
||||
int, int, size_t, size_t);
|
||||
void elfwriter_yoink(struct ElfWriter *, const char *);
|
||||
void elfwriter_setsection(struct ElfWriter *, struct ElfWriterSymRef, uint16_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -47,7 +47,7 @@ static void rehash(struct InternerObject *it) {
|
|||
if (!p[i].hash) continue;
|
||||
step = 0;
|
||||
do {
|
||||
j = (p[i].hash + step * (step + 1) / 2) & (it->n - 1);
|
||||
j = (p[i].hash + step * ((step + 1) >> 1)) & (it->n - 1);
|
||||
step++;
|
||||
} while (it->p[j].hash);
|
||||
memcpy(&it->p[j], &p[i], sizeof(p[i]));
|
||||
|
@ -103,7 +103,7 @@ size_t internobj(struct Interner *t, const void *data, size_t size) {
|
|||
hash = max(1, KnuthMultiplicativeHash32(data, size));
|
||||
do {
|
||||
/* it is written that triangle probe halts iff i<n/2 && popcnt(n)==1 */
|
||||
i = (hash + step * (step + 1) / 2) & (it->n - 1);
|
||||
i = (hash + step * ((step + 1) >> 1)) & (it->n - 1);
|
||||
if (it->p[i].hash == hash && it->p[i].index + size <= it->pool.n &&
|
||||
memcmp(item, &it->pool.p[it->p[i].index], size) == 0) {
|
||||
return it->p[i].index;
|
||||
|
@ -114,7 +114,7 @@ size_t internobj(struct Interner *t, const void *data, size_t size) {
|
|||
rehash(it);
|
||||
step = 0;
|
||||
do {
|
||||
i = (hash + step * (step + 1) / 2) & (it->n - 1);
|
||||
i = (hash + step * ((step + 1) >> 1)) & (it->n - 1);
|
||||
step++;
|
||||
} while (it->p[i].hash);
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ int AppendIovs(struct Iovs *ib, void *base, size_t len) {
|
|||
if (i && (intptr_t)base == (intptr_t)p[i - 1].iov_base + p[i - 1].iov_len) {
|
||||
p[i - 1].iov_len += len;
|
||||
} else {
|
||||
if (unlikely(i == n)) {
|
||||
if (__builtin_expect(i == n, 0)) {
|
||||
n += n >> 1;
|
||||
if (p == ib->init) {
|
||||
if (!(p = malloc(sizeof(struct iovec) * n))) return -1;
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
* Only the first 64kb of each source file is considered.
|
||||
*/
|
||||
|
||||
alignas(16) const char kIncludePrefix[] = "include \"";
|
||||
_Alignas(16) const char kIncludePrefix[] = "include \"";
|
||||
|
||||
const char kSourceExts[][5] = {".s", ".S", ".c", ".cc", ".cpp"};
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "tool/decode/lib/asmcodegen.h"
|
||||
#include "tool/decode/lib/elfidnames.h"
|
||||
#include "tool/decode/lib/flagger.h"
|
||||
|
@ -249,10 +250,10 @@ static char *getelfsymbolname(const Elf64_Ehdr *elf, size_t mapsize,
|
|||
|
||||
static void printelfrelocations(void) {
|
||||
int sym;
|
||||
size_t i, j;
|
||||
size_t i, j, count;
|
||||
const Elf64_Sym *syms;
|
||||
const Elf64_Rela *rela;
|
||||
const Elf64_Shdr *shdr, *boop;
|
||||
const Elf64_Shdr *shdr, *symtab;
|
||||
char *strtab, *shstrtab, *symbolname;
|
||||
strtab = GetElfStringTable(elf, st->st_size);
|
||||
shstrtab = GetElfSectionNameStringTable(elf, st->st_size);
|
||||
|
@ -266,11 +267,16 @@ static void printelfrelocations(void) {
|
|||
min((uintptr_t)elf + st->st_size,
|
||||
(uintptr_t)elf + shdr->sh_offset + shdr->sh_size));
|
||||
++rela, ++j) {
|
||||
boop = GetElfSectionHeaderAddress(elf, st->st_size, shdr->sh_link);
|
||||
syms = GetElfSectionAddress(elf, st->st_size, boop);
|
||||
symtab = GetElfSectionHeaderAddress(elf, st->st_size, shdr->sh_link);
|
||||
count = symtab->sh_size / symtab->sh_entsize;
|
||||
syms = GetElfSectionAddress(elf, st->st_size, symtab);
|
||||
sym = ELF64_R_SYM(rela->r_info);
|
||||
symbolname =
|
||||
getelfsymbolname(elf, st->st_size, strtab, shstrtab, &syms[sym]);
|
||||
if (0 <= sym && sym < count) {
|
||||
symbolname =
|
||||
getelfsymbolname(elf, st->st_size, strtab, shstrtab, syms + sym);
|
||||
} else {
|
||||
symbolname = xasprintf("bad-sym-%d", sym);
|
||||
}
|
||||
printf("/\t%s+%#lx → %s%c%#lx\n",
|
||||
GetElfString(
|
||||
elf, st->st_size, shstrtab,
|
||||
|
@ -297,7 +303,7 @@ static void printelfrelocations(void) {
|
|||
int main(int argc, char *argv[]) {
|
||||
showcrashreports();
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: %`s FILE: %s\n", argv[0]);
|
||||
fprintf(stderr, "usage: %s FILE\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
path = argv[1];
|
||||
|
|
|
@ -1665,7 +1665,6 @@ Keywords={
|
|||
"COSMOPOLITAN_C_END_",
|
||||
"MACHINE_CODE_ANALYSIS_BEGIN_",
|
||||
"MACHINE_CODE_ANALYSIS_END_",
|
||||
"typescompatible",
|
||||
"DebugBreak",
|
||||
"VEIL",
|
||||
"CONCEAL",
|
||||
|
@ -1674,8 +1673,6 @@ Keywords={
|
|||
"STATIC_YOINK",
|
||||
"STATIC_YOINK_SOURCE",
|
||||
"STRINGIFY",
|
||||
"isconstant",
|
||||
"chooseexpr",
|
||||
"likely",
|
||||
"unlikely",
|
||||
"assume",
|
||||
|
|
|
@ -1280,8 +1280,7 @@
|
|||
"MACHINE_CODE_ANALYSIS_END_"))
|
||||
|
||||
(cosmopolitan-builtin-functions
|
||||
'("typescompatible"
|
||||
"DebugBreak"
|
||||
'("DebugBreak"
|
||||
"VEIL"
|
||||
"CONCEAL"
|
||||
"EXPROPRIATE"
|
||||
|
@ -1289,8 +1288,6 @@
|
|||
"STATIC_YOINK"
|
||||
"STATIC_YOINK_SOURCE"
|
||||
"STRINGIFY"
|
||||
"isconstant"
|
||||
"chooseexpr"
|
||||
"likely"
|
||||
"unlikely"))
|
||||
|
||||
|
|
|
@ -441,7 +441,7 @@
|
|||
(cond ((not (eq 0 (logand 8 arg)))
|
||||
(cosmo--assembly (setq arg (logand (lognot 8)))
|
||||
"SILENT=0 COPTS='-Os'"))
|
||||
(t (cosmo--assembly arg "SILENT=0 COPTS='-Os' TARGET_ARCH='-march=znver2 -mdispatch-scheduler' CPPFLAGS='-DSTACK_FRAME_UNLIMITED'"))))
|
||||
(t (cosmo--assembly arg "SILENT=0 COPTS='-Os' TARGET_ARCH='-mdispatch-scheduler' CPPFLAGS='-DSTACK_FRAME_UNLIMITED'"))))
|
||||
|
||||
(defun cosmo-assembly-native (arg)
|
||||
(interactive "P")
|
||||
|
|
Loading…
Reference in a new issue