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
This commit is contained in:
Justine Tunney 2022-04-17 12:25:10 -07:00
parent ab38f0823d
commit f1dfa4bdfa
17 changed files with 417 additions and 201 deletions

View file

@ -80,6 +80,37 @@ o//examples/hello.com
find o -name \*.com | xargs ls -rShal | less 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 ## Support Vector
| Platform | Min Version | Circa | | Platform | Min Version | Circa |

View file

@ -9,7 +9,7 @@
for (;;) { \ for (;;) { \
typeof(*(lock)) x; \ typeof(*(lock)) x; \
__atomic_load(lock, &x, __ATOMIC_RELAXED); \ __atomic_load(lock, &x, __ATOMIC_RELAXED); \
if (!x && !__sync_lock_test_and_set(lock, __ATOMIC_CONSUME)) { \ if (!x && !__sync_lock_test_and_set(lock, 1)) { \
break; \ break; \
} else { \ } else { \
__builtin_ia32_pause(); \ __builtin_ia32_pause(); \

View file

@ -17,6 +17,7 @@ local enhancements
- support __builtin_constant_p, __builtin_likely, etc. - support __builtin_constant_p, __builtin_likely, etc.
- support __builtin_isunordered, __builtin_islessgreater, etc. - support __builtin_isunordered, __builtin_islessgreater, etc.
- support __builtin_ctz, __builtin_bswap, __builtin_popcount, 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 __force_align_arg_pointer__, __no_caller_saved_registers__, etc.
- support __constructor__, __section__, __cold__, -ffunction-sections, etc. - support __constructor__, __section__, __cold__, -ffunction-sections, etc.
- support building -x assembler-with-cpp a.k.a. .S files - support building -x assembler-with-cpp a.k.a. .S files

View file

@ -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) { static void OpMovdqx(struct As *a, int op) {
OpSseMov(a, op + 0x10, 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 OnPunpckldq(struct As *a, struct Slice s) { OpSse(a, 0x660F62); }
static void OnPunpcklqdq(struct As *a, struct Slice s) { OpSse(a, 0x660F6C); } 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 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 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 OnRcl(struct As *a, struct Slice s) { OpBsu(a, s, 2); }
static void OnRcpps(struct As *a, struct Slice s) { OpSse(a, 0x0F53); } static void OnRcpps(struct As *a, struct Slice s) { OpSse(a, 0x0F53); }
@ -3637,6 +3646,7 @@ static const struct Directive16 {
{"cvttss2si", OnCvttss2si}, // {"cvttss2si", OnCvttss2si}, //
{"cvttss2sil", OnCvttss2si}, // {"cvttss2sil", OnCvttss2si}, //
{"cvttss2siq", OnCvttss2si}, // {"cvttss2siq", OnCvttss2si}, //
{"movntdq", OnMovntdq}, //
{"pcmpistri", OnPcmpistri}, // {"pcmpistri", OnPcmpistri}, //
{"pcmpistrm", OnPcmpistrm}, // {"pcmpistrm", OnPcmpistrm}, //
{"phminposuw", OnPhminposuw}, // {"phminposuw", OnPhminposuw}, //

View file

@ -685,6 +685,7 @@ static void OnCtrlC(int sig, siginfo_t *si, ucontext_t *ctx) {
} }
int chibicc(int argc, char **argv) { int chibicc(int argc, char **argv) {
ShowCrashReports();
atexit(chibicc_cleanup); atexit(chibicc_cleanup);
sigaction(SIGINT, &(struct sigaction){.sa_sigaction = OnCtrlC}, NULL); sigaction(SIGINT, &(struct sigaction){.sa_sigaction = OnCtrlC}, NULL);
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {

View file

@ -345,7 +345,12 @@ typedef enum {
ND_ASM, // "asm" ND_ASM, // "asm"
ND_CAS, // Atomic compare-and-swap ND_CAS, // Atomic compare-and-swap
ND_EXCH, // Atomic exchange 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_FPCLASSIFY, // floating point classify
ND_MOVNTDQ, // Intel MOVNTDQ
ND_PMOVMSKB, // Intel PMOVMSKB
} NodeKind; } NodeKind;
struct Node { struct Node {

View file

@ -904,6 +904,9 @@ static bool gen_builtin_funcall(Node *node, const char *name) {
} else if (!strcmp(name, "trap")) { } else if (!strcmp(name, "trap")) {
emitlin("\tint3"); emitlin("\tint3");
return true; return true;
} else if (!strcmp(name, "ia32_pause")) {
emitlin("\tpause");
return true;
} else if (!strcmp(name, "unreachable")) { } else if (!strcmp(name, "unreachable")) {
emitlin("\tud2"); emitlin("\tud2");
return true; return true;
@ -1521,7 +1524,8 @@ void gen_expr(Node *node) {
emitlin("\tmovzbl\t%cl,%eax"); emitlin("\tmovzbl\t%cl,%eax");
return; return;
} }
case ND_EXCH: { case ND_EXCH:
case ND_TESTANDSET: {
gen_expr(node->lhs); gen_expr(node->lhs);
push(); push();
gen_expr(node->rhs); gen_expr(node->rhs);
@ -1529,6 +1533,23 @@ void gen_expr(Node *node) {
println("\txchg\t%s,(%%rdi)", reg_ax(node->ty->size)); println("\txchg\t%s,(%%rdi)", reg_ax(node->ty->size));
return; 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: case ND_FPCLASSIFY:
gen_fpclassify(node->fpc); gen_fpclassify(node->fpc);
return; return;
@ -1658,6 +1679,14 @@ void gen_expr(Node *node) {
dx = "%edx"; dx = "%edx";
} }
switch (node->kind) { 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: case ND_ADD:
if (node->lhs->ty->kind == TY_INT128) { if (node->lhs->ty->kind == TY_INT128) {
emitlin("\tadd\t%rdi,%rax"); emitlin("\tadd\t%rdi,%rax");

View file

@ -81,7 +81,7 @@ __thread, KW__THREAD_LOCAL
__typeof, KW_TYPEOF __typeof, KW_TYPEOF
__builtin_add_overflow, KW___BUILTIN_ADD_OVERFLOW __builtin_add_overflow, KW___BUILTIN_ADD_OVERFLOW
__builtin_assume_aligned, KW___BUILTIN_ASSUME_ALIGNED __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_compare_and_swap, KW___BUILTIN_COMPARE_AND_SWAP
__builtin_constant_p, KW___BUILTIN_CONSTANT_P __builtin_constant_p, KW___BUILTIN_CONSTANT_P
__builtin_expect, KW___BUILTIN_EXPECT __builtin_expect, KW___BUILTIN_EXPECT
@ -118,3 +118,8 @@ __builtin_types_compatible_p, KW___BUILTIN_TYPES_COMPATIBLE_P
"||", KW_LOGOR "||", KW_LOGOR
"->", KW_ARROW "->", KW_ARROW
".", KW_DOT ".", 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

View file

@ -68,7 +68,7 @@
#define KW___ASM__ 84 #define KW___ASM__ 84
#define KW___BUILTIN_ADD_OVERFLOW 85 #define KW___BUILTIN_ADD_OVERFLOW 85
#define KW___BUILTIN_ASSUME_ALIGNED 86 #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_COMPARE_AND_SWAP 88
#define KW___BUILTIN_CONSTANT_P 89 #define KW___BUILTIN_CONSTANT_P 89
#define KW___BUILTIN_EXPECT 90 #define KW___BUILTIN_EXPECT 90
@ -105,6 +105,11 @@
#define KW_LOGOR 121 #define KW_LOGOR 121
#define KW_ARROW 122 #define KW_ARROW 122
#define KW_DOT 123 #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) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_

View file

@ -1,7 +1,7 @@
/* ANSI-C code produced by gperf version 3.1 */ /* ANSI-C code produced by gperf version 3.1 */
/* Command-line: gperf kw.gperf */ /* Command-line: gperf kw.gperf */
/* Computed positions: -k'1,4,11,14,$' */ /* Computed positions: -k'1,4,11,14,$' */
/* clang-format off */ // clang-format off
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
@ -37,51 +37,44 @@
#line 10 "kw.gperf" #line 10 "kw.gperf"
struct thatispacked KwSlot { char *name; unsigned char code; }; struct thatispacked KwSlot { char *name; unsigned char code; };
#define TOTAL_KEYWORDS 109 #define TOTAL_KEYWORDS 114
#define MIN_WORD_LENGTH 1 #define MIN_WORD_LENGTH 1
#define MAX_WORD_LENGTH 28 #define MAX_WORD_LENGTH 28
#define MIN_HASH_VALUE 1 #define MIN_HASH_VALUE 1
#define MAX_HASH_VALUE 211 #define MAX_HASH_VALUE 201
/* maximum key range = 211, duplicates = 0 */ /* maximum key range = 201, duplicates = 0 */
#ifdef __GNUC__ static inline unsigned int
__inline
#else
#ifdef __cplusplus
inline
#endif
#endif
static unsigned int
hash (register const char *str, register size_t len) hash (register const char *str, register size_t len)
{ {
static const unsigned char asso_values[] = static const unsigned char asso_values[] =
{ {
212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
212, 212, 212, 105, 212, 212, 212, 212, 65, 212, 202, 202, 202, 100, 202, 202, 202, 202, 65, 202,
100, 95, 90, 15, 212, 0, 80, 212, 212, 212, 95, 90, 85, 15, 202, 0, 75, 202, 202, 202,
212, 212, 212, 212, 212, 212, 5, 212, 212, 212, 0, 202, 202, 202, 202, 202, 10, 202, 202, 202,
212, 212, 65, 212, 212, 212, 0, 212, 212, 212, 202, 202, 55, 202, 202, 202, 0, 202, 202, 202,
212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
212, 212, 212, 212, 212, 5, 212, 20, 50, 0, 202, 202, 202, 202, 202, 5, 202, 0, 50, 0,
5, 15, 0, 25, 40, 90, 60, 0, 20, 15, 5, 15, 0, 40, 45, 115, 60, 5, 20, 15,
85, 105, 0, 25, 55, 10, 0, 65, 5, 0, 90, 85, 0, 0, 55, 10, 0, 65, 5, 0,
0, 10, 0, 30, 10, 25, 5, 212, 212, 212, 0, 10, 25, 70, 35, 30, 5, 202, 202, 202,
212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
212, 212, 212, 212, 212, 212, 212 202, 202, 202, 202, 202, 202, 202
}; };
register unsigned int hval = len; register unsigned int hval = len;
@ -135,24 +128,23 @@ LookupKw (register const char *str, register size_t len)
{"~", KW_TILDE}, {"~", KW_TILDE},
#line 68 "kw.gperf" #line 68 "kw.gperf"
{"_Atomic", KW__ATOMIC}, {"_Atomic", KW__ATOMIC},
#line 81 "kw.gperf" {""}, {""},
{"__typeof", KW_TYPEOF},
{""},
#line 78 "kw.gperf" #line 78 "kw.gperf"
{"__restrict", KW_RESTRICT}, {"__restrict", KW_RESTRICT},
#line 22 "kw.gperf" #line 22 "kw.gperf"
{"sizeof", KW_SIZEOF}, {"sizeof", KW_SIZEOF},
#line 75 "kw.gperf" #line 75 "kw.gperf"
{"__asm__", KW___ASM__}, {"__asm__", KW___ASM__},
{""}, #line 41 "kw.gperf"
{"asm", KW_ASM},
#line 15 "kw.gperf" #line 15 "kw.gperf"
{"case", KW_CASE}, {"case", KW_CASE},
#line 73 "kw.gperf" #line 73 "kw.gperf"
{"__VA_OPT__", KW___VA_OPT__}, {"__VA_OPT__", KW___VA_OPT__},
#line 13 "kw.gperf" #line 13 "kw.gperf"
{"struct", KW_STRUCT}, {"struct", KW_STRUCT},
#line 118 "kw.gperf" #line 60 "kw.gperf"
{"||", KW_LOGOR}, {"strpbrk", KW_STRPBRK},
{""}, {""}, {""}, {""},
#line 31 "kw.gperf" #line 31 "kw.gperf"
{"short", KW_SHORT}, {"short", KW_SHORT},
@ -178,22 +170,19 @@ LookupKw (register const char *str, register size_t len)
{"while", KW_WHILE}, {"while", KW_WHILE},
#line 85 "kw.gperf" #line 85 "kw.gperf"
{"__builtin_compare_and_swap", KW___BUILTIN_COMPARE_AND_SWAP}, {"__builtin_compare_and_swap", KW___BUILTIN_COMPARE_AND_SWAP},
#line 101 "kw.gperf" #line 82 "kw.gperf"
{"__builtin_strpbrk", KW___BUILTIN_STRPBRK}, {"__builtin_add_overflow", KW___BUILTIN_ADD_OVERFLOW},
#line 41 "kw.gperf" #line 81 "kw.gperf"
{"asm", KW_ASM}, {"__typeof", KW_TYPEOF},
#line 55 "kw.gperf" #line 55 "kw.gperf"
{"line", KW_LINE}, {"line", KW_LINE},
#line 86 "kw.gperf" #line 86 "kw.gperf"
{"__builtin_constant_p", KW___BUILTIN_CONSTANT_P}, {"__builtin_constant_p", KW___BUILTIN_CONSTANT_P},
#line 74 "kw.gperf" #line 74 "kw.gperf"
{"__alignof__", KW___ALIGNOF__}, {"__alignof__", KW___ALIGNOF__},
#line 60 "kw.gperf" #line 101 "kw.gperf"
{"strpbrk", KW_STRPBRK}, {"__builtin_strpbrk", KW___BUILTIN_STRPBRK},
{""}, {""}, {""}, {""}, {""},
#line 47 "kw.gperf"
{"elif", KW_ELIF},
{""}, {""},
#line 103 "kw.gperf" #line 103 "kw.gperf"
{"__builtin_sub_overflow", KW___BUILTIN_SUB_OVERFLOW}, {"__builtin_sub_overflow", KW___BUILTIN_SUB_OVERFLOW},
#line 72 "kw.gperf" #line 72 "kw.gperf"
@ -202,8 +191,8 @@ LookupKw (register const char *str, register size_t len)
{"__builtin_popcountl", KW___BUILTIN_POPCOUNTL}, {"__builtin_popcountl", KW___BUILTIN_POPCOUNTL},
#line 97 "kw.gperf" #line 97 "kw.gperf"
{"__builtin_popcountll", KW___BUILTIN_POPCOUNTLL}, {"__builtin_popcountll", KW___BUILTIN_POPCOUNTLL},
#line 108 "kw.gperf" #line 56 "kw.gperf"
{"}", KW_RB}, {"pragma", KW_PRAGMA},
#line 92 "kw.gperf" #line 92 "kw.gperf"
{"__builtin_mul_overflow", KW___BUILTIN_MUL_OVERFLOW}, {"__builtin_mul_overflow", KW___BUILTIN_MUL_OVERFLOW},
#line 104 "kw.gperf" #line 104 "kw.gperf"
@ -213,15 +202,16 @@ LookupKw (register const char *str, register size_t len)
{"float", KW_FLOAT}, {"float", KW_FLOAT},
#line 87 "kw.gperf" #line 87 "kw.gperf"
{"__builtin_expect", KW___BUILTIN_EXPECT}, {"__builtin_expect", KW___BUILTIN_EXPECT},
#line 82 "kw.gperf" #line 119 "kw.gperf"
{"__builtin_add_overflow", KW___BUILTIN_ADD_OVERFLOW}, {"->", KW_ARROW},
#line 20 "kw.gperf" #line 20 "kw.gperf"
{"for", KW_FOR}, {"for", KW_FOR},
{""}, #line 47 "kw.gperf"
{"elif", KW_ELIF},
#line 91 "kw.gperf" #line 91 "kw.gperf"
{"__builtin_fpclassify", KW___BUILTIN_FPCLASSIFY}, {"__builtin_fpclassify", KW___BUILTIN_FPCLASSIFY},
#line 107 "kw.gperf" #line 108 "kw.gperf"
{"{", KW_LB}, {"}", KW_RB},
#line 42 "kw.gperf" #line 42 "kw.gperf"
{"default", KW_DEFAULT}, {"default", KW_DEFAULT},
{""}, {""},
@ -229,21 +219,19 @@ LookupKw (register const char *str, register size_t len)
{"__builtin_ffsl", KW___BUILTIN_FFSL}, {"__builtin_ffsl", KW___BUILTIN_FFSL},
#line 90 "kw.gperf" #line 90 "kw.gperf"
{"__builtin_ffsll", KW___BUILTIN_FFSLL}, {"__builtin_ffsll", KW___BUILTIN_FFSLL},
#line 56 "kw.gperf" {""}, {""}, {""},
{"pragma", KW_PRAGMA},
#line 119 "kw.gperf"
{"->", KW_ARROW},
{""},
#line 18 "kw.gperf" #line 18 "kw.gperf"
{"char", KW_CHAR}, {"char", KW_CHAR},
#line 64 "kw.gperf" #line 64 "kw.gperf"
{"undef", KW_UNDEF}, {"undef", KW_UNDEF},
#line 61 "kw.gperf" #line 61 "kw.gperf"
{"strstr", KW_STRSTR}, {"strstr", KW_STRSTR},
{""}, #line 118 "kw.gperf"
{"||", KW_LOGOR},
#line 67 "kw.gperf" #line 67 "kw.gperf"
{"_Alignof", KW__ALIGNOF}, {"_Alignof", KW__ALIGNOF},
{""}, #line 122 "kw.gperf"
{"__sync_lock_test_and_set", KW___SYNC_LOCK_TEST_AND_SET},
#line 49 "kw.gperf" #line 49 "kw.gperf"
{"error", KW_ERROR}, {"error", KW_ERROR},
#line 58 "kw.gperf" #line 58 "kw.gperf"
@ -261,19 +249,53 @@ LookupKw (register const char *str, register size_t len)
{""}, {""},
#line 66 "kw.gperf" #line 66 "kw.gperf"
{"_Alignas", KW__ALIGNAS}, {"_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" #line 39 "kw.gperf"
{"define", KW_DEFINE}, {"define", KW_DEFINE},
{""}, {""},
#line 35 "kw.gperf" #line 35 "kw.gperf"
{"continue", KW_CONTINUE}, {"continue", KW_CONTINUE},
#line 24 "kw.gperf" #line 43 "kw.gperf"
{"long", KW_LONG}, {"auto", KW_AUTO},
{""}, {""},
#line 99 "kw.gperf" #line 99 "kw.gperf"
{"__builtin_strchr", KW___BUILTIN_STRCHR}, {"__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" #line 12 "kw.gperf"
{"if", KW_IF}, {"if", KW_IF},
#line 54 "kw.gperf" #line 54 "kw.gperf"
@ -281,37 +303,11 @@ LookupKw (register const char *str, register size_t len)
{""}, {""},
#line 37 "kw.gperf" #line 37 "kw.gperf"
{"ifdef", KW_IFDEF}, {"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" #line 59 "kw.gperf"
{"strlen", KW_STRLEN}, {"strlen", KW_STRLEN},
#line 52 "kw.gperf" {""},
{"include_next", KW_INCLUDE_NEXT}, #line 94 "kw.gperf"
#line 70 "kw.gperf" {"__builtin_offsetof", KW___BUILTIN_OFFSETOF},
{"_Generic", KW__GENERIC},
#line 34 "kw.gperf" #line 34 "kw.gperf"
{"enum", KW_ENUM}, {"enum", KW_ENUM},
{""}, {""},
@ -319,62 +315,65 @@ LookupKw (register const char *str, register size_t len)
{"switch", KW_SWITCH}, {"switch", KW_SWITCH},
#line 93 "kw.gperf" #line 93 "kw.gperf"
{"__builtin_neg_overflow", KW___BUILTIN_NEG_OVERFLOW}, {"__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" #line 57 "kw.gperf"
{"restrict", KW_RESTRICT}, {"restrict", KW_RESTRICT},
#line 43 "kw.gperf" #line 51 "kw.gperf"
{"auto", KW_AUTO}, {"goto", KW_GOTO},
{""}, {""},
#line 111 "kw.gperf" #line 111 "kw.gperf"
{"&", KW_AMP}, {"&", KW_AMP},
#line 117 "kw.gperf" #line 117 "kw.gperf"
{"&&", KW_LOGAND}, {"&&", KW_LOGAND},
#line 76 "kw.gperf" #line 80 "kw.gperf"
{"__inline", KW_INLINE}, {"__thread", KW__THREAD_LOCAL},
#line 51 "kw.gperf" {""}, {""},
{"goto", KW_GOTO}, #line 38 "kw.gperf"
{""}, {""}, {""}, {"ifndef", KW_IFNDEF},
{""},
#line 23 "kw.gperf" #line 23 "kw.gperf"
{"unsigned", KW_UNSIGNED}, {"unsigned", KW_UNSIGNED},
{""}, {""}, {""}, {""},
#line 107 "kw.gperf"
{"{", KW_LB},
#line 52 "kw.gperf"
{"include_next", KW_INCLUDE_NEXT},
{""}, {""}, {""},
#line 100 "kw.gperf" #line 100 "kw.gperf"
{"__builtin_strlen", KW___BUILTIN_STRLEN}, {"__builtin_strlen", KW___BUILTIN_STRLEN},
{""}, #line 124 "kw.gperf"
#line 94 "kw.gperf" {"__builtin_ia32_movntdq", KW___BUILTIN_IA32_MOVNTDQ},
{"__builtin_offsetof", KW___BUILTIN_OFFSETOF}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, #line 120 "kw.gperf"
{".", KW_DOT},
#line 36 "kw.gperf"
{"include", KW_INCLUDE},
{""}, {""}, {""},
#line 14 "kw.gperf" #line 14 "kw.gperf"
{"return", KW_RETURN}, {"return", KW_RETURN},
{""}, {""}, {""}, {""}, {""}, {""},
#line 26 "kw.gperf" #line 26 "kw.gperf"
{"union", KW_UNION}, {"union", KW_UNION},
{""}, {""}, {""}, {""}, {""}, #line 125 "kw.gperf"
#line 120 "kw.gperf" {"__builtin_ia32_pmovmskb128", KW___BUILTIN_IA32_PMOVMSKB128},
{".", KW_DOT},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
#line 53 "kw.gperf" #line 112 "kw.gperf"
{"inline", KW_INLINE}, {"*", KW_STAR},
{""}, {""}, {""}, {""}, {""}, {""}, {""},
#line 121 "kw.gperf"
{"__atomic_load", KW___ATOMIC_LOAD},
{""}, {""}, {""}, {""},
#line 44 "kw.gperf" #line 44 "kw.gperf"
{"register", KW_REGISTER}, {"register", KW_REGISTER},
{""}, {""}, {""}, {""},
#line 112 "kw.gperf"
{"*", KW_STAR},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
#line 106 "kw.gperf" #line 106 "kw.gperf"
{")", KW_RP}, {")", KW_RP},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
#line 105 "kw.gperf" #line 105 "kw.gperf"
{"(", KW_LP}, {"(", KW_LP},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
#line 53 "kw.gperf"
{"inline", KW_INLINE},
{""}, {""}, {""}, {""},
#line 113 "kw.gperf" #line 113 "kw.gperf"
{"!", KW_EXCLAIM} {"!", KW_EXCLAIM}
}; };

View file

@ -976,11 +976,12 @@ static Type *type_suffix(Token **rest, Token *tok, Type *ty) {
return ty; return ty;
} }
// pointers = ("*" ("const" | "volatile" | "restrict")*)* // pointers = ("*" ("const" | "volatile" | "restrict" | attribute)*)*
static Type *pointers(Token **rest, Token *tok, Type *ty) { static Type *pointers(Token **rest, Token *tok, Type *ty) {
while (CONSUME(&tok, tok, "*")) { while (CONSUME(&tok, tok, "*")) {
ty = pointer_to(ty); ty = pointer_to(ty);
for (;;) { for (;;) {
tok = attribute_list(tok, ty, type_attributes);
if (EQUAL(tok, "const")) { if (EQUAL(tok, "const")) {
ty->is_const = true; ty->is_const = true;
tok = tok->next; tok = tok->next;
@ -3218,12 +3219,67 @@ static Node *primary(Token **rest, Token *tok) {
node->ty = node->cas_addr->ty->base; node->ty = node->cas_addr->ty->base;
return node; return node;
} }
if (kw == KW___BUILTIN_ATOMIC_EXCHANGE) { if (kw == KW___ATOMIC_EXCHANGE) {
Node *node = new_node(ND_EXCH, tok); Node *node = new_node(ND_EXCH, tok);
tok = skip(tok->next, '('); tok = skip(tok->next, '(');
node->lhs = assign(&tok, tok); node->lhs = assign(&tok, tok);
add_type(node->lhs);
node->ty = node->lhs->ty->base;
tok = skip(tok, ','); tok = skip(tok, ',');
node->rhs = assign(&tok, 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; node->ty = node->lhs->ty->base;
*rest = skip(tok, ')'); *rest = skip(tok, ')');
return node; return node;
@ -3690,6 +3746,7 @@ void declare_builtin_functions(void) {
Type *pchar = pointer_to(ty_char); Type *pchar = pointer_to(ty_char);
builtin_alloca = declare1("alloca", pointer_to(ty_void), ty_int); builtin_alloca = declare1("alloca", pointer_to(ty_void), ty_int);
declare0("trap", ty_int); declare0("trap", ty_int);
declare0("ia32_pause", ty_void);
declare0("unreachable", ty_int); declare0("unreachable", ty_int);
declare1("ctz", ty_int, ty_int); declare1("ctz", ty_int, ty_int);
declare1("ctzl", ty_int, ty_long); declare1("ctzl", ty_int, ty_long);

View file

@ -1045,12 +1045,16 @@ __UINT32_MAX__\000\
0xffffffffu\000\ 0xffffffffu\000\
__INT64_MAX__\000\ __INT64_MAX__\000\
0x7fffffffffffffffl\000\ 0x7fffffffffffffffl\000\
__INTMAX_MAX__\000\
0x7fffffffffffffffl\000\
__LONG_MAX__\000\ __LONG_MAX__\000\
0x7fffffffffffffffl\000\ 0x7fffffffffffffffl\000\
__LONG_LONG_MAX__\000\ __LONG_LONG_MAX__\000\
0x7fffffffffffffffl\000\ 0x7fffffffffffffffl\000\
__UINT64_MAX__\000\ __UINT64_MAX__\000\
0xfffffffffffffffful\000\ 0xfffffffffffffffful\000\
__UINTMAX_MAX__\000\
0xfffffffffffffffful\000\
__SIZE_MAX__\000\ __SIZE_MAX__\000\
0xfffffffffffffffful\000\ 0xfffffffffffffffful\000\
__INTPTR_MAX__\000\ __INTPTR_MAX__\000\
@ -1103,8 +1107,12 @@ __UINT32_TYPE__\000\
unsigned int\000\ unsigned int\000\
__INT64_TYPE__\000\ __INT64_TYPE__\000\
long int\000\ long int\000\
__INTMAX_TYPE__\000\
long int\000\
__UINT64_TYPE__\000\ __UINT64_TYPE__\000\
long unsigned int\000\ long unsigned int\000\
__UINTMAX_TYPE__\000\
long unsigned int\000\
__INTMAX_TYPE__\000\ __INTMAX_TYPE__\000\
long int\000\ long int\000\
__UINTMAX_TYPE__\000\ __UINTMAX_TYPE__\000\
@ -1271,6 +1279,22 @@ __SSE2__\000\
1\000\ 1\000\
__SSE2_MATH__\000\ __SSE2_MATH__\000\
1\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"; \000";
do { do {
val = name + strlen(name) + 1; val = name + strlen(name) + 1;

6
third_party/chibicc/test/msabi_test.c vendored Normal file
View file

@ -0,0 +1,6 @@
#include "third_party/chibicc/test/test.h"
int (*__attribute__((__ms_abi__)) NtFoo)(int x, int y);
int main() {
}

View file

@ -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);
}

View file

@ -18,6 +18,7 @@
*/ */
#include "third_party/chibicc/test/test.h" #include "third_party/chibicc/test/test.h"
typedef char byte16 __attribute__((__vector_size__(16)));
typedef float float4 __attribute__((__vector_size__(16))); typedef float float4 __attribute__((__vector_size__(16)));
typedef float float4a1 __attribute__((__vector_size__(16), __aligned__(1))); typedef float float4a1 __attribute__((__vector_size__(16), __aligned__(1)));
typedef float float4a16 __attribute__((__vector_size__(16), __aligned__(16))); typedef float float4a16 __attribute__((__vector_size__(16), __aligned__(16)));
@ -39,6 +40,7 @@ int main(void) {
ASSERT(1, _Alignof(double2a1)); ASSERT(1, _Alignof(double2a1));
ASSERT(16, _Alignof(double2a16)); ASSERT(16, _Alignof(double2a16));
{
float4 v1; float4 v1;
float4 v2; float4 v2;
float x[4] = {1, 2, 3, 4}; float x[4] = {1, 2, 3, 4};
@ -48,9 +50,23 @@ int main(void) {
v1 = v1 + v2; v1 = v1 + v2;
memcpy(x, &v1, 16); memcpy(x, &v1, 16);
ASSERT(2, x[0]); ASSERT(2, x[0]);
// TODO(jart): fix me
/* ASSERT(3, x[1]); */ /* ASSERT(3, x[1]); */
/* ASSERT(4, x[2]); */ /* ASSERT(4, x[2]); */
/* ASSERT(5, x[3]); */ /* 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; return 0;
} }

View file

@ -100,6 +100,7 @@ Token *skip(Token *tok, char op) {
if (tok->len == 1 && *tok->loc == op) { if (tok->len == 1 && *tok->loc == op) {
return tok->next; return tok->next;
} else { } else {
// __die();
error_tok(tok, "expected '%c'", op); error_tok(tok, "expected '%c'", op);
} }
} }