diff --git a/gcc/cobol/compare.cc b/gcc/cobol/compare.cc
index d04aad45d52..f9910c98dd8 100644
--- a/gcc/cobol/compare.cc
+++ b/gcc/cobol/compare.cc
@@ -608,7 +608,13 @@ alpha_compare_figconst( tree &left,
__gg__get_charmap(left_side.field->codeset.encoding);
charmap_t *charmap_right =
__gg__get_charmap(right_side.field->codeset.encoding);
- cbl_char_t char_right =
charmap_right->figconst_character(figconst_right);
+
+ // We know the result of this mapping has to be an 8-bit value, because
+ // all figconsts map to a single byte. HIGH-VALUE is a bit of a
problem,
+ // but when is it not? It usually will be 0xFF in the low-order byte,
so
+ // that's what we assume for now.
+
+ uint8_t char_right = charmap_right->figconst_character(figconst_right);
size_t nbytes;
char *converted;
@@ -671,12 +677,12 @@ alpha_compare(tree &left,
charmap_t *charmap_left =
__gg__get_charmap(left_side.field->codeset.encoding);
cbl_figconst_t figconst_left
= (cbl_figconst_t)(left_side.field->attr &
FIGCONST_MASK);
- cbl_char_t char_left =
charmap_left->figconst_character(figconst_left);
+ uint8_t char_left = charmap_left->figconst_character(figconst_left);
charmap_t *charmap_right =
__gg__get_charmap(right_side.field->codeset.encoding);
cbl_figconst_t figconst_right
= (cbl_figconst_t)(right_side.field->attr &
FIGCONST_MASK);
- cbl_char_t char_right =
charmap_right->figconst_character(figconst_right);
+ uint8_t char_right = charmap_right->figconst_character(figconst_right);
tree location_left;
tree location_right;
@@ -792,8 +798,10 @@ alpha_compare(tree &left,
// R.J.Dubner; 2026-05-08
static const long MAGIC_NUMBER = 16;
- // We are going to need the space character in this encoding space:
- cbl_char_t space_char = charmap_left->mapped_character(ascii_space);
+ // We are going to need the space character in this encoding space.
We
+ // know the result of the mapping has to fit into a byte, so we do
that
+ // to make things work in both little-endian and big-endian.
+ uint8_t space_char = charmap_left->mapped_character(ascii_space);
const char *the_routine;
switch( charmap_left->stride() )
{
@@ -1017,7 +1025,7 @@ numeric_alpha_compare(tree &left,
__gg__get_charmap(right_side.field->codeset.encoding);
cbl_figconst_t figconst_right
= (cbl_figconst_t)(right_side.field->attr &
FIGCONST_MASK);
- cbl_char_t char_right =
charmap_right->figconst_character(figconst_right);
+ uint8_t char_right = charmap_right->figconst_character(figconst_right);
if( left_side.field->type == FldLiteralN )
{
@@ -1266,8 +1274,8 @@ float_compare(tree &left,
const cbl_refer_t &right_side)
{
// left is a float, and if right is also a float it is smaller than
left
+ tree type = tree_type_from_field(left_side.field);
get_binary_value(left, left_side);
- tree type = TREE_TYPE(left);
tree rightv;
get_binary_value(rightv, right_side, type);
right = gg_define_variable(type);
diff --git a/gcc/cobol/genapi.cc b/gcc/cobol/genapi.cc
index d0482c2f4d6..3e2b251969b 100644
--- a/gcc/cobol/genapi.cc
+++ b/gcc/cobol/genapi.cc
@@ -2348,9 +2348,10 @@ parser_alter( cbl_perform_tgt_t *tgt )
}
void
-parser_goto( cbl_refer_t value_ref, size_t narg, cbl_label_t * const
labels[] )
- // This routine takes
-{
+parser_goto(const cbl_refer_t &value_ref,
+ size_t narg,
+ cbl_label_t * const labels[] )
+ {
// This is part of the Terrible Trio of parser_perform, parser_goto and
// parser_enter_[procedure]. parser_goto has an easier time of it than
// the other two, because it just has to jump from here to the entry
point
@@ -2390,11 +2391,8 @@ parser_goto( cbl_refer_t value_ref, size_t narg,
cbl_label_t * const labels[] )
{
// We will implement the two or more fanout with a switch statement.
- tree value = gg_define_int();
- get_binary_value( value,
- NULL,
- value_ref.field,
- refer_offset(value_ref));
+ tree value;
+ get_binary_value(value, value_ref, INT);
// value is properly 1 through nargs
@@ -2439,7 +2437,7 @@ parser_goto( cbl_refer_t value_ref, size_t narg,
cbl_label_t * const labels[] )
}
void
-parser_perform_times( cbl_label_t *proc_1, cbl_refer_t count )
+parser_perform_times( cbl_label_t *proc_1, const cbl_refer_t &count )
{
Analyze();
SHOW_PARSE
@@ -2451,7 +2449,8 @@ parser_perform_times( cbl_label_t *proc_1,
cbl_refer_t count )
char ach[32];
sprintf(ach, " proc_1 is at %p", static_cast<void*>(proc_1));
SHOW_PARSE_TEXT(ach)
- sprintf(ach, " proc_1->proc is %p",
static_cast<void*>(proc_1->structs.proc));
+ sprintf(ach, " proc_1->proc is %p",
+ static_cast<void*>(proc_1->structs.proc));
SHOW_PARSE_TEXT(ach)
SHOW_PARSE_END
}
@@ -2463,13 +2462,9 @@ parser_perform_times( cbl_label_t *proc_1,
cbl_refer_t count )
perform_is_armed = CURRENT_LINE_NUMBER ;
- tree counter = gg_define_variable(LONG);
-
// Get the count:
- get_binary_value( counter,
- NULL,
- count.field,
- refer_offset(count));
+ tree counter;
+ get_binary_value(counter, count, LONG);
// Make sure the initial count is valid:
WHILE( counter, gt_op, gg_cast(LONG, integer_zero_node) )
@@ -2588,7 +2583,7 @@ parser_perform(cbl_label_t *label, bool
suppress_nexting)
static void
internal_perform_through_times( cbl_label_t *proc_1,
cbl_label_t *proc_2,
- cbl_refer_t &count)
+ const cbl_refer_t &count)
{
Analyze();
SHOW_PARSE
@@ -2626,11 +2621,8 @@ internal_perform_through_times( cbl_label_t
*proc_1,
perform_is_armed = CURRENT_LINE_NUMBER ;
- tree counter = gg_define_variable(LONG);
- get_binary_value( counter,
- NULL,
- count.field,
- refer_offset(count));
+ tree counter;
+ get_binary_value(counter, count, LONG);
WHILE( counter, gt_op, gg_cast(LONG, integer_zero_node) )
{
internal_perform_through(proc_1, proc_2, true); // true means
suppress_nexting
@@ -4608,7 +4600,7 @@ parser_display_literal(const char *literal, bool
advance)
void
parser_display_internal(tree file_descriptor,
- cbl_refer_t refer,
+ const cbl_refer_t &refer,
bool advance)
{
Analyze();
@@ -5632,11 +5624,8 @@ program_end_stuff(cbl_refer_t refer,
{
// The field_type has a PICTURE string, so we need to convert
from the
// COBOL form to little-endian binary:
- tree value = gg_define_int128();
- get_binary_value( value,
- NULL,
- returner,
- size_t_zero_node);
+ tree value;
+ get_binary_value( value, returner, INT128);
gg_memcpy(gg_get_address_of(retval),
gg_get_address_of(value),
build_int_cst_type(SIZE_T, nbytes));
@@ -7210,11 +7199,8 @@ parser_relop_long(cbl_field_t *tgt,
}
tree tree_a = build_int_cst_type(LONG, avalue);
- tree tree_b = gg_define_variable(LONG);
- get_binary_value( tree_b,
- NULL,
- bref.field,
- refer_offset(bref) );
+ tree tree_b;
+ get_binary_value( tree_b, bref.field, LONG);
tree comp_res = gg_define_variable(LONG);
gg_assign(comp_res, gg_subtract(tree_a, tree_b));
@@ -7327,15 +7313,11 @@ parser_see_stop_run(struct cbl_refer_t
exit_status,
}
// It's a stop run. Return return-code to the operating system:
- tree returned_value = gg_define_variable(INT);
-
+ tree returned_value;
if( exit_status.field )
{
// There is an exit_status, so it wins:
- get_binary_value( returned_value,
- NULL,
- exit_status.field,
- refer_offset(exit_status));
+ get_binary_value( returned_value, exit_status.field, INT);
TRACE1
{
TRACE1_REFER(" exit_status ", exit_status, "")
@@ -7343,6 +7325,7 @@ parser_see_stop_run(struct cbl_refer_t exit_status,
}
else
{
+ returned_value = gg_define_variable(INT);
gg_assign(returned_value, gg_cast(INT,
current_function->var_decl_return));
TRACE1
{
@@ -7568,7 +7551,7 @@ parser_classify( cbl_field_t *tgt,
}
void
-parser_perform(const cbl_perform_tgt_t *tgt, cbl_refer_t how_many)
+parser_perform(const cbl_perform_tgt_t *tgt, const cbl_refer_t &how_many)
{
const cbl_field_t *N = how_many.field;
// No SHOW_PARSE here; we want to fall through:
@@ -8692,11 +8675,8 @@ parser_perform_inline_times(struct
cbl_perform_tgt_t *tgt,
}
gcc_assert(tgt);
- cbl_field_t *count = how_many.field;
- CHECK_FIELD(count);
- // This has to be on the stack, because performs can be nested
- tree counter = gg_define_variable(LONG);
+ tree counter = gg_define_variable(LONG);
/*
GOTO SETUP
@@ -8764,10 +8744,9 @@ parser_perform_inline_times(struct
cbl_perform_tgt_t *tgt,
SHOW_PARSE_END
}
- get_binary_value( counter,
- NULL,
- count,
- refer_offset(how_many));
+ tree initial_value;
+ get_binary_value(initial_value, how_many, LONG);
+ gg_assign(counter, initial_value);
SHOW_PARSE
{
@@ -9430,11 +9409,8 @@ parser_file_write( cbl_file_t *file,
tree t_advance = gg_define_variable(INT);
if(advance.field)
{
- tree value = gg_define_variable(INT);
- get_binary_value( value,
- NULL,
- advance.field,
- refer_offset(advance));
+ tree value;
+ get_binary_value( value, advance, INT);
gg_assign(t_advance, gg_cast(INT, value));
}
else
@@ -9741,7 +9717,7 @@ void
parser_file_start(struct cbl_file_t *file,
relop_t op,
int flk,
- cbl_refer_t length_ref )
+ const cbl_refer_t &length_ref )
{
Analyze();
SHOW_PARSE
@@ -9797,13 +9773,12 @@ parser_file_start(struct cbl_file_t *file,
flk = -1;
}
- tree length = gg_define_variable(SIZE_T);
- gg_assign(length, size_t_zero_node);
+ tree length = size_t_zero_node;
if( flk > 0 && !length_ref.field )
{
- // We need a length, and we don't have one. We have to calculate the
length
- // from the lengths of the fields that make up the specified key.
+ // We need a length, and we don't have one. We have to calculate the
+ // length from the lengths of the fields that make up the specified
key.
size_t combined_length = 0;
@@ -9818,14 +9793,11 @@ parser_file_start(struct cbl_file_t *file,
cbl_field_t *field = cbl_field_of(symbol_at(nfield));
combined_length += field->data.capacity();
}
- gg_assign(length, build_int_cst_type(SIZE_T, combined_length));
+ length = build_int_cst_type(SIZE_T, combined_length);
}
else if( flk > 0 )
{
- get_binary_value( length,
- NULL,
- length_ref.field,
- refer_offset(length_ref));
+ get_binary_value( length, length_ref, SIZE_T);
}
sv_is_i_o = true;
@@ -10820,7 +10792,7 @@ handle_gg_trim(cbl_field_t *tgt,
(arg.field->attr &
FIGCONST_MASK);
if( figconst )
{
- cbl_char_t figcst = charmap->figconst_character(figconst);
+ uint8_t figcst = charmap->figconst_character(figconst);
tree tfigcst = build_int_cst_type(UCHAR, figcst);
gg_assign(gg_indirect(char_p), tfigcst);
}
@@ -10878,7 +10850,7 @@ parser_trim( cbl_field_t *tgt,
(arg.field->attr &
FIGCONST_MASK);
if( figconst )
{
- cbl_char_t figcst = charmap->figconst_character(figconst);
+ uint8_t figcst = charmap->figconst_character(figconst);
tree tfigcst = build_int_cst_type(ULONG, figcst);
gg_memcpy(char_p,
@@ -11069,17 +11041,15 @@ parser_intrinsic_call_4( cbl_field_t *tgt,
static void
field_increment(cbl_field_t *fld )
{
- static tree value = gg_define_variable(INT128);
- static tree rdigits = gg_define_variable(INT);
-
- get_binary_value(value, rdigits, fld, size_t_zero_node);
- gg_assign( value,
- gg_add(value, gg_cast(SIZE_T, integer_one_node)));
+ // rdigits has to be zero.
+ tree value;
+ get_binary_value(value, fld, INT128);
+ gg_increment(value);
gg_call(VOID,
"__gg__int128_to_field",
gg_get_address_of(fld->var_decl_node),
- value,
- rdigits,
+ gg_cast(INT128, value),
+ integer_zero_node,
build_int_cst_type(INT, truncation_e),
null_pointer_node,
NULL_TREE );
@@ -11164,14 +11134,18 @@ parser_lsearch_start( cbl_label_t *name,
// Establish the initial value of our counter:
lsearch->counter = gg_define_variable(LONG);
- tree value = gg_define_int128();
+ tree value;
if(varying)
{
- get_binary_value(value, NULL, varying, size_t_zero_node);
+ get_binary_value(value, varying, SIZE_T);
}
else if( index )
{
- get_binary_value(value, NULL, index, size_t_zero_node);
+ get_binary_value(value, index, SIZE_T);
+ }
+ else
+ {
+ gcc_unreachable();
}
gg_assign(lsearch->counter, gg_cast(LONG, value));
@@ -11925,7 +11899,7 @@ parser_file_sort( cbl_file_t *workfile,
}
void
-parser_release( cbl_field_t *record_area )
+parser_release( const cbl_field_t *record_area )
{
Analyze();
SHOW_PARSE
@@ -13943,8 +13917,8 @@ parser_match_exception(cbl_field_t *index)
TRACE1
{
- tree index_val = gg_define_variable(INT);
- get_binary_value(index_val, NULL, index, size_t_zero_node);
+ tree index_val;
+ get_binary_value(index_val, index, INT);
TRACE1_INDENT
gg_printf("returned value is 0x%x (%d)", index_val, index_val,
NULL_TREE);
TRACE1_END
@@ -14683,7 +14657,9 @@ parser_local_add(struct cbl_field_t *new_var )
}
void
-parser_field_attr_set( cbl_field_t *tgt, cbl_field_attr_t attr, bool
on_off )
+parser_field_attr_set(const cbl_field_t *tgt,
+ cbl_field_attr_t attr,
+ bool on_off )
{
if( on_off )
{
diff --git a/gcc/cobol/genapi.h b/gcc/cobol/genapi.h
index 00c234521fe..773edacb775 100644
--- a/gcc/cobol/genapi.h
+++ b/gcc/cobol/genapi.h
@@ -47,7 +47,7 @@ typedef struct TREEPLET
} TREEPLET;
void parser_display_internal( tree file_descriptor,
- cbl_refer_t refer,
+ const cbl_refer_t &refer,
bool advance=DISPLAY_NO_ADVANCE);
void parser_first_statement( int lineno );
@@ -236,7 +236,7 @@ void
parser_perform( struct cbl_label_t *label, bool suppress_nexting=false );
void
-parser_perform_times( struct cbl_label_t *label, cbl_refer_t count );
+parser_perform_times( struct cbl_label_t *label, const cbl_refer_t &count
);
void
parser_perform_start( struct cbl_perform_tgt_t *tgt );
@@ -253,7 +253,7 @@ parser_perform_conditional_end( struct
cbl_perform_tgt_t *tgt );
* For an in-line loop body, tgt->from.type == LblLoop, and tgt->to is
NULL.
*/
void
-parser_perform( const cbl_perform_tgt_t *tgt, cbl_refer_t N );
+parser_perform( const cbl_perform_tgt_t *tgt, const cbl_refer_t &N );
/*
* A simple UNTIL loop uses 1 varys element. For VARY loops, the
@@ -346,7 +346,7 @@ callback_t *
parser_label_addr( struct cbl_label_t *label );
void
-parser_goto( cbl_refer_t value, size_t narg, cbl_label_t * const labels[]
);
+parser_goto( const cbl_refer_t &value, size_t narg, cbl_label_t * const
labels[] );
void
parser_alter( cbl_perform_tgt_t *tgt );
@@ -357,8 +357,9 @@ void
parser_set_numeric(struct cbl_field_t *tgt, ssize_t value);
void
-parser_field_attr_set( cbl_field_t *tgt, cbl_field_attr_t attr, bool
on_off = true );
-
+parser_field_attr_set(const cbl_field_t *tgt,
+ cbl_field_attr_t attr,
+ bool on_off = true );
void
parser_file_add(struct cbl_file_t *file);
@@ -376,8 +377,10 @@ parser_file_read( struct cbl_file_t *file,
int where );
void
-parser_file_start( struct cbl_file_t *file, relop_t op, int flk,
- cbl_refer_t = cbl_refer_t() );
+parser_file_start( struct cbl_file_t *file,
+ relop_t op,
+ int flk,
+ const cbl_refer_t &length_ref = cbl_refer_t() );
/*
* Write *field* to *file*. *after* is a bool where false
@@ -466,7 +469,7 @@ parser_file_merge( cbl_file_t *file,
cbl_perform_tgt_t *out_proc );
void
-parser_release( cbl_field_t *record_area );
+parser_release( const cbl_field_t *record_area );
void
parser_exception_file( cbl_field_t *tgt, cbl_file_t* file = NULL );
diff --git a/gcc/cobol/gengen.cc b/gcc/cobol/gengen.cc
index 03f79c56692..9ddd296f0e3 100644
--- a/gcc/cobol/gengen.cc
+++ b/gcc/cobol/gengen.cc
@@ -398,6 +398,12 @@ gg_cast(tree type, tree var)
}
#endif
+ if( TREE_CODE(type) == INTEGER_TYPE
+ && TREE_CODE(TREE_TYPE(var)) == REAL_TYPE )
+ {
+ return gg_trunc(type, var);
+ }
+
return fold_convert(type, var);
}
@@ -534,10 +540,8 @@ gg_show_type(tree type)
tree
gg_assign(tree dest, const tree source)
{
- // This does the equivalent of a C/C++ "dest = source". When X1 is
set, it
- // does some checking for conditions that can result in inefficient
code, so
- // that is useful during development when even an astute programmer
might
- // need an assist with keeping variable types straight.
+ // This does the equivalent of a C/C++ "dest = source". It does some
+ // checking for conditions that can result in inefficient code.
// This routine also provides for the possibility that the assignment
is
// for a source that is a function invocation, as in
@@ -578,7 +582,7 @@ gg_assign(tree dest, const tree source)
// the same. This is a compilation-time error, since we want the
caller to
// have sorted the types out explicitly. If we don't throw an error
here,
// the gimple reduction will do so. Better to do it here, when we
know
- // where we are.S
+ // where we are.
static const int debugging = 1;
if( debugging )
{
diff --git a/gcc/cobol/genmath.cc b/gcc/cobol/genmath.cc
index bdbfe8e691b..b3a89f9b899 100644
--- a/gcc/cobol/genmath.cc
+++ b/gcc/cobol/genmath.cc
@@ -392,7 +392,7 @@ largest_binary_term(size_t nA, const cbl_refer_t *A)
static bool
fast_add( size_t nC, cbl_num_result_t *C,
- size_t nA, cbl_refer_t *A,
+ size_t nA, const cbl_refer_t *A,
cbl_arith_format_t format,
const cbl_label_t *error,
const cbl_label_t *not_error)
@@ -426,29 +426,18 @@ fast_add( size_t nC, cbl_num_result_t *C,
// C, which is not how COBOL works.
tree A_value;
- if( refer_is_clean(A[0]) )
- {
- A_value = get_binary_value_tree(dest_type,
- NULL, // No rdigits
- A[0].field,
- integer_zero_node);
- }
- else
- {
- A_value = get_binary_value_tree(dest_type,
- NULL, // No rdigits
- A[0].field,
- refer_offset(A[0]));
- }
+ get_binary_value(A_value, A[0], dest_type);
+
if( refer_is_clean(C[0].refer) )
{
// We are accumulating into memory
- if(false && refer_is_working_storage(C[0].refer)
+ if(is_working_storage(C[0].refer)
&& C[0].refer.field->offset == 0 )
{
gg_assign( C[0].refer.field->data_decl_node,
-
gg_cast(TREE_TYPE(C[0].refer.field->data_decl_node), gg_add(
C[0].refer.field->data_decl_node, A_value)));
+
gg_cast(TREE_TYPE(C[0].refer.field->data_decl_node),
+ gg_add( C[0].refer.field->data_decl_node,
A_value)));
}
else
{
@@ -492,36 +481,10 @@ fast_add( size_t nC, cbl_num_result_t *C,
dest_addr = gg_cast(build_pointer_type(dest_type), dest_addr);
tree A_value;
- if( refer_is_clean(A[0]) )
- {
- A_value = get_binary_value_tree(dest_type,
- NULL, // No rdigits
- A[0].field,
- integer_zero_node);
- }
- else
- {
- A_value = get_binary_value_tree(dest_type,
- NULL, // No rdigits
- A[0].field,
- refer_offset(A[0]));
- }
+ get_binary_value(A_value, A[0], dest_type);
tree B_value;
- if( refer_is_clean(A[1]) )
- {
- B_value = get_binary_value_tree(dest_type,
- NULL, // No rdigits
- A[1].field,
- integer_zero_node);
- }
- else
- {
- B_value = get_binary_value_tree(dest_type,
- NULL, // No rdigits
- A[1].field,
- refer_offset(A[1]));
- }
+ get_binary_value(B_value, A[1], dest_type);
gg_assign( gg_indirect(dest_addr),
gg_add( A_value,
@@ -533,20 +496,14 @@ fast_add( size_t nC, cbl_num_result_t *C,
// We need to calculate the sum of all the A[] terms using
term_type as
// the intermediate type:
- tree sum = gg_define_variable(term_type);
- tree addend = gg_define_variable(term_type);
- get_binary_value( sum,
- NULL,
- A[0].field,
- refer_offset(A[0]));
+ tree sum ;
+ tree addend ;
+ get_binary_value(sum, A[0].field, term_type);
// Add in the rest of them:
for(size_t i=1; i<nA; i++)
{
- get_binary_value( addend,
- NULL,
- A[i].field,
- refer_offset(A[i]));
+ get_binary_value( addend, A[i].field, term_type);
gg_assign(sum, gg_add(sum, addend));
}
@@ -580,8 +537,8 @@ fast_add( size_t nC, cbl_num_result_t *C,
static bool
fast_subtract(size_t nC, cbl_num_result_t *C,
- size_t nA, cbl_refer_t *A,
- size_t nB, cbl_refer_t *B,
+ size_t nA, const cbl_refer_t *A,
+ size_t nB, const cbl_refer_t *B,
cbl_arith_format_t format,
const cbl_label_t *error,
const cbl_label_t *not_error)
@@ -633,20 +590,7 @@ fast_subtract(size_t nC, cbl_num_result_t *C,
// This is the simplest case of all. Just subtract A from C.
tree dest_type = tree_type_from_refer(C[0].refer);
tree A_value;
- if( refer_is_clean(A[0]) )
- {
- A_value = get_binary_value_tree(dest_type,
- NULL, // No rdigits
- A[0].field,
- integer_zero_node);
- }
- else
- {
- A_value = get_binary_value_tree(dest_type,
- NULL, // No rdigits
- A[0].field,
- refer_offset(A[0]));
- }
+ get_binary_value(A_value, A[0], dest_type);
if( format == giving_e )
{
// Make C = B - A
@@ -663,21 +607,7 @@ fast_subtract(size_t nC, cbl_num_result_t *C,
dest_addr = gg_cast(build_pointer_type(dest_type), dest_addr);
tree B_value;
- if( refer_is_clean(B[0]) )
- {
- B_value = get_binary_value_tree(dest_type,
- NULL, // No rdigits
- B[0].field,
- integer_zero_node);
- }
- else
- {
- B_value = get_binary_value_tree(dest_type,
- NULL, // No rdigits
- B[0].field,
- refer_offset(B[0]));
- }
-
+ get_binary_value(B_value, B[0], dest_type);
gg_assign( gg_indirect(dest_addr),
gg_cast(dest_type, gg_subtract( B_value,
A_value)));
@@ -713,14 +643,14 @@ fast_subtract(size_t nC, cbl_num_result_t *C,
// We need to calculate the sum of all the A[] terms using
term_type as
// the intermediate type:
- tree sum = gg_define_variable(term_type);
- tree addend = gg_define_variable(term_type);
- get_binary_value(sum, NULL, A[0].field, refer_offset(A[0]));
+ tree sum ;
+ tree addend ;
+ get_binary_value(sum, A[0].field, term_type);
// Add in the rest of them:
for(size_t i=1; i<nA; i++)
{
- get_binary_value(addend, NULL, A[i].field, refer_offset(A[i]));
+ get_binary_value(addend, A[i].field, term_type);
gg_assign(sum, gg_add(sum, addend));
}
//gg_printf("The intermediate sum is %ld\n", gg_cast(LONG, sum),
NULL_TREE);
@@ -728,7 +658,7 @@ fast_subtract(size_t nC, cbl_num_result_t *C,
if( format == giving_e )
{
// We now subtract the sum from B[0]
- get_binary_value(addend, NULL, B[0].field, refer_offset(B[0]));
+ get_binary_value(addend, B[0].field, term_type);
gg_assign(sum, gg_subtract(addend, sum));
}
@@ -762,8 +692,8 @@ fast_subtract(size_t nC, cbl_num_result_t *C,
static bool
fast_multiply(size_t nC, cbl_num_result_t *C,
- size_t nA, cbl_refer_t *A,
- size_t nB, cbl_refer_t *B)
+ size_t nA, const cbl_refer_t *A,
+ size_t nB, const cbl_refer_t *B)
{
bool retval = false;
if( all_results_integer(nC, C) )
@@ -794,14 +724,14 @@ fast_multiply(size_t nC, cbl_num_result_t *C,
{
// All the terms are things we can work with.
- tree valA = gg_define_variable(term_type);
- tree valB = gg_define_variable(term_type);
- get_binary_value(valA, NULL, A[0].field, refer_offset(A[0]));
+ tree valA ;
+ tree valB ;
+ get_binary_value(valA, A[0].field, term_type);
if( nB )
{
// This is a MULTIPLY Format 2
- get_binary_value(valB, NULL, B[0].field, refer_offset(B[0]));
+ get_binary_value(valB, B[0].field, term_type);
gg_assign(valA, gg_multiply(valA, valB));
}
@@ -834,8 +764,8 @@ fast_multiply(size_t nC, cbl_num_result_t *C,
static bool
fast_divide(size_t nC, cbl_num_result_t *C,
- size_t nA, cbl_refer_t *A,
- size_t nB, cbl_refer_t *B,
+ size_t nA, const cbl_refer_t *A,
+ size_t nB, const cbl_refer_t *B,
const cbl_refer_t &remainder)
{
bool retval = false;
@@ -867,16 +797,16 @@ fast_divide(size_t nC, cbl_num_result_t *C,
{
// All the terms are things we can work with.
- tree divisor = gg_define_variable(term_type);
- tree dividend = gg_define_variable(term_type);
+ tree divisor ;
+ tree dividend ;
tree quotient = NULL_TREE;
- get_binary_value(divisor, NULL, A[0].field, refer_offset(A[0]));
+ get_binary_value(divisor, A[0].field, term_type);
if( nB )
{
// This is a MULTIPLY Format 2, where we are dividing A into B
and
// assigning that to C
- get_binary_value(dividend, NULL, B[0].field, refer_offset(B[0]));
+ get_binary_value(dividend, B[0].field, term_type);
quotient = gg_define_variable(term_type);
// Yes, in this case the divisor and dividend are switched.
Things are
diff --git a/gcc/cobol/genutil.cc b/gcc/cobol/genutil.cc
index 142e0bb02e2..e2b7f1c293b 100644
--- a/gcc/cobol/genutil.cc
+++ b/gcc/cobol/genutil.cc
@@ -41,6 +41,7 @@
#include "toplev.h"
#include "function.h"
#include "fold-const.h"
+#include "target.h"
#include "../../libgcobol/ec.h"
#include "../../libgcobol/common-defs.h"
#include "util.h"
@@ -120,7 +121,7 @@ tree var_decl_dialects; // void* __gg__dialects
#endif
int
-get_scaled_rdigits(cbl_field_t *field)
+get_scaled_rdigits(const cbl_field_t *field)
{
int retval;
if( !(field->attr & scaled_e) )
@@ -149,7 +150,7 @@ get_scaled_rdigits(cbl_field_t *field)
}
int
-get_scaled_digits(cbl_field_t *field)
+get_scaled_digits(const cbl_field_t *field)
{
int retval;
if( !(field->attr & scaled_e) )
@@ -178,15 +179,16 @@ get_scaled_digits(cbl_field_t *field)
return retval;
}
-void
-get_integer_value(tree value, // We know this is a LONG
- cbl_field_t *field,
- tree offset,
- bool check_for_fractional_digits)
+#define CHECK_FOR_FRACTIONAL_DIGITS true
+static void
+giv_helper(tree retval, // We know this is a variable for the returned
value.
+ const cbl_field_t *field,
+ tree value, // Comes in as INT128
+ bool check_for_fractional_digits)
{
if( field->type == FldLiteralN && field->data.rdigits==0 )
{
- gg_assign(value, gg_cast(LONG, field->data_decl_node));
+ gg_assign(retval, gg_cast(TREE_TYPE(retval), field->data_decl_node));
return;
}
@@ -198,32 +200,47 @@ get_integer_value(tree value, // We know this is a
LONG
// If the field_i has rdigits, and if any of those rdigits are
non-zero, we
// return a 1 so that our caller can decide what to do.
- tree temp = gg_define_variable(INT128);
tree rdigits = gg_define_variable(INT);
if( field->attr & intermediate_e )
{
- // Get the binary value, which for 99V99 can be 1234, meaning 12.34
- get_binary_value(temp, NULL, field, offset);
-
// Pick up the run-time number of rdigits:
gg_assign(rdigits, gg_cast(INT, member(field, "rdigits")));
// Scale by the number of rdigits, which turns 12.34 into 12.
// When check_for_fractional_digits is true, __gg__rdigits will be
set
// to 1 for 12.34, and will be set to zero 12.00
- scale_by_power_of_ten(temp,
+ scale_by_power_of_ten(value,
gg_negate(rdigits),
check_for_fractional_digits);
}
else
{
- get_binary_value(temp, rdigits, field, offset);
- scale_by_power_of_ten_N(temp,
+ scale_by_power_of_ten_N(value,
-get_scaled_rdigits(field),
check_for_fractional_digits);
}
- gg_assign(value, gg_cast(TREE_TYPE(value), temp));
+ gg_assign(retval, gg_cast(TREE_TYPE(retval), value));
+ }
+
+static void
+get_integer_value(tree retval,
+ const cbl_field_t *field,
+ bool check_for_fractional_digits = false)
+ {
+ tree value;
+ get_binary_value(value, field, INT128);
+ giv_helper(retval, field, value, check_for_fractional_digits);
+ }
+
+static void
+get_integer_value(tree retval,
+ const cbl_refer_t &refer,
+ bool check_for_fractional_digits = false)
+ {
+ tree value;
+ get_binary_value(value, refer, INT128);
+ giv_helper(retval, refer.field, value, check_for_fractional_digits);
}
static
@@ -270,8 +287,7 @@ get_and_check_refstart_and_reflen( tree
refstart,// LONG returned value
// disaster, disaster is what you get."
get_integer_value(refstart,
- refer.refmod.from->field,
- refer_offset(*refer.refmod.from));
+ *refer.refmod.from);
gg_decrement(refstart);
gg_assign(refstart, gg_multiply(refstart, stride));
@@ -279,8 +295,7 @@ get_and_check_refstart_and_reflen( tree
refstart,// LONG returned value
{
// The length was specified, so that's what we return:
get_integer_value(reflen,
- refer.refmod.len->field,
- refer_offset(*refer.refmod.len));
+ *refer.refmod.len);
// Modify refer.length by stride:
gg_assign(reflen, gg_multiply(reflen, stride));
}
@@ -298,8 +313,7 @@ get_and_check_refstart_and_reflen( tree
refstart,// LONG returned value
// ec_bound_ref_mode_e checking is enabled:
get_integer_value(refstart,
- refer.refmod.from->field,
- refer_offset(*refer.refmod.from),
+ *refer.refmod.from,
CHECK_FOR_FRACTIONAL_DIGITS);
IF( var_decl_rdigits,
@@ -344,8 +358,7 @@ get_and_check_refstart_and_reflen( tree
refstart,// LONG returned value
if( refer.refmod.len )
{
get_integer_value(reflen,
- refer.refmod.len->field,
- refer_offset(*refer.refmod.len),
+ *refer.refmod.len,
CHECK_FOR_FRACTIONAL_DIGITS);
gg_assign(reflen, gg_multiply(reflen, stride));
IF( var_decl_rdigits,
@@ -429,7 +442,7 @@ get_depending_on_value_from_odo(tree retval,
cbl_field_t *odo)
*/
const cbl_enabled_exceptions_t&
enabled_exceptions(
cdf_enabled_exceptions() );
- cbl_field_t *depending_on;
+ const cbl_field_t *depending_on;
depending_on = cbl_field_of(symbol_at(odo->occurs.depending_on));
if( !enabled_exceptions.match(ec_bound_odo_e) )
@@ -437,8 +450,7 @@ get_depending_on_value_from_odo(tree retval,
cbl_field_t *odo)
// With no exception testing, just pick up the value. If there is an
error
// the programmer will simply have to live with the consequences.
get_integer_value(retval,
- depending_on,
- NULL);
+ depending_on);
return;
}
@@ -446,7 +458,6 @@ get_depending_on_value_from_odo(tree retval,
cbl_field_t *odo)
// between the lower and upper OCCURS limits:
get_integer_value(retval,
depending_on,
- NULL,
CHECK_FOR_FRACTIONAL_DIGITS);
IF( var_decl_rdigits, ne_op, integer_zero_node )
@@ -669,14 +680,12 @@ get_data_offset(const cbl_refer_t &refer, int
*pflags = NULL)
{
// With no exception testing, just pick up the value
get_integer_value(subscript,
- refer.subscripts[i].field,
- refer_offset(refer.subscripts[i]));
+ refer.subscripts[i]);
}
else
{
get_integer_value(subscript,
- refer.subscripts[i].field,
- refer_offset(refer.subscripts[i]),
+ refer.subscripts[i],
CHECK_FOR_FRACTIONAL_DIGITS);
IF( var_decl_rdigits,
ne_op,
@@ -776,15 +785,6 @@ get_data_offset(const cbl_refer_t &refer, int *pflags
= NULL)
return retval;
}
-static tree
-digit(tree location, int offset, int stride)
- {
- return gg_bitwise_and(gg_indirect(location,
- build_int_cst_type(SIZE_T,
- offset*stride)),
- build_int_cst_type(UCHAR, 0x0F));
- }
-
static const unsigned long pots[20] =
{
1ULL, // 00
@@ -809,631 +809,6 @@ static const unsigned long pots[20] =
10000000000000000000ULL, // 19
};
-
-static tree
-num_disp_dive(tree location, // UCHAR_P to first digit
- int digits, //
- bool signable,
- int stride)
- {
- tree retval;
- tree type;
- if( digits <= 9 )
- {
- type = signable ? INT : UINT;
- }
- else if( digits < 19 )
- {
- type = signable ? LONG : ULONG;
- }
- else
- {
- type = signable ? INT128 : UINT128;
- }
- retval = gg_define_variable(type);
-
- switch(digits)
- {
- case 1:
- {
- gg_assign(retval, gg_cast(type, digit(location, 0, stride)));
- break;
- }
- case 2:
- {
- tree term_a = gg_multiply(gg_cast(type, digit(location, 0,
stride)),
- build_int_cst_type(type, 10));
- tree term_b = gg_cast(type, digit(location, 1, stride));
- gg_assign(retval,
- gg_add(term_a,
- term_b));
- break;
- }
- case 3:
- {
- tree term_a = gg_multiply(gg_cast(type, digit(location, 0,
stride)),
- build_int_cst_type(type, 100));
- tree term_b = gg_multiply(gg_cast(type, digit(location, 1,
stride)),
- build_int_cst_type(type, 10));
- tree term_c = gg_cast(type, digit(location, 2, stride));
- gg_assign(retval,
- gg_add(term_a,
- gg_add(term_b,
- term_c)));
- break;
- }
- case 4:
- {
- tree term_a = gg_multiply(gg_cast(type, digit(location, 0,
stride)),
- build_int_cst_type(type, 1000));
- tree term_b = gg_multiply(gg_cast(type, digit(location, 1,
stride)),
- build_int_cst_type(type, 100));
- tree term_c = gg_multiply(gg_cast(type, digit(location, 2,
stride)),
- build_int_cst_type(type, 10));
- tree term_d = gg_cast(type, digit(location, 3, stride));
- gg_assign(retval,
- gg_add(term_a,
- gg_add(term_b,
- gg_add(term_c,
- term_d))));
- break;
- }
- default:
- {
- // digits is between 5 and 38
- int nright = digits/2;
- int nleft = digits - nright;
-
- int64_t right_factor = pots[nright];
- tree term_a = gg_multiply(num_disp_dive(location,
- nleft,
- signable,
- stride),
- build_int_cst_type(type, right_factor));
- tree term_b = num_disp_dive(gg_add(location,
- build_int_cst_type(SIZE_T,
-
nleft*stride)),
- nright,
- signable,
- stride);
- gg_assign(retval, gg_add(term_a, term_b));
- break;
- }
- }
-
- return retval;
- }
-
-static tree
-pd_dive(tree location, int nbytes, bool signable)
- {
- tree type;
- int digits = nbytes * 2;
- if( digits < 10 )
- {
- type = signable ? INT : UINT;
- }
- else if(digits < 20 )
- {
- type = signable ? LONG : ULONG;
- }
- else
- {
- type = signable ? INT128 : UINT128;
- }
- tree retval = gg_define_variable(type);
-
- tree ten2 = build_int_cst_type(type, 100);
- tree ten4 = build_int_cst_type(type, 10000);
- tree ten6 = build_int_cst_type(type, 1000000);
-
- tree t1 = integer_one_node;
- tree t2 = build_int_cst_type(INT, 2);
- tree t3 = build_int_cst_type(INT, 3);
-
- switch(nbytes)
- {
- case 0:
- retval = integer_zero_node;
- break;
- case 1:
- gg_assign(retval,
- gg_cast(type,
- gg_array_value(var_decl_dp2bin,
- gg_indirect(location))));
- break;
- case 2:
- {
- tree A = gg_multiply(gg_cast(type,
- gg_array_value(var_decl_dp2bin,
-
gg_indirect(location))),
- ten2);
- tree B = gg_cast(type,
- gg_array_value(var_decl_dp2bin,
- gg_indirect(location, t1)));
- gg_assign(retval, gg_add(A, B));
- break;
- }
- case 3:
- {
- tree A = gg_multiply(gg_cast(type,
- gg_array_value(var_decl_dp2bin,
- gg_indirect(location))),
- ten4);
- tree B = gg_multiply(gg_cast(type,
- gg_array_value(var_decl_dp2bin,
- gg_indirect(location, t1))),
- ten2);
- tree C = gg_cast(type,
- gg_array_value(var_decl_dp2bin,
- gg_indirect(location, t2)));
- gg_assign(retval, gg_add(A, gg_add(B, C)));
- break;
- }
- case 4:
- {
- tree A = gg_multiply(gg_cast(type,
- gg_array_value(var_decl_dp2bin,
- gg_indirect(location))),
- ten6);
- tree B = gg_multiply(gg_cast(type,
- gg_array_value(var_decl_dp2bin,
- gg_indirect(location, t1))),
- ten4);
- tree C = gg_multiply(gg_cast(type,
- gg_array_value(var_decl_dp2bin,
- gg_indirect(location, t2))),
- ten2);
- tree D = gg_cast(type,
- gg_array_value(var_decl_dp2bin,
- gg_indirect(location, t3)));
- gg_assign(retval, gg_add(A, gg_add(B, gg_add(C, D))));
- break;
- }
- default:
- {
- int nright = nbytes/2;
- int nleft = nbytes - nright;
- tree A = gg_multiply( gg_cast(type, pd_dive(location, nleft,
signable)),
- build_int_cst_type(type, pots[nright*2]));
- tree B = gg_cast(type, pd_dive(gg_add(location,
- build_int_cst_type(SIZE_T,
nleft)),
- nright,
- signable));
- gg_assign(retval, gg_add(A, B));
- break;
- }
- }
-
- return retval;
- }
-
-static tree
-get_pd_value(tree return_type, cbl_field_t *field, tree location)
- {
- tree retval = gg_define_variable(return_type);
- bool has_sign_nybble = !(field->attr & separate_e);
- bool signable = !!(field->attr & signable_e);
- int nbytes = field->data.capacity();
-
- gg_assign(retval,
- gg_cast(return_type,
- pd_dive(location,
- has_sign_nybble ? nbytes - 1 : nbytes,
- signable)));
- if( has_sign_nybble )
- {
- gg_assign(retval,
- gg_add(gg_multiply(retval,
- build_int_cst_type(return_type, 10)),
- gg_cast(return_type,
- gg_rshift(gg_indirect(location,
- build_int_cst_type(SIZE_T,
nbytes-1)),
- build_int_cst_type(SIZE_T, 4)))));
-
- IF( gg_bitwise_and(gg_indirect(location, build_int_cst_type(SIZE_T,
nbytes-1)),
- build_int_cst_type(UCHAR, 0x0F)),
- eq_op,
- build_int_cst_type(UCHAR, 0x0D) )
- {
- gg_assign(retval, gg_negate(retval));
- }
- ELSE
- {
- }
- ENDIF
- }
-
- return retval;
- }
-
-tree
-get_binary_value_tree(tree return_type,
- tree rdigits,
- cbl_field_t *field,
- tree field_offset,
- tree hilo
- )
- {
- tree retval = gg_define_variable(return_type);
-
- if( hilo )
- {
- gg_assign(hilo, integer_zero_node);
- }
-
- bool needs_scaling = true;
- static const bool debugging=false;
-
- // Very special case:
- if( strcmp(field->name, "ZEROS") == 0 )
- {
- gg_assign(retval, gg_cast(return_type, integer_zero_node));
- if( rdigits )
- {
- gg_assign(rdigits, gg_cast(TREE_TYPE(rdigits), integer_zero_node));
- }
- return retval;
- }
-
- switch(field->type)
- {
- case FldLiteralN:
- {
- if( return_type == FLOAT )
- {
- cbl_internal_error("cannot get %<float%> value from %s",
field->name);
- }
- else
- {
- if( rdigits )
- {
- gg_assign(rdigits, build_int_cst_type(TREE_TYPE(rdigits),
- field->data.rdigits));
- }
- gg_assign(retval, gg_cast(return_type, field->data_decl_node));
- }
- break;
- }
-
- case FldNumericDisplay:
- {
- charmap_t *charmap = __gg__get_charmap(field->codeset.encoding);
- int stride = charmap->stride();
- // Establish the source
- tree source_location = gg_define_variable(UCHAR_P);
- gg_assign(source_location, get_data_address(field, field_offset));
- tree sign_location;
- if( (field->attr & signable_e)
- && (field->attr & leading_e)
- && (field->attr & separate_e) )
- {
- sign_location = gg_define_variable(UCHAR_P);
- gg_assign(sign_location, source_location);
- gg_assign(source_location,
- gg_add(source_location,
- build_int_cst_type(SIZE_T, stride)));
- }
- // source_location points to the first digit.
-
- tree dive_value = num_disp_dive(source_location,
- field->data.digits,
- !!(field->attr & signable_e),
- stride);
- gg_assign(retval, gg_cast(return_type, dive_value));
-
- // retval is the absolute value of the numeric-display string.
-
- if( field->attr & signable_e )
- {
- // Because the source is signable, we have to check if it is
flagged
- // as negative:
- if( (field->attr & leading_e)
- && (field->attr & separate_e) )
- {
- // We already know that sign_location is established
- }
- else if( !(field->attr & leading_e)
- && (field->attr & separate_e) )
- {
- sign_location = gg_define_variable(UCHAR_P);
- gg_assign(sign_location,
- gg_add(source_location,
- build_int_cst_type(SIZE_T,
-
field->data.digits*stride)));
- }
- else if( (field->attr & leading_e)
- && !(field->attr & separate_e) )
- {
- sign_location = gg_define_variable(UCHAR_P);
- gg_assign(sign_location, source_location);
- }
- else //if( !(field->attr & leading_e)
- // && !(field->attr & separate_e) )
- {
- sign_location = gg_define_variable(UCHAR_P);
- gg_assign(sign_location,
- gg_add(source_location,
- build_int_cst_type(SIZE_T,
-
(field->data.digits-1)*stride)));
- }
- if( field->attr & separate_e )
- {
- IF( gg_indirect(sign_location),
- eq_op,
- build_int_cst_type(UCHAR,
- charmap->mapped_character(ascii_minus))
)
- {
- gg_assign(retval, gg_negate(retval));
- }
- ELSE
- {
- }
- ENDIF
- }
- else
- {
- if( charmap->is_like_ebcdic() )
- {
- IF( gg_indirect(sign_location),
- lt_op,
- build_int_cst_type(UCHAR, 0xF0) )
- {
- // The digit is less than the EBCDIC '0'
- gg_assign(retval, gg_negate(retval));
- }
- ELSE
- {
- }
- ENDIF
- }
- else
- {
- IF( gg_indirect(sign_location),
- gt_op,
- build_int_cst_type(UCHAR, 0x39) )
- {
- // The digit is greater than the ASCII '9'
- gg_assign(retval, gg_negate(retval));
- }
- ELSE
- {
- }
- ENDIF
- }
- }
- }
- break;
- }
-
- case FldNumericBinary:
- {
- // As of this writing, the source value is big-endian
- // We have to convert it to a little-endian destination.
- tree value = gg_define_variable(return_type);
- tree dest = gg_cast(build_pointer_type(UCHAR),
gg_get_address_of(value));
- tree source = get_data_address(field, field_offset);
-
- size_t dest_nbytes =
TREE_INT_CST_LOW(TYPE_SIZE_UNIT(return_type));
- size_t source_nbytes = field->data.capacity();
-
- if( debugging )
- {
- gg_printf("dest_bytes/source_bytes %ld/%ld\n",
- build_int_cst_type(SIZE_T, dest_nbytes),
- build_int_cst_type(SIZE_T, source_nbytes),
- NULL_TREE);
- gg_printf("Starting value: ", NULL_TREE);
- hex_dump(source, source_nbytes);
- gg_printf("\n", NULL_TREE);
- }
-
- if( dest_nbytes <= source_nbytes )
- {
- // Destination is too small. We will move what we can, throwing
away
- // the most significant source bytes:
- for(size_t i=0; i<dest_nbytes; i++)
- {
- gg_assign(gg_array_value(dest, i),
- gg_array_value(source, source_nbytes-1-i) );
- }
- }
- else
- {
- // Destination is too big. We'll need to fill the high-order
bytes with
- // either 0x00 for positive numbers, or 0xFF for negative
- tree extension = gg_define_variable(UCHAR);
- if( field->attr & signable_e )
- {
- IF( gg_array_value(gg_cast(build_pointer_type(SCHAR), source)),
- lt_op,
- gg_cast(SCHAR, integer_zero_node) )
- {
- gg_assign(extension, build_int_cst_type(UCHAR, 0xFF));
- }
- ELSE
- {
- gg_assign(extension, build_int_cst_type(UCHAR, 0));
- }
- ENDIF
- }
- else
- {
- gg_assign(extension, build_int_cst_type(UCHAR, 0));
- }
-
- // Flip the source end-for-end and put it into the dest:
- size_t i=0;
- while(i < source_nbytes)
- {
- gg_assign(gg_array_value(dest, i),
- gg_array_value(source, source_nbytes-1-i) );
- i += 1;
- }
- // Fill the extra high-end bytes with 0x00 or 0xFF extension
-
- while(i < dest_nbytes)
- {
- gg_assign(gg_array_value(dest, i),
- extension);
- i += 1;
- }
- }
- if( debugging )
- {
- gg_printf("Ending value: ", NULL_TREE);
- hex_dump(dest, dest_nbytes);
- gg_printf("\n", NULL_TREE);
- }
- retval = value;
- break;
- }
-
- case FldNumericBin5:
- case FldIndex:
- case FldPointer:
- {
- if( field->attr & intermediate_e )
- {
- // It is a intermediate, so rdigits has to come from the run-time
structure
- if( rdigits )
- {
- gg_assign(rdigits,
- gg_cast( TREE_TYPE(rdigits),
- member(field, "rdigits")));
- }
- }
- else
- {
- // It isn't an intermediate, so we can safely use field->rdigits
- if( rdigits )
- {
- gg_assign(rdigits,
- build_int_cst_type( TREE_TYPE(rdigits),
- get_scaled_rdigits(field)));
- }
- }
- tree source_address = get_data_address(field, field_offset);
- tree source_type = tree_type_from_field(field);
- if( debugging && rdigits)
- {
- gg_printf("get_binary_value bin5 rdigits: %d\n", rdigits,
NULL_TREE);
- }
-
- retval = gg_cast(return_type,
- gg_indirect(gg_cast(
build_pointer_type(source_type),
- source_address )));
- break;
- }
-
- case FldPacked:
- {
- if( rdigits )
- {
- gg_assign(rdigits,
- build_int_cst_type( TREE_TYPE(rdigits),
- get_scaled_rdigits(field)));
- }
- gg_assign(retval,
- get_pd_value(return_type,
- field,
- get_data_address( field, field_offset)));
- break;
- }
-
- case FldFloat:
- {
- // We are going to assume that the float value contains an integer.
- if( rdigits )
- {
- gg_assign(rdigits,
- gg_cast( TREE_TYPE(rdigits), integer_zero_node));
- }
- tree value = gg_define_variable(return_type);
- gg_assign(value, gg_cast(return_type,
- gg_call_expr( INT128,
- "__gg__integer_from_float128",
-
gg_get_address_of(field->var_decl_node),
- NULL_TREE)));
- needs_scaling = false;
- retval = value;
- break;
- }
-
- default:
- {
- char *err = xasprintf("%s(): We know not how to"
- " get a binary value from %s\n",
- __func__,
- cbl_field_type_str(field->type) );
- cbl_internal_error("%s", err);
- abort();
- break;
- }
- }
-
- if( needs_scaling )
- {
- if( field->attr & scaled_e )
- {
- if( field->data.rdigits < 0 )
- {
- // Hey, Dubner!
- // Should that test be != 0 rather than < 0? Maybe not; this
routine
- // is supposed to be for integers.
- tree value = gg_define_variable(return_type);
- gg_assign(value, retval);
- scale_by_power_of_ten_N(value, -field->data.rdigits);
- retval = value;
- }
- }
- }
- return retval;
- }
-
-tree
-get_binary_value_tree(tree return_type,
- tree rdigits,
- const cbl_refer_t &refer,
- tree hilo
- )
- {
- tree retval;
- if( refer_is_clean(refer) )
- {
- retval = get_binary_value_tree(return_type,
- rdigits,
- refer.field,
- integer_zero_node,
- hilo);
- }
- else
- {
- retval = get_binary_value_tree(return_type,
- rdigits,
- refer.field,
- refer_offset(refer),
- hilo);
- }
- return retval;
- }
-
-void
-get_binary_value( tree value,
- tree rdigits,
- cbl_field_t *field,
- tree field_offset,
- tree hilo
- )
- {
- tree return_type = TREE_TYPE(value);
- gg_assign(value, get_binary_value_tree( return_type,
- rdigits,
- field,
- field_offset,
- hilo ));
- }
-
tree
tree_type_from_field(const cbl_field_t *field)
{
@@ -2061,6 +1436,20 @@ refer_is_clean(const cbl_refer_t &refer)
;
}
+
+bool
+field_is_super_clean(const cbl_field_t *field)
+ {
+ return // refer.field->type == FldLiteralA ||
+ field->type == FldLiteralN
+ || !(field->attr & ( based_e
+ | linkage_e
+ | local_e
+ | intermediate_e
+ | any_length_e
+ | external_e)) ;
+ }
+
bool
refer_is_super_clean(const cbl_refer_t &refer)
{
@@ -2085,28 +1474,35 @@ refer_is_super_clean(const cbl_refer_t &refer)
}
bool
-refer_is_working_storage(const cbl_refer_t &refer)
+is_working_storage(const cbl_field_t *field)
{
- // This returns TRUE in cases where the refer.field->data_decl_node is
+ // This returns TRUE in cases where the field->data_decl_node is
// stored in .bss or .data, and is thus directly addressable.
- bool retval = !( refer.field->attr & ( based_e
- | linkage_e
- | local_e
- | intermediate_e) )
- || (refer.field->type == FldLiteralN);
+ bool retval = !( field->attr & ( based_e
+ | linkage_e
+ | local_e
+ | intermediate_e) )
+ || (field->type == FldLiteralN);
return retval;
}
-/* This routine returns the length portion of a refmod(start:length)
reference.
- It extracts both the start and the length so that it can add them
together
- to make sure that result falls within refer.capacity.
+bool
+is_working_storage(const cbl_refer_t &refer)
+ {
+ // This returns TRUE in cases where the refer.field->data_decl_node is
+ return is_working_storage(refer.field);
+ }
- This routine shouldn't be called unless there is refmod involved.
- */
static
tree // size_t
refer_refmod_length(const cbl_refer_t &refer)
{
+ /* This routine returns the length portion of a refmod(start:length)
+ reference. It extracts both the start and the length so that it can
add
+ them together to make sure that result falls within refer.capacity.
+
+ This routine shouldn't be called unless there is refmod involved.
+ */
Analyze();
REFER("refstart and reflen");
tree refstart = gg_define_variable(LONG);
@@ -2353,142 +1749,87 @@ is_pure_integer(const cbl_field_t *field)
case FldGroup:
case FldNumericBinary:
case FldFloat:
- case FldPacked:
- case FldNumericDisplay:
- case FldNumericEdited:
- case FldAlphaEdited:
- case FldLiteralA:
- case FldClass:
- case FldConditional:
- case FldForward:
- case FldSwitch:
- case FldDisplay:
- break;
- }
- return retval;
- }
-
-static bool
-binary_from_FldNumericBin5(tree &value, const cbl_refer_t &refer, tree
type)
- {
- bool retval = false;
-
- tree source_type = tree_type_from_field(refer.field);
-
- if( refer_is_working_storage(refer) )
- {
- if( !type )
- {
- type = source_type;
- }
-
- value = gg_define_variable(type);
-
- if( refer.field->offset == 0
- && TREE_CODE(TREE_TYPE(refer.field->data_decl_node)) ==
INTEGER_TYPE)
- {
- // This is the cleanest method: We can just pick up the original
base
- // data.
-
-//#define FOUND_THE_ALIASING_PROBLEM
-#ifdef FOUND_THE_ALIASING_PROBLEM
- // At the present writing, we can't just pick up the data_decl_node
data,
- // because the contents can be altered by pointer operations that
the
- // compiler doesn't know about. And we get errors, first noted
with the
- // results of fast_add (which uses *(data *) to change the data.)
Using
- // -fno-strict-aliasing makes the problem go away. Until we get
that
- // sorted out, we use the slightly less efficient method on the
other
- // side of the #else.
- gg_assign(value, gg_cast(type, refer.field->data_decl_node));
-#else
- tree base;
- base =
gg_cast(build_pointer_type(TREE_TYPE(refer.field->data_decl_node)),
- member(refer.field->var_decl_node,
"data"));
- gg_assign(value,
- gg_cast(type,
-
gg_indirect(gg_cast(build_pointer_type(source_type),
- base))));
-#endif
- }
- else
- {
- // We can't just pick up the stuff at data_decl_node. Either there
is
- // an offset from the 01 grandfather, or else there is a type
mismatch,
- // probably because of a REDEFINES. So, we do the equivalent of
- // *(type *)&thing;
- tree base;
- base = gg_cast(UCHAR_P,
gg_get_address(refer.field->data_decl_node));
- if( refer_is_clean(refer) )
- {
- if( refer.field->offset )
- {
- base = gg_add(base, build_int_cst_type(SIZE_T,
refer.field->offset));
- }
- }
- else
- {
- base = gg_add(base, refer_offset(refer));
- }
- gg_assign(value,
- gg_cast(type,
-
gg_indirect(gg_cast(build_pointer_type(source_type),
- base))));
- }
- retval = true;
- }
- else
- {
- if( !type )
- {
- type = tree_type_from_field(refer.field);
- }
-
- tree base;
- get_location(base, refer);
- value = gg_define_variable(type);
- gg_assign(value,
- gg_cast(type,
-
gg_indirect(gg_cast(build_pointer_type(source_type),
- base))));
- retval = true;
+ case FldPacked:
+ case FldNumericDisplay:
+ case FldNumericEdited:
+ case FldAlphaEdited:
+ case FldLiteralA:
+ case FldClass:
+ case FldConditional:
+ case FldForward:
+ case FldSwitch:
+ case FldDisplay:
+ break;
}
return retval;
}
-static bool
-binary_from_FldLiteralN(tree &value, const cbl_refer_t &refer, tree type)
+static void
+binary_from_FldNumericBin5(tree &value, const cbl_field_t *field, tree
dest_type)
{
- // The data_decl_node has the value we need.
+ value = gg_define_variable(dest_type);
+ safe_cast(value, field);
+ }
- tree source_type = tree_type_from_field(refer.field);
- if( !type )
- {
- type = source_type;
- }
+static void
+binary_from_FldNumericBin5(tree &value, const cbl_refer_t &refer, tree
dest_type)
+ {
+ value = gg_define_variable(dest_type);
+ safe_cast(value, refer);
+ }
- value = gg_define_variable(type);
- gg_assign(value, gg_cast(type, refer.field->data_decl_node));
+static void
+binary_from_FldLiteralN(tree &value, const cbl_field_t *field, tree
dest_type)
+ {
+ // The data_decl_node has the value we need.
+ value = gg_define_variable(dest_type);
+ gg_assign(value, gg_cast(dest_type, field->data_decl_node));
+ }
- return true;
+static void
+binary_from_FldLiteralN(tree &value, const cbl_refer_t &refer, tree type)
+ {
+ binary_from_FldLiteralN(value, refer.field, type);
}
+static void
+binary_from_FldNumericBinary(tree &value, const cbl_field_t *field, tree
type)
+ {
+ tree unflipped;
+ binary_from_FldNumericBin5(unflipped,
+ field,
+ tree_type_from_field(field));
+ // retval is in the machine's native encoding.
+ value = gg_define_variable(type);
+ if(!BYTES_BIG_ENDIAN)
+ {
+ // The actual return value gets the flipped bytes:
+ gg_assign(value, gg_cast(type, gg_bswap(unflipped)));
+ }
+ else
+ {
+ gg_assign(value, gg_cast(type, unflipped));
+ }
+ }
-bool
+static void
binary_from_FldNumericBinary(tree &value, const cbl_refer_t &refer, tree
type)
{
- bool retval = false;
-
- // get the value as its own type.
tree unflipped;
- retval = binary_from_FldNumericBin5(unflipped, refer, NULL_TREE);
- if( retval )
+ binary_from_FldNumericBin5(unflipped,
+ refer,
+ tree_type_from_field(refer.field));
+ // retval is in the machine's native encoding.
+ value = gg_define_variable(type);
+ if(!BYTES_BIG_ENDIAN)
{
// The actual return value gets the flipped bytes:
- value = gg_define_variable(type);
gg_assign(value, gg_cast(type, gg_bswap(unflipped)));
}
-
- return retval;
+ else
+ {
+ gg_assign(value, gg_cast(type, unflipped));
+ }
}
static void
@@ -2651,30 +1992,17 @@ d_and_q_num_disp( tree &retval, // We define
this return value
}
}
-bool
-binary_from_FldNumericDisplay(tree &value,
- const cbl_refer_t &refer,
- tree return_type)
+static void
+binary_from_numdisp(tree &value,
+ const cbl_field_t *field,
+ tree location,
+ tree return_type)
{
- // A return of false means we couldn't convert this value
- bool retval = false;
-
- tree source_type = tree_type_from_field(refer.field);
- if( !return_type )
- {
- return_type = source_type;
- }
-
// This is where we build the actual numeric value of the digits of the
// COBOL numeric display variable. It is up to the caller to interpret
// scaledness and rdigits and so forth.
value = gg_define_variable(return_type);
- // This is our address pointer, used for walking the digits.
- tree base = gg_define_variable(UCHAR_P);
-
- // This is the location of the byte holding the sign (if any)
- tree sign_location = gg_define_variable(UCHAR_P);
// This is the operational counter
tree digit_count = gg_define_variable(SIZE_T);
@@ -2683,78 +2011,71 @@ binary_from_FldNumericDisplay(tree &value,
// or 2 or 4 for utf16 and utf32.
tree stride;
- // This works for all forms of storage:
- gg_assign(base,
- gg_cast(build_pointer_type(UCHAR_P),
- member(refer.field->var_decl_node,"data")));
- if( !refer_is_clean(refer) )
- {
- gg_assign(base, gg_add(base, refer_offset(refer)));
- }
-
- gg_assign(digit_count, build_int_cst_type(SIZE_T,
refer.field->data.digits));
+ gg_assign(digit_count, build_int_cst_type(SIZE_T, field->data.digits));
- charmap_t *charmap = __gg__get_charmap(refer.field->codeset.encoding);
+ charmap_t *charmap = __gg__get_charmap(field->codeset.encoding);
size_t fstride = charmap->stride();
stride = build_int_cst_type(SIZE_T, fstride);
- if( refer.field->attr & signable_e )
+ tree sign_location = gg_define_variable(UCHAR_P);
+
+ if( field->attr & signable_e )
{
// The value is signable.
- if( refer.field->attr & separate_e )
+ if( field->attr & separate_e )
{
// The sign byte is separate from the digits
- if( refer.field->attr & leading_e )
+ if( field->attr & leading_e )
{
// separate & leading. sign_location is the first character.
- gg_assign(sign_location, base);
- gg_assign(base, gg_add(base, stride));
+ gg_assign(sign_location, location);
+ gg_assign(location, gg_add(location, stride));
}
else
{
// separate & trailing. The sign byte is after the last
character:
gg_assign(sign_location,
- gg_add(base,
+ gg_add(location,
build_int_cst_type(SIZE_T,
- refer.field->data.digits *
fstride)));
+ field->data.digits * fstride)));
}
}
else
{
// sign is internal:
- if( refer.field->attr & leading_e )
+ if( field->attr & leading_e )
{
// internal & leading
- gg_assign(sign_location, base);
+ gg_assign(sign_location, location);
}
else
{
// internal & trailing
gg_assign(sign_location,
- gg_add(base,
+ gg_add(location,
build_int_cst_type(SIZE_T,
fstride *
-
(refer.field->data.digits-1))));
+ (field->data.digits-1))));
}
}
}
- size_t digits = refer.field->data.digits;
+ size_t digits = field->data.digits;
// At this point, we have 'digits', which is the number of characters
at
- // 'base', The obvious thing is a multiply-and-accumulate loop, but
faster
- // code can result from allowing the middle-end to create overlapping.
+ // 'location', The obvious thing is a multiply-and-accumulate loop,
but
+ // faster code can result from allowing the middle-end to create
overlapping.
// This divide-and-conquer algorithm gives the middle-end that
flexibility.
// It runs about three times faster than a multiply-accumulate when
compiled
// with -O0, and about 2.8 times faster when compiled with -O2.
tree d_and_q;
- d_and_q_num_disp(d_and_q, base, digits, fstride);
+ d_and_q_num_disp(d_and_q, location, digits, fstride);
// d_and_q contains our value. We need to know if negativeness is
involved.
- if( refer.field->attr & signable_e )
+ if( field->attr & signable_e )
{
- if( refer.field->attr & separate_e )
+ if( field->attr & separate_e )
{
// If the sign location is a minus sign, we have to negate the
value.
IF( gg_indirect(sign_location),
@@ -2810,26 +2131,33 @@ binary_from_FldNumericDisplay(tree &value,
{
gg_assign(value, gg_cast(return_type, d_and_q));
}
+ }
- retval = true;
- return retval;
+static void
+binary_from_FldNumericDisplay(tree &value,
+ const cbl_field_t *field,
+ tree return_type)
+ {
+ tree location;
+ get_location(location, field);
+ binary_from_numdisp(value,
+ field,
+ location,
+ return_type);
}
- /* This is the GENERIC that creates
- static const unsigned char dp2bin[160] =
- {
- 00, 01, 02, 03, 04, 05, 06, 07, 8, 9, 0, 0, 0, 0, 0, 0, //
0x00
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 10, 10, 10, 10, 10, //
0x10
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 20, 20, 20, 20, 20, 20, //
0x20
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 30, 30, 30, 30, 30, 30, //
0x30
- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 40, 40, 40, 40, 40, 40, //
0x40
- 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 50, 50, 50, 50, 50, 50, //
0x50
- 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 60, 60, 60, 60, 60, 60, //
0x60
- 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 70, 70, 70, 70, 70, 70, //
0x70
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 80, 80, 80, 80, 80, 80, //
0x80
- 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 90, 90, 90, 90, 90, 90, //
0x90
- };
- */
+static void
+binary_from_FldNumericDisplay(tree &value,
+ const cbl_refer_t &refer,
+ tree return_type)
+ {
+ tree location;
+ get_location(location, refer);
+ binary_from_numdisp(value,
+ refer.field,
+ location,
+ return_type);
+ }
static tree
make_dp2bin_decl()
@@ -2995,46 +2323,29 @@ d_and_q_packed(tree &value, tree base, size_t
places)
}
}
-static bool
-binary_from_comp_3(tree &value, const cbl_refer_t &refer, tree type)
+static void
+b_from_c3(tree &value, const cbl_field_t *field, tree location, tree
type)
{
- bool retval = false;
-
// This is where we build the actual numeric value of the digits of the
// COBOL packed-decimal variable. It is up to the caller to interpret
// scaledness and rdigits and so forth.
- tree source_type = tree_type_from_field(refer.field);
-
- if( !type )
- {
- type = source_type;
- }
-
+ tree source_type = tree_type_from_field(field);
tree working = gg_define_variable(source_type);
- tree base = gg_define_variable(UCHAR_P);
- gg_assign(base,
- gg_cast(build_pointer_type(UCHAR_P),
- member(refer.field->var_decl_node,"data")));
- if( !refer_is_clean(refer) )
- {
- gg_assign(base, gg_add(base, refer_offset(refer)));
- }
-
// This is the location of the byte holding the sign nybble
tree sign_location = gg_define_variable(UCHAR_P);
// The sign nybble is in the last byte:
gg_assign(sign_location,
- gg_add(base,
+ gg_add(location,
build_int_cst_type(SIZE_T,
- refer.field->data.capacity()-1)));
+ field->data.capacity()-1)));
tree d_and_q;
// Pick up the binary value of the first capacity-1 places
d_and_q_packed(d_and_q,
- base,
- refer.field->data.capacity()-1);
+ location,
+ field->data.capacity()-1);
// Multiply that by 10
tree d_and_q_10 = gg_multiply(gg_cast(source_type, d_and_q),
build_int_cst_type(source_type, 10));
@@ -3057,85 +2368,166 @@ binary_from_comp_3(tree &value, const cbl_refer_t
&refer, tree type)
value = gg_define_variable(type);
gg_assign(value, gg_cast(type, working));
+ }
- retval = true;
- return retval;
+static void
+binary_from_comp_3(tree &value, const cbl_field_t *field, tree type)
+ {
+ tree location;
+ get_location(location, field);
+ b_from_c3(value, field, location, type);
}
-static bool
-binary_from_comp_6(tree &value, const cbl_refer_t &refer, tree type)
+static void
+binary_from_comp_3(tree &value, const cbl_refer_t &refer, tree type)
{
- bool retval = false;
+ tree location;
+ get_location(location, refer);
+ b_from_c3(value, refer.field, location, type);
+ }
+static void
+binary_from_comp_6(tree &value, const cbl_field_t *field, tree type)
+ {
// This is where we build the actual numeric value of the digits of the
// COBOL packed-decimal variable. It is up to the caller to interpret
// scaledness and rdigits and so forth.
value = gg_define_variable(type);
- tree base = gg_define_variable(UCHAR_P);
- gg_assign(base,
- gg_cast(build_pointer_type(UCHAR_P),
- member(refer.field->var_decl_node,"data")));
- if( !refer_is_clean(refer) )
- {
- gg_assign(base, gg_add(base, refer_offset(refer)));
- }
+ tree base;
+ get_location(base, field);
+ tree d_and_q;
+ d_and_q_packed(d_and_q,
+ base,
+ field->data.capacity());
+ gg_assign(value, gg_cast(type, d_and_q));
+ }
+static void
+binary_from_comp_6(tree &value, const cbl_refer_t &refer, tree type)
+ {
+ // This is where we build the actual numeric value of the digits of the
+ // COBOL packed-decimal variable. It is up to the caller to interpret
+ // scaledness and rdigits and so forth.
+ value = gg_define_variable(type);
+
+ tree base;
+ get_location(base, refer);
tree d_and_q;
d_and_q_packed(d_and_q,
base,
refer.field->data.capacity());
gg_assign(value, gg_cast(type, d_and_q));
+ }
- retval = true;
- return retval;
+static void
+binary_from_FldPacked(tree &value, const cbl_field_t *field, tree type)
+ {
+ if( field->attr & packed_no_sign_e )
+ {
+ binary_from_comp_6(value, field, type);
+ }
+ else
+ {
+ binary_from_comp_3(value, field, type);
+ }
}
-bool
+static void
binary_from_FldPacked(tree &value, const cbl_refer_t &refer, tree type)
{
- bool retval;
if( refer.field->attr & packed_no_sign_e )
{
- retval = binary_from_comp_6(value, refer, type);
+ binary_from_comp_6(value, refer, type);
}
else
{
- retval = binary_from_comp_3(value, refer, type);
+ binary_from_comp_3(value, refer, type);
}
- return retval;
}
-static
-bool binary_from_FldFloat(tree &value, const cbl_refer_t &refer, tree
type)
+static void
+binary_from_FldFloat(tree &value, const cbl_field_t *field, tree type)
{
- tree source_type = tree_type_from_field(refer.field);
+ value = gg_define_variable(type);
+ safe_cast(value, field);
+ }
+
+static void
+binary_from_FldFloat(tree &value, const cbl_refer_t &refer, tree type)
+ {
+ value = gg_define_variable(type);
+ safe_cast(value, refer);
+ }
+
+void
+get_binary_value(tree &value, const cbl_field_t *field, tree type)
+ {
+ /* There are other get binary value routines. This one is intended to
be the
+ "best in class" version, incorporating everything that's been
learned
+ about the process, and incorporating compiler SSA guidelines. */
- if( !type )
+ if( (field->attr & FIGCONST_MASK) == zero_value_e )
{
- type = source_type;
+ // The ZERO figurative constant is not flagged as signed:
+ if( !type )
+ {
+ type = UINT;
+ }
+ value = gg_define_variable(type);
+ gg_assign(value, gg_cast(type, integer_zero_node));
}
+ else
+ {
+ if( !type )
+ {
+ type = TREE_TYPE(value);
+ }
+ switch(field->type)
+ {
+ case FldLiteralN:
+ binary_from_FldLiteralN(value, field, type);
+ break;
- value = gg_define_variable(type);
+ case FldNumericBin5:
+ case FldIndex:
+ case FldPointer:
+ binary_from_FldNumericBin5(value, field, type);
+ break;
- tree base;
- get_location(base, refer);
+ case FldNumericBinary:
+ binary_from_FldNumericBinary(value, field, type);
+ break;
+
+ case FldNumericDisplay:
+ binary_from_FldNumericDisplay(value, field, type);
+ break;
+
+ case FldPacked:
+ binary_from_FldPacked(value, field, type);
+ break;
- gg_assign(value,
- gg_cast(type,
- gg_indirect(gg_cast(build_pointer_type(source_type),
-
base))));
+ case FldFloat:
+ binary_from_FldFloat(value, field, type);
+ break;
- return true;
+ default:
+ gcc_unreachable();
+ break;
+ }
+ }
}
-bool
+void
get_binary_value(tree &value, const cbl_refer_t &refer, tree type)
{
- bool retval = false;
/* There are other get binary value routines. This one is intended to
be the
"best in class" version, incorporating everything that's been
learned
- about the process, and incorporating compiler SSA guidelines. */
+ about the process, and incorporating compiler SSA guidelines.
+
+ On entry, value should be unassigned. It will be given the type
'type',
+ if present, and otherwise will be the same as the type derived from
the
+ source. */
if( (refer.field->attr & FIGCONST_MASK) == zero_value_e )
{
@@ -3146,10 +2538,13 @@ get_binary_value(tree &value, const cbl_refer_t
&refer, tree type)
}
value = gg_define_variable(type);
gg_assign(value, gg_cast(type, integer_zero_node));
- retval = true;
}
else if( refer.addr_of )
{
+ if( !type )
+ {
+ type = tree_type_from_field(refer.field);
+ }
// The case of ADDRESS OF
value = gg_define_variable(type);
tree base = gg_define_variable(UCHAR_P);
@@ -3162,33 +2557,36 @@ get_binary_value(tree &value, const cbl_refer_t
&refer, tree type)
}
else
{
- // We know that the refer is a type that involves an integer binary
value.
+ if( !type )
+ {
+ type = tree_type_from_field(refer.field);
+ }
switch(refer.field->type)
{
case FldLiteralN:
- retval = binary_from_FldLiteralN(value, refer, type);
+ binary_from_FldLiteralN(value, refer, type);
break;
case FldNumericBin5:
case FldIndex:
case FldPointer:
- retval = binary_from_FldNumericBin5(value, refer, type);
+ binary_from_FldNumericBin5(value, refer, type);
break;
case FldNumericBinary:
- retval = binary_from_FldNumericBinary(value, refer, type);
+ binary_from_FldNumericBinary(value, refer, type);
break;
case FldNumericDisplay:
- retval = binary_from_FldNumericDisplay(value, refer, type);
+ binary_from_FldNumericDisplay(value, refer, type);
break;
case FldPacked:
- retval = binary_from_FldPacked(value, refer, type);
+ binary_from_FldPacked(value, refer, type);
break;
case FldFloat:
- retval = binary_from_FldFloat(value, refer, type);
+ binary_from_FldFloat(value, refer, type);
break;
default:
@@ -3196,45 +2594,102 @@ get_binary_value(tree &value, const cbl_refer_t
&refer, tree type)
break;
}
}
- return retval;
}
void
-get_location(tree &retval, const cbl_refer_t &refer)
+get_location(tree &retval, const cbl_field_t *field)
{
- // This routine looks at a refer and returns a UCHAR_P pointer to the
data
- // of the object.
retval = gg_define_variable(UCHAR_P);
-
- if( refer_is_super_clean(refer) )
+ if( field_is_super_clean(field) )
{
- // Working storage, not external, no refmods or subscripts. That
means
- // we can work with the actual data item, and save a level of
indirection.
-
- if( refer.field->offset )
+ if( field->offset )
{
gg_assign(retval,
gg_add(gg_cast(UCHAR_P,
-
gg_get_address(refer.field->data_decl_node)),
- build_int_cst_type(SIZE_T, refer.field->offset)));
+ gg_get_address(field->data_decl_node)),
+ build_int_cst_type(SIZE_T, field->offset)));
}
else
{
gg_assign(retval, gg_cast(UCHAR_P,
-
gg_get_address(refer.field->data_decl_node)));
+ gg_get_address(field->data_decl_node)));
}
}
+ else
+ {
+ gg_assign(retval,
+ gg_add(member(field->var_decl_node,"data"),
+ build_int_cst_type(SIZE_T, field->offset)));
+ }
+ }
+
+void
+get_location(tree &retval, const cbl_refer_t &refer)
+ {
+ /* This routine looks at a refer and returns a UCHAR_P pointer to the
data
+ of the object. */
+
+ if( refer_is_super_clean(refer) )
+ {
+ // Working storage, not external, no refmods or subscripts. That
means
+ // we can work with the actual data item, and save a level of
indirection.
+ get_location(retval, refer.field);
+ }
else
{
// The variable is external, or intermediate_e, or there are
subscripts, or
// there are refmods. We use the run-time "data", and add the
run-time
// offset to it.
+ retval = gg_define_variable(UCHAR_P);
gg_assign(retval,
gg_add(member(refer.field->var_decl_node,"data"),
refer_offset(refer)));
}
}
+void
+safe_cast(tree &target, // A defined variable.
+ tree source_location, // A pointer, usually UCHAR_P.
+ tree source_type) // The variable type pointed to by
+ // source_location.
+ {
+ /* The construction here does the safe equivalent of
+
+ int target = *(int *)location.
+
+ It does this by copying through memcpy rather than dereferencing
+ source_location as a source_type pointer. This avoids creating a
typed
+ lvalue access to storage whose effective/dynamic type may not be
+ source_type, and so avoids strict-aliasing violations. */
+
+ tree source = gg_define_variable(source_type);
+ gg_memcpy(gg_get_address_of(source),
+ source_location,
+ build_int_cst_type(SIZE_T, gg_sizeof(source_type)));
+ gg_assign(target,
+ gg_cast(TREE_TYPE(target), source));
+ }
+
+void
+safe_cast(tree &target, // A defined variable.
+ const cbl_field_t *field)
+ {
+ tree source_type = tree_type_from_field(field);
+ tree source_location;
+ get_location(source_location, field);
+ safe_cast(target, source_location, source_type);
+ }
+
+void
+safe_cast(tree &target, // A defined variable.
+ const cbl_refer_t &refer)
+ {
+ tree source_type = tree_type_from_field(refer.field);
+ tree source_location;
+ get_location(source_location, refer);
+ safe_cast(target, source_location, source_type);
+ }
+
void
get_length(tree &retval, const cbl_refer_t &refer)
{
@@ -3405,15 +2860,16 @@ data_decl_type_for(cbl_field_t *field)
}
void
-attribute_bit_clear(struct cbl_field_t *var, cbl_field_attr_t bits)
+attribute_bit_clear(const struct cbl_field_t *var, cbl_field_attr_t bits)
{
gg_assign( member(var, "attr"),
gg_bitwise_and( member(var, "attr"),
- gg_bitwise_not( build_int_cst_type(SIZE_T,
bits) )));
+ gg_bitwise_not( build_int_cst_type(SIZE_T,
+
bits))));
}
tree
-attribute_bit_get(struct cbl_field_t *var, cbl_field_attr_t bits)
+attribute_bit_get(const struct cbl_field_t *var, cbl_field_attr_t bits)
{
tree retval = gg_bitwise_and( member(var, "attr"),
build_int_cst_type(SIZE_T, bits) );
@@ -3421,7 +2877,7 @@ attribute_bit_get(struct cbl_field_t *var,
cbl_field_attr_t bits)
}
void
-attribute_bit_set(struct cbl_field_t *var, cbl_field_attr_t bits)
+attribute_bit_set(const struct cbl_field_t *var, cbl_field_attr_t bits)
{
gg_assign( member(var, "attr"),
gg_bitwise_or(member(var, "attr"),
@@ -3728,7 +3184,7 @@ round_this_value( tree &value,
ELSE {} ENDIF
break;
}
-
+
case toward_lesser_e:
{
/* "If the TOWARD-LESS phrase is specified, and the arithmetic
value