info->limb_mode = SImode;
else
info->limb_mode = DImode;
+ info->abi_limb_mode = info->limb_mode;
info->big_endian = false;
info->extended = false;
return true;
@deftypefn {Target Hook} bool TARGET_C_BITINT_TYPE_INFO (int @var{n}, struct bitint_info *@var{info})
This target hook returns true if @code{_BitInt(@var{N})} is supported and
provides details on it. @code{_BitInt(@var{N})} is to be represented as
-series of @code{info->limb_mode}
-@code{CEIL (@var{N}, GET_MODE_PRECISION (info->limb_mode))} limbs,
+series of @code{info->abi_limb_mode}
+@code{CEIL (@var{N}, GET_MODE_PRECISION (info->abi_limb_mode))} limbs,
ordered from least significant to most significant if
@code{!info->big_endian}, otherwise from most significant to least
significant. If @code{info->extended} is false, the bits above or equal to
gcc_assert (ok);
if (info.extended)
return false;
- scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.limb_mode);
+ scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.abi_limb_mode);
if (TYPE_PRECISION (type) < GET_MODE_PRECISION (limb_mode))
return true;
else if (TYPE_PRECISION (type) == GET_MODE_PRECISION (limb_mode))
struct bitint_info info;
bool ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info);
gcc_assert (ok);
- scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.limb_mode);
+ scalar_int_mode limb_mode
+ = as_a <scalar_int_mode> (info.abi_limb_mode);
if (TYPE_PRECISION (type) <= GET_MODE_PRECISION (limb_mode))
{
gcc_assert ((size_t) sz <= clear_padding_unit);
unsigned prec = TYPE_PRECISION (TREE_TYPE (field));
bool ok = targetm.c.bitint_type_info (prec, &info);
gcc_assert (ok);
- scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.limb_mode);
+ scalar_int_mode limb_mode
+ = as_a <scalar_int_mode> (info.abi_limb_mode);
unsigned lprec = GET_MODE_PRECISION (limb_mode);
if (prec > lprec)
{
int cnt;
bool ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info);
gcc_assert (ok);
- scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.limb_mode);
+ scalar_int_mode limb_mode
+ = as_a <scalar_int_mode> (info.abi_limb_mode);
if (TYPE_PRECISION (type) <= GET_MODE_PRECISION (limb_mode))
{
SET_TYPE_MODE (type, limb_mode);
+ gcc_assert (info.abi_limb_mode == info.limb_mode);
cnt = 1;
}
else
{
SET_TYPE_MODE (type, BLKmode);
cnt = CEIL (TYPE_PRECISION (type), GET_MODE_PRECISION (limb_mode));
+ gcc_assert (info.abi_limb_mode == info.limb_mode
+ || !info.big_endian == !WORDS_BIG_ENDIAN);
}
TYPE_SIZE (type) = bitsize_int (cnt * GET_MODE_BITSIZE (limb_mode));
TYPE_SIZE_UNIT (type) = size_int (cnt * GET_MODE_SIZE (limb_mode));
(bitint_type_info,
"This target hook returns true if @code{_BitInt(@var{N})} is supported and\n\
provides details on it. @code{_BitInt(@var{N})} is to be represented as\n\
-series of @code{info->limb_mode}\n\
-@code{CEIL (@var{N}, GET_MODE_PRECISION (info->limb_mode))} limbs,\n\
+series of @code{info->abi_limb_mode}\n\
+@code{CEIL (@var{N}, GET_MODE_PRECISION (info->abi_limb_mode))} limbs,\n\
ordered from least significant to most significant if\n\
@code{!info->big_endian}, otherwise from most significant to least\n\
significant. If @code{info->extended} is false, the bits above or equal to\n\
#endif /* !CHECKING_P */
/* Target properties of _BitInt(N) type. _BitInt(N) is to be represented
- as series of limb_mode CEIL (N, GET_MODE_PRECISION (limb_mode)) limbs,
- ordered from least significant to most significant if !big_endian,
+ as series of abi_limb_mode CEIL (N, GET_MODE_PRECISION (abi_limb_mode))
+ limbs, ordered from least significant to most significant if !big_endian,
otherwise from most significant to least significant. If extended is
false, the bits above or equal to N are undefined when stored in a register
or memory, otherwise they are zero or sign extended depending on if
- it is unsigned _BitInt(N) or _BitInt(N) / signed _BitInt(N). */
+ it is unsigned _BitInt(N) or _BitInt(N) / signed _BitInt(N).
+ limb_mode is either the same as abi_limb_mode, or some narrower mode
+ in which _BitInt lowering should actually perform operations in and
+ what libgcc _BitInt helpers should use.
+ E.g. abi_limb_mode could be TImode which is something some processor
+ specific ABI would specify to use, but it would be desirable to handle
+ it as an array of DImode instead for efficiency.
+ Note, abi_limb_mode can be different from limb_mode only if big_endian
+ matches WORDS_BIG_ENDIAN. */
struct bitint_info {
- machine_mode limb_mode;
+ machine_mode abi_limb_mode, limb_mode;
bool big_endian;
bool extended;
};
tree type = TREE_TYPE (exp);
bool ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info);
gcc_assert (ok);
- scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.limb_mode);
+ scalar_int_mode limb_mode
+ = as_a <scalar_int_mode> (info.abi_limb_mode);
if (TYPE_PRECISION (type) <= GET_MODE_PRECISION (limb_mode))
{
cst = expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);