From 3e20ddade31d9c392d8ccf7ec902172f4bb01c2b Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Fri, 10 Feb 2023 16:37:36 -0300 Subject: iconv: Remove _STRING_ARCH_unaligned usage Use put/get macros __builtin_bswap32 instead. It allows to remove the unaligned routines, the compiler will generate unaligned access if the ABI allows it. Checked on x86_64-linux-gnu and i686-linux-gnu. Reviewed-by: Wilco Dijkstra --- iconv/gconv_simple.c | 282 ++++----------------------------------------------- 1 file changed, 17 insertions(+), 265 deletions(-) (limited to 'iconv/gconv_simple.c') diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c index c50ffd3bf0..c60cffad4c 100644 --- a/iconv/gconv_simple.c +++ b/iconv/gconv_simple.c @@ -86,69 +86,22 @@ internal_ucs4_loop (struct __gconv_step *step, #if __BYTE_ORDER == __LITTLE_ENDIAN /* Sigh, we have to do some real work. */ size_t cnt; - uint32_t *outptr32 = (uint32_t *) outptr; - - for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) - *outptr32++ = bswap_32 (*(const uint32_t *) inptr); - - *inptrp = inptr; - *outptrp = (unsigned char *) outptr32; -#elif __BYTE_ORDER == __BIG_ENDIAN - /* Simply copy the data. */ - *inptrp = inptr + n_convert * 4; - *outptrp = __mempcpy (outptr, inptr, n_convert * 4); -#else -# error "This endianess is not supported." -#endif - - /* Determine the status. */ - if (*inptrp == inend) - result = __GCONV_EMPTY_INPUT; - else if (*outptrp + 4 > outend) - result = __GCONV_FULL_OUTPUT; - else - result = __GCONV_INCOMPLETE_INPUT; - - return result; -} - -#if !_STRING_ARCH_unaligned -static inline int -__attribute ((always_inline)) -internal_ucs4_loop_unaligned (struct __gconv_step *step, - struct __gconv_step_data *step_data, - const unsigned char **inptrp, - const unsigned char *inend, - unsigned char **outptrp, - const unsigned char *outend, - size_t *irreversible) -{ - const unsigned char *inptr = *inptrp; - unsigned char *outptr = *outptrp; - size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; - int result; - -# if __BYTE_ORDER == __LITTLE_ENDIAN - /* Sigh, we have to do some real work. */ - size_t cnt; for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4, outptr += 4) { - outptr[0] = inptr[3]; - outptr[1] = inptr[2]; - outptr[2] = inptr[1]; - outptr[3] = inptr[0]; + uint32_t val = get32 (inptr); + put32 (outptr, __builtin_bswap32 (val)); } *inptrp = inptr; *outptrp = outptr; -# elif __BYTE_ORDER == __BIG_ENDIAN +#elif __BYTE_ORDER == __BIG_ENDIAN /* Simply copy the data. */ *inptrp = inptr + n_convert * 4; *outptrp = __mempcpy (outptr, inptr, n_convert * 4); -# else -# error "This endianess is not supported." -# endif +#else +# error "This endianess is not supported." +#endif /* Determine the status. */ if (*inptrp == inend) @@ -160,7 +113,6 @@ internal_ucs4_loop_unaligned (struct __gconv_step *step, return result; } -#endif static inline int @@ -242,12 +194,9 @@ ucs4_internal_loop (struct __gconv_step *step, for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4) { - uint32_t inval; - + uint32_t inval = get32 (inptr); #if __BYTE_ORDER == __LITTLE_ENDIAN - inval = bswap_32 (*(const uint32_t *) inptr); -#else - inval = *(const uint32_t *) inptr; + inval = __builtin_bswap32 (inval); #endif if (__glibc_unlikely (inval > 0x7fffffff)) @@ -272,7 +221,7 @@ ucs4_internal_loop (struct __gconv_step *step, return __GCONV_ILLEGAL_INPUT; } - *((uint32_t *) outptr) = inval; + put32 (outptr, inval); outptr += sizeof (uint32_t); } @@ -290,75 +239,6 @@ ucs4_internal_loop (struct __gconv_step *step, return result; } -#if !_STRING_ARCH_unaligned -static inline int -__attribute ((always_inline)) -ucs4_internal_loop_unaligned (struct __gconv_step *step, - struct __gconv_step_data *step_data, - const unsigned char **inptrp, - const unsigned char *inend, - unsigned char **outptrp, - const unsigned char *outend, - size_t *irreversible) -{ - int flags = step_data->__flags; - const unsigned char *inptr = *inptrp; - unsigned char *outptr = *outptrp; - int result; - - for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4) - { - if (__glibc_unlikely (inptr[0] > 0x80)) - { - /* The value is too large. We don't try transliteration here since - this is not an error because of the lack of possibilities to - represent the result. This is a genuine bug in the input since - UCS4 does not allow such values. */ - if (irreversible == NULL) - /* We are transliterating, don't try to correct anything. */ - return __GCONV_ILLEGAL_INPUT; - - if (flags & __GCONV_IGNORE_ERRORS) - { - /* Just ignore this character. */ - ++*irreversible; - continue; - } - - *inptrp = inptr; - *outptrp = outptr; - return __GCONV_ILLEGAL_INPUT; - } - -# if __BYTE_ORDER == __LITTLE_ENDIAN - outptr[3] = inptr[0]; - outptr[2] = inptr[1]; - outptr[1] = inptr[2]; - outptr[0] = inptr[3]; -# else - outptr[0] = inptr[0]; - outptr[1] = inptr[1]; - outptr[2] = inptr[2]; - outptr[3] = inptr[3]; -# endif - outptr += 4; - } - - *inptrp = inptr; - *outptrp = outptr; - - /* Determine the status. */ - if (*inptrp == inend) - result = __GCONV_EMPTY_INPUT; - else if (*outptrp + 4 > outend) - result = __GCONV_FULL_OUTPUT; - else - result = __GCONV_INCOMPLETE_INPUT; - - return result; -} -#endif - static inline int __attribute ((always_inline)) @@ -453,11 +333,12 @@ internal_ucs4le_loop (struct __gconv_step *step, #if __BYTE_ORDER == __BIG_ENDIAN /* Sigh, we have to do some real work. */ size_t cnt; - uint32_t *outptr32 = (uint32_t *) outptr; - for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4) - *outptr32++ = bswap_32 (*(const uint32_t *) inptr); - outptr = (unsigned char *) outptr32; + for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4, outptr += 4) + { + uint32_t val = get32 (inptr); + put32 (outptr, __builtin_bswap32 (val)); + } *inptrp = inptr; *outptrp = outptr; @@ -480,59 +361,6 @@ internal_ucs4le_loop (struct __gconv_step *step, return result; } -#if !_STRING_ARCH_unaligned -static inline int -__attribute ((always_inline)) -internal_ucs4le_loop_unaligned (struct __gconv_step *step, - struct __gconv_step_data *step_data, - const unsigned char **inptrp, - const unsigned char *inend, - unsigned char **outptrp, - const unsigned char *outend, - size_t *irreversible) -{ - const unsigned char *inptr = *inptrp; - unsigned char *outptr = *outptrp; - size_t n_convert = MIN (inend - inptr, outend - outptr) / 4; - int result; - -# if __BYTE_ORDER == __BIG_ENDIAN - /* Sigh, we have to do some real work. */ - size_t cnt; - - for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4, outptr += 4) - { - outptr[0] = inptr[3]; - outptr[1] = inptr[2]; - outptr[2] = inptr[1]; - outptr[3] = inptr[0]; - } - - *inptrp = inptr; - *outptrp = outptr; -# elif __BYTE_ORDER == __LITTLE_ENDIAN - /* Simply copy the data. */ - *inptrp = inptr + n_convert * 4; - *outptrp = __mempcpy (outptr, inptr, n_convert * 4); -# else -# error "This endianess is not supported." -# endif - - /* Determine the status. */ - if (*inptrp == inend) - result = __GCONV_EMPTY_INPUT; - else if (*inptrp + 4 > inend) - result = __GCONV_INCOMPLETE_INPUT; - else - { - assert (*outptrp + 4 > outend); - result = __GCONV_FULL_OUTPUT; - } - - return result; -} -#endif - static inline int __attribute ((always_inline)) @@ -612,12 +440,9 @@ ucs4le_internal_loop (struct __gconv_step *step, for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4) { - uint32_t inval; - + uint32_t inval = get32 (inptr); #if __BYTE_ORDER == __BIG_ENDIAN - inval = bswap_32 (*(const uint32_t *) inptr); -#else - inval = *(const uint32_t *) inptr; + inval = __builtin_bswap32 (inval); #endif if (__glibc_unlikely (inval > 0x7fffffff)) @@ -642,7 +467,7 @@ ucs4le_internal_loop (struct __gconv_step *step, return __GCONV_ILLEGAL_INPUT; } - *((uint32_t *) outptr) = inval; + put32 (outptr, inval); outptr += sizeof (uint32_t); } @@ -663,79 +488,6 @@ ucs4le_internal_loop (struct __gconv_step *step, return result; } -#if !_STRING_ARCH_unaligned -static inline int -__attribute ((always_inline)) -ucs4le_internal_loop_unaligned (struct __gconv_step *step, - struct __gconv_step_data *step_data, - const unsigned char **inptrp, - const unsigned char *inend, - unsigned char **outptrp, - const unsigned char *outend, - size_t *irreversible) -{ - int flags = step_data->__flags; - const unsigned char *inptr = *inptrp; - unsigned char *outptr = *outptrp; - int result; - - for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4) - { - if (__glibc_unlikely (inptr[3] > 0x80)) - { - /* The value is too large. We don't try transliteration here since - this is not an error because of the lack of possibilities to - represent the result. This is a genuine bug in the input since - UCS4 does not allow such values. */ - if (irreversible == NULL) - /* We are transliterating, don't try to correct anything. */ - return __GCONV_ILLEGAL_INPUT; - - if (flags & __GCONV_IGNORE_ERRORS) - { - /* Just ignore this character. */ - ++*irreversible; - continue; - } - - *inptrp = inptr; - *outptrp = outptr; - return __GCONV_ILLEGAL_INPUT; - } - -# if __BYTE_ORDER == __BIG_ENDIAN - outptr[3] = inptr[0]; - outptr[2] = inptr[1]; - outptr[1] = inptr[2]; - outptr[0] = inptr[3]; -# else - outptr[0] = inptr[0]; - outptr[1] = inptr[1]; - outptr[2] = inptr[2]; - outptr[3] = inptr[3]; -# endif - - outptr += 4; - } - - *inptrp = inptr; - *outptrp = outptr; - - /* Determine the status. */ - if (*inptrp == inend) - result = __GCONV_EMPTY_INPUT; - else if (*inptrp + 4 > inend) - result = __GCONV_INCOMPLETE_INPUT; - else - { - assert (*outptrp + 4 > outend); - result = __GCONV_FULL_OUTPUT; - } - - return result; -} -#endif - static inline int __attribute ((always_inline)) -- cgit v1.2.3