def seed_return(self, typ): """Seeding of return value is optional. """ for blk in utils.dict_itervalues(self.blocks): inst = blk.terminator if isinstance(inst, ir.Return): self.typevars[inst.value.name].lock(typ)
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) else: assert not inst.is_jump, inst # 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.dict_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(): for s, e in self._loops: if s <= b < e: inloopblocks.add(b) self.backbone = backbone - inloopblocks
def _start_new_block(self, inst): self.loc = ir.Loc(filename=self.bytecode.filename, line=inst.lineno) oldblock = self.current_block self.insert_block(inst.offset) # Ensure the last block is terminated if oldblock is not None and not oldblock.is_terminated: jmp = ir.Jump(inst.offset, loc=self.loc) oldblock.append(jmp) # Get DFA block info self.dfainfo = self.dfa.infos[self.current_block_offset] self.assigner = Assigner() # Notify listeners for the new block for fn in utils.dict_itervalues(self._block_actions): fn(self.current_block_offset, self.current_block)
def _start_new_block(self, inst): self.loc = ir.Loc(filename=self.bytecode.filename, line=inst.lineno) oldblock = self.current_block self.insert_block(inst.offset) # Ensure the last block is terminated if oldblock is not None and not oldblock.is_terminated: jmp = ir.Jump(inst.offset, loc=self.loc) oldblock.append(jmp) # Get DFA block info self.dfainfo = self.dfa.infos[self.current_block_offset] # Insert PHI self._insert_phi() # Notify listeners for the new block for fn in utils.dict_itervalues(self._block_actions): fn(self.current_block_offset, self.current_block)
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) else: assert not inst.is_jump, inst # Close all blocks for cur, nxt in zip(self.blockseq, self.blockseq[1:]): blk = self.blocks[cur] if not blk.outgoing and not blk.terminating: blk.outgoing.add(nxt) # Fill incoming for b in utils.dict_itervalues(self.blocks): for out in b.outgoing: self.blocks[out].incoming.add(b.offset) # Find liveblocks self.dead_block_elimin() # Find dominators self.doms = find_dominators(self.liveblocks) for lastblk in reversed(self.blockseq): if lastblk in self.liveblocks: break else: raise AssertionError("No live block that exits!?") # Find backbone backbone = set(self.doms[lastblk]) # 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(): for s, e in self._loops: if s <= b < e: inloopblocks.add(b) self.backbone = backbone - inloopblocks
def get_return_type(self, typemap): rettypes = set() for blk in utils.dict_itervalues(self.blocks): term = blk.terminator if isinstance(term, ir.Return): rettypes.add(typemap[term.value.name]) if types.none in rettypes: # Special case None return rettypes = rettypes - set([types.none]) if rettypes: unified = self.context.unify_types(*rettypes) return types.Optional(unified) else: return types.none else: unified = self.context.unify_types(*rettypes) return unified
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) else: assert not inst.is_jump, inst # Close all blocks for cur, nxt in zip(self.blockseq, self.blockseq[1:]): blk = self.blocks[cur] if not blk.outgoing and not blk.terminating: blk.outgoing.add(nxt) # Fill incoming for b in utils.dict_itervalues(self.blocks): for out in b.outgoing: self.blocks[out].incoming.add(b.offset) # Find liveblocks self.dead_block_elimin() # Find dominators self.doms = find_dominators(self.liveblocks) for lastblk in reversed(self.blockseq): if lastblk in self.liveblocks: break else: raise AssertionError("No live block that exits!?") # Find backbone backbone = set(self.doms[lastblk]) # Filter out in loop blocks (Assuming no other cyclic control blocks) inloopblocks = set() for b in self.blocks.keys(): for s, e in self._loops: if s <= b < e: inloopblocks.add(b) self.backbone = backbone - inloopblocks
def run_block(self, blk): tempassign = {} removeset = set() for offset, inst in enumerate(blk.body): self.mark_asssignment(tempassign, offset, inst) for bag in utils.dict_itervalues(tempassign): if len(bag) == 2: off1, off2 = bag first = blk.body[off1] second = blk.body[off2] inst = ir.Assign(value=first.value, target=second.target, loc=first.loc) # Replacement the second instruction blk.body[off2] = inst # Remove the first removeset.add(off1) # Remove from the highest offset to the lowest to preserve order for off in reversed(sorted(removeset)): del blk.body[off]
def dump(self): for blk in utils.dict_itervalues(self.infos): blk.dump()
def __iter__(self): return utils.dict_itervalues(self.table)
def get_state_token(self): """The algorithm is monotonic. It can only grow the typesets. The sum of all lengths of type sets is a cheap and accurate description of our progress. """ return sum(len(tv) for tv in utils.dict_itervalues(self.typevars))
def build_constrain(self): for blk in utils.dict_itervalues(self.blocks): for inst in blk.body: self.constrain_statement(inst)
def cleanup(self): for var in utils.dict_itervalues(self.varmap): self.decref(self.builder.load(var))
def verify(self): for b in utils.dict_itervalues(self.blocks): b.verify()