From f1dfa4bdfa10f0996aa540ab71baa93cdcae5911 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Sun, 17 Apr 2022 12:25:10 -0700 Subject: [PATCH] Add some more builtins to chibicc https://justine.lol/cosmopolitan/documentation.html should now contain a lot of functions that had been missing previously due to not having them --- README.md | 31 +++ libc/calls/sigaction.c | 84 ++++---- libc/intrin/spinlock.h | 22 +- third_party/chibicc/README.cosmo | 1 + third_party/chibicc/as.c | 10 + third_party/chibicc/chibicc.c | 1 + third_party/chibicc/chibicc.h | 5 + third_party/chibicc/codegen.c | 31 ++- third_party/chibicc/kw.gperf | 7 +- third_party/chibicc/kw.h | 7 +- third_party/chibicc/kw.inc | 261 +++++++++++------------ third_party/chibicc/parse.c | 61 +++++- third_party/chibicc/preprocess.c | 24 +++ third_party/chibicc/test/msabi_test.c | 6 + third_party/chibicc/test/spinlock_test.c | 26 +++ third_party/chibicc/test/vector_test.c | 40 ++-- third_party/chibicc/tokenize.c | 1 + 17 files changed, 417 insertions(+), 201 deletions(-) create mode 100644 third_party/chibicc/test/msabi_test.c create mode 100644 third_party/chibicc/test/spinlock_test.c diff --git a/README.md b/README.md index 209536923..2e8477863 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,37 @@ o//examples/hello.com find o -name \*.com | xargs ls -rShal | less ``` +## GDB + +Here's the recommended `~/.gdbinit` config: + +``` +set host-charset UTF-8 +set target-charset UTF-8 +set target-wide-charset UTF-8 +set osabi none +set complaints 0 +set confirm off +set history save on +set history filename ~/.gdb_history +define asm + layout asm + layout reg +end +define src + layout src + layout reg +end +src +``` + +You normally run the `.com.dbg` file under gdb. If you need to debug the +`.com` file itself, then you can load the debug symbols independently as + +``` +gdb foo.com -ex 'add-symbol-file foo.com.dbg 0x401000' +``` + ## Support Vector | Platform | Min Version | Circa | diff --git a/libc/calls/sigaction.c b/libc/calls/sigaction.c index 4cd2f5738..df89c892e 100644 --- a/libc/calls/sigaction.c +++ b/libc/calls/sigaction.c @@ -292,50 +292,50 @@ static int __sigaction(int sig, const struct sigaction *act, * have your signals work hand-in-glove with the EINTR errno. This * obfuscates the need for having to worry about @asyncsignalsafe. * - * static volatile bool gotctrlc; + * static volatile bool gotctrlc; * - * void OnCtrlC(int sig) { - * gotctrlc = true; - * } + * void OnCtrlC(int sig) { + * gotctrlc = true; + * } * - * int main() { - * size_t got; - * ssize_t rc; - * char buf[1]; - * struct sigaction oldint; - * struct sigaction saint = {.sa_handler = GotCtrlC}; - * if (sigaction(SIGINT, &saint, &oldint) == -1) { - * perror("sigaction"); - * exit(1); - * } - * for (;;) { - * rc = read(0, buf, sizeof(buf)); - * if (rc == -1) { - * if (errno == EINTR) { - * if (gotctrlc) { - * break; - * } - * } else { - * perror("read"); - * exit(2); - * } - * } - * if (!(got = rc)) { - * break; - * } - * for (;;) { - * rc = write(1, buf, got); - * if (rc != -1) { - * assert(rc == 1); - * break; - * } else if (errno != EINTR) { - * perror("write"); - * exit(3); - * } - * } - * } - * sigaction(SIGINT, &oldint, 0); - * } + * int main() { + * size_t got; + * ssize_t rc; + * char buf[1]; + * struct sigaction oldint; + * struct sigaction saint = {.sa_handler = GotCtrlC}; + * if (sigaction(SIGINT, &saint, &oldint) == -1) { + * perror("sigaction"); + * exit(1); + * } + * for (;;) { + * rc = read(0, buf, sizeof(buf)); + * if (rc == -1) { + * if (errno == EINTR) { + * if (gotctrlc) { + * break; + * } + * } else { + * perror("read"); + * exit(2); + * } + * } + * if (!(got = rc)) { + * break; + * } + * for (;;) { + * rc = write(1, buf, got); + * if (rc != -1) { + * assert(rc == 1); + * break; + * } else if (errno != EINTR) { + * perror("write"); + * exit(3); + * } + * } + * } + * sigaction(SIGINT, &oldint, 0); + * } * * Please note that you can't do the above if you use SA_RESTART. Since * the purpose of SA_RESTART is to restart i/o operations whose docs say diff --git a/libc/intrin/spinlock.h b/libc/intrin/spinlock.h index bcba6b5fd..a5ba7d630 100644 --- a/libc/intrin/spinlock.h +++ b/libc/intrin/spinlock.h @@ -4,17 +4,17 @@ #if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 401 && \ !defined(__STRICT_ANSI__) -#define _spinlock(lock) \ - do { \ - for (;;) { \ - typeof(*(lock)) x; \ - __atomic_load(lock, &x, __ATOMIC_RELAXED); \ - if (!x && !__sync_lock_test_and_set(lock, __ATOMIC_CONSUME)) { \ - break; \ - } else { \ - __builtin_ia32_pause(); \ - } \ - } \ +#define _spinlock(lock) \ + do { \ + for (;;) { \ + typeof(*(lock)) x; \ + __atomic_load(lock, &x, __ATOMIC_RELAXED); \ + if (!x && !__sync_lock_test_and_set(lock, 1)) { \ + break; \ + } else { \ + __builtin_ia32_pause(); \ + } \ + } \ } while (0) #define _spunlock(lock) __sync_lock_release(lock) diff --git a/third_party/chibicc/README.cosmo b/third_party/chibicc/README.cosmo index feca45a91..18bbd30fa 100644 --- a/third_party/chibicc/README.cosmo +++ b/third_party/chibicc/README.cosmo @@ -17,6 +17,7 @@ local enhancements - support __builtin_constant_p, __builtin_likely, etc. - support __builtin_isunordered, __builtin_islessgreater, etc. - support __builtin_ctz, __builtin_bswap, __builtin_popcount, etc. +- support __atomic_load, __sync_lock_test_and_set, __sync_lock_release, etc. - support __force_align_arg_pointer__, __no_caller_saved_registers__, etc. - support __constructor__, __section__, __cold__, -ffunction-sections, etc. - support building -x assembler-with-cpp a.k.a. .S files diff --git a/third_party/chibicc/as.c b/third_party/chibicc/as.c index e02999665..64c0c794f 100644 --- a/third_party/chibicc/as.c +++ b/third_party/chibicc/as.c @@ -2428,6 +2428,14 @@ static void OpSseMov(struct As *a, int opWsdVsd, int opVsdWsd) { } } +static void OpMovntdq(struct As *a) { + int reg, modrm, disp; + reg = GetRegisterReg(a); + ConsumeComma(a); + modrm = ParseModrm(a, &disp); + EmitRexOpModrm(a, 0x660FE7, reg, modrm, disp, 0); +} + static void OpMovdqx(struct As *a, int op) { OpSseMov(a, op + 0x10, op); } @@ -3005,6 +3013,7 @@ static void OnPunpcklbw(struct As *a, struct Slice s) { OpSse(a, 0x660F60); } static void OnPunpckldq(struct As *a, struct Slice s) { OpSse(a, 0x660F62); } static void OnPunpcklqdq(struct As *a, struct Slice s) { OpSse(a, 0x660F6C); } static void OnPunpcklwd(struct As *a, struct Slice s) { OpSse(a, 0x660F61); } +static void OnMovntdq(struct As *a, struct Slice s) { OpMovntdq(a); } static void OnPxor(struct As *a, struct Slice s) { OpSse(a, 0x660FEF); } static void OnRcl(struct As *a, struct Slice s) { OpBsu(a, s, 2); } static void OnRcpps(struct As *a, struct Slice s) { OpSse(a, 0x0F53); } @@ -3637,6 +3646,7 @@ static const struct Directive16 { {"cvttss2si", OnCvttss2si}, // {"cvttss2sil", OnCvttss2si}, // {"cvttss2siq", OnCvttss2si}, // + {"movntdq", OnMovntdq}, // {"pcmpistri", OnPcmpistri}, // {"pcmpistrm", OnPcmpistrm}, // {"phminposuw", OnPhminposuw}, // diff --git a/third_party/chibicc/chibicc.c b/third_party/chibicc/chibicc.c index 725bb621b..e1fff9230 100644 --- a/third_party/chibicc/chibicc.c +++ b/third_party/chibicc/chibicc.c @@ -685,6 +685,7 @@ static void OnCtrlC(int sig, siginfo_t *si, ucontext_t *ctx) { } int chibicc(int argc, char **argv) { + ShowCrashReports(); atexit(chibicc_cleanup); sigaction(SIGINT, &(struct sigaction){.sa_sigaction = OnCtrlC}, NULL); for (int i = 1; i < argc; i++) { diff --git a/third_party/chibicc/chibicc.h b/third_party/chibicc/chibicc.h index 9d9d35232..f36485f61 100644 --- a/third_party/chibicc/chibicc.h +++ b/third_party/chibicc/chibicc.h @@ -345,7 +345,12 @@ typedef enum { ND_ASM, // "asm" ND_CAS, // Atomic compare-and-swap ND_EXCH, // Atomic exchange + ND_LOAD, // Atomic load + ND_TESTANDSET, // Atomic lock test and set + ND_RELEASE, // Atomic lock release ND_FPCLASSIFY, // floating point classify + ND_MOVNTDQ, // Intel MOVNTDQ + ND_PMOVMSKB, // Intel PMOVMSKB } NodeKind; struct Node { diff --git a/third_party/chibicc/codegen.c b/third_party/chibicc/codegen.c index 298975e83..fb232f880 100644 --- a/third_party/chibicc/codegen.c +++ b/third_party/chibicc/codegen.c @@ -904,6 +904,9 @@ static bool gen_builtin_funcall(Node *node, const char *name) { } else if (!strcmp(name, "trap")) { emitlin("\tint3"); return true; + } else if (!strcmp(name, "ia32_pause")) { + emitlin("\tpause"); + return true; } else if (!strcmp(name, "unreachable")) { emitlin("\tud2"); return true; @@ -1521,7 +1524,8 @@ void gen_expr(Node *node) { emitlin("\tmovzbl\t%cl,%eax"); return; } - case ND_EXCH: { + case ND_EXCH: + case ND_TESTANDSET: { gen_expr(node->lhs); push(); gen_expr(node->rhs); @@ -1529,6 +1533,23 @@ void gen_expr(Node *node) { println("\txchg\t%s,(%%rdi)", reg_ax(node->ty->size)); return; } + case ND_LOAD: { + gen_expr(node->rhs); + push(); + gen_expr(node->lhs); + println("\tmov\t(%%rax),%s", reg_ax(node->ty->size)); + pop("%rdi"); + println("\tmov\t%s,(%%rdi)", reg_ax(node->ty->size)); + return; + } + case ND_RELEASE: { + gen_expr(node->lhs); + push(); + pop("%rdi"); + println("\txor\t%%eax,%%eax"); + println("\tmov\t%s,(%%rdi)", reg_ax(node->ty->size)); + return; + } case ND_FPCLASSIFY: gen_fpclassify(node->fpc); return; @@ -1658,6 +1679,14 @@ void gen_expr(Node *node) { dx = "%edx"; } switch (node->kind) { + case ND_PMOVMSKB: + println("\tmovdqu\t(%%rax),%%xmm0"); + println("\tpmovmskb\t%%xmm0,%%rax"); + break; + case ND_MOVNTDQ: + println("\tmovdqu\t(%%rdi),%%xmm0"); + println("\tmovntdq\t%%xmm0,(%%rax)"); + break; case ND_ADD: if (node->lhs->ty->kind == TY_INT128) { emitlin("\tadd\t%rdi,%rax"); diff --git a/third_party/chibicc/kw.gperf b/third_party/chibicc/kw.gperf index 13482408c..ab0b828d4 100644 --- a/third_party/chibicc/kw.gperf +++ b/third_party/chibicc/kw.gperf @@ -81,7 +81,7 @@ __thread, KW__THREAD_LOCAL __typeof, KW_TYPEOF __builtin_add_overflow, KW___BUILTIN_ADD_OVERFLOW __builtin_assume_aligned, KW___BUILTIN_ASSUME_ALIGNED -__builtin_atomic_exchange, KW___BUILTIN_ATOMIC_EXCHANGE +__atomic_exchange, KW___ATOMIC_EXCHANGE __builtin_compare_and_swap, KW___BUILTIN_COMPARE_AND_SWAP __builtin_constant_p, KW___BUILTIN_CONSTANT_P __builtin_expect, KW___BUILTIN_EXPECT @@ -118,3 +118,8 @@ __builtin_types_compatible_p, KW___BUILTIN_TYPES_COMPATIBLE_P "||", KW_LOGOR "->", KW_ARROW ".", KW_DOT +__atomic_load, KW___ATOMIC_LOAD +__sync_lock_test_and_set, KW___SYNC_LOCK_TEST_AND_SET +__sync_lock_release, KW___SYNC_LOCK_RELEASE +__builtin_ia32_movntdq, KW___BUILTIN_IA32_MOVNTDQ +__builtin_ia32_pmovmskb128, KW___BUILTIN_IA32_PMOVMSKB128 diff --git a/third_party/chibicc/kw.h b/third_party/chibicc/kw.h index 185d180e0..e5d1f8f13 100644 --- a/third_party/chibicc/kw.h +++ b/third_party/chibicc/kw.h @@ -68,7 +68,7 @@ #define KW___ASM__ 84 #define KW___BUILTIN_ADD_OVERFLOW 85 #define KW___BUILTIN_ASSUME_ALIGNED 86 -#define KW___BUILTIN_ATOMIC_EXCHANGE 87 +#define KW___ATOMIC_EXCHANGE 87 #define KW___BUILTIN_COMPARE_AND_SWAP 88 #define KW___BUILTIN_CONSTANT_P 89 #define KW___BUILTIN_EXPECT 90 @@ -105,6 +105,11 @@ #define KW_LOGOR 121 #define KW_ARROW 122 #define KW_DOT 123 +#define KW___ATOMIC_LOAD 124 +#define KW___SYNC_LOCK_TEST_AND_SET 125 +#define KW___SYNC_LOCK_RELEASE 126 +#define KW___BUILTIN_IA32_PMOVMSKB128 127 +#define KW___BUILTIN_IA32_MOVNTDQ 128 #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ diff --git a/third_party/chibicc/kw.inc b/third_party/chibicc/kw.inc index eeb8bc5c8..c61680cb6 100644 --- a/third_party/chibicc/kw.inc +++ b/third_party/chibicc/kw.inc @@ -1,7 +1,7 @@ /* ANSI-C code produced by gperf version 3.1 */ /* Command-line: gperf kw.gperf */ /* Computed positions: -k'1,4,11,14,$' */ -/* clang-format off */ +// clang-format off #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ @@ -37,51 +37,44 @@ #line 10 "kw.gperf" struct thatispacked KwSlot { char *name; unsigned char code; }; -#define TOTAL_KEYWORDS 109 +#define TOTAL_KEYWORDS 114 #define MIN_WORD_LENGTH 1 #define MAX_WORD_LENGTH 28 #define MIN_HASH_VALUE 1 -#define MAX_HASH_VALUE 211 -/* maximum key range = 211, duplicates = 0 */ +#define MAX_HASH_VALUE 201 +/* maximum key range = 201, duplicates = 0 */ -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static unsigned int +static inline unsigned int hash (register const char *str, register size_t len) { static const unsigned char asso_values[] = { - 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 212, 105, 212, 212, 212, 212, 65, 212, - 100, 95, 90, 15, 212, 0, 80, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 5, 212, 212, 212, - 212, 212, 65, 212, 212, 212, 0, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 212, 212, 212, 5, 212, 20, 50, 0, - 5, 15, 0, 25, 40, 90, 60, 0, 20, 15, - 85, 105, 0, 25, 55, 10, 0, 65, 5, 0, - 0, 10, 0, 30, 10, 25, 5, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, - 212, 212, 212, 212, 212, 212, 212 + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 100, 202, 202, 202, 202, 65, 202, + 95, 90, 85, 15, 202, 0, 75, 202, 202, 202, + 0, 202, 202, 202, 202, 202, 10, 202, 202, 202, + 202, 202, 55, 202, 202, 202, 0, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 5, 202, 0, 50, 0, + 5, 15, 0, 40, 45, 115, 60, 5, 20, 15, + 90, 85, 0, 0, 55, 10, 0, 65, 5, 0, + 0, 10, 25, 70, 35, 30, 5, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202 }; register unsigned int hval = len; @@ -135,24 +128,23 @@ LookupKw (register const char *str, register size_t len) {"~", KW_TILDE}, #line 68 "kw.gperf" {"_Atomic", KW__ATOMIC}, -#line 81 "kw.gperf" - {"__typeof", KW_TYPEOF}, - {""}, + {""}, {""}, #line 78 "kw.gperf" {"__restrict", KW_RESTRICT}, #line 22 "kw.gperf" {"sizeof", KW_SIZEOF}, #line 75 "kw.gperf" {"__asm__", KW___ASM__}, - {""}, +#line 41 "kw.gperf" + {"asm", KW_ASM}, #line 15 "kw.gperf" {"case", KW_CASE}, #line 73 "kw.gperf" {"__VA_OPT__", KW___VA_OPT__}, #line 13 "kw.gperf" {"struct", KW_STRUCT}, -#line 118 "kw.gperf" - {"||", KW_LOGOR}, +#line 60 "kw.gperf" + {"strpbrk", KW_STRPBRK}, {""}, {""}, #line 31 "kw.gperf" {"short", KW_SHORT}, @@ -178,22 +170,19 @@ LookupKw (register const char *str, register size_t len) {"while", KW_WHILE}, #line 85 "kw.gperf" {"__builtin_compare_and_swap", KW___BUILTIN_COMPARE_AND_SWAP}, -#line 101 "kw.gperf" - {"__builtin_strpbrk", KW___BUILTIN_STRPBRK}, -#line 41 "kw.gperf" - {"asm", KW_ASM}, +#line 82 "kw.gperf" + {"__builtin_add_overflow", KW___BUILTIN_ADD_OVERFLOW}, +#line 81 "kw.gperf" + {"__typeof", KW_TYPEOF}, #line 55 "kw.gperf" {"line", KW_LINE}, #line 86 "kw.gperf" {"__builtin_constant_p", KW___BUILTIN_CONSTANT_P}, #line 74 "kw.gperf" {"__alignof__", KW___ALIGNOF__}, -#line 60 "kw.gperf" - {"strpbrk", KW_STRPBRK}, - {""}, -#line 47 "kw.gperf" - {"elif", KW_ELIF}, - {""}, {""}, +#line 101 "kw.gperf" + {"__builtin_strpbrk", KW___BUILTIN_STRPBRK}, + {""}, {""}, {""}, {""}, #line 103 "kw.gperf" {"__builtin_sub_overflow", KW___BUILTIN_SUB_OVERFLOW}, #line 72 "kw.gperf" @@ -202,8 +191,8 @@ LookupKw (register const char *str, register size_t len) {"__builtin_popcountl", KW___BUILTIN_POPCOUNTL}, #line 97 "kw.gperf" {"__builtin_popcountll", KW___BUILTIN_POPCOUNTLL}, -#line 108 "kw.gperf" - {"}", KW_RB}, +#line 56 "kw.gperf" + {"pragma", KW_PRAGMA}, #line 92 "kw.gperf" {"__builtin_mul_overflow", KW___BUILTIN_MUL_OVERFLOW}, #line 104 "kw.gperf" @@ -213,15 +202,16 @@ LookupKw (register const char *str, register size_t len) {"float", KW_FLOAT}, #line 87 "kw.gperf" {"__builtin_expect", KW___BUILTIN_EXPECT}, -#line 82 "kw.gperf" - {"__builtin_add_overflow", KW___BUILTIN_ADD_OVERFLOW}, +#line 119 "kw.gperf" + {"->", KW_ARROW}, #line 20 "kw.gperf" {"for", KW_FOR}, - {""}, +#line 47 "kw.gperf" + {"elif", KW_ELIF}, #line 91 "kw.gperf" {"__builtin_fpclassify", KW___BUILTIN_FPCLASSIFY}, -#line 107 "kw.gperf" - {"{", KW_LB}, +#line 108 "kw.gperf" + {"}", KW_RB}, #line 42 "kw.gperf" {"default", KW_DEFAULT}, {""}, @@ -229,21 +219,19 @@ LookupKw (register const char *str, register size_t len) {"__builtin_ffsl", KW___BUILTIN_FFSL}, #line 90 "kw.gperf" {"__builtin_ffsll", KW___BUILTIN_FFSLL}, -#line 56 "kw.gperf" - {"pragma", KW_PRAGMA}, -#line 119 "kw.gperf" - {"->", KW_ARROW}, - {""}, + {""}, {""}, {""}, #line 18 "kw.gperf" {"char", KW_CHAR}, #line 64 "kw.gperf" {"undef", KW_UNDEF}, #line 61 "kw.gperf" {"strstr", KW_STRSTR}, - {""}, +#line 118 "kw.gperf" + {"||", KW_LOGOR}, #line 67 "kw.gperf" {"_Alignof", KW__ALIGNOF}, - {""}, +#line 122 "kw.gperf" + {"__sync_lock_test_and_set", KW___SYNC_LOCK_TEST_AND_SET}, #line 49 "kw.gperf" {"error", KW_ERROR}, #line 58 "kw.gperf" @@ -261,19 +249,53 @@ LookupKw (register const char *str, register size_t len) {""}, #line 66 "kw.gperf" {"_Alignas", KW__ALIGNAS}, +#line 123 "kw.gperf" + {"__sync_lock_release", KW___SYNC_LOCK_RELEASE}, {""}, -#line 84 "kw.gperf" - {"__builtin_atomic_exchange", KW___BUILTIN_ATOMIC_EXCHANGE}, #line 39 "kw.gperf" {"define", KW_DEFINE}, {""}, #line 35 "kw.gperf" {"continue", KW_CONTINUE}, -#line 24 "kw.gperf" - {"long", KW_LONG}, +#line 43 "kw.gperf" + {"auto", KW_AUTO}, {""}, #line 99 "kw.gperf" {"__builtin_strchr", KW___BUILTIN_STRCHR}, +#line 21 "kw.gperf" + {"do", KW_DO}, + {""}, {""}, {""}, {""}, {""}, +#line 70 "kw.gperf" + {"_Generic", KW__GENERIC}, +#line 98 "kw.gperf" + {"__builtin_reg_class", KW___BUILTIN_REG_CLASS}, + {""}, +#line 102 "kw.gperf" + {"__builtin_strstr", KW___BUILTIN_STRSTR}, +#line 84 "kw.gperf" + {"__atomic_exchange", KW___ATOMIC_EXCHANGE}, +#line 45 "kw.gperf" + {"__attribute__", KW___ATTRIBUTE__}, +#line 83 "kw.gperf" + {"__builtin_assume_aligned", KW___BUILTIN_ASSUME_ALIGNED}, + {""}, +#line 32 "kw.gperf" + {"signed", KW_SIGNED}, + {""}, +#line 77 "kw.gperf" + {"__int128", KW___INT128}, +#line 24 "kw.gperf" + {"long", KW_LONG}, +#line 33 "kw.gperf" + {"break", KW_BREAK}, +#line 50 "kw.gperf" + {"extern", KW_EXTERN}, + {""}, +#line 76 "kw.gperf" + {"__inline", KW_INLINE}, +#line 46 "kw.gperf" + {"_Noreturn", KW__NORETURN}, + {""}, {""}, #line 12 "kw.gperf" {"if", KW_IF}, #line 54 "kw.gperf" @@ -281,37 +303,11 @@ LookupKw (register const char *str, register size_t len) {""}, #line 37 "kw.gperf" {"ifdef", KW_IFDEF}, - {""}, {""}, {""}, -#line 98 "kw.gperf" - {"__builtin_reg_class", KW___BUILTIN_REG_CLASS}, - {""}, -#line 102 "kw.gperf" - {"__builtin_strstr", KW___BUILTIN_STRSTR}, - {""}, -#line 45 "kw.gperf" - {"__attribute__", KW___ATTRIBUTE__}, - {""}, -#line 33 "kw.gperf" - {"break", KW_BREAK}, -#line 50 "kw.gperf" - {"extern", KW_EXTERN}, - {""}, -#line 80 "kw.gperf" - {"__thread", KW__THREAD_LOCAL}, -#line 46 "kw.gperf" - {"_Noreturn", KW__NORETURN}, - {""}, -#line 38 "kw.gperf" - {"ifndef", KW_IFNDEF}, -#line 21 "kw.gperf" - {"do", KW_DO}, - {""}, {""}, {""}, #line 59 "kw.gperf" {"strlen", KW_STRLEN}, -#line 52 "kw.gperf" - {"include_next", KW_INCLUDE_NEXT}, -#line 70 "kw.gperf" - {"_Generic", KW__GENERIC}, + {""}, +#line 94 "kw.gperf" + {"__builtin_offsetof", KW___BUILTIN_OFFSETOF}, #line 34 "kw.gperf" {"enum", KW_ENUM}, {""}, @@ -319,62 +315,65 @@ LookupKw (register const char *str, register size_t len) {"switch", KW_SWITCH}, #line 93 "kw.gperf" {"__builtin_neg_overflow", KW___BUILTIN_NEG_OVERFLOW}, -#line 77 "kw.gperf" - {"__int128", KW___INT128}, -#line 83 "kw.gperf" - {"__builtin_assume_aligned", KW___BUILTIN_ASSUME_ALIGNED}, - {""}, -#line 32 "kw.gperf" - {"signed", KW_SIGNED}, -#line 36 "kw.gperf" - {"include", KW_INCLUDE}, #line 57 "kw.gperf" {"restrict", KW_RESTRICT}, -#line 43 "kw.gperf" - {"auto", KW_AUTO}, +#line 51 "kw.gperf" + {"goto", KW_GOTO}, {""}, #line 111 "kw.gperf" {"&", KW_AMP}, #line 117 "kw.gperf" {"&&", KW_LOGAND}, -#line 76 "kw.gperf" - {"__inline", KW_INLINE}, -#line 51 "kw.gperf" - {"goto", KW_GOTO}, - {""}, {""}, {""}, +#line 80 "kw.gperf" + {"__thread", KW__THREAD_LOCAL}, + {""}, {""}, +#line 38 "kw.gperf" + {"ifndef", KW_IFNDEF}, + {""}, #line 23 "kw.gperf" {"unsigned", KW_UNSIGNED}, {""}, {""}, +#line 107 "kw.gperf" + {"{", KW_LB}, +#line 52 "kw.gperf" + {"include_next", KW_INCLUDE_NEXT}, + {""}, {""}, {""}, #line 100 "kw.gperf" {"__builtin_strlen", KW___BUILTIN_STRLEN}, - {""}, -#line 94 "kw.gperf" - {"__builtin_offsetof", KW___BUILTIN_OFFSETOF}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 124 "kw.gperf" + {"__builtin_ia32_movntdq", KW___BUILTIN_IA32_MOVNTDQ}, + {""}, {""}, {""}, +#line 120 "kw.gperf" + {".", KW_DOT}, +#line 36 "kw.gperf" + {"include", KW_INCLUDE}, + {""}, {""}, {""}, #line 14 "kw.gperf" {"return", KW_RETURN}, {""}, {""}, {""}, #line 26 "kw.gperf" {"union", KW_UNION}, - {""}, {""}, {""}, {""}, {""}, -#line 120 "kw.gperf" - {".", KW_DOT}, +#line 125 "kw.gperf" + {"__builtin_ia32_pmovmskb128", KW___BUILTIN_IA32_PMOVMSKB128}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 53 "kw.gperf" - {"inline", KW_INLINE}, - {""}, {""}, {""}, {""}, {""}, {""}, +#line 112 "kw.gperf" + {"*", KW_STAR}, + {""}, +#line 121 "kw.gperf" + {"__atomic_load", KW___ATOMIC_LOAD}, + {""}, {""}, {""}, {""}, #line 44 "kw.gperf" {"register", KW_REGISTER}, {""}, {""}, -#line 112 "kw.gperf" - {"*", KW_STAR}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, #line 106 "kw.gperf" {")", KW_RP}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, #line 105 "kw.gperf" {"(", KW_LP}, - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, {""}, +#line 53 "kw.gperf" + {"inline", KW_INLINE}, + {""}, {""}, {""}, {""}, #line 113 "kw.gperf" {"!", KW_EXCLAIM} }; diff --git a/third_party/chibicc/parse.c b/third_party/chibicc/parse.c index 2d06faee3..fe2b5b8cc 100644 --- a/third_party/chibicc/parse.c +++ b/third_party/chibicc/parse.c @@ -976,11 +976,12 @@ static Type *type_suffix(Token **rest, Token *tok, Type *ty) { return ty; } -// pointers = ("*" ("const" | "volatile" | "restrict")*)* +// pointers = ("*" ("const" | "volatile" | "restrict" | attribute)*)* static Type *pointers(Token **rest, Token *tok, Type *ty) { while (CONSUME(&tok, tok, "*")) { ty = pointer_to(ty); for (;;) { + tok = attribute_list(tok, ty, type_attributes); if (EQUAL(tok, "const")) { ty->is_const = true; tok = tok->next; @@ -3218,12 +3219,67 @@ static Node *primary(Token **rest, Token *tok) { node->ty = node->cas_addr->ty->base; return node; } - if (kw == KW___BUILTIN_ATOMIC_EXCHANGE) { + if (kw == KW___ATOMIC_EXCHANGE) { Node *node = new_node(ND_EXCH, tok); tok = skip(tok->next, '('); node->lhs = assign(&tok, tok); + add_type(node->lhs); + node->ty = node->lhs->ty->base; tok = skip(tok, ','); node->rhs = assign(&tok, tok); + *rest = skip(tok, ')'); + return node; + } + if (kw == KW___ATOMIC_LOAD) { + Node *node = new_node(ND_LOAD, tok); + tok = skip(tok->next, '('); + node->lhs = assign(&tok, tok); + add_type(node->lhs); + node->ty = node->lhs->ty->base; + tok = skip(tok, ','); + node->rhs = assign(&tok, tok); + tok = skip(tok, ','); + const_expr(&tok, tok); + *rest = skip(tok, ')'); + return node; + } + if (kw == KW___SYNC_LOCK_TEST_AND_SET) { + Node *node = new_node(ND_TESTANDSET, tok); + tok = skip(tok->next, '('); + node->lhs = assign(&tok, tok); + add_type(node->lhs); + node->ty = node->lhs->ty->base; + tok = skip(tok, ','); + node->rhs = assign(&tok, tok); + *rest = skip(tok, ')'); + return node; + } + if (kw == KW___SYNC_LOCK_RELEASE) { + Node *node = new_node(ND_RELEASE, tok); + tok = skip(tok->next, '('); + node->lhs = assign(&tok, tok); + add_type(node->lhs); + node->ty = node->lhs->ty->base; + *rest = skip(tok, ')'); + return node; + } + if (kw == KW___BUILTIN_IA32_MOVNTDQ) { + Node *node = new_node(ND_MOVNTDQ, tok); + tok = skip(tok->next, '('); + node->lhs = assign(&tok, tok); + add_type(node->lhs); + node->ty = node->lhs->ty->base; + tok = skip(tok, ','); + node->rhs = assign(&tok, tok); + add_type(node->rhs); + *rest = skip(tok, ')'); + return node; + } + if (kw == KW___BUILTIN_IA32_PMOVMSKB128) { + Node *node = new_node(ND_PMOVMSKB, tok); + tok = skip(tok->next, '('); + node->lhs = assign(&tok, tok); + add_type(node->lhs); node->ty = node->lhs->ty->base; *rest = skip(tok, ')'); return node; @@ -3690,6 +3746,7 @@ void declare_builtin_functions(void) { Type *pchar = pointer_to(ty_char); builtin_alloca = declare1("alloca", pointer_to(ty_void), ty_int); declare0("trap", ty_int); + declare0("ia32_pause", ty_void); declare0("unreachable", ty_int); declare1("ctz", ty_int, ty_int); declare1("ctzl", ty_int, ty_long); diff --git a/third_party/chibicc/preprocess.c b/third_party/chibicc/preprocess.c index 854ca53d6..ae78c1f01 100644 --- a/third_party/chibicc/preprocess.c +++ b/third_party/chibicc/preprocess.c @@ -1045,12 +1045,16 @@ __UINT32_MAX__\000\ 0xffffffffu\000\ __INT64_MAX__\000\ 0x7fffffffffffffffl\000\ +__INTMAX_MAX__\000\ +0x7fffffffffffffffl\000\ __LONG_MAX__\000\ 0x7fffffffffffffffl\000\ __LONG_LONG_MAX__\000\ 0x7fffffffffffffffl\000\ __UINT64_MAX__\000\ 0xfffffffffffffffful\000\ +__UINTMAX_MAX__\000\ +0xfffffffffffffffful\000\ __SIZE_MAX__\000\ 0xfffffffffffffffful\000\ __INTPTR_MAX__\000\ @@ -1103,8 +1107,12 @@ __UINT32_TYPE__\000\ unsigned int\000\ __INT64_TYPE__\000\ long int\000\ +__INTMAX_TYPE__\000\ +long int\000\ __UINT64_TYPE__\000\ long unsigned int\000\ +__UINTMAX_TYPE__\000\ +long unsigned int\000\ __INTMAX_TYPE__\000\ long int\000\ __UINTMAX_TYPE__\000\ @@ -1271,6 +1279,22 @@ __SSE2__\000\ 1\000\ __SSE2_MATH__\000\ 1\000\ +__ATOMIC_ACQUIRE\000\ +2\000\ +__ATOMIC_HLE_RELEASE\000\ +131072\000\ +__ATOMIC_HLE_ACQUIRE\000\ +65536\000\ +__ATOMIC_RELAXED\000\ +0\000\ +__ATOMIC_CONSUME\000\ +1\000\ +__ATOMIC_SEQ_CST\000\ +5\000\ +__ATOMIC_ACQ_REL\000\ +4\000\ +__ATOMIC_RELEASE\000\ +3\000\ \000"; do { val = name + strlen(name) + 1; diff --git a/third_party/chibicc/test/msabi_test.c b/third_party/chibicc/test/msabi_test.c new file mode 100644 index 000000000..ef14721a0 --- /dev/null +++ b/third_party/chibicc/test/msabi_test.c @@ -0,0 +1,6 @@ +#include "third_party/chibicc/test/test.h" + +int (*__attribute__((__ms_abi__)) NtFoo)(int x, int y); + +int main() { +} diff --git a/third_party/chibicc/test/spinlock_test.c b/third_party/chibicc/test/spinlock_test.c new file mode 100644 index 000000000..5e50af42d --- /dev/null +++ b/third_party/chibicc/test/spinlock_test.c @@ -0,0 +1,26 @@ +#include "third_party/chibicc/test/test.h" + +#define SPINLOCK(lock) \ + do { \ + for (;;) { \ + typeof(*(lock)) x; \ + __atomic_load(lock, &x, __ATOMIC_RELAXED); \ + if (!x && !__sync_lock_test_and_set(lock, 1)) { \ + break; \ + } else { \ + __builtin_ia32_pause(); \ + } \ + } \ + } while (0) + +#define SPUNLOCK(lock) __sync_lock_release(lock) + +_Alignas(64) char lock; + +main() { + ASSERT(0, lock); + SPINLOCK(&lock); + ASSERT(1, lock); + SPUNLOCK(&lock); + ASSERT(0, lock); +} diff --git a/third_party/chibicc/test/vector_test.c b/third_party/chibicc/test/vector_test.c index a09b88cda..ea8160bf1 100644 --- a/third_party/chibicc/test/vector_test.c +++ b/third_party/chibicc/test/vector_test.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "third_party/chibicc/test/test.h" +typedef char byte16 __attribute__((__vector_size__(16))); typedef float float4 __attribute__((__vector_size__(16))); typedef float float4a1 __attribute__((__vector_size__(16), __aligned__(1))); typedef float float4a16 __attribute__((__vector_size__(16), __aligned__(16))); @@ -39,18 +40,33 @@ int main(void) { ASSERT(1, _Alignof(double2a1)); ASSERT(16, _Alignof(double2a16)); - float4 v1; - float4 v2; - float x[4] = {1, 2, 3, 4}; - float y[4] = {1, 1, 1, 1}; - memcpy(&v1, x, 16); - memcpy(&v2, y, 16); - v1 = v1 + v2; - memcpy(x, &v1, 16); - ASSERT(2, x[0]); - /* ASSERT(3, x[1]); */ - /* ASSERT(4, x[2]); */ - /* ASSERT(5, x[3]); */ + { + float4 v1; + float4 v2; + float x[4] = {1, 2, 3, 4}; + float y[4] = {1, 1, 1, 1}; + memcpy(&v1, x, 16); + memcpy(&v2, y, 16); + v1 = v1 + v2; + memcpy(x, &v1, 16); + ASSERT(2, x[0]); + // TODO(jart): fix me + /* ASSERT(3, x[1]); */ + /* ASSERT(4, x[2]); */ + /* ASSERT(5, x[3]); */ + } + + { + byte16 v; + float x1[4] = {1, 2, 3, 4}; + float x2[4]; + memcpy(&v, x1, 16); + __builtin_ia32_movntdq(x1, &v); + memcpy(x2, &v, 16); + ASSERT(1, x2[0]); + // TODO(jart): fix me + /* ASSERT(2, x[1]); */ + } return 0; } diff --git a/third_party/chibicc/tokenize.c b/third_party/chibicc/tokenize.c index 3be9520bf..f4954e597 100644 --- a/third_party/chibicc/tokenize.c +++ b/third_party/chibicc/tokenize.c @@ -100,6 +100,7 @@ Token *skip(Token *tok, char op) { if (tok->len == 1 && *tok->loc == op) { return tok->next; } else { + // __die(); error_tok(tok, "expected '%c'", op); } }