tinycc-devel
[Top][All Lists]
Advanced

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

[Tinycc-devel] [PATCH] stdatomic: ld/st/xchg/cmpxchg on simple types


From: Dmitry Selyutin
Subject: [Tinycc-devel] [PATCH] stdatomic: ld/st/xchg/cmpxchg on simple types
Date: Fri, 19 Mar 2021 01:13:48 +0300

Some complex types can still be small and simple enough to fit into
register. Other compilers allow some operations on these types, and it
seems to be quite a reasonable choice. From now on, we should be able
to compile the following artificial example:

    struct combo {
        uint16_t lo;
        uint16_t hi;
    };

    struct combo load(const _Atomic(struct combo) *atom)
    {
        return atomic_load(atom);
    }

    void store(_Atomic(struct combo) *atom, struct combo value)
    {
        atomic_store(atom, value);
    }

    struct combo xchg(_Atomic(struct combo) *atom, struct combo value)
    {
        return atomic_exchange(atom, value);
    }

    bool cmpxchg(_Atomic(struct combo) *atom,
            struct combo *cmp, struct combo xchg)
    {
        return atomic_compare_exchange_strong(atom, cmp, xchg);
    }

This might be useful for some corner cases, though it is quite likely
that many programmers will prefer operating on a single 32-bit value
instead of using the structure consisting of 16-bit pair.

Things will work as long as the overall structure size happens to be
the same as for any integer type we support in atomics.
---
 tccgen.c | 41 ++++++++++++++++++++++++++++++++---------
 1 file changed, 32 insertions(+), 9 deletions(-)

diff --git a/tccgen.c b/tccgen.c
index 11e6962..e49c1de 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -5766,6 +5766,7 @@ static void parse_atomic(int atok)
     int mode;
     size_t arg;
     SValue *call;
+    CType rv = {};
     CType atom = {};
     static const char *const templates[] = {
         /*
@@ -5824,7 +5825,7 @@ static void parse_atomic(int atok)
                 expect_arg("qualified pointer to atomic value", arg);
             if ((template[arg] == 'a') && (atom.t & VT_CONSTANT))
                 expect_arg("pointer to writable atomic", arg);
-            switch (btype_size(atom.t & VT_BTYPE)) {
+            switch (type_size(&atom, &(int){0})) {
             case 8: mode = 4; break;
             case 4: mode = 3; break;
             case 2: mode = 2; break;
@@ -5840,8 +5841,13 @@ static void parse_atomic(int atok)
             break;

         case 'v':
-            if (!is_integer_btype(vtop->type.t & VT_BTYPE))
-                expect_arg("integer type", arg);
+            if (atom.ref && is_integer_btype(vtop->type.t & VT_BTYPE)) {
+                if ((tok != TOK___atomic_store) &&
+                        (tok != TOK___atomic_load) &&
+                        (tok != TOK___atomic_exchange) &&
+                        (tok != TOK___atomic_compare_exchange))
+                    expect_arg("integer type", arg);
+            }
             break;

         case 'm':
@@ -5865,15 +5871,32 @@ static void parse_atomic(int atok)

     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");
+    case 'b':
+        vpushi(0);
+        PUT_R_RET(vtop, VT_BOOL);
+        break;
+
+    case 'p':
+        vpushs(0);
+        PUT_R_RET(vtop, VT_SIZE_T);
+        break;
+
+    case 'v':
+        vpush(&atom);
+        PUT_R_RET(vtop, atom.t);
+        break;
+
+    case '?':
+        vpushi(0);
+        PUT_R_RET(vtop, VT_VOID);
+        break;
+
+    default:
+        tcc_error("incorrect atomic template");
     }
+    vtop->r2 = VT_CONST;
 }

 ST_FUNC void unary(void)
--
2.30.1



reply via email to

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