stdatomic: atomic builtins parsing support
This commit is contained in:
parent
557b4a1f6d
commit
a110287c31
4 changed files with 184 additions and 0 deletions
4
tcc.h
4
tcc.h
|
@ -1051,6 +1051,9 @@ struct filespec {
|
||||||
#define IS_ENUM_VAL(t) ((t & VT_STRUCT_MASK) == VT_ENUM_VAL)
|
#define IS_ENUM_VAL(t) ((t & VT_STRUCT_MASK) == VT_ENUM_VAL)
|
||||||
#define IS_UNION(t) ((t & (VT_STRUCT_MASK|VT_BTYPE)) == VT_UNION)
|
#define IS_UNION(t) ((t & (VT_STRUCT_MASK|VT_BTYPE)) == VT_UNION)
|
||||||
|
|
||||||
|
#define VT_ATOMIC VT_VOLATILE
|
||||||
|
#define VT_MEMMODEL (VT_STATIC | VT_ENUM_VAL | VT_TYPEDEF)
|
||||||
|
|
||||||
/* type mask (except storage) */
|
/* type mask (except storage) */
|
||||||
#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
|
#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
|
||||||
#define VT_TYPE (~(VT_STORAGE|VT_STRUCT_MASK))
|
#define VT_TYPE (~(VT_STORAGE|VT_STRUCT_MASK))
|
||||||
|
@ -1418,6 +1421,7 @@ ST_FUNC void tccpp_delete(TCCState *s);
|
||||||
ST_FUNC int tcc_preprocess(TCCState *s1);
|
ST_FUNC int tcc_preprocess(TCCState *s1);
|
||||||
ST_FUNC void skip(int c);
|
ST_FUNC void skip(int c);
|
||||||
ST_FUNC NORETURN void expect(const char *msg);
|
ST_FUNC NORETURN void expect(const char *msg);
|
||||||
|
ST_FUNC NORETURN void expect_arg(const char *msg, size_t arg);
|
||||||
|
|
||||||
/* space excluding newline */
|
/* space excluding newline */
|
||||||
static inline int is_space(int ch) {
|
static inline int is_space(int ch) {
|
||||||
|
|
153
tccgen.c
153
tccgen.c
|
@ -5160,6 +5160,20 @@ static int parse_btype(CType *type, AttributeDef *ad)
|
||||||
goto basic_type2;
|
goto basic_type2;
|
||||||
|
|
||||||
/* type modifiers */
|
/* type modifiers */
|
||||||
|
case TOK__Atomic:
|
||||||
|
next();
|
||||||
|
type->t = t;
|
||||||
|
parse_btype_qualify(type, VT_ATOMIC);
|
||||||
|
t = type->t;
|
||||||
|
if (tok == '(') {
|
||||||
|
parse_expr_type(&type1);
|
||||||
|
/* remove all storage modifiers except typedef */
|
||||||
|
type1.t &= ~(VT_STORAGE&~VT_TYPEDEF);
|
||||||
|
if (type1.ref)
|
||||||
|
sym_to_attr(ad, type1.ref);
|
||||||
|
goto basic_type2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case TOK_CONST1:
|
case TOK_CONST1:
|
||||||
case TOK_CONST2:
|
case TOK_CONST2:
|
||||||
case TOK_CONST3:
|
case TOK_CONST3:
|
||||||
|
@ -5515,6 +5529,9 @@ static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td)
|
||||||
redo:
|
redo:
|
||||||
next();
|
next();
|
||||||
switch(tok) {
|
switch(tok) {
|
||||||
|
case TOK__Atomic:
|
||||||
|
qualifiers |= VT_ATOMIC;
|
||||||
|
goto redo;
|
||||||
case TOK_CONST1:
|
case TOK_CONST1:
|
||||||
case TOK_CONST2:
|
case TOK_CONST2:
|
||||||
case TOK_CONST3:
|
case TOK_CONST3:
|
||||||
|
@ -5710,6 +5727,117 @@ static void parse_builtin_params(int nc, const char *args)
|
||||||
nocode_wanted--;
|
nocode_wanted--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void parse_memory_model(int mtok)
|
||||||
|
{
|
||||||
|
next();
|
||||||
|
|
||||||
|
switch (mtok) {
|
||||||
|
case TOK___ATOMIC_RELAXED: vpushs(0); break;
|
||||||
|
case TOK___ATOMIC_CONSUME: vpushs(1); break;
|
||||||
|
case TOK___ATOMIC_ACQUIRE: vpushs(2); break;
|
||||||
|
case TOK___ATOMIC_RELEASE: vpushs(3); break;
|
||||||
|
case TOK___ATOMIC_ACQ_REL: vpushs(4); break;
|
||||||
|
case TOK___ATOMIC_SEQ_CST: vpushs(5); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
vtop->type.t |= (VT_UNSIGNED | VT_MEMMODEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_atomic(int atok)
|
||||||
|
{
|
||||||
|
size_t arg;
|
||||||
|
size_t argc;
|
||||||
|
int param;
|
||||||
|
char const *params;
|
||||||
|
CType *atom = NULL;
|
||||||
|
|
||||||
|
next();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* a -- atomic
|
||||||
|
* A -- read-only atomic
|
||||||
|
* p -- pointer to memory
|
||||||
|
* P -- pointer to read-only memory
|
||||||
|
* v -- value
|
||||||
|
* m -- memory model
|
||||||
|
*/
|
||||||
|
switch (atok) {
|
||||||
|
case TOK___atomic_init: params = "-a"; break;
|
||||||
|
case TOK___atomic_store: params = "-avm"; break;
|
||||||
|
case TOK___atomic_load: params = "am"; break;
|
||||||
|
case TOK___atomic_exchange: params = "avm"; break;
|
||||||
|
case TOK___atomic_compare_exchange_strong: params = "apvmm"; break;
|
||||||
|
case TOK___atomic_compare_exchange_weak: params = "apvmm"; break;
|
||||||
|
case TOK___atomic_fetch_add: params = "avm"; break;
|
||||||
|
case TOK___atomic_fetch_sub: params = "avm"; break;
|
||||||
|
case TOK___atomic_fetch_or: params = "avm"; break;
|
||||||
|
case TOK___atomic_fetch_xor: params = "avm"; break;
|
||||||
|
case TOK___atomic_fetch_and: params = "avm"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
argc = strlen(params);
|
||||||
|
if (params[0] == '-') {
|
||||||
|
++params;
|
||||||
|
--argc;
|
||||||
|
}
|
||||||
|
|
||||||
|
skip('(');
|
||||||
|
for (arg = 0; arg < argc; ++arg) {
|
||||||
|
expr_eq();
|
||||||
|
|
||||||
|
param = params[arg];
|
||||||
|
switch (param) {
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
if (atom)
|
||||||
|
expect_arg("exactly one pointer to atomic", arg);
|
||||||
|
if ((vtop->type.t & VT_BTYPE) != VT_PTR)
|
||||||
|
expect_arg("pointer to atomic expected", arg);
|
||||||
|
atom = pointed_type(&vtop->type);
|
||||||
|
if (!(atom->t & VT_ATOMIC))
|
||||||
|
expect_arg("qualified pointer to atomic", arg);
|
||||||
|
if ((param == 'a') && (atom->t & VT_CONSTANT))
|
||||||
|
expect_arg("pointer to writable atomic", arg);
|
||||||
|
if (!is_integer_btype(atom->t & VT_BTYPE))
|
||||||
|
expect_arg("only atomic integers are supported", arg);
|
||||||
|
atom->t &= ~VT_ATOMIC;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
if (((vtop->type.t & VT_BTYPE) != VT_PTR)
|
||||||
|
|| !is_compatible_unqualified_types(atom, pointed_type(&vtop->type)))
|
||||||
|
expect_arg("pointer to compatible type", arg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
if (!is_integer_btype(vtop->type.t & VT_BTYPE))
|
||||||
|
expect_arg("only atomic integers are supported", arg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'm':
|
||||||
|
if ((vtop->type.t & VT_MEMMODEL) != VT_MEMMODEL)
|
||||||
|
expect_arg("memory model constant", arg);
|
||||||
|
vtop->type.t &= ~VT_MEMMODEL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
tcc_error("unknown parameter type");
|
||||||
|
}
|
||||||
|
if (tok == ')')
|
||||||
|
break;
|
||||||
|
skip(',');
|
||||||
|
}
|
||||||
|
if (arg < (argc - 1))
|
||||||
|
expect("more parameters");
|
||||||
|
if (arg > (argc - 1))
|
||||||
|
expect("less parameters");
|
||||||
|
skip(')');
|
||||||
|
|
||||||
|
for (arg = 0; arg < (argc - 1); ++arg)
|
||||||
|
vpop();
|
||||||
|
tcc_error("atomics are not supported yet");
|
||||||
|
}
|
||||||
|
|
||||||
ST_FUNC void unary(void)
|
ST_FUNC void unary(void)
|
||||||
{
|
{
|
||||||
int n, t, align, size, r, sizeof_caller;
|
int n, t, align, size, r, sizeof_caller;
|
||||||
|
@ -6086,6 +6214,31 @@ ST_FUNC void unary(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* memory models */
|
||||||
|
case TOK___ATOMIC_RELAXED:
|
||||||
|
case TOK___ATOMIC_CONSUME:
|
||||||
|
case TOK___ATOMIC_ACQUIRE:
|
||||||
|
case TOK___ATOMIC_RELEASE:
|
||||||
|
case TOK___ATOMIC_ACQ_REL:
|
||||||
|
case TOK___ATOMIC_SEQ_CST:
|
||||||
|
parse_memory_model(tok);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* atomic operations */
|
||||||
|
case TOK___atomic_init:
|
||||||
|
case TOK___atomic_store:
|
||||||
|
case TOK___atomic_load:
|
||||||
|
case TOK___atomic_exchange:
|
||||||
|
case TOK___atomic_compare_exchange_strong:
|
||||||
|
case TOK___atomic_compare_exchange_weak:
|
||||||
|
case TOK___atomic_fetch_add:
|
||||||
|
case TOK___atomic_fetch_sub:
|
||||||
|
case TOK___atomic_fetch_or:
|
||||||
|
case TOK___atomic_fetch_xor:
|
||||||
|
case TOK___atomic_fetch_and:
|
||||||
|
parse_atomic(tok);
|
||||||
|
break;
|
||||||
|
|
||||||
/* pre operations */
|
/* pre operations */
|
||||||
case TOK_INC:
|
case TOK_INC:
|
||||||
case TOK_DEC:
|
case TOK_DEC:
|
||||||
|
|
5
tccpp.c
5
tccpp.c
|
@ -107,6 +107,11 @@ ST_FUNC void expect(const char *msg)
|
||||||
tcc_error("%s expected", msg);
|
tcc_error("%s expected", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ST_FUNC void expect_arg(const char *msg, size_t arg)
|
||||||
|
{
|
||||||
|
tcc_error("%s expected as arg #%zu", msg, arg);
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
/* Custom allocator for tiny objects */
|
/* Custom allocator for tiny objects */
|
||||||
|
|
||||||
|
|
22
tcctok.h
22
tcctok.h
|
@ -17,6 +17,7 @@
|
||||||
DEF(TOK_SWITCH, "switch")
|
DEF(TOK_SWITCH, "switch")
|
||||||
DEF(TOK_CASE, "case")
|
DEF(TOK_CASE, "case")
|
||||||
|
|
||||||
|
DEF(TOK__Atomic, "_Atomic")
|
||||||
DEF(TOK_CONST1, "const")
|
DEF(TOK_CONST1, "const")
|
||||||
DEF(TOK_CONST2, "__const") /* gcc keyword */
|
DEF(TOK_CONST2, "__const") /* gcc keyword */
|
||||||
DEF(TOK_CONST3, "__const__") /* gcc keyword */
|
DEF(TOK_CONST3, "__const__") /* gcc keyword */
|
||||||
|
@ -173,6 +174,27 @@
|
||||||
DEF(TOK_builtin_va_start, "__builtin_va_start")
|
DEF(TOK_builtin_va_start, "__builtin_va_start")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* memory models */
|
||||||
|
DEF(TOK___ATOMIC_RELAXED, "__ATOMIC_RELAXED")
|
||||||
|
DEF(TOK___ATOMIC_CONSUME, "__ATOMIC_CONSUME")
|
||||||
|
DEF(TOK___ATOMIC_ACQUIRE, "__ATOMIC_ACQUIRE")
|
||||||
|
DEF(TOK___ATOMIC_RELEASE, "__ATOMIC_RELEASE")
|
||||||
|
DEF(TOK___ATOMIC_ACQ_REL, "__ATOMIC_ACQ_REL")
|
||||||
|
DEF(TOK___ATOMIC_SEQ_CST, "__ATOMIC_SEQ_CST")
|
||||||
|
|
||||||
|
/* atomic operations */
|
||||||
|
DEF(TOK___atomic_init, "__atomic_init")
|
||||||
|
DEF(TOK___atomic_store, "__atomic_store")
|
||||||
|
DEF(TOK___atomic_load, "__atomic_load")
|
||||||
|
DEF(TOK___atomic_exchange, "__atomic_exchange")
|
||||||
|
DEF(TOK___atomic_compare_exchange_strong, "__atomic_compare_exchange_strong")
|
||||||
|
DEF(TOK___atomic_compare_exchange_weak, "__atomic_compare_exchange_weak")
|
||||||
|
DEF(TOK___atomic_fetch_add, "__atomic_fetch_add")
|
||||||
|
DEF(TOK___atomic_fetch_sub, "__atomic_fetch_sub")
|
||||||
|
DEF(TOK___atomic_fetch_or, "__atomic_fetch_or")
|
||||||
|
DEF(TOK___atomic_fetch_xor, "__atomic_fetch_xor")
|
||||||
|
DEF(TOK___atomic_fetch_and, "__atomic_fetch_and")
|
||||||
|
|
||||||
/* pragma */
|
/* pragma */
|
||||||
DEF(TOK_pack, "pack")
|
DEF(TOK_pack, "pack")
|
||||||
#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_X86_64) && \
|
#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_X86_64) && \
|
||||||
|
|
Loading…
Reference in a new issue