History

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.

Dmitry Selyutin committed 5 years ago

Commit 47da8e41 parent 82b0af71 file · +34 −9Browse files

Unified · Split

tccgen.c+34−9
@@ -5766,6 +5766,7 @@ static void parse_atomic(int atok) · 5765 unmodified lines
57665766 int mode;
57675767 size_t arg;
57685768 SValue *call;
5769+ CType rv;
57695770 CType atom;
57705771 static const char *const templates[] = {
57715772 /*
@@ -5795,6 +5796,8 @@ static void parse_atomic(int atok) · 23 unmodified lines
57955796
57965797 next();
57975798
5799+ memset(&rv, 0, sizeof(rv));
5800+ memset(&atom, 0, sizeof(atom));
57985801 mode = 0; /* pacify compiler */
57995802 vpush_helper_func(atok);
58005803 call = vtop;
@@ -5824,7 +5827,7 @@ static void parse_atomic(int atok) · 23 unmodified lines
58245827 expect_arg("qualified pointer to atomic value", arg);
58255828 if ((template[arg] == 'a') && (atom.t & VT_CONSTANT))
58265829 expect_arg("pointer to writable atomic", arg);
5827− switch (btype_size(atom.t & VT_BTYPE)) {
5830+ switch (type_size(&atom, &(int){0})) {
58285831 case 8: mode = 4; break;
58295832 case 4: mode = 3; break;
58305833 case 2: mode = 2; break;
@@ -5840,8 +5843,13 @@ static void parse_atomic(int atok) · 9 unmodified lines
58405843 break;
58415844
58425845 case 'v':
5843− if (!is_integer_btype(vtop->type.t & VT_BTYPE))
5844− expect_arg("integer type", arg);
5846+ if (atom.ref && is_integer_btype(vtop->type.t & VT_BTYPE)) {
5847+ if ((tok != TOK___atomic_store) &&
5848+ (tok != TOK___atomic_load) &&
5849+ (tok != TOK___atomic_exchange) &&
5850+ (tok != TOK___atomic_compare_exchange))
5851+ expect_arg("integer type", arg);
5852+ }
58455853 break;
58465854
58475855 case 'm':
@@ -5865,15 +5873,32 @@ static void parse_atomic(int atok) · 17 unmodified lines
58655873
58665874 call->sym = external_helper_sym(atok + mode);
58675875 gfunc_call(argc);
5868− vpushi(0);
58695876
58705877 switch (template[argc]) {
5871− case 'b': PUT_R_RET(vtop, VT_BOOL); break;
5872− case 'v': PUT_R_RET(vtop, atom.t); break;
5873− case 'p': PUT_R_RET(vtop, VT_SIZE_T); break;
5874− case '?': PUT_R_RET(vtop, VT_VOID); break;
5875− default: tcc_error("incorrect atomic template");
5878+ case 'b':
5879+ vpushi(0);
5880+ PUT_R_RET(vtop, VT_BOOL);
5881+ break;
5882+
5883+ case 'p':
5884+ vpushs(0);
5885+ PUT_R_RET(vtop, VT_SIZE_T);
5886+ break;
5887+
5888+ case 'v':
5889+ vpush(&atom);
5890+ PUT_R_RET(vtop, atom.t);
5891+ break;
5892+
5893+ case '?':
5894+ vpushi(0);
5895+ PUT_R_RET(vtop, VT_VOID);
5896+ break;
5897+
5898+ default:
5899+ tcc_error("incorrect atomic template");
58765900 }
5901+ vtop->r2 = VT_CONST;
58775902 }
58785903
58795904 ST_FUNC void unary(void)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t