mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 07:29:23 +00:00
Clean up the clone() code a bit
This commit is contained in:
parent
ce71677156
commit
2743f3d012
20 changed files with 252 additions and 150 deletions
|
@ -18,11 +18,11 @@
|
||||||
#include "libc/fmt/conv.h"
|
#include "libc/fmt/conv.h"
|
||||||
#include "libc/fmt/itoa.h"
|
#include "libc/fmt/itoa.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/intrin/threaded.h"
|
|
||||||
#include "libc/log/check.h"
|
#include "libc/log/check.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/nexgen32e/threaded.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/runtime/sysconf.h"
|
#include "libc/runtime/sysconf.h"
|
||||||
#include "libc/sock/sock.h"
|
#include "libc/sock/sock.h"
|
||||||
|
|
|
@ -35,12 +35,11 @@ privileged wontreturn void _Exit1(int rc) {
|
||||||
struct WinThread *wt;
|
struct WinThread *wt;
|
||||||
STRACE("_Exit1(%d)", rc);
|
STRACE("_Exit1(%d)", rc);
|
||||||
if (!IsWindows() && !IsMetal()) {
|
if (!IsWindows() && !IsMetal()) {
|
||||||
register long r10 asm("r10") = 0;
|
asm volatile("xor\t%%r10d,%%r10d\n\t"
|
||||||
asm volatile("syscall"
|
"syscall"
|
||||||
: /* no outputs */
|
: /* no outputs */
|
||||||
: "a"(__NR_exit), "D"(IsLinux() ? rc : 0), "S"(0), "d"(0),
|
: "a"(__NR_exit), "D"(IsLinux() ? rc : 0), "S"(0), "d"(0)
|
||||||
"r"(r10)
|
: "rcx", "r10", "r11", "memory");
|
||||||
: "rcx", "r11", "memory");
|
|
||||||
} else if (IsWindows()) {
|
} else if (IsWindows()) {
|
||||||
ExitThread(rc);
|
ExitThread(rc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/threaded.h"
|
#include "libc/nexgen32e/threaded.h"
|
||||||
#include "libc/nt/thread.h"
|
#include "libc/nt/thread.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -31,11 +31,11 @@
|
||||||
#include "libc/intrin/lockcmpxchg.h"
|
#include "libc/intrin/lockcmpxchg.h"
|
||||||
#include "libc/intrin/nomultics.internal.h"
|
#include "libc/intrin/nomultics.internal.h"
|
||||||
#include "libc/intrin/spinlock.h"
|
#include "libc/intrin/spinlock.h"
|
||||||
#include "libc/intrin/threaded.h"
|
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
#include "libc/log/internal.h"
|
#include "libc/log/internal.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/nexgen32e/rdtsc.h"
|
#include "libc/nexgen32e/rdtsc.h"
|
||||||
|
#include "libc/nexgen32e/threaded.h"
|
||||||
#include "libc/nexgen32e/uart.internal.h"
|
#include "libc/nexgen32e/uart.internal.h"
|
||||||
#include "libc/nt/process.h"
|
#include "libc/nt/process.h"
|
||||||
#include "libc/nt/runtime.h"
|
#include "libc/nt/runtime.h"
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_INTRIN_THREADED_H_
|
|
||||||
#define COSMOPOLITAN_LIBC_INTRIN_THREADED_H_
|
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
|
||||||
COSMOPOLITAN_C_START_
|
|
||||||
|
|
||||||
extern bool __threaded;
|
|
||||||
extern bool __tls_enabled;
|
|
||||||
extern unsigned __tls_index;
|
|
||||||
|
|
||||||
void *__initialize_tls(char[hasatleast 64]);
|
|
||||||
void __install_tls(char[hasatleast 64]);
|
|
||||||
char *__get_tls(void);
|
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
|
||||||
#endif /* COSMOPOLITAN_LIBC_INTRIN_THREADED_H_ */
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/threaded.h"
|
#include "libc/nexgen32e/threaded.h"
|
||||||
#include "libc/nt/thread.h"
|
#include "libc/nt/thread.h"
|
||||||
#include "libc/nt/thunk/msabi.h"
|
#include "libc/nt/thunk/msabi.h"
|
||||||
#include "libc/sysv/consts/nrlinux.h"
|
#include "libc/sysv/consts/nrlinux.h"
|
||||||
|
|
38
libc/nexgen32e/checkstackalign.S
Normal file
38
libc/nexgen32e/checkstackalign.S
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 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/macros.internal.h"
|
||||||
|
|
||||||
|
// Checks that stack is 16-byte aligned.
|
||||||
|
//
|
||||||
|
// This function crashes if called with a misaligned stack.
|
||||||
|
_checkstackalign:
|
||||||
|
push %rbp
|
||||||
|
mov %rsp,%rbp
|
||||||
|
|
||||||
|
/ allocate sixteen bytes
|
||||||
|
push %rax
|
||||||
|
push %rax
|
||||||
|
|
||||||
|
/ put a value in it
|
||||||
|
xorps %xmm0,%xmm0
|
||||||
|
movaps %xmm0,-16(%rbp)
|
||||||
|
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
.endfn _checkstackalign,globl
|
|
@ -7,6 +7,7 @@ extern long kHalfCache3;
|
||||||
|
|
||||||
void imapxlatab(void *);
|
void imapxlatab(void *);
|
||||||
void insertionsort(int32_t *, size_t);
|
void insertionsort(int32_t *, size_t);
|
||||||
|
void _checkstackalign(void);
|
||||||
|
|
||||||
int64_t div10int64(int64_t) libcesque pureconst;
|
int64_t div10int64(int64_t) libcesque pureconst;
|
||||||
int64_t div100int64(int64_t) libcesque pureconst;
|
int64_t div100int64(int64_t) libcesque pureconst;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/intrin/threaded.h"
|
#include "libc/nexgen32e/threaded.h"
|
||||||
|
|
||||||
bool __threaded;
|
bool __threaded;
|
||||||
bool __tls_enabled;
|
bool __tls_enabled;
|
||||||
|
|
39
libc/nexgen32e/threaded.h
Normal file
39
libc/nexgen32e/threaded.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_THREADED_H_
|
||||||
|
#define COSMOPOLITAN_LIBC_NEXGEN32E_THREADED_H_
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
extern bool __threaded;
|
||||||
|
extern bool __tls_enabled;
|
||||||
|
extern unsigned __tls_index;
|
||||||
|
|
||||||
|
void *__initialize_tls(char[hasatleast 64]);
|
||||||
|
void __install_tls(char[hasatleast 64]);
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && defined(__x86_64__)
|
||||||
|
/**
|
||||||
|
* Returns address of thread information block.
|
||||||
|
*
|
||||||
|
* This function must not be called until TLS is initialized.
|
||||||
|
*
|
||||||
|
* @see __install_tls()
|
||||||
|
* @see clone()
|
||||||
|
*/
|
||||||
|
static noasan inline char *__get_tls(void) {
|
||||||
|
char *tib, *lin = (char *)0x30;
|
||||||
|
if (IsLinux() || IsFreebsd() || IsNetbsd() || IsOpenbsd()) {
|
||||||
|
asm("mov\t%%fs:(%1),%0" : "=a"(tib) : "r"(lin));
|
||||||
|
} else {
|
||||||
|
asm("mov\t%%gs:(%1),%0" : "=a"(tib) : "r"(lin));
|
||||||
|
if (IsWindows()) {
|
||||||
|
tib = *(char **)(tib + 0x1480 + __tls_index * 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tib;
|
||||||
|
}
|
||||||
|
#endif /* GNU x86-64 */
|
||||||
|
|
||||||
|
COSMOPOLITAN_C_END_
|
||||||
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_THREADED_H_ */
|
|
@ -26,7 +26,7 @@
|
||||||
#include "libc/intrin/asan.internal.h"
|
#include "libc/intrin/asan.internal.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/intrin/spinlock.h"
|
#include "libc/intrin/spinlock.h"
|
||||||
#include "libc/intrin/threaded.h"
|
#include "libc/nexgen32e/threaded.h"
|
||||||
#include "libc/nt/runtime.h"
|
#include "libc/nt/runtime.h"
|
||||||
#include "libc/nt/thread.h"
|
#include "libc/nt/thread.h"
|
||||||
#include "libc/nt/thunk/msabi.h"
|
#include "libc/nt/thunk/msabi.h"
|
||||||
|
@ -50,17 +50,32 @@ STATIC_YOINK("gettid"); // for kprintf()
|
||||||
#define LWP_DETACHED 0x00000040
|
#define LWP_DETACHED 0x00000040
|
||||||
#define LWP_SUSPENDED 0x00000080
|
#define LWP_SUSPENDED 0x00000080
|
||||||
|
|
||||||
static char tibdefault[64];
|
struct CloneArgs {
|
||||||
|
union {
|
||||||
struct WinThread {
|
int tid;
|
||||||
uint32_t tid;
|
uint32_t utid;
|
||||||
|
int64_t tid64;
|
||||||
|
};
|
||||||
|
int lock;
|
||||||
int flags;
|
int flags;
|
||||||
int *ctid;
|
int *ctid;
|
||||||
void *tls;
|
char *tls;
|
||||||
int (*func)(void *);
|
int (*func)(void *);
|
||||||
void *arg;
|
void *arg;
|
||||||
|
void *pad; // TODO: Why does FreeBSD clobber this?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct __tfork {
|
||||||
|
void *tf_tcb;
|
||||||
|
int32_t *tf_tid;
|
||||||
|
void *tf_stack;
|
||||||
|
};
|
||||||
|
|
||||||
|
static char tibdefault[64];
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// THE NEW TECHNOLOGY
|
||||||
|
|
||||||
uint32_t WinThreadThunk(void *warg);
|
uint32_t WinThreadThunk(void *warg);
|
||||||
asm(".section\t.text.windows,\"ax\",@progbits\n\t"
|
asm(".section\t.text.windows,\"ax\",@progbits\n\t"
|
||||||
".local\tWinThreadThunk\n"
|
".local\tWinThreadThunk\n"
|
||||||
|
@ -69,13 +84,14 @@ asm(".section\t.text.windows,\"ax\",@progbits\n\t"
|
||||||
"mov\t%rcx,%rdi\n\t"
|
"mov\t%rcx,%rdi\n\t"
|
||||||
"mov\t%rcx,%rsp\n\t"
|
"mov\t%rcx,%rsp\n\t"
|
||||||
"and\t$-16,%rsp\n\t"
|
"and\t$-16,%rsp\n\t"
|
||||||
"call\tWinThreadMain\n\t"
|
"push\t%rax\n\t"
|
||||||
|
"jmp\tWinThreadMain\n\t"
|
||||||
".size\tWinThreadThunk,.-WinThreadThunk\n\t"
|
".size\tWinThreadThunk,.-WinThreadThunk\n\t"
|
||||||
".previous");
|
".previous");
|
||||||
__attribute__((__used__, __no_reorder__))
|
__attribute__((__used__, __no_reorder__))
|
||||||
|
|
||||||
static textwindows wontreturn void
|
static textwindows wontreturn void
|
||||||
WinThreadMain(struct WinThread *wt) {
|
WinThreadMain(struct CloneArgs *wt) {
|
||||||
int rc;
|
int rc;
|
||||||
if (wt->flags & CLONE_SETTLS) {
|
if (wt->flags & CLONE_SETTLS) {
|
||||||
TlsSetValue(__tls_index, wt->tls);
|
TlsSetValue(__tls_index, wt->tls);
|
||||||
|
@ -91,16 +107,16 @@ static textwindows int CloneWindows(int (*func)(void *), char *stk,
|
||||||
size_t stksz, int flags, void *arg,
|
size_t stksz, int flags, void *arg,
|
||||||
void *tls, size_t tlssz, int *ctid) {
|
void *tls, size_t tlssz, int *ctid) {
|
||||||
int64_t h;
|
int64_t h;
|
||||||
struct WinThread *wt;
|
struct CloneArgs *wt;
|
||||||
wt = (struct WinThread *)(((intptr_t)(stk + stksz) -
|
wt = (struct CloneArgs *)(((intptr_t)(stk + stksz) -
|
||||||
sizeof(struct WinThread)) &
|
sizeof(struct CloneArgs)) &
|
||||||
-alignof(struct WinThread));
|
-alignof(struct CloneArgs));
|
||||||
wt->flags = flags;
|
wt->flags = flags;
|
||||||
wt->ctid = ctid;
|
wt->ctid = ctid;
|
||||||
wt->func = func;
|
wt->func = func;
|
||||||
wt->arg = arg;
|
wt->arg = arg;
|
||||||
wt->tls = tls;
|
wt->tls = tls;
|
||||||
if ((h = CreateThread(0, 0, WinThreadThunk, wt, 0, &wt->tid))) {
|
if ((h = CreateThread(0, 0, WinThreadThunk, wt, 0, &wt->utid))) {
|
||||||
CloseHandle(h);
|
CloseHandle(h);
|
||||||
return wt->tid;
|
return wt->tid;
|
||||||
} else {
|
} else {
|
||||||
|
@ -108,45 +124,49 @@ static textwindows int CloneWindows(int (*func)(void *), char *stk,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// XNU'S NOT UNIX
|
||||||
|
|
||||||
void XnuThreadThunk(void *pthread, int machport, void *(*func)(void *),
|
void XnuThreadThunk(void *pthread, int machport, void *(*func)(void *),
|
||||||
void *arg, intptr_t *stack, unsigned flags);
|
void *arg, intptr_t *stack, unsigned flags);
|
||||||
asm(".local\tXnuThreadThunk\n"
|
asm(".local\tXnuThreadThunk\n"
|
||||||
"XnuThreadThunk:\n\t"
|
"XnuThreadThunk:\n\t"
|
||||||
"xor\t%ebp,%ebp\n\t"
|
"xor\t%ebp,%ebp\n\t"
|
||||||
"mov\t%r8,%rsp\n\t"
|
"mov\t%r8,%rsp\n\t"
|
||||||
|
"and\t$-16,%rsp\n\t"
|
||||||
|
"push\t%rax\n\t"
|
||||||
"jmp\tXnuThreadMain\n\t"
|
"jmp\tXnuThreadMain\n\t"
|
||||||
".size\tXnuThreadThunk,.-XnuThreadThunk");
|
".size\tXnuThreadThunk,.-XnuThreadThunk");
|
||||||
__attribute__((__used__, __no_reorder__))
|
__attribute__((__used__, __no_reorder__))
|
||||||
|
|
||||||
static wontreturn void
|
static wontreturn void
|
||||||
XnuThreadMain(void *pthread, int tid, int (*func)(void *arg), void *arg,
|
XnuThreadMain(void *pthread, int tid, int (*func)(void *arg), void *arg,
|
||||||
intptr_t *sp, unsigned flags) {
|
struct CloneArgs *wt, unsigned flags) {
|
||||||
int rc;
|
int ax;
|
||||||
sp[1] = tid;
|
wt->tid = tid;
|
||||||
_spunlock(sp);
|
_spunlock(&wt->lock);
|
||||||
if (sp[4] & CLONE_SETTLS) {
|
if (wt->flags & CLONE_SETTLS) {
|
||||||
// XNU uses the same 0x30 offset as the WIN32 TIB x64. They told the
|
// XNU uses the same 0x30 offset as the WIN32 TIB x64. They told the
|
||||||
// Go team at Google that they Apply stands by our ability to use it
|
// Go team at Google that they Apply stands by our ability to use it
|
||||||
// https://github.com/golang/go/issues/23617#issuecomment-376662373
|
// https://github.com/golang/go/issues/23617#issuecomment-376662373
|
||||||
asm volatile("syscall"
|
asm volatile("syscall"
|
||||||
: "=a"(rc)
|
: "=a"(ax)
|
||||||
: "0"(__NR_thread_fast_set_cthread_self), "D"(sp[3] - 0x30)
|
: "0"(__NR_thread_fast_set_cthread_self), "D"(wt->tls - 0x30)
|
||||||
: "rcx", "r11", "memory", "cc");
|
: "rcx", "r11", "memory", "cc");
|
||||||
}
|
}
|
||||||
if (sp[4] & CLONE_CHILD_SETTID) {
|
if (wt->flags & CLONE_CHILD_SETTID) {
|
||||||
*(int *)sp[2] = tid;
|
*wt->ctid = tid;
|
||||||
}
|
}
|
||||||
rc = func(arg);
|
_Exit1(func(arg));
|
||||||
_Exit1(rc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CloneXnu(int (*fn)(void *), char *stk, size_t stksz, int flags,
|
static int CloneXnu(int (*fn)(void *), char *stk, size_t stksz, int flags,
|
||||||
void *arg, void *tls, size_t tlssz, int *ctid) {
|
void *arg, void *tls, size_t tlssz, int *ctid) {
|
||||||
int rc;
|
int rc;
|
||||||
bool failed;
|
bool failed;
|
||||||
intptr_t *sp;
|
|
||||||
static bool once;
|
static bool once;
|
||||||
static int broken;
|
static int broken;
|
||||||
|
struct CloneArgs *wt;
|
||||||
if (!once) {
|
if (!once) {
|
||||||
if (bsdthread_register(XnuThreadThunk, 0, 0, 0, 0, 0, 0) == -1) {
|
if (bsdthread_register(XnuThreadThunk, 0, 0, 0, 0, 0, 0) == -1) {
|
||||||
broken = errno;
|
broken = errno;
|
||||||
|
@ -157,38 +177,40 @@ static int CloneXnu(int (*fn)(void *), char *stk, size_t stksz, int flags,
|
||||||
errno = broken;
|
errno = broken;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
sp = (intptr_t *)(stk + stksz);
|
wt = (struct CloneArgs *)(((intptr_t)(stk + stksz) -
|
||||||
*--sp = 0; // 5 padding
|
sizeof(struct CloneArgs)) &
|
||||||
*--sp = flags; // 4 clone() flags
|
-alignof(struct CloneArgs));
|
||||||
*--sp = (intptr_t)tls; // 3 thread local storage
|
wt->flags = flags;
|
||||||
*--sp = (intptr_t)ctid; // 2 child tid api
|
wt->ctid = ctid;
|
||||||
*--sp = 0; // 1 receives tid
|
wt->tls = tls;
|
||||||
*--sp = 0; // 0 lock
|
_seizelock(&wt->lock); // TODO: How can we get the tid without locking?
|
||||||
_seizelock(sp); // TODO: How can we get the tid without locking?
|
if ((rc = bsdthread_create(fn, arg, wt, 0, PTHREAD_START_CUSTOM_XNU)) != -1) {
|
||||||
if ((rc = bsdthread_create(fn, arg, sp, 0, PTHREAD_START_CUSTOM_XNU)) != -1) {
|
_spinlock(&wt->lock);
|
||||||
_spinlock(sp);
|
rc = wt->tid;
|
||||||
rc = sp[1];
|
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreebsdThreadThunk(void *sp) wontreturn;
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// FREE BESIYATA DISHMAYA
|
||||||
|
|
||||||
|
void FreebsdThreadThunk(void *) wontreturn;
|
||||||
asm(".local\tFreebsdThreadThunk\n"
|
asm(".local\tFreebsdThreadThunk\n"
|
||||||
"FreebsdThreadThunk:\n\t"
|
"FreebsdThreadThunk:\n\t"
|
||||||
"xor\t%ebp,%ebp\n\t"
|
"xor\t%ebp,%ebp\n\t"
|
||||||
"mov\t%rdi,%rsp\n\t"
|
"mov\t%rdi,%rsp\n\t"
|
||||||
|
"and\t$-16,%rsp\n\t"
|
||||||
|
"push\t%rax\n\t"
|
||||||
"jmp\tFreebsdThreadMain\n\t"
|
"jmp\tFreebsdThreadMain\n\t"
|
||||||
".size\tFreebsdThreadThunk,.-FreebsdThreadThunk");
|
".size\tFreebsdThreadThunk,.-FreebsdThreadThunk");
|
||||||
__attribute__((__used__, __no_reorder__))
|
__attribute__((__used__, __no_reorder__))
|
||||||
|
|
||||||
static wontreturn void
|
static wontreturn void
|
||||||
FreebsdThreadMain(intptr_t *sp) {
|
FreebsdThreadMain(struct CloneArgs *wt) {
|
||||||
int rc;
|
if (wt->flags & CLONE_CHILD_SETTID) {
|
||||||
if (sp[3] & CLONE_CHILD_SETTID) {
|
*wt->ctid = wt->tid;
|
||||||
*(int *)sp[2] = sp[4];
|
|
||||||
}
|
}
|
||||||
rc = ((int (*)(intptr_t))sp[0])(sp[1]);
|
_Exit1(wt->func(wt->arg));
|
||||||
_Exit1(rc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CloneFreebsd(int (*func)(void *), char *stk, size_t stksz, int flags,
|
static int CloneFreebsd(int (*func)(void *), char *stk, size_t stksz, int flags,
|
||||||
|
@ -196,22 +218,23 @@ static int CloneFreebsd(int (*func)(void *), char *stk, size_t stksz, int flags,
|
||||||
int ax;
|
int ax;
|
||||||
bool failed;
|
bool failed;
|
||||||
int64_t tid;
|
int64_t tid;
|
||||||
intptr_t *sp;
|
struct CloneArgs *wt;
|
||||||
sp = (intptr_t *)(stk + stksz);
|
wt = (struct CloneArgs *)(((intptr_t)(stk + stksz) -
|
||||||
*--sp = 0; // 5 [padding]
|
sizeof(struct CloneArgs)) &
|
||||||
*--sp = 0; // 4 [child_tid]
|
-alignof(struct CloneArgs));
|
||||||
*--sp = flags; // 3
|
wt->flags = flags;
|
||||||
*--sp = (intptr_t)ctid; // 2
|
wt->ctid = ctid;
|
||||||
*--sp = (intptr_t)arg; // 1
|
wt->tls = tls;
|
||||||
*--sp = (intptr_t)func; // 0
|
wt->func = func;
|
||||||
|
wt->arg = arg;
|
||||||
struct thr_param params = {
|
struct thr_param params = {
|
||||||
.start_func = FreebsdThreadThunk,
|
.start_func = FreebsdThreadThunk,
|
||||||
.arg = sp,
|
.arg = wt,
|
||||||
.stack_base = stk,
|
.stack_base = stk,
|
||||||
.stack_size = stksz,
|
.stack_size = stksz,
|
||||||
.tls_base = flags & CLONE_SETTLS ? tls : 0,
|
.tls_base = flags & CLONE_SETTLS ? tls : 0,
|
||||||
.tls_size = flags & CLONE_SETTLS ? tlssz : 0,
|
.tls_size = flags & CLONE_SETTLS ? tlssz : 0,
|
||||||
.child_tid = sp + 4,
|
.child_tid = &wt->tid64,
|
||||||
.parent_tid = &tid,
|
.parent_tid = &tid,
|
||||||
};
|
};
|
||||||
asm volatile(CFLAG_ASM("syscall")
|
asm volatile(CFLAG_ASM("syscall")
|
||||||
|
@ -225,13 +248,10 @@ static int CloneFreebsd(int (*func)(void *), char *stk, size_t stksz, int flags,
|
||||||
return tid;
|
return tid;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct __tfork {
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void *tf_tcb;
|
// OPEN BESIYATA DISHMAYA
|
||||||
int32_t *tf_tid;
|
|
||||||
void *tf_stack;
|
|
||||||
};
|
|
||||||
|
|
||||||
int __tfork(struct __tfork *params, size_t psize, intptr_t *stack);
|
int __tfork(struct __tfork *params, size_t psize, struct CloneArgs *wt);
|
||||||
asm(".section\t.privileged,\"ax\",@progbits\n\t"
|
asm(".section\t.privileged,\"ax\",@progbits\n\t"
|
||||||
".local\t__tfork\n"
|
".local\t__tfork\n"
|
||||||
"__tfork:\n\t"
|
"__tfork:\n\t"
|
||||||
|
@ -248,46 +268,50 @@ asm(".section\t.privileged,\"ax\",@progbits\n\t"
|
||||||
"xor\t%ebp,%ebp\n\t"
|
"xor\t%ebp,%ebp\n\t"
|
||||||
"mov\t%r8,%rsp\n\t"
|
"mov\t%r8,%rsp\n\t"
|
||||||
"mov\t%r8,%rdi\n\t"
|
"mov\t%r8,%rdi\n\t"
|
||||||
|
"and\t$-16,%rsp\n\t"
|
||||||
|
"push\t%rax\n\t"
|
||||||
"jmp\tOpenbsdThreadMain\n\t"
|
"jmp\tOpenbsdThreadMain\n\t"
|
||||||
".size\t__tfork,.-__tfork\n\t"
|
".size\t__tfork,.-__tfork\n\t"
|
||||||
".previous");
|
".previous");
|
||||||
__attribute__((__used__, __no_reorder__))
|
__attribute__((__used__, __no_reorder__))
|
||||||
|
|
||||||
static privileged wontreturn void
|
static privileged wontreturn void
|
||||||
OpenbsdThreadMain(intptr_t *sp) {
|
OpenbsdThreadMain(struct CloneArgs *wt) {
|
||||||
int rc;
|
_Exit1(wt->func(wt->arg));
|
||||||
rc = ((int (*)(intptr_t))sp[0])(sp[1]);
|
|
||||||
_Exit1(rc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CloneOpenbsd(int (*func)(void *), char *stk, size_t stksz, int flags,
|
static int CloneOpenbsd(int (*func)(void *), char *stk, size_t stksz, int flags,
|
||||||
void *arg, void *tls, size_t tlssz, int *ctid) {
|
void *arg, void *tls, size_t tlssz, int *ctid) {
|
||||||
int tid;
|
int tid;
|
||||||
intptr_t *sp;
|
struct CloneArgs *wt;
|
||||||
struct __tfork params;
|
struct __tfork params;
|
||||||
sp = (intptr_t *)(stk + stksz);
|
wt = (struct CloneArgs *)(((intptr_t)(stk + stksz) -
|
||||||
*--sp = flags; // 3
|
sizeof(struct CloneArgs)) &
|
||||||
*--sp = (intptr_t)ctid; // 2
|
-alignof(struct CloneArgs));
|
||||||
*--sp = (intptr_t)arg; // 1
|
wt->flags = flags;
|
||||||
*--sp = (intptr_t)func; // 0
|
wt->ctid = ctid;
|
||||||
params.tf_stack = sp;
|
wt->func = func;
|
||||||
|
wt->arg = arg;
|
||||||
|
params.tf_stack = wt;
|
||||||
params.tf_tcb = flags & CLONE_SETTLS ? tls : 0;
|
params.tf_tcb = flags & CLONE_SETTLS ? tls : 0;
|
||||||
params.tf_tid = flags & CLONE_CHILD_SETTID ? ctid : 0;
|
params.tf_tid = flags & CLONE_CHILD_SETTID ? ctid : 0;
|
||||||
if ((tid = __tfork(¶ms, sizeof(params), sp)) < 0) {
|
if ((tid = __tfork(¶ms, sizeof(params), wt)) < 0) {
|
||||||
errno = -tid;
|
errno = -tid;
|
||||||
tid = -1;
|
tid = -1;
|
||||||
}
|
}
|
||||||
return tid;
|
return tid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// NET BESIYATA DISHMAYA
|
||||||
|
|
||||||
static wontreturn void NetbsdThreadMain(void *arg, int (*func)(void *arg),
|
static wontreturn void NetbsdThreadMain(void *arg, int (*func)(void *arg),
|
||||||
int *tid, int *ctid, int flags) {
|
int *tid, int *ctid, int flags) {
|
||||||
int rc;
|
int rc;
|
||||||
if (flags & CLONE_CHILD_SETTID) {
|
if (flags & CLONE_CHILD_SETTID) {
|
||||||
*ctid = *tid;
|
*ctid = *tid;
|
||||||
}
|
}
|
||||||
rc = func(arg);
|
_Exit1(func(arg));
|
||||||
_Exit1(rc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CloneNetbsd(int (*func)(void *), char *stk, size_t stksz, int flags,
|
static int CloneNetbsd(int (*func)(void *), char *stk, size_t stksz, int flags,
|
||||||
|
@ -353,16 +377,21 @@ static int CloneNetbsd(int (*func)(void *), char *stk, size_t stksz, int flags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CloneLinux(int (*func)(void *), char *stk, size_t stksz, int flags,
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void *arg, int *ptid, void *tls, size_t tlssz,
|
// GNU/SYSTEMD
|
||||||
int *ctid) {
|
|
||||||
|
int CloneLinux(int (*func)(void *), char *stk, size_t stksz, int flags,
|
||||||
|
void *arg, int *ptid, void *tls, size_t tlssz, int *ctid) {
|
||||||
|
#ifdef __chibicc__
|
||||||
|
return -1; // TODO
|
||||||
|
#else
|
||||||
int ax;
|
int ax;
|
||||||
register int *r8 asm("r8") = tls;
|
|
||||||
register int *r10 asm("r10") = ctid;
|
|
||||||
register void *r9 asm("r9") = func;
|
|
||||||
intptr_t *stack = (intptr_t *)(stk + stksz);
|
intptr_t *stack = (intptr_t *)(stk + stksz);
|
||||||
*--stack = (intptr_t)arg;
|
*--stack = (intptr_t)arg;
|
||||||
asm volatile("syscall\n\t"
|
asm volatile("mov\t%4,%%r10\n\t" // ctid
|
||||||
|
"mov\t%5,%%r8\n\t" // tls
|
||||||
|
"mov\t%6,%%r9\n\t" // func
|
||||||
|
"syscall\n\t"
|
||||||
"test\t%0,%0\n\t"
|
"test\t%0,%0\n\t"
|
||||||
"jnz\t1f\n\t"
|
"jnz\t1f\n\t"
|
||||||
"xor\t%%ebp,%%ebp\n\t"
|
"xor\t%%ebp,%%ebp\n\t"
|
||||||
|
@ -371,13 +400,17 @@ static int CloneLinux(int (*func)(void *), char *stk, size_t stksz, int flags,
|
||||||
"xchg\t%%eax,%%edi\n\t"
|
"xchg\t%%eax,%%edi\n\t"
|
||||||
"jmp\t_Exit1\n1:"
|
"jmp\t_Exit1\n1:"
|
||||||
: "=a"(ax)
|
: "=a"(ax)
|
||||||
: "0"(__NR_clone_linux), "D"(flags), "S"(stack), "r"(r10),
|
: "0"(__NR_clone_linux), "D"(flags), "S"(stack), "g"(ctid),
|
||||||
"r"(r8), "r"(r9)
|
"g"(tls), "g"(func)
|
||||||
: "rcx", "r11", "memory");
|
: "rcx", "r8", "r9", "r10", "r11", "memory");
|
||||||
if (ax > -4096u) errno = -ax, ax = -1;
|
if (ax > -4096u) errno = -ax, ax = -1;
|
||||||
return ax;
|
return ax;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// COSMOPOLITAN
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates thread.
|
* Creates thread.
|
||||||
*
|
*
|
||||||
|
@ -446,9 +479,13 @@ static int CloneLinux(int (*func)(void *), char *stk, size_t stksz, int flags,
|
||||||
int clone(int (*func)(void *), void *stk, size_t stksz, int flags, void *arg,
|
int clone(int (*func)(void *), void *stk, size_t stksz, int flags, void *arg,
|
||||||
int *ptid, void *tls, size_t tlssz, int *ctid) {
|
int *ptid, void *tls, size_t tlssz, int *ctid) {
|
||||||
int rc;
|
int rc;
|
||||||
|
struct CloneArgs *wt;
|
||||||
|
|
||||||
__threaded = true;
|
if (flags & CLONE_THREAD) {
|
||||||
if (tls && !__tls_enabled) {
|
__threaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & CLONE_SETTLS) && !__tls_enabled) {
|
||||||
__initialize_tls(tibdefault);
|
__initialize_tls(tibdefault);
|
||||||
__install_tls(tibdefault);
|
__install_tls(tibdefault);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,8 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/bits/weaken.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/nexgen32e/threaded.h"
|
||||||
#include "libc/dce.h"
|
|
||||||
#include "libc/intrin/threaded.h"
|
|
||||||
#include "libc/nt/thread.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global variable for last error.
|
* Global variable for last error.
|
||||||
|
@ -36,24 +33,9 @@
|
||||||
*/
|
*/
|
||||||
errno_t __errno;
|
errno_t __errno;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns address of thread information block.
|
|
||||||
* @see __install_tls()
|
|
||||||
* @see clone()
|
|
||||||
*/
|
|
||||||
privileged nocallersavedregisters char *__get_tls(void) {
|
|
||||||
char *tib, *linear = (char *)0x30;
|
|
||||||
if (IsLinux() || IsFreebsd() || IsNetbsd() || IsOpenbsd()) {
|
|
||||||
asm("mov\t%%fs:(%1),%0" : "=a"(tib) : "r"(linear));
|
|
||||||
} else {
|
|
||||||
asm("mov\t%%gs:(%1),%0" : "=a"(tib) : "r"(linear));
|
|
||||||
if (IsWindows()) tib = *(char **)(tib + 0x1480 + __tls_index * 8);
|
|
||||||
}
|
|
||||||
return tib;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns address of errno variable.
|
* Returns address of errno variable.
|
||||||
|
*
|
||||||
* @see __initialize_tls()
|
* @see __initialize_tls()
|
||||||
* @see __install_tls()
|
* @see __install_tls()
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -34,13 +34,15 @@ int cthread_join(cthread_t td, int* rc) {
|
||||||
: "cc");
|
: "cc");
|
||||||
|
|
||||||
if (!(state & cthread_finished)) {
|
if (!(state & cthread_finished)) {
|
||||||
|
int ax;
|
||||||
int flags = FUTEX_WAIT; // PRIVATE makes it hang
|
int flags = FUTEX_WAIT; // PRIVATE makes it hang
|
||||||
register struct timespec* timeout asm("r10") = NULL;
|
struct timespec* timeout = NULL;
|
||||||
asm volatile("syscall"
|
asm volatile("mov\t%5,%%r10\n\t" // timeout
|
||||||
: /* no outputs */
|
"syscall"
|
||||||
: "a"(__NR_futex), "D"(&td->tid), "S"(flags), "d"(tid),
|
: "=a"(ax)
|
||||||
"r"(timeout)
|
: "0"(__NR_futex), "D"(&td->tid), "S"(flags), "d"(tid),
|
||||||
: "rcx", "r11", "cc", "memory");
|
"g"(timeout)
|
||||||
|
: "rcx", "r10", "r11", "cc", "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
*rc = td->rc;
|
*rc = td->rc;
|
||||||
|
|
|
@ -25,12 +25,12 @@ int cthread_memory_wait32(uint32_t* addr, uint32_t val,
|
||||||
if (__NR_futex != 0xfff) {
|
if (__NR_futex != 0xfff) {
|
||||||
int flags = FUTEX_WAIT;
|
int flags = FUTEX_WAIT;
|
||||||
int rc;
|
int rc;
|
||||||
register struct timespec* timeout_ asm("r10") = timeout;
|
asm volatile("mov\t%5,%%r10\n\t" // timeout
|
||||||
asm volatile("syscall"
|
"syscall"
|
||||||
: "=a"(rc)
|
: "=a"(rc)
|
||||||
: "0"(__NR_futex), "D"(addr), "S"(flags), "d"(val),
|
: "0"(__NR_futex), "D"(addr), "S"(flags), "d"(val),
|
||||||
"r"(timeout_)
|
"g"(timeout)
|
||||||
: "rcx", "r11", "cc", "memory");
|
: "rcx", "r10", "r11", "cc", "memory");
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/threaded.h"
|
#include "libc/nexgen32e/threaded.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/spinlock.h"
|
#include "libc/intrin/spinlock.h"
|
||||||
#include "libc/intrin/threaded.h"
|
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
|
#include "libc/nexgen32e/threaded.h"
|
||||||
#include "libc/rand/rand.h"
|
#include "libc/rand/rand.h"
|
||||||
#include "libc/runtime/stack.h"
|
#include "libc/runtime/stack.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
|
|
@ -21,13 +21,15 @@
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/intrin/spinlock.h"
|
#include "libc/intrin/spinlock.h"
|
||||||
#include "libc/intrin/threaded.h"
|
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/nexgen32e/nexgen32e.h"
|
||||||
|
#include "libc/nexgen32e/threaded.h"
|
||||||
#include "libc/runtime/stack.h"
|
#include "libc/runtime/stack.h"
|
||||||
#include "libc/sysv/consts/clone.h"
|
#include "libc/sysv/consts/clone.h"
|
||||||
#include "libc/sysv/consts/map.h"
|
#include "libc/sysv/consts/map.h"
|
||||||
#include "libc/sysv/consts/prot.h"
|
#include "libc/sysv/consts/prot.h"
|
||||||
#include "libc/sysv/consts/sig.h"
|
#include "libc/sysv/consts/sig.h"
|
||||||
|
#include "libc/testlib/ezbench.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
#include "libc/time/time.h"
|
#include "libc/time/time.h"
|
||||||
|
|
||||||
|
@ -48,15 +50,11 @@ void SetUp(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TearDown(void) {
|
void TearDown(void) {
|
||||||
if (thechilde) {
|
|
||||||
tkill(thechilde, SIGKILL);
|
|
||||||
errno = 0;
|
|
||||||
}
|
|
||||||
sched_yield();
|
|
||||||
free(tls);
|
free(tls);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CloneTest1(void *arg) {
|
int CloneTest1(void *arg) {
|
||||||
|
_checkstackalign();
|
||||||
x = 42;
|
x = 42;
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
ASSERT_EQ(31337, errno);
|
ASSERT_EQ(31337, errno);
|
||||||
|
@ -72,6 +70,7 @@ int CloneTest1(void *arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int DoNothing(void *arg) {
|
int DoNothing(void *arg) {
|
||||||
|
_checkstackalign();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +91,7 @@ TEST(clone, test1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int CloneTestSys(void *arg) {
|
int CloneTestSys(void *arg) {
|
||||||
|
_checkstackalign();
|
||||||
thechilde = gettid();
|
thechilde = gettid();
|
||||||
ASSERT_EQ(31337, errno);
|
ASSERT_EQ(31337, errno);
|
||||||
open(0, 0);
|
open(0, 0);
|
||||||
|
@ -112,3 +112,10 @@ TEST(clone, tlsSystemCallsErrno_wontClobberMainThreadBecauseTls) {
|
||||||
ASSERT_EQ(0, errno);
|
ASSERT_EQ(0, errno);
|
||||||
ASSERT_EQ(EFAULT, *(int *)(tls + 0x3c));
|
ASSERT_EQ(EFAULT, *(int *)(tls + 0x3c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BENCH(clone, bench) {
|
||||||
|
errno_t *volatile ep;
|
||||||
|
char *volatile tp;
|
||||||
|
EZBENCH2("__errno_location", donothing, (ep = (__errno_location())));
|
||||||
|
EZBENCH2("__get_tls", donothing, (tp = __get_tls()));
|
||||||
|
}
|
||||||
|
|
1
third_party/chibicc/parse.c
vendored
1
third_party/chibicc/parse.c
vendored
|
@ -559,6 +559,7 @@ static Token *thing_attributes(Token *tok, void *arg) {
|
||||||
consume_attribute(&tok, tok, "warn_unused_result") ||
|
consume_attribute(&tok, tok, "warn_unused_result") ||
|
||||||
consume_attribute(&tok, tok, "flatten") ||
|
consume_attribute(&tok, tok, "flatten") ||
|
||||||
consume_attribute(&tok, tok, "leaf") ||
|
consume_attribute(&tok, tok, "leaf") ||
|
||||||
|
consume_attribute(&tok, tok, "no_reorder") ||
|
||||||
consume_attribute(&tok, tok, "dontthrow") ||
|
consume_attribute(&tok, tok, "dontthrow") ||
|
||||||
consume_attribute(&tok, tok, "optnone") ||
|
consume_attribute(&tok, tok, "optnone") ||
|
||||||
consume_attribute(&tok, tok, "returns_twice") ||
|
consume_attribute(&tok, tok, "returns_twice") ||
|
||||||
|
|
8
third_party/chibicc/preprocess.c
vendored
8
third_party/chibicc/preprocess.c
vendored
|
@ -1174,6 +1174,14 @@ __INT_FAST32_TYPE__\000\
|
||||||
int\000\
|
int\000\
|
||||||
__UINT_FAST32_TYPE__\000\
|
__UINT_FAST32_TYPE__\000\
|
||||||
unsigned\000\
|
unsigned\000\
|
||||||
|
__INT_FAST8_MAX__\000\
|
||||||
|
0x7f\000\
|
||||||
|
__INT_FAST16_MAX__\000\
|
||||||
|
0x7fffffff\000\
|
||||||
|
__INT_FAST32_MAX__\000\
|
||||||
|
0x7fffffff\000\
|
||||||
|
__INT_FAST64_MAX__\000\
|
||||||
|
0x7fffffffffffffffl\000\
|
||||||
__INT_FAST64_TYPE__\000\
|
__INT_FAST64_TYPE__\000\
|
||||||
long\000\
|
long\000\
|
||||||
__UINT_FAST64_TYPE__\000\
|
__UINT_FAST64_TYPE__\000\
|
||||||
|
|
4
third_party/chibicc/type.c
vendored
4
third_party/chibicc/type.c
vendored
|
@ -1,3 +1,4 @@
|
||||||
|
#include "libc/assert.h"
|
||||||
#include "third_party/chibicc/chibicc.h"
|
#include "third_party/chibicc/chibicc.h"
|
||||||
|
|
||||||
/* TODO(jart): Why can't these be const? */
|
/* TODO(jart): Why can't these be const? */
|
||||||
|
@ -144,6 +145,9 @@ static Type *get_common_type(Type *ty1, Type *ty2) {
|
||||||
//
|
//
|
||||||
// This operation is called the "usual arithmetic conversion".
|
// This operation is called the "usual arithmetic conversion".
|
||||||
static void usual_arith_conv(Node **lhs, Node **rhs) {
|
static void usual_arith_conv(Node **lhs, Node **rhs) {
|
||||||
|
if (!(*lhs)->ty || !(*rhs)->ty) {
|
||||||
|
error_tok((*lhs)->tok, "internal npe error");
|
||||||
|
}
|
||||||
Type *ty = get_common_type((*lhs)->ty, (*rhs)->ty);
|
Type *ty = get_common_type((*lhs)->ty, (*rhs)->ty);
|
||||||
*lhs = new_cast(*lhs, ty);
|
*lhs = new_cast(*lhs, ty);
|
||||||
*rhs = new_cast(*rhs, ty);
|
*rhs = new_cast(*rhs, ty);
|
||||||
|
|
Loading…
Add table
Reference in a new issue