Пример #1
0
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;
}
Пример #2
0
/**
 * 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;

}