BasicBlock *Program::takeOwnership(std::unique_ptr<BasicBlock> basicBlock) { assert(basicBlock != NULL); BasicBlock *result = basicBlock.get(); basicBlocks_.push_back(std::move(basicBlock)); if (result->address()) { assert(getBasicBlockStartingAt(*result->address()) == NULL); start2basicBlock_[*result->address()] = result; } return result; }
/** * Scan the CFG for finding exit and builds virtual edges with entry and exit. * For memory-place and time purposes, this method is only called when the CFG * is used (call to an accessors method). */ void CFG::scan(void) { // Prepare data typedef HashTable<BasicBlock *, BasicBlock *> map_t; map_t map; VectorQueue<BasicBlock *> todo; todo.put(ent); // Find all BB _bbs.add(&_entry); while(todo) { BasicBlock *bb = todo.get(); ASSERT(bb); // second case : calling jump to a function if(map.exists(bb) || (bb != ent && ENTRY(bb))) continue; // build the virtual BB BasicBlock *vbb = new VirtualBasicBlock(bb); _bbs.add(vbb); map.put(bb, vbb); ASSERTP(map.exists(bb), "not for " << bb->address()); // resolve targets for(BasicBlock::OutIterator edge(bb); edge; edge++) { ASSERT(edge->target()); if(edge->kind() != Edge::CALL) todo.put(edge->target()); } } // Relink the BB BasicBlock *vent = map.get(ent, 0); ASSERT(vent); new Edge(&_entry, vent, Edge::VIRTUAL); for(bbs_t::Iterator vbb(_bbs); vbb; vbb++) { if(vbb->isEnd()) continue; BasicBlock *bb = ((VirtualBasicBlock *)*vbb)->bb(); if(bb->isReturn()) new Edge(vbb, &_exit, Edge::VIRTUAL); for(BasicBlock::OutIterator edge(bb); edge; edge++) { // A call if(edge->kind() == Edge::CALL) { Edge *vedge = new Edge(vbb, edge->target(), Edge::CALL); vedge->toCall(); } // Pending edge else if(!edge->target()) { new Edge(vbb, 0, edge->kind()); } // Possibly a not explicit call else { ASSERT(edge->target()); BasicBlock *vtarget = map.get(edge->target(), 0); if(vtarget) new Edge(vbb, vtarget, edge->kind()); else { // calling jump to a function Edge *nedge = new Edge(vbb, edge->target(), Edge::CALL); vbb->flags |= BasicBlock::FLAG_Call; new Edge(vbb, &_exit, Edge::VIRTUAL); } } } } _bbs.add(&_exit); // Number the BB for(int i = 0; i < _bbs.length(); i++) { INDEX(_bbs[i]) = i; _bbs[i]->_cfg = this; } flags |= FLAG_Scanned; }