Get codebase completely working with LLVM

You can now build Cosmopolitan with Clang:

    make -j8 MODE=llvm
    o/llvm/examples/hello.com

The assembler and linker code is now friendly to LLVM too.
So it's not needed to configure Clang to use binutils under
the hood. If you love LLVM then you can now use pure LLVM.
This commit is contained in:
Justine Tunney 2021-02-08 09:19:00 -08:00
parent 0e36cb3ac4
commit e75ffde09e
4528 changed files with 7776 additions and 11640 deletions

View file

@ -4,27 +4,8 @@
#include "libc/mem/mem.h"
#include "libc/str/str.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#if 0
/**
* @fileoverview Cosmopolitan Array List.
*
* This is a generically-typed ArrayList<T> template which follows a
* duck-typing philosophy like Python, exporting an interface paradigm
* similar to Go, that's implicitly defined by way of macros like Lisp.
*
* struct MyArrayList {
* size_t i; // current item count
* size_t n; // current item capacity
* T *p; // pointer to array (initially NULL)
* };
*
* Any struct with those fields can be used. It's also very important
* that other data structures, which reference items in an arraylist, do
* so using indices rather than pointers, since realloc() can relocate.
*
* @see libc/mem/grow.c
*/
#endif
/* TOOD(jart): DELETE */
#define append(ARRAYLIST, ITEM) concat((ARRAYLIST), (ITEM), 1)
@ -38,7 +19,7 @@
size_t Idx = List->i; \
if (Idx + Count < List->n || __grow(&List->p, &List->n, SizE, Count)) { \
memcpy(&List->p[Idx], Item, SizE *Count); \
atomic_store(&List->i, Idx + Count); \
List->i = Idx + Count; \
} else { \
Idx = -1UL; \
} \

View file

