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. --- tccgen.c | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/tccgen.c b/tccgen.c index 11e6962..e49c1de 100644 --- a/tccgen.c +++ b/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[] = { /* @@ -5824,7 +5825,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 +5841,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 +5871,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) -- 2.30.1 _______________________________________________ Tinycc-devel mailing list Tinycc-devel@nongnu.org https://lists.nongnu.org/mailman/listinfo/tinycc-devel