A small note on "-" sign at the mapping table. It's not used yet for any
real purpose; I've been thinking of re-using it as marker to determine
whether the function returns the underlying type or returns void.

вт, 26 янв. 2021 г., 23:46 Dmitry Selyutin <ghostman...@gmail.com>:

> Dear all,
>
> I'm one of tcc users; thank you for this wonderful compiler! Recently I
> decided
> that it'd be great to contribute to the project, and one of the things I
> found
> missing is stdatomic.h support. For now I've implemented the very basic
> parts
> required on the syntax side; all atomic intrinsics currently is supposed to
> emit a call to the internal function, based on the type of the arguments.
>
> Since I'm new to tcc code, some parts can certainly be improved; I'd be
> glad
> to know your remarks and opinion. If you find these patches useful, please
> let
> me know.
>
> I'm not entirely sure of the approach with internal calls; it seems
> reasonable
> to generate the assembly instead. However, I haven't checked the assembly
> code
> generation yet; any tips and suggestions are welcome.
>
> P.S. The code is also available at stdatomic branch.
>
> ---
>  tcc.h    |   4 ++
>  tccgen.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  tccpp.c  |   5 ++
>  tcctok.h |  22 ++++++++
>  4 files changed, 184 insertions(+)
>
> diff --git a/tcc.h b/tcc.h
> index 7879d6e..691f649 100644
> --- a/tcc.h
> +++ b/tcc.h
> @@ -1051,6 +1051,9 @@ struct filespec {
>  #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 VT_ATOMIC   VT_VOLATILE
> +#define VT_MEMMODEL (VT_STATIC | VT_ENUM_VAL | VT_TYPEDEF)
> +
>  /* type mask (except storage) */
>  #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
>  #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 void skip(int c);
>  ST_FUNC NORETURN void expect(const char *msg);
> +ST_FUNC NORETURN void expect_arg(const char *msg, size_t arg);
>
>  /* space excluding newline */
>  static inline int is_space(int ch) {
> diff --git a/tccgen.c b/tccgen.c
> index 1f1af70..86b0e86 100644
> --- a/tccgen.c
> +++ b/tccgen.c
> @@ -5160,6 +5160,20 @@ static int parse_btype(CType *type, AttributeDef
> *ad)
>              goto basic_type2;
>
>              /* 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_CONST2:
>          case TOK_CONST3:
> @@ -5515,6 +5529,9 @@ static CType *type_decl(CType *type,
> AttributeDef *ad, int *v, int td)
>      redo:
>          next();
>          switch(tok) {
> +        case TOK__Atomic:
> +            qualifiers |= VT_ATOMIC;
> +            goto redo;
>          case TOK_CONST1:
>          case TOK_CONST2:
>          case TOK_CONST3:
> @@ -5710,6 +5727,117 @@ static void parse_builtin_params(int nc, const
> char *args)
>          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)
>  {
>      int n, t, align, size, r, sizeof_caller;
> @@ -6086,6 +6214,31 @@ ST_FUNC void unary(void)
>      }
>  #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 */
>      case TOK_INC:
>      case TOK_DEC:
> diff --git a/tccpp.c b/tccpp.c
> index b21210d..20328a1 100644
> --- a/tccpp.c
> +++ b/tccpp.c
> @@ -107,6 +107,11 @@ ST_FUNC void expect(const char *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 */
>
> diff --git a/tcctok.h b/tcctok.h
> index 390eca3..3ac525e 100644
> --- a/tcctok.h
> +++ b/tcctok.h
> @@ -17,6 +17,7 @@
>       DEF(TOK_SWITCH, "switch")
>       DEF(TOK_CASE, "case")
>
> +     DEF(TOK__Atomic, "_Atomic")
>       DEF(TOK_CONST1, "const")
>       DEF(TOK_CONST2, "__const") /* gcc keyword */
>       DEF(TOK_CONST3, "__const__") /* gcc keyword */
> @@ -173,6 +174,27 @@
>       DEF(TOK_builtin_va_start, "__builtin_va_start")
>  #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 */
>       DEF(TOK_pack, "pack")
>  #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_X86_64) && \
> --
> 2.30.0
>
> --
> Best regards,
> Dmitry Selyutin
>
_______________________________________________
Tinycc-devel mailing list
Tinycc-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

Reply via email to