@ -234,12 +234,10 @@ intptr_t atomic_store(void *, intptr_t, size_t);
* @return LOCALVAR[0]
* @see xchg()
*/
#define lockxchg(MEMORY, LOCALVAR) \
({ \
_Static_assert( \
__builtin_types_compatible_p(typeof(*(MEMORY)), typeof(*(LOCALVAR)))); \
asm("xchg\t%0,%1" : "+%m"(*(MEMORY)), "+r"(*(LOCALVAR))); \
*(LOCALVAR); \
#define lockxchg(MEMORY, LOCALVAR) \
({ \
asm("xchg\t%0,%1" : "+%m"(*(MEMORY)), "+r"(*(LOCALVAR))); \
*(LOCALVAR); \
})
/**

View file

@ -1,5 +1,6 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_SYSCALLS_H_
#define COSMOPOLITAN_LIBC_CALLS_SYSCALLS_H_
#include "libc/calls/struct/dirent.h"
#include "libc/calls/struct/iovec.h"
#include "libc/calls/struct/rlimit.h"
#include "libc/calls/struct/rusage.h"
@ -62,7 +63,6 @@ COSMOPOLITAN_C_START_
*/
typedef int sig_atomic_t;
typedef struct dirstream DIR;
extern const struct sigset kSigsetFull;
extern const struct sigset kSigsetEmpty;
@ -102,7 +102,6 @@ int execvp(const char *, char *const[]) paramsnonnull();
int execvpe(const char *, char *const[], char *const[]) paramsnonnull();
int faccessat(int, const char *, int, uint32_t);
int fadvise(int, uint64_t, uint64_t, int);
int fallocate(int, int32_t, int64_t, int64_t);
int fchmod(int, uint32_t) nothrow;
int fchmodat(int, const char *, uint32_t, uint32_t);
int fchown(int, uint32_t, uint32_t);
@ -147,7 +146,6 @@ int personality(uint64_t);
int pipe(int[hasatleast 2]);
int pipe2(int[hasatleast 2], int);
int posix_fadvise(int, uint64_t, uint64_t, int);
int posix_fallocate(int, int64_t, int64_t);
int posix_madvise(void *, uint64_t, int);
int raise(int);
int readlink(const char *, char *, size_t);

View file

@ -1,74 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/nt/enum/fsctl.h"
#include "libc/nt/files.h"
#include "libc/nt/struct/filezerodatainformation.h"
#include "libc/sysv/consts/falloc.h"
#include "libc/sysv/errfuns.h"
/**
* Manipulates underlying physical medium of file.
*
* This system call generalizes to many powerful use cases on Linux,
* such as creating gigantic sparse files that take up little space.
* This API can polyfill a certain subset of parameters safely, e.g.
* ones identical to ftruncate(), but errs on the side of caution.
*
* @param fd must be open for writing
* @param mode can be 0, FALLOC_xxx
* @param length is how much physical space to reserve / commit
* @return 0 on success, or -1 w/ errno
* @note limited availability on rhel5 and openbsd
* @see ftruncate()
*/
int fallocate(int fd, int32_t mode, int64_t offset, int64_t length) {
int rc;
uint32_t br;
if (mode == -1 /* our sysvconsts definition */) return eopnotsupp();
if (!mode && !length) return ftruncate(fd, offset);
if (IsLinux()) {
rc = sys_fallocate(fd, mode, offset, length);
if (rc == 0x011d) rc = enosys(); /*RHEL5:CVE-2010-3301*/
return rc;
} else if (!IsWindows()) {
return sys_posix_fallocate(fd, offset, length);
} else {
if (!__isfdkind(fd, kFdFile)) return ebadf();
if (mode == FALLOC_FL_ZERO_RANGE) {
if (DeviceIoControl(
g_fds.p[fd].handle, kNtFsctlSetZeroData,
&(struct NtFileZeroDataInformation){offset, offset + length},
sizeof(struct NtFileZeroDataInformation), NULL, 0, &br, NULL)) {
return 0;
} else {
return __winerr();
}
} else if (!mode && !offset) {
/*
* this should commit physical space
* but not guaranteed zero'd like linux
*/
return sys_ftruncate_nt(fd, length);
} else {
return enosys();
}
}
}

View file

@ -29,7 +29,6 @@
* since the prior extends logically and the latter physically
* @return 0 on success, or -1 w/ errno
* @asyncsignalsafe
* @see fallocate()
*/
int ftruncate(int fd, int64_t length) {
if (!IsWindows()) {

View file

@ -19,13 +19,13 @@
#include "libc/macros.h"
.source __FILE__
/ Obtains WIN32 magic path, e.g. GetTempPathA.
/
/ @param rax is address of ANSI path provider function
/ @param rdi is output buffer
/ @param rdx is output buffer size in bytes that's >0
/ @return eax is string length w/ NUL that's ≤ edx
/ @return rdi is rdi+edx
// Obtains WIN32 magic path, e.g. GetTempPathA.
//
// @param rax is address of ANSI path provider function
// @param rdi is output buffer
// @param rdx is output buffer size in bytes that's >0
// @return eax is string length w/ NUL that's ≤ edx
// @return rdi is rdi+edx
.text.startup
__getntsyspath:
push %rbp
@ -40,14 +40,14 @@ __getntsyspath:
cmovbe %edx,%eax
cmp $1,%eax # leave empty strings empty
jbe 1f
cmpb $'\\,-1(%rdi,%rax) # guarantee trailing slash
cmpb $'\\',-1(%rdi,%rax) # guarantee trailing slash
je 1f
movw $'\\,(%rdi,%rax)
movw $'\\',(%rdi,%rax)
inc %eax
1: inc %rdi # change backslash to slash
cmpb $'\\,-1(%rdi)
cmpb $'\\',-1(%rdi)
jne 2f
movb $'/,-1(%rdi)
movb $'/',-1(%rdi)
2: .loop 1b
leave
ret

View file

@ -22,8 +22,8 @@
#include "libc/sysv/errfuns.h"
textwindows int sys_getsetpriority_nt(int which, unsigned who, int value,
int (*impl)(int)) {
int (*impl)(int)) {
if (which != PRIO_PROCESS && which != PRIO_PGRP) return einval();
if (who && abs(who) != getpid() && abs(who) != gettid()) return eopnotsupp();
if (who && who != getpid() && who != gettid()) return eopnotsupp();
return impl(value);
}

View file

@ -19,9 +19,9 @@
#include "libc/macros.h"
.source __FILE__
/ Calls GetTempPathA() w/ different API.
/
/ @see GetSystemDirectoryA(), GetWindowsDirectoryA()
// Calls GetTempPathA() w/ different API.
//
// @see GetSystemDirectoryA(), GetWindowsDirectoryA()
GetTempPathA_flunk:
xchg %rcx,%rdx
jmp *__imp_GetTempPathA(%rip)

View file

@ -120,7 +120,6 @@ i32 sys_dup3(i32, i32, i32) hidden;
i32 sys_execve(const char *, char *const[], char *const[]) hidden;
i32 sys_faccessat(i32, const char *, i32, u32) hidden;
i32 sys_fadvise(i32, i64, i64, i32) hidden;
i32 sys_fallocate(i64, i32, i64, i64) hidden;
i32 sys_fchdir(i32) hidden;
i32 sys_fchmod(i32, u32) hidden;
i32 sys_fchmodat(i32, const char *, u32, u32) hidden;
@ -158,7 +157,6 @@ i32 sys_openat(i32, const char *, i32, ...) hidden;
i32 sys_pause(void) hidden;
i32 sys_pipe(i32[hasatleast 2]) hidden;
i32 sys_pipe2(i32[hasatleast 2], u32) hidden;
i32 sys_posix_fallocate(i64, i64, i64) hidden;
i32 sys_posix_openpt(i32) hidden;
i32 sys_renameat(i32, const char *, i32, const char *) hidden;
i32 sys_sched_setaffinity(i32, u64, const void *) hidden;
@ -277,7 +275,7 @@ ssize_t sys_write_nt(struct Fd *, const struct iovec *, size_t, ssize_t) hidden;
int64_t ntreturn(uint32_t);
void WinMainForked(void) hidden;
void *GetProcAddressModule(const char *, const char *) hidden;
int sys_getsetpriority_nt(int, unsigned, int, int (*)(int));
int sys_getsetpriority_nt(int, int, int, int (*)(int));
void ntcontext2linux(struct ucontext *, const struct NtContext *) hidden;
struct NtOverlapped *offset2overlap(int64_t, struct NtOverlapped *) hidden;
bool32 ntsetprivilege(i64, const char16_t *, u32) hidden;

View file

@ -22,9 +22,9 @@
#define BYTES 64
/ RII constant holding 'C:/WINDOWS/SYSTEM32' directory.
/
/ @note guarantees trailing slash if non-empty
// RII constant holding 'C:/WINDOWS/SYSTEM32' directory.
//
// @note guarantees trailing slash if non-empty
.initbss 300,_init_kNtSystemDirectory
kNtSystemDirectory:
.zero BYTES

View file

@ -22,9 +22,9 @@
#define BYTES 64
/ RII constant holding 'C:/WINDOWS' directory.
/
/ @note guarantees trailing slash if non-empty
// RII constant holding 'C:/WINDOWS' directory.
//
// @note guarantees trailing slash if non-empty
.initbss 300,_init_kNtWindowsDirectory
kNtWindowsDirectory:
.zero BYTES

View file

@ -22,10 +22,10 @@
#define kTmpPathMax 80
/ RII constant holding /tmp/ directory.
/
/ @note on win32 this is firstNonNull($TMP, $TEMP, $PWD)
/ @note guarantees trailing slash if non-empty
// RII constant holding /tmp/ directory.
//
// @note on win32 this is firstNonNull($TMP, $TEMP, $PWD)
// @note guarantees trailing slash if non-empty
.initbss 300,_init_kTmpPath
kTmpPath:
.zero kTmpPathMax
@ -33,8 +33,8 @@ kTmpPath:
.previous
.init.start 300,_init_kTmpPath
movl $'/|'t<<010|'m<<020|'p<<030,(%rdi)
movw $'/,4(%rdi)
movl $'/'|'t'<<010|'m'<<020|'p'<<030,(%rdi)
movw $'/',4(%rdi)
#if SupportsWindows()
pushpop kTmpPathMax,%rdx
ezlea GetTempPathA_flunk,ax

View file

@ -19,10 +19,10 @@
#include "libc/nexgen32e/x86feature.h"
#include "libc/macros.h"
/ Returns timestamp without needing system calls.
/
/ @return seconds since unix epoch in %st0
/ @note uses microsecond scale fallback on k8 or vm
// Returns timestamp without needing system calls.
//
// @return seconds since unix epoch in %st0
// @note uses microsecond scale fallback on k8 or vm
.initbss 202,_init_nowl
nowl: .quad 0
.endobj nowl,globl

View file

@ -1,33 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/sysv/errfuns.h"
/**
* Manipulates underlying physical medium of file, the POSIX way.
*
* @param fd must be open for writing
* @param length is how much physical space to reserve
* @return 0 on success, or -1 w/ errno
* @see fallocate(), ftruncate()
*/
int posix_fallocate(int fd, int64_t offset, int64_t length) {
return fallocate(fd, 0, offset, length);
}

View file

@ -19,18 +19,19 @@
#include "libc/calls/calls.h"
#include "libc/calls/termios.h"
#include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/fmt/itoa.h"
#include "libc/sysv/consts/termios.h"
#include "libc/sysv/errfuns.h"
errno_t ptsname_r(int fd, char *buf, size_t size) {
int pty;
char tb[32];
if (size) {
if (!buf) return einval();
if (ioctl(fd, TIOCGPTN, &pty) == -1) return errno;
if (snprintf(buf, size, "/dev/pts/%d", pty) >= size) {
return (errno = ERANGE);
}
int64toarray_radix10(pty, stpcpy(tb, "/dev/pts/"));
if (strlen(tb) + 1 >= size) return (errno = ERANGE);
stpcpy(buf, tb);
/* TODO(jart): OpenBSD OMG */
}
return 0;

View file

@ -19,10 +19,10 @@
#include "libc/macros.h"
.source __FILE__
/ Sets effective group ID.
/
/ @param %edi is group id
/ @see setgid(), getauxval(AT_SECURE)
// Sets effective group ID.
//
// @param %edi is group id
// @see setgid(), getauxval(AT_SECURE)
setegid:push %rbp
mov %rsp,%rbp
.profilable

View file

@ -19,10 +19,10 @@
#include "libc/macros.h"
.source __FILE__
/ Sets effective user ID.
/
/ @param %edi is user id
/ @see setuid(), getauxval(AT_SECURE)
// Sets effective user ID.
//
// @param %edi is user id
// @see setuid(), getauxval(AT_SECURE)
seteuid:push %rbp
mov %rsp,%rbp
.profilable

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
@ -134,15 +135,15 @@ static void sigaction_native2cosmo(union metasigaction *sa) {
* @vforksafe
*/
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) &&
sizeof(struct sigaction) > sizeof(struct sigaction_netbsd));
int64_t arg4, arg5;
int rc, rva, oldrva;
struct sigaction *ap, copy;
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) &&
sizeof(struct sigaction) > sizeof(struct sigaction_netbsd));
if (IsMetal()) return enosys(); /* TODO: Signals on Metal */
if (!(0 < sig && sig < NSIG)) return einval();
if (sig == SIGKILL || sig == SIGSTOP) return einval();

View file

@ -20,16 +20,16 @@
#include "libc/macros.h"
.source __FILE__
/ BSD signal handler.
/
/ This is needed because (1) a signal is allowed to trigger at
/ just about any time, and leaf functions (e.g. memcpy) aren't
/ required to leave Cosmopolitan's image base register alone.
/
/ @param %edi is the signal number
/ @param %rsi will be passed for sigactions
/ @param %rdx will be passed for sigactions
/ @return true if handler was invoked
// BSD signal handler.
//
// This is needed because (1) a signal is allowed to trigger at
// just about any time, and leaf functions (e.g. memcpy) aren't
// required to leave Cosmopolitan's image base register alone.
//
// @param %edi is the signal number
// @param %rsi will be passed for sigactions
// @param %rdx will be passed for sigactions
// @return true if handler was invoked
__sigenter:
push %rbp
mov %rsp,%rbp

View file

@ -10,5 +10,8 @@ struct dirent { /* linux getdents64 abi */
char d_name[256]; /* NUL-terminated basename */
};
struct dirstream;
typedef struct dirstream DIR;
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_DIRENT_H_ */

View file

@ -21,6 +21,7 @@
#include "libc/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/fmt/fmt.h"
#include "libc/fmt/itoa.h"
#include "libc/log/log.h"
#include "libc/nt/console.h"
#include "libc/nt/enum/consolemodeflags.h"
@ -58,7 +59,7 @@ static int ttyname_linux(int fd, char *buf, size_t size) {
struct stat st1, st2;
if (!isatty(fd)) return errno;
char name[PATH_MAX];
snprintf(name, sizeof(name), "/proc/self/fd/%d", fd);
int64toarray_radix10(fd, stpcpy(name, "/proc/self/fd/"));
ssize_t got;
got = readlink(name, buf, size);
if (got == -1) return errno;

View file

@ -4,7 +4,5 @@
typedef void (*sighandler_t)(int);
typedef void (*sighandler_t)(int);
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_TYPEDEF_SIGHANDLER_T_H_ */

View file

@ -23,11 +23,11 @@
.section .start,"ax",@progbits
.align 16
/ System Five userspace program entrypoint.
/
/ @param rsp is [n,argv₀..argvₙ₋₁,0,envp₀..,0,auxv₀..,0,..]
/ @note FreeBSD is special (see freebsd/lib/csu/amd64/...)
/ @noreturn
// System Five userspace program entrypoint.
//
// @param rsp is [n,argv₀..argvₙ₋₁,0,envp₀..,0,auxv₀..,0,..]
// @note FreeBSD is special (see freebsd/lib/csu/amd64/...)
// @noreturn
_start:
#if SupportsFreebsd()
test %rdi,%rdi
@ -39,12 +39,12 @@ _start:
lea 8(%rsp),%rsi # argv
lea 24(%rsp,%rbx,8),%rdx # envp
.frame0
/ bofram 9f
.weak idata.iat
.weak idata.iatend
// bofram 9f
.weak ape_idata_iat
.weak ape_idata_iatend
ezlea missingno,ax # make win32 imps noop
ezlea idata.iat,di
ezlea idata.iatend,cx
ezlea ape_idata_iat,di
ezlea ape_idata_iatend,cx
sub %rdi,%rcx
shr $3,%ecx
rep stosq
@ -70,11 +70,11 @@ _start:
.endfn _start,weak,hidden
#if SupportsXnu()
/ Macintosh userspace program entrypoint.
/
/ @param rsp is [n,argv₀..argvₙ₋₁,0,envp₀..,0,auxv₀..,0,..]
/ @note FreeBSD is special (see freebsd/lib/csu/amd64/...)
/ @noreturn
// Macintosh userspace program entrypoint.
//
// @param rsp is [n,argv₀..argvₙ₋₁,0,envp₀..,0,auxv₀..,0,..]
// @note FreeBSD is special (see freebsd/lib/csu/amd64/...)
// @noreturn
_xnu: movb $XNU,__hostos(%rip)
jmp 0b
.endfn _xnu,weak,hidden

View file

@ -13,10 +13,8 @@ struct DnsHeader {
uint16_t arcount; /* additional record count */
};
int serializednsheader(uint8_t *buf, size_t size,
const struct DnsHeader header);
int deserializednsheader(struct DnsHeader *header, const uint8_t *buf,
size_t size);
int serializednsheader(uint8_t *, size_t, const struct DnsHeader);
int deserializednsheader(struct DnsHeader *, const uint8_t *, size_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -54,7 +54,11 @@ static textwindows noinline char *getnthoststxtpath(char *pathbuf,
* @note yoinking realloc() ensures there's no size limits
*/
const struct HostsTxt *gethoststxt(void) {
struct HostsTxtInitialStaticMemory *init = &g_hoststxt_init;
FILE *f;
const char *path;
char pathbuf[PATH_MAX];
struct HostsTxtInitialStaticMemory *init;
init = &g_hoststxt_init;
if (!g_hoststxt) {
g_hoststxt = &init->ht;
init->ht.entries.n = pushpop(ARRAYLEN(init->entries));
@ -62,14 +66,12 @@ const struct HostsTxt *gethoststxt(void) {
init->ht.strings.n = pushpop(ARRAYLEN(init->strings));
init->ht.strings.p = init->strings;
__cxa_atexit(freehoststxt, &g_hoststxt, NULL);
char pathbuf[PATH_MAX];
const char *path = "/etc/hosts";
path = "/etc/hosts";
if (IsWindows()) {
path = firstnonnull(getnthoststxtpath(pathbuf, ARRAYLEN(pathbuf)), path);
}
FILE *f;
if (!(f = fopen(path, "r")) || parsehoststxt(g_hoststxt, f) == -1) {
if (!IsTiny()) fprintf(stderr, "%s: %s: %m\n", "warning", path);
/* TODO(jart): Elevate robustness. */
}
fclose(f);
sorthoststxt(g_hoststxt);

View file

@ -55,7 +55,7 @@ const struct ResolvConf *getresolvconf(void) {
rc = getntnameservers(g_resolvconf);
}
if (rc == -1 && !IsTiny()) {
fprintf(stderr, "%s: %m\n", "nameserver discovery failed");
/* TODO(jart): Elevate robustness. */
}
}
return g_resolvconf;

View file

@ -18,15 +18,20 @@
*/
#include "libc/elf/def.h"
#include "libc/elf/elf.h"
#include "libc/str/str.h"
char *GetElfStringTable(const Elf64_Ehdr *elf, size_t mapsize) {
char *name;
Elf64_Half i;
Elf64_Shdr *shdr;
for (i = elf->e_shnum; i > 0; --i) {
if (i - 1 == elf->e_shstrndx) continue;
shdr = GetElfSectionHeaderAddress(elf, mapsize, i - 1);
for (i = 0; i < elf->e_shnum; ++i) {
shdr = GetElfSectionHeaderAddress(elf, mapsize, i);
if (shdr->sh_type == SHT_STRTAB) {
return GetElfSectionAddress(elf, mapsize, shdr);
name = GetElfSectionName(elf, mapsize,
GetElfSectionHeaderAddress(elf, mapsize, i));
if (name && !strcmp(name, ".strtab")) {
return GetElfSectionAddress(elf, mapsize, shdr);
}
}
}
return NULL;

View file

@ -17,7 +17,6 @@ COSMOPOLITAN_C_START_
int abs(int) libcesque pureconst;
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 atoi(const char *) paramsnonnull() libcesque;
long atol(const char *) paramsnonnull() libcesque;

View file

@ -26,7 +26,7 @@
* @param a needs at least 21 bytes
* @return bytes written w/o nul
*/
noinline size_t uint64toarray_radix10(uint64_t i, char *a) {
noinline size_t uint64toarray_radix10(uint64_t i, char a[hasatleast 21]) {
size_t j;
j = 0;
do {
@ -43,7 +43,7 @@ noinline size_t uint64toarray_radix10(uint64_t i, char *a) {
* @param a needs at least 21 bytes
* @return bytes written w/o nul
*/
size_t int64toarray_radix10(int64_t i, char *a) {
size_t int64toarray_radix10(int64_t i, char a[hasatleast 21]) {
if (i >= 0) return uint64toarray_radix10(i, a);
*a++ = '-';
return 1 + uint64toarray_radix10(-i, a);

View file

@ -1,31 +0,0 @@
/*-*- mode:c; indent-tabs-mode:nil; tab-width:2; coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/bits.h"
#include "libc/fmt/conv.h"
char *ltpcpy(char *dst, long x) {
unsigned len = llog10(abs(x)) + 1;
if (x < 0) *dst++ = '-';
unsigned i = len;
do {
dst[--i] = '0' + x % 10;
x /= 10;
} while (i);
return dst + len;
}

View file

@ -129,7 +129,7 @@ hidden int palandprintf(void *fn, void *arg, const char *format, va_list va) {
int w, flags, width, lasterr, precision;
lasterr = errno;
out = fn ? fn : (int (*)(int, void *))missingno;
out = fn ? fn : (void *)missingno;
while (*format) {
/* %[flags][width][.precision][length] */
@ -267,9 +267,8 @@ hidden int palandprintf(void *fn, void *arg, const char *format, va_list va) {
case 'u': {
flags &= ~FLAGS_HASH; /* no hash for dec format */
DoNumber:
if (!weaken(ntoa) ||
weaken(ntoa)(out, arg, va, signbit, log2base, precision, width,
flags, alphabet) == -1) {
if (ntoa(out, arg, va, signbit, log2base, precision, width, flags,
alphabet) == -1) {
return -1;
}
break;
@ -282,8 +281,7 @@ hidden int palandprintf(void *fn, void *arg, const char *format, va_list va) {
} else {
ldbl = va_arg(va, double);
}
if (!weaken(ftoa) ||
weaken(ftoa)(out, arg, ldbl, precision, width, flags) == -1) {
if (ftoa(out, arg, ldbl, precision, width, flags) == -1) {
return -1;
}
break;
@ -312,8 +310,7 @@ hidden int palandprintf(void *fn, void *arg, const char *format, va_list va) {
case 's':
p = va_arg(va, void *);
showstr:
if (!weaken(stoa) || weaken(stoa)(out, arg, p, flags, precision, width,
signbit, qchar) == -1) {
if (stoa(out, arg, p, flags, precision, width, signbit, qchar) == -1) {
return -1;
}
break;

View file

@ -17,22 +17,19 @@
* format strings are constexprs that only contain directives.
*/
#define PFLINK(FMT) \
({ \
if (___PFLINK(FMT, strpbrk, "bxdinupo")) STATIC_YOINK("ntoa"); \
if (___PFLINK(FMT, strpbrk, "fFgGaA")) STATIC_YOINK("ftoa"); \
if (___PFLINK(FMT, strpbrk, "cmrqs")) { \
STATIC_YOINK("stoa"); \
if (___PFLINK(FMT, strchr, '#')) STATIC_YOINK("kCp437"); \
if (___PFLINK(FMT, strstr, "%m")) STATIC_YOINK("strerror"); \
if (!IsTiny() && (___PFLINK(FMT, strstr, "%*") || \
___PFLINK(FMT, strpbrk, "0123456789"))) { \
STATIC_YOINK("strnwidth"); \
STATIC_YOINK("strnwidth16"); \
STATIC_YOINK("wcsnwidth"); \
} \
} \
FMT; \
#define PFLINK(FMT) \
({ \
if (___PFLINK(FMT, strpbrk, "cmrqs")) { \
if (___PFLINK(FMT, strchr, '#')) STATIC_YOINK("kCp437"); \
if (___PFLINK(FMT, strstr, "%m")) STATIC_YOINK("strerror"); \
if (!IsTiny() && (___PFLINK(FMT, strstr, "%*") || \
___PFLINK(FMT, strpbrk, "0123456789"))) { \
STATIC_YOINK("strnwidth"); \
STATIC_YOINK("strnwidth16"); \
STATIC_YOINK("wcsnwidth"); \
} \
} \
FMT; \
})
#define SFLINK(FMT) \
@ -40,7 +37,7 @@
if (___PFLINK(FMT, strchr, 'm')) { \
STATIC_YOINK("malloc"); \
STATIC_YOINK("calloc"); \
STATIC_YOINK("free_s"); \
STATIC_YOINK("free"); \
STATIC_YOINK("__grow"); \
} \
FMT; \
@ -70,8 +67,6 @@
#define SFLINK(FMT) FMT
#ifdef __GNUC__
__asm__(".section .yoink\n\t"
"nopl\tntoa(%rip)\n\t"
"nopl\tftoa(%rip)\n\t"
"nopl\tkCp437(%rip)\n\t"
"nopl\tstrerror(%rip)\n\t"
"nopl\tstrnwidth(%rip)\n\t"
@ -79,14 +74,11 @@ __asm__(".section .yoink\n\t"
"nopl\twcsnwidth(%rip)\n\t"
"nopl\tmalloc(%rip)\n\t"
"nopl\tcalloc(%rip)\n\t"
"nopl\tfree_s(%rip)\n\t"
"nopl\t__grow(%rip)\n\t"
".previous");
#else
static long __pflink(long x) {
x |= kCp437[0];
x |= ntoa(0, 0, 0, 0, 0, 0, 0, 0, 0);
x |= ftoa(0, 0, 0, 0, 0, 0);
x |= strnwidth(0, 0, 0);
x |= strnwidth16(0, 0, 0);
x |= wcsnwidth(0, 0, 0);
@ -94,7 +86,6 @@ static long __pflink(long x) {
x |= __grow(0, 0, 0, 0);
x |= (intptr_t)strerror(0);
x |= (intptr_t)calloc(0, 0);
free_s(0);
return x;
}
#endif

View file

@ -26,6 +26,9 @@
#include "libc/nt/runtime.h"
#include "libc/str/str.h"
STATIC_YOINK("ntoa");
STATIC_YOINK("stoa");
STATIC_YOINK("E2BIG");
STATIC_YOINK("EACCES");
STATIC_YOINK("EADDRINUSE");
@ -321,7 +324,7 @@ int strerror_r(int err, char *buf, size_t size) {
s = firstnonnull(geterrname(err), "?");
}
if (!SupportsWindows()) {
snprintf(buf, size, "E%s[%d]", s, err);
(snprintf)(buf, size, "E%s[%d]", s, err);
} else {
winstate = GetLastError();
sysvstate = errno;
@ -332,8 +335,8 @@ int strerror_r(int err, char *buf, size_t size) {
} else {
buf16[0] = u'\0';
}
snprintf(buf, size, "E%s/err=%d/errno:%d/GetLastError:%d%s%hs", s, err,
sysvstate, winstate, buf16[0] ? " " : "", buf16);
(snprintf)(buf, size, "E%s/err=%d/errno:%d/GetLastError:%d%s%hs", s, err,
sysvstate, winstate, buf16[0] ? " " : "", buf16);
}
return 0;
}

View file

@ -286,13 +286,11 @@ int vcscanf(int callback(void *), int unget(int, void *), void *arg,
}
}
Done:
while (freeme) {
while (freeme && weaken(free)) {
struct FreeMe *entry = freeme;
freeme = entry->next;
if (items == -1) {
weaken(free_s)((void **)&entry->ptr);
}
weaken(free_s)((void **)&entry);
if (items == -1) weaken(free)(entry->ptr);
weaken(free)(entry);
}
return items;
}

View file

@ -67,22 +67,6 @@
} while (0)
#endif
#if __STDC_VERSION__ + 0 < 201112
#define ____Static_assert(x, y) A##B
#define ___Static_assert(x, y) ____Static_assert(x, y)
#ifndef __cplusplus /* todo jart what */
#define __Static_assert(x) __builtin_choose_expr(__builtin_constant_p(x), x, 1)
#else
#define __Static_assert(x) (x)
#endif
#define _Static_assert(x, s) /* clang-format off */ do { \
__builtin_assume(x); \
enum { ___Static_assert(_Assert, __COUNTER__) = \
1 / !!__Static_assert(x) \
} /*_Unused*/; /* clang-format on */ \
} while (0)
#endif
#if __STDC_VERSION__ + 0 < 201112 && defined(__x86__)
#define _Atomic(TYPE) TYPE
#endif
@ -652,7 +636,7 @@ typedef uint64_t uintmax_t;
#endif
#ifndef _Section
#ifndef __STRICT_ANSI__
#if !defined(__STRICT_ANSI__) && !defined(__APPLE__)
#define _Section(s) __attribute__((__section__(s)))
#else
#define _Section(s)
@ -667,16 +651,17 @@ typedef uint64_t uintmax_t;
#ifndef __STRICT_ANSI__
#if defined(__GNUC__) || defined(__llvm__)
#pragma GCC diagnostic ignored "-Wsign-compare" /* lint needs to change */
#pragma GCC diagnostic ignored "-Wtype-limits" /* makes macros unsafe */
#pragma GCC diagnostic ignored "-Woverflow" /* also breaks macros */
#pragma GCC diagnostic ignored "-Wformat" /* forces only gnu pf */
#pragma GCC diagnostic ignored "-Wunused-parameter" /* extreme prejudice */
#pragma GCC diagnostic ignored "-Wunused-function" /* contradicts dce! */
#pragma GCC diagnostic ignored "-Wunused-variable" /* belongs in tidy */
#pragma GCC diagnostic ignored "-Wsign-compare" /* lint needs to change */
#pragma GCC diagnostic ignored "-Wtype-limits" /* makes macros unsafe */
#pragma GCC diagnostic ignored "-Woverflow" /* also breaks macros */
#pragma GCC diagnostic ignored "-Wformat" /* forces only gnu pf */
#pragma GCC diagnostic ignored "-Wunused-parameter" /* extreme prejudice */
#pragma GCC diagnostic ignored "-Wunused-function" /* contradicts dce! */
#pragma GCC diagnostic ignored "-Wunused-variable" /* belongs in tidy */
#pragma GCC diagnostic ignored "-Wformat-extra-args" /* is also broken */
#pragma GCC diagnostic ignored "-Wparentheses" /* annoying tidy */
#pragma GCC diagnostic ignored "-Wdangling-else" /* come on tidy */
#pragma GCC diagnostic ignored "-Wparentheses" /* annoying tidy */
#pragma GCC diagnostic ignored "-Wdangling-else" /* come on tidy */
#pragma GCC diagnostic ignored "-Wformat-security" /* come on tidy */
#ifndef __cplusplus
#pragma GCC diagnostic ignored "-Wimplicit-int"
#endif /* C++ */
@ -704,8 +689,8 @@ typedef uint64_t uintmax_t;
"-Wincompatible-pointer-types-discards-qualifiers"
#pragma clang diagnostic ignored "-Wbuiltin-requires-header"
#pragma clang diagnostic ignored "-Wparentheses-equality" /*-save-temps*/
#pragma clang diagnostic ignored "-Wunused-value" /*({-save-temps})*/
#pragma clang diagnostic ignored "-Wstring-plus-int" /* special ed */
#pragma clang diagnostic ignored "-Wunused-value" /*({-save-temps})*/
#pragma clang diagnostic ignored "-Wstring-plus-int" /* special ed */
#pragma clang diagnostic ignored "-Wunused-value" /* extreme prejudice */
#pragma clang diagnostic ignored "-Wbuiltin-requires-header"
#pragma clang diagnostic ignored \
@ -797,22 +782,14 @@ typedef uint64_t uintmax_t;
#define EXPROPRIATE(EXPRESSION) (EXPRESSION)
#endif
#ifndef __STRICT_ANSI__
#define YOINK(SYMBOL) \
do { \
_Static_assert(!__builtin_types_compatible_p(typeof(SYMBOL), char[]), \
"Please YOINK(symbol), not YOINK(\"symbol\")"); \
asm(".section .yoink\n\t" \
"nop\t%a0\n\t" \
".previous" \
: /* no outputs */ \
: "X"(SYMBOL)); \
} while (0)
#if !defined(__STRICT_ANSI__) && !defined(__APPLE__)
#define YOINK(SYMBOL) \
asm(".section .yoink\n\tnopl\t%a0\n\t.previous" : : "X"(SYMBOL))
#else
#define YOINK(SYMBOL) (void)0
#endif
#ifndef __STRICT_ANSI__
#if !defined(__STRICT_ANSI__) && !defined(__APPLE__)
#define STATIC_YOINK(SYMBOLSTR) \
asm(".section .yoink\n\tnopl\t\"" SYMBOLSTR "\"\n\t.previous")
#else

View file

@ -21,12 +21,12 @@
.privileged
.alignfunc
/ Returns 𝑥+𝑦, aborting on overflow.
/
/ @param rdi is int64 𝑥
/ @param rsi is int64 𝑦
/ @return rax is 𝑥+𝑦
/ @see -ftrapv
// Returns 𝑥+𝑦, aborting on overflow.
//
// @param rdi is int64 𝑥
// @param rsi is int64 𝑦
// @return rax is 𝑥+𝑦
// @see -ftrapv
__addvdi3:
mov %rdi,%rax
add %rsi,%rax

View file

@ -21,12 +21,12 @@
.privileged
.alignfunc
/ Returns 𝑥+𝑦, aborting on overflow.
/
/ @param edi is int32 𝑥
/ @param esi is int32 𝑦
/ @return eax is 𝑥+𝑦
/ @see -ftrapv
// Returns 𝑥+𝑦, aborting on overflow.
//
// @param edi is int32 𝑥
// @param esi is int32 𝑦
// @return eax is 𝑥+𝑦
// @see -ftrapv
__addvsi3:
mov %edi,%eax
add %esi,%eax

View file

@ -21,12 +21,12 @@
.privileged
.alignfunc
/ Returns 𝑥+𝑦, aborting on overflow.
/
/ @param rdi:rsi is int128 𝑥
/ @param rdx:rcx is int128 𝑦
/ @return rdx:rax is 𝑥+𝑦
/ @see -ftrapv
// Returns 𝑥+𝑦, aborting on overflow.
//
// @param rdi:rsi is int128 𝑥
// @param rdx:rcx is int128 𝑦
// @return rdx:rax is 𝑥+𝑦
// @see -ftrapv
__addvti3:
mov %rdi,%rax
add %rdx,%rax

View file

@ -18,10 +18,10 @@
*/
#include "libc/macros.h"
/ Jump table for mpsadbw() with non-constexpr immediate parameter.
/
/ @note needs sse4 cf. core c. 2006 cf. bulldozer c. 2011
/ @see mpsadbw()
// 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

View file

@ -21,12 +21,12 @@
.privileged
.alignfunc
/ Returns 𝑥*𝑦, aborting on overflow.
/
/ @param rdi is int64 𝑥
/ @param rdi is int64 𝑦
/ @return rax is 𝑥*𝑦
/ @see -ftrapv
// Returns 𝑥*𝑦, aborting on overflow.
//
// @param rdi is int64 𝑥
// @param rdi is int64 𝑦
// @return rax is 𝑥*𝑦
// @see -ftrapv
__mulvdi3:
mov %rdi,%rax
imul %rsi

View file

@ -21,12 +21,12 @@
.privileged
.alignfunc
/ Returns 𝑥*𝑦, aborting on overflow.
/
/ @param edi is int32 𝑥
/ @param esi is int32 𝑦
/ @return eax is 𝑥*𝑦
/ @see -ftrapv
// Returns 𝑥*𝑦, aborting on overflow.
//
// @param edi is int32 𝑥
// @param esi is int32 𝑦
// @return eax is 𝑥*𝑦
// @see -ftrapv
__mulvsi3:
mov %edi,%eax
imul %esi

View file

@ -21,12 +21,12 @@
.privileged
.alignfunc
/ Returns 𝑥*𝑦, aborting on overflow.
/
/ @param rdi:rsi is int128 𝑥
/ @param rdx:rcx is int128 𝑦
/ @return rdx:rax is 𝑥*𝑦
/ @see -ftrapv
// Returns 𝑥*𝑦, aborting on overflow.
//
// @param rdi:rsi is int128 𝑥
// @param rdx:rcx is int128 𝑦
// @return rdx:rax is 𝑥*𝑦
// @see -ftrapv
__mulvti3:
push %rbp
mov %rsp,%rbp

View file

@ -21,11 +21,11 @@
.privileged
.alignfunc
/ Returns -𝑥, aborting on overflow (two's complement bane).
/
/ @param rdi is int64 𝑥
/ @return rax is -𝑥
/ @see -ftrapv
// Returns -𝑥, aborting on overflow (two's complement bane).
//
// @param rdi is int64 𝑥
// @return rax is -𝑥
// @see -ftrapv
__negvdi2:
mov %rdi,%rax
neg %rax

View file

@ -21,11 +21,11 @@
.privileged
.alignfunc
/ Returns -𝑥, aborting on overflow (two's complement bane).
/
/ @param edi is int32 𝑥
/ @return eax is -𝑥
/ @see -ftrapv
// Returns -𝑥, aborting on overflow (two's complement bane).
//
// @param edi is int32 𝑥
// @return eax is -𝑥
// @see -ftrapv
__negvsi2:
mov %edi,%eax
neg %eax

View file

@ -21,11 +21,11 @@
.privileged
.alignfunc
/ Returns -𝑥, aborting on overflow.
/
/ @param rdi:rsi is int128 𝑥
/ @return rdx:rax is -𝑥
/ @see -ftrapv
// Returns -𝑥, aborting on overflow.
//
// @param rdi:rsi is int128 𝑥
// @return rdx:rax is -𝑥
// @see -ftrapv
__negvti2:
mov %rdi,%rax
mov %rsi,%rdx

View file

@ -20,8 +20,8 @@
.privileged
.source __FILE__
/ Arithmetic overflow handler.
/ @see -ftrapv
// Arithmetic overflow handler.
// @see -ftrapv
__on_arithmetic_overflow:
push %rbp
mov %rsp,%rbp

View file

@ -18,10 +18,10 @@
*/
#include "libc/macros.h"
/ Jump table for palignr() with non-constexpr immediate parameter.
/
/ @note needs ssse3 cf. prescott c. 2004 cf. bulldozer c. 2011
/ @see palignr()
// Jump table for palignr() with non-constexpr immediate parameter.
//
// @note needs ssse3 cf. prescott c. 2004 cf. bulldozer c. 2011
// @see palignr()
.align 8
__palignrs:
palignr $0,%xmm1,%xmm0

View file

@ -18,7 +18,7 @@
*/
#include "libc/macros.h"
/ Jump table for pslldq() with non-constexpr immediate parameter.
// Jump table for pslldq() with non-constexpr immediate parameter.
.align 8
__pslldqs:
pslldq $0,%xmm0

View file

@ -18,7 +18,7 @@
*/
#include "libc/macros.h"
/ Jump table for psrldq() with non-constexpr immediate parameter.
// Jump table for psrldq() with non-constexpr immediate parameter.
.align 8
__psrldqs:
psrldq $0,%xmm0

View file

@ -53,11 +53,11 @@ __asan_report_load16:
.endfn __asan_report_load16,globl
__asan_report_load32:
push $32
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn __asan_report_load32,globl
OnReportLoad:
pop %rsi
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn OnReportLoad
__asan_report_load_n:
lea __asan_report_load(%rip),%r11
@ -86,15 +86,15 @@ __asan_report_store16:
.endfn __asan_report_store16,globl
__asan_report_store32:
push $32
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn __asan_report_store32,globl
ReportStore:
pop %rsi
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn ReportStore
__asan_report_store_n:
lea __asan_report_store(%rip),%r11
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn __asan_report_store_n,globl
__asan_report_noreentry:
@ -152,7 +152,7 @@ __asan_stack_free_9:
.endfn __asan_stack_free_9,globl
__asan_stack_free_10:
push $10
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn __asan_stack_free_10,globl
OnStackFree:
pop %rdx
@ -201,7 +201,7 @@ __asan_stack_malloc_9:
.endfn __asan_stack_malloc_9,globl
__asan_stack_malloc_10:
push $10
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn __asan_stack_malloc_10,globl
OnStackMalloc:
pop %rsi
@ -212,7 +212,7 @@ __asan_version_mismatch_check_v8:
ret
.endfn __asan_version_mismatch_check_v8,globl
/ Initializes Address Sanitizer runtime earlier if linked.
// Initializes Address Sanitizer runtime earlier if linked.
.init.start 301,_init_asan
push %rdi
push %rsi

View file

@ -21,12 +21,12 @@
.privileged
.alignfunc
/ Returns 𝑥-𝑦, aborting on overflow.
/
/ @param rdi is int64 𝑥
/ @param rsi is int64 𝑦
/ @return rax is 𝑥-𝑦
/ @see -ftrapv
// Returns 𝑥-𝑦, aborting on overflow.
//
// @param rdi is int64 𝑥
// @param rsi is int64 𝑦
// @return rax is 𝑥-𝑦
// @see -ftrapv
__subvdi3:
mov %rdi,%rax
sub %rsi,%rax

View file

@ -21,11 +21,11 @@
.privileged
.alignfunc
/ Returns 𝑥-𝑦, aborting on overflow.
/
/ @param edi is int32 𝑥
/ @param esi is int32 𝑦
/ @see -ftrapv
// Returns 𝑥-𝑦, aborting on overflow.
//
// @param edi is int32 𝑥
// @param esi is int32 𝑦
// @see -ftrapv
__subvsi3:
mov %edi,%eax
sub %esi,%eax

View file

@ -21,12 +21,12 @@
.privileged
.alignfunc
/ Returns 𝑥-𝑦, aborting on overflow.
/
/ @param rdi:rsi is int128 𝑥
/ @param rdx:rcx is int128 𝑦
/ @return rdx:rax is 𝑥-𝑦
/ @see -ftrapv
// Returns 𝑥-𝑦, aborting on overflow.
//
// @param rdi:rsi is int128 𝑥
// @param rdx:rcx is int128 𝑦
// @return rdx:rax is 𝑥-𝑦
// @see -ftrapv
__subvti3:
mov %rdi,%rax
sub %rdx,%rax

View file

@ -1,15 +1,18 @@
#ifndef COSMOPOLITAN_LIBC_LOG_LOG_H_
#define COSMOPOLITAN_LIBC_LOG_LOG_H_
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/winsize.h"
#include "libc/stdio/stdio.h"
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § liblog
*/
#define kLogFatal 0u
#define kLogError 1u
#define kLogWarn 2u
#define kLogInfo 3u
#define kLogVerbose 4u
#define kLogDebug 5u
#define kLogFatal 0
#define kLogError 1
#define kLogWarn 2
#define kLogInfo 3
#define kLogVerbose 4
#define kLogDebug 5
/**
* Log level for compile-time DCE.
@ -27,10 +30,6 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct sigset;
struct winsize;
typedef struct FILE FILE;
extern FILE *g_logfile;
void perror(const char *) relegated; /* print the last system error */

View file

@ -19,9 +19,9 @@
#include "libc/macros.h"
.source __FILE__
/ These function names make it a bit more obvious which signal
/ caused the crash, particularly in the GDB GUI. They're coded
/ into an array to pinch pennies on code size registering them.
// These function names make it a bit more obvious which signal
// caused the crash, particularly in the GDB GUI. They're coded
// into an array to pinch pennies on code size registering them.
__oncrash_thunks:

View file

@ -49,7 +49,7 @@ __ubsan_handle_type_mismatch_v1_abort:
__ubsan_handle_add_overflow_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_add_overflow_abort,globl
__ubsan_handle_add_overflow:
loadstr "add_overflow",si
@ -58,7 +58,7 @@ __ubsan_handle_add_overflow:
__ubsan_handle_alignment_assumption_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_alignment_assumption_abort,globl
__ubsan_handle_alignment_assumption:
loadstr "alignment_assumption",si
@ -67,7 +67,7 @@ __ubsan_handle_alignment_assumption:
__ubsan_handle_builtin_unreachable_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_builtin_unreachable_abort,globl
__ubsan_handle_builtin_unreachable:
loadstr "builtin_unreachable",si
@ -76,7 +76,7 @@ __ubsan_handle_builtin_unreachable:
__ubsan_handle_cfi_bad_type_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_cfi_bad_type_abort,globl
__ubsan_handle_cfi_bad_type:
loadstr "cfi_bad_type",si
@ -85,7 +85,7 @@ __ubsan_handle_cfi_bad_type:
__ubsan_handle_cfi_check_fail_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_cfi_check_fail_abort,globl
__ubsan_handle_cfi_check_fail:
loadstr "cfi_check_fail",si
@ -94,7 +94,7 @@ __ubsan_handle_cfi_check_fail:
__ubsan_handle_divrem_overflow_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_divrem_overflow_abort,globl
__ubsan_handle_divrem_overflow:
loadstr "divrem_overflow",si
@ -103,7 +103,7 @@ __ubsan_handle_divrem_overflow:
__ubsan_handle_dynamic_type_cache_miss_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_dynamic_type_cache_miss_abort,globl
__ubsan_handle_dynamic_type_cache_miss:
loadstr "dynamic_type_cache_miss",si
@ -112,7 +112,7 @@ __ubsan_handle_dynamic_type_cache_miss:
__ubsan_handle_function_type_mismatch_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_function_type_mismatch_abort,globl
__ubsan_handle_function_type_mismatch:
loadstr "function_type_mismatch",si
@ -121,7 +121,7 @@ __ubsan_handle_function_type_mismatch:
__ubsan_handle_implicit_conversion_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_implicit_conversion_abort,globl
__ubsan_handle_implicit_conversion:
loadstr "implicit_conversion",si
@ -130,7 +130,7 @@ __ubsan_handle_implicit_conversion:
__ubsan_handle_invalid_builtin_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_invalid_builtin_abort,globl
__ubsan_handle_invalid_builtin:
loadstr "invalid_builtin",si
@ -139,7 +139,7 @@ __ubsan_handle_invalid_builtin:
__ubsan_handle_load_invalid_value_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_load_invalid_value_abort,globl
__ubsan_handle_load_invalid_value:
loadstr "load_invalid_value (try checking for uninitialized variables)",si
@ -148,7 +148,7 @@ __ubsan_handle_load_invalid_value:
__ubsan_handle_missing_return_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_missing_return_abort,globl
__ubsan_handle_missing_return:
loadstr "missing_return",si
@ -157,7 +157,7 @@ __ubsan_handle_missing_return:
__ubsan_handle_mul_overflow_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_mul_overflow_abort,globl
__ubsan_handle_mul_overflow:
loadstr "mul_overflow",si
@ -166,7 +166,7 @@ __ubsan_handle_mul_overflow:
__ubsan_handle_negate_overflow_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_negate_overflow_abort,globl
__ubsan_handle_negate_overflow:
loadstr "negate_overflow",si
@ -175,7 +175,7 @@ __ubsan_handle_negate_overflow:
__ubsan_handle_nonnull_arg_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_nonnull_arg_abort,globl
__ubsan_handle_nonnull_arg:
loadstr "nonnull_arg",si
@ -184,7 +184,7 @@ __ubsan_handle_nonnull_arg:
__ubsan_handle_nonnull_return_v1_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_nonnull_return_v1_abort,globl
__ubsan_handle_nonnull_return_v1:
loadstr "nonnull_return_v1",si
@ -197,7 +197,7 @@ __ubsan_hop:
__ubsan_handle_nullability_arg_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_nullability_arg_abort,globl
__ubsan_handle_nullability_arg:
loadstr "nullability_arg",si
@ -206,7 +206,7 @@ __ubsan_handle_nullability_arg:
__ubsan_handle_nullability_return_v1_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_nullability_return_v1_abort,globl
__ubsan_handle_nullability_return_v1:
loadstr "nullability_return_v1",si
@ -215,7 +215,7 @@ __ubsan_handle_nullability_return_v1:
__ubsan_handle_pointer_overflow_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_pointer_overflow_abort,globl
__ubsan_handle_pointer_overflow:
loadstr "pointer_overflow",si
@ -224,7 +224,7 @@ __ubsan_handle_pointer_overflow:
__ubsan_handle_shift_out_of_bounds_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_shift_out_of_bounds_abort,globl
__ubsan_handle_shift_out_of_bounds:
loadstr "shift_out_of_bounds",si
@ -233,7 +233,7 @@ __ubsan_handle_shift_out_of_bounds:
__ubsan_handle_sub_overflow_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_sub_overflow_abort,globl
__ubsan_handle_sub_overflow:
loadstr "sub_overflow",si
@ -242,7 +242,7 @@ __ubsan_handle_sub_overflow:
__ubsan_handle_vla_bound_not_positive_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_vla_bound_not_positive_abort,globl
__ubsan_handle_vla_bound_not_positive:
loadstr "vla_bound_not_positive",si
@ -251,7 +251,7 @@ __ubsan_handle_vla_bound_not_positive:
__ubsan_handle_nonnull_return_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_nonnull_return_abort,globl
__ubsan_handle_nonnull_return:
loadstr "nonnull_return",si

View file

@ -20,7 +20,7 @@
.text.unlikely
.source __FILE__
/ Code-size saving thunk for CHECK_EQ() in NDEBUG mode.
// Code-size saving thunk for CHECK_EQ() in NDEBUG mode.
__check_fail_eq:
loadstr "==",dx
jmp __check_fail_ndebug

View file

@ -20,7 +20,7 @@
.text.unlikely
.source __FILE__
/ Code-size saving thunk for CHECK_GE() in NDEBUG mode.
// Code-size saving thunk for CHECK_GE() in NDEBUG mode.
__check_fail_ge:
loadstr ">=",dx
jmp __check_fail_ndebug

View file

@ -20,7 +20,7 @@
.text.unlikely
.source __FILE__
/ Code-size saving thunk for CHECK_GT() in NDEBUG mode.
// Code-size saving thunk for CHECK_GT() in NDEBUG mode.
__check_fail_gt:
loadstr ">",dx
jmp __check_fail_ndebug

View file

@ -20,7 +20,7 @@
.text.unlikely
.source __FILE__
/ Code-size saving thunk for CHECK_LE() in NDEBUG mode.
// Code-size saving thunk for CHECK_LE() in NDEBUG mode.
__check_fail_le:
loadstr "<=",dx
jmp __check_fail_ndebug

View file

@ -20,7 +20,7 @@
.text.unlikely
.source __FILE__
/ Code-size saving thunk for CHECK_LT() in NDEBUG mode.
// Code-size saving thunk for CHECK_LT() in NDEBUG mode.
__check_fail_lt:
loadstr "<",dx
jmp __check_fail_ndebug

View file

@ -20,7 +20,7 @@
.text.unlikely
.source __FILE__
/ Code-size saving thunk for CHECK_NE() in NDEBUG mode.
// Code-size saving thunk for CHECK_NE() in NDEBUG mode.
__check_fail_ne:
loadstr "!=",dx
jmp __check_fail_ndebug

View file

@ -23,7 +23,7 @@
#define vzeroupper
#endif
/ Begins definition of frameless function that calls no functions.
// Begins definition of frameless function that calls no functions.
.macro .leafprologue
#if !(defined(TINY) && !defined(__PG__))
push %rbp
@ -31,7 +31,7 @@
#endif
.endm
/ Ends definition of frameless function that calls no functions.
// Ends definition of frameless function that calls no functions.
.macro .leafepilogue
#if !(defined(TINY) && !defined(__PG__))
pop %rbp
@ -39,16 +39,16 @@
ret
.endm
/ Good alignment for functions where alignment actually helps.
/ @note 16-byte
// Good alignment for functions where alignment actually helps.
// @note 16-byte
.macro .alignfunc
#ifndef __OPTIMIZE_SIZE__
.p2align 4
#endif
.endm
/ Good alignment for loops where alignment actually helps.
/ @note 16-byte if <10 padding otherwise 8-byte
// Good alignment for loops where alignment actually helps.
// @note 16-byte if <10 padding otherwise 8-byte
.macro .alignloop
#ifndef __OPTIMIZE_SIZE__
.p2align 4,,10
@ -56,8 +56,8 @@
#endif
.endm
/ Loads Effective Address
/ Supporting security blankets
// Loads Effective Address
// Supporting security blankets
.macro plea symbol:req reg64:req reg32:req
#if __PIC__ + __PIE__ + __code_model_medium__ + __code_model_large__ + 0 > 1
lea \symbol(%rip),\reg64
@ -66,8 +66,8 @@
#endif
.endm
/ Loads Effective Address to Stack
/ Supporting security blankets
// Loads Effective Address to Stack
// Supporting security blankets
.macro pshaddr symbol:req
#if __PIC__ + __PIE__ + __code_model_medium__ + __code_model_large__ + 0 > 1
push $IMAGE_BASE_VIRTUAL+RVA(\symbol)(%rip),\reg64
@ -76,12 +76,12 @@
#endif
.endm
/ TODO(jart): delete
/ Loads Effective Address
/ Supporting security blankets
// TODO(jart): delete
// Loads Effective Address
// Supporting security blankets
.macro ezlea symbol:req reg:req
#if __pic__ + __pie__ + __code_model_medium__ + __code_model_large__ + 0 > 1
/ lea \symbol(%rip),%r\reg
// lea \symbol(%rip),%r\reg
mov $\symbol,%e\reg
#else
mov $\symbol,%e\reg
@ -97,7 +97,7 @@
#endif
.endm
/ Creates first stack frame.
// Creates first stack frame.
.macro .frame0
and $-16,%rsp
xor %ebp,%ebp
@ -106,38 +106,33 @@
.macro .source symbol:req
.endm
/ Inserts profiling hook in prologue if cc wants it.
/
/ Cosmopolitan does this in a slightly different way from normal
/ GNU toolchains. We always use the -mnop-mcount behavior, since
/ the runtime is able to morph the binary at runtime. It is good
/ since we can put hooks for profiling and function tracing into
/ most builds, without any impact on performance.
/
/ @cost ≥0.3 cycles, 5 bytes
/ @see build/compile
// Inserts profiling hook in prologue if cc wants it.
//
// Cosmopolitan does this in a slightly different way from normal
// GNU toolchains. We always use the -mnop-mcount behavior, since
// the runtime is able to morph the binary at runtime. It is good
// since we can put hooks for profiling and function tracing into
// most builds, without any impact on performance.
//
// @cost ≥0.3 cycles, 5 bytes
// @see build/compile
.macro .profilable
#ifdef __PG__
1382:
#if defined(__MFENTRY__)
call __fentry__
#elif defined(__PIC__) || defined(__PIE__)
/ nopw 0x00(%rax,%rax,1)
// nopw 0x00(%rax,%rax,1)
.byte 0x66,0x0f,0x1f,0x44,0x00,0x00
#else
/ nopl 0x00(%rax,%rax,1)
// nopl 0x00(%rax,%rax,1)
.byte 0x0f,0x1f,0x44,0x00,0x00
#endif
#if defined(__MRECORD_MCOUNT__) && !defined(__MFENTRY__)
.section __mcount_loc,"a",@progbits
.quad 1382b
.previous
#endif
#endif
.endm
/ Pushes RVA on stack of linktime mergeable string literal.
/ @see popstr
// Pushes RVA on stack of linktime mergeable string literal.
// @see popstr
.macro pushstr text
.section .rodata.str1.1,"aSM",@progbits,1
.Lstr\@: .asciz "\text"
@ -146,14 +141,14 @@
push $.Lstr\@ - IMAGE_BASE_VIRTUAL
.endm
/ Pops off stack string address.
/ @see pushstr
// Pops off stack string address.
// @see pushstr
.macro popstr dest:req
addl $IMAGE_BASE_VIRTUAL,(%rsp)
pop \dest
.endm
/ Loads address of linktime mergeable string literal into register.
// Loads address of linktime mergeable string literal into register.
.macro getstr text:req reg64:req reg32 regsz64 regsz32 bias=0
.section .rodata.str1.1,"aSM",@progbits,1
.type .Lstr\@,@object
@ -175,8 +170,8 @@
.endif
.endm
/ TODO(jart): delete
/ Loads address of linktime mergeable string literal into register.
// TODO(jart): delete
// Loads address of linktime mergeable string literal into register.
.macro loadstr text:req reg:req regsz bias=0
.section .rodata.str1.1,"aSM",@progbits,1
.type .Lstr\@,@object

View file

@ -14,7 +14,6 @@
#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))

View file

@ -17,7 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
╚─────────────────────────────────────────────────────────────────────────────*/
/ Shorthand notation for widely-acknowledged sections.
// Shorthand notation for widely-acknowledged sections.
.macro .rodata
.section .rodata,"a",@progbits
.endm
@ -62,11 +62,11 @@
.section .text.windows,"ax",@progbits
.endm
/ Mergeable numeric constant sections.
/
/ @note linker de-dupes item/values across whole compile
/ @note therefore item/values are reordered w.r.t. link order
/ @note therefore no section relative addressing
// Mergeable numeric constant sections.
//
// @note linker de-dupes item/values across whole compile
// @note therefore item/values are reordered w.r.t. link order
// @note therefore no section relative addressing
.macro .rodata.cst4
.section .rodata.cst4,"aM",@progbits,4
.align 4
@ -96,33 +96,33 @@
.align 4
.endm
/ Mergeable NUL-terminated UTF-8 string constant section.
/
/ @note linker de-dupes C strings here across whole compile
/ @note therefore item/values are reordered w.r.t. link order
/ @note therefore no section relative addressing
// Mergeable NUL-terminated UTF-8 string constant section.
//
// @note linker de-dupes C strings here across whole compile
// @note therefore item/values are reordered w.r.t. link order
// @note therefore no section relative addressing
.macro .rodata.str1.1
.section .rodata.str1.1,"aSM",@progbits,1
.align 1
.endm
/ Locates unreferenced code invulnerable to --gc-sections.
// Locates unreferenced code invulnerable to --gc-sections.
.macro .keep.text
.section .keep.text,"ax",@progbits
.endm
/ Flags code as only allowed for testing purposes.
// Flags code as only allowed for testing purposes.
.macro .testonly
.section .test,"ax",@progbits
.endm
/ Makes code runnable while code morphing.
// Makes code runnable while code morphing.
.macro .privileged
.section .privileged,"ax",@progbits
.endm
/ Post-Initialization Read-Only (PIRO) BSS section.
/ @param ss is an optional string, for control image locality
// Post-Initialization Read-Only (PIRO) BSS section.
// @param ss is an optional string, for control image locality
.macro .piro ss
.ifnb \ss
.section .piro.sort.bss.\ss,"aw",@nobits
@ -131,9 +131,9 @@
.endif
.endm
/ Helpers for Cosmopolitan _init() amalgamation magic.
/ @param name should be consistent across macros for a module
/ @see libc/runtime/_init.S
// Helpers for Cosmopolitan _init() amalgamation magic.
// @param name should be consistent across macros for a module
// @see libc/runtime/_init.S
.macro .initro number:req name:req
.section .initro.\number\().\name,"a",@progbits
.align 8
@ -151,16 +151,16 @@
.previous
.endm
/ Declares alternative implementation of function.
/ @param implement e.g. tinymath_pow
/ @param canonical e.g. pow
// Declares alternative implementation of function.
// @param implement e.g. tinymath_pow
// @param canonical e.g. pow
.macro .alias implement:req canonical:req
.equ \canonical,\implement
.weak \canonical
.endm
/ Ends function definition.
/ @cost saves 1-3 lines of code
// Ends function definition.
// @cost saves 1-3 lines of code
.macro .endfn name:req bnd vis
.size \name,.-\name
.type \name,@function
@ -172,8 +172,8 @@
.endif
.endm
/ Ends variable definition.
/ @cost saves 1-3 lines of code
// Ends variable definition.
// @cost saves 1-3 lines of code
.macro .endobj name:req bnd vis
.size \name,.-\name
.type \name,@object
@ -185,35 +185,35 @@
.endif
.endm
/ LOOP Instruction Replacement.
/ With its mop-Fusion Mexican equivalent.
/ Thus avoiding 3x legacy pipeline slowdown.
// LOOP Instruction Replacement.
// With its mop-Fusion Mexican equivalent.
// Thus avoiding 3x legacy pipeline slowdown.
.macro .loop label:req
.byte 0x83,0xe9,0x01 # sub $1,%ecx
jnz \label
.endm
/ Pushes CONSTEXPR [-128,127].
/ @note assembler is wrong for non-literal constexprs
// Pushes CONSTEXPR ∈ [-128,127].
// @note assembler is wrong for non-literal constexprs
.macro pushb x:req
.byte 0x6a,\x
.endm
/ Sign-extends CONSTEXPR [-128,127] to REGISTER.
/ @cost ≥1 cycles, -2 bytes
// Sign-extends CONSTEXPR ∈ [-128,127] to REGISTER.
// @cost ≥1 cycles, -2 bytes
.macro pushpop constexpr:req register:req
pushb \constexpr
pop \register
.endm
/ Moves REGISTER to REGISTER.
/ @cost ≥1 cycles, -1 REX byte
// Moves REGISTER to REGISTER.
// @cost ≥1 cycles, -1 REX byte
.macro movpp src:req dest:req
push \src
pop \dest
.endm
/ Declares optional function.
// Declares optional function.
.macro .optfn fn:req
.globl \fn
.weak \fn
@ -221,8 +221,8 @@
.type \fn,@function
.endm
/ Embeds fixed-width zero-filled string table.
/ @note zero-padded nul-terminated
// Embeds fixed-width zero-filled string table.
// @note zero-padded ≠ nul-terminated
.macro .fxstr width head rest:vararg
.ifnb \head
0: .ascii "\head"
@ -231,15 +231,15 @@
.endif
.endm
/ Embeds Fixed-Width Zero-Padded String.
/ @note .fxstr is better
// Embeds Fixed-Width Zero-Padded String.
// @note .fxstr is better
.macro .ascin str:req fieldsize:req
1347: .ascii "\str"
.org 1347b+\fieldsize,0x00
.endm
/ Marks symbols as object en-masse.
/ @note zero-padded nul-terminated
// Marks symbols as object en-masse.
// @note zero-padded ≠ nul-terminated
.macro .object symbol rest:vararg
.ifnb \symbol
.type \symbol,@object
@ -247,18 +247,14 @@
.endif
.endm
/ Pads function prologue unconditionally for runtime hooking.
/ @cost ≥0.3 cycles, 5 bytes
/ @see .profilable
// Pads function prologue unconditionally for runtime hooking.
// @cost ≥0.3 cycles, 5 bytes
// @see .profilable
.macro .hookable
/ nopl 0x00(%rax,%rax,1)
83457: .byte 0x0f,0x1f,0x44,0x00,0x00
.section __mcount_loc,"a",@progbits
.quad 83457b
.previous
.byte 0x0f,0x1f,0x44,0x00,0x00
.endm
/ Puts initialized data in uninitialized data section.
// Puts initialized data in uninitialized data section.
.macro .bsdata name:req expr:req bnd vis
.section .initbss.300._init_\name,"aw",@nobits
\name: .quad 0
@ -274,9 +270,9 @@ _init_\name:
.previous
.endm
/ ICE Breakpoint.
/ Modern gas forgot this but objdump knows
/ @mode long,legacy,real
// ICE Breakpoint.
// Modern gas forgot this but objdump knows
// @mode long,legacy,real
.macro icebp
.byte 0xF1
.endm
@ -284,8 +280,8 @@ _init_\name:
icebp
.endm
/ Sets breakpoint for software debugger.
/ @mode long,legacy,real
// Sets breakpoint for software debugger.
// @mode long,legacy,real
.macro .softicebp
.byte 0x53 # push bx
.byte 0x87,0xdb # xchg bx,bx (bochs breakpoint)
@ -294,38 +290,38 @@ _init_\name:
int3 # gdb breakpoint
.endm
/ Assembles Intel Official 4-Byte NOP.
// Assembles Intel Official 4-Byte NOP.
.macro fatnop4
.byte 0x0f,0x1f,0x40,0x00
.endm
/ Pulls unrelated module into linkage.
/
/ In order for this technique to work with --gc-sections, another
/ module somewhere might want to weakly reference whats yoinked.
// Pulls unrelated module into linkage.
//
// In order for this technique to work with --gc-sections, another
// module somewhere might want to weakly reference whats yoinked.
.macro yoink symbol:req
.section .yoink
nop "\symbol"
nopl "\symbol"(%rip)
.previous
.endm
.macro .yoink symbol:req
.section .yoink
nop "\symbol"
nopl "\symbol"(%rip)
.previous
.endm
/ Calls Windows function.
/
/ @param cx,dx,r8,r9,stack
/ @return ax
/ @clob ax,cx,dx,r8-r11
// Calls Windows function.
//
// @param cx,dx,r8,r9,stack
// @return ax
// @clob ax,cx,dx,r8-r11
.macro ntcall symbol:req
sub $32,%rsp
call *\symbol(%rip)
add $32,%rsp
.endm
/ Custom emulator instruction for bottom stack frame.
// Custom emulator instruction for bottom stack frame.
.macro bofram endfunc:req
.byte 0x0f,0x1f,0105,\endfunc-. # nopl disp8(%rbp)
.endm

View file

@ -20,12 +20,12 @@
#include "libc/notice.inc"
.source __FILE__
/ Allocates n * itemsize bytes, initialized to zero.
/
/ @param rdi is number of items (n)
/ @param rsi is size of each item (itemsize)
/ @return rax is memory address, or NULL w/ errno
/ @note overreliance on memalign is a sure way to fragment space
/ @see dlcalloc()
// Allocates n * itemsize bytes, initialized to zero.
//
// @param rdi is number of items (n)
// @param rsi is size of each item (itemsize)
// @return rax is memory address, or NULL w/ errno
// @note overreliance on memalign is a sure way to fragment space
// @see dlcalloc()
calloc: jmp *hook_calloc(%rip)
.endfn calloc,globl

View file

@ -19,67 +19,67 @@
#include "libc/macros.h"
.source __FILE__
/ Frees memory the C++ way.
/
/ \param %rdi is pointer, or NULL for no-op
/ \param %rsi is ignored
/ \param %rdx is ignored
// Frees memory the C++ way.
//
// \param %rdi is pointer, or NULL for no-op
// \param %rsi is ignored
// \param %rdx is ignored
_ZdlPvSt11align_val_tRKSt9nothrow_t:
/ operator delete(void*, std::align_val_t, std::nothrow_t const&)
// operator delete(void*, std::align_val_t, std::nothrow_t const&)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdlPvSt11align_val_tRKSt9nothrow_t,weak
_ZdaPvSt11align_val_tRKSt9nothrow_t:
/ operator delete[](void*, std::align_val_t, std::nothrow_t const&)
// operator delete[](void*, std::align_val_t, std::nothrow_t const&)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdaPvSt11align_val_tRKSt9nothrow_t,weak
_ZdlPvRKSt9nothrow_t:
/ operator delete(void*, std::nothrow_t const&)
// operator delete(void*, std::nothrow_t const&)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdlPvRKSt9nothrow_t,weak
_ZdaPvRKSt9nothrow_t:
/ operator delete[](void*, std::nothrow_t const&)
// operator delete[](void*, std::nothrow_t const&)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdaPvRKSt9nothrow_t,weak
_ZdlPvmSt11align_val_t:
/ operator delete(void*, unsigned long, std::align_val_t)
// operator delete(void*, unsigned long, std::align_val_t)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdlPvmSt11align_val_t,weak
_ZdaPvmSt11align_val_t:
/ operator delete[](void*, unsigned long, std::align_val_t)
// operator delete[](void*, unsigned long, std::align_val_t)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdaPvmSt11align_val_t,weak
_ZdlPvSt11align_val_t:
/ operator delete(void*, std::align_val_t)
// operator delete(void*, std::align_val_t)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdlPvSt11align_val_t,weak
_ZdaPvSt11align_val_t:
/ operator delete[](void*, std::align_val_t)
// operator delete[](void*, std::align_val_t)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdaPvSt11align_val_t,weak
_ZdaPvm:
/ operator delete[](void*, unsigned long):
// operator delete[](void*, unsigned long):
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdaPvm,weak
_ZdlPvm:
/ operator delete(void*, unsigned long)
// operator delete(void*, unsigned long)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdlPvm,weak
_ZdaPv:
/ operator delete[](void*)
// operator delete[](void*)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdaPv,weak
_ZdlPv:
/ operator delete(void*)
// operator delete(void*)
jmp *hook_free(%rip)
.endfn _ZdlPv,weak

View file

@ -19,28 +19,28 @@
#include "libc/macros.h"
.source __FILE__
/ Allocates memory the C++ way.
/
/ \param %rdi is bytes to allocate
/ \param %rsi is ignored
/ \return new memory or NULL on OOM
// Allocates memory the C++ way.
//
// \param %rdi is bytes to allocate
// \param %rsi is ignored
// \return new memory or NULL on OOM
_ZnamRKSt9nothrow_t:
/ operator new[](unsigned long, std::nothrow_t const&)
// operator new[](unsigned long, std::nothrow_t const&)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZnamRKSt9nothrow_t,weak
_ZnwmRKSt9nothrow_t:
/ operator new(unsigned long, std::nothrow_t const&)
// operator new(unsigned long, std::nothrow_t const&)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZnwmRKSt9nothrow_t,weak
_Znam:
/ operator new[](unsigned long)
// operator new[](unsigned long)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _Znam,weak
_Znwm:
/ operator new(unsigned long)
// operator new(unsigned long)
test %rdi,%rdi
jne 1f
mov $1,%edi

View file

@ -19,29 +19,29 @@
#include "libc/macros.h"
.source __FILE__
/ Allocates aligned memory the C++ way.
/
/ \param %rdi is bytes to allocate
/ \param %rsi is byte alignment
/ \param %rdx is ignored
/ \return new memory or NULL on OOM
// Allocates aligned memory the C++ way.
//
// \param %rdi is bytes to allocate
// \param %rsi is byte alignment
// \param %rdx is ignored
// \return new memory or NULL on OOM
_ZnamSt11align_val_tRKSt9nothrow_t:
/ operator new[](unsigned long, std::align_val_t, std::nothrow_t const&)
// operator new[](unsigned long, std::align_val_t, std::nothrow_t const&)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZnamSt11align_val_tRKSt9nothrow_t,weak
_ZnwmSt11align_val_tRKSt9nothrow_t:
/ operator new(unsigned long, std::align_val_t, std::nothrow_t const&)
// operator new(unsigned long, std::align_val_t, std::nothrow_t const&)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZnwmSt11align_val_tRKSt9nothrow_t,weak
_ZnwmSt11align_val_t:
/ operator new(unsigned long, std::align_val_t)
// operator new(unsigned long, std::align_val_t)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZnwmSt11align_val_t,weak
_ZnamSt11align_val_t:
/ operator new[](unsigned long, std::align_val_t)
// operator new[](unsigned long, std::align_val_t)
test %rdi,%rdi
jnz 1f
mov $1,%eax

View file

@ -16,9 +16,8 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/alg/arraylist.internal.h"
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/bits/likely.h"
#include "libc/calls/calls.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/gc.internal.h"
@ -41,22 +40,26 @@ forceinline bool PointerNotOwnedByParentStackFrame(struct StackFrame *frame,
* @return arg
*/
void __defer(struct StackFrame *frame, void *fn, void *arg) {
struct StackFrame *frame2;
/*
* To avoid an API requiring dlmalloc dependency, say:
* defer(free_s, &ptr_not_owned_by_current_frame)
* Rather than:
* defer(weak(free), ptr)
*/
size_t n2;
struct Garbage *p2;
struct StackFrame *f2;
if (!arg) return;
frame2 = __builtin_frame_address(0);
assert(frame2->next == frame);
assert(PointerNotOwnedByParentStackFrame(frame2, frame, arg));
if (append(&__garbage,
(&(const struct Garbage){frame->next, (intptr_t)fn, (intptr_t)arg,
frame->addr})) != -1) {
atomic_store(&frame->addr, (intptr_t)&__gc);
} else {
abort();
f2 = __builtin_frame_address(0);
assert(__garbage.n);
assert(f2->next == frame);
assert(PointerNotOwnedByParentStackFrame(f2, frame, arg));
if (UNLIKELY(__garbage.i == __garbage.n)) {
n2 = __garbage.n + (__garbage.n >> 1);
p2 = malloc(n2 * sizeof(*__garbage.p));
memcpy(p2, __garbage.p, __garbage.n * sizeof(*__garbage.p));
if (__garbage.p != __garbage.initmem) free(__garbage.p);
__garbage.p = p2;
__garbage.n = n2;
}
__garbage.p[__garbage.i].frame = frame->next;
__garbage.p[__garbage.i].fn = (intptr_t)fn;
__garbage.p[__garbage.i].arg = (intptr_t)arg;
__garbage.p[__garbage.i].ret = frame->addr;
__garbage.i++;
frame->addr = (intptr_t)__gc;
}

View file

@ -19,15 +19,15 @@
#include "libc/macros.h"
.source __FILE__
/ Free memory returned by malloc() & co.
/
/ Releases the chunk of memory pointed to by p, that had been
/ previously allocated using malloc or a related routine such as
/ realloc. It has no effect if p is null. If p was not malloced or
/ already freed, free(p) will by default cuase the current program to
/ abort.
/
/ @param rdi is allocation address, which may be NULL
/ @see dlfree()
// Free memory returned by malloc() & co.
//
// Releases the chunk of memory pointed to by p, that had been
// previously allocated using malloc or a related routine such as
// realloc. It has no effect if p is null. If p was not malloced or
// already freed, free(p) will by default cuase the current program to
// abort.
//
// @param rdi is allocation address, which may be NULL
// @see dlfree()
free: jmp *hook_free(%rip)
.endfn free,globl

View file

@ -19,22 +19,22 @@
#include "libc/macros.h"
.source __FILE__
/ Allocates uninitialized memory.
/
/ Returns a pointer to a newly allocated chunk of at least n bytes, or
/ null if no space is available, in which case errno is set to ENOMEM
/ on ANSI C systems.
/
/ If n is zero, malloc returns a minimum-sized chunk. (The minimum size
/ is 32 bytes on 64bit systems.) Note that size_t is an unsigned type,
/ so calls with arguments that would be negative if signed are
/ interpreted as requests for huge amounts of space, which will often
/ fail. The maximum supported value of n differs across systems, but is
/ in all cases less than the maximum representable value of a size_t.
/
/ @param rdi is number of bytes needed
/ @return new memory, or NULL w/ errno
/ @note malloc(0) → malloc(32)
/ @see dlmalloc()
// Allocates uninitialized memory.
//
// Returns a pointer to a newly allocated chunk of at least n bytes, or
// null if no space is available, in which case errno is set to ENOMEM
// on ANSI C systems.
//
// If n is zero, malloc returns a minimum-sized chunk. (The minimum size
// is 32 bytes on 64bit systems.) Note that size_t is an unsigned type,
// so calls with arguments that would be negative if signed are
// interpreted as requests for huge amounts of space, which will often
// fail. The maximum supported value of n differs across systems, but is
// in all cases less than the maximum representable value of a size_t.
//
// @param rdi is number of bytes needed
// @return new memory, or NULL w/ errno
// @note malloc(0) → malloc(32)
// @see dlmalloc()
malloc: jmp *hook_malloc(%rip)
.endfn malloc,globl

View file

@ -18,10 +18,10 @@
*/
#include "libc/macros.h"
/ Releases freed memory back to system.
/
/ @param rdi specifies bytes of memory to leave available
/ @return 1 if it actually released any memory, else 0
// Releases freed memory back to system.
//
// @param rdi specifies bytes of memory to leave available
// @return 1 if it actually released any memory, else 0
malloc_trim:
jmp *hook_malloc_trim(%rip)
.endfn malloc_trim,globl

View file

@ -20,22 +20,22 @@
#include "libc/notice.inc"
.source __FILE__
/ Returns the number of bytes you can actually use in
/ an allocated chunk, which may be more than you requested
/ (although often not) due to alignment and minimum size
/ constraints.
/
/ You can use this many bytes without worrying about overwriting
/ other allocated objects. This is not a particularly great
/ programming practice. malloc_usable_size can be more useful in
/ debugging and assertions, for example:
/
/ p = malloc(n)
/ assert(malloc_usable_size(p) >= 256)
/
/ @param rdi is address of allocation
/ @return rax is total number of bytes
/ @see dlmalloc_usable_size()
// Returns the number of bytes you can actually use in
// an allocated chunk, which may be more than you requested
// (although often not) due to alignment and minimum size
// constraints.
//
// You can use this many bytes without worrying about overwriting
// other allocated objects. This is not a particularly great
// programming practice. malloc_usable_size can be more useful in
// debugging and assertions, for example:
//
// p = malloc(n)
// assert(malloc_usable_size(p) >= 256)
//
// @param rdi is address of allocation
// @return rax is total number of bytes
// @see dlmalloc_usable_size()
malloc_usable_size:
jmp *hook_malloc_usable_size(%rip)
.endfn malloc_usable_size,globl

View file

@ -20,20 +20,20 @@
#include "libc/notice.inc"
.source __FILE__
/ Allocates aligned memory.
/
/ Returns a pointer to a newly allocated chunk of n bytes, aligned in
/ accord with the alignment argument. The alignment argument should be
/ a power of two. If the argument is not a power of two, the nearest
/ greater power is used. 8-byte alignment is guaranteed by normal
/ malloc calls, so don't bother calling memalign with an argument of 8
/ or less.
/
/ @param rdi is alignment in bytes
/ @param rsi (newsize) is number of bytes needed
/ @return rax is memory address, or NULL w/ errno
/ @note overreliance on memalign is a sure way to fragment space
/ @see dlmemalign()
// Allocates aligned memory.
//
// Returns a pointer to a newly allocated chunk of n bytes, aligned in
// accord with the alignment argument. The alignment argument should be
// a power of two. If the argument is not a power of two, the nearest
// greater power is used. 8-byte alignment is guaranteed by normal
// malloc calls, so don't bother calling memalign with an argument of 8
// or less.
//
// @param rdi is alignment in bytes
// @param rsi (newsize) is number of bytes needed
// @return rax is memory address, or NULL w/ errno
// @note overreliance on memalign is a sure way to fragment space
// @see dlmemalign()
memalign:
jmp *hook_memalign(%rip)
.endfn memalign,globl

View file

@ -19,18 +19,18 @@
#include "libc/macros.h"
.source __FILE__
/ Allocates aligned memory the POSIX way.
/
/ Allocates a chunk of n bytes, aligned in accord with the alignment
/ argument. Differs from memalign only in that it (1) assigns the
/ allocated memory to *pp rather than returning it, (2) fails and
/ returns EINVAL if the alignment is not a power of two (3) fails and
/ returns ENOMEM if memory cannot be allocated.
/
/ @param rdi is void **pp
/ @param rsi is size_t align
/ @param rdx is size_t size
/ @return eax
// Allocates aligned memory the POSIX way.
//
// Allocates a chunk of n bytes, aligned in accord with the alignment
// argument. Differs from memalign only in that it (1) assigns the
// allocated memory to *pp rather than returning it, (2) fails and
// returns EINVAL if the alignment is not a power of two (3) fails and
// returns ENOMEM if memory cannot be allocated.
//
// @param rdi is void **pp
// @param rsi is size_t align
// @param rdx is size_t size
// @return eax
posix_memalign:
jmp *hook_posix_memalign(%rip)
.endfn posix_memalign,globl

View file

@ -20,11 +20,11 @@
#include "libc/notice.inc"
.source __FILE__
/ Equivalent to valloc(minimum-page-that-holds(n)), that is,
/ round up n to nearest pagesize.
/
/ @param rdi is number of bytes needed
/ @return rax is memory address, or NULL w/ errno
/ @see dlpvalloc()
// Equivalent to valloc(minimum-page-that-holds(n)), that is,
// round up n to nearest pagesize.
//
// @param rdi is number of bytes needed
// @return rax is memory address, or NULL w/ errno
// @see dlpvalloc()
pvalloc:jmp *hook_pvalloc(%rip)
.endfn pvalloc,globl

View file

@ -20,40 +20,40 @@
#include "libc/notice.inc"
.source __FILE__
/ Allocates / resizes / frees memory, e.g.
/
/ Returns a pointer to a chunk of size n that contains the same data as
/ does chunk p up to the minimum of (n, p's size) bytes, or null if no
/ space is available.
/
/ If p is NULL, realloc is equivalent to malloc.
/ If p is not NULL and n is 0, realloc is equivalent to free.
/
/ The returned pointer may or may not be the same as p. The algorithm
/ prefers extending p in most cases when possible, otherwise it employs
/ the equivalent of a malloc-copy-free sequence.
/
/ Please note that p is NOT free()'d should realloc() fail, thus:
/
/ if ((p2 = realloc(p, n2))) {
/ p = p2;
/ ...
/ } else {
/ ...
/ }
/
/ if n is for fewer bytes than already held by p, the newly unused
/ space is lopped off and freed if possible.
/
/ The old unix realloc convention of allowing the last-free'd chunk to
/ be used as an argument to realloc is not supported.
/
/ @param rdi (p) is address of current allocation or NULL
/ @param rsi (n) is number of bytes needed
/ @return rax is result, or NULL w/ errno w/o free(p)
/ @note realloc(p=0, n=0) → malloc(32)
/ @note realloc(p≠0, n=0) → free(p)
/ @see dlrealloc()
// Allocates / resizes / frees memory, e.g.
//
// Returns a pointer to a chunk of size n that contains the same data as
// does chunk p up to the minimum of (n, p's size) bytes, or null if no
// space is available.
//
// If p is NULL, realloc is equivalent to malloc.
// If p is not NULL and n is 0, realloc is equivalent to free.
//
// The returned pointer may or may not be the same as p. The algorithm
// prefers extending p in most cases when possible, otherwise it employs
// the equivalent of a malloc-copy-free sequence.
//
// Please note that p is NOT free()'d should realloc() fail, thus:
//
// if ((p2 = realloc(p, n2))) {
// p = p2;
// ...
// } else {
// ...
// }
//
// if n is for fewer bytes than already held by p, the newly unused
// space is lopped off and freed if possible.
//
// The old unix realloc convention of allowing the last-free'd chunk to
// be used as an argument to realloc is not supported.
//
// @param rdi (p) is address of current allocation or NULL
// @param rsi (n) is number of bytes needed
// @return rax is result, or NULL w/ errno w/o free(p)
// @note realloc(p=0, n=0) → malloc(32)
// @note realloc(p≠0, n=0) → free(p)
// @see dlrealloc()
realloc:
jmp *hook_realloc(%rip)
.endfn realloc,globl

View file

@ -20,19 +20,19 @@
#include "libc/notice.inc"
.source __FILE__
/ Resizes the space allocated for p to size n, only if this can be
/ done without moving p (i.e., only if there is adjacent space
/ available if n is greater than p's current allocated size, or n
/ is less than or equal to p's size). This may be used instead of
/ plain realloc if an alternative allocation strategy is needed
/ upon failure to expand space, for example, reallocation of a
/ buffer that must be memory-aligned or cleared. You can use
/ realloc_in_place to trigger these alternatives only when needed.
/
/ @param rdi (p) is address of current allocation
/ @param rsi (newsize) is number of bytes needed
/ @return rax is result, or NULL w/ errno
/ @see dlrealloc_in_place()
// Resizes the space allocated for p to size n, only if this can be
// done without moving p (i.e., only if there is adjacent space
// available if n is greater than p's current allocated size, or n
// is less than or equal to p's size). This may be used instead of
// plain realloc if an alternative allocation strategy is needed
// upon failure to expand space, for example, reallocation of a
// buffer that must be memory-aligned or cleared. You can use
// realloc_in_place to trigger these alternatives only when needed.
//
// @param rdi (p) is address of current allocation
// @param rsi (newsize) is number of bytes needed
// @return rax is result, or NULL w/ errno
// @see dlrealloc_in_place()
realloc_in_place:
jmp *hook_realloc_in_place(%rip)
.endfn realloc_in_place,globl

View file

@ -20,10 +20,10 @@
#include "libc/notice.inc"
.source __FILE__
/ Equivalent to memalign(4096, n).
/
/ @param rdi is number of bytes needed
/ @return rax is memory address, or NULL w/ errno
/ @see dlvalloc()
// Equivalent to memalign(4096, n).
//
// @param rdi is number of bytes needed
// @return rax is memory address, or NULL w/ errno
// @see dlvalloc()
valloc: jmp *hook_valloc(%rip)
.endfn valloc,globl

View file

@ -18,21 +18,21 @@
*/
#include "libc/macros.h"
/ Returns binary logarithm of integer 𝑥.
/
/ uint32 𝑥 bsf(𝑥) tzcnt(𝑥) ffs(𝑥) bsr(𝑥) lzcnt(𝑥)
/ 0x00000000 wut 32 0 wut 32
/ 0x00000001 0 0 1 0 31
/ 0x80000001 0 0 1 31 0
/ 0x80000000 31 31 32 31 0
/ 0x00000010 4 4 5 4 27
/ 0x08000010 4 4 5 27 4
/ 0x08000000 27 27 28 27 4
/ 0xffffffff 0 0 1 31 0
/
/ @param rsi:rdi is 128-bit unsigned 𝑥 value
/ @return eax number in range [0,128) or undef if 𝑥 is 0
/ @see also treasure trove of nearly identical functions
// Returns binary logarithm of integer 𝑥.
//
// uint32 𝑥 bsf(𝑥) tzcnt(𝑥) ffs(𝑥) bsr(𝑥) lzcnt(𝑥)
// 0x00000000 wut 32 0 wut 32
// 0x00000001 0 0 1 0 31
// 0x80000001 0 0 1 31 0
// 0x80000000 31 31 32 31 0
// 0x00000010 4 4 5 4 27
// 0x08000010 4 4 5 27 4
// 0x08000000 27 27 28 27 4
// 0xffffffff 0 0 1 31 0
//
// @param rsi:rdi is 128-bit unsigned 𝑥 value
// @return eax number in range [0,128) or undef if 𝑥 is 0
// @see also treasure trove of nearly identical functions
bsrmax: .leafprologue
.profilable
bsr %rsi,%rax

View file

@ -18,15 +18,15 @@
*/
#include "libc/macros.h"
/ Sets memory to zero.
/
/ C code should always favor memset(), since that's the one we've
/ prototyped with the best optimizations. This definition is used
/ by old code and sometimes code generators, as a thunk.
/
/ @param rdi is dest
/ @param rsi is the number of bytes to set
/ @see memset(), explicit_bzero()
// Sets memory to zero.
//
// C code should always favor memset(), since that's the one we've
// prototyped with the best optimizations. This definition is used
// by old code and sometimes code generators, as a thunk.
//
// @param rdi is dest
// @param rsi is the number of bytes to set
// @see memset(), explicit_bzero()
bzero: mov %rsi,%rdx
xor %esi,%esi
jmp MemSet

View file

@ -19,19 +19,19 @@
#include "ape/relocations.h"
#include "libc/macros.h"
/ Escapes byte for string literal.
/
/ This turns stuff like (char)0xFF into \0377. The returned
/ string is word-encoded, e.g. '\\'|'0'<<010|'3'<<020|etc.
/
/ @param dil contains byte to escape
/ @see libc/nexgen32e/cescapec.c
// Escapes byte for string literal.
//
// This turns stuff like (char)0xFF into \0377. The returned
// string is word-encoded, e.g. '\\'|'0'<<010|'3'<<020|etc.
//
// @param dil contains byte to escape
// @see libc/nexgen32e/cescapec.c
cescapec:
movzbl %dil,%edi
lea -7(%rdi),%ecx
cmp $85,%cl
ja 1f
mov $'\\,%eax
mov $'\\',%eax
movzbl %cl,%ecx
jmp *cescapectab(,%rcx,8)
.Lanchorpoint:
@ -74,7 +74,7 @@ cescapec:
shl $24,%edi
or %ecx,%edi
lea (%rdi,%rax,4),%eax
add $'0<<030|'0<<020|'0<<010|'\\,%eax
add $'0'<<030|'0'<<020|'0'<<010|'\\',%eax
ret
.endfn cescapec,globl
@ -87,13 +87,13 @@ cescapectab.ro:
.byte 1,.LVT-.Lanchorpoint
.byte 1,.LFF-.Lanchorpoint
.byte 1,.LCR-.Lanchorpoint
.byte '\"-'\r-1,1b-.Lanchorpoint
.byte 20,1b-.Lanchorpoint
.byte 1,.LDQ-.Lanchorpoint
.byte '\'-'\"-1,1b-.Lanchorpoint
.byte '\''-'\"'-1,1b-.Lanchorpoint
.byte 1,.LSQ-.Lanchorpoint
.byte '?-'\'-1,1b-.Lanchorpoint
.byte '?'-'\''-1,1b-.Lanchorpoint
.byte 1,.LQM-.Lanchorpoint
.byte '\\-'?-1,1b-.Lanchorpoint
.byte '\\'-'?'-1,1b-.Lanchorpoint
.byte 1,.LBSL-.Lanchorpoint
.equ .Lcescapectab.ro.size,.-cescapectab.ro
.org 8 - .Lcescapectab.ro.size % 8 + .
@ -102,7 +102,7 @@ cescapectab.ro:
.initbss 300,_init_cescapec
cescapectab:
.rept '\\-7+1
.rept '\\'-7+1
.quad 0
.endr
.endobj cescapectab

View file

@ -18,11 +18,11 @@
*/
#include "libc/macros.h"
/ Compares 8-bit signed integers.
/
/ @param rdi points to left integer
/ @param rsi points to right integer
/ @return <0, 0, or >0 based on comparison
// Compares 8-bit signed integers.
//
// @param rdi points to left integer
// @param rsi points to right integer
// @return <0, 0, or >0 based on comparison
.align 16
cmpsb: .leafprologue
.profilable

View file

@ -18,19 +18,19 @@
*/
#include "libc/macros.h"
/ Compares 32-bit signed integers.
/
/ @param rdi points to left integer
/ @param rsi points to right integer
/ @return <0, 0, or >0 based on comparison
// Compares 32-bit signed integers.
//
// @param rdi points to left integer
// @param rsi points to right integer
// @return <0, 0, or >0 based on comparison
.align 16
cmpsl: .leafprologue
.profilable
xor %eax,%eax
cmpsl
/ mov (%rdi),%edi
/ mov (%rsi),%esi
/ cmp %edi,%esi
// mov (%rdi),%edi
// mov (%rsi),%esi
// cmp %edi,%esi
setl %al
cmovg .Lneg1(%rip),%eax
.leafepilogue

View file

@ -18,11 +18,11 @@
*/
#include "libc/macros.h"
/ Compares 64-bit signed integers.
/
/ @param rdi points to left integer
/ @param rsi points to right integer
/ @return <0, 0, or >0 based on comparison
// Compares 64-bit signed integers.
//
// @param rdi points to left integer
// @param rsi points to right integer
// @return <0, 0, or >0 based on comparison
.align 16
cmpsq: .leafprologue
.profilable

View file

@ -18,11 +18,11 @@
*/
#include "libc/macros.h"
/ Compares 16-bit signed integers.
/
/ @param rdi points to left integer
/ @param rsi points to right integer
/ @return <0, 0, or >0 based on comparison
// Compares 16-bit signed integers.
//
// @param rdi points to left integer
// @param rsi points to right integer
// @return <0, 0, or >0 based on comparison
.align 16
cmpsw: .leafprologue
.profilable

View file

@ -18,11 +18,11 @@
*/
#include "libc/macros.h"
/ Compares 8-bit unsigned integers.
/
/ @param rdi points to left integer
/ @param rsi points to right integer
/ @return <0, 0, or >0 based on comparison
// Compares 8-bit unsigned integers.
//
// @param rdi points to left integer
// @param rsi points to right integer
// @return <0, 0, or >0 based on comparison
.align 16
cmpub: .leafprologue
.profilable

View file

@ -18,11 +18,11 @@
*/
#include "libc/macros.h"
/ Compares 32-bit unsigned integers.
/
/ @param rdi points to left integer
/ @param rsi points to right integer
/ @return <0, 0, or >0 based on comparison
// Compares 32-bit unsigned integers.
//
// @param rdi points to left integer
// @param rsi points to right integer
// @return <0, 0, or >0 based on comparison
.align 16
cmpul: .leafprologue
.profilable

View file

@ -18,11 +18,11 @@
*/
#include "libc/macros.h"
/ Compares 64-bit unsigned integers.
/
/ @param rdi points to left integer
/ @param rsi points to right integer
/ @return <0, 0, or >0 based on comparison
// Compares 64-bit unsigned integers.
//
// @param rdi points to left integer
// @param rsi points to right integer
// @return <0, 0, or >0 based on comparison
.align 16
cmpuq: .leafprologue
.profilable

View file

@ -18,11 +18,11 @@
*/
#include "libc/macros.h"
/ Compares 16-bit unsigned integers.
/
/ @param rdi points to left integer
/ @param rsi points to right integer
/ @return <0, 0, or >0 based on comparison
// Compares 16-bit unsigned integers.
//
// @param rdi points to left integer
// @param rsi points to right integer
// @return <0, 0, or >0 based on comparison
.align 16
cmpuw: .leafprologue
.profilable

View file

@ -18,18 +18,18 @@
*/
#include "libc/macros.h"
/ Computes Phil Katz CRC-32 w/ carryless multiply isa.
/
/ This is support code that's abstracted by crc32_z().
/
/ @param edi is initial value
/ @param rsi points to buffer
/ @param rdx is bytes in buffer that's >=64 and %16==0
/ @return eax is crc32
/ @note needs Westmere (c.2010) or Bulldozer (c.2011)
/ @see “Fast CRC Computation for Generic Polynomials Using
/ PCLMULQDQ Instruction V. Gopal, E. Ozturk, et al.,
/ 2009, intel.ly/2ySEwL0
// Computes Phil Katz CRC-32 w/ carryless multiply isa.
//
// This is support code that's abstracted by crc32_z().
//
// @param edi is initial value
// @param rsi points to buffer
// @param rdx is bytes in buffer that's >=64 and %16==0
// @return eax is crc32
// @note needs Westmere (c.2010) or Bulldozer (c.2011)
// @see “Fast CRC Computation for Generic Polynomials Using
// PCLMULQDQ Instruction V. Gopal, E. Ozturk, et al.,
// 2009, intel.ly/2ySEwL0
crc32_pclmul:
.leafprologue
.profilable
@ -139,8 +139,8 @@ crc32_pclmul:
.endfn crc32_pclmul,globl,hidden
.source __FILE__
/ Definitions of the bit-reflected domain constants k1,k2,k3, etc.
/ and the CRC32+Barrett polynomials given at the end of the paper.
// Definitions of the bit-reflected domain constants k1,k2,k3, etc.
// and the CRC32+Barrett polynomials given at the end of the paper.
.rodata.cst16
.Lk1k2: .quad 0x0000000154442bd4
.quad 0x00000001c6e41596

View file

@ -18,22 +18,22 @@
*/
#include "libc/macros.h"
/ Generates lookup table for computing CRC-32 byte-by-byte.
/
/ void crc32init(uint32_t table[256], uint32_t polynomial) {
/ uint32_t d, i, r;
/ for (d = 0; d < 256; ++d) {
/ r = d;
/ for (i = 0; i < 8; ++i) {
/ r = r >> 1 ^ (r & 1 ? polynomial : 0);
/ }
/ table[d] = r;
/ }
/ }
/
/ @param rdi is pointer to uint32_t[256] array
/ @param esi 32-bit binary polynomial config
/ @note imposes ~300ns one-time cost
// Generates lookup table for computing CRC-32 byte-by-byte.
//
// void crc32init(uint32_t table[256], uint32_t polynomial) {
// uint32_t d, i, r;
// for (d = 0; d < 256; ++d) {
// r = d;
// for (i = 0; i < 8; ++i) {
// r = r >> 1 ^ (r & 1 ? polynomial : 0);
// }
// table[d] = r;
// }
// }
//
// @param rdi is pointer to uint32_t[256] array
// @param esi 32-bit binary polynomial config
// @note imposes ~300ns one-time cost
crc32init:
push %rbp
mov %rsp,%rbp

View file

@ -18,10 +18,10 @@
*/
#include "libc/macros.h"
/ Divides 64-bit signed integer by 1,000,000,000.
/
/ @param rdi is number to divide
/ @return quotient
// Divides 64-bit signed integer by 1,000,000,000.
//
// @param rdi is number to divide
// @return quotient
div1000000000int64:
mov $0x1a,%cl
movabs $0x112e0be826d694b3,%rdx

View file

@ -18,10 +18,10 @@
*/
#include "libc/macros.h"
/ Divides 64-bit signed integer by 1,000,000.
/
/ @param rdi is number to divide
/ @return quotient
// Divides 64-bit signed integer by 1,000,000.
//
// @param rdi is number to divide
// @return quotient
div1000000int64:
mov $0x12,%cl
movabs $0x431bde82d7b634db,%rdx

View file

@ -18,10 +18,10 @@
*/
#include "libc/macros.h"
/ Divides 64-bit signed integer by 10,000.
/
/ @param rdi is number to divide
/ @return truncated quotient
// Divides 64-bit signed integer by 10,000.
//
// @param rdi is number to divide
// @return truncated quotient
div10000int64:
mov $11,%cl
movabs $0x346dc5d63886594b,%rdx

View file

@ -18,10 +18,10 @@
*/
#include "libc/macros.h"
/ Divides 64-bit signed integer by 1,000.
/
/ @param rdi is number to divide
/ @return quotient
// Divides 64-bit signed integer by 1,000.
//
// @param rdi is number to divide
// @return quotient
div1000int64:
mov $0x7,%cl
movabs $0x20c49ba5e353f7cf,%rdx

View file

@ -18,10 +18,10 @@
*/
#include "libc/macros.h"
/ Divides 64-bit signed integer by 100.
/
/ @param rdi is number to divide
/ @return rax has quotient
// Divides 64-bit signed integer by 100.
//
// @param rdi is number to divide
// @return rax has quotient
div100int64:
mov %rdi,%rax
movabs $-6640827866535438581,%rdx

View file

@ -18,10 +18,10 @@
*/
#include "libc/macros.h"
/ Divides 64-bit signed integer by 10.
/
/ @param rdi is number to divide
/ @return quotient
// Divides 64-bit signed integer by 10.
//
// @param rdi is number to divide
// @return quotient
div10int64:
mov $2,%cl
movabs $0x6666666666666667,%rdx

View file

@ -1,12 +1,12 @@
#include "libc/macros.h"
.source __FILE__
/ D.J. Bernstein's outrageously fast integer sorting algorithm.
/
/ @param rdi is int32 array
/ @param rsi is number of elements in rdi
/ @note public domain
/ @see en.wikipedia.org/wiki/Sorting_network
// D.J. Bernstein's outrageously fast integer sorting algorithm.
//
// @param rdi is int32 array
// @param rsi is number of elements in rdi
// @note public domain
// @see en.wikipedia.org/wiki/Sorting_network
djbsort_avx2:
push %rbp
mov %rsp,%rbp
@ -1115,7 +1115,7 @@ int32_sort_2power:
vpxor 32(%rdi),%ymm0,%ymm2
vpxor (%rdi),%ymm0,%ymm0
vmovdqa .LC1(%rip),%ymm4
cmp $0,-116(%rbp)
cmpl $0,-116(%rbp)
vpunpckldq %ymm2,%ymm0,%ymm1
vpunpckhdq %ymm2,%ymm0,%ymm0
vpunpcklqdq %ymm0,%ymm1,%ymm3
@ -1179,7 +1179,7 @@ int32_sort_2power:
mov $16,%esi
mov %r13,%rdi
call int32_sort_2power
cmp $0,-116(%rbp)
cmpl $0,-116(%rbp)
vmovdqu (%r12),%ymm4
vmovdqu 32(%r12),%ymm1
vmovdqu 64(%r12),%ymm2
@ -1750,7 +1750,7 @@ int32_sort_2power:
vpunpckhdq 160(%rax),%ymm7,%ymm0
vpunpcklqdq %ymm2,%ymm12,%ymm8
vpunpcklqdq %ymm4,%ymm6,%ymm9
cmp $0,-116(%rbp)
cmpl $0,-116(%rbp)
vmovdqu 192(%rax),%ymm7
vpunpckhqdq %ymm2,%ymm12,%ymm12
vpunpckhqdq %ymm4,%ymm6,%ymm4
@ -1837,7 +1837,7 @@ int32_sort_2power:
vmovdqu %ymm2,-64(%rax)
vmovdqu %ymm0,-32(%rax)
jmp .L85
.L142: cmp $32,-112(%rbp)
.L142: cmpq $32,-112(%rbp)
jne .L94
.L93: mov -112(%rbp),%rcx
sar $2,%rcx
@ -1871,7 +1871,7 @@ int32_sort_2power:
cmp %rax,%r15
jg .L92
sarq $3,-112(%rbp)
.L89: cmp $127,-112(%rbp)
.L89: cmpq $127,-112(%rbp)
jle .L142
jmp .L93
.L92: cmp -136(%rbp),%rax
@ -1925,7 +1925,7 @@ int32_sort_2power:
add %rdx,-136(%rbp)
jmp .L90
.L145: sarq $2,-112(%rbp)
.L94: cmp $15,-112(%rbp)
.L94: cmpq $15,-112(%rbp)
jle .L144
mov -112(%rbp),%rcx
xor %esi,%esi
@ -1962,7 +1962,7 @@ int32_sort_2power:
.L146: add %rdx,%rsi
add %rdx,%rcx
jmp .L95
.L144: cmp $8,-112(%rbp)
.L144: cmpq $8,-112(%rbp)
je .L111
.L102: mov -152(%rbp),%rdx
add -128(%rbp),%rdx
@ -1997,7 +1997,7 @@ int32_sort_2power:
vpmaxsd %ymm3,%ymm5,%ymm3
vpminsd (%rdi),%ymm7,%ymm1
vpminsd %ymm2,%ymm4,%ymm10
cmp $0,-116(%rbp)
cmpl $0,-116(%rbp)
vpmaxsd (%rdi),%ymm7,%ymm0
vmovdqu (%rsi),%ymm7
vpmaxsd %ymm2,%ymm4,%ymm2

Some files were not shown because too many files have changed in this diff Show more