Message ID | 20230213135558.3328727-7-adhemerval.zanella@linaro.org |
---|---|
State | New |
Headers | show |
Series | Remove _STRING_ARCH_unaligned | expand |
Hi Adhemerval,
What a mess that was, great cleanup! LGTM.
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
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))
OK
diff --git a/iconv/loop.c b/iconv/loop.c
index 9d8a7cceb3..b2a1727ad4 100644
--- a/iconv/loop.c
+++ b/iconv/loop.c
@@ -58,12 +58,7 @@
#include <libc-diag.h>
#undef FCTNAME2
-#if _STRING_ARCH_unaligned || !defined DEFINE_UNALIGNED
-# define FCTNAME2(name) name
-#else
-# define FCTNAME2(name) name##_unaligned
-#endif
-#define FCTNAME(name) FCTNAME2(name)
+#define FCTNAME(name) name
/* We need at least one byte for the next round. */
@@ -279,20 +274,9 @@ FCTNAME (LOOPFCT) (struct __gconv_step *step,
}
-/* Include the file a second time to define the function to handle
- unaligned access. */
-#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 unaligned
-
-# define DEFINE_UNALIGNED
-# include "loop.c"
-# undef DEFINE_UNALIGNED
-#else
-# if MAX_NEEDED_INPUT > 1
-# define SINGLE(fct) SINGLE2 (fct)
-# define SINGLE2(fct) fct##_single
+#if MAX_NEEDED_INPUT > 1
+# define SINGLE(fct) SINGLE2 (fct)
+# define SINGLE2(fct) fct##_single
static inline int
__attribute ((always_inline))
SINGLE(LOOPFCT) (struct __gconv_step *step,
@@ -302,37 +286,37 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
size_t *irreversible EXTRA_LOOP_DECLS)
{
mbstate_t *state = step_data->__statep;
-# ifdef LOOP_NEED_FLAGS
+# ifdef LOOP_NEED_FLAGS
int flags = step_data->__flags;
-# endif
-# ifdef LOOP_NEED_DATA
+# endif
+# ifdef LOOP_NEED_DATA
void *data = step->__data;
-# endif
+# endif
int result = __GCONV_OK;
unsigned char bytebuf[MAX_NEEDED_INPUT];
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
size_t inlen;
-# ifdef INIT_PARAMS
+# ifdef INIT_PARAMS
INIT_PARAMS;
-# endif
+# endif
-# ifdef UNPACK_BYTES
+# ifdef UNPACK_BYTES
UNPACK_BYTES
-# else
+# else
/* Add the bytes from the state to the input buffer. */
assert ((state->__count & 7) <= sizeof (state->__value));
for (inlen = 0; inlen < (size_t) (state->__count & 7); ++inlen)
bytebuf[inlen] = state->__value.__wchb[inlen];
-# endif
+# endif
/* Are there enough bytes in the input buffer? */
if (MIN_NEEDED_INPUT > 1
&& __builtin_expect (inptr + (MIN_NEEDED_INPUT - inlen) > inend, 0))
{
*inptrp = inend;
-# ifdef STORE_REST
+# ifdef STORE_REST
/* Building with -O3 GCC emits a `array subscript is above array
bounds' warning. GCC BZ #64739 has been opened for this. */
@@ -347,14 +331,14 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
inend = &bytebuf[inlen];
STORE_REST
-# else
+# else
/* We don't have enough input for another complete input
character. */
size_t inlen_after = inlen + (inend - inptr);
assert (inlen_after <= sizeof (state->__value.__wchb));
for (; inlen < inlen_after; inlen++)
state->__value.__wchb[inlen] = *inptr++;
-# endif
+# endif
return __GCONV_INCOMPLETE_INPUT;
}
@@ -406,11 +390,11 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
result = __GCONV_OK;
/* Clear the state buffer. */
-# ifdef CLEAR_STATE
+# ifdef CLEAR_STATE
CLEAR_STATE;
-# else
+# else
state->__count &= ~7;
-# endif
+# endif
}
else if (result == __GCONV_INCOMPLETE_INPUT)
{
@@ -419,11 +403,11 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
assert (inend != &bytebuf[MAX_NEEDED_INPUT]);
*inptrp += inend - bytebuf - (state->__count & 7);
-# ifdef STORE_REST
+# ifdef STORE_REST
inptrp = &inptr;
STORE_REST
-# else
+# else
/* We don't have enough input for another complete input
character. */
assert (inend - inptr > (state->__count & ~7));
@@ -432,14 +416,13 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
for (inlen = 0; inlen < inend - inptr; inlen++)
state->__value.__wchb[inlen] = inptr[inlen];
inptr = inend;
-# endif
+# endif
}
return result;
}
-# undef SINGLE
-# undef SINGLE2
-# endif
+# undef SINGLE
+# undef SINGLE2
# ifdef ONEBYTE_BODY
@@ -471,4 +454,3 @@ gconv_btowc (struct __gconv_step *step, unsigned char c)
#undef LOOP_NEED_STATE
#undef LOOP_NEED_FLAGS
#undef LOOP_NEED_DATA
-#undef unaligned
OK
diff --git a/iconv/skeleton.c b/iconv/skeleton.c
index 9423d3fc5a..61cff234ac 100644
--- a/iconv/skeleton.c
+++ b/iconv/skeleton.c
@@ -448,33 +448,6 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
size_t lirreversible = 0;
size_t *lirreversiblep = irreversible ? &lirreversible : NULL;
- /* The following assumes that encodings, which have a variable length
- what might unalign a buffer even though it is an aligned in the
- beginning, either don't have the minimal number of bytes as a divisor
- of the maximum length or have a minimum length of 1. This is true
- for all known and supported encodings.
- We use && instead of || to combine the subexpression for the FROM
- encoding and for the TO encoding, because usually one of them is
- INTERNAL, for which the subexpression evaluates to 1, but INTERNAL
- buffers are always aligned correctly. */
-#define POSSIBLY_UNALIGNED \
- (!_STRING_ARCH_unaligned \
- && (((FROM_LOOP_MIN_NEEDED_FROM != 1 \
- && FROM_LOOP_MAX_NEEDED_FROM % FROM_LOOP_MIN_NEEDED_FROM == 0) \
- && (FROM_LOOP_MIN_NEEDED_TO != 1 \
- && FROM_LOOP_MAX_NEEDED_TO % FROM_LOOP_MIN_NEEDED_TO == 0)) \
- || ((TO_LOOP_MIN_NEEDED_FROM != 1 \
- && TO_LOOP_MAX_NEEDED_FROM % TO_LOOP_MIN_NEEDED_FROM == 0) \
- && (TO_LOOP_MIN_NEEDED_TO != 1 \
- && TO_LOOP_MAX_NEEDED_TO % TO_LOOP_MIN_NEEDED_TO == 0))))
-#if POSSIBLY_UNALIGNED
- int unaligned;
-# define GEN_unaligned(name) GEN_unaligned2 (name)
-# define GEN_unaligned2(name) name##_unaligned
-#else
-# define unaligned 0
-#endif
-
#ifdef PREPARE_LOOP
PREPARE_LOOP
#endif
@@ -514,18 +487,6 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
}
#endif
-#if POSSIBLY_UNALIGNED
- unaligned =
- ((FROM_DIRECTION
- && ((uintptr_t) inptr % FROM_LOOP_MIN_NEEDED_FROM != 0
- || ((data->__flags & __GCONV_IS_LAST)
- && (uintptr_t) outbuf % FROM_LOOP_MIN_NEEDED_TO != 0)))
- || (!FROM_DIRECTION
- && (((data->__flags & __GCONV_IS_LAST)
- && (uintptr_t) outbuf % TO_LOOP_MIN_NEEDED_TO != 0)
- || (uintptr_t) inptr % TO_LOOP_MIN_NEEDED_FROM != 0)));
-#endif
-
while (1)
{
/* Remember the start value for this round. */
@@ -543,34 +504,14 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
SAVE_RESET_STATE (1);
#endif
- if (__glibc_likely (!unaligned))
- {
- if (FROM_DIRECTION)
- /* Run the conversion loop. */
- status = FROM_LOOP (step, data, inptrp, inend, &outbuf, outend,
- lirreversiblep EXTRA_LOOP_ARGS);
- else
- /* Run the conversion loop. */
- status = TO_LOOP (step, data, inptrp, inend, &outbuf, outend,
- lirreversiblep EXTRA_LOOP_ARGS);
- }
-#if POSSIBLY_UNALIGNED
+ if (FROM_DIRECTION)
+ /* Run the conversion loop. */
+ status = FROM_LOOP (step, data, inptrp, inend, &outbuf, outend,
+ lirreversiblep EXTRA_LOOP_ARGS);
else
- {
- if (FROM_DIRECTION)
- /* Run the conversion loop. */
- status = GEN_unaligned (FROM_LOOP) (step, data, inptrp, inend,
- &outbuf, outend,
- lirreversiblep
- EXTRA_LOOP_ARGS);
- else
- /* Run the conversion loop. */
- status = GEN_unaligned (TO_LOOP) (step, data, inptrp, inend,
- &outbuf, outend,
- lirreversiblep
- EXTRA_LOOP_ARGS);
- }
-#endif
+ /* Run the conversion loop. */
+ status = TO_LOOP (step, data, inptrp, inend, &outbuf, outend,
+ lirreversiblep EXTRA_LOOP_ARGS);
/* If we were called as part of an error handling module we
don't do anything else here. */
@@ -635,41 +576,18 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
SAVE_RESET_STATE (0);
#endif
- if (__glibc_likely (!unaligned))
- {
- if (FROM_DIRECTION)
- /* Run the conversion loop. */
- nstatus = FROM_LOOP (step, data, inptrp, inend,
- &outbuf, outerr,
- lirreversiblep
- EXTRA_LOOP_ARGS);
- else
- /* Run the conversion loop. */
- nstatus = TO_LOOP (step, data, inptrp, inend,
- &outbuf, outerr,
- lirreversiblep
- EXTRA_LOOP_ARGS);
- }
-#if POSSIBLY_UNALIGNED
+ if (FROM_DIRECTION)
+ /* Run the conversion loop. */
+ nstatus = FROM_LOOP (step, data, inptrp, inend,
+ &outbuf, outerr,
+ lirreversiblep
+ EXTRA_LOOP_ARGS);
else
- {
- if (FROM_DIRECTION)
- /* Run the conversion loop. */
- nstatus = GEN_unaligned (FROM_LOOP) (step, data,
- inptrp, inend,
- &outbuf,
- outerr,
- lirreversiblep
- EXTRA_LOOP_ARGS);
- else
- /* Run the conversion loop. */
- nstatus = GEN_unaligned (TO_LOOP) (step, data,
- inptrp, inend,
- &outbuf, outerr,
- lirreversiblep
- EXTRA_LOOP_ARGS);
- }
-#endif
+ /* Run the conversion loop. */
+ nstatus = TO_LOOP (step, data, inptrp, inend,
+ &outbuf, outerr,
+ lirreversiblep
+ EXTRA_LOOP_ARGS);
/* We must run out of output buffer space in this
rerun. */
OK
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)) diff --git a/iconv/loop.c b/iconv/loop.c index 9d8a7cceb3..b2a1727ad4 100644 --- a/iconv/loop.c +++ b/iconv/loop.c @@ -58,12 +58,7 @@ #include <libc-diag.h> #undef FCTNAME2 -#if _STRING_ARCH_unaligned || !defined DEFINE_UNALIGNED -# define FCTNAME2(name) name -#else -# define FCTNAME2(name) name##_unaligned -#endif -#define FCTNAME(name) FCTNAME2(name) +#define FCTNAME(name) name /* We need at least one byte for the next round. */ @@ -279,20 +274,9 @@ FCTNAME (LOOPFCT) (struct __gconv_step *step, } -/* Include the file a second time to define the function to handle - unaligned access. */ -#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 unaligned - -# define DEFINE_UNALIGNED -# include "loop.c" -# undef DEFINE_UNALIGNED -#else -# if MAX_NEEDED_INPUT > 1 -# define SINGLE(fct) SINGLE2 (fct) -# define SINGLE2(fct) fct##_single +#if MAX_NEEDED_INPUT > 1 +# define SINGLE(fct) SINGLE2 (fct) +# define SINGLE2(fct) fct##_single static inline int __attribute ((always_inline)) SINGLE(LOOPFCT) (struct __gconv_step *step, @@ -302,37 +286,37 @@ SINGLE(LOOPFCT) (struct __gconv_step *step, size_t *irreversible EXTRA_LOOP_DECLS) { mbstate_t *state = step_data->__statep; -# ifdef LOOP_NEED_FLAGS +# ifdef LOOP_NEED_FLAGS int flags = step_data->__flags; -# endif -# ifdef LOOP_NEED_DATA +# endif +# ifdef LOOP_NEED_DATA void *data = step->__data; -# endif +# endif int result = __GCONV_OK; unsigned char bytebuf[MAX_NEEDED_INPUT]; const unsigned char *inptr = *inptrp; unsigned char *outptr = *outptrp; size_t inlen; -# ifdef INIT_PARAMS +# ifdef INIT_PARAMS INIT_PARAMS; -# endif +# endif -# ifdef UNPACK_BYTES +# ifdef UNPACK_BYTES UNPACK_BYTES -# else +# else /* Add the bytes from the state to the input buffer. */ assert ((state->__count & 7) <= sizeof (state->__value)); for (inlen = 0; inlen < (size_t) (state->__count & 7); ++inlen) bytebuf[inlen] = state->__value.__wchb[inlen]; -# endif +# endif /* Are there enough bytes in the input buffer? */ if (MIN_NEEDED_INPUT > 1 && __builtin_expect (inptr + (MIN_NEEDED_INPUT - inlen) > inend, 0)) { *inptrp = inend; -# ifdef STORE_REST +# ifdef STORE_REST /* Building with -O3 GCC emits a `array subscript is above array bounds' warning. GCC BZ #64739 has been opened for this. */ @@ -347,14 +331,14 @@ SINGLE(LOOPFCT) (struct __gconv_step *step, inend = &bytebuf[inlen]; STORE_REST -# else +# else /* We don't have enough input for another complete input character. */ size_t inlen_after = inlen + (inend - inptr); assert (inlen_after <= sizeof (state->__value.__wchb)); for (; inlen < inlen_after; inlen++) state->__value.__wchb[inlen] = *inptr++; -# endif +# endif return __GCONV_INCOMPLETE_INPUT; } @@ -406,11 +390,11 @@ SINGLE(LOOPFCT) (struct __gconv_step *step, result = __GCONV_OK; /* Clear the state buffer. */ -# ifdef CLEAR_STATE +# ifdef CLEAR_STATE CLEAR_STATE; -# else +# else state->__count &= ~7; -# endif +# endif } else if (result == __GCONV_INCOMPLETE_INPUT) { @@ -419,11 +403,11 @@ SINGLE(LOOPFCT) (struct __gconv_step *step, assert (inend != &bytebuf[MAX_NEEDED_INPUT]); *inptrp += inend - bytebuf - (state->__count & 7); -# ifdef STORE_REST +# ifdef STORE_REST inptrp = &inptr; STORE_REST -# else +# else /* We don't have enough input for another complete input character. */ assert (inend - inptr > (state->__count & ~7)); @@ -432,14 +416,13 @@ SINGLE(LOOPFCT) (struct __gconv_step *step, for (inlen = 0; inlen < inend - inptr; inlen++) state->__value.__wchb[inlen] = inptr[inlen]; inptr = inend; -# endif +# endif } return result; } -# undef SINGLE -# undef SINGLE2 -# endif +# undef SINGLE +# undef SINGLE2 # ifdef ONEBYTE_BODY @@ -471,4 +454,3 @@ gconv_btowc (struct __gconv_step *step, unsigned char c) #undef LOOP_NEED_STATE #undef LOOP_NEED_FLAGS #undef LOOP_NEED_DATA -#undef unaligned diff --git a/iconv/skeleton.c b/iconv/skeleton.c index 9423d3fc5a..61cff234ac 100644 --- a/iconv/skeleton.c +++ b/iconv/skeleton.c @@ -448,33 +448,6 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, size_t lirreversible = 0; size_t *lirreversiblep = irreversible ? &lirreversible : NULL; - /* The following assumes that encodings, which have a variable length - what might unalign a buffer even though it is an aligned in the - beginning, either don't have the minimal number of bytes as a divisor - of the maximum length or have a minimum length of 1. This is true - for all known and supported encodings. - We use && instead of || to combine the subexpression for the FROM - encoding and for the TO encoding, because usually one of them is - INTERNAL, for which the subexpression evaluates to 1, but INTERNAL - buffers are always aligned correctly. */ -#define POSSIBLY_UNALIGNED \ - (!_STRING_ARCH_unaligned \ - && (((FROM_LOOP_MIN_NEEDED_FROM != 1 \ - && FROM_LOOP_MAX_NEEDED_FROM % FROM_LOOP_MIN_NEEDED_FROM == 0) \ - && (FROM_LOOP_MIN_NEEDED_TO != 1 \ - && FROM_LOOP_MAX_NEEDED_TO % FROM_LOOP_MIN_NEEDED_TO == 0)) \ - || ((TO_LOOP_MIN_NEEDED_FROM != 1 \ - && TO_LOOP_MAX_NEEDED_FROM % TO_LOOP_MIN_NEEDED_FROM == 0) \ - && (TO_LOOP_MIN_NEEDED_TO != 1 \ - && TO_LOOP_MAX_NEEDED_TO % TO_LOOP_MIN_NEEDED_TO == 0)))) -#if POSSIBLY_UNALIGNED - int unaligned; -# define GEN_unaligned(name) GEN_unaligned2 (name) -# define GEN_unaligned2(name) name##_unaligned -#else -# define unaligned 0 -#endif - #ifdef PREPARE_LOOP PREPARE_LOOP #endif @@ -514,18 +487,6 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, } #endif -#if POSSIBLY_UNALIGNED - unaligned = - ((FROM_DIRECTION - && ((uintptr_t) inptr % FROM_LOOP_MIN_NEEDED_FROM != 0 - || ((data->__flags & __GCONV_IS_LAST) - && (uintptr_t) outbuf % FROM_LOOP_MIN_NEEDED_TO != 0))) - || (!FROM_DIRECTION - && (((data->__flags & __GCONV_IS_LAST) - && (uintptr_t) outbuf % TO_LOOP_MIN_NEEDED_TO != 0) - || (uintptr_t) inptr % TO_LOOP_MIN_NEEDED_FROM != 0))); -#endif - while (1) { /* Remember the start value for this round. */ @@ -543,34 +504,14 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, SAVE_RESET_STATE (1); #endif - if (__glibc_likely (!unaligned)) - { - if (FROM_DIRECTION) - /* Run the conversion loop. */ - status = FROM_LOOP (step, data, inptrp, inend, &outbuf, outend, - lirreversiblep EXTRA_LOOP_ARGS); - else - /* Run the conversion loop. */ - status = TO_LOOP (step, data, inptrp, inend, &outbuf, outend, - lirreversiblep EXTRA_LOOP_ARGS); - } -#if POSSIBLY_UNALIGNED + if (FROM_DIRECTION) + /* Run the conversion loop. */ + status = FROM_LOOP (step, data, inptrp, inend, &outbuf, outend, + lirreversiblep EXTRA_LOOP_ARGS); else - { - if (FROM_DIRECTION) - /* Run the conversion loop. */ - status = GEN_unaligned (FROM_LOOP) (step, data, inptrp, inend, - &outbuf, outend, - lirreversiblep - EXTRA_LOOP_ARGS); - else - /* Run the conversion loop. */ - status = GEN_unaligned (TO_LOOP) (step, data, inptrp, inend, - &outbuf, outend, - lirreversiblep - EXTRA_LOOP_ARGS); - } -#endif + /* Run the conversion loop. */ + status = TO_LOOP (step, data, inptrp, inend, &outbuf, outend, + lirreversiblep EXTRA_LOOP_ARGS); /* If we were called as part of an error handling module we don't do anything else here. */ @@ -635,41 +576,18 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data, SAVE_RESET_STATE (0); #endif - if (__glibc_likely (!unaligned)) - { - if (FROM_DIRECTION) - /* Run the conversion loop. */ - nstatus = FROM_LOOP (step, data, inptrp, inend, - &outbuf, outerr, - lirreversiblep - EXTRA_LOOP_ARGS); - else - /* Run the conversion loop. */ - nstatus = TO_LOOP (step, data, inptrp, inend, - &outbuf, outerr, - lirreversiblep - EXTRA_LOOP_ARGS); - } -#if POSSIBLY_UNALIGNED + if (FROM_DIRECTION) + /* Run the conversion loop. */ + nstatus = FROM_LOOP (step, data, inptrp, inend, + &outbuf, outerr, + lirreversiblep + EXTRA_LOOP_ARGS); else - { - if (FROM_DIRECTION) - /* Run the conversion loop. */ - nstatus = GEN_unaligned (FROM_LOOP) (step, data, - inptrp, inend, - &outbuf, - outerr, - lirreversiblep - EXTRA_LOOP_ARGS); - else - /* Run the conversion loop. */ - nstatus = GEN_unaligned (TO_LOOP) (step, data, - inptrp, inend, - &outbuf, outerr, - lirreversiblep - EXTRA_LOOP_ARGS); - } -#endif + /* Run the conversion loop. */ + nstatus = TO_LOOP (step, data, inptrp, inend, + &outbuf, outerr, + lirreversiblep + EXTRA_LOOP_ARGS); /* We must run out of output buffer space in this rerun. */