def describe_template_defns(template_defns: Tuple[ir.TemplateDefn, ...], identifier_generator: Iterator[str]): return header_to_cpp(ir.Header(template_defns=template_defns, check_if_error_specializations=(), toplevel_content=(), public_names=frozenset(), split_template_name_by_old_name_and_result_element_name=()), identifier_generator, coverage_collection_enabled=False)
def describe_toplevel_elems(toplevel_elems: Tuple[Union[ir.StaticAssert, ir.ConstantDef, ir.Typedef], ...], identifier_generator: Iterator[str]): return header_to_cpp(ir.Header(template_defns=(), toplevel_content=toplevel_elems, public_names=frozenset(), split_template_name_by_old_name_and_result_element_name=(), check_if_error_specializations=()), identifier_generator, coverage_collection_enabled=False)
def describe_template_defns(template_defns: List[ir.TemplateDefn], identifier_generator: Iterator[str]): return header_to_cpp( ir.Header( template_defns=template_defns, check_if_error_specializations=[], toplevel_content=[], public_names=set(), split_template_name_by_old_name_and_result_element_name=dict()), identifier_generator)
def describe_toplevel_elems(toplevel_elems: List[Union[ir.StaticAssert, ir.ConstantDef, ir.Typedef]], identifier_generator: Iterator[str]): return header_to_cpp( ir.Header( template_defns=[], toplevel_content=toplevel_elems, public_names=set(), split_template_name_by_old_name_and_result_element_name=dict(), check_if_error_specializations=[]), identifier_generator)
def replace_metafunction_calls_with_split_template_calls(header, new_template_defns, split_template_name_by_old_name_and_result_element_name): transformation = ReplaceMetafunctionCallWithSplitTemplateCallTransformation( split_template_name_by_old_name_and_result_element_name) return transformation.transform_header( ir.Header(template_defns=new_template_defns, toplevel_content=header.toplevel_content, public_names=header.public_names, split_template_name_by_old_name_and_result_element_name=split_template_name_by_old_name_and_result_element_name, check_if_error_specializations=header.check_if_error_specializations))
def remove_unused_toplevel_elems(header: ir.Header, linking_final_header: bool): toplevel_elem_names = { elem.name for elem in itertools.chain(header.toplevel_content, header.template_defns) if not isinstance(elem, (ir.StaticAssert, ir.NoOpStmt)) } public_names = header.public_names if not linking_final_header: public_names = public_names.union( split_name for _, split_name in header.split_template_name_by_old_name_and_result_element_name) elem_dependency_graph = nx.DiGraph() for elem in itertools.chain(header.template_defns, header.toplevel_content): if isinstance(elem, (ir.TemplateDefn, ir.ConstantDef, ir.Typedef)): elem_name = elem.name else: # We'll use a dummy name for non-template toplevel elems. elem_name = '' elem_dependency_graph.add_node(elem_name) if elem_name in public_names or (isinstance( elem, (ir.ConstantDef, ir.Typedef)) and any( isinstance(expr, ir.TemplateInstantiation) and expr.instantiation_might_trigger_static_asserts for expr in elem.transitive_subexpressions)): # We also add an edge from the node '' to all toplevel defns that must remain, so that we can use '' as a source below. elem_dependency_graph.add_edge('', elem_name) for identifier in elem.referenced_identifiers: if identifier in toplevel_elem_names: elem_dependency_graph.add_edge(elem_name, identifier) elem_dependency_graph.add_node('') used_elem_names = nx.single_source_shortest_path(elem_dependency_graph, source='').keys() return ir.Header( template_defns=tuple(template_defn for template_defn in header.template_defns if template_defn.name in used_elem_names), toplevel_content=tuple( elem for elem in header.toplevel_content if isinstance(elem, (ir.StaticAssert, ir.NoOpStmt)) or elem.name in used_elem_names), public_names=header.public_names, split_template_name_by_old_name_and_result_element_name=header. split_template_name_by_old_name_and_result_element_name, check_if_error_specializations=header.check_if_error_specializations)
def transform_header(self, header: ir.Header) -> ir.Header: writer = ToplevelWriter() with self.set_writer(writer): for template_defn in header.template_defns: self.transform_template_defn(template_defn) for elem in header.toplevel_content: self.transform_toplevel_elem(elem) check_if_error_specializations = tuple( self.transform_template_specialization(specialization) for specialization in header.check_if_error_specializations) return ir.Header( template_defns=tuple(writer.template_defns), toplevel_content=tuple(writer.toplevel_elems), public_names=header.public_names, split_template_name_by_old_name_and_result_element_name=header. split_template_name_by_old_name_and_result_element_name, check_if_error_specializations=check_if_error_specializations)
def replace_metafunction_calls_with_split_template_calls( header, new_template_defns, split_template_name_by_old_name_and_result_element_name: Dict[Tuple[str, str], str] ) -> ir.Header: transformation = ReplaceMetafunctionCallWithSplitTemplateCallTransformation( split_template_name_by_old_name_and_result_element_name) return transformation.transform_header( ir.Header( template_defns=new_template_defns, toplevel_content=header.toplevel_content, public_names=header.public_names, split_template_name_by_old_name_and_result_element_name=tuple( (k, v) for k, v in split_template_name_by_old_name_and_result_element_name.items( )), check_if_error_specializations=header. check_if_error_specializations))
def _optimize_header_second_pass( header: ir.Header, identifier_generator: Iterator[str], context_object_file_content: ObjectFileContent): new_template_defns = {elem.name: elem for elem in header.template_defns} template_dependency_graph = compute_template_dependency_graph( header.template_defns, new_template_defns) template_dependency_graph_transitive_closure = nx.transitive_closure( template_dependency_graph) assert isinstance(template_dependency_graph_transitive_closure, nx.DiGraph) optimizations = [ lambda template_defn: perform_template_inlining( template_defn, { other_node for other_node in template_dependency_graph_transitive_closure. successors(template_defn.name) if not template_dependency_graph_transitive_closure.has_edge( other_node, template_defn.name) }, new_template_defns, identifier_generator, context_object_file_content), lambda template_defn: perform_local_optimizations_on_template_defn( template_defn, identifier_generator, inline_template_instantiations_with_multiple_references=False), ] for connected_component in reversed( list( compute_condensation_in_topological_order( template_dependency_graph))): def optimize(template_name: str): new_template_defns[ template_name], needs_another_loop = combine_optimizations( new_template_defns[template_name], optimizations) return None, needs_another_loop _iterate_optimization( None, lambda _: optimize_list( sorted(connected_component, key=lambda node: new_template_defns[node].name), lambda template_name: optimize(template_name)), len(connected_component), lambda _: '\n'.join( template_defn_to_cpp_simple(new_template_defns[template_name], identifier_generator) for template_name in connected_component)) optimizations = [ lambda toplevel_content: perform_template_inlining_on_toplevel_elems( toplevel_content, new_template_defns.keys(), new_template_defns, identifier_generator, context_object_file_content), lambda toplevel_content: perform_local_optimizations_on_toplevel_elems( toplevel_content, identifier_generator, inline_template_instantiations_with_multiple_references=False), ] toplevel_content = _iterate_optimization( header.toplevel_content, lambda toplevel_content: combine_optimizations(toplevel_content, optimizations), len(header.toplevel_content), lambda toplevel_content: '\n'.join( toplevel_elem_to_cpp_simple(elem, identifier_generator) for elem in toplevel_content)) return ir.Header( template_defns=tuple(new_template_defns[template_defn.name] for template_defn in header.template_defns), toplevel_content=toplevel_content, public_names=header.public_names, split_template_name_by_old_name_and_result_element_name=header. split_template_name_by_old_name_and_result_element_name, check_if_error_specializations=header.check_if_error_specializations)