Trace* TraceBuilder::genExitTrace(uint32_t bcOff, int32_t stackDeficit, uint32_t numOpnds, SSATmp* const* opnds, TraceExitType::ExitType exitType, uint32_t notTakenBcOff, std::function<void(IRFactory*, Trace*)> beforeExit) { Trace* exitTrace = makeExitTrace(bcOff); MarkerData marker; marker.bcOff = bcOff; marker.stackOff = m_spOffset + numOpnds - stackDeficit; marker.func = m_curFunc->getValFunc(); exitTrace->back()->push_back(m_irFactory.gen(Marker, marker)); if (beforeExit) { beforeExit(&m_irFactory, exitTrace); } SSATmp* sp = m_spValue; if (numOpnds != 0 || stackDeficit != 0) { SSATmp* srcs[numOpnds + 2]; srcs[0] = m_spValue; srcs[1] = cns(stackDeficit); std::copy(opnds, opnds + numOpnds, srcs + 2); SSATmp** decayedPtr = srcs; auto* spillInst = m_irFactory.gen( SpillStack, std::make_pair(numOpnds + 2, decayedPtr) ); sp = spillInst->getDst(); exitTrace->back()->push_back(spillInst); } SSATmp* pc = cns(int64_t(bcOff)); if (exitType == TraceExitType::NormalCc) { assert(notTakenBcOff != 0); SSATmp* notTakenPC = cns(notTakenBcOff); genFor(exitTrace, getExitOpcode(exitType), m_curFunc, pc, sp, m_fpValue, notTakenPC); } else { assert(notTakenBcOff == 0); genFor(exitTrace, getExitOpcode(exitType), m_curFunc, pc, sp, m_fpValue); } return exitTrace; }
void TraceBuilder::genTraceEnd(uint32_t nextPc, TraceExitType::ExitType exitType /* = Normal */) { gen(getExitOpcode(TraceExitType::Normal), m_curFunc, cns(nextPc), m_spValue, m_fpValue); }
IRInstruction* IRFactory::exitTrace(TraceExitType::ExitType exitType, SSATmp* func, SSATmp* pc, SSATmp* sp, SSATmp* fp) { SSATmp* args[2] = { sp, fp }; return new (m_arena) ExtendedInstruction(*this, getExitOpcode(exitType), Type::None, func, pc, (sizeof(args) / sizeof(SSATmp*)), args); }