def destack(code, mname, fname, root, argnames, vargs, kargs, compiler, callback, trace=False): dv = DestackVisitor(code, mname, compiler, callback, trace) # Create the locals for each parameter. param = [] for name in argnames: assert isinstance(name, str), name p = Local(name) param.append(p) dv.locals[name] = p if vargs: assert isinstance(vargs, str), vargs v = Local(vargs) dv.locals[vargs] = v else: v = None if kargs: assert isinstance(kargs, str), kargs k = Local(kargs) dv.locals[kargs] = k else: k = None stack = PythonStack() root = dv.process(root, stack) root.name = fname selfparam = root.codeparameters.selfparam defaults = root.codeparameters.defaults returnparams = root.codeparameters.returnparams root.codeparameters = CodeParameters(selfparam, param, argnames, defaults, v, k, returnparams) origin = codeOrigin(code) root.rewriteAnnotation(origin=origin) return root
def process(self, code, instructions): self.code = code self.instIn = collections.defaultdict(list) self.instOut = collections.defaultdict(list) self.blocks = {} self.merges = {} self.regionExit = {} origin = codeOrigin(self.code) func = CodeBlock(None, origin) self.queue = [(0, func)] while self.queue: i, region = self.queue.pop() inst = instructions[i] if not self.instOut[i]: self.linkInstruction(i, inst, region) self.eliminateNullBlocks() # Create merges for i, o in self.instIn.iteritems(): if not i in self.rename and len(o) > 1: next = self.reachBlock(i) merge = Merge(next.region) merge.setNext(next) self.merges[i] = merge # Connect the blocks func.setHead(self.blocks[0]) for i, block in self.blocks.iteritems(): if block: self.linkBlock(i, block) # Fuse adjacent linear blocks self.fuseLinear(func) return func
def setOpOrigin(self, op): if not isinstance(op, (Local, Existing)): op.rewriteAnnotation(origin=(codeOrigin(self.code, self.lineno),)) assert op.annotation.origin
def linkInstruction(self, i, inst, region): origin = (codeOrigin(self.code, inst.line), ) op = inst.opcode if op == opmap['JUMP_IF_FALSE']: block = Switch(region, origin) self.makeLink(i, i + 1, region) self.makeLink(i, inst.arg, region) elif op == opmap['JUMP_IF_TRUE']: block = Switch(region, origin) self.makeLink(i, inst.arg, region) self.makeLink(i, i + 1, region) elif op == opmap['RETURN_VALUE']: block = Return(region, origin) elif op == opmap['BREAK_LOOP']: block = Break(region, origin) elif op == opmap['JUMP_FORWARD'] or op == opmap['JUMP_ABSOLUTE']: block = None # Eliminate this block. self.makeLink(i, inst.arg, region) elif op == opmap['FOR_ITER']: block = ForIter(region, origin) self.makeLink(i, i + 1, region) self.makeLink(i, inst.arg, region) elif op == opmap['SETUP_LOOP']: block = LoopRegion(region, origin) self.makeLink(i, i + 1, block) self.makeLink(i, inst.arg, region) #region = block elif op == opmap['SETUP_FINALLY']: block = FinallyRegion(region, origin) self.makeLink(i, i + 1, block) self.makeLink(i, inst.arg, region) #region = block elif op == opmap['SETUP_EXCEPT']: block = ExceptRegion(region, origin) self.makeLink(i, i + 1, block) self.makeLink(i, inst.arg, region) #region = block elif op == opmap['RAISE_VARARGS']: block = Raise(region, origin, inst.arg) elif op == opmap['POP_BLOCK']: assert not inst.isFlowControl() #block = None block = Linear(region, origin) block.instructions.append(inst) self.makeLink(i, i + 1, region.region) assert not region in self.regionExit self.regionExit[region] = (i, i + 1) elif op == opmap['END_FINALLY']: block = EndFinally(region, origin) self.makeLink(i, i + 1, region) else: assert not inst.isFlowControl() block = Linear(region, origin) block.instructions.append(inst) self.makeLink(i, i + 1, region) self.blocks[i] = block
def linkInstruction(self, i, inst, region): origin = (codeOrigin(self.code, inst.line),) op = inst.opcode if op == opmap["JUMP_IF_FALSE"]: block = Switch(region, origin) self.makeLink(i, i + 1, region) self.makeLink(i, inst.arg, region) elif op == opmap["JUMP_IF_TRUE"]: block = Switch(region, origin) self.makeLink(i, inst.arg, region) self.makeLink(i, i + 1, region) elif op == opmap["RETURN_VALUE"]: block = Return(region, origin) elif op == opmap["BREAK_LOOP"]: block = Break(region, origin) elif op == opmap["JUMP_FORWARD"] or op == opmap["JUMP_ABSOLUTE"]: block = None # Eliminate this block. self.makeLink(i, inst.arg, region) elif op == opmap["FOR_ITER"]: block = ForIter(region, origin) self.makeLink(i, i + 1, region) self.makeLink(i, inst.arg, region) elif op == opmap["SETUP_LOOP"]: block = LoopRegion(region, origin) self.makeLink(i, i + 1, block) self.makeLink(i, inst.arg, region) # region = block elif op == opmap["SETUP_FINALLY"]: block = FinallyRegion(region, origin) self.makeLink(i, i + 1, block) self.makeLink(i, inst.arg, region) # region = block elif op == opmap["SETUP_EXCEPT"]: block = ExceptRegion(region, origin) self.makeLink(i, i + 1, block) self.makeLink(i, inst.arg, region) # region = block elif op == opmap["RAISE_VARARGS"]: block = Raise(region, origin, inst.arg) elif op == opmap["POP_BLOCK"]: assert not inst.isFlowControl() # block = None block = Linear(region, origin) block.instructions.append(inst) self.makeLink(i, i + 1, region.region) assert not region in self.regionExit self.regionExit[region] = (i, i + 1) elif op == opmap["END_FINALLY"]: block = EndFinally(region, origin) self.makeLink(i, i + 1, region) else: assert not inst.isFlowControl() block = Linear(region, origin) block.instructions.append(inst) self.makeLink(i, i + 1, region) self.blocks[i] = block