about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2023-02-10 14:09:10 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2023-02-17 15:56:54 -0300
commit5729e0e9af590807df66a3db688008f9547bce9f (patch)
treeb4f50ff2f122c75e0833ec18c7256afa2c4c1ab7
parent62d4c768a4df59e4381464385b3a7246e6df6661 (diff)
downloadglibc-5729e0e9af590807df66a3db688008f9547bce9f.tar.gz
glibc-5729e0e9af590807df66a3db688008f9547bce9f.tar.xz
glibc-5729e0e9af590807df66a3db688008f9547bce9f.zip
iconv: Remove _STRING_ARCH_unaligned usage for get/set macros
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>
-rw-r--r--iconv/gconv_int.h28
-rw-r--r--iconv/loop.c73
-rw-r--r--iconv/skeleton.c67
-rw-r--r--iconvdata/iso-2022-jp-3.c2
-rw-r--r--iconvdata/unicode.c6
-rw-r--r--iconvdata/utf-16.c6
-rw-r--r--iconvdata/utf-32.c6
-rw-r--r--sysdeps/s390/utf16-utf32-z9.c4
-rw-r--r--sysdeps/s390/utf8-utf16-z9.c2
-rw-r--r--sysdeps/s390/utf8-utf32-z9.c2
10 files changed, 42 insertions, 154 deletions
diff --git a/iconv/gconv_int.h b/iconv/gconv_int.h
index da792a95f5..4b247a815f 100644
--- a/iconv/gconv_int.h
+++ b/iconv/gconv_int.h
@@ -26,6 +26,34 @@
 
 __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
diff --git a/iconv/loop.c b/iconv/loop.c
index 963c59ca9a..9d8a7cceb3 100644
--- a/iconv/loop.c
+++ b/iconv/loop.c
@@ -57,75 +57,10 @@
 #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
diff --git a/iconv/skeleton.c b/iconv/skeleton.c
index 673b474134..9423d3fc5a 100644
--- a/iconv/skeleton.c
+++ b/iconv/skeleton.c
@@ -204,73 +204,6 @@
 #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
diff --git a/iconvdata/iso-2022-jp-3.c b/iconvdata/iso-2022-jp-3.c
index 4a4d5a3046..d341a14f51 100644
--- a/iconvdata/iso-2022-jp-3.c
+++ b/iconvdata/iso-2022-jp-3.c
@@ -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;			      \
diff --git a/iconvdata/unicode.c b/iconvdata/unicode.c
index 2d131270b9..cc7999e36c 100644
--- a/iconvdata/unicode.c
+++ b/iconvdata/unicode.c
@@ -51,10 +51,10 @@
 	    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;
diff --git a/iconvdata/utf-16.c b/iconvdata/utf-16.c
index ad7dfa1a5c..edd1816c9d 100644
--- a/iconvdata/utf-16.c
+++ b/iconvdata/utf-16.c
@@ -55,10 +55,10 @@
 		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;						      \
 	    }								      \
 	}								      \
diff --git a/iconvdata/utf-32.c b/iconvdata/utf-32.c
index 01b6d95018..41be52bb3a 100644
--- a/iconvdata/utf-32.c
+++ b/iconvdata/utf-32.c
@@ -52,10 +52,10 @@
 	    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)	      \
diff --git a/sysdeps/s390/utf16-utf32-z9.c b/sysdeps/s390/utf16-utf32-z9.c
index d87eac0bdf..36c56ccbf7 100644
--- a/sysdeps/s390/utf16-utf32-z9.c
+++ b/sysdeps/s390/utf16-utf32-z9.c
@@ -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;							\
 	}								\
     }
diff --git a/sysdeps/s390/utf8-utf16-z9.c b/sysdeps/s390/utf8-utf16-z9.c
index 4d5510335e..33f7c64da4 100644
--- a/sysdeps/s390/utf8-utf16-z9.c
+++ b/sysdeps/s390/utf8-utf16-z9.c
@@ -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;							\
     }
 
diff --git a/sysdeps/s390/utf8-utf32-z9.c b/sysdeps/s390/utf8-utf32-z9.c
index c3a431d0a9..55321c519a 100644
--- a/sysdeps/s390/utf8-utf32-z9.c
+++ b/sysdeps/s390/utf8-utf32-z9.c
@@ -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;							\
     }