From: Michal Jires Date: Thu, 8 Jan 2026 00:40:07 +0000 (+0100) Subject: lto: Stream toplevel extended assembly X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f7a08611ee6eea1d76c10013e42974cd0c314d74;p=thirdparty%2Fgcc.git lto: Stream toplevel extended assembly Streaming of toplevel extended assembly was missing implementation. Streaming must be after merging of decls, otherwise we would have to fix the pointers to new decls. gcc/ChangeLog: * ipa-free-lang-data.cc (find_decls_types_in_asm): New. (free_lang_data_in_cgraph): Use find_decls_types_in_asm. * lto-cgraph.cc (input_cgraph_1): Move asm to.. (input_toplevel_asms): ..here. * lto-streamer-in.cc (lto_input_toplevel_asms): Allow extended asm. * lto-streamer-out.cc (lto_output_toplevel_asms): Allow extended asm. (lto_output_toplevel_asms): Allow ASM_EXPR. * lto-streamer.h (input_toplevel_asms): New. gcc/lto/ChangeLog: * lto-common.cc (read_cgraph_and_symbols): Call input_toplevel_asms after decl merging. gcc/testsuite/ChangeLog: * g++.dg/lto/toplevel_asm-0_0.C: New test. --- diff --git a/gcc/ipa-free-lang-data.cc b/gcc/ipa-free-lang-data.cc index a655a1da5f4..edc4f1aed81 100644 --- a/gcc/ipa-free-lang-data.cc +++ b/gcc/ipa-free-lang-data.cc @@ -1036,6 +1036,19 @@ find_decls_types_in_var (varpool_node *v, class free_lang_data_d *fld) find_decls_types (v->decl, fld); } +/* Find decls and types referenced in asm node N and store them in + FLD->DECLS and FLD->TYPES. + Asm strings are represented as a C/C++/etc. strings. If there is + no other string, we would delete/prune/unify the type and cause + issues in verify_type(tree). + Likely we could just add the string type, but we scan the whole + tree to be sure. */ +static void +find_decls_types_in_asm (asm_node *v, class free_lang_data_d *fld) +{ + find_decls_types (v->asm_str, fld); +} + /* Free language specific information for every operand and expression in every node of the call graph. This process operates in three stages: @@ -1073,6 +1086,12 @@ free_lang_data_in_cgraph (class free_lang_data_d *fld) FOR_EACH_VARIABLE (v) find_decls_types_in_var (v, fld); + /* Find the decls and types in every asm node. + Should only be a string type. */ + for (asm_node* anode = symtab->first_asm_symbol (); anode; + anode = safe_as_a (anode->next)) + find_decls_types_in_asm (anode, fld); + /* Set the assembler name on every decl found. We need to do this now because free_lang_data_in_decl will invalidate data needed for mangling. This breaks mangling on interdependent decls. */ diff --git a/gcc/lto-cgraph.cc b/gcc/lto-cgraph.cc index 50635f3f8a4..cbb37875b89 100644 --- a/gcc/lto-cgraph.cc +++ b/gcc/lto-cgraph.cc @@ -1641,8 +1641,6 @@ input_cgraph_1 (struct lto_file_decl_data *file_data, tag = streamer_read_enum (ib, LTO_symtab_tags, LTO_symtab_last_tag); } - lto_input_toplevel_asms (file_data, file_data->order_base); - /* AUX pointers should be all non-zero for function nodes read from the stream. */ if (flag_checking) { @@ -1860,6 +1858,19 @@ input_symtab (void) } } +/* Input toplevel asms from each of the .o files passed to lto1. + Must be called after merging of decls. */ +void +input_toplevel_asms (void) +{ + struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data (); + struct lto_file_decl_data *file_data; + unsigned int j = 0; + + while ((file_data = file_data_vec[j++])) + lto_input_toplevel_asms (file_data, file_data->order_base); +} + static void omp_requires_to_name (char *buf, size_t size, HOST_WIDE_INT requires_mask) { diff --git a/gcc/lto-streamer-in.cc b/gcc/lto-streamer-in.cc index 6261b37f9af..9659d4aa532 100644 --- a/gcc/lto-streamer-in.cc +++ b/gcc/lto-streamer-in.cc @@ -1987,7 +1987,6 @@ lto_input_toplevel_asms (struct lto_file_decl_data *file_data, int order_base) = (const struct lto_simple_header_with_strings *) data; int string_offset; class data_in *data_in; - tree str; if (! data) return; @@ -2000,8 +1999,10 @@ lto_input_toplevel_asms (struct lto_file_decl_data *file_data, int order_base) data_in = lto_data_in_create (file_data, data + string_offset, header->string_size, vNULL); - while ((str = streamer_read_string_cst (data_in, &ib))) + unsigned asm_count = streamer_read_uhwi (&ib); + for (unsigned i = 0; i < asm_count; i++) { + tree str = stream_read_tree (&ib, data_in); asm_node *node = symtab->finalize_toplevel_asm (str); node->order = streamer_read_hwi (&ib) + order_base; node->lto_file_data = file_data; diff --git a/gcc/lto-streamer-out.cc b/gcc/lto-streamer-out.cc index 24cbf499549..293871cd7ed 100644 --- a/gcc/lto-streamer-out.cc +++ b/gcc/lto-streamer-out.cc @@ -384,6 +384,7 @@ lto_is_streamable (tree expr) && code != STATEMENT_LIST && (code == CASE_LABEL_EXPR || code == DECL_EXPR + || code == ASM_EXPR || TREE_CODE_CLASS (code) != tcc_statement); } @@ -2560,19 +2561,18 @@ lto_output_toplevel_asms (lto_symtab_encoder_t encoder) char *section_name; struct lto_simple_header_with_strings header; - bool any_asm = false; + unsigned asm_count = 0; for (int i = 0; i < lto_symtab_encoder_size (encoder); i++) if (is_a (lto_symtab_encoder_deref (encoder, i))) - any_asm = true; + asm_count++; - if (!any_asm) + if (!asm_count) return; ob = create_output_block (LTO_section_asm); - /* Make string 0 be a NULL string. */ - streamer_write_char_stream (ob->string_stream, 0); - + /* Stream the length. */ + streamer_write_uhwi (ob, asm_count); for (int i = 0; i < lto_symtab_encoder_size (encoder); i++) { toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i); @@ -2580,19 +2580,11 @@ lto_output_toplevel_asms (lto_symtab_encoder_t encoder) if (!anode) continue; - if (TREE_CODE (anode->asm_str) != STRING_CST) - { - sorry_at (EXPR_LOCATION (anode->asm_str), - "LTO streaming of toplevel extended % " - "unimplemented"); - continue; - } - streamer_write_string_cst (ob, ob->main_stream, anode->asm_str); - streamer_write_hwi (ob, anode->order); + int output_order = *encoder->order_remap->get (anode->order); + stream_write_tree (ob, anode->asm_str, true); + streamer_write_hwi (ob, output_order); } - streamer_write_string_cst (ob, ob->main_stream, NULL_TREE); - section_name = lto_get_section_name (LTO_section_asm, NULL, 0, NULL); lto_begin_section (section_name, !flag_wpa); free (section_name); diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index 4e43f60f562..f8aa8465b7c 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -933,6 +933,7 @@ bool lto_symtab_encoder_encode_initializer_p (lto_symtab_encoder_t, varpool_node *); void output_symtab (void); void input_symtab (void); +void input_toplevel_asms (void); void output_offload_tables (void); void input_offload_tables (bool); bool referenced_from_other_partition_p (struct ipa_ref_list *, diff --git a/gcc/lto/lto-common.cc b/gcc/lto/lto-common.cc index 37888361904..e5c5bc6c675 100644 --- a/gcc/lto/lto-common.cc +++ b/gcc/lto/lto-common.cc @@ -2948,6 +2948,9 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames) if (tree_with_vars) ggc_free (tree_with_vars); tree_with_vars = NULL; + + input_toplevel_asms (); + /* During WPA we want to prevent ggc collecting by default. Grow limits until after the IPA summaries are streamed in. Basically all IPA memory is explcitly managed by ggc_free and ggc collect is not useful. diff --git a/gcc/testsuite/g++.dg/lto/toplevel_asm-0_0.C b/gcc/testsuite/g++.dg/lto/toplevel_asm-0_0.C new file mode 100644 index 00000000000..4bfe6b1852d --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/toplevel_asm-0_0.C @@ -0,0 +1,7 @@ +// { dg-lto-do link } + +// Test that type of asm string is not removed. +char c; +asm(""); + +int main() { }