Browse Source

Make improvements

- Emulator can now test the αcτµαlly pδrταblε εxεcµταblε bootloader

- Whipped up a webserver named redbean. It services 150k requests per
  second on a single core. Bundling assets inside zip enables extremely
  fast serving for two reasons. The first is that zip central directory
  lookups go faster than stat() system calls. The second is that both
  zip and gzip content-encoding use DEFLATE, therefore, compressed
  responses can be served via the sendfile() system call which does an
  in-kernel copy directly from the zip executable structure. Also note
  that red bean zip executables can be deployed easily to all platforms,
  since these native executables work on Linux, Mac, BSD, and Windows.

- Address sanitizer now works very well
main
Justine Tunney 1 year ago
parent
commit
416fd86676
  1. 25
      ape/ape.S
  2. 2
      ape/config.h
  3. 6
      dsp/core/core.mk
  4. 14
      dsp/scale/gyarados.c
  5. 6
      dsp/tty/tty.mk
  6. 6
      examples/fld.c
  7. 82
      examples/ls.c
  8. 3
      examples/tiny-raw-linux-tutorial.S
  9. 107
      libc/calls/hefty/dirstream.c
  10. 13
      libc/calls/internal.h
  11. 2
      libc/calls/stat.c
  12. 6
      libc/calls/struct/dirent.h
  13. 6
      libc/conv/conv.mk
  14. 22
      libc/conv/itoa64fixed16.greg.c
  15. 16
      libc/conv/itoa64radix16.greg.c
  16. 2
      libc/crt/crt.S
  17. 8
      libc/elf/elf.h
  18. 10
      libc/elf/iself64binary.c
  19. 20
      libc/fmt/palandftoa.c
  20. 2
      libc/fmt/palandprintf.h
  21. 132
      libc/integral/c.inc
  22. 2
      libc/integral/normalize.inc
  23. 45
      libc/intrin/mpsadbw.c
  24. 41
      libc/intrin/mpsadbw.h
  25. 33
      libc/intrin/mpsadbws.S
  26. 2
      libc/intrin/repstosb.h
  27. 317
      libc/log/asan.c
  28. 25
      libc/log/asan.h
  29. 51
      libc/log/backtrace3.c
  30. 19
      libc/log/checkfail_ndebug.c
  31. 5
      libc/log/commandvenv.c
  32. 2
      libc/log/malloc_stats.c
  33. 64
      libc/log/somanyasan.S
  34. 10
      libc/log/startfatal_ndebug.c
  35. 23
      libc/log/ubsan.c
  36. 24
      libc/math.h
  37. 2
      libc/nexgen32e/crc32.h
  38. 1
      libc/nexgen32e/crc32init.S
  39. 13
      libc/nexgen32e/crc32z.c
  40. 5
      libc/nt/struct/win32finddata.h
  41. 45
      libc/runtime/destruct.S
  42. 1
      libc/runtime/exit.S
  43. 3
      libc/runtime/missioncritical.h
  44. 9
      libc/runtime/print.greg.c
  45. 2
      libc/sock/accept4.c
  46. 1
      libc/sock/bind.c
  47. 1
      libc/sock/connect.c
  48. 2
      libc/sock/internal.h
  49. 7
      libc/sock/sendto-nt.c
  50. 2
      libc/sock/sendto.c
  51. 3
      libc/sock/setsockopt.c
  52. 10
      libc/sock/sock.h
  53. 16
      libc/str/stpcpy.c
  54. 17
      libc/str/str.h
  55. 4
      libc/str/str.mk
  56. 2
      libc/sysv/calls/getdents.s
  57. 29
      libc/sysv/consts.sh
  58. 2
      libc/sysv/consts/DT_BLK.s
  59. 2
      libc/sysv/consts/DT_CHR.s
  60. 2
      libc/sysv/consts/DT_DIR.s
  61. 2
      libc/sysv/consts/DT_FIFO.s
  62. 2
      libc/sysv/consts/DT_LNK.s
  63. 2
      libc/sysv/consts/DT_REG.s
  64. 2
      libc/sysv/consts/DT_SOCK.s
  65. 2
      libc/sysv/consts/DT_UNKNOWN.s
  66. 2
      libc/sysv/consts/SOL_ICMPV6.s
  67. 2
      libc/sysv/consts/SOL_IPV6.s
  68. 2
      libc/sysv/consts/SOL_TCP.s
  69. 2
      libc/sysv/consts/SOL_UDP.s
  70. 2
      libc/sysv/consts/TIOCOUTQ.s
  71. 28
      libc/sysv/consts/dt.h
  72. 2
      libc/sysv/syscalls.sh
  73. 2
      libc/testlib/formatbinaryasglyphs.c
  74. 2
      libc/time/asctime_r.c
  75. 2
      libc/time/ctime_r.c
  76. 2
      libc/time/gettimeofday.c
  77. 350
      libc/time/localtime.c
  78. 161
      libc/time/strftime.c
  79. 12
      libc/time/time.h
  80. 3
      libc/time/time.mk
  81. 3
      libc/tinymath/copysignl.S
  82. 12
      libc/tinymath/lroundl.S
  83. 2
      libc/tinymath/round.S
  84. 10
      libc/tinymath/roundl.S
  85. 8
      net/http/gethttpheader.c
  86. 102
      net/http/gethttpheader.gperf
  87. 365
      net/http/gethttpheader.inc
  88. 20
      net/http/gethttpmethod.c
  89. 36
      net/http/gethttpmethod.gperf
  90. 206
      net/http/gethttpmethod.inc
  91. 153
      net/http/http.h
  92. 24
      net/http/method.gperf
  93. 2
      net/http/negotiatehttprequest.c
  94. 111
      net/http/parsehttprequest.c
  95. 5
      test/ape/lib/test.mk
  96. 4
      test/dsp/core/getintegercoefficients8_test.c
  97. 8
      test/dsp/core/test.mk
  98. 32
      test/dsp/scale/scale_test.c
  99. 4
      test/libc/conv/itoa64radix16_test.c
  100. 8
      test/libc/fmt/palandprintf_test.c

25
ape/ape.S

