def run(self): for inst in self._iter_inst(): fname = "op_%s" % inst.opname fn = getattr(self, fname, None) if fn is not None: fn(inst) elif inst.is_jump: # this catches e.g. try... except l = Loc(self.bytecode.func_id.filename, inst.lineno) if inst.opname in {"SETUP_EXCEPT", "SETUP_FINALLY"}: msg = "'try' block not supported until python3.7 or later" else: msg = "Use of unsupported opcode (%s) found" % inst.opname raise UnsupportedError(msg, loc=l) else: # Non-jump instructions are ignored pass # intentionally # Close all blocks for cur, nxt in zip(self.blockseq, self.blockseq[1:]): blk = self.blocks[cur] if not blk.outgoing_jumps and not blk.terminating: blk.outgoing_jumps[nxt] = 0 graph = CFGraph() for b in self.blocks: graph.add_node(b) for b in self.blocks.values(): for out, pops in b.outgoing_jumps.items(): graph.add_edge(b.offset, out, pops) graph.set_entry_point(min(self.blocks)) graph.process() self.graph = graph # Fill incoming for b in utils.itervalues(self.blocks): for out, pops in b.outgoing_jumps.items(): self.blocks[out].incoming_jumps[b.offset] = pops # Find liveblocks self.liveblocks = dict((i, self.blocks[i]) for i in self.graph.nodes()) for lastblk in reversed(self.blockseq): if lastblk in self.liveblocks: break else: raise AssertionError("No live block that exits!?") # Find backbone backbone = self.graph.backbone() # Filter out in loop blocks (Assuming no other cyclic control blocks) # This is to unavoid variable defined in loops to be considered as # function scope. inloopblocks = set() for b in self.blocks.keys(): if self.graph.in_loops(b): inloopblocks.add(b) self.backbone = backbone - inloopblocks
def op_CALL_FUNCTION_EX(self, state, inst): if inst.arg & 1: errmsg = "CALL_FUNCTION_EX with **kwargs not supported" raise UnsupportedError(errmsg) vararg = state.pop() func = state.pop() res = state.make_temp() state.append(inst, func=func, vararg=vararg, res=res) state.push(res)
def dispatch(self, state): inst = state.get_inst() _logger.debug("dispatch pc=%s, inst=%s", state._pc, inst) fn = getattr(self, "op_{}".format(inst.opname), None) if fn is not None: fn(state, inst) else: msg = "Use of unsupported opcode (%s) found" % inst.opname raise UnsupportedError(msg, loc=self.get_debug_loc(inst.lineno))
def literal_unroll_impl(container): from numba.errors import UnsupportedError if sys.version_info[:2] < (3, 6): raise UnsupportedError( "literal_unroll is only support in Python > 3.5") def impl(container): return container return impl
def op_POP_EXCEPT(self, state, inst): blk = state.pop_block() if blk['kind'] not in {BlockKind('EXCEPT'), BlockKind('FINALLY')}: raise UnsupportedError( "POP_EXCEPT got an unexpected block: {}".format(blk['kind']), loc=self.get_debug_loc(inst.lineno), ) state.pop() state.pop() state.pop() # Forces a new block state.fork(pc=inst.next)
def op_RAISE_VARARGS(self, state, inst): in_exc_block = any([ state.get_top_block("EXCEPT") is not None, state.get_top_block("FINALLY") is not None ]) if inst.arg == 0: exc = None if in_exc_block: raise UnsupportedError( "The re-raising of an exception is not yet supported.", loc=self.get_debug_loc(inst.lineno), ) elif inst.arg == 1: exc = state.pop() else: raise ValueError("Multiple argument raise is not supported.") state.append(inst, exc=exc) state.terminate()
def op_POP_FINALLY(self, state, inst): # we don't emulate the exact stack behavior if inst.arg != 0: msg = ('Unsupported use of a bytecode related to try..finally' ' or a with-context') raise UnsupportedError(msg, loc=self.get_debug_loc(inst.lineno))