Add atomic_exchange

This commit is contained in:
Rui Ueyama 2020-09-15 11:30:56 +09:00
parent ca27455b92
commit 80ea9d427c
6 changed files with 32 additions and 0 deletions

View File

@ -221,6 +221,7 @@ typedef enum {
ND_MEMZERO, // Zero-clear a stack variable
ND_ASM, // "asm"
ND_CAS, // Atomic compare-and-swap
ND_EXCH, // Atomic exchange
} NodeKind;
// AST node type

View File

@ -983,6 +983,16 @@ static void gen_expr(Node *node) {
println(" movzbl %%cl, %%eax");
return;
}
case ND_EXCH: {
gen_expr(node->lhs);
push();
gen_expr(node->rhs);
pop("%rdi");
int sz = node->lhs->ty->base->size;
println(" xchg %s, (%%rdi)", reg_ax(sz));
return;
}
}
switch (node->lhs->ty->kind) {

View File

@ -7,4 +7,7 @@
#define atomic_compare_exchange_strong(p, old, new) \
__builtin_compare_and_swap((p), (old), (new))
#define atomic_exchange(obj, val) __builtin_atomic_exchange(obj, val)
#define atomic_exchange_explicit(obj, val, order) __builtin_atomic_exchange(obj, val)
#endif

10
parse.c
View File

@ -2954,6 +2954,16 @@ static Node *primary(Token **rest, Token *tok) {
return node;
}
if (equal(tok, "__builtin_atomic_exchange")) {
Node *node = new_node(ND_EXCH, tok);
tok = skip(tok->next, "(");
node->lhs = assign(&tok, tok);
tok = skip(tok, ",");
node->rhs = assign(&tok, tok);
*rest = skip(tok, ")");
return node;
}
if (tok->kind == TK_IDENT) {
// Variable or enum constant
VarScope *sc = find_var(tok);

View File

@ -38,6 +38,9 @@ static int add_millions(void) {
int main() {
ASSERT(3*1000*1000, add_millions());
ASSERT(3, ({ int x=3; atomic_exchange(&x, 5); }));
ASSERT(5, ({ int x=3; atomic_exchange(&x, 5); x; }));
printf("OK\n");
return 0;
}

5
type.c
View File

@ -298,5 +298,10 @@ void add_type(Node *node) {
if (node->cas_old->ty->kind != TY_PTR)
error_tok(node->cas_old->tok, "pointer expected");
return;
case ND_EXCH:
if (node->lhs->ty->kind != TY_PTR)
error_tok(node->cas_addr->tok, "pointer expected");
node->ty = node->lhs->ty->base;
return;
}
}