@ -236,9 +236,6 @@ pc: cld
ljmp $0,$REAL(realmodeloader)
.endfn pc,globl,hidden
/ Be gentler on Unix line buffer impls.
.byte 0x0a
/ Determines disk geometry.
/
/ We use imperial measurements for storage systems so the software
@ -1055,9 +1052,9 @@ realmodeloader:
call rlinit
call sinit4
mov $VIDYA_MODE,%di
call vinit
mov %es,XLM(VIDEO_POSITION_FAR_POINTER)
mov %ax,XLM(VIDEO_POSITION_FAR_POINTER)+2
call vinit
mov $REAL(.Lstr.ape),%di
call rvputs
.optfn _start16
@ -1370,8 +1367,8 @@ vtput: push %bp
mov %di,%dx
bband VIDYA_REWIND,%dh,%dl
bbadd VIDYA_SIZE,%dh,%dl
bbmov VIDYA_COLUMNS*2,%bx,%bh,%bl
0: cmp %di,%dx
bbmov VIDYA_COLUMNS*2-2,%bx,%bh,%bl
0: cmp %dx,%di
je 6f
ja 3f
lodsb # todo: utf8 cp437
@ -1523,12 +1520,12 @@ longmodeloader:
/ Long Mode Hardware Check
lcheck: push %bp
mov %sp,%bp
pushfw # check for i8086 / i8088 / i80186
pushf # check for i8086 / i8088 / i80186
pop %ax
and $0b111<<12,%ax # see intel manual volume 1 §19.1.2
jnz 9f
pushfl # now check for later model of 80486
pop %eax # test ability to *change* cpuid bit
test $0x80,%ah # see intel manual volume 1 20.1.2
jnz 9f # we now assume 32bit is supported
pushfl # now check for i386 or early i486
pop %eax # test ability to change cpuid bit
mov %eax,%ecx
mov $1<<21,%ebx
xor %ebx,%eax
@ -1537,8 +1534,8 @@ lcheck: push %bp
pushfl
pop %eax
cmp %eax,%ecx
je 12f
and %ebx,%eax # puts cpuid bit in the on position
je 12f # we assume cpuid inst is available
or %ebx,%eax # puts cpuid bit in the on position
push %eax
popfl
mov $0x80000000,%edi # get amd ext cpuid thingy length
@ -1549,7 +1546,7 @@ lcheck: push %bp
jl 10f
mov %edi,%eax
cpuid
mov $1<<29/*LM*/,%edi # check for nexgen32e support
mov $1<<29,%edi # need nexgen32e long mode support
and %edi,%edx
cmp %edi,%edx
jne 10f

2
ape/config.h

