Improve threading support further

This commit is contained in:
Justine Tunney 2022-05-17 04:14:28 -07:00
parent 8bfb70ca3f
commit ce71677156
61 changed files with 882 additions and 747 deletions

View file

@ -2921,6 +2921,7 @@ static void OnMaxpd(struct As *a, struct Slice s) { OpSse(a, 0x660F5F); }
static void OnMaxps(struct As *a, struct Slice s) { OpSse(a, 0x0F5F); }
static void OnMaxsd(struct As *a, struct Slice s) { OpSse(a, 0xF20F5F); }
static void OnMaxss(struct As *a, struct Slice s) { OpSse(a, 0xF30F5F); }
static void OnMfence(struct As *a, struct Slice s) { EmitVarword(a, 0x0faef0); }
static void OnMinpd(struct As *a, struct Slice s) { OpSse(a, 0x660F5D); }
static void OnMinps(struct As *a, struct Slice s) { OpSse(a, 0x0F5D); }
static void OnMinsd(struct As *a, struct Slice s) { OpSse(a, 0xF20F5D); }
@ -3370,6 +3371,7 @@ static const struct Directive8 {
{"maxps", OnMaxps}, //
{"maxsd", OnMaxsd}, //
{"maxss", OnMaxss}, //
{"mfence", OnMfence}, //
{"minpd", OnMinpd}, //
{"minps", OnMinps}, //
{"minsd", OnMinsd}, //

View file

@ -297,62 +297,65 @@ struct Relocation {
};
typedef enum {
ND_NULL_EXPR, // Do nothing
ND_ADD, // +
ND_SUB, // -
ND_MUL, // *
ND_DIV, // /
ND_NEG, // unary -
ND_REM, // %
ND_BINAND, // &
ND_BINOR, // |
ND_BINXOR, // ^
ND_SHL, // <<
ND_SHR, // >>
ND_EQ, // ==
ND_NE, // !=
ND_LT, // <
ND_LE, // <=
ND_ASSIGN, // =
ND_COND, // ?:
ND_COMMA, // ,
ND_MEMBER, // . (struct member access)
ND_ADDR, // unary &
ND_DEREF, // unary *
ND_NOT, // !
ND_BITNOT, // ~
ND_LOGAND, // &&
ND_LOGOR, // ||
ND_RETURN, // "return"
ND_IF, // "if"
ND_FOR, // "for" or "while"
ND_DO, // "do"
ND_SWITCH, // "switch"
ND_CASE, // "case"
ND_BLOCK, // { ... }
ND_GOTO, // "goto"
ND_GOTO_EXPR, // "goto" labels-as-values
ND_LABEL, // Labeled statement
ND_LABEL_VAL, // [GNU] Labels-as-values
ND_FUNCALL, // Function call
ND_EXPR_STMT, // Expression statement
ND_STMT_EXPR, // Statement expression
ND_VAR, // Variable
ND_VLA_PTR, // VLA designator
ND_NUM, // Integer
ND_CAST, // Type cast
ND_MEMZERO, // Zero-clear a stack variable
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_FETCHADD, // Atomic fetch and add
ND_SUBFETCH, // Atomic sub and fetch
ND_FPCLASSIFY, // floating point classify
ND_MOVNTDQ, // Intel MOVNTDQ
ND_PMOVMSKB, // Intel PMOVMSKB
ND_NULL_EXPR, // Do nothing
ND_ADD, // +
ND_SUB, // -
ND_MUL, // *
ND_DIV, // /
ND_NEG, // unary -
ND_REM, // %
ND_BINAND, // &
ND_BINOR, // |
ND_BINXOR, // ^
ND_SHL, // <<
ND_SHR, // >>
ND_EQ, // ==
ND_NE, // !=
ND_LT, // <
ND_LE, // <=
ND_ASSIGN, // =
ND_COND, // ?:
ND_COMMA, // ,
ND_MEMBER, // . (struct member access)
ND_ADDR, // unary &
ND_DEREF, // unary *
ND_NOT, // !
ND_BITNOT, // ~
ND_LOGAND, // &&
ND_LOGOR, // ||
ND_RETURN, // "return"
ND_IF, // "if"
ND_FOR, // "for" or "while"
ND_DO, // "do"
ND_SWITCH, // "switch"
ND_CASE, // "case"
ND_BLOCK, // { ... }
ND_GOTO, // "goto"
ND_GOTO_EXPR, // "goto" labels-as-values
ND_LABEL, // Labeled statement
ND_LABEL_VAL, // [GNU] Labels-as-values
ND_FUNCALL, // Function call
ND_EXPR_STMT, // Expression statement
ND_STMT_EXPR, // Statement expression
ND_VAR, // Variable
ND_VLA_PTR, // VLA designator
ND_NUM, // Integer
ND_CAST, // Type cast
ND_MEMZERO, // Zero-clear a stack variable
ND_ASM, // "asm"
ND_CAS, // Atomic compare-and-swap
ND_EXCH, // Atomic exchange
ND_LOAD, // Atomic load
ND_STORE, // Atomic store
ND_TESTANDSET, // Sync lock test and set
ND_TESTANDSETA, // Atomic lock test and set
ND_CLEAR, // Atomic clear
ND_RELEASE, // Atomic lock release
ND_FETCHADD, // Atomic fetch and add
ND_SUBFETCH, // Atomic sub and fetch
ND_FPCLASSIFY, // floating point classify
ND_MOVNTDQ, // Intel MOVNTDQ
ND_PMOVMSKB, // Intel PMOVMSKB
} NodeKind;
struct Node {
@ -394,6 +397,7 @@ struct Node {
// Assembly
Asm *azm;
// Atomic compare-and-swap
char memorder;
Node *cas_addr;
Node *cas_old;
Node *cas_new;

View file

@ -1547,6 +1547,14 @@ void gen_expr(Node *node) {
println("\txchg\t%s,(%%rdi)", reg_ax(node->ty->size));
return;
}
case ND_TESTANDSETA: {
gen_expr(node->lhs);
push();
println("\tmov\t$1,%%eax");
pop("%rdi");
println("\txchg\t%s,(%%rdi)", reg_ax(node->ty->size));
return;
}
case ND_LOAD: {
gen_expr(node->rhs);
push();
@ -1556,6 +1564,28 @@ void gen_expr(Node *node) {
println("\tmov\t%s,(%%rdi)", reg_ax(node->ty->size));
return;
}
case ND_STORE: {
gen_expr(node->lhs);
push();
gen_expr(node->rhs);
pop("%rdi");
println("\tmov\t(%%rax),%s", reg_ax(node->ty->size));
println("\tmov\t%s,(%%rdi)", reg_ax(node->ty->size));
if (node->memorder) {
println("\tmfence");
}
return;
}
case ND_CLEAR: {
gen_expr(node->lhs);
println("\tmov\t%%rax,%%rdi");
println("\txor\t%%eax,%%eax");
println("\tmov\t%s,(%%rdi)", reg_ax(node->ty->size));
if (node->memorder) {
println("\tmfence");
}
return;
}
case ND_FETCHADD: {
gen_expr(node->lhs);
push();

View file

@ -119,8 +119,11 @@ __builtin_types_compatible_p, KW___BUILTIN_TYPES_COMPATIBLE_P
"->", KW_ARROW
".", KW_DOT
__atomic_load, KW___ATOMIC_LOAD
__atomic_fetch_add, KW___ATOMIC_FETCH_ADD
__atomic_store, KW___ATOMIC_STORE
__atomic_clear, KW___ATOMIC_CLEAR
__atomic_sub_fetch, KW___ATOMIC_SUB_FETCH
__atomic_fetch_add, KW___ATOMIC_FETCH_ADD
__atomic_test_and_set, KW___ATOMIC_TEST_AND_SET
__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

View file

@ -112,6 +112,9 @@
#define KW___BUILTIN_IA32_MOVNTDQ 128
#define KW___ATOMIC_FETCH_ADD 129
#define KW___ATOMIC_SUB_FETCH 130
#define KW___ATOMIC_TEST_AND_SET 131
#define KW___ATOMIC_CLEAR 132
#define KW___ATOMIC_STORE 133
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_

View file

@ -37,44 +37,44 @@
#line 10 "kw.gperf"
struct thatispacked KwSlot { char *name; unsigned char code; };
#define TOTAL_KEYWORDS 116
#define TOTAL_KEYWORDS 119
#define MIN_WORD_LENGTH 1
#define MAX_WORD_LENGTH 28
#define MIN_HASH_VALUE 1
#define MAX_HASH_VALUE 201
/* maximum key range = 201, duplicates = 0 */
#define MAX_HASH_VALUE 238
/* maximum key range = 238, duplicates = 0 */
static inline unsigned int
hash (register const char *str, register size_t len)
{
static const unsigned char asso_values[] =
{
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
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
239, 239, 239, 115, 239, 239, 239, 239, 50, 239,
110, 105, 100, 5, 239, 0, 95, 239, 239, 239,
10, 239, 239, 239, 239, 239, 0, 239, 239, 239,
239, 239, 45, 239, 239, 239, 0, 239, 239, 239,
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
239, 239, 239, 239, 239, 5, 239, 0, 90, 5,
55, 10, 0, 25, 75, 105, 15, 10, 20, 15,
125, 60, 15, 10, 10, 10, 0, 70, 5, 5,
10, 0, 45, 85, 10, 30, 15, 239, 239, 239,
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
239, 239, 239, 239, 239, 239, 239
};
register unsigned int hval = len;
@ -116,19 +116,21 @@ LookupKw (register const char *str, register size_t len)
{"-", KW_MINUS},
#line 116 "kw.gperf"
{"--", KW_DECREMENT},
{""}, {""},
#line 29 "kw.gperf"
{"const", KW_CONST},
{""}, {""}, {""},
#line 63 "kw.gperf"
{"typeof", KW_TYPEOF},
#line 62 "kw.gperf"
{"typedef", KW_TYPEDEF},
{""}, {""}, {""},
#line 114 "kw.gperf"
{"~", KW_TILDE},
#line 68 "kw.gperf"
{"_Atomic", KW__ATOMIC},
{""}, {""},
#line 29 "kw.gperf"
{"const", KW_CONST},
#line 109 "kw.gperf"
{"+", KW_PLUS},
#line 115 "kw.gperf"
{"++", KW_INCREMENT},
#line 20 "kw.gperf"
{"for", KW_FOR},
{""},
#line 78 "kw.gperf"
{"__restrict", KW_RESTRICT},
#line 22 "kw.gperf"
@ -143,244 +145,261 @@ LookupKw (register const char *str, register size_t len)
{"__VA_OPT__", KW___VA_OPT__},
#line 13 "kw.gperf"
{"struct", KW_STRUCT},
#line 60 "kw.gperf"
{"strpbrk", KW_STRPBRK},
{""}, {""},
#line 31 "kw.gperf"
{"short", KW_SHORT},
#line 28 "kw.gperf"
{"double", KW_DOUBLE},
#line 79 "kw.gperf"
{"__restrict__", KW_RESTRICT},
#line 95 "kw.gperf"
{"__builtin_popcount", KW___BUILTIN_POPCOUNT},
#line 17 "kw.gperf"
{"void", KW_VOID},
#line 69 "kw.gperf"
{"_Bool", KW__BOOL},
#line 109 "kw.gperf"
{"+", KW_PLUS},
#line 115 "kw.gperf"
{"++", KW_INCREMENT},
#line 88 "kw.gperf"
{"__builtin_ffs", KW___BUILTIN_FFS},
#line 118 "kw.gperf"
{"||", KW_LOGOR},
{""},
#line 19 "kw.gperf"
{"else", KW_ELSE},
#line 25 "kw.gperf"
{"while", KW_WHILE},
#line 85 "kw.gperf"
{"__builtin_compare_and_swap", KW___BUILTIN_COMPARE_AND_SWAP},
#line 82 "kw.gperf"
{"__builtin_add_overflow", KW___BUILTIN_ADD_OVERFLOW},
#line 81 "kw.gperf"
{"__typeof", KW_TYPEOF},
#line 31 "kw.gperf"
{"short", KW_SHORT},
#line 61 "kw.gperf"
{"strstr", KW_STRSTR},
#line 79 "kw.gperf"
{"__restrict__", KW_RESTRICT},
#line 67 "kw.gperf"
{"_Alignof", KW__ALIGNOF},
#line 18 "kw.gperf"
{"char", KW_CHAR},
#line 48 "kw.gperf"
{"endif", KW_ENDIF},
#line 114 "kw.gperf"
{"~", KW_TILDE},
#line 68 "kw.gperf"
{"_Atomic", KW__ATOMIC},
#line 88 "kw.gperf"
{"__builtin_ffs", KW___BUILTIN_FFS},
#line 55 "kw.gperf"
{"line", KW_LINE},
#line 86 "kw.gperf"
{"__builtin_constant_p", KW___BUILTIN_CONSTANT_P},
#line 25 "kw.gperf"
{"while", KW_WHILE},
{""},
#line 60 "kw.gperf"
{"strpbrk", KW_STRPBRK},
#line 66 "kw.gperf"
{"_Alignas", KW__ALIGNAS},
#line 47 "kw.gperf"
{"elif", KW_ELIF},
#line 49 "kw.gperf"
{"error", KW_ERROR},
#line 74 "kw.gperf"
{"__alignof__", KW___ALIGNOF__},
#line 101 "kw.gperf"
{"__builtin_strpbrk", KW___BUILTIN_STRPBRK},
{""}, {""}, {""}, {""},
#line 103 "kw.gperf"
{"__builtin_sub_overflow", KW___BUILTIN_SUB_OVERFLOW},
#line 72 "kw.gperf"
{"_Thread_local", KW__THREAD_LOCAL},
#line 96 "kw.gperf"
{"__builtin_popcountl", KW___BUILTIN_POPCOUNTL},
#line 97 "kw.gperf"
{"__builtin_popcountll", KW___BUILTIN_POPCOUNTLL},
#line 56 "kw.gperf"
{"pragma", KW_PRAGMA},
#line 92 "kw.gperf"
{"__builtin_mul_overflow", KW___BUILTIN_MUL_OVERFLOW},
#line 104 "kw.gperf"
{"__builtin_types_compatible_p", KW___BUILTIN_TYPES_COMPATIBLE_P},
#line 82 "kw.gperf"
{"__builtin_add_overflow", KW___BUILTIN_ADD_OVERFLOW},
#line 44 "kw.gperf"
{"register", KW_REGISTER},
{""},
#line 30 "kw.gperf"
{"float", KW_FLOAT},
#line 69 "kw.gperf"
{"_Bool", KW__BOOL},
#line 87 "kw.gperf"
{"__builtin_expect", KW___BUILTIN_EXPECT},
#line 119 "kw.gperf"
{"->", KW_ARROW},
#line 20 "kw.gperf"
{"for", KW_FOR},
#line 47 "kw.gperf"
{"elif", KW_ELIF},
#line 95 "kw.gperf"
{"__builtin_popcount", KW___BUILTIN_POPCOUNT},
{""},
#line 91 "kw.gperf"
{"__builtin_fpclassify", KW___BUILTIN_FPCLASSIFY},
#line 108 "kw.gperf"
{"}", KW_RB},
#line 42 "kw.gperf"
{"default", KW_DEFAULT},
{""},
#line 89 "kw.gperf"
{"__builtin_ffsl", KW___BUILTIN_FFSL},
#line 90 "kw.gperf"
{"__builtin_ffsll", KW___BUILTIN_FFSLL},
{""}, {""}, {""},
#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 124 "kw.gperf"
{"__sync_lock_test_and_set", KW___SYNC_LOCK_TEST_AND_SET},
#line 49 "kw.gperf"
{"error", KW_ERROR},
#line 58 "kw.gperf"
{"strchr", KW_STRCHR},
#line 40 "kw.gperf"
{"defined", KW_DEFINED},
#line 65 "kw.gperf"
{"volatile", KW_VOLATILE},
#line 71 "kw.gperf"
{"_Static_assert", KW__STATIC_ASSERT},
#line 48 "kw.gperf"
{"endif", KW_ENDIF},
#line 16 "kw.gperf"
{"static", KW_STATIC},
{""},
#line 66 "kw.gperf"
{"_Alignas", KW__ALIGNAS},
#line 125 "kw.gperf"
{"__sync_lock_release", KW___SYNC_LOCK_RELEASE},
{""},
#line 39 "kw.gperf"
{"define", KW_DEFINE},
{""},
#line 35 "kw.gperf"
{"continue", KW_CONTINUE},
#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 103 "kw.gperf"
{"__builtin_sub_overflow", KW___BUILTIN_SUB_OVERFLOW},
#line 72 "kw.gperf"
{"_Thread_local", KW__THREAD_LOCAL},
#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 92 "kw.gperf"
{"__builtin_mul_overflow", KW___BUILTIN_MUL_OVERFLOW},
#line 81 "kw.gperf"
{"__typeof", KW_TYPEOF},
{""},
#line 32 "kw.gperf"
{"signed", KW_SIGNED},
#line 86 "kw.gperf"
{"__builtin_constant_p", KW___BUILTIN_CONSTANT_P},
#line 108 "kw.gperf"
{"}", KW_RB},
#line 101 "kw.gperf"
{"__builtin_strpbrk", KW___BUILTIN_STRPBRK},
#line 104 "kw.gperf"
{"__builtin_types_compatible_p", KW___BUILTIN_TYPES_COMPATIBLE_P},
#line 89 "kw.gperf"
{"__builtin_ffsl", KW___BUILTIN_FFSL},
#line 90 "kw.gperf"
{"__builtin_ffsll", KW___BUILTIN_FFSLL},
{""}, {""}, {""},
#line 96 "kw.gperf"
{"__builtin_popcountl", KW___BUILTIN_POPCOUNTL},
#line 97 "kw.gperf"
{"__builtin_popcountll", KW___BUILTIN_POPCOUNTLL},
#line 85 "kw.gperf"
{"__builtin_compare_and_swap", KW___BUILTIN_COMPARE_AND_SWAP},
{""},
#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 17 "kw.gperf"
{"void", KW_VOID},
#line 64 "kw.gperf"
{"undef", KW_UNDEF},
#line 28 "kw.gperf"
{"double", KW_DOUBLE},
{""},
#line 70 "kw.gperf"
{"_Generic", KW__GENERIC},
#line 43 "kw.gperf"
{"auto", KW_AUTO},
{""},
#line 58 "kw.gperf"
{"strchr", KW_STRCHR},
{""},
#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"
{"int", KW_INT},
#line 39 "kw.gperf"
{"define", KW_DEFINE},
{""},
#line 37 "kw.gperf"
{"ifdef", KW_IFDEF},
#line 59 "kw.gperf"
{"strlen", KW_STRLEN},
#line 57 "kw.gperf"
{"restrict", KW_RESTRICT},
{""}, {""},
#line 16 "kw.gperf"
{"static", KW_STATIC},
{""},
#line 35 "kw.gperf"
{"continue", KW_CONTINUE},
#line 127 "kw.gperf"
{"__sync_lock_test_and_set", KW___SYNC_LOCK_TEST_AND_SET},
#line 30 "kw.gperf"
{"float", KW_FLOAT},
#line 56 "kw.gperf"
{"pragma", KW_PRAGMA},
{""},
#line 94 "kw.gperf"
{"__builtin_offsetof", KW___BUILTIN_OFFSETOF},
#line 34 "kw.gperf"
{"enum", KW_ENUM},
{""},
#line 27 "kw.gperf"
{"switch", KW_SWITCH},
#line 93 "kw.gperf"
{"__builtin_neg_overflow", KW___BUILTIN_NEG_OVERFLOW},
#line 57 "kw.gperf"
{"restrict", KW_RESTRICT},
#line 51 "kw.gperf"
{"goto", KW_GOTO},
#line 128 "kw.gperf"
{"__sync_lock_release", KW___SYNC_LOCK_RELEASE},
{""},
#line 111 "kw.gperf"
{"&", KW_AMP},
#line 117 "kw.gperf"
{"&&", KW_LOGAND},
#line 80 "kw.gperf"
{"__thread", KW__THREAD_LOCAL},
#line 45 "kw.gperf"
{"__attribute__", KW___ATTRIBUTE__},
#line 51 "kw.gperf"
{"goto", KW_GOTO},
{""}, {""},
#line 12 "kw.gperf"
{"if", KW_IF},
#line 54 "kw.gperf"
{"int", KW_INT},
#line 122 "kw.gperf"
{"__atomic_store", KW___ATOMIC_STORE},
#line 37 "kw.gperf"
{"ifdef", KW_IFDEF},
#line 126 "kw.gperf"
{"__atomic_test_and_set", KW___ATOMIC_TEST_AND_SET},
#line 84 "kw.gperf"
{"__atomic_exchange", KW___ATOMIC_EXCHANGE},
#line 65 "kw.gperf"
{"volatile", KW_VOLATILE},
{""}, {""}, {""},
#line 21 "kw.gperf"
{"do", KW_DO},
{""},
#line 71 "kw.gperf"
{"_Static_assert", KW__STATIC_ASSERT},
{""},
#line 38 "kw.gperf"
{"ifndef", KW_IFNDEF},
{""},
#line 23 "kw.gperf"
{"unsigned", KW_UNSIGNED},
{""}, {""},
#line 107 "kw.gperf"
{"{", KW_LB},
#line 24 "kw.gperf"
{"long", KW_LONG},
{""}, {""}, {""}, {""},
#line 123 "kw.gperf"
{"__atomic_clear", KW___ATOMIC_CLEAR},
{""},
#line 32 "kw.gperf"
{"signed", KW_SIGNED},
#line 40 "kw.gperf"
{"defined", KW_DEFINED},
{""}, {""}, {""},
#line 53 "kw.gperf"
{"inline", KW_INLINE},
#line 36 "kw.gperf"
{"include", KW_INCLUDE},
{""}, {""}, {""},
#line 50 "kw.gperf"
{"extern", KW_EXTERN},
#line 52 "kw.gperf"
{"include_next", KW_INCLUDE_NEXT},
{""}, {""}, {""},
#line 100 "kw.gperf"
{"__builtin_strlen", KW___BUILTIN_STRLEN},
#line 126 "kw.gperf"
{"__builtin_ia32_movntdq", KW___BUILTIN_IA32_MOVNTDQ},
{""}, {""}, {""},
#line 120 "kw.gperf"
{".", KW_DOT},
#line 36 "kw.gperf"
{"include", KW_INCLUDE},
#line 122 "kw.gperf"
{"__atomic_fetch_add", KW___ATOMIC_FETCH_ADD},
{""}, {""},
#line 14 "kw.gperf"
{"return", KW_RETURN},
{""}, {""}, {""},
#line 26 "kw.gperf"
{"union", KW_UNION},
#line 127 "kw.gperf"
{""},
#line 23 "kw.gperf"
{"unsigned", KW_UNSIGNED},
#line 46 "kw.gperf"
{"_Noreturn", KW__NORETURN},
{""},
#line 130 "kw.gperf"
{"__builtin_ia32_pmovmskb128", KW___BUILTIN_IA32_PMOVMSKB128},
#line 42 "kw.gperf"
{"default", KW_DEFAULT},
{""},
#line 34 "kw.gperf"
{"enum", KW_ENUM},
{""},
#line 59 "kw.gperf"
{"strlen", KW_STRLEN},
#line 129 "kw.gperf"
{"__builtin_ia32_movntdq", KW___BUILTIN_IA32_MOVNTDQ},
{""},
#line 83 "kw.gperf"
{"__builtin_assume_aligned", KW___BUILTIN_ASSUME_ALIGNED},
{""},
#line 27 "kw.gperf"
{"switch", KW_SWITCH},
{""}, {""}, {""}, {""}, {""},
#line 93 "kw.gperf"
{"__builtin_neg_overflow", KW___BUILTIN_NEG_OVERFLOW},
{""}, {""}, {""},
#line 107 "kw.gperf"
{"{", KW_LB},
{""},
#line 80 "kw.gperf"
{"__thread", KW__THREAD_LOCAL},
{""}, {""}, {""}, {""}, {""}, {""}, {""},
#line 100 "kw.gperf"
{"__builtin_strlen", KW___BUILTIN_STRLEN},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
#line 120 "kw.gperf"
{".", KW_DOT},
{""}, {""}, {""},
#line 33 "kw.gperf"
{"break", KW_BREAK},
{""}, {""}, {""}, {""}, {""},
#line 112 "kw.gperf"
{"*", KW_STAR},
{""},
#line 121 "kw.gperf"
{"__atomic_load", KW___ATOMIC_LOAD},
{""}, {""}, {""}, {""},
#line 44 "kw.gperf"
{"register", KW_REGISTER},
{""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""},
#line 106 "kw.gperf"
{")", KW_RP},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""},
#line 26 "kw.gperf"
{"union", KW_UNION},
{""}, {""}, {""}, {""}, {""},
#line 105 "kw.gperf"
{"(", KW_LP},
{""}, {""}, {""}, {""},
#line 53 "kw.gperf"
{"inline", KW_INLINE},
{""},
#line 123 "kw.gperf"
{"__atomic_sub_fetch", KW___ATOMIC_SUB_FETCH},
{""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
#line 113 "kw.gperf"
{"!", KW_EXCLAIM}
{"!", KW_EXCLAIM},
{""},
#line 125 "kw.gperf"
{"__atomic_fetch_add", KW___ATOMIC_FETCH_ADD},
{""}, {""}, {""}, {""},
#line 124 "kw.gperf"
{"__atomic_sub_fetch", KW___ATOMIC_SUB_FETCH}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)

View file

@ -3259,7 +3259,42 @@ static Node *primary(Token **rest, Token *tok) {
tok = skip(tok, ',');
node->rhs = assign(&tok, tok);
tok = skip(tok, ',');
const_expr(&tok, tok);
node->memorder = const_expr(&tok, tok);
*rest = skip(tok, ')');
return node;
}
if (kw == KW___ATOMIC_STORE) {
Node *node = new_node(ND_STORE, 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, ',');
node->memorder = const_expr(&tok, tok);
*rest = skip(tok, ')');
return node;
}
if (kw == KW___ATOMIC_TEST_AND_SET) {
Node *node = new_node(ND_TESTANDSETA, tok);
tok = skip(tok->next, '(');
node->lhs = assign(&tok, tok);
add_type(node->lhs);
node->ty = node->lhs->ty->base;
tok = skip(tok, ',');
node->memorder = const_expr(&tok, tok);
*rest = skip(tok, ')');
return node;
}
if (kw == KW___ATOMIC_CLEAR) {
Node *node = new_node(ND_CLEAR, tok);
tok = skip(tok->next, '(');
node->lhs = assign(&tok, tok);
add_type(node->lhs);
node->ty = node->lhs->ty->base;
tok = skip(tok, ',');
node->memorder = const_expr(&tok, tok);
*rest = skip(tok, ')');
return node;
}

View file

@ -15,12 +15,66 @@
#define SPUNLOCK(lock) __sync_lock_release(lock)
////////////////////////////////////////////////////////////////////////////////
#define SPINLOCK2(lock) \
do { \
for (;;) { \
typeof(*(lock)) x; \
__atomic_load(lock, &x, __ATOMIC_RELAXED); \
if (!x && !__atomic_test_and_set(lock, __ATOMIC_SEQ_CST)) { \
break; \
} else { \
__builtin_ia32_pause(); \
} \
} \
} while (0)
#define SPUNLOCK2(lock) __sync_lock_release(lock)
////////////////////////////////////////////////////////////////////////////////
_Alignas(64) char lock;
main() {
int x, y;
ASSERT(0, lock);
SPINLOCK(&lock);
ASSERT(1, lock);
SPUNLOCK(&lock);
ASSERT(0, lock);
ASSERT(0, lock);
SPINLOCK2(&lock);
ASSERT(1, lock);
SPUNLOCK2(&lock);
ASSERT(0, lock);
x = 0;
y = 7;
ASSERT(0, x);
ASSERT(7, y);
__atomic_store(&x, &y, __ATOMIC_RELAXED);
ASSERT(7, x);
ASSERT(7, y);
x = 0;
y = 7;
ASSERT(0, x);
ASSERT(7, y);
__atomic_store(&x, &y, __ATOMIC_SEQ_CST);
ASSERT(7, x);
ASSERT(7, y);
x = 5;
y = __atomic_test_and_set(&x, __ATOMIC_SEQ_CST);
ASSERT(1, x);
ASSERT(5, y);
x = 5;
__atomic_clear(&x, __ATOMIC_SEQ_CST);
ASSERT(0, x);
//
}

View file

@ -20,7 +20,7 @@
#include "third_party/dlmalloc/dlmalloc.h"
// clang-format off
#define FOOTERS 0
#define FOOTERS 1
#define MSPACES 0
#define HAVE_MMAP 1