Working on full opcode coverage and support for exception control flow.
This commit is contained in:
parent
5ef00671e7
commit
6f532f164a
4 changed files with 61 additions and 23 deletions
|
|
@ -33,7 +33,7 @@ class ControlFlowBuilder (BenignBytecodeVisitorMixin, BasicBlockVisitor):
|
||||||
self.block_list = list(blocks.keys())
|
self.block_list = list(blocks.keys())
|
||||||
self.block_list.sort()
|
self.block_list.sort()
|
||||||
self.cfg = ControlFlowGraph()
|
self.cfg = ControlFlowGraph()
|
||||||
self.loop_stack = []
|
self.control_stack = []
|
||||||
for block in self.block_list:
|
for block in self.block_list:
|
||||||
self.cfg.add_block(block, blocks[block])
|
self.cfg.add_block(block, blocks[block])
|
||||||
|
|
||||||
|
|
@ -43,7 +43,7 @@ class ControlFlowBuilder (BenignBytecodeVisitorMixin, BasicBlockVisitor):
|
||||||
self.cfg.compute_dataflow()
|
self.cfg.compute_dataflow()
|
||||||
self.cfg.update_for_ssa()
|
self.cfg.update_for_ssa()
|
||||||
ret_val = self.cfg
|
ret_val = self.cfg
|
||||||
del self.loop_stack
|
del self.control_stack
|
||||||
del self.cfg
|
del self.cfg
|
||||||
del self.block_list
|
del self.block_list
|
||||||
del self.blocks
|
del self.blocks
|
||||||
|
|
@ -70,7 +70,7 @@ class ControlFlowBuilder (BenignBytecodeVisitorMixin, BasicBlockVisitor):
|
||||||
elif op in opcode.hasjrel:
|
elif op in opcode.hasjrel:
|
||||||
self.cfg.add_edge(block, i + arg + 3)
|
self.cfg.add_edge(block, i + arg + 3)
|
||||||
elif opname == 'BREAK_LOOP':
|
elif opname == 'BREAK_LOOP':
|
||||||
loop_i, _, loop_arg = self.loop_stack[-1]
|
loop_i, _, loop_arg = self.control_stack[-1]
|
||||||
self.cfg.add_edge(block, loop_i + loop_arg + 3)
|
self.cfg.add_edge(block, loop_i + loop_arg + 3)
|
||||||
elif opname != 'RETURN_VALUE':
|
elif opname != 'RETURN_VALUE':
|
||||||
self.cfg.add_edge(block, self._get_next_block(block))
|
self.cfg.add_edge(block, self._get_next_block(block))
|
||||||
|
|
@ -87,13 +87,28 @@ class ControlFlowBuilder (BenignBytecodeVisitorMixin, BasicBlockVisitor):
|
||||||
return super(ControlFlowBuilder, self).op_STORE_FAST(i, op, arg, *args,
|
return super(ControlFlowBuilder, self).op_STORE_FAST(i, op, arg, *args,
|
||||||
**kws)
|
**kws)
|
||||||
|
|
||||||
|
def op_SETUP_EXCEPT (self, i, op, arg, *args, **kws):
|
||||||
|
self.control_stack.append((i, op, arg))
|
||||||
|
return super(ControlFlowBuilder, self).op_SETUP_EXCEPT(i, op, arg,
|
||||||
|
*args, **kws)
|
||||||
|
|
||||||
|
def op_SETUP_FINALLY (self, i, op, arg, *args, **kws):
|
||||||
|
self.control_stack.append((i, op, arg))
|
||||||
|
return super(ControlFlowBuilder, self).op_SETUP_FINALLY(i, op, arg,
|
||||||
|
*args, **kws)
|
||||||
|
|
||||||
def op_SETUP_LOOP (self, i, op, arg, *args, **kws):
|
def op_SETUP_LOOP (self, i, op, arg, *args, **kws):
|
||||||
self.loop_stack.append((i, op, arg))
|
self.control_stack.append((i, op, arg))
|
||||||
return super(ControlFlowBuilder, self).op_SETUP_LOOP(i, op, arg, *args,
|
return super(ControlFlowBuilder, self).op_SETUP_LOOP(i, op, arg, *args,
|
||||||
**kws)
|
**kws)
|
||||||
|
|
||||||
|
def op_SETUP_WITH (self, i, op, arg, *args, **kws):
|
||||||
|
self.control_stack.append((i, op, arg))
|
||||||
|
return super(ControlFlowBuilder, self).op_SETUP_WITH(i, op, arg, *args,
|
||||||
|
**kws)
|
||||||
|
|
||||||
def op_POP_BLOCK (self, i, op, arg, *args, **kws):
|
def op_POP_BLOCK (self, i, op, arg, *args, **kws):
|
||||||
self.loop_stack.pop()
|
self.control_stack.pop()
|
||||||
return super(ControlFlowBuilder, self).op_POP_BLOCK(i, op, arg, *args,
|
return super(ControlFlowBuilder, self).op_POP_BLOCK(i, op, arg, *args,
|
||||||
**kws)
|
**kws)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ class BytecodeFlowBuilder (BasicBlockVisitor):
|
||||||
op_CALL_FUNCTION_VAR = _op
|
op_CALL_FUNCTION_VAR = _op
|
||||||
op_CALL_FUNCTION_VAR_KW = _op
|
op_CALL_FUNCTION_VAR_KW = _op
|
||||||
op_COMPARE_OP = _op
|
op_COMPARE_OP = _op
|
||||||
#op_CONTINUE_LOOP = _op
|
#op_CONTINUE_LOOP = _not_implemented
|
||||||
op_DELETE_ATTR = _op
|
op_DELETE_ATTR = _op
|
||||||
op_DELETE_FAST = _op
|
op_DELETE_FAST = _op
|
||||||
op_DELETE_GLOBAL = _op
|
op_DELETE_GLOBAL = _op
|
||||||
|
|
@ -142,9 +142,14 @@ class BytecodeFlowBuilder (BasicBlockVisitor):
|
||||||
def op_DUP_TOPX (self, i, op, arg):
|
def op_DUP_TOPX (self, i, op, arg):
|
||||||
self.stack += self.stack[-arg:]
|
self.stack += self.stack[-arg:]
|
||||||
|
|
||||||
#op_END_FINALLY = _op
|
#op_DUP_TOP_TWO = _not_implemented
|
||||||
|
#op_END_FINALLY = _not_implemented
|
||||||
op_EXEC_STMT = _op
|
op_EXEC_STMT = _op
|
||||||
#op_EXTENDED_ARG = _op
|
|
||||||
|
def op_EXTENDED_ARG (self, i, op, arg):
|
||||||
|
raise ValueError("Unexpected EXTENDED_ARG opcode at index %d (should "
|
||||||
|
"be removed by itercode)." % i)
|
||||||
|
|
||||||
op_FOR_ITER = _op
|
op_FOR_ITER = _op
|
||||||
op_GET_ITER = _op
|
op_GET_ITER = _op
|
||||||
|
|
||||||
|
|
@ -175,15 +180,26 @@ class BytecodeFlowBuilder (BasicBlockVisitor):
|
||||||
op_JUMP_FORWARD = _op
|
op_JUMP_FORWARD = _op
|
||||||
|
|
||||||
def op_JUMP_IF_FALSE (self, i, op, arg):
|
def op_JUMP_IF_FALSE (self, i, op, arg):
|
||||||
opname, _, _, _ = self.opmap[op]
|
ret_val = i, op, self.opnames[op], arg, [self.stack[-1]]
|
||||||
ret_val = (i, op, opname, arg, [self.stack[-1]])
|
|
||||||
self.block.append(ret_val)
|
self.block.append(ret_val)
|
||||||
return ret_val
|
return ret_val
|
||||||
|
|
||||||
|
#op_JUMP_IF_FALSE_OR_POP = _not_implemented
|
||||||
op_JUMP_IF_TRUE = op_JUMP_IF_FALSE
|
op_JUMP_IF_TRUE = op_JUMP_IF_FALSE
|
||||||
op_LIST_APPEND = _op
|
#op_JUMP_IF_TRUE_OR_POP = op_JUMP_IF_FALSE_OR_POP
|
||||||
|
|
||||||
|
def op_LIST_APPEND (self, i, op, arg):
|
||||||
|
'''This method is used for both LIST_APPEND, and SET_ADD
|
||||||
|
opcodes.'''
|
||||||
|
elem = self.stack.pop()
|
||||||
|
container = self.stack[-arg]
|
||||||
|
ret_val = i, op, self.opnames[op], arg, [container, elem]
|
||||||
|
self.block.append(ret_val)
|
||||||
|
return ret_val
|
||||||
|
|
||||||
op_LOAD_ATTR = _op
|
op_LOAD_ATTR = _op
|
||||||
op_LOAD_CLOSURE = _op
|
#op_LOAD_BUILD_CLASS = _not_implemented
|
||||||
|
#op_LOAD_CLOSURE = _not_implemented
|
||||||
op_LOAD_CONST = _op
|
op_LOAD_CONST = _op
|
||||||
op_LOAD_DEREF = _op
|
op_LOAD_DEREF = _op
|
||||||
op_LOAD_FAST = _op
|
op_LOAD_FAST = _op
|
||||||
|
|
@ -219,19 +235,24 @@ class BytecodeFlowBuilder (BasicBlockVisitor):
|
||||||
def op_ROT_TWO (self, i, op, arg):
|
def op_ROT_TWO (self, i, op, arg):
|
||||||
self.stack[-2:] = (self.stack[-1], self.stack[-2])
|
self.stack[-2:] = (self.stack[-1], self.stack[-2])
|
||||||
|
|
||||||
#op_SETUP_EXCEPT = _op
|
#op_SETUP_EXCEPT = _not_implemented
|
||||||
#op_SETUP_FINALLY = _op
|
#op_SETUP_FINALLY = _not_implemented
|
||||||
|
|
||||||
def op_SETUP_LOOP (self, i, op, arg):
|
def op_SETUP_LOOP (self, i, op, arg):
|
||||||
self.loop_stack.append((i, op, arg))
|
self.loop_stack.append((i, op, arg))
|
||||||
self.block.append((i, op, self.opnames[op], arg, []))
|
ret_val = i, op, self.opnames[op], arg, []
|
||||||
|
self.block.append(ret_val)
|
||||||
|
return ret_val
|
||||||
|
|
||||||
|
#op_SETUP_WITH = _not_implemented
|
||||||
|
op_SET_ADD = op_LIST_APPEND
|
||||||
op_SLICE = _op
|
op_SLICE = _op
|
||||||
#op_STOP_CODE = _op
|
#op_STOP_CODE = _not_implemented
|
||||||
op_STORE_ATTR = _op
|
op_STORE_ATTR = _op
|
||||||
op_STORE_DEREF = _op
|
op_STORE_DEREF = _op
|
||||||
op_STORE_FAST = _op
|
op_STORE_FAST = _op
|
||||||
op_STORE_GLOBAL = _op
|
op_STORE_GLOBAL = _op
|
||||||
|
#op_STORE_LOCALS = _not_implemented
|
||||||
op_STORE_MAP = _op
|
op_STORE_MAP = _op
|
||||||
op_STORE_NAME = _op
|
op_STORE_NAME = _op
|
||||||
op_STORE_SLICE = _op
|
op_STORE_SLICE = _op
|
||||||
|
|
@ -241,8 +262,9 @@ class BytecodeFlowBuilder (BasicBlockVisitor):
|
||||||
op_UNARY_NEGATIVE = _op
|
op_UNARY_NEGATIVE = _op
|
||||||
op_UNARY_NOT = _op
|
op_UNARY_NOT = _op
|
||||||
op_UNARY_POSITIVE = _op
|
op_UNARY_POSITIVE = _op
|
||||||
op_UNPACK_SEQUENCE = _op
|
#op_UNPACK_EX = _not_implemented
|
||||||
#op_WITH_CLEANUP = _op
|
#op_UNPACK_SEQUENCE = _not_implemented
|
||||||
|
#op_WITH_CLEANUP = _not_implemented
|
||||||
op_YIELD_VALUE = _op
|
op_YIELD_VALUE = _op
|
||||||
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
|
|
@ -254,6 +276,7 @@ def build_flow (func):
|
||||||
cfg = byte_control.build_cfg(func)
|
cfg = byte_control.build_cfg(func)
|
||||||
return BytecodeFlowBuilder().visit_cfg(cfg)
|
return BytecodeFlowBuilder().visit_cfg(cfg)
|
||||||
|
|
||||||
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
# Main (self-test) routine
|
# Main (self-test) routine
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -591,7 +591,7 @@ def llpython_into (llvm_function, **kws):
|
||||||
# Main (self-test) routine
|
# Main (self-test) routine
|
||||||
|
|
||||||
def main (*args):
|
def main (*args):
|
||||||
from tests import llfuncs, llfunctys
|
from .tests import llfuncs, llfunctys
|
||||||
if not args:
|
if not args:
|
||||||
args = ('doslice',)
|
args = ('doslice',)
|
||||||
elif 'all' in args:
|
elif 'all' in args:
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@ OPCODE_MAP = {
|
||||||
'BUILD_CLASS': (3, 1, None),
|
'BUILD_CLASS': (3, 1, None),
|
||||||
'BUILD_LIST': (-1, 1, None),
|
'BUILD_LIST': (-1, 1, None),
|
||||||
'BUILD_MAP': (-1, 1, None),
|
'BUILD_MAP': (-1, 1, None),
|
||||||
'BUILD_SET': (None, None, None),
|
'BUILD_SET': (-1, 1, None),
|
||||||
'BUILD_SLICE': (None, None, None),
|
'BUILD_SLICE': (-1, 1, None), # oparg should only be 2 or 3
|
||||||
'BUILD_TUPLE': (-1, 1, None),
|
'BUILD_TUPLE': (-1, 1, None),
|
||||||
'CALL_FUNCTION': (-2, 1, None),
|
'CALL_FUNCTION': (-2, 1, None),
|
||||||
'CALL_FUNCTION_KW': (-3, 1, None),
|
'CALL_FUNCTION_KW': (-3, 1, None),
|
||||||
|
|
@ -57,7 +57,7 @@ OPCODE_MAP = {
|
||||||
'DUP_TOPX': (None, None, None),
|
'DUP_TOPX': (None, None, None),
|
||||||
'DUP_TOP_TWO': (None, None, None),
|
'DUP_TOP_TWO': (None, None, None),
|
||||||
'END_FINALLY': (None, None, None),
|
'END_FINALLY': (None, None, None),
|
||||||
'EXEC_STMT': (None, None, None),
|
'EXEC_STMT': (3, 0, 1),
|
||||||
'EXTENDED_ARG': (None, None, None),
|
'EXTENDED_ARG': (None, None, None),
|
||||||
'FOR_ITER': (1, 1, 1),
|
'FOR_ITER': (1, 1, 1),
|
||||||
'GET_ITER': (1, 1, None),
|
'GET_ITER': (1, 1, None),
|
||||||
|
|
@ -83,7 +83,7 @@ OPCODE_MAP = {
|
||||||
'JUMP_IF_FALSE_OR_POP': (None, None, None),
|
'JUMP_IF_FALSE_OR_POP': (None, None, None),
|
||||||
'JUMP_IF_TRUE': (1, 1, 1),
|
'JUMP_IF_TRUE': (1, 1, 1),
|
||||||
'JUMP_IF_TRUE_OR_POP': (None, None, None),
|
'JUMP_IF_TRUE_OR_POP': (None, None, None),
|
||||||
'LIST_APPEND': (2, 0, 1),
|
'LIST_APPEND': (None, None, None),
|
||||||
'LOAD_ATTR': (1, 1, None),
|
'LOAD_ATTR': (1, 1, None),
|
||||||
'LOAD_BUILD_CLASS': (None, None, None),
|
'LOAD_BUILD_CLASS': (None, None, None),
|
||||||
'LOAD_CLOSURE': (None, None, None),
|
'LOAD_CLOSURE': (None, None, None),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue