PhysRegSaver::PhysRegSaver(Vout& v, RegSet regs) : m_v(v) , m_regs(regs) { auto gpr = m_regs & abi().gp(); auto xmm = m_regs & abi().simd(); auto const sp = rsp(); m_adjust = gpr.size() & 0x1 ? 8 : 0; if (!xmm.empty()) { v << lea{sp[-16 * xmm.size()], sp}; int offset = 0; xmm.forEach([&] (PhysReg r) { v << storeups{r, sp[offset]}; offset += 16; }); } gpr.forEach([&] (PhysReg r) { v << push{r}; }); if (m_adjust) { v << lea{sp[-m_adjust], sp}; } }
Vauto::~Vauto() { for (auto& b : unit().blocks) { if (!b.code.empty()) { // Found at least one nonempty block. Finish up. if (!main().closed()) main() << fallthru{}; // Prevent spurious printir traces. Trace::Bump bumper{Trace::printir, 10}; switch (arch()) { case Arch::X64: optimizeX64(unit(), abi(m_kind)); emitX64(unit(), m_text, nullptr); break; case Arch::ARM: finishARM(unit(), m_text, abi(m_kind), nullptr); break; } return; } } }
PhysRegSaver::~PhysRegSaver() { auto& v = m_v; auto const sp = rsp(); if (m_adjust) { v << lea{sp[m_adjust], sp}; } auto gpr = m_regs & abi().gp(); auto xmm = m_regs & abi().simd(); gpr.forEachR([&] (PhysReg r) { v << pop{r}; }); if (!xmm.empty()) { int offset = 0; xmm.forEach([&] (PhysReg r) { v << loadups{sp[offset], r}; offset += 16; }); v << lea{sp[offset], sp}; } }
bool GccToolChain::fromMap(const QVariantMap &data) { if (!ToolChain::fromMap(data)) return false; m_compilerCommand = Utils::FileName::fromString(data.value(QLatin1String(compilerCommandKeyC)).toString()); m_targetAbi = Abi(data.value(QLatin1String(targetAbiKeyC)).toString()); QStringList abiList = data.value(QLatin1String(supportedAbisKeyC)).toStringList(); m_supportedAbis.clear(); foreach (const QString &a, abiList) { ProjectExplorer::Abi abi(a); if (!abi.isValid()) continue; m_supportedAbis.append(abi); }
PhysReg r_svcreq_sf() { return abi().sf.choose(); }
int main(void) { printf("%s\n", abi()); return 0; }
PhysReg r_svcreq_sf() { return abi().sf.findFirst(); }
jit::vector<VMoveInfo> doVregMoves(Vunit& unit, MovePlan& moves) { constexpr auto N = 64; assertx(abi().all().size() <= N); jit::vector<VMoveInfo> howTo; CycleInfo cycles[N]; size_t num_cycles = 0; PhysReg::Map<int> outDegree; PhysReg::Map<int> index; for (auto reg : moves) { // Ignore moves from a register to itself if (reg == moves[reg]) moves[reg] = InvalidReg; index[reg] = -1; } // Iterate over the nodes filling in outDegree[] and cycles[] as we go int nextIndex = 0; for (auto reg : moves) { // skip registers we've visited already. if (index[reg] >= 0) continue; // Begin walking a path from reg. for (auto node = reg;;) { assertx(nextIndex < N); index[node] = nextIndex++; auto next = moves[node]; if (next != InvalidReg) { ++outDegree[next]; if (index[next] < 0) { // There is an edge from node to next, and next has not been // visited. Extend current path to include next, then loop. node = next; continue; } // next already visited; check if next is on current path. if (index[next] >= index[reg]) { // found a cycle. assert(num_cycles < N); cycles[num_cycles++] = { next, nextIndex - index[next] }; } } break; } } // Handle all moves that aren't part of a cycle. Only nodes with outdegree // zero are put into the queue, which is how nodes in a cycle get excluded. { PhysReg q[N]; int qBack = 0; auto enque = [&](PhysReg r) { assertx(qBack < N); q[qBack++] = r; }; for (auto node : outDegree) { if (outDegree[node] == 0) enque(node); } for (int i = 0; i < qBack; ++i) { auto node = q[i]; if (moves[node] == InvalidReg) continue; auto nextNode = moves[node]; howTo.push_back({VMoveInfo::Kind::Move, nextNode, node}); --outDegree[nextNode]; if (outDegree[nextNode] == 0) enque(nextNode); } } // Deal with any cycles we encountered for (size_t i = 0; i < num_cycles; ++i) { auto const& cycle = cycles[i]; // can't use xchg if one of the registers is SIMD bool hasSIMDReg = cycleHasSIMDReg(cycle, moves); if (cycle.length == 2 && !hasSIMDReg) { auto v = cycle.node; auto w = moves[v]; howTo.push_back({VMoveInfo::Kind::Xchg, w, v}); } else if (cycle.length == 3 && !hasSIMDReg) { auto v = cycle.node; auto w = moves[v]; howTo.push_back({VMoveInfo::Kind::Xchg, w, v}); auto x = moves[w]; howTo.push_back({VMoveInfo::Kind::Xchg, x, w}); } else { auto t = unit.makeReg(); auto v = cycle.node; howTo.push_back({VMoveInfo::Kind::Move, v, t}); auto w = v; auto x = moves[w]; while (x != v) { howTo.push_back({VMoveInfo::Kind::Move, x, w}); w = x; x = moves[w]; } howTo.push_back({VMoveInfo::Kind::Move, t, w}); } } return howTo; }
int PhysReg::getNumSIMD() { return abi().simd().size(); }
int PhysReg::getNumGP() { return abi().gp().size(); }