@ -41,7 +41,7 @@
* @see ape/lib/vidya.h
*/
#ifndef VIDYA_MODE
#define VIDYA_MODE VIDYA_MODE_MDA
#define VIDYA_MODE VIDYA_MODE_CGA
#endif
/* FPU Control Word (x87) Exception Masks

6
dsp/core/core.mk

@ -58,6 +58,12 @@ o/$(MODE)/dsp/core/det3.o: \
OVERRIDE_CFLAGS += \
-ffast-math
ifeq (,$(MODE))
$(DSP_CORE_OBJS): \
OVERRIDE_CFLAGS += \
-fsanitize=address
endif
DSP_CORE_LIBS = $(foreach x,$(DSP_CORE_ARTIFACTS),$($(x)))
DSP_CORE_SRCS = $(foreach x,$(DSP_CORE_ARTIFACTS),$($(x)_SRCS))
DSP_CORE_HDRS = $(foreach x,$(DSP_CORE_ARTIFACTS),$($(x)_HDRS))

14
dsp/scale/gyarados.c

@ -102,7 +102,7 @@ struct SamplingSolution *ComputeSamplingSolution(long dn, long sn, double dar,
if (!dar) dar = sn, dar /= dn;
if (!off) off = (dar - 1) / 2;
f = dar < 1 ? 1 / dar : dar;
s = 3 * f + 1;
s = 3 * f + 4;
fweights = gc(xcalloc(s, sizeof(double)));
res = NewSamplingSolution(dn, s);
weights = res->weights;
@ -147,9 +147,9 @@ static int Sharpen(int ax, int bx, int cx) {
static void GyaradosImpl(long dyw, long dxw, int dst[dyw][dxw], long syw,
long sxw, const int src[syw][sxw], long dyn, long dxn,
long syn, long sxn, short tmp0[restrict dyn][sxn],
short tmp1[restrict dyn][sxn],
short tmp2[restrict dyn][dxn], long yfn, long xfn,
long syn, long sxn, int tmp0[restrict dyn][sxn],
int tmp1[restrict dyn][sxn],
int tmp2[restrict dyn][dxn], long yfn, long xfn,
const short fyi[dyn][yfn], const short fyw[dyn][yfn],
const short fxi[dxn][xfn], const short fxw[dxn][xfn],
bool sharpen) {
@ -216,9 +216,9 @@ void *Gyarados(long dyw, long dxw, int dst[dyw][dxw], long syw, long sxw,
CHECK_LE(syn, 0x7fff);
CHECK_LE(sxn, 0x7fff);
GyaradosImpl(dyw, dxw, dst, syw, sxw, src, dyn, dxn, syn, sxn,
gc(xmemalign(64, sizeof(short) * dyn * sxn)),
gc(xmemalign(64, sizeof(short) * dyn * sxn)),
gc(xmemalign(64, sizeof(short) * dyn * dxn)), cy->s, cx->s,
gc(xmemalign(64, sizeof(int) * dyn * sxn)),
gc(xmemalign(64, sizeof(int) * dyn * sxn)),
gc(xmemalign(64, sizeof(int) * dyn * dxn)), cy->s, cx->s,
cy->indices, cy->weights, cx->indices, cx->weights, sharpen);
} else {
ZeroMatrix(dyw, dxw, dst, dyn, dxn);

6
dsp/tty/tty.mk

@ -59,6 +59,12 @@ o/$(MODE)/dsp/tty/ttyraster.o: \
OVERRIDE_CFLAGS += \
$(MATHEMATICAL)
ifeq (,$(MODE))
$(DSP_TTY_OBJS): \
OVERRIDE_CFLAGS += \
-fsanitize=address
endif
DSP_TTY_LIBS = $(foreach x,$(DSP_TTY_ARTIFACTS),$($(x)))
DSP_TTY_SRCS = $(foreach x,$(DSP_TTY_ARTIFACTS),$($(x)_SRCS))
DSP_TTY_HDRS = $(foreach x,$(DSP_TTY_ARTIFACTS),$($(x)_HDRS))

6
examples/fld.c

@ -35,7 +35,7 @@ void dobin(const char *op, long double x, FILE *f) {
memcpy(buf, &x, sizeof(x));
memcpy(&lo, &buf[0], sizeof(lo));
memcpy(&hi, &buf[8], sizeof(hi));
fprintf(f, "/\t%016" PRIb16 "%064" PRIb64 " %-8s % 19.19Lf\n", hi, lo, op, x);
fprintf(f, "/\t%016" PRIb16 "%064" PRIb64 " %-8s % 17.14Lf\n", hi, lo, op, x);
}
void dohex(const char *op, long double x, FILE *f) {
@ -45,7 +45,7 @@ void dohex(const char *op, long double x, FILE *f) {
memcpy(buf, &x, sizeof(x));
memcpy(&lo, &buf[0], sizeof(lo));
memcpy(&hi, &buf[8], sizeof(hi));
fprintf(f, "/\t%04" PRIx16 "%016" PRIx64 " %-8s % 19.19Lf\n", hi, lo, op, x);
fprintf(f, "/\t%04" PRIx16 "%016" PRIx64 " %-8s % 17.14Lf\n", hi, lo, op, x);
}
#define DOBIN(OP) \
@ -65,7 +65,6 @@ int main(int argc, char *argv[]) {
DOBIN(fldlg2);
DOBIN(fldln2);
DOBIN(fldl2e);
DOBIN(finit);
fputc('\n', stdout);
fputs(kHeaderHex, stdout);
DOHEX(fldz);
@ -75,7 +74,6 @@ int main(int argc, char *argv[]) {
DOHEX(fldlg2);
DOHEX(fldln2);
DOHEX(fldl2e);
DOHEX(finit);
return 0;
}

82
examples/ls.c

@ -0,0 +1,82 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/
http://creativecommons.org/publicdomain/zero/1.0/
*/
#endif
#include "libc/calls/calls.h"
#include "libc/calls/struct/dirent.h"
#include "libc/calls/struct/stat.h"
#include "libc/log/check.h"
#include "libc/runtime/gc.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/dt.h"
#include "libc/x/x.h"
struct stat st;
const char *TypeToString(uint8_t type) {
switch (type) {
case DT_UNKNOWN:
return "DT_UNKNOWN";
case DT_FIFO:
return "DT_FIFO";
case DT_CHR:
return "DT_CHR";
case DT_DIR:
return "DT_DIR";
case DT_BLK:
return "DT_BLK";
case DT_REG:
return "DT_REG";
case DT_LNK:
return "DT_LNK";
case DT_SOCK:
return "DT_SOCK";
default:
return "UNKNOWN";
}
}
void List(const char *path) {
DIR *d;
struct dirent *e;
const char *vpath;
if (strcmp(path, ".") == 0) {
vpath = "";
} else if (!endswith(path, "/")) {
vpath = gc(xasprintf("%s/", path));
} else {
vpath = path;
}
if (stat(path, &st) != -1) {
if (S_ISDIR(st.st_mode)) {
CHECK((d = opendir(path)));
while ((e = readdir(d))) {
printf("0x%016x 0x%016x %-10s %s%s\n", e->d_ino, e->d_off,
TypeToString(e->d_type), vpath, e->d_name);
}
closedir(d);
} else {
printf("%s\n", path);
}
} else {
fprintf(stderr, "not found: %s\n", path);
}
}
int main(int argc, char *argv[]) {
int i;
if (argc == 1) {
List(".");
} else {
for (i = 1; i < argc; ++i) {
List(argv[i]);
}
}
return 0;
}

3
examples/tiny-raw-linux-tutorial.S

@ -58,3 +58,6 @@ _start: mov $12,%rdx # arg no. 3 is length
jmp 0b
.endfn _start,globl
.source __FILE__
.rodata.cst4
1: .float -1.5

107
libc/calls/hefty/dirstream.c

