[Stackmap] Refactor operand parsing.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197329 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Juergen Ributzka 2013-12-14 23:06:19 +00:00
parent 729e476834
commit bfee019790
2 changed files with 76 additions and 92 deletions

View File

@ -171,9 +171,10 @@ private:
CallsiteInfoList CSInfos; CallsiteInfoList CSInfos;
ConstantPool ConstPool; ConstantPool ConstPool;
std::pair<Location, MachineInstr::const_mop_iterator> MachineInstr::const_mop_iterator
parseOperand(MachineInstr::const_mop_iterator MOI, parseOperand(MachineInstr::const_mop_iterator MOI,
MachineInstr::const_mop_iterator MOE) const; MachineInstr::const_mop_iterator MOE,
LocationVec &Locs, LiveOutVec &LiveOuts) const;
/// \brief Create a live-out register record for the given register @p Reg. /// \brief Create a live-out register record for the given register @p Reg.
LiveOutReg createLiveOutReg(unsigned Reg, const MCRegisterInfo &MCRI, LiveOutReg createLiveOutReg(unsigned Reg, const MCRegisterInfo &MCRI,

View File

@ -29,14 +29,13 @@
using namespace llvm; using namespace llvm;
PatchPointOpers::PatchPointOpers(const MachineInstr *MI): PatchPointOpers::PatchPointOpers(const MachineInstr *MI)
MI(MI), : MI(MI),
HasDef(MI->getOperand(0).isReg() && MI->getOperand(0).isDef() && HasDef(MI->getOperand(0).isReg() && MI->getOperand(0).isDef() &&
!MI->getOperand(0).isImplicit()), !MI->getOperand(0).isImplicit()),
IsAnyReg(MI->getOperand(getMetaIdx(CCPos)).getImm() == CallingConv::AnyReg) { IsAnyReg(MI->getOperand(getMetaIdx(CCPos)).getImm() == CallingConv::AnyReg)
{
#ifndef NDEBUG #ifndef NDEBUG
{
unsigned CheckStartIdx = 0, e = MI->getNumOperands(); unsigned CheckStartIdx = 0, e = MI->getNumOperands();
while (CheckStartIdx < e && MI->getOperand(CheckStartIdx).isReg() && while (CheckStartIdx < e && MI->getOperand(CheckStartIdx).isReg() &&
MI->getOperand(CheckStartIdx).isDef() && MI->getOperand(CheckStartIdx).isDef() &&
@ -45,7 +44,6 @@ PatchPointOpers::PatchPointOpers(const MachineInstr *MI):
assert(getMetaIdx() == CheckStartIdx && assert(getMetaIdx() == CheckStartIdx &&
"Unexpected additonal definition in Patchpoint intrinsic."); "Unexpected additonal definition in Patchpoint intrinsic.");
}
#endif #endif
} }
@ -66,61 +64,64 @@ unsigned PatchPointOpers::getNextScratchIdx(unsigned StartIdx) const {
return ScratchIdx; return ScratchIdx;
} }
std::pair<StackMaps::Location, MachineInstr::const_mop_iterator> MachineInstr::const_mop_iterator
StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI, StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,
MachineInstr::const_mop_iterator MOE) const { MachineInstr::const_mop_iterator MOE,
const MachineOperand &MOP = *MOI; LocationVec &Locs, LiveOutVec &LiveOuts) const {
assert((!MOP.isReg() || !MOP.isImplicit()) && if (MOI->isImm()) {
"Implicit operands should not be processed."); switch (MOI->getImm()) {
default: llvm_unreachable("Unrecognized operand type.");
if (MOP.isImm()) { case StackMaps::DirectMemRefOp: {
// Verify anyregcc unsigned Size = AP.TM.getDataLayout()->getPointerSizeInBits();
// [<def>], <id>, <numBytes>, <target>, <numArgs>, <cc>, ... assert((Size % 8) == 0 && "Need pointer size in bytes.");
Size /= 8;
switch (MOP.getImm()) { unsigned Reg = (++MOI)->getReg();
default: llvm_unreachable("Unrecognized operand type."); int64_t Imm = (++MOI)->getImm();
case StackMaps::DirectMemRefOp: { Locs.push_back(Location(StackMaps::Location::Direct, Size, Reg, Imm));
unsigned Size = AP.TM.getDataLayout()->getPointerSizeInBits(); break;
assert((Size % 8) == 0 && "Need pointer size in bytes.");
Size /= 8;
unsigned Reg = (++MOI)->getReg();
int64_t Imm = (++MOI)->getImm();
return std::make_pair(
Location(StackMaps::Location::Direct, Size, Reg, Imm), ++MOI);
}
case StackMaps::IndirectMemRefOp: {
int64_t Size = (++MOI)->getImm();
assert(Size > 0 && "Need a valid size for indirect memory locations.");
unsigned Reg = (++MOI)->getReg();
int64_t Imm = (++MOI)->getImm();
return std::make_pair(
Location(StackMaps::Location::Indirect, Size, Reg, Imm), ++MOI);
}
case StackMaps::ConstantOp: {
++MOI;
assert(MOI->isImm() && "Expected constant operand.");
int64_t Imm = MOI->getImm();
return std::make_pair(
Location(Location::Constant, sizeof(int64_t), 0, Imm), ++MOI);
}
} }
case StackMaps::IndirectMemRefOp: {
int64_t Size = (++MOI)->getImm();
assert(Size > 0 && "Need a valid size for indirect memory locations.");
unsigned Reg = (++MOI)->getReg();
int64_t Imm = (++MOI)->getImm();
Locs.push_back(Location(StackMaps::Location::Indirect, Size, Reg, Imm));
break;
}
case StackMaps::ConstantOp: {
++MOI;
assert(MOI->isImm() && "Expected constant operand.");
int64_t Imm = MOI->getImm();
Locs.push_back(Location(Location::Constant, sizeof(int64_t), 0, Imm));
break;
}
}
return ++MOI;
} }
if (MOP.isRegMask() || MOP.isRegLiveOut()) // The physical register number will ultimately be encoded as a DWARF regno.
return std::make_pair(Location(), ++MOI); // The stack map also records the size of a spill slot that can hold the
// register content. (The runtime can track the actual size of the data type
// if it needs to.)
if (MOI->isReg()) {
// Skip implicit registers (this includes our scratch registers)
if (MOI->isImplicit())
return ++MOI;
// Otherwise this is a reg operand. The physical register number will assert(TargetRegisterInfo::isPhysicalRegister(MOI->getReg()) &&
// ultimately be encoded as a DWARF regno. The stack map also records the size "Virtreg operands should have been rewritten before now.");
// of a spill slot that can hold the register content. (The runtime can const TargetRegisterClass *RC =
// track the actual size of the data type if it needs to.) AP.TM.getRegisterInfo()->getMinimalPhysRegClass(MOI->getReg());
assert(MOP.isReg() && "Expected register operand here."); assert(!MOI->getSubReg() && "Physical subreg still around.");
assert(TargetRegisterInfo::isPhysicalRegister(MOP.getReg()) && Locs.push_back(
"Virtreg operands should have been rewritten before now."); Location(Location::Register, RC->getSize(), MOI->getReg(), 0));
const TargetRegisterClass *RC = return ++MOI;
AP.TM.getRegisterInfo()->getMinimalPhysRegClass(MOP.getReg()); }
assert(!MOP.getSubReg() && "Physical subreg still around.");
return std::make_pair( if (MOI->isRegLiveOut())
Location(Location::Register, RC->getSize(), MOP.getReg(), 0), ++MOI); LiveOuts = parseRegisterLiveOutMask(MOI->getRegLiveOut());
return ++MOI;
} }
/// Go up the super-register chain until we hit a valid dwarf register number. /// Go up the super-register chain until we hit a valid dwarf register number.
@ -195,28 +196,23 @@ void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint64_t ID,
LiveOutVec LiveOuts; LiveOutVec LiveOuts;
if (recordResult) { if (recordResult) {
std::pair<Location, MachineInstr::const_mop_iterator> ParseResult = assert(PatchPointOpers(&MI).hasDef() && "Stackmap has no return value.");
parseOperand(MI.operands_begin(), llvm::next(MI.operands_begin())); parseOperand(MI.operands_begin(), llvm::next(MI.operands_begin()),
Locations, LiveOuts);
Location &Loc = ParseResult.first;
assert(Loc.LocType == Location::Register &&
"Stackmap return location must be a register.");
Locations.push_back(Loc);
} }
// Parse operands.
while (MOI != MOE) { while (MOI != MOE) {
Location Loc; MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
tie(Loc, MOI) = parseOperand(MOI, MOE); }
// Move large constants into the constant pool. // Move large constants into the constant pool.
if (Loc.LocType == Location::Constant && (Loc.Offset & ~0xFFFFFFFFULL)) { for (LocationVec::iterator I = Locations.begin(), E = Locations.end();
Loc.LocType = Location::ConstantIndex; I != E; ++I) {
Loc.Offset = ConstPool.getConstantIndex(Loc.Offset); if (I->LocType == Location::Constant && (I->Offset & ~0xFFFFFFFFULL)) {
I->LocType = Location::ConstantIndex;
I->Offset = ConstPool.getConstantIndex(I->Offset);
} }
// Skip the register mask and register live-out mask
if (Loc.LocType != Location::Unprocessed)
Locations.push_back(Loc);
} }
const MCExpr *CSOffsetExpr = MCBinaryExpr::CreateSub( const MCExpr *CSOffsetExpr = MCBinaryExpr::CreateSub(
@ -224,28 +220,15 @@ void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint64_t ID,
MCSymbolRefExpr::Create(AP.CurrentFnSym, OutContext), MCSymbolRefExpr::Create(AP.CurrentFnSym, OutContext),
OutContext); OutContext);
if (MOI->isRegLiveOut())
LiveOuts = parseRegisterLiveOutMask(MOI->getRegLiveOut());
CSInfos.push_back(CallsiteInfo(CSOffsetExpr, ID, Locations, LiveOuts)); CSInfos.push_back(CallsiteInfo(CSOffsetExpr, ID, Locations, LiveOuts));
} }
static MachineInstr::const_mop_iterator
getStackMapEndMOP(MachineInstr::const_mop_iterator MOI,
MachineInstr::const_mop_iterator MOE) {
for (; MOI != MOE; ++MOI)
if (MOI->isRegLiveOut() || (MOI->isReg() && MOI->isImplicit()))
break;
return MOI;
}
void StackMaps::recordStackMap(const MachineInstr &MI) { void StackMaps::recordStackMap(const MachineInstr &MI) {
assert(MI.getOpcode() == TargetOpcode::STACKMAP && "expected stackmap"); assert(MI.getOpcode() == TargetOpcode::STACKMAP && "expected stackmap");
int64_t ID = MI.getOperand(0).getImm(); int64_t ID = MI.getOperand(0).getImm();
recordStackMapOpers(MI, ID, llvm::next(MI.operands_begin(), 2), recordStackMapOpers(MI, ID, llvm::next(MI.operands_begin(), 2),
getStackMapEndMOP(MI.operands_begin(), MI.operands_end());
MI.operands_end()));
} }
void StackMaps::recordPatchPoint(const MachineInstr &MI) { void StackMaps::recordPatchPoint(const MachineInstr &MI) {
@ -256,7 +239,7 @@ void StackMaps::recordPatchPoint(const MachineInstr &MI) {
MachineInstr::const_mop_iterator MOI = MachineInstr::const_mop_iterator MOI =
llvm::next(MI.operands_begin(), opers.getStackMapStartIdx()); llvm::next(MI.operands_begin(), opers.getStackMapStartIdx());
recordStackMapOpers(MI, ID, MOI, getStackMapEndMOP(MOI, MI.operands_end()), recordStackMapOpers(MI, ID, MOI, MI.operands_end(),
opers.isAnyReg() && opers.hasDef()); opers.isAnyReg() && opers.hasDef());
#ifndef NDEBUG #ifndef NDEBUG