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>
This commit is contained in:
Adhemerval Zanella 2023-02-10 14:09:10 -03:00
parent 62d4c768a4
commit 5729e0e9af
10 changed files with 42 additions and 154 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View 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; \

View File

@ -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;

View File

@ -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; \
} \
} \

View File

@ -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) \

View 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; \
} \
}

View 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; \
}

View 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; \
}