@ -23,6 +23,8 @@
#include "libc/calls/struct/dirent.h"
#include "libc/dce.h"
#include "libc/mem/mem.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/filetype.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/win32finddata.h"
@ -31,9 +33,18 @@
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
struct dirent$freebsd {
uint32_t d_fileno;
uint16_t d_reclen;
uint8_t d_type;
uint8_t d_namlen;
char d_name[256];
};
struct dirstream {
int64_t tell;
int64_t fd;
struct dirent ent;
union {
struct {
unsigned buf_pos;
@ -41,8 +52,6 @@ struct dirstream {
char buf[BUFSIZ];
};
struct {
struct dirent winent;
char __d_name[PATH_MAX];
bool isdone;
struct NtWin32FindData windata;
};
@ -71,17 +80,60 @@ static textwindows noinline DIR *opendir$nt(const char *name) {
}
}
static textwindows noinline struct dirent *readdir$nt(DIR *dir) {
if (!dir->isdone) {
memset(&dir->ent, 0, sizeof(dir->ent));
dir->ent.d_ino = 0;
dir->ent.d_off = dir->tell++;
dir->ent.d_reclen = sizeof(dir->ent) +
tprecode16to8(dir->ent.d_name, sizeof(dir->ent.d_name),
dir->windata.cFileName) +
1;
switch (dir->windata.dwFileType) {
case kNtFileTypeDisk:
dir->ent.d_type = DT_BLK;
break;
case kNtFileTypeChar:
dir->ent.d_type = DT_CHR;
break;
case kNtFileTypePipe:
dir->ent.d_type = DT_FIFO;
break;
default:
if (dir->windata.dwFileAttributes & kNtFileAttributeDirectory) {
dir->ent.d_type = DT_DIR;
} else {
dir->ent.d_type = DT_REG;
}
break;
}
dir->isdone = !FindNextFile(dir->fd, &dir->windata);
return &dir->ent;
} else {
return NULL;
}
}
/**
* Opens directory so readdir() and closedir() may be called.
* Opens directory, e.g.
*
* DIR *d;
* struct dirent *e;
* CHECK((d = opendir(path)));
* while ((e = readdir(d))) {
* printf("%s/%s\n", path, e->d_name);
* }
* LOGIFNEG1(closedir(d));
*
* @returns newly allocated DIR object, or NULL w/ errno
* @errors ENOENT, ENOTDIR, EACCES, EMFILE, ENFILE, ENOMEM
* @see glob()
*/
DIR *opendir(const char *name) {
int fd;
DIR *res;
if (!IsWindows() && !IsXnu()) {
int fd;
DIR *res = NULL;
res = NULL;
if ((fd = open(name, O_RDONLY | O_DIRECTORY | O_CLOEXEC, 0)) != -1) {
if (!(res = fdopendir(fd))) close(fd);
}
@ -103,8 +155,8 @@ DIR *opendir(const char *name) {
* @errors ENOMEM and fd is closed
*/
DIR *fdopendir(int fd) {
DIR *dir;
if (!IsWindows() && !IsXnu()) {
DIR *dir;
if ((dir = calloc(1, sizeof(*dir)))) {
dir->fd = fd;
return dir;
@ -125,35 +177,36 @@ DIR *fdopendir(int fd) {
* differentiated by setting errno to 0 beforehand
*/
struct dirent *readdir(DIR *dir) {
int rc;
struct dirent *ent;
struct dirent$freebsd *freebsd;
if (!IsWindows()) {
if (dir->buf_pos >= dir->buf_end) {
int rc;
if (!(rc = getdents(dir->fd, dir->buf, BUFSIZ)) || rc == -1) {
if (!(rc = getdents(dir->fd, dir->buf,
sizeof(dir->buf) - sizeof(dir->ent.d_name))) ||
rc == -1) {
return NULL;
}
dir->buf_pos = 0;
dir->buf_end = rc;
}
/* TODO(jart): Check FreeBSD and OpenBSD again regarding this */
char *record = dir->buf + dir->buf_pos;
char *name = record + 8 + 8 + 2;
size_t namelen = strlen(name);
unsigned char dtype = name[namelen + 1];
memmove(name + 1, name, namelen + 1); /* shove forward one byte */
*name = dtype; /* is dirent d_type field */
struct dirent *ent = (void *)record;
dir->buf_pos += ent->d_reclen;
dir->tell = ent->d_off;
if (IsLinux()) {
ent = (struct dirent *)(dir->buf + dir->buf_pos);
dir->buf_pos += ent->d_reclen;
dir->tell = ent->d_off;
} else {
freebsd = (struct dirent$freebsd *)(dir->buf + dir->buf_pos);
dir->buf_pos += freebsd->d_reclen;
ent = &dir->ent;
ent->d_ino = freebsd->d_fileno;
ent->d_off = dir->tell++;
ent->d_reclen = freebsd->d_reclen;
ent->d_type = freebsd->d_type;
memcpy(ent->d_name, freebsd->d_name, freebsd->d_namlen + 1);
}
return ent;
} else {
if (dir->isdone) return NULL;
struct dirent *ent = &dir->winent;
memset(ent, 0, sizeof(*ent));
ent->d_reclen =
sizeof(*ent) +
tprecode16to8(ent->d_name, PATH_MAX, dir->windata.cFileName) + 1;
dir->isdone = FindNextFile(dir->fd, &dir->windata);
return ent;
return readdir$nt(dir);
}
}
@ -177,7 +230,7 @@ int closedir(DIR *dir) {
}
/**
* Returns current byte offset into directory data.
* Returns offset into directory data.
*/
long telldir(DIR *dir) {
return dir->tell;

13
libc/calls/internal.h

@ -21,6 +21,9 @@
#define COSMOPOLITAN_LIBC_CALLS_INTERNAL_H_
#ifndef __STRICT_ANSI__
#include "libc/calls/calls.h"
#include "libc/calls/struct/itimerval.h"
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timeval.h"
#include "libc/dce.h"
#include "libc/limits.h"
#include "libc/macros.h"
@ -28,6 +31,8 @@
#include "libc/nt/struct/startupinfo.h"
#include "libc/nt/struct/systeminfo.h"
#include "libc/runtime/runtime.h"
#include "libc/time/struct/timezone.h"
#include "libc/time/struct/utimbuf.h"
#define kSigactionMinRva 8 /* >SIG_{ERR,DFL,IGN,...} */
@ -41,14 +46,6 @@ struct NtWin32FileAttributeData;
struct ZiposHandle;
struct __darwin_siginfo;
struct __darwin_ucontext;
struct itimerval;
struct rlimit;
struct rusage;
struct sigset;
struct sysinfo;
struct timeval;
struct timezone;
struct utimbuf;
struct IoctlPtmGet {
int theduxfd;

2
libc/calls/stat.c

@ -28,6 +28,8 @@
/**
* Returns information about thing.
*
* @see S_ISDIR(st.st_mode), S_ISREG(), etc.
* @asyncsignalsafe
*/
int stat(const char *pathname, struct stat *st) {

6
libc/calls/struct/dirent.h

@ -2,12 +2,12 @@
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_DIRENT_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
struct dirent {
struct dirent { /* linux getdents64 abi */
uint64_t d_ino; /* inode number */
int64_t d_off; /* implementation-dependent location number */
uint16_t d_reclen; /* byte length of this whole struct and string */
uint8_t d_type; /* DT_UNKNOWN, DT_BLK, DT_DIR, etc. it's flaky */
char d_name[1]; /* NUL-terminated basename */
uint8_t d_type; /* DT_UNKNOWN, DT_BLK, DT_DIR, etc. */
char d_name[256]; /* NUL-terminated basename */
};
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

6
libc/conv/conv.mk

@ -58,9 +58,13 @@ o/$(MODE)/libc/conv/filetimetotime.o \
o/$(MODE)/libc/conv/timespectofiletime.o \
o/$(MODE)/libc/conv/filetimetotimespec.o \
o/$(MODE)/libc/conv/filetimetotimeval.o: \
OVERRIDE_COPTS += \
OVERRIDE_CFLAGS += \
-O3
$(LIBC_CONV_A_OBJS): \
OVERRIDE_CFLAGS += \
$(NO_MAGIC)
LIBC_CONV_LIBS = $(foreach x,$(LIBC_CONV_ARTIFACTS),$($(x)))
LIBC_CONV_SRCS = $(foreach x,$(LIBC_CONV_ARTIFACTS),$($(x)_SRCS))
LIBC_CONV_HDRS = $(foreach x,$(LIBC_CONV_ARTIFACTS),$($(x)_HDRS))

22
libc/conv/itoa64fixed16.greg.c

@ -17,22 +17,14 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/alg/reverse.h"
#include "libc/assert.h"
#include "libc/conv/itoa.h"
size_t uint64toarray_fixed16(uint64_t i, char a[hasatleast 17], uint8_t b) {
size_t j;
assert(b <= 64);
assert(b % 4 == 0);
j = 0;
if (b) {
do {
a[j++] = "0123456789abcdef"[i & 15];
i >>= 4;
} while (b -= 4);
}
a[j] = '\0';
reverse(a, j);
return j;
size_t uint64toarray_fixed16(uint64_t x, char b[hasatleast 17], uint8_t k) {
int i;
char *p;
assert(k <= 64 && !(k & 3));
for (p = b; k > 0;) *p++ = "0123456789abcdef"[(x >> (k -= 4)) & 15];
*p = '\0';
return p - b;
}

16
libc/conv/itoa64radix16.greg.c

@ -17,17 +17,11 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/alg/reverse.h"
#include "libc/conv/conv.h"
#include "libc/conv/itoa.h"
#include "libc/macros.h"
#include "libc/nexgen32e/bsr.h"
size_t uint64toarray_radix16(uint64_t i, char a[hasatleast 17]) {
size_t j;
j = 0;
do {
a[j++] = "0123456789abcdef"[i % 16];
i /= 16;
} while (i > 0);
a[j] = '\0';
reverse(a, j);
return j;
size_t uint64toarray_radix16(uint64_t x, char b[hasatleast 17]) {
return uint64toarray_fixed16(x, b, ROUNDUP(x ? bsrl(x) + 1 : 1, 4));
}

2
libc/crt/crt.S

@ -39,7 +39,7 @@ _start: test %rdi,%rdi
lea 8(%rsp),%rsi # argv
lea 24(%rsp,%rbx,8),%rdx # envp
.frame0
bofram 9f
/ bofram 9f
.weak idata.iat,idata.iatend
ezlea missingno,ax # make win32 imps noop
ezlea idata.iat,di

8
libc/elf/elf.h

@ -23,6 +23,7 @@ Elf64_Ehdr *mapelfread(const char *, struct MappedFile *);
char *getelfstringtable(const Elf64_Ehdr *, size_t);
Elf64_Sym *getelfsymboltable(const Elf64_Ehdr *, size_t, Elf64_Xword *);
Elf64_Shdr *getelfsectionbyaddress(const Elf64_Ehdr *, size_t, void *);
bool iself64binary(const Elf64_Ehdr *, size_t);
forceinline void checkelfaddress(const Elf64_Ehdr *elf, size_t mapsize,
intptr_t addr, size_t addrsize) {
@ -33,13 +34,6 @@ forceinline void checkelfaddress(const Elf64_Ehdr *elf, size_t mapsize,
#endif
}
static inline bool iself64binary(const Elf64_Ehdr *elf, size_t mapsize) {
return mapsize >= sizeof(Elf64_Ehdr) &&
memcmp(elf->e_ident, ELFMAG, 4) == 0 &&
(elf->e_ident[EI_CLASS] == ELFCLASSNONE ||
elf->e_ident[EI_CLASS] == ELFCLASS64);
}
static inline bool iselfsymbolcontent(const Elf64_Sym *sym) {
return sym->st_size > 0 && (ELF64_ST_TYPE(sym->st_info) == STT_FUNC ||
ELF64_ST_TYPE(sym->st_info) == STT_OBJECT);

10
test/ape/lib/flattenhighmemory_test.c → libc/elf/iself64binary.c

@ -17,9 +17,11 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/testlib/testlib.h"
#include "libc/elf/elf.h"
TEST(flattenhighmemory, test) {
/* EXPECT_EQ(0, flattenhighmemory()); */
/* EXPECT_STREQ("", flattenhighmemory()); */
bool iself64binary(const Elf64_Ehdr *elf, size_t mapsize) {
if (mapsize < sizeof(Elf64_Ehdr)) return false;
if (memcmp(elf->e_ident, ELFMAG, 4)) return false;
return (elf->e_ident[EI_CLASS] == ELFCLASSNONE ||
elf->e_ident[EI_CLASS] == ELFCLASS64);
}

20
libc/fmt/palandftoa.c

@ -34,16 +34,13 @@
#include "libc/fmt/palandprintf.h"
#include "libc/math.h"
static const int kPow10[] = {1, 10, 100, 1000, 10000,
100000, 1000000, 10000000, 100000000, 1000000000};
/**
* Formats floating point number.
*
* @see xdtoa() for higher precision at the cost of bloat
* @see palandprintf() which is intended caller
*/
int ftoa(int out(int, void *), void *arg, long double value, unsigned long prec,
int ftoa(int out(int, void *), void *arg, long double value, int prec,
unsigned long width, unsigned long flags) {
long whole, frac;
long double tmp, diff;
@ -72,32 +69,31 @@ int ftoa(int out(int, void *), void *arg, long double value, unsigned long prec,
prec = 6;
}
/* limit precision to 9, cause a prec >= 10 can lead to overflow errors */
while (len < PRINTF_FTOA_BUFFER_SIZE && prec > 9) {
while (len < PRINTF_FTOA_BUFFER_SIZE && prec > 14) {
buf[len++] = '0';
prec--;
}
whole = truncl(fabsl(value));
tmp = (fabsl(value) - whole) * kPow10[prec];
tmp = (fabsl(value) - whole) * exp10l(prec);
frac = tmp;
diff = tmp - frac;
if (diff > 0.5) {
if (diff > .5) {
++frac; /* handle rollover, e.g. case 0.99 with prec 1 is 1.0 */
if (frac >= kPow10[prec]) {
if (frac >= exp10l(prec)) {
frac = 0;
++whole;
}
} else if (diff < 0.5) {
} else if (diff < .5) {
} else if (!frac || (frac & 1)) {
++frac; /* if halfway, round up if odd OR if last digit is 0 */
}
if (!prec) {
diff = fabsl(value) - whole;
if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
/* exactly 0.5 and ODD, then round up */
if ((!(diff < .5) || (diff > .5)) && (whole & 1)) {
/* exactly .5 and ODD, then round up */
/* 1.5 -> 2, but 2.5 -> 2 */
++whole;
}

2
libc/fmt/palandprintf.h

@ -8,7 +8,7 @@
COSMOPOLITAN_C_START_
int spacepad(int(int, void *), void *, unsigned long) hidden;
int ftoa(int(int, void *), void *, long double, unsigned long, unsigned long,
int ftoa(int(int, void *), void *, long double, int, unsigned long,
unsigned long) hidden;
int stoa(int(int, void *), void *, void *, unsigned long, unsigned long,
unsigned long, unsigned char, unsigned char) hidden;

132
libc/integral/c.inc

@ -179,7 +179,7 @@ typedef struct axdx_t {
#undef __SIZEOF_INTMAX__
#endif
#if !defined(__STRICT_ANSI__) && __SIZEOF_POINTER__ == 8 && \
(__GNUC__ * 100 + __GNUC_MINOR__ >= 406 || defined(__llvm__))
((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 406 || defined(__llvm__))
#define __SIZEOF_INTMAX__ 16
#else
#define __SIZEOF_INTMAX__ __SIZEOF_POINTER__
@ -279,7 +279,7 @@ typedef uint64_t uintmax_t;
#ifndef noinstrument
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__no_instrument_function__) || \
__GNUC__ * 100 + __GNUC_MINOR__ >= 204)
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 204)
#define noinstrument __attribute__((__no_instrument_function__))
#else
#define noinstrument
@ -287,8 +287,9 @@ typedef uint64_t uintmax_t;
#endif
#ifndef noreturn
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__noreturn__) || __GNUC__ * 100 + __GNUC_MINOR__ >= 208)
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__noreturn__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 208)
#define noreturn __attribute__((__noreturn__))
#else
#define noreturn
@ -301,8 +302,9 @@ typedef uint64_t uintmax_t;
* @see pureconst
*/
#ifndef nosideeffect
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__pure__) || __GNUC__ * 100 + __GNUC_MINOR__ >= 296)
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__pure__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 296)
#define nosideeffect __attribute__((__pure__))
#else
#define nosideeffect
@ -310,8 +312,9 @@ typedef uint64_t uintmax_t;
#endif
#ifndef noinline
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__noinline__) || __GNUC__ * 100 + __GNUC_MINOR__ >= 301)
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__noinline__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 301)
#define noinline __attribute__((__noinline__))
#else
#define noinline
@ -319,8 +322,9 @@ typedef uint64_t uintmax_t;
#endif
#ifndef noclone
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__noclone__) || __GNUC__ * 100 + __GNUC_MINOR__ >= 405)
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__noclone__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 405)
#define noclone __attribute__((__noclone__))
#else
#define noclone
@ -343,9 +347,11 @@ typedef uint64_t uintmax_t;
#ifdef __cplusplus
#define forceinline inline
#else
#if !defined(__STRICT_ANSI__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 302
#if __GNUC__ * 100 + __GNUC_MINOR__ >= 403 || !defined(__cplusplus) || \
(defined(__clang__) && \
#if !defined(__STRICT_ANSI__) && \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 302
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403 || \
!defined(__cplusplus) || \
(defined(__clang__) && \
(defined(__GNUC_STDC_INLINE__) || defined(__GNUC_GNU_INLINE__)))
#if defined(__GNUC_STDC_INLINE__) || defined(__cplusplus)
#define forceinline \
@ -379,8 +385,9 @@ typedef uint64_t uintmax_t;
* @see unsigned char
*/
#ifndef mayalias
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__may_alias__) || __GNUC__ * 100 + __GNUC_MINOR__ >= 303)
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__may_alias__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 303)
#define mayalias __attribute__((__may_alias__))
#else
#define mayalias
@ -393,8 +400,9 @@ typedef uint64_t uintmax_t;
* @see gc(), free(), close(), etc.
*/
#ifndef nodiscard
#if !defined(__STRICT_ANSI__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 304 || \
__has_attribute(__warn_unused_result__))
#if !defined(__STRICT_ANSI__) && \
((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 304 || \
__has_attribute(__warn_unused_result__))
#define nodiscard __attribute__((__warn_unused_result__))
#else
#define nodiscard
@ -416,7 +424,7 @@ typedef uint64_t uintmax_t;
#ifndef flattenout
#if __has_attribute(__flatten__) || \
(__GNUC__ * 100 + __GNUC_MINOR__ >= 401 && !defined(__llvm__))
((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 401 && !defined(__llvm__))
#define flattenout __attribute__((__flatten__))
#else
#define flattenout
@ -424,9 +432,10 @@ typedef uint64_t uintmax_t;
#endif
#ifndef externinline
#if !defined(__STRICT_ANSI__) && \
(!defined(__cplusplus) || __GNUC__ * 100 + __GNUC_MINOR__ >= 403 || \
(defined(__clang__) && \
#if !defined(__STRICT_ANSI__) && \
(!defined(__cplusplus) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403 || \
(defined(__clang__) && \
(defined(__GNUC_STDC_INLINE__) || defined(__GNUC_GNU_INLINE__))))
#if defined(__GNUC_STDC_INLINE__) || defined(__cplusplus)
#define externinline extern __inline __attribute__((__gnu_inline__))
@ -443,16 +452,18 @@ typedef uint64_t uintmax_t;
* @note can be used to minimize page-faults and improve locality
*/
#ifndef relegated
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__cold__) || __GNUC__ * 100 + __GNUC_MINOR__ >= 403)
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__cold__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403)
#define relegated __attribute__((__cold__))
#else
#define relegated
#endif
#endif
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__warning__) || __GNUC__ * 100 + __GNUC_MINOR__ >= 403)
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__warning__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403)
#define warnifused(s) __attribute__((__warning__(s)))
#else
#define warnifused(s)
@ -465,7 +476,8 @@ typedef uint64_t uintmax_t;
*/
#ifndef firstclass
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__hot__) || __GNUC__ * 100 + __GNUC_MINOR__ >= 403)
(__has_attribute(__hot__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403)
#define firstclass __attribute__((__hot__))
#else
#define firstclass
@ -479,8 +491,9 @@ typedef uint64_t uintmax_t;
* runtime too (only in MODE=dbg mode) by synthetic Ubsan code.
*/
#ifndef paramsnonnull
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__nonnull__) || __GNUC__ * 100 + __GNUC_MINOR__ >= 403)
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__nonnull__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403)
#define paramsnonnull(opt_1idxs) __attribute__((__nonnull__ opt_1idxs))
#else
#define paramsnonnull(opt_1idxs)
@ -505,7 +518,7 @@ typedef uint64_t uintmax_t;
*/
#if __STDC_VERSION__ + 0 < 199901L && !defined(restrict)
#if !defined(__STRICT_ANSI__) && !defined(__cplusplus) && \
(__GNUC__ * 100 + __GNUC_MINOR__ >= 301 || defined(_MSC_VER))
((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 301 || defined(_MSC_VER))
#define restrict __restrict__
#else
#define restrict
@ -520,7 +533,8 @@ typedef uint64_t uintmax_t;
#ifndef nocallback
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__leaf__) || \
(!defined(__llvm__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 406))
(!defined(__llvm__) && \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 406))
#define nocallback __attribute__((__leaf__))
#else
#define nocallback
@ -529,7 +543,8 @@ typedef uint64_t uintmax_t;
#ifndef nothrow
#if defined(__cplusplus) && !defined(__STRICT_ANSI__) && \
(__has_attribute(nothrow) || __GNUC__ * 100 + __GNUC_MINOR__ >= 303)
(__has_attribute(nothrow) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 303)
#define nothrow __attribute__((__nothrow__))
#elif defined(_MSC_VER)
#define nothrow __declspec(nothrow)
@ -545,7 +560,8 @@ typedef uint64_t uintmax_t;
*/
#ifndef nooptimize
#ifndef __STRICT_ANSI__
#if __GNUC__ * 100 + __GNUC_MINOR__ >= 407 || __has_attribute(__optimize__)
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407 || \
__has_attribute(__optimize__)
#define nooptimize __attribute__((__optimize__(1)))
#elif defined(__llvm__) || __has_attribute(__optnone__)
#define nooptimize __attribute__((__optnone__))
@ -564,7 +580,8 @@ typedef uint64_t uintmax_t;
*/
#ifndef optimizesize
#ifndef __STRICT_ANSI__
#if __GNUC__ * 100 + __GNUC_MINOR__ >= 407 || __has_attribute(__optimize__)
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407 || \
__has_attribute(__optimize__)
#define optimizesize __attribute__((__optimize__("s")))
#elif defined(__llvm__) || __has_attribute(__optnone__)
#define optimizesize __attribute__((__optnone__))
@ -584,8 +601,9 @@ typedef uint64_t uintmax_t;
* @todo this is dangerous delete?
*/
#ifndef optimizespeed
#if !defined(__STRICT_ANSI__) && \
(__GNUC__ * 100 + __GNUC_MINOR__ >= 407 || __has_attribute(__optimize__))
#if !defined(__STRICT_ANSI__) && \
((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407 || \
__has_attribute(__optimize__))
#define optimizespeed __attribute__((__optimize__(3)))
#else
#define optimizespeed
@ -596,8 +614,9 @@ typedef uint64_t uintmax_t;
* Declares prototype that behaves similar to setjmp() or vfork().
*/
#ifndef returnstwice
#if !defined(__STRICT_ANSI__) && (__has_attribute(__returns_twice__) || \
__GNUC__ * 100 + __GNUC_MINOR__ >= 402)
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__returns_twice__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 402)
#define returnstwice __attribute__((__returns_twice__))
#else
#define returnstwice
@ -622,8 +641,9 @@ typedef uint64_t uintmax_t;
* @see nodebuginfo
*/
#ifndef artificial
#if !defined(__STRICT_ANSI__) && (__has_attribute(__artificial__) || \
__GNUC__ * 100 + __GNUC_MINOR__ >= 403)
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__artificial__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403)
#define artificial __attribute__((__artificial__))
#else
#define artificial
@ -636,8 +656,9 @@ typedef uint64_t uintmax_t;
* @see libc/dce.h
*/
#ifndef microarchitecture
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__target__) || __GNUC__ * 100 + __GNUC_MINOR__ >= 404)
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__target__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 404)
#define microarchitecture(march) __attribute__((__target__(march)))
#else
#define microarchitecture(march)
@ -661,7 +682,7 @@ typedef uint64_t uintmax_t;
* Defines function with prologue that fixes misaligned stack.
* @see nocallersavedregisters and consider assembly
*/
#if __GNUC__ * 100 + __GNUC_MINOR__ >= 408 || \
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 408 || \
__has_attribute(__force_align_arg_pointer__)
#define forcealignargpointer __attribute__((__force_align_arg_pointer__))
#else
@ -675,8 +696,9 @@ typedef uint64_t uintmax_t;
* runtime too by synthetic code, only in MODE=dbg mode.
*/
#ifndef returnsnonnull
#if !defined(__STRICT_ANSI__) && (__has_attribute(__returns_nonnull__) || \
__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__returns_nonnull__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409)
#define returnsnonnull __attribute__((__returns_nonnull__))
#else
#define returnsnonnull
@ -690,8 +712,9 @@ typedef uint64_t uintmax_t;
* @param (alignment, misalignment)
* @see attributeallocalign(), returnspointerwithnoaliases, mallocesque
*/
#if !defined(__STRICT_ANSI__) && (__has_attribute(__assume_aligned__) || \
__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__assume_aligned__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409)
#define returnsaligned(x) __attribute__((__assume_aligned__ x))
#else
#define returnsaligned(x)
@ -702,8 +725,9 @@ typedef uint64_t uintmax_t;
* @see attributeallocsize(), attributeallocalign()
*/
#ifndef returnspointerwithnoaliases
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__malloc__) || __GNUC__ * 100 + __GNUC_MINOR__ >= 409)
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__malloc__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409)
#define returnspointerwithnoaliases __attribute__((__malloc__))
#elif defined(_MSC_VER)
#define returnspointerwithnoaliases __declspec(allocator)
@ -713,8 +737,9 @@ typedef uint64_t uintmax_t;
#endif
#ifndef attributeallocsize
#if !defined(__STRICT_ANSI__) && (__has_attribute(__alloc_size__) || \
__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__alloc_size__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409)
#define attributeallocsize(x) __attribute__((__alloc_size__ x))
#else
#define attributeallocsize(x)
@ -722,8 +747,9 @@ typedef uint64_t uintmax_t;
#endif
#ifndef attributeallocalign
#if !defined(__STRICT_ANSI__) && (__has_attribute(__alloc_align__) || \
__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__alloc_align__) || \
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409)
#define attributeallocalign(x) __attribute__((__alloc_align__ x))
#else
#define attributeallocalign(x)
@ -747,7 +773,7 @@ typedef uint64_t uintmax_t;
#if __cplusplus + 0 >= 201103L
#define autotype(x) auto
#elif (__has_builtin(auto_type) || defined(__llvm__) || \
__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409)
#define autotype(x) __auto_type
#else
#define autotype(x) typeof(x)

