> -----Original Message-----
> From: Jakub Jelinek <ja...@redhat.com>
> Sent: Wednesday, April 2, 2025 12:36
> To: Richard Biener <rguent...@suse.de>; Robert Dubner
<rdub...@symas.com>;
> James K. Lowden <jklow...@cobolworx.com>; Richard Sandiford
> <richard.sandif...@arm.com>
> Cc: gcc-patches@gcc.gnu.org
> Subject: [PATCH] fold-const, cobol: Add native_encode_wide_int and use
it
> in COBOL FE [PR119242]
>
> Hi!
>
> As has been mentioned earlier, various parts of the COBOL FE and the
> library
> aren't endian clean. In the library that means that for now we have to
> live with no support for big endian targets, but in the FE that means
> that as well as not being able to build cross-compilers from big endian
> or pdp endian hosts to little endian targets which are otherwise
> supported.
>
> The following patch attempts to fix one such spot, where it wants to
> encode
> in target byte ordering wide_int constants into 1, 2, 4, 8 or 16 bytes.
>
> We could wide_int_to_tree and then native_encode_expr, but so that we
> don't
> need to build the constants, the following patch exports from fold-
> const.cc
> a variant to native_encode_int which takes type and wide_int reference
> rather than an expression.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
I patched this into the cobolworx environment, and ran my full suite of
tests.
Everything passed. LGTM
>
> 2025-04-02 Jakub Jelinek <ja...@redhat.com>
>
> PR cobol/119242
> * fold-const.h (native_encode_wide_int): Declare.
> * fold-const.cc (native_encode_wide_int_1): New function template.
> (native_encode_wide_int): New function.
> (native_encode_int): Use native_encode_wide_int_1.
>
> * cobol/genapi.cc (binary_initial_from_float128): Use
> native_encode_wide_int.
>
> --- gcc/fold-const.h.jj 2025-03-28 10:38:23.165538304 +0100
> +++ gcc/fold-const.h 2025-04-02 14:31:22.921136606 +0200
> @@ -35,6 +35,8 @@ extern bool folding_cxx_constexpr;
> extern int native_encode_expr (const_tree, unsigned char *, int, int
off
> = -1);
> extern int native_encode_initializer (tree, unsigned char *, int,
> int off = -1, unsigned char * =
nullptr);
> +extern int native_encode_wide_int (tree, const wide_int_ref &,
> + unsigned char *, int, int off = -1);
> extern int native_encode_real (scalar_float_mode, const REAL_VALUE_TYPE
> *,
> unsigned char *, int, int off = -1);
> extern tree native_interpret_expr (tree, const unsigned char *, int);
> --- gcc/fold-const.cc.jj 2025-03-28 10:38:23.148538537 +0100
> +++ gcc/fold-const.cc 2025-04-02 14:30:15.072074312 +0200
> @@ -7465,15 +7465,17 @@ fold_plusminus_mult_expr (location_t loc
> return NULL_TREE;
> }
>
> -/* Subroutine of native_encode_expr. Encode the INTEGER_CST
> - specified by EXPR into the buffer PTR of length LEN bytes.
> +
> +/* Subroutine of native_encode_int and native_encode_wide_int. Encode
> the
> + integer VAL with type TYPE into the buffer PTR of length LEN bytes.
> Return the number of bytes placed in the buffer, or zero
> upon failure. */
>
> +template <typename T>
> static int
> -native_encode_int (const_tree expr, unsigned char *ptr, int len, int
off)
> +native_encode_wide_int_1 (tree type, const T &val,
> + unsigned char *ptr, int len, int off)
> {
> - tree type = TREE_TYPE (expr);
> int total_bytes;
> if (TREE_CODE (type) == BITINT_TYPE)
> {
> @@ -7516,7 +7518,7 @@ native_encode_int (const_tree expr, unsi
> int bitpos = byte * BITS_PER_UNIT;
> /* Extend EXPR according to TYPE_SIGN if the precision isn't a
> whole
> number of bytes. */
> - value = wi::extract_uhwi (wi::to_widest (expr), bitpos,
> BITS_PER_UNIT);
> + value = wi::extract_uhwi (val, bitpos, BITS_PER_UNIT);
>
> if (total_bytes > UNITS_PER_WORD)
> {
> @@ -7537,6 +7539,31 @@ native_encode_int (const_tree expr, unsi
> return MIN (len, total_bytes - off);
> }
>
> +/* Encode the integer VAL with type TYPE into the buffer PTR of length
> LEN
> + bytes.
> + Return the number of bytes placed in the buffer, or zero
> + upon failure. */
> +
> +int
> +native_encode_wide_int (tree type, const wide_int_ref &val,
> + unsigned char *ptr, int len, int off)
> +{
> + return native_encode_wide_int_1 (type, val, ptr, len, off);
> +}
> +
> +
> +/* Subroutine of native_encode_expr. Encode the INTEGER_CST
> + specified by EXPR into the buffer PTR of length LEN bytes.
> + Return the number of bytes placed in the buffer, or zero
> + upon failure. */
> +
> +static int
> +native_encode_int (const_tree expr, unsigned char *ptr, int len, int
off)
> +{
> + return native_encode_wide_int_1 (TREE_TYPE (expr), wi::to_widest
> (expr),
> + ptr, len, off);
> +}
> +
>
> /* Subroutine of native_encode_expr. Encode the FIXED_CST
> specified by EXPR into the buffer PTR of length LEN bytes.
> --- gcc/cobol/genapi.cc.jj 2025-04-02 10:36:25.517574640 +0200
> +++ gcc/cobol/genapi.cc 2025-04-02 14:31:36.373950683 +0200
> @@ -15216,25 +15216,19 @@ binary_initial_from_float128(cbl_field_t
> FIXED_WIDE_INT(128) i
> = FIXED_WIDE_INT(128)::from (real_to_integer (&value, &fail, 128),
> SIGNED);
>
> - /* ??? Use native_encode_* below. */
> retval = (char *)xmalloc(field->data.capacity);
> switch(field->data.capacity)
> {
> + tree type;
> case 1:
> - *(signed char *)retval = (signed char)i.slow ();
> - break;
> case 2:
> - *(signed short *)retval = (signed short)i.slow ();
> - break;
> case 4:
> - *(signed int *)retval = (signed int)i.slow ();
> - break;
> case 8:
> - *(signed long *)retval = (signed long)i.slow ();
> - break;
> case 16:
> - *(unsigned long *)retval = (unsigned long)i.ulow ();
> - *((signed long *)retval + 1) = (signed long)i.shigh ();
> + type = build_nonstandard_integer_type (field->data.capacity
> + * BITS_PER_UNIT, 0);
> + native_encode_wide_int (type, i, (unsigned char *)retval,
> + field->data.capacity);
> break;
> default:
> fprintf(stderr,
>
> Jakub