mirror of
https://github.com/mirror/tinycc.git
synced 2024-12-28 04:00:06 +08:00
stdatomic: ld/st/xchg/cmpxchg on simple types
Some complex types can still be small and simple enough to fit into register. Other compilers allow some operations on these types, and it seems to be quite a reasonable choice. From now on, we should be able to compile the following artificial example: struct combo { uint16_t lo; uint16_t hi; }; struct combo load(const _Atomic(struct combo) *atom) { return atomic_load(atom); } void store(_Atomic(struct combo) *atom, struct combo value) { atomic_store(atom, value); } struct combo xchg(_Atomic(struct combo) *atom, struct combo value) { return atomic_exchange(atom, value); } bool cmpxchg(_Atomic(struct combo) *atom, struct combo *cmp, struct combo xchg) { return atomic_compare_exchange_strong(atom, cmp, xchg); } This might be useful for some corner cases, though it is quite likely that many programmers will prefer operating on a single 32-bit value instead of using the structure consisting of 16-bit pair. Things will work as long as the overall structure size happens to be the same as for any integer type we support in atomics.
This commit is contained in:
parent
82b0af7450
commit
47da8e450e
43
tccgen.c
43
tccgen.c
@ -5766,6 +5766,7 @@ static void parse_atomic(int atok)
|
||||
int mode;
|
||||
size_t arg;
|
||||
SValue *call;
|
||||
CType rv;
|
||||
CType atom;
|
||||
static const char *const templates[] = {
|
||||
/*
|
||||
@ -5795,6 +5796,8 @@ static void parse_atomic(int atok)
|
||||
|
||||
next();
|
||||
|
||||
memset(&rv, 0, sizeof(rv));
|
||||
memset(&atom, 0, sizeof(atom));
|
||||
mode = 0; /* pacify compiler */
|
||||
vpush_helper_func(atok);
|
||||
call = vtop;
|
||||
@ -5824,7 +5827,7 @@ static void parse_atomic(int atok)
|
||||
expect_arg("qualified pointer to atomic value", arg);
|
||||
if ((template[arg] == 'a') && (atom.t & VT_CONSTANT))
|
||||
expect_arg("pointer to writable atomic", arg);
|
||||
switch (btype_size(atom.t & VT_BTYPE)) {
|
||||
switch (type_size(&atom, &(int){0})) {
|
||||
case 8: mode = 4; break;
|
||||
case 4: mode = 3; break;
|
||||
case 2: mode = 2; break;
|
||||
@ -5840,8 +5843,13 @@ static void parse_atomic(int atok)
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
if (!is_integer_btype(vtop->type.t & VT_BTYPE))
|
||||
expect_arg("integer type", arg);
|
||||
if (atom.ref && is_integer_btype(vtop->type.t & VT_BTYPE)) {
|
||||
if ((tok != TOK___atomic_store) &&
|
||||
(tok != TOK___atomic_load) &&
|
||||
(tok != TOK___atomic_exchange) &&
|
||||
(tok != TOK___atomic_compare_exchange))
|
||||
expect_arg("integer type", arg);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
@ -5865,15 +5873,32 @@ static void parse_atomic(int atok)
|
||||
|
||||
call->sym = external_helper_sym(atok + mode);
|
||||
gfunc_call(argc);
|
||||
vpushi(0);
|
||||
|
||||
switch (template[argc]) {
|
||||
case 'b': PUT_R_RET(vtop, VT_BOOL); break;
|
||||
case 'v': PUT_R_RET(vtop, atom.t); break;
|
||||
case 'p': PUT_R_RET(vtop, VT_SIZE_T); break;
|
||||
case '?': PUT_R_RET(vtop, VT_VOID); break;
|
||||
default: tcc_error("incorrect atomic template");
|
||||
case 'b':
|
||||
vpushi(0);
|
||||
PUT_R_RET(vtop, VT_BOOL);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
vpushs(0);
|
||||
PUT_R_RET(vtop, VT_SIZE_T);
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
vpush(&atom);
|
||||
PUT_R_RET(vtop, atom.t);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
vpushi(0);
|
||||
PUT_R_RET(vtop, VT_VOID);
|
||||
break;
|
||||
|
||||
default:
|
||||
tcc_error("incorrect atomic template");
|
||||
}
|
||||
vtop->r2 = VT_CONST;
|
||||
}
|
||||
|
||||
ST_FUNC void unary(void)
|
||||
|
Loading…
Reference in New Issue
Block a user