2
libc/integral/normalize.inc

@ -75,7 +75,7 @@
#define ENV_MAX 0x7fff /* b/c windows */
#define ARG_MAX 0x3fff /* b/c windows */
#define CMD_MAX 0x4000 /* b/c windows */
#define PATH_MAX 248 /* b/c windows */
#define PATH_MAX 248 /* b/c win32 apis limit ~248..260 */
#define NAME_MAX 63 /* b/c dns */
#define CHILD_MAX 25 /* only if malloc isn't linked */
#define OPEN_MAX 16 /* only if malloc isn't linked */

45
libc/intrin/mpsadbw.c

@ -0,0 +1,45 @@
/*-*- 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/intrin/mpsadbw.h"
#include "libc/macros.h"
#include "libc/str/str.h"
/**
* Computes multiple sum of absolute differences.
*
* This appears to be intended for video encoding motion estimation. It
* can be combined with phminposuw. That allows us to search for an int
* overlapping inside 𝑏 that's nearest to an aligned int in 𝑎.
*
* @note goes fast w/ sse4 cf. core c. 2006 cf. bulldozer c. 2011
* @mayalias
*/
void(mpsadbw)(uint16_t c[8], const uint8_t b[16], const uint8_t a[16],
uint8_t control) {
unsigned i, j;
uint16_t r[8];
for (i = 0; i < 8; ++i) {
r[i] = 0;
for (j = 0; j < 4; ++j) {
r[i] += ABS(b[(control & 4) + i + j] - a[(control & 3) * 4 + j]);
}
}
memcpy(c, r, 16);
}

