Beispiel #1
0
 def enter_blocks (self, blocks):
     super(ControlFlowBuilder, self).enter_blocks(blocks)
     self.blocks = blocks
     self.block_list = list(blocks.keys())
     self.block_list.sort()
     self.cfg = ControlFlowGraph()
     self.loop_stack = []
     for block in self.block_list:
         self.cfg.add_block(block, blocks[block])
Beispiel #2
0
 def enter_flow_object(self, flow):
     super(ControlFlowBuilder, self).enter_flow_object(flow)
     self.flow = flow
     self.cfg = ControlFlowGraph()
     for block in flow.keys():
         self.cfg.add_block(block, flow[block])
Beispiel #3
0
class ControlFlowBuilder(BenignBytecodeVisitorMixin, BytecodeFlowVisitor):
    '''Visitor responsible for traversing a bytecode flow object and
    building a control flow graph (CFG).

    The primary purpose of this transformation is to create a CFG,
    which is used by later transformers for dataflow analysis.
    '''
    def visit(self, flow, nargs=0, *args, **kws):
        '''Given a bytecode flow, and an optional number of arguments,
        return a :py:class:`llpython.control_flow.ControlFlowGraph`
        instance describing the full control flow of the bytecode
        flow.'''
        self.nargs = nargs
        ret_val = super(ControlFlowBuilder, self).visit(flow, *args, **kws)
        del self.nargs
        return ret_val

    def enter_flow_object(self, flow):
        super(ControlFlowBuilder, self).enter_flow_object(flow)
        self.flow = flow
        self.cfg = ControlFlowGraph()
        for block in flow.keys():
            self.cfg.add_block(block, flow[block])

    def exit_flow_object(self, flow):
        super(ControlFlowBuilder, self).exit_flow_object(flow)
        assert self.flow == flow
        self.cfg.compute_dataflow()
        self.cfg.update_for_ssa()
        ret_val = self.cfg
        del self.cfg
        del self.flow
        return ret_val

    def enter_block(self, block):
        self.block = block
        assert block in self.cfg.blocks
        if block == 0:
            for local_index in range(self.nargs):
                self.op_STORE_FAST(0, opcode.opmap['STORE_FAST'], local_index)
        return True

    def _get_next_block(self, block):
        return self.block_list[self.block_list.index(block) + 1]

    def exit_block(self, block):
        assert block == self.block
        del self.block
        i, op, opname, arg, args = self.flow[block][-1]
        if op in opcode.hasjabs:
            self.cfg.add_edge(block, arg)
        elif op in opcode.hasjrel:
            self.cfg.add_edge(block, i + arg + 3)
        elif opname == 'BREAK_LOOP':
            self.cfg.add_edge(block, arg)
        elif opname != 'RETURN_VALUE':
            self.cfg.add_edge(block, self._get_next_block(block))
        if op in opcode_util.hascbranch:
            self.cfg.add_edge(block, self._get_next_block(block))

    def op_LOAD_FAST(self, i, op, arg, *args, **kws):
        self.cfg.blocks_reads[self.block].add(arg)
        return super(ControlFlowBuilder,
                     self).op_LOAD_FAST(i, op, arg, *args, **kws)

    def op_STORE_FAST(self, i, op, arg, *args, **kws):
        self.cfg.writes_local(self.block, i, arg)
        return super(ControlFlowBuilder,
                     self).op_STORE_FAST(i, op, arg, *args, **kws)
Beispiel #4
0
 def enter_flow_object (self, flow):
     super(ControlFlowBuilder, self).enter_flow_object(flow)
     self.flow = flow
     self.cfg = ControlFlowGraph()
     for block in flow.keys():
         self.cfg.add_block(block, flow[block])
Beispiel #5
0
class ControlFlowBuilder (BenignBytecodeVisitorMixin, BytecodeFlowVisitor):
    '''Visitor responsible for traversing a bytecode flow object and
    building a control flow graph (CFG).

    The primary purpose of this transformation is to create a CFG,
    which is used by later transformers for dataflow analysis.
    '''
    def visit (self, flow, nargs = 0, *args, **kws):
        '''Given a bytecode flow, and an optional number of arguments,
        return a :py:class:`llpython.control_flow.ControlFlowGraph`
        instance describing the full control flow of the bytecode
        flow.'''
        self.nargs = nargs
        ret_val = super(ControlFlowBuilder, self).visit(flow, *args, **kws)
        del self.nargs
        return ret_val

    def enter_flow_object (self, flow):
        super(ControlFlowBuilder, self).enter_flow_object(flow)
        self.flow = flow
        self.cfg = ControlFlowGraph()
        for block in flow.keys():
            self.cfg.add_block(block, flow[block])

    def exit_flow_object (self, flow):
        super(ControlFlowBuilder, self).exit_flow_object(flow)
        assert self.flow == flow
        self.cfg.compute_dataflow()
        self.cfg.update_for_ssa()
        ret_val = self.cfg
        del self.cfg
        del self.flow
        return ret_val

    def enter_block (self, block):
        self.block = block
        assert block in self.cfg.blocks
        if block == 0:
            for local_index in range(self.nargs):
                self.op_STORE_FAST(0, opcode.opmap['STORE_FAST'], local_index)
        return True

    def _get_next_block (self, block):
        return self.block_list[self.block_list.index(block) + 1]

    def exit_block (self, block):
        assert block == self.block
        del self.block
        i, op, opname, arg, args = self.flow[block][-1]
        if op in opcode.hasjabs:
            self.cfg.add_edge(block, arg)
        elif op in opcode.hasjrel:
            self.cfg.add_edge(block, i + arg + 3)
        elif opname == 'BREAK_LOOP':
            self.cfg.add_edge(block, arg)
        elif opname != 'RETURN_VALUE':
            self.cfg.add_edge(block, self._get_next_block(block))
        if op in opcode_util.hascbranch:
            self.cfg.add_edge(block, self._get_next_block(block))

    def op_LOAD_FAST (self, i, op, arg, *args, **kws):
        self.cfg.blocks_reads[self.block].add(arg)
        return super(ControlFlowBuilder, self).op_LOAD_FAST(i, op, arg, *args,
                                                            **kws)

    def op_STORE_FAST (self, i, op, arg, *args, **kws):
        self.cfg.writes_local(self.block, i, arg)
        return super(ControlFlowBuilder, self).op_STORE_FAST(i, op, arg, *args,
                                                             **kws)