]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
iconv: Remove _STRING_ARCH_unaligned usage for get/set macros
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Fri, 10 Feb 2023 17:09:10 +0000 (14:09 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Fri, 17 Feb 2023 18:56:54 +0000 (15:56 -0300)
And use a packed structure instead.  The compiler generates optimized
unaligned code if the architecture supports it.

Checked on x86_64-linux-gnu and i686-linux-gnu.

Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
iconv/gconv_int.h
iconv/loop.c
iconv/skeleton.c
iconvdata/iso-2022-jp-3.c
iconvdata/unicode.c
iconvdata/utf-16.c
iconvdata/utf-32.c
sysdeps/s390/utf16-utf32-z9.c
sysdeps/s390/utf8-utf16-z9.c
sysdeps/s390/utf8-utf32-z9.c

index da792a95f54534079bbaffcb3f3ba665e8c15e57..4b247a815f7be306a832f74b966e5d5708738680 100644 (file)
 
 __BEGIN_DECLS
 
+/* We have to provide support for machines which are not able to handled
+   unaligned memory accesses.  Some of the character encodings have
+   representations with a fixed width of 2 or 4 bytes.  */
+#define get16(addr)                                                    \
+({                                                                     \
+  const struct { uint16_t r; } __attribute__ ((__packed__)) *__ptr     \
+    = (__typeof(__ptr))(addr);                                         \
+  __ptr->r;                                                            \
+})
+#define get32(addr)                                                    \
+({                                                                     \
+  const struct { uint32_t r; } __attribute__ ((__packed__)) *__ptr     \
+    = (__typeof(__ptr))(addr);                                         \
+  __ptr->r;                                                            \
+})
+
+#define put16(addr, val)                                               \
+do {                                                                   \
+   struct { uint16_t r; } __attribute__ ((__packed__)) *__ptr          \
+    = (__typeof(__ptr))(addr);                                         \
+   __ptr->r = val;                                                     \
+} while (0)
+#define put32(addr, val)                                               \
+do {                                                                   \
+   struct { uint32_t r; } __attribute__ ((__packed__)) *__ptr          \
+    = (__typeof(__ptr))(addr);                                         \
+   __ptr->r = val;                                                     \
+} while (0)
 
 /* Structure for alias definition.  Simply two strings.  */
 struct gconv_alias
index 963c59ca9a5c57511ba658497ab8a3cadb11eae0..9d8a7cceb3c43d359090a1e5cf2c36cdcb3732bd 100644 (file)
 #include <stddef.h>
 #include <libc-diag.h>
 
-/* We have to provide support for machines which are not able to handled
-   unaligned memory accesses.  Some of the character encodings have
-   representations with a fixed width of 2 or 4 bytes.  But if we cannot
-   access unaligned memory we still have to read byte-wise.  */
 #undef FCTNAME2
 #if _STRING_ARCH_unaligned || !defined DEFINE_UNALIGNED
-/* We can handle unaligned memory access.  */
-# define get16(addr) *((const uint16_t *) (addr))
-# define get32(addr) *((const uint32_t *) (addr))
-
-/* We need no special support for writing values either.  */
-# define put16(addr, val) *((uint16_t *) (addr)) = (val)
-# define put32(addr, val) *((uint32_t *) (addr)) = (val)
-
 # define FCTNAME2(name) name
 #else
-/* Distinguish between big endian and little endian.  */
-# if __BYTE_ORDER == __LITTLE_ENDIAN
-#  define get16(addr) \
-     (((const unsigned char *) (addr))[1] << 8                               \
-      | ((const unsigned char *) (addr))[0])
-#  define get32(addr) \
-     (((((const unsigned char *) (addr))[3] << 8                             \
-       | ((const unsigned char *) (addr))[2]) << 8                           \
-       | ((const unsigned char *) (addr))[1]) << 8                           \
-      | ((const unsigned char *) (addr))[0])
-
-#  define put16(addr, val) \
-     ({ uint16_t __val = (val);                                                      \
-       ((unsigned char *) (addr))[0] = __val;                                \
-       ((unsigned char *) (addr))[1] = __val >> 8;                           \
-       (void) 0; })
-#  define put32(addr, val) \
-     ({ uint32_t __val = (val);                                                      \
-       ((unsigned char *) (addr))[0] = __val;                                \
-       __val >>= 8;                                                          \
-       ((unsigned char *) (addr))[1] = __val;                                \
-       __val >>= 8;                                                          \
-       ((unsigned char *) (addr))[2] = __val;                                \
-       __val >>= 8;                                                          \
-       ((unsigned char *) (addr))[3] = __val;                                \
-       (void) 0; })
-# else
-#  define get16(addr) \
-     (((const unsigned char *) (addr))[0] << 8                               \
-      | ((const unsigned char *) (addr))[1])
-#  define get32(addr) \
-     (((((const unsigned char *) (addr))[0] << 8                             \
-       | ((const unsigned char *) (addr))[1]) << 8                           \
-       | ((const unsigned char *) (addr))[2]) << 8                           \
-      | ((const unsigned char *) (addr))[3])
-
-#  define put16(addr, val) \
-     ({ uint16_t __val = (val);                                                      \
-       ((unsigned char *) (addr))[1] = __val;                                \
-       ((unsigned char *) (addr))[0] = __val >> 8;                           \
-       (void) 0; })
-#  define put32(addr, val) \
-     ({ uint32_t __val = (val);                                                      \
-       ((unsigned char *) (addr))[3] = __val;                                \
-       __val >>= 8;                                                          \
-       ((unsigned char *) (addr))[2] = __val;                                \
-       __val >>= 8;                                                          \
-       ((unsigned char *) (addr))[1] = __val;                                \
-       __val >>= 8;                                                          \
-       ((unsigned char *) (addr))[0] = __val;                                \
-       (void) 0; })
-# endif
-
 # define FCTNAME2(name) name##_unaligned
 #endif
 #define FCTNAME(name) FCTNAME2(name)
@@ -349,10 +284,6 @@ FCTNAME (LOOPFCT) (struct __gconv_step *step,
 #if !defined DEFINE_UNALIGNED && !_STRING_ARCH_unaligned \
     && MIN_NEEDED_INPUT != 1 && MAX_NEEDED_INPUT % MIN_NEEDED_INPUT == 0 \
     && MIN_NEEDED_OUTPUT != 1 && MAX_NEEDED_OUTPUT % MIN_NEEDED_OUTPUT == 0
-# undef get16
-# undef get32
-# undef put16
-# undef put32
 # undef unaligned
 
 # define DEFINE_UNALIGNED
@@ -540,8 +471,4 @@ gconv_btowc (struct __gconv_step *step, unsigned char c)
 #undef LOOP_NEED_STATE
 #undef LOOP_NEED_FLAGS
 #undef LOOP_NEED_DATA
-#undef get16
-#undef get32
-#undef put16
-#undef put32
 #undef unaligned
index 673b4741345727c093550393fe7b4c0c9925bce5..9423d3fc5af65024ca64fe5e9cb488fd9de0c34a 100644 (file)
 #endif
 
 
-/* Define macros which can access unaligned buffers.  These macros are
-   supposed to be used only in code outside the inner loops.  For the inner
-   loops we have other definitions which allow optimized access.  */
-#if _STRING_ARCH_unaligned
-/* We can handle unaligned memory access.  */
-# define get16u(addr) *((const uint16_t *) (addr))
-# define get32u(addr) *((const uint32_t *) (addr))
-
-/* We need no special support for writing values either.  */
-# define put16u(addr, val) *((uint16_t *) (addr)) = (val)
-# define put32u(addr, val) *((uint32_t *) (addr)) = (val)
-#else
-/* Distinguish between big endian and little endian.  */
-# if __BYTE_ORDER == __LITTLE_ENDIAN
-#  define get16u(addr) \
-     (((const unsigned char *) (addr))[1] << 8                               \
-      | ((const unsigned char *) (addr))[0])
-#  define get32u(addr) \
-     (((((const unsigned char *) (addr))[3] << 8                             \
-       | ((const unsigned char *) (addr))[2]) << 8                           \
-       | ((const unsigned char *) (addr))[1]) << 8                           \
-      | ((const unsigned char *) (addr))[0])
-
-#  define put16u(addr, val) \
-     ({ uint16_t __val = (val);                                                      \
-       ((unsigned char *) (addr))[0] = __val;                                \
-       ((unsigned char *) (addr))[1] = __val >> 8;                           \
-       (void) 0; })
-#  define put32u(addr, val) \
-     ({ uint32_t __val = (val);                                                      \
-       ((unsigned char *) (addr))[0] = __val;                                \
-       __val >>= 8;                                                          \
-       ((unsigned char *) (addr))[1] = __val;                                \
-       __val >>= 8;                                                          \
-       ((unsigned char *) (addr))[2] = __val;                                \
-       __val >>= 8;                                                          \
-       ((unsigned char *) (addr))[3] = __val;                                \
-       (void) 0; })
-# else
-#  define get16u(addr) \
-     (((const unsigned char *) (addr))[0] << 8                               \
-      | ((const unsigned char *) (addr))[1])
-#  define get32u(addr) \
-     (((((const unsigned char *) (addr))[0] << 8                             \
-       | ((const unsigned char *) (addr))[1]) << 8                           \
-       | ((const unsigned char *) (addr))[2]) << 8                           \
-      | ((const unsigned char *) (addr))[3])
-
-#  define put16u(addr, val) \
-     ({ uint16_t __val = (val);                                                      \
-       ((unsigned char *) (addr))[1] = __val;                                \
-       ((unsigned char *) (addr))[0] = __val >> 8;                           \
-       (void) 0; })
-#  define put32u(addr, val) \
-     ({ uint32_t __val = (val);                                                      \
-       ((unsigned char *) (addr))[3] = __val;                                \
-       __val >>= 8;                                                          \
-       ((unsigned char *) (addr))[2] = __val;                                \
-       __val >>= 8;                                                          \
-       ((unsigned char *) (addr))[1] = __val;                                \
-       __val >>= 8;                                                          \
-       ((unsigned char *) (addr))[0] = __val;                                \
-       (void) 0; })
-# endif
-#endif
-
-
 /* For conversions from a fixed width character set to another fixed width
    character set we can define RESET_INPUT_BUFFER in a very fast way.  */
 #if !defined RESET_INPUT_BUFFER && !defined SAVE_RESET_STATE
index 4a4d5a304664c949cf112fda47fc05872531dfad..d341a14f5170bdecb6936a8d051424a9c546449f 100644 (file)
@@ -91,7 +91,7 @@ enum
              if (__glibc_likely (outbuf + 4 <= outend))                      \
                {                                                             \
                  /* Write out the last character.  */                        \
-                 put32u (outbuf, ch);                                        \
+                 put32 (outbuf, ch);                                         \
                  outbuf += 4;                                                \
                  data->__statep->__count &= 7;                               \
                  data->__statep->__count |= ASCII_set;                       \
index 2d131270b961c55f90e33346263939c77d84b865..cc7999e36c50551f5bdbe4e9fc9628f4b04b4b9d 100644 (file)
            return (inptr == inend                                            \
                    ? __GCONV_EMPTY_INPUT : __GCONV_INCOMPLETE_INPUT);        \
                                                                              \
-         if (get16u (inptr) == BOM)                                          \
+         if (get16 (inptr) == BOM)                                           \
            /* Simply ignore the BOM character.  */                           \
            *inptrp = inptr += 2;                                             \
-         else if (get16u (inptr) == BOM_OE)                                  \
+         else if (get16 (inptr) == BOM_OE)                                   \
            {                                                                 \
              data->__flags |= __GCONV_SWAP;                                  \
              *inptrp = inptr += 2;                                           \
@@ -67,7 +67,7 @@
       if (__glibc_unlikely (outbuf + 2 > outend))                            \
        return __GCONV_FULL_OUTPUT;                                           \
                                                                              \
-      put16u (outbuf, BOM);                                                  \
+      put16 (outbuf, BOM);                                                   \
       outbuf += 2;                                                           \
     }                                                                        \
   swap = data->__flags & __GCONV_SWAP;
index ad7dfa1a5c902f2dad60e91d3df1642a83c3d566..edd1816c9d77b7a2f9d509d80f93f71aea1904fa 100644 (file)
                return (inptr == inend                                        \
                        ? __GCONV_EMPTY_INPUT : __GCONV_INCOMPLETE_INPUT);    \
                                                                              \
-             if (get16u (inptr) == BOM)                                      \
+             if (get16 (inptr) == BOM)                                       \
                /* Simply ignore the BOM character.  */                       \
                *inptrp = inptr += 2;                                         \
-             else if (get16u (inptr) == BOM_OE)                              \
+             else if (get16 (inptr) == BOM_OE)                               \
                {                                                             \
                  data->__flags |= __GCONV_SWAP;                              \
                  *inptrp = inptr += 2;                                       \
@@ -70,7 +70,7 @@
              if (__glibc_unlikely (outbuf + 2 > outend))                     \
                return __GCONV_FULL_OUTPUT;                                   \
                                                                              \
-             put16u (outbuf, BOM);                                           \
+             put16 (outbuf, BOM);                                            \
              outbuf += 2;                                                    \
            }                                                                 \
        }                                                                     \
index 01b6d950185143bddfb9222bea3979905a846f19..41be52bb3a7718d7b325c3c9cdb5d435aa7acf3f 100644 (file)
            return (inptr == inend                                            \
                    ? __GCONV_EMPTY_INPUT : __GCONV_INCOMPLETE_INPUT);        \
                                                                              \
-         if (get32u (inptr) == BOM)                                          \
+         if (get32 (inptr) == BOM)                                           \
            /* Simply ignore the BOM character.  */                           \
            *inptrp = inptr += 4;                                             \
-         else if (get32u (inptr) == BOM_OE)                                  \
+         else if (get32 (inptr) == BOM_OE)                                   \
            {                                                                 \
              data->__flags |= __GCONV_SWAP;                                  \
              *inptrp = inptr += 4;                                           \
@@ -69,7 +69,7 @@
       if (__glibc_unlikely (outbuf + 4 > outend))                            \
        return __GCONV_FULL_OUTPUT;                                           \
                                                                              \
-      put32u (outbuf, BOM);                                                  \
+      put32 (outbuf, BOM);                                                   \
       outbuf += 4;                                                           \
     }                                                                        \
   else if (__builtin_expect (data->__invocation_counter == 0, 0)             \
index d87eac0bdf60f344bf25b570db52af498fc5c5f9..36c56ccbf775f8d4dce7c0430fdb752994a69678 100644 (file)
@@ -171,7 +171,7 @@ gconv_end (struct __gconv_step *data)
          if (__glibc_unlikely (outbuf + 2 > outend))                   \
            return __GCONV_FULL_OUTPUT;                                 \
                                                                        \
-         put16u (outbuf, BOM_UTF16);                                   \
+         put16 (outbuf, BOM_UTF16);                                    \
          outbuf += 2;                                                  \
        }                                                               \
       else                                                             \
@@ -180,7 +180,7 @@ gconv_end (struct __gconv_step *data)
          if (__glibc_unlikely (outbuf + 4 > outend))                   \
            return __GCONV_FULL_OUTPUT;                                 \
                                                                        \
-         put32u (outbuf, BOM_UTF32);                                   \
+         put32 (outbuf, BOM_UTF32);                                    \
          outbuf += 4;                                                  \
        }                                                               \
     }
index 4d5510335e0041afe828ab73f02b3a67d47be838..33f7c64da4cfdede2a31c4cf880e5633ee1289ef 100644 (file)
@@ -211,7 +211,7 @@ gconv_end (struct __gconv_step *data)
       if (__glibc_unlikely (outbuf + 2 > outend))                      \
        return __GCONV_FULL_OUTPUT;                                     \
                                                                        \
-      put16u (outbuf, BOM_UTF16);                                      \
+      put16 (outbuf, BOM_UTF16);                                       \
       outbuf += 2;                                                     \
     }
 
index c3a431d0a98ae241db18966a1b743820b853425e..55321c519aa968b1b873826c0b7d04754a57eee6 100644 (file)
@@ -211,7 +211,7 @@ gconv_end (struct __gconv_step *data)
       if (__glibc_unlikely (outbuf + 4 > outend))                      \
        return __GCONV_FULL_OUTPUT;                                     \
                                                                        \
-      put32u (outbuf, BOM);                                            \
+      put32 (outbuf, BOM);                                             \
       outbuf += 4;                                                     \
     }