41
libc/intrin/mpsadbw.h

@ -0,0 +1,41 @@
#ifndef COSMOPOLITAN_LIBC_INTRIN_MPSADBW_H_
#define COSMOPOLITAN_LIBC_INTRIN_MPSADBW_H_
#include "libc/intrin/macros.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void mpsadbw(uint16_t[8], const uint8_t[16], const uint8_t[16], uint8_t);
#ifndef __STRICT_ANSI__
__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))) { \
__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("mpsadbw\t%2,%1,%0" \
: "=x"(*Xmm0) \
: "x"(*Xmm2), "i"(I), "0"(*Xmm1)); \
} else { \
asm("vmpsadbw\t%3,%2,%1,%0" \
: "=x"(*Xmm0) \
: "x"(*Xmm1), "x"(*Xmm2), "i"(I)); \
} \
} else { \
unsigned long Vimm = (I); \
typeof(__mpsadbws) *Fn; \
Fn = (typeof(__mpsadbws) *)((uintptr_t)&__mpsadbws + (Vimm & 7) * 8); \
*Xmm0 = Fn(*Xmm1, *Xmm2); \
} \
} else { \
mpsadbw(C, B, A, I); \
} \
} while (0)
#endif
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_INTRIN_MPSADBW_H_ */

33
libc/nexgen32e/kcrc32tab.S → libc/intrin/mpsadbws.S

