Skip to content

Commit

Permalink
Add atomic_exchange
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed Dec 7, 2020
1 parent ca27455 commit 80ea9d4
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 0 deletions.
1 change: 1 addition & 0 deletions chibicc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
3 changes: 3 additions & 0 deletions include/stdatomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 10 additions & 0 deletions parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions test/atomic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 5 additions & 0 deletions type.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

0 comments on commit 80ea9d4

Please sign in to comment.