tinycc-devel
[Top][All Lists]
Advanced

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

[Tinycc-devel] [PATCH 2/4] stdatomic: refactor atomic parser and generat


From: Dmitry Selyutin
Subject: [Tinycc-devel] [PATCH 2/4] stdatomic: refactor atomic parser and generator
Date: Sun, 14 Feb 2021 22:52:16 +0300

---
 tccgen.c | 137 ++++++++++++++++++++++++++++++-------------------------
 tcctok.h |  31 +++++--------
 2 files changed, 87 insertions(+), 81 deletions(-)

diff --git a/tccgen.c b/tccgen.c
index bad4659..44255e3 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -5753,91 +5753,95 @@ static inline int is_memory_model(const SValue *sv)
     return (((sv->type.t & VT_BTYPE) == VT_INT) && (sv->c.i < 6));
 }

+ST_FUNC void gen_atomic_init(int mode)
+{
+    vpushi(0); /* __ATOMIC_RELAXED */
+    gen_atomic_store(mode);
+}
+
+struct atomic_generator {
+    void (*const generate)(int mode);
+    char const *const template;
+};
+
 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[] = {
+    CType atom;
+    const char *template;
+    void (*generate)(int mode);
+    const int idx = ((size_t)atok - TOK___c11_atomic_init);
+    static const struct atomic_generator generators[] = {
         /*
-         * 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"},
+        {gen_atomic_init, "av?"},
+        {gen_atomic_store, "avm?"},
+        {gen_atomic_load, "Amv"},
+        {gen_atomic_exchange, "avmv"},
+        {gen_atomic_compare_exchange_strong, "apvmmb"},
+        {gen_atomic_compare_exchange_weak, "apvmmb"},
+        {gen_atomic_fetch_add, "avmv"},
+        {gen_atomic_fetch_sub, "avmv"},
+        {gen_atomic_fetch_or, "avmv"},
+        {gen_atomic_fetch_xor, "avmv"},
+        {gen_atomic_fetch_and, "avmv"},
     };

     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 */
+    memset(&atom, 0, sizeof(CType));
+    template = generators[idx].template;
+    argc = (strlen(template) - 1);

     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 = 3; break;
+            case 4: mode = 2; break;
+            case 2: mode = 1; break;
+            case 1: mode = 0; 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;

@@ -5865,7 +5869,18 @@ static void parse_atomic(int atok)
         expect("less parameters");
     skip(')');

-    gfunc_call(argc);
+    generators[idx].generate(mode);
+
+    switch (template[argc]) {
+    case 'a':
+    case 'A':
+    case 'm':
+        tcc_error("incorrect atomic tempate");
+
+    case 'b': vtop->type.t = VT_BOOL; break;
+    case 'v': vtop->type.t = atom.t; break;
+    case 'p': vtop->type.t = VT_SIZE_T; break;
+    }
 }

 ST_FUNC void unary(void)
diff --git a/tcctok.h b/tcctok.h
index 0fe3a8f..e872aa3 100644
--- a/tcctok.h
+++ b/tcctok.h
@@ -174,27 +174,18 @@
      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")
-
-#undef DEF_ATOMIC
+     DEF(TOK___c11_atomic_init, "__c11_atomic_init")
+     DEF(TOK___c11_atomic_store, "__c11_atomic_store")
+     DEF(TOK___c11_atomic_load, "__c11_atomic_load")
+     DEF(TOK___c11_atomic_exchange, "__c11_atomic_exchange")
+     DEF(TOK___c11_atomic_compare_exchange_strong,
"__c11_atomic_compare_exchange_strong")
+     DEF(TOK___c11_atomic_compare_exchange_weak,
"__c11_atomic_compare_exchange_weak")
+     DEF(TOK___c11_atomic_fetch_add, "__c11_atomic_fetch_add")
+     DEF(TOK___c11_atomic_fetch_sub, "__c11_atomic_fetch_sub")
+     DEF(TOK___c11_atomic_fetch_or, "__c11_atomic_fetch_or")
+     DEF(TOK___c11_atomic_fetch_xor, "__c11_atomic_fetch_xor")
+     DEF(TOK___c11_atomic_fetch_and, "__c11_atomic_fetch_and")

 /* pragma */
      DEF(TOK_pack, "pack")
--
2.30.0



reply via email to

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