mirror of
git://repo.or.cz/tinycc.git
synced 2026-07-07 11:58:41 +08:00
stdatomic: refactor parser and generator
This commit is contained in:
parent
d0d0c8b688
commit
1ff8679e79
@ -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
146
tccgen.c
@ -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;
|
||||||
|
|
||||||
|
|||||||
34
tcctok.h
34
tcctok.h
@ -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
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user