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