@@ -2286,103 +2286,24 @@ referenced_type_should_be_emitted(const type_base *t,
return false;
}
-/// Serialize a translation unit to an output stream.
+/// Emit the types that were referenced by other emitted types.
///
-/// @param ctxt the context of the serialization. It contains e.g,
-/// the output stream to serialize to.
+/// This is a sub-routine of write_translation_unit.
///
-/// @param tu the translation unit to serialize.
+/// @param ctxt the write context to use.
///
-/// @param indent how many indentation spaces to use during the
-/// serialization.
+/// @param tu the current translation unit that is being emitted.
///
-/// @param is_last If true, it means the TU to emit is the last one of
-/// the corpus. If this is the case, all the remaining referenced
-/// types that were not emitted are going to be emitted here,
-/// irrespective of if they belong to this TU or not. This is quite a
-/// hack. Ideally, we should have a pass that walks all the TUs,
-/// detect their non-emitted referenced types, before hand. Then,
-/// when we start emitting the TUs, we know for each TU which
-/// non-emitted referenced type should be emitted. As we don't yet
-/// have such a pass, we do our best for now.
+/// @param indent the indentation string.
///
-/// @return true upon successful completion, false otherwise.
-bool
-write_translation_unit(write_context& ctxt,
+/// @param is_last whether @p tu is the last translation unit or not.
+static void
+write_referenced_types(write_context & ctxt,
const translation_unit& tu,
const unsigned indent,
bool is_last)
{
- if (tu.is_empty() && !is_last)
- return false;
-
- if (is_last
- && tu.is_empty()
- && ctxt.has_non_emitted_referenced_types())
- return false;
-
- ostream& o = ctxt.get_ostream();
const config& c = ctxt.get_config();
-
- do_indent(o, indent);
-
- o << "<abi-instr";
-
- if (tu.get_address_size() != 0)
- o << " address-size='" << static_cast<int>(tu.get_address_size()) << "'";
-
- std::string tu_path = tu.get_path();
- if (ctxt.get_short_locs())
- tools_utils::base_name(tu_path, tu_path);
- if (!tu_path.empty())
- o << " path='" << xml::escape_xml_string(tu_path) << "'";
-
- if (!tu.get_compilation_dir_path().empty() && ctxt.get_write_comp_dir())
- o << " comp-dir-path='"
- << xml::escape_xml_string(tu.get_compilation_dir_path()) << "'";
-
- if (tu.get_language() != translation_unit::LANG_UNKNOWN)
- o << " language='"
- << translation_unit_language_to_string(tu.get_language())
- <<"'";
-
- if (tu.is_empty() && !is_last)
- {
- o << "/>\n";
- return true;
- }
-
- o << ">\n";
-
- write_canonical_types_of_scope(*tu.get_global_scope(),
- ctxt, indent + c.get_xml_element_indent());
-
- typedef scope_decl::declarations declarations;
- typedef declarations::const_iterator const_iterator;
- const declarations& d = tu.get_global_scope()->get_sorted_member_decls();
-
- for (const_iterator i = d.begin(); i != d.end(); ++i)
- {
- if (type_base_sptr t = is_type(*i))
- {
- // Emit declaration-only classes that are needed. Some of
- // these classes can be empty. Those beasts can be classes
- // that only contain member types. They can also be classes
- // considered "opaque".
- if (class_decl_sptr class_type = is_class_type(t))
- if (class_type->get_is_declaration_only()
- && !ctxt.type_is_emitted(class_type))
- write_type(class_type, ctxt,
- indent + c.get_xml_element_indent());
- continue;
- }
-
- if (decl_base_sptr d = is_decl(*i))
- if (ctxt.decl_is_emitted(d))
- continue;
- write_decl(*i, ctxt, indent + c.get_xml_element_indent());
- }
-
// Now let's handle types that were referenced, but not yet
// emitted because they are either:
// 1/ Types without canonical type
@@ -2479,6 +2400,106 @@ write_translation_unit(write_context& ctxt,
if (referenced_type_should_be_emitted(*i, ctxt, tu, is_last))
referenced_types_to_emit.insert(*i);
}
+}
+
+/// Serialize a translation unit to an output stream.
+///
+/// @param ctxt the context of the serialization. It contains e.g,
+/// the output stream to serialize to.
+///
+/// @param tu the translation unit to serialize.
+///
+/// @param indent how many indentation spaces to use during the
+/// serialization.
+///
+/// @param is_last If true, it means the TU to emit is the last one of
+/// the corpus. If this is the case, all the remaining referenced
+/// types that were not emitted are going to be emitted here,
+/// irrespective of if they belong to this TU or not. This is quite a
+/// hack. Ideally, we should have a pass that walks all the TUs,
+/// detect their non-emitted referenced types, before hand. Then,
+/// when we start emitting the TUs, we know for each TU which
+/// non-emitted referenced type should be emitted. As we don't yet
+/// have such a pass, we do our best for now.
+///
+/// @return true upon successful completion, false otherwise.
+bool
+write_translation_unit(write_context& ctxt,
+ const translation_unit& tu,
+ const unsigned indent,
+ bool is_last)
+{
+ if (tu.is_empty() && !is_last)
+ return false;
+
+ if (is_last
+ && tu.is_empty()
+ && ctxt.has_non_emitted_referenced_types())
+ return false;
+
+ ostream& o = ctxt.get_ostream();
+ const config& c = ctxt.get_config();
+
+ do_indent(o, indent);
+
+ o << "<abi-instr";
+
+ if (tu.get_address_size() != 0)
+ o << " address-size='" << static_cast<int>(tu.get_address_size()) << "'";
+
+ std::string tu_path = tu.get_path();
+ if (ctxt.get_short_locs())
+ tools_utils::base_name(tu_path, tu_path);
+ if (!tu_path.empty())
+ o << " path='" << xml::escape_xml_string(tu_path) << "'";
+
+ if (!tu.get_compilation_dir_path().empty() && ctxt.get_write_comp_dir())
+ o << " comp-dir-path='"
+ << xml::escape_xml_string(tu.get_compilation_dir_path()) << "'";
+
+ if (tu.get_language() != translation_unit::LANG_UNKNOWN)
+ o << " language='"
+ << translation_unit_language_to_string(tu.get_language())
+ <<"'";
+
+ if (tu.is_empty() && !is_last)
+ {
+ o << "/>\n";
+ return true;
+ }
+
+ o << ">\n";
+
+ write_canonical_types_of_scope(*tu.get_global_scope(),
+ ctxt, indent + c.get_xml_element_indent());
+
+ typedef scope_decl::declarations declarations;
+ typedef declarations::const_iterator const_iterator;
+ const declarations& d = tu.get_global_scope()->get_sorted_member_decls();
+
+ for (const_iterator i = d.begin(); i != d.end(); ++i)
+ {
+ if (type_base_sptr t = is_type(*i))
+ {
+ // Emit declaration-only classes that are needed. Some of
+ // these classes can be empty. Those beasts can be classes
+ // that only contain member types. They can also be classes
+ // considered "opaque".
+ if (class_decl_sptr class_type = is_class_type(t))
+ if (class_type->get_is_declaration_only()
+ && !ctxt.type_is_emitted(class_type))
+ write_type(class_type, ctxt,
+ indent + c.get_xml_element_indent());
+ continue;
+ }
+
+ if (decl_base_sptr d = is_decl(*i))
+ if (ctxt.decl_is_emitted(d))
+ continue;
+ write_decl(*i, ctxt, indent + c.get_xml_element_indent());
+ }
+
+ write_referenced_types(ctxt, tu, indent, is_last);
// Now handle all function types that were not only referenced by
// emitted types.
@@ -2502,6 +2523,10 @@ write_translation_unit(write_context& ctxt,
write_function_type(fn_type, ctxt, indent + c.get_xml_element_indent());
}
+ // After we've written out the live function types, we need to write
+ // the types they referenced.
+ write_referenced_types(ctxt, tu, indent, is_last);
+
do_indent(o, indent);
o << "</abi-instr>\n";