1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 19:12:56 +02:00

[Stackmaps] Refactor serialization code. No functional change intended.

llvm-svn: 207804
This commit is contained in:
Juergen Ributzka 2014-05-01 22:21:27 +00:00
parent 08694158e1
commit 60208fb4c5
2 changed files with 157 additions and 123 deletions

View File

@ -21,6 +21,7 @@ namespace llvm {
class AsmPrinter; class AsmPrinter;
class MCExpr; class MCExpr;
class MCStreamer;
/// \brief MI-level patchpoint operands. /// \brief MI-level patchpoint operands.
/// ///
@ -131,6 +132,8 @@ public:
void serializeToStackMapSection(); void serializeToStackMapSection();
private: private:
const char *WSMP = "Stack Maps: ";
typedef SmallVector<Location, 8> LocationVec; typedef SmallVector<Location, 8> LocationVec;
typedef SmallVector<LiveOutReg, 8> LiveOutVec; typedef SmallVector<LiveOutReg, 8> LiveOutVec;
typedef MapVector<int64_t, int64_t> ConstantPool; typedef MapVector<int64_t, int64_t> ConstantPool;
@ -177,6 +180,18 @@ private:
MachineInstr::const_mop_iterator MOI, MachineInstr::const_mop_iterator MOI,
MachineInstr::const_mop_iterator MOE, MachineInstr::const_mop_iterator MOE,
bool recordResult = false); bool recordResult = false);
/// \brief Emit the stackmap header.
void emitStackmapHeader(MCStreamer &OS);
/// \brief Emit the function frame record for each function.
void emitFunctionFrameRecords(MCStreamer &OS);
/// \brief Emit the constant pool.
void emitConstantPoolEntries(MCStreamer &OS);
/// \brief Emit the callsite info for each stackmap/patchpoint intrinsic call.
void emitCallsiteEntries(MCStreamer &OS, const TargetRegisterInfo *TRI);
}; };
} }

View File

@ -260,7 +260,7 @@ void StackMaps::recordPatchPoint(const MachineInstr &MI) {
#endif #endif
} }
/// serializeToStackMapSection conceptually populates the following fields: /// Emit the stackmap header.
/// ///
/// Header { /// Header {
/// uint8 : Stack Map Version (currently 1) /// uint8 : Stack Map Version (currently 1)
@ -270,11 +270,54 @@ void StackMaps::recordPatchPoint(const MachineInstr &MI) {
/// uint32 : NumFunctions /// uint32 : NumFunctions
/// uint32 : NumConstants /// uint32 : NumConstants
/// uint32 : NumRecords /// uint32 : NumRecords
void StackMaps::emitStackmapHeader(MCStreamer &OS) {
// Header.
OS.EmitIntValue(1, 1); // Version.
OS.EmitIntValue(0, 1); // Reserved.
OS.EmitIntValue(0, 2); // Reserved.
// Num functions.
DEBUG(dbgs() << WSMP << "#functions = " << FnStackSize.size() << '\n');
OS.EmitIntValue(FnStackSize.size(), 4);
// Num constants.
DEBUG(dbgs() << WSMP << "#constants = " << ConstPool.size() << '\n');
OS.EmitIntValue(ConstPool.size(), 4);
// Num callsites.
DEBUG(dbgs() << WSMP << "#callsites = " << CSInfos.size() << '\n');
OS.EmitIntValue(CSInfos.size(), 4);
}
/// Emit the function frame record for each function.
///
/// StkSizeRecord[NumFunctions] { /// StkSizeRecord[NumFunctions] {
/// uint64 : Function Address /// uint64 : Function Address
/// uint64 : Stack Size /// uint64 : Stack Size
/// } /// }
void StackMaps::emitFunctionFrameRecords(MCStreamer &OS) {
// Function Frame records.
DEBUG(dbgs() << WSMP << "functions:\n");
for (auto const &FR : FnStackSize) {
DEBUG(dbgs() << WSMP << "function addr: " << FR.first
<< " frame size: " << FR.second);
OS.EmitSymbolValue(FR.first, 8);
OS.EmitIntValue(FR.second, 8);
}
}
/// Emit the constant pool.
///
/// int64 : Constants[NumConstants] /// int64 : Constants[NumConstants]
void StackMaps::emitConstantPoolEntries(MCStreamer &OS) {
// Constant pool entries.
DEBUG(dbgs() << WSMP << "constants:\n");
for (auto ConstEntry : ConstPool) {
DEBUG(dbgs() << WSMP << ConstEntry.second << '\n');
OS.EmitIntValue(ConstEntry.second, 8);
}
}
/// Emit the callsite info for each callsite.
///
/// StkMapRecord[NumRecords] { /// StkMapRecord[NumRecords] {
/// uint64 : PatchPoint ID /// uint64 : PatchPoint ID
/// uint32 : Instruction Offset /// uint32 : Instruction Offset
@ -302,95 +345,43 @@ void StackMaps::recordPatchPoint(const MachineInstr &MI) {
/// 0x3, Indirect, [Reg + Offset] (spilled value) /// 0x3, Indirect, [Reg + Offset] (spilled value)
/// 0x4, Constant, Offset (small constant) /// 0x4, Constant, Offset (small constant)
/// 0x5, ConstIndex, Constants[Offset] (large constant) /// 0x5, ConstIndex, Constants[Offset] (large constant)
/// void StackMaps::emitCallsiteEntries(MCStreamer &OS,
void StackMaps::serializeToStackMapSection() { const TargetRegisterInfo *TRI) {
// Bail out if there's no stack map data.
if (CSInfos.empty())
return;
MCContext &OutContext = AP.OutStreamer.getContext();
const TargetRegisterInfo *TRI = AP.TM.getRegisterInfo();
// Create the section.
const MCSection *StackMapSection =
OutContext.getObjectFileInfo()->getStackMapSection();
AP.OutStreamer.SwitchSection(StackMapSection);
// Emit a dummy symbol to force section inclusion.
AP.OutStreamer.EmitLabel(
OutContext.GetOrCreateSymbol(Twine("__LLVM_StackMaps")));
// Serialize data.
const char *WSMP = "Stack Maps: ";
(void)WSMP;
DEBUG(dbgs() << "********** Stack Map Output **********\n");
// Header.
AP.OutStreamer.EmitIntValue(1, 1); // Version.
AP.OutStreamer.EmitIntValue(0, 1); // Reserved.
AP.OutStreamer.EmitIntValue(0, 2); // Reserved.
// Num functions.
DEBUG(dbgs() << WSMP << "#functions = " << FnStackSize.size() << '\n');
AP.OutStreamer.EmitIntValue(FnStackSize.size(), 4);
// Num constants.
DEBUG(dbgs() << WSMP << "#constants = " << ConstPool.size()
<< '\n');
AP.OutStreamer.EmitIntValue(ConstPool.size(), 4);
// Num callsites.
DEBUG(dbgs() << WSMP << "#callsites = " << CSInfos.size() << '\n');
AP.OutStreamer.EmitIntValue(CSInfos.size(), 4);
// Function stack size entries.
for (FnStackSizeMap::iterator I = FnStackSize.begin(), E = FnStackSize.end();
I != E; ++I) {
AP.OutStreamer.EmitSymbolValue(I->first, 8);
AP.OutStreamer.EmitIntValue(I->second, 8);
}
// Constant pool entries.
for (auto Constant : ConstPool)
AP.OutStreamer.EmitIntValue(Constant.second, 8);
// Callsite entries. // Callsite entries.
for (CallsiteInfoList::const_iterator CSII = CSInfos.begin(), DEBUG(dbgs() << WSMP << "callsites:\n");
CSIE = CSInfos.end(); CSII != CSIE; ++CSII) { for (const auto &CSI : CSInfos) {
uint64_t CallsiteID = CSII->ID; const LocationVec &CSLocs = CSI.Locations;
const LocationVec &CSLocs = CSII->Locations; const LiveOutVec &LiveOuts = CSI.LiveOuts;
const LiveOutVec &LiveOuts = CSII->LiveOuts;
DEBUG(dbgs() << WSMP << "callsite " << CallsiteID << "\n"); DEBUG(dbgs() << WSMP << "callsite " << CSI.ID << "\n");
// Verify stack map entry. It's better to communicate a problem to the // Verify stack map entry. It's better to communicate a problem to the
// runtime than crash in case of in-process compilation. Currently, we do // runtime than crash in case of in-process compilation. Currently, we do
// simple overflow checks, but we may eventually communicate other // simple overflow checks, but we may eventually communicate other
// compilation errors this way. // compilation errors this way.
if (CSLocs.size() > UINT16_MAX || LiveOuts.size() > UINT16_MAX) { if (CSLocs.size() > UINT16_MAX || LiveOuts.size() > UINT16_MAX) {
AP.OutStreamer.EmitIntValue(UINT64_MAX, 8); // Invalid ID. OS.EmitIntValue(UINT64_MAX, 8); // Invalid ID.
AP.OutStreamer.EmitValue(CSII->CSOffsetExpr, 4); OS.EmitValue(CSI.CSOffsetExpr, 4);
AP.OutStreamer.EmitIntValue(0, 2); // Reserved. OS.EmitIntValue(0, 2); // Reserved.
AP.OutStreamer.EmitIntValue(0, 2); // 0 locations. OS.EmitIntValue(0, 2); // 0 locations.
AP.OutStreamer.EmitIntValue(0, 2); // padding. OS.EmitIntValue(0, 2); // padding.
AP.OutStreamer.EmitIntValue(0, 2); // 0 live-out registers. OS.EmitIntValue(0, 2); // 0 live-out registers.
AP.OutStreamer.EmitIntValue(0, 4); // padding. OS.EmitIntValue(0, 4); // padding.
continue; continue;
} }
AP.OutStreamer.EmitIntValue(CallsiteID, 8); OS.EmitIntValue(CSI.ID, 8);
AP.OutStreamer.EmitValue(CSII->CSOffsetExpr, 4); OS.EmitValue(CSI.CSOffsetExpr, 4);
// Reserved for flags. // Reserved for flags.
AP.OutStreamer.EmitIntValue(0, 2); OS.EmitIntValue(0, 2);
DEBUG(dbgs() << WSMP << " has " << CSLocs.size() << " locations\n"); DEBUG(dbgs() << WSMP << " has " << CSLocs.size() << " locations\n");
AP.OutStreamer.EmitIntValue(CSLocs.size(), 2); OS.EmitIntValue(CSLocs.size(), 2);
unsigned operIdx = 0; unsigned OperIdx = 0;
for (LocationVec::const_iterator LocI = CSLocs.begin(), LocE = CSLocs.end(); for (const auto &Loc : CSLocs) {
LocI != LocE; ++LocI, ++operIdx) {
const Location &Loc = *LocI;
unsigned RegNo = 0; unsigned RegNo = 0;
int Offset = Loc.Offset; int Offset = Loc.Offset;
if(Loc.Reg) { if(Loc.Reg) {
@ -411,68 +402,96 @@ void StackMaps::serializeToStackMapSection() {
"Missing location register"); "Missing location register");
} }
DEBUG( DEBUG(dbgs() << WSMP << " Loc " << OperIdx << ": ";
dbgs() << WSMP << " Loc " << operIdx << ": "; switch (Loc.LocType) {
switch (Loc.LocType) { case Location::Unprocessed:
case Location::Unprocessed: dbgs() << "<Unprocessed operand>";
dbgs() << "<Unprocessed operand>"; break;
break; case Location::Register:
case Location::Register: dbgs() << "Register " << TRI->getName(Loc.Reg);
dbgs() << "Register " << TRI->getName(Loc.Reg); break;
break; case Location::Direct:
case Location::Direct: dbgs() << "Direct " << TRI->getName(Loc.Reg);
dbgs() << "Direct " << TRI->getName(Loc.Reg); if (Loc.Offset)
if (Loc.Offset) dbgs() << " + " << Loc.Offset;
dbgs() << " + " << Loc.Offset; break;
break; case Location::Indirect:
case Location::Indirect: dbgs() << "Indirect " << TRI->getName(Loc.Reg)
dbgs() << "Indirect " << TRI->getName(Loc.Reg) << " + " << Loc.Offset;
<< " + " << Loc.Offset; break;
break; case Location::Constant:
case Location::Constant: dbgs() << "Constant " << Loc.Offset;
dbgs() << "Constant " << Loc.Offset; break;
break; case Location::ConstantIndex:
case Location::ConstantIndex: dbgs() << "Constant Index " << Loc.Offset;
dbgs() << "Constant Index " << Loc.Offset; break;
break; }
} dbgs() << " [encoding: .byte " << Loc.LocType
dbgs() << " [encoding: .byte " << Loc.LocType << ", .byte " << Loc.Size
<< ", .byte " << Loc.Size << ", .short " << RegNo
<< ", .short " << RegNo << ", .int " << Offset << "]\n";
<< ", .int " << Offset << "]\n"; );
);
AP.OutStreamer.EmitIntValue(Loc.LocType, 1); OS.EmitIntValue(Loc.LocType, 1);
AP.OutStreamer.EmitIntValue(Loc.Size, 1); OS.EmitIntValue(Loc.Size, 1);
AP.OutStreamer.EmitIntValue(RegNo, 2); OS.EmitIntValue(RegNo, 2);
AP.OutStreamer.EmitIntValue(Offset, 4); OS.EmitIntValue(Offset, 4);
OperIdx++;
} }
DEBUG(dbgs() << WSMP << " has " << LiveOuts.size() DEBUG(dbgs() << WSMP << " has " << LiveOuts.size()
<< " live-out registers\n"); << " live-out registers\n");
// Num live-out registers and padding to align to 4 byte. // Num live-out registers and padding to align to 4 byte.
AP.OutStreamer.EmitIntValue(0, 2); OS.EmitIntValue(0, 2);
AP.OutStreamer.EmitIntValue(LiveOuts.size(), 2); OS.EmitIntValue(LiveOuts.size(), 2);
operIdx = 0; OperIdx = 0;
for (LiveOutVec::const_iterator LI = LiveOuts.begin(), LE = LiveOuts.end(); for (const auto &LO : LiveOuts) {
LI != LE; ++LI, ++operIdx) { DEBUG(dbgs() << WSMP << " LO " << OperIdx << ": "
DEBUG(dbgs() << WSMP << " LO " << operIdx << ": " << TRI->getName(LO.Reg)
<< TRI->getName(LI->Reg) << " [encoding: .short " << LO.RegNo
<< " [encoding: .short " << LI->RegNo << ", .byte 0, .byte " << LO.Size << "]\n");
<< ", .byte 0, .byte " << LI->Size << "]\n"); OS.EmitIntValue(LO.RegNo, 2);
OS.EmitIntValue(0, 1);
AP.OutStreamer.EmitIntValue(LI->RegNo, 2); OS.EmitIntValue(LO.Size, 1);
AP.OutStreamer.EmitIntValue(0, 1);
AP.OutStreamer.EmitIntValue(LI->Size, 1);
} }
// Emit alignment to 8 byte. // Emit alignment to 8 byte.
AP.OutStreamer.EmitValueToAlignment(8); OS.EmitValueToAlignment(8);
} }
}
AP.OutStreamer.AddBlankLine(); /// Serialize the stackmap data.
void StackMaps::serializeToStackMapSection() {
// Bail out if there's no stack map data.
assert((!CSInfos.empty() || (CSInfos.empty() && ConstPool.empty())) &&
"Expected empty constant pool too!");
assert((!CSInfos.empty() || (CSInfos.empty() && FnStackSize.empty())) &&
"Expected empty function record too!");
if (CSInfos.empty())
return;
MCContext &OutContext = AP.OutStreamer.getContext();
MCStreamer &OS = AP.OutStreamer;
const TargetRegisterInfo *TRI = AP.TM.getRegisterInfo();
// Create the section.
const MCSection *StackMapSection =
OutContext.getObjectFileInfo()->getStackMapSection();
OS.SwitchSection(StackMapSection);
// Emit a dummy symbol to force section inclusion.
OS.EmitLabel(OutContext.GetOrCreateSymbol(Twine("__LLVM_StackMaps")));
// Serialize data.
DEBUG(dbgs() << "********** Stack Map Output **********\n");
emitStackmapHeader(OS);
emitFunctionFrameRecords(OS);
emitConstantPoolEntries(OS);
emitCallsiteEntries(OS, TRI);
OS.AddBlankLine();
// Clean up.
CSInfos.clear(); CSInfos.clear();
ConstPool.clear(); ConstPool.clear();
} }