/** * Create blocks for each entry point as well as ordinary control * flow boundaries. Calls are not treated as basic-block ends. */ void GraphBuilder::createBlocks() { PC bc = m_unit->entry(); m_graph->param_count = m_func->params().size(); m_graph->first_linear = createBlock(m_func->base()); // DV entry points m_graph->entries = new (m_arena) Block*[m_graph->param_count + 1]; int dv_index = 0; for (auto& param : m_func->params()) { m_graph->entries[dv_index++] = !param.hasDefaultValue() ? 0 : createBlock(param.funcletOff); } // main entry point assert(dv_index == m_graph->param_count); m_graph->entries[dv_index] = createBlock(m_func->base()); // ordinary basic block boundaries for (InstrRange i = funcInstrs(m_func); !i.empty(); ) { PC pc = i.popFront(); if ((isCF(pc) || isTF(pc)) && !i.empty()) createBlock(i.front()); if (isSwitch(peek_op(pc))) { foreachSwitchTarget(pc, [&](Offset o) { createBlock(pc + o); }); } else { Offset target = instrJumpTarget(bc, pc - bc); if (target != InvalidAbsoluteOffset) createBlock(target); } } }
void printInstr(const Unit* unit, PC pc) { std::cout << " " << std::setw(4) << (pc - unit->entry()) << ":" << (isCF(pc) ? "C":" ") << (isTF(pc) ? "T":" ") << (isFF(pc) ? "F":" ") << std::setw(3) << instrLen(pc) << " " << instrToString(pc, unit) << std::endl; }
void printInstr(const Unit* unit, PC pc) { Opcode* op = (Opcode*)pc; std::cout << " " << std::setw(4) << (pc - unit->entry()) << ":" << (isCF(pc) ? "C":" ") << (isTF(pc) ? "T":" ") << (isFF(pc) ? "F":" ") << std::setw(3) << instrLen(op) << " " << instrToString(op, unit) << std::endl; }
/** * Link ordinary blocks with ordinary edges and set their last instruction * and end offsets */ void GraphBuilder::linkBlocks() { PC bc = m_unit->entry(); Block* block = m_graph->first_linear; block->id = m_graph->block_count++; for (InstrRange i = funcInstrs(m_func); !i.empty(); ) { PC pc = i.popFront(); block->last = pc; if (isCF(pc)) { if (isSwitch(*reinterpret_cast<const Op*>(pc))) { int i = 0; foreachSwitchTarget((Op*)pc, [&](Offset& o) { succs(block)[i++] = at(pc + o); }); } else { Offset target = instrJumpTarget((Op*)bc, pc - bc); if (target != InvalidAbsoluteOffset) { assert(numSuccBlocks(block) > 0); succs(block)[numSuccBlocks(block) - 1] = at(target); } } } PC next_pc = !i.empty() ? i.front() : m_unit->at(m_func->past()); Block* next = at(next_pc); if (next) { block->next_linear = next; block->end = next_pc; if (!isTF(pc)) { assert(numSuccBlocks(block) > 0); succs(block)[0] = next; } block = next; block->id = m_graph->block_count++; } } block->end = m_unit->at(m_func->past()); }