Jakub Jelinek <ja...@redhat.com> writes: > 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? > > 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); > }
I'm not sure the _1 template is worth it. wi::to_widest -> const wide_int_ref & should be very cheap (it doesn't for example construct a widest_int), so I think native_encode_int could call native_encode_wide_int. LGTM otherwise. Thanks, Richard > > +/* 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