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.
Unified · Split
| @@ -5766,6 +5766,7 @@ static void parse_atomic(int atok) · 5765 unmodified lines | ||
| 5766 | 5766 | int mode; |
| 5767 | 5767 | size_t arg; |
| 5768 | 5768 | SValue *call; |
| 5769 | + CType rv; | |
| 5769 | 5770 | CType atom; |
| 5770 | 5771 | static const char *const templates[] = { |
| 5771 | 5772 | /* |
| @@ -5795,6 +5796,8 @@ static void parse_atomic(int atok) · 23 unmodified lines | ||
| 5795 | 5796 | |
| 5796 | 5797 | next(); |
| 5797 | 5798 | |
| 5799 | + memset(&rv, 0, sizeof(rv)); | |
| 5800 | + memset(&atom, 0, sizeof(atom)); | |
| 5798 | 5801 | mode = 0; /* pacify compiler */ |
| 5799 | 5802 | vpush_helper_func(atok); |
| 5800 | 5803 | call = vtop; |
| @@ -5824,7 +5827,7 @@ static void parse_atomic(int atok) · 23 unmodified lines | ||
| 5824 | 5827 | expect_arg("qualified pointer to atomic value", arg); |
| 5825 | 5828 | if ((template[arg] == 'a') && (atom.t & VT_CONSTANT)) |
| 5826 | 5829 | expect_arg("pointer to writable atomic", arg); |
| 5827 | − switch (btype_size(atom.t & VT_BTYPE)) { | |
| 5830 | + switch (type_size(&atom, &(int){0})) { | |
| 5828 | 5831 | case 8: mode = 4; break; |
| 5829 | 5832 | case 4: mode = 3; break; |
| 5830 | 5833 | case 2: mode = 2; break; |
| @@ -5840,8 +5843,13 @@ static void parse_atomic(int atok) · 9 unmodified lines | ||
| 5840 | 5843 | break; |
| 5841 | 5844 | |
| 5842 | 5845 | 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 | + } | |
| 5845 | 5853 | break; |
| 5846 | 5854 | |
| 5847 | 5855 | case 'm': |
| @@ -5865,15 +5873,32 @@ static void parse_atomic(int atok) · 17 unmodified lines | ||
| 5865 | 5873 | |
| 5866 | 5874 | call->sym = external_helper_sym(atok + mode); |
| 5867 | 5875 | gfunc_call(argc); |
| 5868 | − vpushi(0); | |
| 5869 | 5876 | |
| 5870 | 5877 | 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"); | |
| 5876 | 5900 | } |
| 5901 | + vtop->r2 = VT_CONST; | |
| 5877 | 5902 | } |
| 5878 | 5903 | |
| 5879 | 5904 | ST_FUNC void unary(void) |