stdatomic: refactor parser and generator

This commit is contained in:
Dmitry Selyutin 2021-02-14 21:41:59 +03:00
parent d0d0c8b688
commit 1ff8679e79
3 changed files with 116 additions and 116 deletions

View File

@ -72,57 +72,59 @@ typedef struct {
#define ATOMIC_FLAG_INIT {0} #define ATOMIC_FLAG_INIT {0}
#define atomic_flag_test_and_set(object) \ #define atomic_flag_test_and_set(object) \
__c11_atomic_exchange(&(object)->value, 1, __ATOMIC_SEQ_CST) __atomic_exchange(&(object)->value, 1, __ATOMIC_SEQ_CST)
#define atomic_flag_test_and_set_explicit(object, order) \ #define atomic_flag_test_and_set_explicit(object, order) \
__c11_atomic_exchange(&(object)->value, 1, order) __atomic_exchange(&(object)->value, 1, order)
#define atomic_flag_clear(object) \ #define atomic_flag_clear(object) \
__c11_atomic_store(&(object)->value, 0, __ATOMIC_SEQ_CST) __atomic_store(&(object)->value, 0, __ATOMIC_SEQ_CST)
#define atomic_flag_clear_explicit(object, order) \ #define atomic_flag_clear_explicit(object, order) \
__c11_atomic_store(&(object)->value, 0, order) __atomic_store(&(object)->value, 0, order)
/* Generic routines */ /* Generic routines */
#define atomic_init(object, desired) \ #define atomic_init(object, desired) \
__c11_atomic_init(object, desired) __atomic_store(object, desired, __ATOMIC_RELAXED)
#define atomic_store(object, desired) \ #define atomic_store(object, desired) \
__c11_atomic_store(object, desired, __ATOMIC_SEQ_CST) __atomic_store(object, desired, __ATOMIC_SEQ_CST)
#define atomic_store_explicit __c11_atomic_store #define atomic_store_explicit __atomic_store
#define atomic_load(object) \ #define atomic_load(object) \
__c11_atomic_load(object, __ATOMIC_SEQ_CST) __atomic_load(object, __ATOMIC_SEQ_CST)
#define atomic_load_explicit __c11_atomic_load #define atomic_load_explicit __atomic_load
#define atomic_exchange(object, desired) \ #define atomic_exchange(object, desired) \
__c11_atomic_exchange(object, desired, __ATOMIC_SEQ_CST) __atomic_exchange(object, desired, __ATOMIC_SEQ_CST)
#define atomic_exchange_explicit __c11_atomic_exchange #define atomic_exchange_explicit __atomic_exchange
#define atomic_compare_exchange_strong(object, expected, desired) \ #define atomic_compare_exchange_strong(object, expected, desired) \
__c11_atomic_compare_exchange_strong(object, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) __atomic_compare_exchange(object, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
#define atomic_compare_exchange_strong_explicit __c11_atomic_compare_exchange_strong #define atomic_compare_exchange_strong_explicit(object, expected, desired, success, failure) \
__atomic_compare_exchange(object, expected, desired, 0, success, failure)
#define atomic_compare_exchange_weak(object, expected, desired) \ #define atomic_compare_exchange_weak(object, expected, desired) \
__c11_atomic_compare_exchange_weak(object, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) __atomic_compare_exchange(object, expected, desired, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
#define atomic_compare_exchange_weak_explicit __c11_atomic_compare_exchange_weak #define atomic_compare_exchange_weak_explicit(object, expected, desired, success, failure) \
__atomic_compare_exchange(object, expected, desired, 1, success, failure)
#define atomic_fetch_add(object, operand) \ #define atomic_fetch_add(object, operand) \
__c11_atomic_fetch_add(object, operand, __ATOMIC_SEQ_CST) __atomic_fetch_add(object, operand, __ATOMIC_SEQ_CST)
#define atomic_fetch_add_explicit __c11_atomic_fetch_add #define atomic_fetch_add_explicit __atomic_fetch_add
#define atomic_fetch_sub(object, operand) \ #define atomic_fetch_sub(object, operand) \
__c11_atomic_fetch_sub(object, operand, __ATOMIC_SEQ_CST) __atomic_fetch_sub(object, operand, __ATOMIC_SEQ_CST)
#define atomic_fetch_sub_explicit __c11_atomic_fetch_sub #define atomic_fetch_sub_explicit __atomic_fetch_sub
#define atomic_fetch_or(object, operand) \ #define atomic_fetch_or(object, operand) \
__c11_atomic_fetch_or(object, operand, __ATOMIC_SEQ_CST) __atomic_fetch_or(object, operand, __ATOMIC_SEQ_CST)
#define atomic_fetch_or_explicit __c11_atomic_fetch_or #define atomic_fetch_or_explicit __atomic_fetch_or
#define atomic_fetch_xor(object, operand) \ #define atomic_fetch_xor(object, operand) \
__c11_atomic_fetch_xor(object, operand, __ATOMIC_SEQ_CST) __atomic_fetch_xor(object, operand, __ATOMIC_SEQ_CST)
#define atomic_fetch_xor_explicit __c11_atomic_fetch_xor #define atomic_fetch_xor_explicit __atomic_fetch_xor
#define atomic_fetch_and(object, operand) \ #define atomic_fetch_and(object, operand) \
__c11_atomic_fetch_and(object, operand, __ATOMIC_SEQ_CST) __atomic_fetch_and(object, operand, __ATOMIC_SEQ_CST)
#define atomic_fetch_and_explicit __c11_atomic_fetch_and #define atomic_fetch_and_explicit __atomic_fetch_and
#endif /* _STDATOMIC_H */ #endif /* _STDATOMIC_H */

146
tccgen.c
View File

@ -5755,94 +5755,86 @@ static inline int is_memory_model(const SValue *sv)
* Ideally we should check whether the model matches 1:1. * Ideally we should check whether the model matches 1:1.
* If it is possible, we should check by the name of the value. * If it is possible, we should check by the name of the value.
*/ */
return (((sv->type.t & VT_BTYPE) == VT_INT) && (sv->c.i < 6)); return 1;
} }
#define ATOMIC_ID(ATOK) \
(ATOK - TOK___atomic_store)
static void parse_atomic(int atok) static void parse_atomic(int atok)
{ {
size_t op; int mode;
size_t arg; size_t arg;
size_t argc; SValue *call;
CType *atom = NULL; CType atom = {};
char const *params = NULL; static const char const *templates[] = {
static struct {
int const tok;
char const *const params;
} const ops[] = {
/* /*
* a -- atomic * Each entry consists of callback and function template.
* A -- read-only atomic * The template represents argument types and return type.
* p -- pointer to memory *
* P -- pointer to read-only memory * ? void (return-only)
* v -- value * b bool
* m -- memory model * a atomic
* A read-only atomic
* p pointer to memory
* v value
* m memory model
*/ */
{TOK___c11_atomic_init, "-av"}, [ATOMIC_ID(TOK___atomic_store)] = "avm?",
{TOK___c11_atomic_store, "-avm"}, [ATOMIC_ID(TOK___atomic_load)] = "Amv",
{TOK___c11_atomic_load, "am"}, [ATOMIC_ID(TOK___atomic_exchange)] = "avmv",
{TOK___c11_atomic_exchange, "avm"}, [ATOMIC_ID(TOK___atomic_compare_exchange)] = "apvbmmb",
{TOK___c11_atomic_compare_exchange_strong, "apvmm"}, [ATOMIC_ID(TOK___atomic_fetch_add)] = "avmv",
{TOK___c11_atomic_compare_exchange_weak, "apvmm"}, [ATOMIC_ID(TOK___atomic_fetch_sub)] = "avmv",
{TOK___c11_atomic_fetch_add, "avm"}, [ATOMIC_ID(TOK___atomic_fetch_or)] = "avmv",
{TOK___c11_atomic_fetch_sub, "avm"}, [ATOMIC_ID(TOK___atomic_fetch_xor)] = "avmv",
{TOK___c11_atomic_fetch_or, "avm"}, [ATOMIC_ID(TOK___atomic_fetch_and)] = "avmv",
{TOK___c11_atomic_fetch_xor, "avm"},
{TOK___c11_atomic_fetch_and, "avm"},
}; };
const char *template = templates[ATOMIC_ID(atok)];
const size_t argc = (strlen(template) - 1);
next(); next();
for (op = 0; op < (sizeof(ops) / sizeof(*ops)); ++op) { vpush_helper_func(atok);
if (ops[op].tok == atok) { call = vtop;
params = ops[op].params;
break;
}
}
if (!params)
tcc_error("unknown atomic operation");
argc = strlen(params);
if (params[0] == '-') {
++params;
--argc;
}
vpushi(0);
vpushi(0); /* function address */
skip('('); skip('(');
if ((*template != 'a') && (*template != 'A'))
expect_arg("pointer to atomic", 0);
for (arg = 0; arg < argc; ++arg) { for (arg = 0; arg < argc; ++arg) {
expr_eq(); expr_eq();
switch (params[arg]) { switch (template[arg]) {
case '?':
/* void makes sense only for return value. */
if (arg != (argc - 1))
tcc_error("illegal atomic built-in template");
break;
case 'b':
break;
case 'a': case 'a':
case 'A': case 'A':
if (atom)
expect_arg("exactly one pointer to atomic", arg);
if ((vtop->type.t & VT_BTYPE) != VT_PTR) if ((vtop->type.t & VT_BTYPE) != VT_PTR)
expect_arg("pointer to atomic expected", arg); expect_arg("pointer to atomic value", arg);
atom = pointed_type(&vtop->type); memcpy(&atom, pointed_type(&vtop->type), sizeof(CType));
if (!(atom->t & VT_ATOMIC)) if (!(atom.t & VT_ATOMIC))
expect_arg("qualified pointer to atomic", arg); expect_arg("qualified pointer to atomic value", arg);
if ((params[arg] == 'a') && (atom->t & VT_CONSTANT)) if ((template[arg] == 'a') && (atom.t & VT_CONSTANT))
expect_arg("pointer to writable atomic", arg); expect_arg("pointer to writable atomic", arg);
atom->t &= ~VT_ATOMIC; switch (btype_size(atom.t & VT_BTYPE)) {
switch (btype_size(atom->t & VT_BTYPE)) { case 8: mode = 4; break;
case 1: atok += 1; break; case 4: mode = 3; break;
case 2: atok += 2; break; case 2: mode = 2; break;
case 4: atok += 3; break; case 1: mode = 1; break;
case 8: atok += 4; break;
default: tcc_error("only integer-sized types are supported"); default: tcc_error("only integer-sized types are supported");
} }
vswap();
vpop();
vpush_helper_func(atok);
vswap();
break; break;
case 'p': case 'p':
if (((vtop->type.t & VT_BTYPE) != VT_PTR) if (((vtop->type.t & VT_BTYPE) != VT_PTR)
|| !is_compatible_unqualified_types(atom, pointed_type(&vtop->type))) || !is_compatible_unqualified_types(&atom, pointed_type(&vtop->type)))
expect_arg("pointer to compatible type", arg); expect_arg("pointer to compatible type", arg);
break; break;
@ -5870,7 +5862,17 @@ static void parse_atomic(int atok)
expect("less parameters"); expect("less parameters");
skip(')'); skip(')');
call->sym = external_helper_sym(atok + mode);
gfunc_call(argc); gfunc_call(argc);
vpushi(0);
switch (template[argc]) {
case 'b': PUT_R_RET(vtop, VT_BOOL); break;
case 'v': PUT_R_RET(vtop, atom.t); break;
case 'p': PUT_R_RET(vtop, VT_SIZE_T); break;
case '?': PUT_R_RET(vtop, VT_VOID); break;
default: tcc_error("incorrect atomic template");
}
} }
ST_FUNC void unary(void) ST_FUNC void unary(void)
@ -6255,17 +6257,15 @@ ST_FUNC void unary(void)
#endif #endif
/* atomic operations */ /* atomic operations */
case TOK___c11_atomic_init: case TOK___atomic_store:
case TOK___c11_atomic_store: case TOK___atomic_load:
case TOK___c11_atomic_load: case TOK___atomic_exchange:
case TOK___c11_atomic_exchange: case TOK___atomic_compare_exchange:
case TOK___c11_atomic_compare_exchange_strong: case TOK___atomic_fetch_add:
case TOK___c11_atomic_compare_exchange_weak: case TOK___atomic_fetch_sub:
case TOK___c11_atomic_fetch_add: case TOK___atomic_fetch_or:
case TOK___c11_atomic_fetch_sub: case TOK___atomic_fetch_xor:
case TOK___c11_atomic_fetch_or: case TOK___atomic_fetch_and:
case TOK___c11_atomic_fetch_xor:
case TOK___c11_atomic_fetch_and:
parse_atomic(tok); parse_atomic(tok);
break; break;

View File

@ -174,25 +174,23 @@
DEF(TOK_builtin_va_start, "__builtin_va_start") DEF(TOK_builtin_va_start, "__builtin_va_start")
#endif #endif
#define DEF_ATOMIC(id, str) \
DEF(id, str) \
DEF(id##_8, str "_8") \
DEF(id##_16, str "_16") \
DEF(id##_32, str "_32") \
DEF(id##_64, str "_64")
/* atomic operations */ /* atomic operations */
DEF_ATOMIC(TOK___c11_atomic_init, "__c11_atomic_init") #define DEF_ATOMIC(ID) \
DEF_ATOMIC(TOK___c11_atomic_store, "__c11_atomic_store") DEF(TOK_##__##ID, "__"#ID) \
DEF_ATOMIC(TOK___c11_atomic_load, "__c11_atomic_load") DEF(TOK_##__##ID##_1, "__"#ID"_1") \
DEF_ATOMIC(TOK___c11_atomic_exchange, "__c11_atomic_exchange") DEF(TOK_##__##ID##_2, "__"#ID"_2") \
DEF_ATOMIC(TOK___c11_atomic_compare_exchange_strong, "__c11_atomic_compare_exchange_strong") DEF(TOK_##__##ID##_4, "__"#ID"_4") \
DEF_ATOMIC(TOK___c11_atomic_compare_exchange_weak, "__c11_atomic_compare_exchange_weak") DEF(TOK_##__##ID##_8, "__"#ID"_8")
DEF_ATOMIC(TOK___c11_atomic_fetch_add, "__c11_atomic_fetch_add")
DEF_ATOMIC(TOK___c11_atomic_fetch_sub, "__c11_atomic_fetch_sub") DEF_ATOMIC(atomic_store)
DEF_ATOMIC(TOK___c11_atomic_fetch_or, "__c11_atomic_fetch_or") DEF_ATOMIC(atomic_load)
DEF_ATOMIC(TOK___c11_atomic_fetch_xor, "__c11_atomic_fetch_xor") DEF_ATOMIC(atomic_exchange)
DEF_ATOMIC(TOK___c11_atomic_fetch_and, "__c11_atomic_fetch_and") DEF_ATOMIC(atomic_compare_exchange)
DEF_ATOMIC(atomic_fetch_add)
DEF_ATOMIC(atomic_fetch_sub)
DEF_ATOMIC(atomic_fetch_or)
DEF_ATOMIC(atomic_fetch_xor)
DEF_ATOMIC(atomic_fetch_and)
#undef DEF_ATOMIC #undef DEF_ATOMIC