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.sort()
|
||||
self.cfg = ControlFlowGraph()
|
||||
self.loop_stack = []
|
||||
self.control_stack = []
|
||||
for block in self.block_list:
|
||||
self.cfg.add_block(block, blocks[block])
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ class ControlFlowBuilder (BenignBytecodeVisitorMixin, BasicBlockVisitor):
|
|||
self.cfg.compute_dataflow()
|
||||
self.cfg.update_for_ssa()
|
||||
ret_val = self.cfg
|
||||
del self.loop_stack
|
||||
del self.control_stack
|
||||
del self.cfg
|
||||
del self.block_list
|
||||
del self.blocks
|
||||
|
|
@ -70,7 +70,7 @@ class ControlFlowBuilder (BenignBytecodeVisitorMixin, BasicBlockVisitor):
|
|||
elif op in opcode.hasjrel:
|
||||
self.cfg.add_edge(block, i + arg + 3)
|
||||
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)
|
||||
elif opname != 'RETURN_VALUE':
|
||||
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,
|
||||
**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):
|
||||
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,
|
||||
**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):
|
||||
self.loop_stack.pop()
|
||||
self.control_stack.pop()
|
||||
return super(ControlFlowBuilder, self).op_POP_BLOCK(i, op, arg, *args,
|
||||
**kws)
|
||||
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ class BytecodeFlowBuilder (BasicBlockVisitor):
|
|||
op_CALL_FUNCTION_VAR = _op
|
||||
op_CALL_FUNCTION_VAR_KW = _op
|
||||
op_COMPARE_OP = _op
|
||||
#op_CONTINUE_LOOP = _op
|
||||
#op_CONTINUE_LOOP = _not_implemented
|
||||
op_DELETE_ATTR = _op
|
||||
op_DELETE_FAST = _op
|
||||
op_DELETE_GLOBAL = _op
|
||||
|
|
@ -142,9 +142,14 @@ class BytecodeFlowBuilder (BasicBlockVisitor):
|
|||
def op_DUP_TOPX (self, i, op, 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_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_GET_ITER = _op
|
||||
|
||||
|
|
@ -175,15 +180,26 @@ class BytecodeFlowBuilder (BasicBlockVisitor):
|
|||
op_JUMP_FORWARD = _op
|
||||
|
||||
def op_JUMP_IF_FALSE (self, i, op, arg):
|
||||
opname, _, _, _ = self.opmap[op]
|
||||
ret_val = (i, op, opname, arg, [self.stack[-1]])
|
||||
ret_val = i, op, self.opnames[op], arg, [self.stack[-1]]
|
||||
self.block.append(ret_val)
|
||||
return ret_val
|
||||
|
||||
#op_JUMP_IF_FALSE_OR_POP = _not_implemented
|
||||
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_CLOSURE = _op
|
||||
#op_LOAD_BUILD_CLASS = _not_implemented
|
||||
#op_LOAD_CLOSURE = _not_implemented
|
||||
op_LOAD_CONST = _op
|
||||
op_LOAD_DEREF = _op
|
||||
op_LOAD_FAST = _op
|
||||
|
|
@ -219,19 +235,24 @@ class BytecodeFlowBuilder (BasicBlockVisitor):
|
|||
def op_ROT_TWO (self, i, op, arg):
|
||||
self.stack[-2:] = (self.stack[-1], self.stack[-2])
|
||||
|
||||
#op_SETUP_EXCEPT = _op
|
||||
#op_SETUP_FINALLY = _op
|
||||
#op_SETUP_EXCEPT = _not_implemented
|
||||
#op_SETUP_FINALLY = _not_implemented
|
||||
|
||||
def op_SETUP_LOOP (self, 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_STOP_CODE = _op
|
||||
#op_STOP_CODE = _not_implemented
|
||||
op_STORE_ATTR = _op
|
||||
op_STORE_DEREF = _op
|
||||
op_STORE_FAST = _op
|
||||
op_STORE_GLOBAL = _op
|
||||
#op_STORE_LOCALS = _not_implemented
|
||||
op_STORE_MAP = _op
|
||||
op_STORE_NAME = _op
|
||||
op_STORE_SLICE = _op
|
||||
|
|
@ -241,8 +262,9 @@ class BytecodeFlowBuilder (BasicBlockVisitor):
|
|||
op_UNARY_NEGATIVE = _op
|
||||
op_UNARY_NOT = _op
|
||||
op_UNARY_POSITIVE = _op
|
||||
op_UNPACK_SEQUENCE = _op
|
||||
#op_WITH_CLEANUP = _op
|
||||
#op_UNPACK_EX = _not_implemented
|
||||
#op_UNPACK_SEQUENCE = _not_implemented
|
||||
#op_WITH_CLEANUP = _not_implemented
|
||||
op_YIELD_VALUE = _op
|
||||
|
||||
# ______________________________________________________________________
|
||||
|
|
@ -254,6 +276,7 @@ def build_flow (func):
|
|||
cfg = byte_control.build_cfg(func)
|
||||
return BytecodeFlowBuilder().visit_cfg(cfg)
|
||||
|
||||
|
||||
# ______________________________________________________________________
|
||||
# Main (self-test) routine
|
||||
|
||||
|
|
|
|||
|
|
@ -591,7 +591,7 @@ def llpython_into (llvm_function, **kws):
|
|||
# Main (self-test) routine
|
||||
|
||||
def main (*args):
|
||||
from tests import llfuncs, llfunctys
|
||||
from .tests import llfuncs, llfunctys
|
||||
if not args:
|
||||
args = ('doslice',)
|
||||
elif 'all' in args:
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ OPCODE_MAP = {
|
|||
'BUILD_CLASS': (3, 1, None),
|
||||
'BUILD_LIST': (-1, 1, None),
|
||||
'BUILD_MAP': (-1, 1, None),
|
||||
'BUILD_SET': (None, None, None),
|
||||
'BUILD_SLICE': (None, None, None),
|
||||
'BUILD_SET': (-1, 1, None),
|
||||
'BUILD_SLICE': (-1, 1, None), # oparg should only be 2 or 3
|
||||
'BUILD_TUPLE': (-1, 1, None),
|
||||
'CALL_FUNCTION': (-2, 1, None),
|
||||
'CALL_FUNCTION_KW': (-3, 1, None),
|
||||
|
|
@ -57,7 +57,7 @@ OPCODE_MAP = {
|
|||
'DUP_TOPX': (None, None, None),
|
||||
'DUP_TOP_TWO': (None, None, None),
|
||||
'END_FINALLY': (None, None, None),
|
||||
'EXEC_STMT': (None, None, None),
|
||||
'EXEC_STMT': (3, 0, 1),
|
||||
'EXTENDED_ARG': (None, None, None),
|
||||
'FOR_ITER': (1, 1, 1),
|
||||
'GET_ITER': (1, 1, None),
|
||||
|
|
@ -83,7 +83,7 @@ OPCODE_MAP = {
|
|||
'JUMP_IF_FALSE_OR_POP': (None, None, None),
|
||||
'JUMP_IF_TRUE': (1, 1, 1),
|
||||
'JUMP_IF_TRUE_OR_POP': (None, None, None),
|
||||
'LIST_APPEND': (2, 0, 1),
|
||||
'LIST_APPEND': (None, None, None),
|
||||
'LOAD_ATTR': (1, 1, None),
|
||||
'LOAD_BUILD_CLASS': (None, None, None),
|
||||
'LOAD_CLOSURE': (None, None, None),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue