From d9a44930e51fa6284c9ad92688ae171a52b43fe7 Mon Sep 17 00:00:00 2001 From: Bob Dubner <rdubner@symas.com> Date: Mon, 17 Jun 2024 01:19:48 -0400 Subject: [PATCH] Refactor FldLiteralA to be completely static at run-time --- .gitignore | 1 + gcc/cobol/genapi.cc | 147 +++++++++++++++++++++++++++++++++++------ gcc/cobol/genutil.cc | 11 +-- libgcobol/libgcobol.cc | 4 +- 4 files changed, 134 insertions(+), 29 deletions(-) diff --git a/.gitignore b/.gitignore index 076713d5d148..8ec6320eac5d 100644 --- a/.gitignore +++ b/.gitignore @@ -76,5 +76,6 @@ stamp-* # of having the BUILD directories adjacent to the SRC directory, rather than # inside the SRC directory build/ +buildrel/ build1/ build2/ diff --git a/gcc/cobol/genapi.cc b/gcc/cobol/genapi.cc index 46b1c11b9ca5..c4dc29ea91dc 100644 --- a/gcc/cobol/genapi.cc +++ b/gcc/cobol/genapi.cc @@ -890,6 +890,11 @@ initialize_variable_internal( cbl_refer_t refer, // gg_string_literal(refer.field->name), // NULL_TREE); cbl_field_t *parsed_var = refer.field; + + if( parsed_var->type == FldLiteralA ) + { + return; + } if( parsed_var->is_key_name() ) { @@ -1086,16 +1091,11 @@ initialize_variable_internal( cbl_refer_t refer, { // We have a clean refer with no mods, so we can send just the pointer to // the field - // FAZZBAZZ - //gg_printf("KILROY ct %s %s\n", gg_string_literal(refer.field->name), gg_string_literal(cbl_field_type_str(refer.field->type)), NULL_TREE); - //fprintf(stderr, "KILROY rt %s %s\n", refer.field->name, cbl_field_type_str(refer.field->type)); - //refer_fill_dest(refer); gg_call(VOID, "__gg__initialize_variable_clean", 2, gg_get_address_of(refer.field->var_decl_node), build_int_cst_type(INT, flag_bits) ); - //refer_release(refer); } suppress_dest_depends = true; @@ -1862,8 +1862,6 @@ cobol_compare( tree return_int, // now I decided to keep using the libgcobol code, which according to NIST // works properly. -// gg_printf(" KILROY %d\n", build_int_cst_type(INT, __LINE__), NULL_TREE); - if( !left_side_ref.refmod.from && !left_side_ref.refmod.len && !right_side_ref.refmod.from @@ -1875,10 +1873,6 @@ cobol_compare( tree return_int, int ntries = 1; while( ntries <= 2 ) { - // gg_printf(" KILROY %d %s %s\n", build_int_cst_type(INT, __LINE__), - // gg_string_literal(cbl_field_type_str(lefty ->field->type)), - // gg_string_literal(cbl_field_type_str(righty->field->type)), - // NULL_TREE); switch( lefty->field->type ) { case FldLiteralN: @@ -1976,7 +1970,6 @@ cobol_compare( tree return_int, if( !compared ) { -//gg_printf(" KILROY %d\n", build_int_cst_type(INT, __LINE__), NULL_TREE); // None of our explicit comparisons up above worked, so we revert to the // general case: refer_fill_source(left_side_ref); @@ -2070,7 +2063,6 @@ move_tree( cbl_refer_t &dest, source_length, gg_get_address_of(rdigits))); -//gg_printf("KILROY %d\n", build_int_cst_type(INT, __LINE__), NULL_TREE); gg_call(VOID, "__gg__int128_to_refer", 5, @@ -3984,6 +3976,7 @@ psa_FldBlob(struct cbl_field_t *var ) var->var_decl_node = gg_get_address_of(var_decl_node); } + void parser_accept( struct cbl_refer_t refer, enum special_name_t special_e ) @@ -5163,6 +5156,7 @@ parser_move(cbl_refer_t destref, bool skip_fill_from // Defaults to false ) { + line_tick(); Analyze(); SHOW_PARSE @@ -5235,12 +5229,18 @@ line_tick(); } } + TRACE1 + { + TRACE1_HEADER + TRACE1_TEXT("About to call move_helper") + } + static bool dont_check_for_error = false; move_helper(destref, sourceref, skip_fill_from, rounded, dont_check_for_error ); TRACE1 { - TRACE1_HEADER + TRACE1_INDENT TRACE1_REFER_INFO("source ", sourceref) TRACE1_INDENT TRACE1_REFER_INFO("dest ", destref) @@ -11500,10 +11500,6 @@ create_and_call(size_t narg, tree returned_value; if( returned.field ) { -//gg_printf("KILROY %d %s %p\n", build_int_cst_type(INT, __LINE__), -// gg_string_literal(returned.field->name), -// returned.refer_decl_node, -// NULL_TREE); returned_value = gg_define_variable(returned_value_type); // We are expecting a return value of type CHAR_P, SSIZE_T, SIZE_T, @@ -11572,10 +11568,6 @@ create_and_call(size_t narg, // We got back a 64-bit or 128-bit integer. The called and calling // programs have to agree on size, but other than that, integer numeric // types are converted one to the other. -// gg_printf("KILROY %d %s %p\n", build_int_cst_type(INT, __LINE__), - // gg_string_literal(returned.field->name), - // returned.refer_decl_node, - // NULL_TREE); gg_call(VOID, "__gg__int128_to_refer", 5, @@ -15322,6 +15314,110 @@ psa_new_var_decl(cbl_field_t *new_var, const char *external_record_base) return new_var_decl; } +#if 1 +static void +psa_FldLiteralA(struct cbl_field_t *field ) + { + Analyze(); + SHOW_PARSE + { + SHOW_PARSE_HEADER + SHOW_PARSE_FIELD(" ", field) + SHOW_PARSE_END + } + + TRACE1 + { + TRACE1_HEADER + TRACE1_END + } + + // We are constructing a completely static constant structure. We know the + // capacity. We'll create it from the data.initial. The cblc_field_t:data + // will be an ASCII/EBCDIC copy of the .initial data. The .initial will be + // left as ASCII. The var_decl_node will be an ordinary cblc_field_t, which + // means that at this point in time, a FldLiteralA can be used anywhere a + // FldGroup or FldAlphanumeric can be used. We are counting on the parser + // not allowing a FldLiteralA to be a left-hand-side variable. + + // First make room + static size_t buffer_size = 1024; + static char *buffer = (char *)xmalloc(buffer_size); + if( buffer_size < field->data.capacity+1 ) + { + buffer_size = field->data.capacity+1; + buffer = (char *)xrealloc(buffer, buffer_size); + } + + cbl_figconst_t figconst = cbl_figconst_of( field->data.initial ); + gcc_assert(figconst == normal_value_e); + + if( internal_codeset_is_ebcdic() ) + { + for( size_t i=0; i<field->data.capacity; i++ ) + { + buffer[i] = ascii_to_internal(field->data.initial[i]); + } + } + else + { + memcpy(buffer, field->data.initial, field->data.capacity); + } + buffer[field->data.capacity] = '\0'; + + // We have the original nul-terminated text at data.initial. We have a + // copy of it in buffer[] in the internal codeset. + + // We will re-use a single static structure for each string + static std::unordered_map<std::string, int> seen_before; + std::string field_string(buffer); + std::unordered_map<std::string, int>::const_iterator it = + seen_before.find(field_string); + + static const char name_base[] = "_literal_a_"; + + if( it != seen_before.end() ) + { + // We've seen that string before. + int nvar = it->second; + char ach[32]; + sprintf(ach, "%s%d", name_base, nvar); + field->var_decl_node = gg_declare_variable(cblc_field_type_node, + ach, + NULL, + vs_file_static); + } + else + { + // We have not seen that string before + static int nvar = 1; + seen_before[field_string] = nvar; + + char ach[32]; + sprintf(ach, "%s%d", name_base, nvar); + field->var_decl_node = gg_define_variable( cblc_field_type_node, + ach, + vs_file_static); + actually_create_the_static_field( + field, + build_string_literal(field->data.capacity+1, + buffer), + field->data.capacity+1, + field->data.initial, + NULL_TREE, + field->var_decl_node); + nvar += 1; + } + TRACE1 + { + TRACE1_INDENT + TRACE1_TEXT("Finished") + TRACE1_END + } + } +#endif + + void parser_local_add(struct cbl_field_t *new_var ) { @@ -15495,6 +15591,13 @@ parser_symbol_add(struct cbl_field_t *new_var ) return; } + if( new_var->type == FldLiteralA ) + { + new_var->data.picture = ""; + psa_FldLiteralA(new_var); + return; + } + size_t length_of_initial_string = 0; const char *new_initial = NULL; diff --git a/gcc/cobol/genutil.cc b/gcc/cobol/genutil.cc index 6187fceb8794..db411e9b78e4 100644 --- a/gcc/cobol/genutil.cc +++ b/gcc/cobol/genutil.cc @@ -2449,7 +2449,7 @@ refer_fill_depends(cbl_refer_t &refer, refer_type_t refer_type) } } -#define NEW_STYLE 1 +#define NEW_STYLE 0 void refer_release(cbl_refer_t &refer) @@ -2520,7 +2520,7 @@ refer_fill_internal(cbl_refer_t &refer, refer_type_t refer_type) // This refer doesn't have a refer_decl_node, so we are reserving one // for it. - #if NEW_STYLE +#if NEW_STYLE tree referp_type = build_pointer_type(cblc_refer_type_node); if( !refer.refer_decl_node ) { @@ -2554,6 +2554,10 @@ refer_fill_internal(cbl_refer_t &refer, refer_type_t refer_type) #if 1 if( refer.field && refer.field->type == FldLiteralA ) { + if(!refer.field->var_decl_node) + { + gcc_assert(refer.field->var_decl_node); + } gg_assign(member(refer.refer_decl_node, "field"), gg_cast(cblc_field_p_type_node, gg_get_address_of(refer.field->var_decl_node))); @@ -2566,9 +2570,6 @@ refer_fill_internal(cbl_refer_t &refer, refer_type_t refer_type) gg_cast(UCHAR_P, gg_string_literal(litstring))); gg_assign(member(refer.refer_decl_node, "qual_size"), build_int_cst_type(SIZE_T, refer.field->data.capacity)); - gg_memcpy(member(refer.field, "data"), - member(refer.refer_decl_node, "qual_data"), - build_int_cst_type(SIZE_T, refer.field->data.capacity) ); } else #endif diff --git a/libgcobol/libgcobol.cc b/libgcobol/libgcobol.cc index b8a3a7e2442f..52cd3cd5ec3a 100644 --- a/libgcobol/libgcobol.cc +++ b/libgcobol/libgcobol.cc @@ -3647,8 +3647,8 @@ __gg__compare_2(cblc_field_t *left_side, if( left_side->type == FldLiteralA ) { - left_location = (unsigned char *)left_side->initial; - left_length = strlen(left_side->initial); + left_location = (unsigned char *)left_side->data; + left_length = left_side->capacity; } static size_t right_string_size = MINIMUM_ALLOCATION_SIZE; -- GitLab