> In addition of pr61644 and pr61646, this commit breaks a lot of > fortran tests with -flto -O0. Hello, the problem here is that we have POINTER_TYPE that points to array of variable length (not sure why it happens only with -O0). The ICE is introduced by the fact that we stream the type inside of function body then and thus it never goes through the lto.c's type handling.
This patch fixes the ICE by moving the fixup somewhat earlier (perhaps it is good idea in general). I do not believe resulting IL is correct: we do not compute canonical type of the pointer nor we link correctly the variants. Richard, we probably ought to try to make all of the canonical type fixup happen also for function local types which would involve moving it all from lto.c into generic code? :(( I am testing the patch. I think it is better to have fixup here, so OK if it passes? Honza Index: lto-streamer-in.c =================================================================== --- lto-streamer-in.c (revision 212098) +++ lto-streamer-in.c (working copy) @@ -1182,6 +1182,58 @@ lto_read_tree (struct lto_input_block *i } +/* Copy fields that are not streamed but copied from other nodes. */ +static void +lto_copy_fields_not_streamed (tree t) +{ + if (TYPE_P (t) && TYPE_MAIN_VARIANT (t) != t) + { + tree mv = TYPE_MAIN_VARIANT (t); + + if (COMPLETE_TYPE_P (t)) + { + TYPE_SIZE (t) = TYPE_SIZE (mv); + TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (mv); + } + TYPE_ATTRIBUTES (t) = TYPE_ATTRIBUTES (mv); + + if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_TYPE_NON_COMMON)) + { + if (TREE_CODE (t) == ENUMERAL_TYPE && COMPLETE_TYPE_P (t)) + TYPE_VALUES (t) = TYPE_VALUES (mv); + else if (TREE_CODE (t) == ARRAY_TYPE) + TYPE_DOMAIN (t) = TYPE_DOMAIN (mv); + + if (RECORD_OR_UNION_TYPE_P (t) && COMPLETE_TYPE_P (t)) + TYPE_VFIELD (t) = TYPE_VFIELD (mv); + else if ((TREE_CODE (t) == ENUMERAL_TYPE && COMPLETE_TYPE_P (t)) + || TREE_CODE (t) == INTEGER_TYPE + || TREE_CODE (t) == BOOLEAN_TYPE + || TREE_CODE (t) == REAL_TYPE + || TREE_CODE (t) == FIXED_POINT_TYPE) + TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (mv); + + if (TREE_CODE (t) == METHOD_TYPE) + TYPE_METHOD_BASETYPE (t) = TYPE_METHOD_BASETYPE (mv); + else if (RECORD_OR_UNION_TYPE_P (t) && COMPLETE_TYPE_P (t)) + TYPE_METHODS (t) = TYPE_METHODS (mv); + else if (TREE_CODE (t) == OFFSET_TYPE) + TYPE_OFFSET_BASETYPE (t) = TYPE_OFFSET_BASETYPE (mv); + else if (TREE_CODE (t) == ARRAY_TYPE) + TYPE_ARRAY_MAX_SIZE (t) = TYPE_ARRAY_MAX_SIZE (mv); + else if ((TREE_CODE (t) == ENUMERAL_TYPE && COMPLETE_TYPE_P (t)) + || TREE_CODE (t) == INTEGER_TYPE + || TREE_CODE (t) == BOOLEAN_TYPE + || TREE_CODE (t) == REAL_TYPE + || TREE_CODE (t) == FIXED_POINT_TYPE) + TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (mv); + + if (RECORD_OR_UNION_TYPE_P (t) && COMPLETE_TYPE_P (t)) + TYPE_BINFO (t) = TYPE_BINFO (mv); + } + } +} + /* Populate the reader cache with trees materialized from the SCC following in the IB, DATA_IN stream. */ @@ -1194,6 +1246,7 @@ lto_input_scc (struct lto_input_block *i unsigned size = streamer_read_uhwi (ib); hashval_t scc_hash = streamer_read_uhwi (ib); unsigned scc_entry_len = 1; + unsigned from = data_in->reader_cache->nodes.length (); if (size == 1) { @@ -1233,6 +1286,12 @@ lto_input_scc (struct lto_input_block *i } } + /* Copy fileds we do not stream before unification so we can compare them + without being worried if they are already initialized. */ + for (unsigned i = 0; i < size; ++i) + lto_copy_fields_not_streamed + (streamer_tree_cache_get_tree (data_in->reader_cache, from + i)); + *len = size; *entry_len = scc_entry_len; return scc_hash; Index: lto/lto.c =================================================================== --- lto/lto.c (revision 212114) +++ lto/lto.c (working copy) @@ -1050,58 +1050,6 @@ lto_register_function_decl_in_symtab (st decl, get_resolution (data_in, ix)); } -/* Copy fields that are not streamed but copied from other nodes. */ -static void -lto_copy_fields_not_streamed (tree t) -{ - if (TYPE_P (t) && TYPE_MAIN_VARIANT (t) != t) - { - tree mv = TYPE_MAIN_VARIANT (t); - - if (COMPLETE_TYPE_P (t)) - { - TYPE_SIZE (t) = TYPE_SIZE (mv); - TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (mv); - } - TYPE_ATTRIBUTES (t) = TYPE_ATTRIBUTES (mv); - - if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_TYPE_NON_COMMON)) - { - if (TREE_CODE (t) == ENUMERAL_TYPE && COMPLETE_TYPE_P (t)) - TYPE_VALUES (t) = TYPE_VALUES (mv); - else if (TREE_CODE (t) == ARRAY_TYPE) - TYPE_DOMAIN (t) = TYPE_DOMAIN (mv); - - if (RECORD_OR_UNION_TYPE_P (t) && COMPLETE_TYPE_P (t)) - TYPE_VFIELD (t) = TYPE_VFIELD (mv); - else if ((TREE_CODE (t) == ENUMERAL_TYPE && COMPLETE_TYPE_P (t)) - || TREE_CODE (t) == INTEGER_TYPE - || TREE_CODE (t) == BOOLEAN_TYPE - || TREE_CODE (t) == REAL_TYPE - || TREE_CODE (t) == FIXED_POINT_TYPE) - TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (mv); - - if (TREE_CODE (t) == METHOD_TYPE) - TYPE_METHOD_BASETYPE (t) = TYPE_METHOD_BASETYPE (mv); - else if (RECORD_OR_UNION_TYPE_P (t) && COMPLETE_TYPE_P (t)) - TYPE_METHODS (t) = TYPE_METHODS (mv); - else if (TREE_CODE (t) == OFFSET_TYPE) - TYPE_OFFSET_BASETYPE (t) = TYPE_OFFSET_BASETYPE (mv); - else if (TREE_CODE (t) == ARRAY_TYPE) - TYPE_ARRAY_MAX_SIZE (t) = TYPE_ARRAY_MAX_SIZE (mv); - else if ((TREE_CODE (t) == ENUMERAL_TYPE && COMPLETE_TYPE_P (t)) - || TREE_CODE (t) == INTEGER_TYPE - || TREE_CODE (t) == BOOLEAN_TYPE - || TREE_CODE (t) == REAL_TYPE - || TREE_CODE (t) == FIXED_POINT_TYPE) - TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (mv); - - if (RECORD_OR_UNION_TYPE_P (t) && COMPLETE_TYPE_P (t)) - TYPE_BINFO (t) = TYPE_BINFO (mv); - } - } -} - /* For the type T re-materialize it in the type variant list and the pointer/reference-to chains. */ @@ -1958,19 +1906,13 @@ lto_read_decls (struct lto_file_decl_dat || streamer_handle_as_builtin_p (first))) continue; - /* Copy fileds we do not stream before unification so we can compare them - without being worried if they are already initialized. */ - for (unsigned i = 0; i < len; ++i) - lto_copy_fields_not_streamed - (streamer_tree_cache_get_tree (data_in->reader_cache, from + i)); - /* Try to unify the SCC with already existing ones. */ if (!flag_ltrans && unify_scc (data_in->reader_cache, from, len, scc_entry_len, scc_hash)) continue; /* Do remaining fixup tasks for prevailing nodes. */ bool seen_type = false; for (unsigned i = 0; i < len; ++i) {