Hi! The following patch changes some remaining __int128 uses in the FE into FIXED_WIDE_INT(128), i.e. emulated 128-bit integral type. The use of wide_int_to_tree directly from that rather than going through build_int_cst_type means we don't throw away the upper 64 bits of the values, so the emitting of constants needing full 128 bits can be greatly simplied. Plus all the #pragma GCC diagnostic ignored "-Wpedantic" spots aren't needed, we don't use the _Float128/__int128 types directly in the FE anymore.
Tested on x86_64-linux with make check-cobol, could you please test this on UAT/NIST? Note, PR119241/PR119242 bugs are still not fully fixed, I think the remaining problem is that several FE sources include ../../libgcobol/libgcobol.h and that header declares various APIs with __int128 and _Float128 types, so trying to build a cross-compiler on a host without __int128 and _Float128 will still fail miserably. I believe none of those APIs are actually used by the FE, so the question is what the FE needs from libgcobol.h and whether the rest could be wrapped with #ifndef IN_GCC or #ifndef IN_GCC_FRONTEND or something similar (those 2 macros are predefined when compiling the FE files). 2025-03-26 Jakub Jelinek <ja...@redhat.com> PR cobol/119242 * cobol/genutil.h (get_power_of_ten): Remove #pragma GCC diagnostic around declaration. * cobol/genapi.cc (psa_FldLiteralN): Change type of value from __int128 to FIXED_WIDE_INT(128). Remove #pragma GCC diagnostic around the declaration. Use wi::min_precision to determine minimum unsigned precision of the value. Use wi::neg_p instead of value < 0 tests and wi::set_bit_in_zero<FIXED_WIDE_INT(128)> to build sign bit. Handle field->data.capacity == 16 like 1, 2, 4 and 8, use wide_int_to_tree instead of build_int_cst. (mh_source_is_literalN): Remove #pragma GCC diagnostic around the definition. (binary_initial_from_float128): Likewise. * cobol/genutil.cc (get_power_of_ten): Remove #pragma GCC diagnostic before the definition. --- gcc/cobol/genutil.h.jj 2025-03-25 21:14:48.448384925 +0100 +++ gcc/cobol/genutil.h 2025-03-25 21:19:24.358620134 +0100 @@ -104,10 +104,7 @@ void get_binary_value( tree value, tree get_data_address( cbl_field_t *field, tree offset); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" FIXED_WIDE_INT(128) get_power_of_ten(int n); -#pragma GCC diagnostic pop void scale_by_power_of_ten_N(tree value, int N, bool check_for_fractional = false); --- gcc/cobol/genapi.cc.jj 2025-03-25 21:11:06.767409766 +0100 +++ gcc/cobol/genapi.cc 2025-03-25 21:22:28.038113833 +0100 @@ -3798,16 +3798,13 @@ psa_FldLiteralN(struct cbl_field_t *fiel // We are constructing a completely static constant structure, based on the // text string in .initial -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - __int128 value = 0; -#pragma GCC diagnostic pop + FIXED_WIDE_INT(128) value = 0; do { // This is a false do{}while, to isolate the variables: - // We need to convert data.initial to an __int128 value + // We need to convert data.initial to an FIXED_WIDE_INT(128) value char *p = const_cast<char *>(field->data.initial); int sign = 1; if( *p == '-' ) @@ -3903,24 +3900,24 @@ psa_FldLiteralN(struct cbl_field_t *fiel // We now need to calculate the capacity. - unsigned char *pvalue = (unsigned char *)&value; + unsigned int min_prec = wi::min_precision(value, UNSIGNED); int capacity; - if( *(uint64_t*)(pvalue + 8) ) + if( min_prec > 64 ) { // Bytes 15 through 8 are non-zero capacity = 16; } - else if( *(uint32_t*)(pvalue + 4) ) + else if( min_prec > 32 ) { // Bytes 7 through 4 are non-zero capacity = 8; } - else if( *(uint16_t*)(pvalue + 2) ) + else if( min_prec > 16 ) { // Bytes 3 and 2 capacity = 4; } - else if( pvalue[1] ) + else if( min_prec > 8 ) { // Byte 1 is non-zero capacity = 2; @@ -3940,11 +3937,15 @@ psa_FldLiteralN(struct cbl_field_t *fiel if( capacity < 16 && (field->attr & signable_e) ) { - if( value < 0 && (((pvalue[capacity-1] & 0x80) == 0 ))) + if( wi::neg_p (value) + && (value & wi::set_bit_in_zero<FIXED_WIDE_INT(128)>(capacity * 8 + - 1)) != 0 ) { capacity *= 2; } - else if( value >= 0 && (((pvalue[capacity-1] & 0x80) == 0x80 ))) + else if( !wi::neg_p (value) + && (value & wi::set_bit_in_zero<FIXED_WIDE_INT(128)>(capacity * 8 + - 1)) == 0 ) { capacity *= 2; } @@ -3964,86 +3965,15 @@ psa_FldLiteralN(struct cbl_field_t *fiel tree var_type; - if( field->data.capacity == 16 ) - { - /* GCC-13 has no provision for an int128 constructor. So, we use a - union for our necessary __int128. - - typedef union cblc_int128_t - { - unsigned char array16[16]; - __uint128 uval128; - __int128 sval128; - } cblc_int128_t; - - We build a constructor for the array16[], and then we use that - constructor in the constructor for the union. - */ - - // Build the constructor for array16 - tree array16_type = build_array_type_nelts(UCHAR, 16); - tree array_16_constructor = make_node(CONSTRUCTOR); - TREE_TYPE(array_16_constructor) = array16_type; - TREE_STATIC(array_16_constructor) = 1; - TREE_CONSTANT(array_16_constructor) = 1; - - for(int i=0; i<16; i++) - { - CONSTRUCTOR_APPEND_ELT( CONSTRUCTOR_ELTS(array_16_constructor), - build_int_cst_type(INT, i), - build_int_cst_type(UCHAR, - ((unsigned char *)&value)[i])); - } - - // The array16 constructor is ready to be used - - // So, we need a constructor for the union: - // Now we create the union: - var_type = cblc_int128_type_node; - - tree union_constructor = make_node(CONSTRUCTOR); - TREE_TYPE(union_constructor) = var_type; - TREE_STATIC(union_constructor) = 1; - TREE_CONSTANT(union_constructor) = 1; - - // point next_field to the first field of the union, and - // set the value to be the table constructor - tree next_field = TYPE_FIELDS(var_type); - CONSTRUCTOR_APPEND_ELT( CONSTRUCTOR_ELTS(union_constructor), - next_field, - array_16_constructor ); - - tree new_var_decl = gg_define_variable( var_type, - base_name, - vs_static); - DECL_INITIAL(new_var_decl) = union_constructor; - - field->data_decl_node = member(new_var_decl, "sval128"); - TREE_READONLY(field->data_decl_node) = 1; - TREE_CONSTANT(field->data_decl_node) = 1; - - // Convert the compile-time data.value to a run-time variable decl node: - sprintf(id_string, ".%ld", ++our_index); - strcpy(base_name, field->name); - strcat(base_name, id_string); - field->literal_decl_node = gg_define_variable(DOUBLE, id_string, vs_static); - TREE_READONLY(field->literal_decl_node) = 1; - TREE_CONSTANT(field->literal_decl_node) = 1; - tree initer = fold_convert (DOUBLE, field->data.value_of()); - DECL_INITIAL(field->literal_decl_node) = initer; - - } - else - { - // The value is 1, 2, 4, or 8 bytes, so an ordinary constructor can be used. - var_type = tree_type_from_size( field->data.capacity, - field->attr & signable_e); - tree new_var_decl = gg_define_variable( var_type, - base_name, - vs_static); - DECL_INITIAL(new_var_decl) = build_int_cst_type(var_type, value); - field->data_decl_node = new_var_decl; - } + // The value is 1, 2, 4, 8 or 16 bytes, so an ordinary constructor can be + // used. + var_type = tree_type_from_size( field->data.capacity, + field->attr & signable_e); + tree new_var_decl = gg_define_variable( var_type, + base_name, + vs_static); + DECL_INITIAL(new_var_decl) = wide_int_to_tree(var_type, value); + field->data_decl_node = new_var_decl; } static void @@ -13739,8 +13669,6 @@ mh_identical(cbl_refer_t &destref, return moved; } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" static bool mh_source_is_literalN(cbl_refer_t &destref, cbl_refer_t &sourceref, @@ -14013,7 +13941,6 @@ mh_source_is_literalN(cbl_refer_t &destr } return moved; } -#pragma GCC diagnostic pop static tree float_type_of(int n) @@ -15245,8 +15172,6 @@ real_powi10 (uint32_t x) return pow10; } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" char * binary_initial_from_float128(cbl_field_t *field, int rdigits, REAL_VALUE_TYPE value) @@ -15322,7 +15247,6 @@ binary_initial_from_float128(cbl_field_t return retval; } -#pragma GCC diagnostic pop static void --- gcc/cobol/genutil.cc.jj 2025-03-25 21:14:52.450330315 +0100 +++ gcc/cobol/genutil.cc 2025-03-25 21:19:08.743833202 +0100 @@ -1419,9 +1419,6 @@ get_data_address( cbl_field_t *field, } } -// Ignore pedantic because we know 128-bit computation is not ISO C++14. -#pragma GCC diagnostic ignored "-Wpedantic" - FIXED_WIDE_INT(128) get_power_of_ten(int n) { Jakub