예제 #1
0
    def format(self):
        # Yes... when serializing a whole function, this is computed once per
        # basic block instead of once for the function... But do we care?
        from decompil.analysis.predecessors import get_predecessors
        preds = get_predecessors(self.function, allow_incomplete=True)[self]
        indentation = (Text, '    ')

        result = self.format_label() + [(Punctuation, ':'), (Text, '\n')]
        if preds:
            result.extend([
                indentation,
                (Comment, '; Predecessors: {}'.format(', '.join(
                    sorted(pred.name for pred in preds)))),
                (Text, '\n'),
            ])

        current_origin = None
        for insn in self.instructions:
            if insn.origin != current_origin:
                current_origin = insn.origin
                result.extend([
                    indentation,
                    (Comment, '; {}'.format(current_origin)),
                    (Text, '\n'),
                ])
            result.append(indentation)
            result.extend(insn.format())
            result.append((Text, '\n'))
        return result
예제 #2
0
파일: ir.py 프로젝트: mewbak/decompil
    def format(self):
        # Yes... when serializing a whole function, this is computed once per
        # basic block instead of once for the function... But do we care?
        from decompil.analysis.predecessors import get_predecessors
        preds = get_predecessors(self.function, allow_incomplete=True)[self]
        indentation = (Text, '    ')

        result = self.format_label() + [
            (Punctuation, ':'),
            (Text, '\n')
        ]
        if preds:
            result.extend([
                indentation,
                (Comment, '; Predecessors: {}'.format(', '.join(sorted(
                    pred.name for pred in preds
                )))),
                (Text, '\n'),
            ])

        current_origin = None
        for insn in self.instructions:
            if insn.origin != current_origin:
                current_origin = insn.origin
                result.extend([
                    indentation,
                    (Comment, '; {}'.format(current_origin)),
                    (Text, '\n'),
                ])
            result.append(indentation)
            result.extend(insn.format())
            result.append((Text, '\n'))
        return result
예제 #3
0
    def __init__(self, function):
        self.function = function
        self.predecessors = get_predecessors(function)
        self.bld = builder.Builder()

        # Mapping: register -> set of all basic blocks that store a value in
        # this register.
        self.store_sites = None
        # Reverse mapping for it (i.e. basic block -> set of all registers
        # affected by this basic block).
        self.stored_registers = None

        # Mapping: register -> stack of values to use when loading the register
        # (at some specific point, take the top).  Initialized in _process and
        # really used in transform_reg_insns.
        self.def_stacks = collections.defaultdict(list)

        self.dom_tree = None
예제 #4
0
def get_dominator_tree(func):
    """Return the dominance tree for basic blocks in func.

    This tree is a dictionnary that maps basic blocks to their parent (their
    immediate dominator).
    """
    # Implementation is based on Modern Compiler Implementation, Andew W.
    # Appel, Chapter 19 Static Single-Assignment Form, algorithms 19.9 and
    # 19.10 (naive versions).

    predecessors = get_predecessors(func)

    dfs_tree, dfs_numbers = get_dfs_spanning_tree(func)
    # Mapping: basic block -> its immediate dominator. Once completely built,
    # we can build the dominator tree from it.
    imm_dominators = {}

    # Mapping: basic block -> semidominator
    semidominators = {}
    # Mapping: basic_block -> ??? TODO
    ancestors = {}
    # Mapping: basic_block -> ??? TODO
    buckets = collections.defaultdict(set)
    # Mapping: basic_block -> ??? TODO
    same_dominators = {}

    def ancestor_with_lowest_semi_no(basic_block):
        result = basic_block
        while result not in ancestors:
            bb_semi = semidominators.get(basic_block, None)
            result_semi = semidominators.get(result, None)
            if (dfs_numbers.get(bb_semi, 0) < dfs_numbers.get(result_semi, 0)):
                result = basic_block
            result = ancestors[result]
        return result

    basic_blocks_dfs_order = list(
        sorted((dfs_number, basic_block)
               for basic_block, dfs_number in dfs_numbers.items()))

    for i, basic_block in reversed(basic_blocks_dfs_order):
        if i == 0:
            imm_dominators[basic_block] = None
            continue
        parent = dfs_tree.get_parent(basic_block)

        # Compute the semi-dominator for basic_block.
        semi_candidate = parent
        semi_candidate_number = dfs_numbers[semi_candidate]

        for pred in predecessors[basic_block]:
            s = (pred if dfs_numbers[pred] <= i else semidominators.get(
                ancestor_with_lowest_semi_no(pred), None))
            s_no = dfs_numbers[s]
            if s_no < semi_candidate_number:
                semi_candidate, semi_candidate_number = s, s_no

        semidominators[basic_block] = semi_candidate
        buckets[semi_candidate].add(basic_block)
        ancestors[basic_block] = parent

        for bb in buckets[parent]:
            y = ancestor_with_lowest_semi_no(bb)
            if semidominators[y] == semidominators[bb]:
                imm_dominators[bb] = parent
            else:
                same_dominators[bb] = y
        buckets[parent] = set()

    for i, basic_block in basic_blocks_dfs_order[1:]:
        try:
            same_dom = same_dominators[basic_block]
        except KeyError:
            pass
        else:
            imm_dominators[basic_block] = imm_dominators[same_dom]

    return parent_links_to_tree(imm_dominators)
 def __init__(self, function):
     self.function = function
     self.predecessors = get_predecessors(function)
