mirror of https://github.com/rui314/chibicc
Add atomic_exchange
This commit is contained in:
parent
ca27455b92
commit
80ea9d427c
|
@ -221,6 +221,7 @@ typedef enum {
|
||||||
ND_MEMZERO, // Zero-clear a stack variable
|
ND_MEMZERO, // Zero-clear a stack variable
|
||||||
ND_ASM, // "asm"
|
ND_ASM, // "asm"
|
||||||
ND_CAS, // Atomic compare-and-swap
|
ND_CAS, // Atomic compare-and-swap
|
||||||
|
ND_EXCH, // Atomic exchange
|
||||||
} NodeKind;
|
} NodeKind;
|
||||||
|
|
||||||
// AST node type
|
// AST node type
|
||||||
|
|
10
codegen.c
10
codegen.c
|
@ -983,6 +983,16 @@ static void gen_expr(Node *node) {
|
||||||
println(" movzbl %%cl, %%eax");
|
println(" movzbl %%cl, %%eax");
|
||||||
return;
|
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) {
|
switch (node->lhs->ty->kind) {
|
||||||
|
|
|
@ -7,4 +7,7 @@
|
||||||
#define atomic_compare_exchange_strong(p, old, new) \
|
#define atomic_compare_exchange_strong(p, old, new) \
|
||||||
__builtin_compare_and_swap((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
|
#endif
|
||||||
|
|
10
parse.c
10
parse.c
|
@ -2954,6 +2954,16 @@ static Node *primary(Token **rest, Token *tok) {
|
||||||
return node;
|
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) {
|
if (tok->kind == TK_IDENT) {
|
||||||
// Variable or enum constant
|
// Variable or enum constant
|
||||||
VarScope *sc = find_var(tok);
|
VarScope *sc = find_var(tok);
|
||||||
|
|
|
@ -38,6 +38,9 @@ static int add_millions(void) {
|
||||||
int main() {
|
int main() {
|
||||||
ASSERT(3*1000*1000, add_millions());
|
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");
|
printf("OK\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
5
type.c
5
type.c
|
@ -298,5 +298,10 @@ void add_type(Node *node) {
|
||||||
if (node->cas_old->ty->kind != TY_PTR)
|
if (node->cas_old->ty->kind != TY_PTR)
|
||||||
error_tok(node->cas_old->tok, "pointer expected");
|
error_tok(node->cas_old->tok, "pointer expected");
|
||||||
return;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue