Unified · Split
| @@ -72,57 +72,59 @@ typedef struct { · 71 unmodified lines | ||
| 72 | 72 | #define ATOMIC_FLAG_INIT {0} |
| 73 | 73 | |
| 74 | 74 | #define atomic_flag_test_and_set(object) \ |
| 75 | − __c11_atomic_exchange(&(object)->value, 1, __ATOMIC_SEQ_CST) | |
| 75 | + __atomic_exchange(&(object)->value, 1, __ATOMIC_SEQ_CST) | |
| 76 | 76 | #define atomic_flag_test_and_set_explicit(object, order) \ |
| 77 | − __c11_atomic_exchange(&(object)->value, 1, order) | |
| 77 | + __atomic_exchange(&(object)->value, 1, order) | |
| 78 | 78 | |
| 79 | 79 | #define atomic_flag_clear(object) \ |
| 80 | − __c11_atomic_store(&(object)->value, 0, __ATOMIC_SEQ_CST) | |
| 80 | + __atomic_store(&(object)->value, 0, __ATOMIC_SEQ_CST) | |
| 81 | 81 | #define atomic_flag_clear_explicit(object, order) \ |
| 82 | − __c11_atomic_store(&(object)->value, 0, order) | |
| 82 | + __atomic_store(&(object)->value, 0, order) | |
| 83 | 83 | |
| 84 | 84 | /* Generic routines */ |
| 85 | 85 | #define atomic_init(object, desired) \ |
| 86 | − __c11_atomic_init(object, desired) | |
| 86 | + __atomic_store(object, desired, __ATOMIC_RELAXED) | |
| 87 | 87 | |
| 88 | 88 | #define atomic_store(object, desired) \ |
| 89 | − __c11_atomic_store(object, desired, __ATOMIC_SEQ_CST) | |
| 90 | −#define atomic_store_explicit __c11_atomic_store | |
| 89 | + __atomic_store(object, desired, __ATOMIC_SEQ_CST) | |
| 90 | +#define atomic_store_explicit __atomic_store | |
| 91 | 91 | |
| 92 | 92 | #define atomic_load(object) \ |
| 93 | − __c11_atomic_load(object, __ATOMIC_SEQ_CST) | |
| 94 | −#define atomic_load_explicit __c11_atomic_load | |
| 93 | + __atomic_load(object, __ATOMIC_SEQ_CST) | |
| 94 | +#define atomic_load_explicit __atomic_load | |
| 95 | 95 | |
| 96 | 96 | #define atomic_exchange(object, desired) \ |
| 97 | − __c11_atomic_exchange(object, desired, __ATOMIC_SEQ_CST) | |
| 98 | −#define atomic_exchange_explicit __c11_atomic_exchange | |
| 97 | + __atomic_exchange(object, desired, __ATOMIC_SEQ_CST) | |
| 98 | +#define atomic_exchange_explicit __atomic_exchange | |
| 99 | 99 | |
| 100 | 100 | #define atomic_compare_exchange_strong(object, expected, desired) \ |
| 101 | − __c11_atomic_compare_exchange_strong(object, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) | |
| 102 | −#define atomic_compare_exchange_strong_explicit __c11_atomic_compare_exchange_strong | |
| 101 | + __atomic_compare_exchange(object, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) | |
| 102 | +#define atomic_compare_exchange_strong_explicit(object, expected, desired, success, failure) \ | |
| 103 | + __atomic_compare_exchange(object, expected, desired, 0, success, failure) | |
| 103 | 104 | |
| 104 | 105 | #define atomic_compare_exchange_weak(object, expected, desired) \ |
| 105 | − __c11_atomic_compare_exchange_weak(object, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) | |
| 106 | −#define atomic_compare_exchange_weak_explicit __c11_atomic_compare_exchange_weak | |
| 106 | + __atomic_compare_exchange(object, expected, desired, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) | |
| 107 | +#define atomic_compare_exchange_weak_explicit(object, expected, desired, success, failure) \ | |
| 108 | + __atomic_compare_exchange(object, expected, desired, 1, success, failure) | |
| 107 | 109 | |
| 108 | 110 | #define atomic_fetch_add(object, operand) \ |
| 109 | − __c11_atomic_fetch_add(object, operand, __ATOMIC_SEQ_CST) | |
| 110 | −#define atomic_fetch_add_explicit __c11_atomic_fetch_add | |
| 111 | + __atomic_fetch_add(object, operand, __ATOMIC_SEQ_CST) | |
| 112 | +#define atomic_fetch_add_explicit __atomic_fetch_add | |
| 111 | 113 | |
| 112 | 114 | #define atomic_fetch_sub(object, operand) \ |
| 113 | − __c11_atomic_fetch_sub(object, operand, __ATOMIC_SEQ_CST) | |
| 114 | −#define atomic_fetch_sub_explicit __c11_atomic_fetch_sub | |
| 115 | + __atomic_fetch_sub(object, operand, __ATOMIC_SEQ_CST) | |
| 116 | +#define atomic_fetch_sub_explicit __atomic_fetch_sub | |
| 115 | 117 | |
| 116 | 118 | #define atomic_fetch_or(object, operand) \ |
| 117 | − __c11_atomic_fetch_or(object, operand, __ATOMIC_SEQ_CST) | |
| 118 | −#define atomic_fetch_or_explicit __c11_atomic_fetch_or | |
| 119 | + __atomic_fetch_or(object, operand, __ATOMIC_SEQ_CST) | |
| 120 | +#define atomic_fetch_or_explicit __atomic_fetch_or | |
| 119 | 121 | |
| 120 | 122 | #define atomic_fetch_xor(object, operand) \ |
| 121 | − __c11_atomic_fetch_xor(object, operand, __ATOMIC_SEQ_CST) | |
| 122 | −#define atomic_fetch_xor_explicit __c11_atomic_fetch_xor | |
| 123 | + __atomic_fetch_xor(object, operand, __ATOMIC_SEQ_CST) | |
| 124 | +#define atomic_fetch_xor_explicit __atomic_fetch_xor | |
| 123 | 125 | |
| 124 | 126 | #define atomic_fetch_and(object, operand) \ |
| 125 | − __c11_atomic_fetch_and(object, operand, __ATOMIC_SEQ_CST) | |
| 126 | −#define atomic_fetch_and_explicit __c11_atomic_fetch_and | |
| 127 | + __atomic_fetch_and(object, operand, __ATOMIC_SEQ_CST) | |
| 128 | +#define atomic_fetch_and_explicit __atomic_fetch_and | |
| 127 | 129 | |
| 128 | 130 | #endif /* _STDATOMIC_H */ |
| @@ -5755,94 +5755,86 @@ static inline int is_memory_model(const SValue *sv) · 5754 unmodified lines | ||
| 5755 | 5755 | * Ideally we should check whether the model matches 1:1. |
| 5756 | 5756 | * If it is possible, we should check by the name of the value. |
| 5757 | 5757 | */ |
| 5758 | − return (((sv->type.t & VT_BTYPE) == VT_INT) && (sv->c.i < 6)); | |
| 5758 | + return 1; | |
| 5759 | 5759 | } |
| 5760 | 5760 | |
| 5761 | +#define ATOMIC_ID(ATOK) \ | |
| 5762 | + (ATOK - TOK___atomic_store) | |
| 5763 | + | |
| 5761 | 5764 | static void parse_atomic(int atok) |
| 5762 | 5765 | { |
| 5763 | − size_t op; | |
| 5766 | + int mode; | |
| 5764 | 5767 | size_t arg; |
| 5765 | − size_t argc; | |
| 5766 | − CType *atom = NULL; | |
| 5767 | − char const *params = NULL; | |
| 5768 | − static struct { | |
| 5769 | − int const tok; | |
| 5770 | − char const *const params; | |
| 5771 | − } const ops[] = { | |
| 5768 | + SValue *call; | |
| 5769 | + CType atom = {}; | |
| 5770 | + static const char const *templates[] = { | |
| 5772 | 5771 | /* |
| 5773 | − * a -- atomic | |
| 5774 | − * A -- read-only atomic | |
| 5775 | − * p -- pointer to memory | |
| 5776 | − * P -- pointer to read-only memory | |
| 5777 | − * v -- value | |
| 5778 | − * m -- memory model | |
| 5772 | + * Each entry consists of callback and function template. | |
| 5773 | + * The template represents argument types and return type. | |
| 5774 | + * | |
| 5775 | + * ? void (return-only) | |
| 5776 | + * b bool | |
| 5777 | + * a atomic | |
| 5778 | + * A read-only atomic | |
| 5779 | + * p pointer to memory | |
| 5780 | + * v value | |
| 5781 | + * m memory model | |
| 5779 | 5782 | */ |
| 5780 | − {TOK___c11_atomic_init, "-av"}, | |
| 5781 | − {TOK___c11_atomic_store, "-avm"}, | |
| 5782 | − {TOK___c11_atomic_load, "am"}, | |
| 5783 | − {TOK___c11_atomic_exchange, "avm"}, | |
| 5784 | − {TOK___c11_atomic_compare_exchange_strong, "apvmm"}, | |
| 5785 | − {TOK___c11_atomic_compare_exchange_weak, "apvmm"}, | |
| 5786 | − {TOK___c11_atomic_fetch_add, "avm"}, | |
| 5787 | − {TOK___c11_atomic_fetch_sub, "avm"}, | |
| 5788 | − {TOK___c11_atomic_fetch_or, "avm"}, | |
| 5789 | − {TOK___c11_atomic_fetch_xor, "avm"}, | |
| 5790 | − {TOK___c11_atomic_fetch_and, "avm"}, | |
| 5783 | + [ATOMIC_ID(TOK___atomic_store)] = "avm?", | |
| 5784 | + [ATOMIC_ID(TOK___atomic_load)] = "Amv", | |
| 5785 | + [ATOMIC_ID(TOK___atomic_exchange)] = "avmv", | |
| 5786 | + [ATOMIC_ID(TOK___atomic_compare_exchange)] = "apvbmmb", | |
| 5787 | + [ATOMIC_ID(TOK___atomic_fetch_add)] = "avmv", | |
| 5788 | + [ATOMIC_ID(TOK___atomic_fetch_sub)] = "avmv", | |
| 5789 | + [ATOMIC_ID(TOK___atomic_fetch_or)] = "avmv", | |
| 5790 | + [ATOMIC_ID(TOK___atomic_fetch_xor)] = "avmv", | |
| 5791 | + [ATOMIC_ID(TOK___atomic_fetch_and)] = "avmv", | |
| 5791 | 5792 | }; |
| 5793 | + const char *template = templates[ATOMIC_ID(atok)]; | |
| 5794 | + const size_t argc = (strlen(template) - 1); | |
| 5792 | 5795 | |
| 5793 | 5796 | next(); |
| 5794 | 5797 | |
| 5795 | − for (op = 0; op < (sizeof(ops) / sizeof(*ops)); ++op) { | |
| 5796 | − if (ops[op].tok == atok) { | |
| 5797 | − params = ops[op].params; | |
| 5798 | − break; | |
| 5799 | − } | |
| 5800 | − } | |
| 5801 | − if (!params) | |
| 5802 | − tcc_error("unknown atomic operation"); | |
| 5803 | − | |
| 5804 | − argc = strlen(params); | |
| 5805 | − if (params[0] == '-') { | |
| 5806 | − ++params; | |
| 5807 | − --argc; | |
| 5808 | − } | |
| 5809 | − | |
| 5810 | − vpushi(0); | |
| 5811 | − vpushi(0); /* function address */ | |
| 5798 | + vpush_helper_func(atok); | |
| 5799 | + call = vtop; | |
| 5812 | 5800 | |
| 5813 | 5801 | skip('('); |
| 5802 | + if ((*template != 'a') && (*template != 'A')) | |
| 5803 | + expect_arg("pointer to atomic", 0); | |
| 5814 | 5804 | for (arg = 0; arg < argc; ++arg) { |
| 5815 | 5805 | expr_eq(); |
| 5816 | 5806 | |
| 5817 | − switch (params[arg]) { | |
| 5807 | + switch (template[arg]) { | |
| 5808 | + case '?': | |
| 5809 | + /* void makes sense only for return value. */ | |
| 5810 | + if (arg != (argc - 1)) | |
| 5811 | + tcc_error("illegal atomic built-in template"); | |
| 5812 | + break; | |
| 5813 | + | |
| 5814 | + case 'b': | |
| 5815 | + break; | |
| 5816 | + | |
| 5818 | 5817 | case 'a': |
| 5819 | 5818 | case 'A': |
| 5820 | − if (atom) | |
| 5821 | − expect_arg("exactly one pointer to atomic", arg); | |
| 5822 | 5819 | if ((vtop->type.t & VT_BTYPE) != VT_PTR) |
| 5823 | − expect_arg("pointer to atomic expected", arg); | |
| 5824 | − atom = pointed_type(&vtop->type); | |
| 5825 | − if (!(atom->t & VT_ATOMIC)) | |
| 5826 | − expect_arg("qualified pointer to atomic", arg); | |
| 5827 | − if ((params[arg] == 'a') && (atom->t & VT_CONSTANT)) | |
| 5820 | + expect_arg("pointer to atomic value", arg); | |
| 5821 | + memcpy(&atom, pointed_type(&vtop->type), sizeof(CType)); | |
| 5822 | + if (!(atom.t & VT_ATOMIC)) | |
| 5823 | + expect_arg("qualified pointer to atomic value", arg); | |
| 5824 | + if ((template[arg] == 'a') && (atom.t & VT_CONSTANT)) | |
| 5828 | 5825 | expect_arg("pointer to writable atomic", arg); |
| 5829 | − atom->t &= ~VT_ATOMIC; | |
| 5830 | − switch (btype_size(atom->t & VT_BTYPE)) { | |
| 5831 | − case 1: atok += 1; break; | |
| 5832 | − case 2: atok += 2; break; | |
| 5833 | − case 4: atok += 3; break; | |
| 5834 | − case 8: atok += 4; break; | |
| 5826 | + switch (btype_size(atom.t & VT_BTYPE)) { | |
| 5827 | + case 8: mode = 4; break; | |
| 5828 | + case 4: mode = 3; break; | |
| 5829 | + case 2: mode = 2; break; | |
| 5830 | + case 1: mode = 1; break; | |
| 5835 | 5831 | default: tcc_error("only integer-sized types are supported"); |
| 5836 | 5832 | } |
| 5837 | − vswap(); | |
| 5838 | − vpop(); | |
| 5839 | − vpush_helper_func(atok); | |
| 5840 | − vswap(); | |
| 5841 | 5833 | break; |
| 5842 | 5834 | |
| 5843 | 5835 | case 'p': |
| 5844 | 5836 | if (((vtop->type.t & VT_BTYPE) != VT_PTR) |
| 5845 | − || !is_compatible_unqualified_types(atom, pointed_type(&vtop->type))) | |
| 5837 | + || !is_compatible_unqualified_types(&atom, pointed_type(&vtop->type))) | |
| 5846 | 5838 | expect_arg("pointer to compatible type", arg); |
| 5847 | 5839 | break; |
| 5848 | 5840 | |
| @@ -5870,7 +5862,17 @@ static void parse_atomic(int atok) · 21 unmodified lines | ||
| 5870 | 5862 | expect("less parameters"); |
| 5871 | 5863 | skip(')'); |
| 5872 | 5864 | |
| 5865 | + call->sym = external_helper_sym(atok + mode); | |
| 5873 | 5866 | gfunc_call(argc); |
| 5867 | + vpushi(0); | |
| 5868 | + | |
| 5869 | + switch (template[argc]) { | |
| 5870 | + case 'b': PUT_R_RET(vtop, VT_BOOL); break; | |
| 5871 | + case 'v': PUT_R_RET(vtop, atom.t); break; | |
| 5872 | + case 'p': PUT_R_RET(vtop, VT_SIZE_T); break; | |
| 5873 | + case '?': PUT_R_RET(vtop, VT_VOID); break; | |
| 5874 | + default: tcc_error("incorrect atomic template"); | |
| 5875 | + } | |
| 5874 | 5876 | } |
| 5875 | 5877 | |
| 5876 | 5878 | ST_FUNC void unary(void) |
| @@ -6255,17 +6257,15 @@ ST_FUNC void unary(void) · 378 unmodified lines | ||
| 6255 | 6257 | #endif |
| 6256 | 6258 | |
| 6257 | 6259 | /* atomic operations */ |
| 6258 | − case TOK___c11_atomic_init: | |
| 6259 | − case TOK___c11_atomic_store: | |
| 6260 | − case TOK___c11_atomic_load: | |
| 6261 | − case TOK___c11_atomic_exchange: | |
| 6262 | − case TOK___c11_atomic_compare_exchange_strong: | |
| 6263 | − case TOK___c11_atomic_compare_exchange_weak: | |
| 6264 | − case TOK___c11_atomic_fetch_add: | |
| 6265 | − case TOK___c11_atomic_fetch_sub: | |
| 6266 | − case TOK___c11_atomic_fetch_or: | |
| 6267 | − case TOK___c11_atomic_fetch_xor: | |
| 6268 | − case TOK___c11_atomic_fetch_and: | |
| 6260 | + case TOK___atomic_store: | |
| 6261 | + case TOK___atomic_load: | |
| 6262 | + case TOK___atomic_exchange: | |
| 6263 | + case TOK___atomic_compare_exchange: | |
| 6264 | + case TOK___atomic_fetch_add: | |
| 6265 | + case TOK___atomic_fetch_sub: | |
| 6266 | + case TOK___atomic_fetch_or: | |
| 6267 | + case TOK___atomic_fetch_xor: | |
| 6268 | + case TOK___atomic_fetch_and: | |
| 6269 | 6269 | parse_atomic(tok); |
| 6270 | 6270 | break; |
| 6271 | 6271 | |
| @@ -174,25 +174,23 @@ · 173 unmodified lines | ||
| 174 | 174 | DEF(TOK_builtin_va_start, "__builtin_va_start") |
| 175 | 175 | #endif |
| 176 | 176 | |
| 177 | −#define DEF_ATOMIC(id, str) \ | |
| 178 | − DEF(id, str) \ | |
| 179 | − DEF(id##_8, str "_8") \ | |
| 180 | − DEF(id##_16, str "_16") \ | |
| 181 | − DEF(id##_32, str "_32") \ | |
| 182 | − DEF(id##_64, str "_64") | |
| 183 | − | |
| 184 | 177 | /* atomic operations */ |
| 185 | − DEF_ATOMIC(TOK___c11_atomic_init, "__c11_atomic_init") | |
| 186 | − DEF_ATOMIC(TOK___c11_atomic_store, "__c11_atomic_store") | |
| 187 | − DEF_ATOMIC(TOK___c11_atomic_load, "__c11_atomic_load") | |
| 188 | − DEF_ATOMIC(TOK___c11_atomic_exchange, "__c11_atomic_exchange") | |
| 189 | − DEF_ATOMIC(TOK___c11_atomic_compare_exchange_strong, "__c11_atomic_compare_exchange_strong") | |
| 190 | − DEF_ATOMIC(TOK___c11_atomic_compare_exchange_weak, "__c11_atomic_compare_exchange_weak") | |
| 191 | − DEF_ATOMIC(TOK___c11_atomic_fetch_add, "__c11_atomic_fetch_add") | |
| 192 | − DEF_ATOMIC(TOK___c11_atomic_fetch_sub, "__c11_atomic_fetch_sub") | |
| 193 | − DEF_ATOMIC(TOK___c11_atomic_fetch_or, "__c11_atomic_fetch_or") | |
| 194 | − DEF_ATOMIC(TOK___c11_atomic_fetch_xor, "__c11_atomic_fetch_xor") | |
| 195 | − DEF_ATOMIC(TOK___c11_atomic_fetch_and, "__c11_atomic_fetch_and") | |
| 178 | +#define DEF_ATOMIC(ID) \ | |
| 179 | + DEF(TOK_##__##ID, "__"#ID) \ | |
| 180 | + DEF(TOK_##__##ID##_1, "__"#ID"_1") \ | |
| 181 | + DEF(TOK_##__##ID##_2, "__"#ID"_2") \ | |
| 182 | + DEF(TOK_##__##ID##_4, "__"#ID"_4") \ | |
| 183 | + DEF(TOK_##__##ID##_8, "__"#ID"_8") | |
| 184 | + | |
| 185 | + DEF_ATOMIC(atomic_store) | |
| 186 | + DEF_ATOMIC(atomic_load) | |
| 187 | + DEF_ATOMIC(atomic_exchange) | |
| 188 | + DEF_ATOMIC(atomic_compare_exchange) | |
| 189 | + DEF_ATOMIC(atomic_fetch_add) | |
| 190 | + DEF_ATOMIC(atomic_fetch_sub) | |
| 191 | + DEF_ATOMIC(atomic_fetch_or) | |
| 192 | + DEF_ATOMIC(atomic_fetch_xor) | |
| 193 | + DEF_ATOMIC(atomic_fetch_and) | |
| 196 | 194 | |
| 197 | 195 | #undef DEF_ATOMIC |
| 198 | 196 | |