예제 #6
0
def get_dominator_tree(func):
    """Return the dominance tree for basic blocks in func.

    This tree is a dictionnary that maps basic blocks to their parent (their
    immediate dominator).
    """
    # Implementation is based on Modern Compiler Implementation, Andew W.
    # Appel, Chapter 19 Static Single-Assignment Form, algorithms 19.9 and
    # 19.10 (naive versions).

    predecessors = get_predecessors(func)

    dfs_tree, dfs_numbers = get_dfs_spanning_tree(func)
    # Mapping: basic block -> its immediate dominator. Once completely built,
    # we can build the dominator tree from it.
    imm_dominators = {}

    # Mapping: basic block -> semidominator
    semidominators = {}
    # Mapping: basic_block -> ??? TODO
    ancestors = {}
    # Mapping: basic_block -> ??? TODO
    buckets = collections.defaultdict(set)
    # Mapping: basic_block -> ??? TODO
    same_dominators = {}

    def ancestor_with_lowest_semi_no(basic_block):
        result = basic_block
        while result not in ancestors:
            bb_semi = semidominators.get(basic_block, None)
            result_semi = semidominators.get(result, None)
            if (dfs_numbers.get(bb_semi, 0)
                < dfs_numbers.get(result_semi, 0)
            ):
                result = basic_block
            result = ancestors[result]
        return result

    basic_blocks_dfs_order = list(sorted(
        (dfs_number, basic_block)
        for basic_block, dfs_number in dfs_numbers.items()
    ))

    for i, basic_block in reversed(basic_blocks_dfs_order):
        if i == 0:
            imm_dominators[basic_block] = None
            continue
        parent = dfs_tree.get_parent(basic_block)

        # Compute the semi-dominator for basic_block.
        semi_candidate = parent
        semi_candidate_number = dfs_numbers[semi_candidate]

        for pred in predecessors[basic_block]:
            s = (
                pred
                if dfs_numbers[pred] <= i else
                semidominators.get(ancestor_with_lowest_semi_no(pred), None)
            )
            s_no = dfs_numbers[s]
            if s_no < semi_candidate_number:
                semi_candidate, semi_candidate_number = s, s_no

        semidominators[basic_block] = semi_candidate
        buckets[semi_candidate].add(basic_block)
        ancestors[basic_block] = parent

        for bb in buckets[parent]:
            y = ancestor_with_lowest_semi_no(bb)
            if semidominators[y] == semidominators[bb]:
                imm_dominators[bb] = parent
            else:
                same_dominators[bb] = y
        buckets[parent] = set()

    for i, basic_block in basic_blocks_dfs_order[1:]:
        try:
            same_dom = same_dominators[basic_block]
        except KeyError:
            pass
        else:
            imm_dominators[basic_block] = imm_dominators[same_dom]

    return parent_links_to_tree(imm_dominators)
예제 #7
0
 def __init__(self, function):
     self.function = function
     self.predecessors = get_predecessors(function)
예제 #8
0
    def __init__(self, function):
        self.function = function
        self.predecessors = get_predecessors(function)

        # Set of indices for basic blocks to remove.
        self.to_remove = set()
    def __init__(self, function):
        self.function = function
        self.predecessors = get_predecessors(function)

        # Set of indices for basic blocks to remove.
        self.to_remove = set()