| @@ -5160,6 +5160,20 @@ static int parse_btype(CType *type, AttributeDef *ad) · 5159 unmodified lines |
| 5160 | goto basic_type2; | 5160 | goto basic_type2; |
| 5161 | | 5161 | |
| 5162 | /* type modifiers */ | 5162 | /* type modifiers */ |
| | 5163 | case TOK__Atomic: |
| | 5164 | next(); |
| | 5165 | type->t = t; |
| | 5166 | parse_btype_qualify(type, VT_ATOMIC); |
| | 5167 | t = type->t; |
| | 5168 | if (tok == '(') { |
| | 5169 | parse_expr_type(&type1); |
| | 5170 | /* remove all storage modifiers except typedef */ |
| | 5171 | type1.t &= ~(VT_STORAGE&~VT_TYPEDEF); |
| | 5172 | if (type1.ref) |
| | 5173 | sym_to_attr(ad, type1.ref); |
| | 5174 | goto basic_type2; |
| | 5175 | } |
| | 5176 | break; |
| 5163 | case TOK_CONST1: | 5177 | case TOK_CONST1: |
| 5164 | case TOK_CONST2: | 5178 | case TOK_CONST2: |
| 5165 | case TOK_CONST3: | 5179 | case TOK_CONST3: |
| @@ -5515,6 +5529,9 @@ static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td) · 349 unmodified lines |
| 5515 | redo: | 5529 | redo: |
| 5516 | next(); | 5530 | next(); |
| 5517 | switch(tok) { | 5531 | switch(tok) { |
| | 5532 | case TOK__Atomic: |
| | 5533 | qualifiers |= VT_ATOMIC; |
| | 5534 | goto redo; |
| 5518 | case TOK_CONST1: | 5535 | case TOK_CONST1: |
| 5519 | case TOK_CONST2: | 5536 | case TOK_CONST2: |
| 5520 | case TOK_CONST3: | 5537 | case TOK_CONST3: |
| @@ -5710,6 +5727,117 @@ static void parse_builtin_params(int nc, const char *args) · 189 unmodified lines |
| 5710 | nocode_wanted--; | 5727 | nocode_wanted--; |
| 5711 | } | 5728 | } |
| 5712 | | 5729 | |
| | 5730 | static void parse_memory_model(int mtok) |
| | 5731 | { |
| | 5732 | next(); |
| | 5733 | |
| | 5734 | switch (mtok) { |
| | 5735 | case TOK___ATOMIC_RELAXED: vpushs(0); break; |
| | 5736 | case TOK___ATOMIC_CONSUME: vpushs(1); break; |
| | 5737 | case TOK___ATOMIC_ACQUIRE: vpushs(2); break; |
| | 5738 | case TOK___ATOMIC_RELEASE: vpushs(3); break; |
| | 5739 | case TOK___ATOMIC_ACQ_REL: vpushs(4); break; |
| | 5740 | case TOK___ATOMIC_SEQ_CST: vpushs(5); break; |
| | 5741 | } |
| | 5742 | |
| | 5743 | vtop->type.t |= (VT_UNSIGNED | VT_MEMMODEL); |
| | 5744 | } |
| | 5745 | |
| | 5746 | static void parse_atomic(int atok) |
| | 5747 | { |
| | 5748 | size_t arg; |
| | 5749 | size_t argc; |
| | 5750 | int param; |
| | 5751 | char const *params; |
| | 5752 | CType *atom = NULL; |
| | 5753 | |
| | 5754 | next(); |
| | 5755 | |
| | 5756 | /* |
| | 5757 | * a -- atomic |
| | 5758 | * A -- read-only atomic |
| | 5759 | * p -- pointer to memory |
| | 5760 | * P -- pointer to read-only memory |
| | 5761 | * v -- value |
| | 5762 | * m -- memory model |
| | 5763 | */ |
| | 5764 | switch (atok) { |
| | 5765 | case TOK___atomic_init: params = "-a"; break; |
| | 5766 | case TOK___atomic_store: params = "-avm"; break; |
| | 5767 | case TOK___atomic_load: params = "am"; break; |
| | 5768 | case TOK___atomic_exchange: params = "avm"; break; |
| | 5769 | case TOK___atomic_compare_exchange_strong: params = "apvmm"; break; |
| | 5770 | case TOK___atomic_compare_exchange_weak: params = "apvmm"; break; |
| | 5771 | case TOK___atomic_fetch_add: params = "avm"; break; |
| | 5772 | case TOK___atomic_fetch_sub: params = "avm"; break; |
| | 5773 | case TOK___atomic_fetch_or: params = "avm"; break; |
| | 5774 | case TOK___atomic_fetch_xor: params = "avm"; break; |
| | 5775 | case TOK___atomic_fetch_and: params = "avm"; break; |
| | 5776 | } |
| | 5777 | |
| | 5778 | argc = strlen(params); |
| | 5779 | if (params[0] == '-') { |
| | 5780 | ++params; |
| | 5781 | --argc; |
| | 5782 | } |
| | 5783 | |
| | 5784 | skip('('); |
| | 5785 | for (arg = 0; arg < argc; ++arg) { |
| | 5786 | expr_eq(); |
| | 5787 | |
| | 5788 | param = params[arg]; |
| | 5789 | switch (param) { |
| | 5790 | case 'a': |
| | 5791 | case 'A': |
| | 5792 | if (atom) |
| | 5793 | expect_arg("exactly one pointer to atomic", arg); |
| | 5794 | if ((vtop->type.t & VT_BTYPE) != VT_PTR) |
| | 5795 | expect_arg("pointer to atomic expected", arg); |
| | 5796 | atom = pointed_type(&vtop->type); |
| | 5797 | if (!(atom->t & VT_ATOMIC)) |
| | 5798 | expect_arg("qualified pointer to atomic", arg); |
| | 5799 | if ((param == 'a') && (atom->t & VT_CONSTANT)) |
| | 5800 | expect_arg("pointer to writable atomic", arg); |
| | 5801 | if (!is_integer_btype(atom->t & VT_BTYPE)) |
| | 5802 | expect_arg("only atomic integers are supported", arg); |
| | 5803 | atom->t &= ~VT_ATOMIC; |
| | 5804 | break; |
| | 5805 | |
| | 5806 | case 'p': |
| | 5807 | if (((vtop->type.t & VT_BTYPE) != VT_PTR) |
| | 5808 | || !is_compatible_unqualified_types(atom, pointed_type(&vtop->type))) |
| | 5809 | expect_arg("pointer to compatible type", arg); |
| | 5810 | break; |
| | 5811 | |
| | 5812 | case 'v': |
| | 5813 | if (!is_integer_btype(vtop->type.t & VT_BTYPE)) |
| | 5814 | expect_arg("only atomic integers are supported", arg); |
| | 5815 | break; |
| | 5816 | |
| | 5817 | case 'm': |
| | 5818 | if ((vtop->type.t & VT_MEMMODEL) != VT_MEMMODEL) |
| | 5819 | expect_arg("memory model constant", arg); |
| | 5820 | vtop->type.t &= ~VT_MEMMODEL; |
| | 5821 | break; |
| | 5822 | |
| | 5823 | default: |
| | 5824 | tcc_error("unknown parameter type"); |
| | 5825 | } |
| | 5826 | if (tok == ')') |
| | 5827 | break; |
| | 5828 | skip(','); |
| | 5829 | } |
| | 5830 | if (arg < (argc - 1)) |
| | 5831 | expect("more parameters"); |
| | 5832 | if (arg > (argc - 1)) |
| | 5833 | expect("less parameters"); |
| | 5834 | skip(')'); |
| | 5835 | |
| | 5836 | for (arg = 0; arg < (argc - 1); ++arg) |
| | 5837 | vpop(); |
| | 5838 | tcc_error("atomics are not supported yet"); |
| | 5839 | } |
| | 5840 | |
| 5713 | ST_FUNC void unary(void) | 5841 | ST_FUNC void unary(void) |
| 5714 | { | 5842 | { |
| 5715 | int n, t, align, size, r, sizeof_caller; | 5843 | int n, t, align, size, r, sizeof_caller; |
| @@ -6086,6 +6214,31 @@ ST_FUNC void unary(void) · 370 unmodified lines |
| 6086 | } | 6214 | } |
| 6087 | #endif | 6215 | #endif |
| 6088 | | 6216 | |
| | 6217 | /* memory models */ |
| | 6218 | case TOK___ATOMIC_RELAXED: |
| | 6219 | case TOK___ATOMIC_CONSUME: |
| | 6220 | case TOK___ATOMIC_ACQUIRE: |
| | 6221 | case TOK___ATOMIC_RELEASE: |
| | 6222 | case TOK___ATOMIC_ACQ_REL: |
| | 6223 | case TOK___ATOMIC_SEQ_CST: |
| | 6224 | parse_memory_model(tok); |
| | 6225 | break; |
| | 6226 | |
| | 6227 | /* atomic operations */ |
| | 6228 | case TOK___atomic_init: |
| | 6229 | case TOK___atomic_store: |
| | 6230 | case TOK___atomic_load: |
| | 6231 | case TOK___atomic_exchange: |
| | 6232 | case TOK___atomic_compare_exchange_strong: |
| | 6233 | case TOK___atomic_compare_exchange_weak: |
| | 6234 | case TOK___atomic_fetch_add: |
| | 6235 | case TOK___atomic_fetch_sub: |
| | 6236 | case TOK___atomic_fetch_or: |
| | 6237 | case TOK___atomic_fetch_xor: |
| | 6238 | case TOK___atomic_fetch_and: |
| | 6239 | parse_atomic(tok); |
| | 6240 | break; |
| | 6241 | |
| 6089 | /* pre operations */ | 6242 | /* pre operations */ |
| 6090 | case TOK_INC: | 6243 | case TOK_INC: |
| 6091 | case TOK_DEC: | 6244 | case TOK_DEC: |