| @@ -5160,6 +5160,20 @@ static int parse_btype(CType *type, AttributeDef *ad) · 5159 unmodified lines |
| 5160 | 5160 | goto basic_type2; |
| 5161 | 5161 | |
| 5162 | 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 | 5177 | case TOK_CONST1: |
| 5164 | 5178 | case TOK_CONST2: |
| 5165 | 5179 | case TOK_CONST3: |
| @@ -5515,6 +5529,9 @@ static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td) · 349 unmodified lines |
| 5515 | 5529 | redo: |
| 5516 | 5530 | next(); |
| 5517 | 5531 | switch(tok) { |
| 5532 | + case TOK__Atomic: |
| 5533 | + qualifiers |= VT_ATOMIC; |
| 5534 | + goto redo; |
| 5518 | 5535 | case TOK_CONST1: |
| 5519 | 5536 | case TOK_CONST2: |
| 5520 | 5537 | case TOK_CONST3: |
| @@ -5710,6 +5727,117 @@ static void parse_builtin_params(int nc, const char *args) · 189 unmodified lines |
| 5710 | 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 | 5841 | ST_FUNC void unary(void) |
| 5714 | 5842 | { |
| 5715 | 5843 | int n, t, align, size, r, sizeof_caller; |
| @@ -6086,6 +6214,31 @@ ST_FUNC void unary(void) · 370 unmodified lines |
| 6086 | 6214 | } |
| 6087 | 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 | 6242 | /* pre operations */ |
| 6090 | 6243 | case TOK_INC: |
| 6091 | 6244 | case TOK_DEC: |