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)
Exemple #3
0
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)
Exemple #4
0
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)
Exemple #5
0
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))
Exemple #6
0
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)
Exemple #7
0
    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)
Exemple #8
0
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))
Exemple #9
0
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)