@ -19,24 +19,17 @@
*/
#include "libc/macros.h"
/ Phil Katz CRC-32 Polynomial
/ x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
/ 0b100000100110000010001110110110111
/ bitreverse32(0x104c11db7)
#define kZipCrc32Polynomial 0xedb88320
.initbss 300,_init_kCrc32Tab
kCrc32Tab:
.rept 256
.long 0
/ Jump table for mpsadbw() with non-constexpr immediate parameter.
/
/ @note needs sse4 cf. core c. 2006 cf. bulldozer c. 2011
/ @see mpsadbw()
.align 8
__mpsadbws:
i = 0
.rept 8
mpsadbw $i,%xmm1,%xmm0
ret
nop
i = i + 1
.endr
.endobj kCrc32Tab,globl,hidden
.previous
.init.start 300,_init_kCrc32Tab
push %rsi
mov $kZipCrc32Polynomial,%esi
call crc32init
pop %rsi
.init.end 300,_init_kCrc32Tab
.source __FILE__
.endfn __mpsadbws,globl

2
libc/intrin/repstosb.h

@ -14,7 +14,7 @@ forceinline void *repstosb(void *dest, unsigned char al, size_t cx) {
void *Di = (DI); \
size_t Cx = (CX); \
unsigned char Al = (AL); \
asm("rep stosb" \
asm("rep stosb %b5,(%0)" \
: "=D"(Di), "=c"(Cx), "=m"(*(char(*)[Cx])Di) \
: "0"(Di), "1"(Cx), "a"(Al)); \
Di; \

317
libc/log/asan.c

@ -102,48 +102,120 @@ struct AsanGlobal {
char *odr_indicator;
};
static bool __asan_is_mapped(void *p) {
int x, i;
x = (intptr_t)p >> 16;
i = FindMemoryInterval(&_mmi, x);