tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Tinycc-devel] [PATCH 1/2] stdatomic: refactor parser and generator


From: Dmitry Selyutin
Subject: [Tinycc-devel] [PATCH 1/2] stdatomic: refactor parser and generator
Date: Thu, 11 Mar 2021 23:11:41 +0300

---
 include/stdatomic.h |  52 ++++++++--------
 tccgen.c            | 146 ++++++++++++++++++++++----------------------
 tcctok.h            |  34 +++++------
 3 files changed, 116 insertions(+), 116 deletions(-)

diff --git a/include/stdatomic.h b/include/stdatomic.h
index ebec3e1..b910d12 100644
--- a/include/stdatomic.h
+++ b/include/stdatomic.h
@@ -72,57 +72,59 @@ typedef struct {
 #define ATOMIC_FLAG_INIT {0}

 #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) \
-    __c11_atomic_exchange(&(object)->value, 1, order)
+    __atomic_exchange(&(object)->value, 1, order)

 #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) \
-    __c11_atomic_store(&(object)->value, 0, order)
+    __atomic_store(&(object)->value, 0, order)

 /* Generic routines */
 #define atomic_init(object, desired) \
-    __c11_atomic_init(object, desired)
+    __atomic_store(object, desired, __ATOMIC_RELAXED)

 #define atomic_store(object, desired) \
-    __c11_atomic_store(object, desired, __ATOMIC_SEQ_CST)
-#define atomic_store_explicit __c11_atomic_store
+    __atomic_store(object, desired, __ATOMIC_SEQ_CST)
+#define atomic_store_explicit __atomic_store

 #define atomic_load(object) \
-    __c11_atomic_load(object, __ATOMIC_SEQ_CST)
-#define atomic_load_explicit __c11_atomic_load
+    __atomic_load(object, __ATOMIC_SEQ_CST)
+#define atomic_load_explicit __atomic_load

 #define atomic_exchange(object, desired) \
-    __c11_atomic_exchange(object, desired, __ATOMIC_SEQ_CST)
-#define atomic_exchange_explicit __c11_atomic_exchange
+    __atomic_exchange(object, desired, __ATOMIC_SEQ_CST)
+#define atomic_exchange_explicit __atomic_exchange

 #define atomic_compare_exchange_strong(object, expected, desired) \
-    __c11_atomic_compare_exchange_strong(object, expected, desired,
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
-#define atomic_compare_exchange_strong_explicit
__c11_atomic_compare_exchange_strong
+    __atomic_compare_exchange(object, expected, desired, 0,
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
+#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) \
-    __c11_atomic_compare_exchange_weak(object, expected, desired,
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
-#define atomic_compare_exchange_weak_explicit
__c11_atomic_compare_exchange_weak
+    __atomic_compare_exchange(object, expected, desired, 1,
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
+#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) \
-    __c11_atomic_fetch_add(object, operand, __ATOMIC_SEQ_CST)
-#define atomic_fetch_add_explicit __c11_atomic_fetch_add
+    __atomic_fetch_add(object, operand, __ATOMIC_SEQ_CST)
+#define atomic_fetch_add_explicit __atomic_fetch_add

 #define atomic_fetch_sub(object, operand) \
-    __c11_atomic_fetch_sub(object, operand, __ATOMIC_SEQ_CST)
-#define atomic_fetch_sub_explicit __c11_atomic_fetch_sub
+    __atomic_fetch_sub(object, operand, __ATOMIC_SEQ_CST)
+#define atomic_fetch_sub_explicit __atomic_fetch_sub

 #define atomic_fetch_or(object, operand) \
-    __c11_atomic_fetch_or(object, operand, __ATOMIC_SEQ_CST)
-#define atomic_fetch_or_explicit __c11_atomic_fetch_or
+    __atomic_fetch_or(object, operand, __ATOMIC_SEQ_CST)
+#define atomic_fetch_or_explicit __atomic_fetch_or

 #define atomic_fetch_xor(object, operand) \
-    __c11_atomic_fetch_xor(object, operand, __ATOMIC_SEQ_CST)
-#define atomic_fetch_xor_explicit __c11_atomic_fetch_xor
+    __atomic_fetch_xor(object, operand, __ATOMIC_SEQ_CST)
+#define atomic_fetch_xor_explicit __atomic_fetch_xor

 #define atomic_fetch_and(object, operand) \
-    __c11_atomic_fetch_and(object, operand, __ATOMIC_SEQ_CST)
-#define atomic_fetch_and_explicit __c11_atomic_fetch_and
+    __atomic_fetch_and(object, operand, __ATOMIC_SEQ_CST)
+#define atomic_fetch_and_explicit __atomic_fetch_and

 #endif /* _STDATOMIC_H */
diff --git a/tccgen.c b/tccgen.c
index 31c4f47..545369b 100644
--- a/tccgen.c
+++ b/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.
      * 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)
 {
-    size_t op;
+    int mode;
     size_t arg;
-    size_t argc;
-    CType *atom = NULL;
-    char const *params = NULL;
-    static struct {
-        int const tok;
-        char const *const params;
-    } const ops[] = {
+    SValue *call;
+    CType atom = {};
+    static const char const *templates[] = {
         /*
-         * a -- atomic
-         * A -- read-only atomic
-         * p -- pointer to memory
-         * P -- pointer to read-only memory
-         * v -- value
-         * m -- memory model
+         * Each entry consists of callback and function template.
+         * The template represents argument types and return type.
+         *
+         * ? void (return-only)
+         * b bool
+         * a atomic
+         * A read-only atomic
+         * p pointer to memory
+         * v value
+         * m memory model
          */
-        {TOK___c11_atomic_init, "-av"},
-        {TOK___c11_atomic_store, "-avm"},
-        {TOK___c11_atomic_load, "am"},
-        {TOK___c11_atomic_exchange, "avm"},
-        {TOK___c11_atomic_compare_exchange_strong, "apvmm"},
-        {TOK___c11_atomic_compare_exchange_weak, "apvmm"},
-        {TOK___c11_atomic_fetch_add, "avm"},
-        {TOK___c11_atomic_fetch_sub, "avm"},
-        {TOK___c11_atomic_fetch_or, "avm"},
-        {TOK___c11_atomic_fetch_xor, "avm"},
-        {TOK___c11_atomic_fetch_and, "avm"},
+        [ATOMIC_ID(TOK___atomic_store)] = "avm?",
+        [ATOMIC_ID(TOK___atomic_load)] = "Amv",
+        [ATOMIC_ID(TOK___atomic_exchange)] = "avmv",
+        [ATOMIC_ID(TOK___atomic_compare_exchange)] = "apvbmmb",
+        [ATOMIC_ID(TOK___atomic_fetch_add)] = "avmv",
+        [ATOMIC_ID(TOK___atomic_fetch_sub)] = "avmv",
+        [ATOMIC_ID(TOK___atomic_fetch_or)] = "avmv",
+        [ATOMIC_ID(TOK___atomic_fetch_xor)] = "avmv",
+        [ATOMIC_ID(TOK___atomic_fetch_and)] = "avmv",
     };
+    const char *template = templates[ATOMIC_ID(atok)];
+    const size_t argc = (strlen(template) - 1);

     next();

-    for (op = 0; op < (sizeof(ops) / sizeof(*ops)); ++op) {
-        if (ops[op].tok == atok) {
-            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 */
+    vpush_helper_func(atok);
+    call = vtop;

     skip('(');
+    if ((*template != 'a') && (*template != 'A'))
+        expect_arg("pointer to atomic", 0);
     for (arg = 0; arg < argc; ++arg) {
         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':
-            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 ((params[arg] == 'a') && (atom->t & VT_CONSTANT))
+                expect_arg("pointer to atomic value", arg);
+            memcpy(&atom, pointed_type(&vtop->type), sizeof(CType));
+            if (!(atom.t & VT_ATOMIC))
+                expect_arg("qualified pointer to atomic value", arg);
+            if ((template[arg] == 'a') && (atom.t & VT_CONSTANT))
                 expect_arg("pointer to writable atomic", arg);
-            atom->t &= ~VT_ATOMIC;
-            switch (btype_size(atom->t & VT_BTYPE)) {
-            case 1: atok += 1; break;
-            case 2: atok += 2; break;
-            case 4: atok += 3; break;
-            case 8: atok += 4; break;
+            switch (btype_size(atom.t & VT_BTYPE)) {
+            case 8: mode = 4; break;
+            case 4: mode = 3; break;
+            case 2: mode = 2; break;
+            case 1: mode = 1; break;
             default: tcc_error("only integer-sized types are supported");
             }
-            vswap();
-            vpop();
-            vpush_helper_func(atok);
-            vswap();
             break;

         case 'p':
             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);
             break;

@@ -5870,7 +5862,17 @@ static void parse_atomic(int atok)
         expect("less parameters");
     skip(')');

+    call->sym = external_helper_sym(atok + mode);
     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)
@@ -6255,17 +6257,15 @@ ST_FUNC void unary(void)
 #endif

     /* atomic operations */
-    case TOK___c11_atomic_init:
-    case TOK___c11_atomic_store:
-    case TOK___c11_atomic_load:
-    case TOK___c11_atomic_exchange:
-    case TOK___c11_atomic_compare_exchange_strong:
-    case TOK___c11_atomic_compare_exchange_weak:
-    case TOK___c11_atomic_fetch_add:
-    case TOK___c11_atomic_fetch_sub:
-    case TOK___c11_atomic_fetch_or:
-    case TOK___c11_atomic_fetch_xor:
-    case TOK___c11_atomic_fetch_and:
+    case TOK___atomic_store:
+    case TOK___atomic_load:
+    case TOK___atomic_exchange:
+    case TOK___atomic_compare_exchange:
+    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;

diff --git a/tcctok.h b/tcctok.h
index 0fe3a8f..a5d893e 100644
--- a/tcctok.h
+++ b/tcctok.h
@@ -174,25 +174,23 @@
      DEF(TOK_builtin_va_start, "__builtin_va_start")
 #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 */
-     DEF_ATOMIC(TOK___c11_atomic_init, "__c11_atomic_init")
-     DEF_ATOMIC(TOK___c11_atomic_store, "__c11_atomic_store")
-     DEF_ATOMIC(TOK___c11_atomic_load, "__c11_atomic_load")
-     DEF_ATOMIC(TOK___c11_atomic_exchange, "__c11_atomic_exchange")
-     DEF_ATOMIC(TOK___c11_atomic_compare_exchange_strong,
"__c11_atomic_compare_exchange_strong")
-     DEF_ATOMIC(TOK___c11_atomic_compare_exchange_weak,
"__c11_atomic_compare_exchange_weak")
-     DEF_ATOMIC(TOK___c11_atomic_fetch_add, "__c11_atomic_fetch_add")
-     DEF_ATOMIC(TOK___c11_atomic_fetch_sub, "__c11_atomic_fetch_sub")
-     DEF_ATOMIC(TOK___c11_atomic_fetch_or, "__c11_atomic_fetch_or")
-     DEF_ATOMIC(TOK___c11_atomic_fetch_xor, "__c11_atomic_fetch_xor")
-     DEF_ATOMIC(TOK___c11_atomic_fetch_and, "__c11_atomic_fetch_and")
+#define DEF_ATOMIC(ID) \
+     DEF(TOK_##__##ID, "__"#ID) \
+     DEF(TOK_##__##ID##_1, "__"#ID"_1") \
+     DEF(TOK_##__##ID##_2, "__"#ID"_2") \
+     DEF(TOK_##__##ID##_4, "__"#ID"_4") \
+     DEF(TOK_##__##ID##_8, "__"#ID"_8")
+
+     DEF_ATOMIC(atomic_store)
+     DEF_ATOMIC(atomic_load)
+     DEF_ATOMIC(atomic_exchange)
+     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

--
2.30.1



reply via email to

[Prev in Thread] Current Thread [Next in Thread]