diff --git a/Makefile b/Makefile index 63bce3f8f..46e0b69d9 100644 --- a/Makefile +++ b/Makefile @@ -524,6 +524,7 @@ COSMOCC_PKGS = \ THIRD_PARTY_AARCH64 \ THIRD_PARTY_LIBCXX \ THIRD_PARTY_LIBCXXABI \ + THIRD_PARTY_LIBUNWIND \ THIRD_PARTY_OPENMP \ THIRD_PARTY_INTEL diff --git a/libc/BUILD.mk b/libc/BUILD.mk index b7eb93f49..2ce70f1a9 100644 --- a/libc/BUILD.mk +++ b/libc/BUILD.mk @@ -251,6 +251,7 @@ libc/isystem/uio.h \ libc/isystem/unistd.h \ libc/isystem/unordered_map \ libc/isystem/unordered_set \ +libc/isystem/unwind.h \ libc/isystem/utility \ libc/isystem/utime.h \ libc/isystem/utmp.h \ diff --git a/libc/calls/isqemu.c b/libc/calls/isqemu.c index 02ccc7022..4746128cd 100644 --- a/libc/calls/isqemu.c +++ b/libc/calls/isqemu.c @@ -24,11 +24,15 @@ /** * Returns true if process is running under qemu-x86_64 or qemu-aarch64. */ -int IsQemu(void) { - // qemu doesn't validate the advice argument - // we could also check if __getcwd(0, 0) raises efault - int e = errno; - int r = !sys_madvise(__executable_start, 16384, 127); - errno = e; - return r; +int IsQemuUser(void) { + static char rplus1; + if (!rplus1) { + // qemu doesn't validate the advice argument + // we could also check if __getcwd(0, 0) raises efault + int e = errno; + int r = !sys_madvise(__executable_start, 16384, 127); + errno = e; + rplus1 = r + 1; + } + return rplus1 - 1; } diff --git a/libc/dce.h b/libc/dce.h index 9ce486947..5b9f7e0fb 100644 --- a/libc/dce.h +++ b/libc/dce.h @@ -121,7 +121,7 @@ COSMOPOLITAN_C_START_ extern const int __hostos; -int IsQemu(void); +int IsQemuUser(void); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/integral/c.inc b/libc/integral/c.inc index c1f86f5ae..11f6a781d 100644 --- a/libc/integral/c.inc +++ b/libc/integral/c.inc @@ -649,8 +649,9 @@ void abort(void) wontreturn; #pragma GCC diagnostic ignored "-Wformat-extra-args" /* todo: patch gcc */ #pragma GCC diagnostic ignored "-Wunused-function" /* contradicts dce */ #pragma GCC diagnostic ignored "-Wunused-const-variable" /* sooo ridiculous */ +#pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch" #ifndef __cplusplus -#pragma GCC diagnostic ignored "-Wold-style-definition" /* orwellian bulls */ +#pragma GCC diagnostic ignored "-Wold-style-definition" /* orwellian bullsh */ #endif #ifndef __STRICT_ANSI__ diff --git a/libc/intrin/getmainstack.c b/libc/intrin/getmainstack.c index c1d3db94d..1a51d5f36 100644 --- a/libc/intrin/getmainstack.c +++ b/libc/intrin/getmainstack.c @@ -103,7 +103,7 @@ void __get_main_stack(void **out_addr, size_t *out_size, int *out_guardsize) { if (IsWindows()) { *out_addr = (void *)GetStaticStackAddr(0); *out_size = GetStaticStackSize(); - *out_guardsize = GetGuardSize(); + *out_guardsize = getauxval(AT_PAGESZ); return; } int pagesz = getauxval(AT_PAGESZ); diff --git a/libc/isystem/unwind.h b/libc/isystem/unwind.h new file mode 100644 index 000000000..8af15d0b5 --- /dev/null +++ b/libc/isystem/unwind.h @@ -0,0 +1,4 @@ +#ifndef _UNWIND_H +#define _UNWIND_H +#include "third_party/libunwind/include/unwind.h" +#endif /* _UNWIND_H */ diff --git a/libc/nexgen32e/kcpuids.S b/libc/nexgen32e/kcpuids.S index 6046bb0ab..0c5fdea05 100644 --- a/libc/nexgen32e/kcpuids.S +++ b/libc/nexgen32e/kcpuids.S @@ -31,28 +31,38 @@ // are quite toilsome. // // @see www.felixcloutier.com/x86/cpuid -kCpuids:.long 0,0,0,0 # EAX=0 (Basic Processor Info) - .long 0,0,0,0 # EAX=1 (Processor Info) - .long 0,0,0,0 # EAX=2 - .long 0,0,0,0 # EAX=7 (Extended Features) - .long 0,0,0,0 # EAX=0x80000001 (NexGen32e) - .long 0,0,0,0 # EAX=0x80000007 (APM) - .long 0,0,0,0 # EAX=16h (CPU Frequency) +kCpuids:.long 0,0,0,0 // EAX=0 (Basic Processor Info) + .long 0,0,0,0 // EAX=1 (Processor Info) + .long 0,0,0,0 // EAX=2 + .long 0,0,0,0 // EAX=7 (Extended Features) + .long 0,0,0,0 // EAX=0x80000001 (NexGen32e) + .long 0,0,0,0 // EAX=0x80000007 (APM) + .long 0,0,0,0 // EAX=16h (CPU Frequency) + .long 0,0,0,0 // EAX=7 ECX=1 (Extended Feats) .endobj kCpuids,globl .previous .init.start 201,_init_kCpuids push %rbx push $0 - push $0x16 - push $0xffffffff80000007 - push $0xffffffff80000001 + push $1 push $7 + push $0 + push $0x16 + push $0 + push $0xffffffff80000007 + push $0 + push $0xffffffff80000001 + push $0 + push $7 + push $0 push $2 + push $0 push $1 mov %rdi,%r8 xor %eax,%eax -1: xor %ecx,%ecx + xor %ecx,%ecx +1: nop #ifdef FEATURELESS // It's been reported that GDB reverse debugging doesn't // understand VEX encoding. The workaround is to put: @@ -62,6 +72,7 @@ kCpuids:.long 0,0,0,0 # EAX=0 (Basic Processor Info) // Inside your ~/.cosmo.mk file. xor %eax,%eax xor %ebx,%ebx + xor %ecx,%ecx xor %edx,%edx #else cpuid @@ -74,10 +85,11 @@ kCpuids:.long 0,0,0,0 # EAX=0 (Basic Processor Info) xchg %eax,%edx stosl 2: pop %rax - test %eax,%eax # EAX = stacklist->pop() - jz 3f # EAX ≠ 0 (EOL sentinel) - cmp KCPUIDS(0H,EAX)(%r8),%al # EAX ≤ CPUID.0 max leaf - jbe 1b # CPUID too new to probe + test %eax,%eax // EAX = stacklist->pop() + jz 3f // EAX ≠ 0 (EOL sentinel) + pop %rcx // HERE WE GO AGAIN CPUID + cmp KCPUIDS(0H,EAX)(%r8),%al // EAX ≤ CPUID.0 max leaf + jbe 1b // CPUID too new to probe add $4*4,%rdi jmp 2b 3: nop diff --git a/libc/nexgen32e/kcpuids.h b/libc/nexgen32e/kcpuids.h index 1c0f9def8..d40c9010d 100644 --- a/libc/nexgen32e/kcpuids.h +++ b/libc/nexgen32e/kcpuids.h @@ -8,7 +8,8 @@ #define KCPUIDS_80000001H 4 #define KCPUIDS_80000007H 5 #define KCPUIDS_16H 6 -#define KCPUIDS_LEN 7 +#define KCPUIDS_7H_1H 7 +#define KCPUIDS_LEN 8 #define KCPUIDS_6H -1 /* TBD: Thermal and Power Management */ #define KCPUIDS_DH -1 /* TBD: Extended state features */ #define KCPUIDS_80000008H -1 /* TBD: AMD Miscellaneous */ diff --git a/libc/nexgen32e/x86compiler.h b/libc/nexgen32e/x86compiler.h index b1c6d9f63..1c63cf62b 100644 --- a/libc/nexgen32e/x86compiler.h +++ b/libc/nexgen32e/x86compiler.h @@ -37,6 +37,18 @@ #define _X86_CC_AVXVNNI 0 #endif +#ifdef __AVXVNNIINT8__ +#define _X86_CC_AVXVNNIINT8 1 +#else +#define _X86_CC_AVXVNNIINT8 0 +#endif + +#ifdef __AVXVNNIINT16__ +#define _X86_CC_AVXVNNIINT16 1 +#else +#define _X86_CC_AVXVNNIINT16 0 +#endif + #ifdef __AVX512F__ #define _X86_CC_AVX512F 1 #else diff --git a/libc/nexgen32e/x86feature.h b/libc/nexgen32e/x86feature.h index c7b30ba54..c9cc4a39c 100644 --- a/libc/nexgen32e/x86feature.h +++ b/libc/nexgen32e/x86feature.h @@ -28,7 +28,9 @@ #define X86_ARCH_CAPABILITIES 7H, EDX, 29, 0 #define X86_AVX 1H, ECX, 28, _X86_CC_AVX /* sandybridge c. 2012 */ #define X86_AVX2 7H, EBX, 5, _X86_CC_AVX2 /* haswell c. 2013 */ -#define X86_AVXVNNI 7H, EAX, 4, _X86_CC_AVXVNNI +#define X86_AVXVNNI 7H_1H, EAX, 4, _X86_CC_AVXVNNI +#define X86_AVXVNNIINT8 7H_1H, EDX, 4, _X86_CC_AVXVNNIINT8 +#define X86_AVXVNNIINT16 7H_1H, EDX, 10, _X86_CC_AVXVNNIINT16 #define X86_AVX512BW 7H, EBX, 30, 0 #define X86_AVX512CD 7H, EBX, 28, 0 #define X86_AVX512DQ 7H, EBX, 17, 0 diff --git a/libc/runtime/mapstack.c b/libc/runtime/mapstack.c index 409e7961d..1b3fc3ada 100644 --- a/libc/runtime/mapstack.c +++ b/libc/runtime/mapstack.c @@ -23,6 +23,7 @@ #include "libc/runtime/memtrack.internal.h" #include "libc/runtime/runtime.h" #include "libc/runtime/stack.h" +#include "libc/sysv/consts/auxv.h" #include "libc/sysv/consts/map.h" #include "libc/sysv/consts/prot.h" @@ -42,10 +43,13 @@ void *NewCosmoStack(void) { char *p; if ((p = mmap(0, GetStackSize(), PROT_READ | PROT_WRITE, - MAP_STACK | MAP_ANONYMOUS, -1, 0)) != MAP_FAILED) { + MAP_ANONYMOUS | + (IsAarch64() && IsLinux() && IsQemuUser() ? MAP_PRIVATE + : MAP_STACK), + -1, 0)) != MAP_FAILED) { if (IsAsan()) { __asan_poison(p + GetStackSize() - 16, 16, kAsanStackOverflow); - __asan_poison(p, GetGuardSize(), kAsanStackOverflow); + __asan_poison(p, getauxval(AT_PAGESZ), kAsanStackOverflow); } return p; } else { diff --git a/libc/sock/in6addr_any.c b/libc/sock/in6addr_any.c new file mode 100644 index 000000000..eba834cb2 --- /dev/null +++ b/libc/sock/in6addr_any.c @@ -0,0 +1,22 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2024 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/sock/struct/sockaddr6.h" +#include "libc/sysv/consts/inaddr.h" + +const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; diff --git a/libc/sock/in6addr_loopback.c b/libc/sock/in6addr_loopback.c new file mode 100644 index 000000000..6ee3e4d54 --- /dev/null +++ b/libc/sock/in6addr_loopback.c @@ -0,0 +1,22 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2024 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/sock/struct/sockaddr6.h" +#include "libc/sysv/consts/inaddr.h" + +const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; diff --git a/libc/sock/struct/sockaddr6.h b/libc/sock/struct/sockaddr6.h index d10ce8855..6f949915c 100644 --- a/libc/sock/struct/sockaddr6.h +++ b/libc/sock/struct/sockaddr6.h @@ -17,4 +17,7 @@ struct sockaddr_in6 { /* Linux+NT ABI */ uint32_t sin6_scope_id; /* rfc2553 */ }; +extern const struct in6_addr in6addr_any; +extern const struct in6_addr in6addr_loopback; + #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SOCKADDR6_H_ */ diff --git a/libc/thread/pthread_attr_init.c b/libc/thread/pthread_attr_init.c index 7e13c9fa5..9db001b24 100644 --- a/libc/thread/pthread_attr_init.c +++ b/libc/thread/pthread_attr_init.c @@ -38,7 +38,7 @@ errno_t pthread_attr_init(pthread_attr_t *attr) { *attr = (pthread_attr_t){ .__stacksize = GetStackSize(), - .__guardsize = GetGuardSize(), + .__guardsize = getauxval(AT_PAGESZ), }; return 0; } diff --git a/libc/thread/pthread_create.c b/libc/thread/pthread_create.c index f86b2090f..d259e8923 100644 --- a/libc/thread/pthread_create.c +++ b/libc/thread/pthread_create.c @@ -216,7 +216,9 @@ static errno_t pthread_create_impl(pthread_t *thread, _pthread_free(pt, false); return EINVAL; } - if (pt->pt_attr.__guardsize == pagesize) { + if (pt->pt_attr.__guardsize == pagesize && + !(IsAarch64() && IsLinux() && IsQemuUser())) { + // MAP_GROWSDOWN doesn't work very well on qemu-aarch64 pt->pt_attr.__stackaddr = mmap(0, pt->pt_attr.__stacksize, PROT_READ | PROT_WRITE, MAP_STACK | MAP_ANONYMOUS, -1, 0); diff --git a/test/libc/calls/getcwd_test.c b/test/libc/calls/getcwd_test.c index 875aaea1d..0c5a4194d 100644 --- a/test/libc/calls/getcwd_test.c +++ b/test/libc/calls/getcwd_test.c @@ -33,7 +33,7 @@ void SetUpOnce(void) { } TEST(__getcwd, zero) { - if (IsQemu()) return; + if (IsQemuUser()) return; ASSERT_SYS(ERANGE, -1, __getcwd(0, 0)); } diff --git a/test/libc/calls/getprogramexecutablename_test.c b/test/libc/calls/getprogramexecutablename_test.c index 7d3cd73b8..efe28fb5b 100644 --- a/test/libc/calls/getprogramexecutablename_test.c +++ b/test/libc/calls/getprogramexecutablename_test.c @@ -122,7 +122,7 @@ TEST(GetProramExecutableName, weirdArgv0NullEnv) { TEST(GetProgramExecutableName, movedSelf) { if (skiptests) return; - if (IsAarch64() && IsQemu()) { + if (IsAarch64() && IsQemuUser()) { // clang-format off // TODO(mrdomino): fix: make -j8 m=aarch64 o/aarch64/test/libc/calls/getprogramexecutablename_test.com.ok // possibly related to the intersection of binfmt_misc and qemu-aarch64 diff --git a/test/libc/calls/madvise_test.c b/test/libc/calls/madvise_test.c index 45947b6e5..a5de04344 100644 --- a/test/libc/calls/madvise_test.c +++ b/test/libc/calls/madvise_test.c @@ -69,8 +69,8 @@ TEST(madvise, subPages) { TEST(madvise, misalign) { char *p; - if (!IsLinux()) return; // most platforms don't care - if (IsQemu()) return; // qemu claims to be linux but doesn't care + if (!IsLinux()) return; // most platforms don't care + if (IsQemuUser()) return; // qemu claims to be linux but doesn't care ASSERT_NE(MAP_FAILED, (p = mmap(0, FRAMESIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0))); ASSERT_SYS(EINVAL, -1, madvise(p + 1, FRAMESIZE - 1, MADV_WILLNEED)); @@ -79,7 +79,7 @@ TEST(madvise, misalign) { TEST(madvise, badAdvice) { char *p; - if (IsAarch64() && IsQemu()) return; // qemu doesn't validate advice + if (IsAarch64() && IsQemuUser()) return; // qemu doesn't validate advice ASSERT_NE(MAP_FAILED, (p = mmap(0, FRAMESIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0))); ASSERT_SYS(EINVAL, -1, madvise(p, FRAMESIZE, 127)); @@ -87,8 +87,8 @@ TEST(madvise, badAdvice) { } TEST(madvise, missingMemory) { - if (!IsLinux()) return; // most platforms don't care - if (IsQemu()) return; // qemu claims to be linux but doesn't care + if (!IsLinux()) return; // most platforms don't care + if (IsQemuUser()) return; // qemu claims to be linux but doesn't care ASSERT_SYS(ENOMEM, -1, madvise((char *)0x83483838000, FRAMESIZE, MADV_WILLNEED)); } diff --git a/test/libc/calls/stackoverflow3_test.c b/test/libc/calls/stackoverflow3_test.c index 10cc75784..d7cfe2870 100644 --- a/test/libc/calls/stackoverflow3_test.c +++ b/test/libc/calls/stackoverflow3_test.c @@ -21,6 +21,7 @@ #include "libc/calls/struct/siginfo.h" #include "libc/calls/struct/ucontext.internal.h" #include "libc/calls/ucontext.h" +#include "libc/dce.h" #include "libc/intrin/kprintf.h" #include "libc/limits.h" #include "libc/mem/gc.h" diff --git a/test/libc/calls/writev_test.c b/test/libc/calls/writev_test.c index 53b64499c..c045cd7ec 100644 --- a/test/libc/calls/writev_test.c +++ b/test/libc/calls/writev_test.c @@ -23,7 +23,6 @@ #include "libc/limits.h" #include "libc/macros.internal.h" #include "libc/mem/gc.h" -#include "libc/mem/gc.h" #include "libc/mem/mem.h" #include "libc/runtime/runtime.h" #include "libc/sock/sock.h" @@ -126,7 +125,7 @@ TEST(writev, empty_stillPerformsIoOperation) { ASSERT_NE(-1, (fd = open("file", O_RDONLY))); errno = 0; EXPECT_SYS(EBADF, -1, writev(fd, iov, ARRAYLEN(iov))); - if (!(IsAarch64() && IsQemu())) { + if (!(IsAarch64() && IsQemuUser())) { EXPECT_EQ(-1, writev(fd, NULL, 0)); } EXPECT_NE(-1, close(fd)); diff --git a/test/libc/thread/makecontext_test.c b/test/libc/thread/makecontext_test.c index 9b6171029..93bdee907 100644 --- a/test/libc/thread/makecontext_test.c +++ b/test/libc/thread/makecontext_test.c @@ -19,6 +19,7 @@ #include "libc/calls/calls.h" #include "libc/calls/ucontext.h" #include "libc/dce.h" +#include "libc/intrin/kprintf.h" #include "libc/limits.h" #include "libc/mem/gc.h" #include "libc/nt/createfile.h" diff --git a/test/libcxx/BUILD.mk b/test/libcxx/BUILD.mk index 348b4c3b1..c646ddd56 100644 --- a/test/libcxx/BUILD.mk +++ b/test/libcxx/BUILD.mk @@ -18,7 +18,6 @@ TEST_LIBCXX_DIRECTDEPS = \ LIBC_RUNTIME \ LIBC_STDIO \ THIRD_PARTY_LIBCXX \ - THIRD_PARTY_DOUBLECONVERSION \ THIRD_PARTY_OPENMP TEST_LIBCXX_DEPS := \ diff --git a/test/libcxx/openmp_test.cc b/test/libcxx/openmp_test.cc index ab9c8bf37..ecf5ef3c2 100644 --- a/test/libcxx/openmp_test.cc +++ b/test/libcxx/openmp_test.cc @@ -68,7 +68,7 @@ void matmul(long m, long n, long k, const T *A, long sa, const T *B, long sb, } template -void sgemmk(long k, const T *A, long sa, const T *B, long sb, T *C, long sc) { +void gemmk(long k, const T *A, long sa, const T *B, long sb, T *C, long sc) { T S[BM][BN] = {0}; for (long l = 0; l < k; ++l) { for (long i = 0; i < BM; ++i) { @@ -86,12 +86,12 @@ void sgemmk(long k, const T *A, long sa, const T *B, long sb, T *C, long sc) { // (m×k)ᵀ * k×n → m×n template -void sgemm(long m, long n, long k, const T *A, long sa, const T *B, long sb, - T *C, long sc) { +void gemm(long m, long n, long k, const T *A, long sa, const T *B, long sb, + T *C, long sc) { #pragma omp parallel for collapse(2) for (long i = 0; i < m; i += BM) { for (long j = 0; j < n; j += BN) { - sgemmk(k, A + i, sa, B + j, sb, C + sc * i + j, sc); + gemmk(k, A + i, sa, B + j, sb, C + sc * i + j, sc); } } } @@ -221,7 +221,7 @@ void check_transposed_blocking_gemm_is_ok(void) { bench(matmul(m, n, k, A, k, B, n, C, n)); float *At = new float[k * m]; bench(transpose(m, k, A, k, At, m)); - bench((sgemm<8, 4>(m, n, k, At, m, B, n, D, n))); + bench((gemm<8, 4>(m, n, k, At, m, B, n, D, n))); check(FLAWLESS, m, n, C, n, D, n); delete[] At; delete[] D; diff --git a/third_party/libunwind/BUILD.mk b/third_party/libunwind/BUILD.mk index cc2274eb5..6f006bd2e 100644 --- a/third_party/libunwind/BUILD.mk +++ b/third_party/libunwind/BUILD.mk @@ -37,7 +37,8 @@ THIRD_PARTY_LIBUNWIND_A_SRCS_CC = \ THIRD_PARTY_LIBUNWIND_A_SRCS_C = \ third_party/libunwind/Unwind-sjlj.c \ third_party/libunwind/UnwindLevel1-gcc-ext.c \ - third_party/libunwind/UnwindLevel1.c + third_party/libunwind/UnwindLevel1.c \ + third_party/libunwind/gcc_personality_v0.c THIRD_PARTY_LIBUNWIND_A_SRCS = \ $(THIRD_PARTY_LIBUNWIND_A_SRCS_C) \ @@ -70,6 +71,7 @@ $(THIRD_PARTY_LIBUNWIND_A).pkg: \ $(THIRD_PARTY_LIBUNWIND_A_OBJS): private \ CFLAGS += \ + -fexceptions \ -fno-sanitize=all \ -ffunction-sections \ -fdata-sections \ @@ -77,6 +79,7 @@ $(THIRD_PARTY_LIBUNWIND_A_OBJS): private \ $(THIRD_PARTY_LIBUNWIND_A_OBJS): private \ CXXFLAGS += \ + -fexceptions \ -fno-sanitize=all \ -ffunction-sections \ -fdata-sections \ diff --git a/third_party/libunwind/gcc_personality_v0.c b/third_party/libunwind/gcc_personality_v0.c new file mode 100644 index 000000000..19cf404ca --- /dev/null +++ b/third_party/libunwind/gcc_personality_v0.c @@ -0,0 +1,236 @@ +//===-- gcc_personality_v0.c - Implement __gcc_personality_v0 -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "third_party/libunwind/include/unwind.h" +#include "third_party/compiler_rt/int_lib.h" + +// Pointer encodings documented at: +// http://refspecs.freestandards.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html + +#define DW_EH_PE_omit 0xff // no data follows + +#define DW_EH_PE_absptr 0x00 +#define DW_EH_PE_uleb128 0x01 +#define DW_EH_PE_udata2 0x02 +#define DW_EH_PE_udata4 0x03 +#define DW_EH_PE_udata8 0x04 +#define DW_EH_PE_sleb128 0x09 +#define DW_EH_PE_sdata2 0x0A +#define DW_EH_PE_sdata4 0x0B +#define DW_EH_PE_sdata8 0x0C + +#define DW_EH_PE_pcrel 0x10 +#define DW_EH_PE_textrel 0x20 +#define DW_EH_PE_datarel 0x30 +#define DW_EH_PE_funcrel 0x40 +#define DW_EH_PE_aligned 0x50 +#define DW_EH_PE_indirect 0x80 // gcc extension + +// read a uleb128 encoded value and advance pointer +static size_t readULEB128(const uint8_t **data) { + size_t result = 0; + size_t shift = 0; + unsigned char byte; + const uint8_t *p = *data; + do { + byte = *p++; + result |= (byte & 0x7f) << shift; + shift += 7; + } while (byte & 0x80); + *data = p; + return result; +} + +// read a pointer encoded value and advance pointer +static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) { + const uint8_t *p = *data; + uintptr_t result = 0; + + if (encoding == DW_EH_PE_omit) + return 0; + + // first get value + switch (encoding & 0x0F) { + case DW_EH_PE_absptr: + result = *((const uintptr_t *)p); + p += sizeof(uintptr_t); + break; + case DW_EH_PE_uleb128: + result = readULEB128(&p); + break; + case DW_EH_PE_udata2: + result = *((const uint16_t *)p); + p += sizeof(uint16_t); + break; + case DW_EH_PE_udata4: + result = *((const uint32_t *)p); + p += sizeof(uint32_t); + break; + case DW_EH_PE_udata8: + result = *((const uint64_t *)p); + p += sizeof(uint64_t); + break; + case DW_EH_PE_sdata2: + result = *((const int16_t *)p); + p += sizeof(int16_t); + break; + case DW_EH_PE_sdata4: + result = *((const int32_t *)p); + p += sizeof(int32_t); + break; + case DW_EH_PE_sdata8: + result = *((const int64_t *)p); + p += sizeof(int64_t); + break; + case DW_EH_PE_sleb128: + default: + // not supported + compilerrt_abort(); + break; + } + + // then add relative offset + switch (encoding & 0x70) { + case DW_EH_PE_absptr: + // do nothing + break; + case DW_EH_PE_pcrel: + result += (uintptr_t)(*data); + break; + case DW_EH_PE_textrel: + case DW_EH_PE_datarel: + case DW_EH_PE_funcrel: + case DW_EH_PE_aligned: + default: + // not supported + compilerrt_abort(); + break; + } + + // then apply indirection + if (encoding & DW_EH_PE_indirect) { + result = *((const uintptr_t *)result); + } + + *data = p; + return result; +} + +#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ + !defined(__ARM_DWARF_EH__) && !defined(__SEH__) +#define USING_ARM_EHABI 1 +_Unwind_Reason_Code __gnu_unwind_frame(struct _Unwind_Exception *, + struct _Unwind_Context *); +#endif + +static inline _Unwind_Reason_Code +continueUnwind(struct _Unwind_Exception *exceptionObject, + struct _Unwind_Context *context) { +#if USING_ARM_EHABI + // On ARM EHABI the personality routine is responsible for actually + // unwinding a single stack frame before returning (ARM EHABI Sec. 6.1). + if (__gnu_unwind_frame(exceptionObject, context) != _URC_OK) + return _URC_FAILURE; +#endif + return _URC_CONTINUE_UNWIND; +} + +// The C compiler makes references to __gcc_personality_v0 in +// the dwarf unwind information for translation units that use +// __attribute__((cleanup(xx))) on local variables. +// This personality routine is called by the system unwinder +// on each frame as the stack is unwound during a C++ exception +// throw through a C function compiled with -fexceptions. +#if __USING_SJLJ_EXCEPTIONS__ +// the setjump-longjump based exceptions personality routine has a +// different name +COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_sj0( + int version, _Unwind_Action actions, uint64_t exceptionClass, + struct _Unwind_Exception *exceptionObject, struct _Unwind_Context *context) +#elif USING_ARM_EHABI +// The ARM EHABI personality routine has a different signature. +COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( + _Unwind_State state, struct _Unwind_Exception *exceptionObject, + struct _Unwind_Context *context) +#elif defined(__SEH__) +static _Unwind_Reason_Code __gcc_personality_imp( + int version, _Unwind_Action actions, uint64_t exceptionClass, + struct _Unwind_Exception *exceptionObject, struct _Unwind_Context *context) +#else +COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( + int version, _Unwind_Action actions, uint64_t exceptionClass, + struct _Unwind_Exception *exceptionObject, struct _Unwind_Context *context) +#endif +{ + // Since C does not have catch clauses, there is nothing to do during + // phase 1 (the search phase). +#if USING_ARM_EHABI + // After resuming from a cleanup we should also continue on to the next + // frame straight away. + if ((state & _US_ACTION_MASK) != _US_UNWIND_FRAME_STARTING) +#else + if (actions & _UA_SEARCH_PHASE) +#endif + return continueUnwind(exceptionObject, context); + + // There is nothing to do if there is no LSDA for this frame. + const uint8_t *lsda = (uint8_t *)_Unwind_GetLanguageSpecificData(context); + if (lsda == (uint8_t *)0) + return continueUnwind(exceptionObject, context); + + uintptr_t pc = (uintptr_t)_Unwind_GetIP(context) - 1; + uintptr_t funcStart = (uintptr_t)_Unwind_GetRegionStart(context); + uintptr_t pcOffset = pc - funcStart; + + // Parse LSDA header. + uint8_t lpStartEncoding = *lsda++; + if (lpStartEncoding != DW_EH_PE_omit) { + readEncodedPointer(&lsda, lpStartEncoding); + } + uint8_t ttypeEncoding = *lsda++; + if (ttypeEncoding != DW_EH_PE_omit) { + readULEB128(&lsda); + } + // Walk call-site table looking for range that includes current PC. + uint8_t callSiteEncoding = *lsda++; + size_t callSiteTableLength = readULEB128(&lsda); + const uint8_t *callSiteTableStart = lsda; + const uint8_t *callSiteTableEnd = callSiteTableStart + callSiteTableLength; + const uint8_t *p = callSiteTableStart; + while (p < callSiteTableEnd) { + uintptr_t start = readEncodedPointer(&p, callSiteEncoding); + size_t length = readEncodedPointer(&p, callSiteEncoding); + size_t landingPad = readEncodedPointer(&p, callSiteEncoding); + readULEB128(&p); // action value not used for C code + if (landingPad == 0) + continue; // no landing pad for this entry + if ((start <= pcOffset) && (pcOffset < (start + length))) { + // Found landing pad for the PC. + // Set Instruction Pointer to so we re-enter function + // at landing pad. The landing pad is created by the compiler + // to take two parameters in registers. + _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), + (uintptr_t)exceptionObject); + _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0); + _Unwind_SetIP(context, (funcStart + landingPad)); + return _URC_INSTALL_CONTEXT; + } + } + + // No landing pad found, continue unwinding. + return continueUnwind(exceptionObject, context); +} + +#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) +COMPILER_RT_ABI EXCEPTION_DISPOSITION +__gcc_personality_seh0(PEXCEPTION_RECORD ms_exc, void *this_frame, + PCONTEXT ms_orig_context, PDISPATCHER_CONTEXT ms_disp) { + return _GCC_specific_handler(ms_exc, this_frame, ms_orig_context, ms_disp, + __gcc_personality_imp); +} +#endif diff --git a/third_party/musl/netdb.h b/third_party/musl/netdb.h index 0aef37604..d3c660982 100644 --- a/third_party/musl/netdb.h +++ b/third_party/musl/netdb.h @@ -99,6 +99,9 @@ struct protoent *getprotoent (void); struct protoent *getprotobyname (const char *); struct protoent *getprotobynumber (int); +#define NI_MAXHOST 255 +#define NI_MAXSERV 32 + #if defined(_COSMO_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_POSIX_SOURCE) \ || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE+0 < 200809L) \ || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700) @@ -130,8 +133,6 @@ int getservbyname_r(const char *, const char *, struct servent *, char *, size_t #define EAI_ALLDONE -103 #define EAI_INTR -104 #define EAI_IDN_ENCODE -105 -#define NI_MAXHOST 255 -#define NI_MAXSERV 32 #endif COSMOPOLITAN_C_END_ diff --git a/third_party/openmp/README.cosmo b/third_party/openmp/README.cosmo index 87543d2c9..9a2268a27 100644 --- a/third_party/openmp/README.cosmo +++ b/third_party/openmp/README.cosmo @@ -14,3 +14,4 @@ LOCAL CHANGES - Ran third_party/openmp/generate.sh - Removed usage of syscall() function - Turned off quad floating point support (why does openmp have it?) + - Remove bloat for checking if multiple OpenMP libraries are linked diff --git a/third_party/openmp/kmp_config.h b/third_party/openmp/kmp_config.h index feb27a500..102aacff8 100644 --- a/third_party/openmp/kmp_config.h +++ b/third_party/openmp/kmp_config.h @@ -18,12 +18,14 @@ #include "libc/stdio/syscall.h" #endif +#if IsModeDbg() +#define KMP_DEBUG 1 +#endif + #define KMP_USE_FUTEX 0 #define KMP_FTN_ENTRIES KMP_FTN_PLAIN #define syscall {{openmp_shall_not_use_syscall}} -#define DEBUG_BUILD IsModeDbg() -#define RELWITHDEBINFO_BUILD (IsOptimized() && !IsTiny()) #define LIBOMP_USE_ITT_NOTIFY 0 #define USE_ITT_NOTIFY LIBOMP_USE_ITT_NOTIFY #if ! LIBOMP_USE_ITT_NOTIFY @@ -152,9 +154,6 @@ #if STUBS_LIBRARY # define KMP_STUB 1 #endif -#if DEBUG_BUILD || RELWITHDEBINFO_BUILD -# define KMP_DEBUG 1 -#endif #if KMP_OS_WINDOWS # define KMP_WIN_CDECL @@ -169,8 +168,4 @@ #define KMP_USE_SHM #endif -#ifdef __COSMOPOLITAN__ -#define KMP_USE_SHM -#endif - #endif // KMP_CONFIG_H diff --git a/third_party/openmp/kmp_runtime.cpp b/third_party/openmp/kmp_runtime.cpp index 8161a2896..e89752164 100644 --- a/third_party/openmp/kmp_runtime.cpp +++ b/third_party/openmp/kmp_runtime.cpp @@ -6699,10 +6699,12 @@ void __kmp_internal_end_thread(int gtid_req) { // ----------------------------------------------------------------------------- // Library registration stuff. +#ifndef __COSMOPOLITAN__ static long __kmp_registration_flag = 0; // Random value used to indicate library initialization. static char *__kmp_registration_str = NULL; // Value to be saved in env var __KMP_REGISTERED_LIB_. +#endif // __COSMOPOLITAN__ static inline char *__kmp_reg_status_name() { /* On RHEL 3u5 if linked statically, getpid() returns different values in @@ -6726,6 +6728,7 @@ char *temp_reg_status_file_name = nullptr; #endif void __kmp_register_library_startup(void) { +#ifndef __COSMOPOLITAN__ char *name = __kmp_reg_status_name(); // Name of the environment variable. int done = 0; @@ -6937,9 +6940,11 @@ void __kmp_register_library_startup(void) { } // while KMP_INTERNAL_FREE((void *)name); +#endif // __COSMOPOLITAN__ } // func __kmp_register_library_startup void __kmp_unregister_library(void) { +#ifndef __COSMOPOLITAN__ char *name = __kmp_reg_status_name(); char *value = NULL; @@ -7006,6 +7011,7 @@ void __kmp_unregister_library(void) { __kmp_registration_flag = 0; __kmp_registration_str = NULL; +#endif // __COSMOPOLITAN__ } // __kmp_unregister_library // End of Library registration stuff. diff --git a/third_party/openmp/util1.cpp b/third_party/openmp/util1.cpp index 1e668d644..eafdadd6c 100644 --- a/third_party/openmp/util1.cpp +++ b/third_party/openmp/util1.cpp @@ -2054,6 +2054,7 @@ void __kmp_initialize_system_tick() { } #endif +#ifndef __COSMOPOLITAN__ /* Determine whether the given address is mapped into the current address space. */ @@ -2062,12 +2063,7 @@ int __kmp_is_address_mapped(void *addr) { int found = 0; int rc; -#if defined(__COSMOPOLITAN__) - - (void)rc; - found = kisdangerous(addr); - -#elif KMP_OS_LINUX || KMP_OS_HURD +#if KMP_OS_LINUX || KMP_OS_HURD /* On GNUish OSes, read the /proc//maps pseudo-file to get all the address ranges mapped into the address space. */ @@ -2236,6 +2232,7 @@ int __kmp_is_address_mapped(void *addr) { return found; } // __kmp_is_address_mapped +#endif // __COSMOPOLITAN__ #ifdef USE_LOAD_BALANCE diff --git a/third_party/openmp/util2.S b/third_party/openmp/util2.S index 941a2c33e..859fa1d91 100644 --- a/third_party/openmp/util2.S +++ b/third_party/openmp/util2.S @@ -11,6 +11,14 @@ ////===----------------------------------------------------------------------===// // +#ifdef __COSMOPOLITAN__ + .macro no.comm name:req size:req align:req + .globl \name +\name: .align \align + .byte \size + .endm +#endif + // ----------------------------------------------------------------------- // macros // ----------------------------------------------------------------------- @@ -180,11 +188,11 @@ KMP_PREFIX_UNDERSCORE(\proc): .macro COMMON name, size, align_power #if KMP_OS_DARWIN - .comm \name, \size + no.comm \name, \size #elif KMP_OS_WINDOWS - .comm \name, \size, \align_power + no.comm \name, \size, \align_power #else // !KMP_OS_DARWIN && !KMP_OS_WINDOWS - .comm \name, \size, (1<<(\align_power)) + no.comm \name, \size, (1<<(\align_power)) #endif .endm @@ -202,14 +210,14 @@ KMP_PREFIX_UNDERSCORE(\proc): # if KMP_ARCH_X86 # if KMP_OS_DARWIN .data - .comm .gomp_critical_user_,32 + no.comm .gomp_critical_user_,32 .data .globl ___kmp_unnamed_critical_addr ___kmp_unnamed_critical_addr: .long .gomp_critical_user_ # else /* Linux* OS */ .data - .comm .gomp_critical_user_,32,8 + no.comm .gomp_critical_user_,32,8 .data ALIGN 4 .global __kmp_unnamed_critical_addr @@ -223,21 +231,14 @@ __kmp_unnamed_critical_addr: # if KMP_ARCH_X86_64 # if KMP_OS_DARWIN .data - .comm .gomp_critical_user_,32 + no.comm .gomp_critical_user_,32 .data .globl ___kmp_unnamed_critical_addr ___kmp_unnamed_critical_addr: .quad .gomp_critical_user_ # else /* Linux* OS */ .data -#ifdef __COSMOPOLITAN__ - .globl .gomp_critical_user_ -".gomp_critical_user_": - .align 8 - .byte 32 -#else - .comm .gomp_critical_user_,32,8 -#endif + no.comm .gomp_critical_user_,32,8 .data ALIGN 8 .global __kmp_unnamed_critical_addr diff --git a/tool/cosmocc/package.sh b/tool/cosmocc/package.sh index 2864d0214..63e6bf191 100755 --- a/tool/cosmocc/package.sh +++ b/tool/cosmocc/package.sh @@ -129,9 +129,11 @@ for arch in $AMD64 $ARM64; do cp -f o/$arch/libc/crt/crt.o "$OUTDIR/$arch-linux-cosmo/lib/" cp -f o/$arch/cosmopolitan.a "$OUTDIR/$arch-linux-cosmo/lib/libcosmo.a" cp -f o/$arch/third_party/libcxx/libcxx.a "$OUTDIR/$arch-linux-cosmo/lib/" - for lib in c dl gcc_s m pthread resolv rt dl z stdc++; do + for lib in c dl gcc_s m pthread resolv rt dl unwind gomp stdc++; do printf '\041\074\141\162\143\150\076\012' >"$OUTDIR/$arch-linux-cosmo/lib/lib$lib.a" done + mkdir -p "$OUTDIR/lib/gcc/" + touch "$OUTDIR/lib/gcc/libgomp.spec" # needed if user passes -fopenmp but not -lgomp done cp -f o/$AMD64/ape/ape.o "$OUTDIR/x86_64-linux-cosmo/lib/" cp -f o/$AMD64/ape/ape.lds "$OUTDIR/x86_64-linux-cosmo/lib/" diff --git a/tool/emacs/cosmo-cpp-constants.el b/tool/emacs/cosmo-cpp-constants.el index 8fbe277aa..b5f2af0fa 100644 --- a/tool/emacs/cosmo-cpp-constants.el +++ b/tool/emacs/cosmo-cpp-constants.el @@ -59,7 +59,8 @@ "__AVX512VBMI__" "__AVX512VNNI__" "__AVXVNNI__" - "__AVXVNNI__" + "__AVXVNNIINT8__" + "__AVXVNNIINT16__" "__ABM__" "__BMI__" "__BMI2__" diff --git a/tool/viz/cpuid.c b/tool/viz/cpuid.c index b6b7e0bb5..ab654d9a6 100644 --- a/tool/viz/cpuid.c +++ b/tool/viz/cpuid.c @@ -175,6 +175,8 @@ int main(int argc, char *argv[]) { : ""); CANIUSE(AVXVNNI); + CANIUSE(AVXVNNIINT8); + CANIUSE(AVXVNNIINT16); CANIUSE(AVX512BW); CANIUSE(AVX512CD); CANIUSE(AVX512DQ);