summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR/AsmWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/IR/AsmWriter.cpp')
-rw-r--r--llvm/lib/IR/AsmWriter.cpp489
1 files changed, 486 insertions, 3 deletions
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 359ca1d5054..7659a6b580d 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -59,6 +59,7 @@
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSlotTracker.h"
+#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/Statepoint.h"
#include "llvm/IR/Type.h"
@@ -676,6 +677,9 @@ private:
bool FunctionProcessed = false;
bool ShouldInitializeAllMetadata;
+ /// The summary index for which we are holding slot numbers.
+ const ModuleSummaryIndex *TheIndex = nullptr;
+
/// mMap - The slot map for the module level data.
ValueMap mMap;
unsigned mNext = 0;
@@ -692,6 +696,10 @@ private:
DenseMap<AttributeSet, unsigned> asMap;
unsigned asNext = 0;
+ /// GUIDMap - The slot map for GUIDs used in the summary index.
+ DenseMap<GlobalValue::GUID, unsigned> GUIDMap;
+ unsigned GUIDNext = 0;
+
public:
/// Construct from a module.
///
@@ -709,6 +717,9 @@ public:
explicit SlotTracker(const Function *F,
bool ShouldInitializeAllMetadata = false);
+ /// Construct from a module summary index.
+ explicit SlotTracker(const ModuleSummaryIndex *Index);
+
SlotTracker(const SlotTracker &) = delete;
SlotTracker &operator=(const SlotTracker &) = delete;
@@ -718,6 +729,7 @@ public:
int getGlobalSlot(const GlobalValue *V);
int getMetadataSlot(const MDNode *N);
int getAttributeGroupSlot(AttributeSet AS);
+ int getGUIDSlot(GlobalValue::GUID GUID);
/// If you'd like to deal with a function instead of just a module, use
/// this method to get its data into the SlotTracker.
@@ -749,8 +761,12 @@ public:
unsigned as_size() const { return asMap.size(); }
bool as_empty() const { return asMap.empty(); }
- /// This function does the actual initialization.
+ /// GUID map iterators.
+ using guid_iterator = DenseMap<GlobalValue::GUID, unsigned>::iterator;
+
+ /// These functions do the actual initialization.
inline void initialize();
+ void initializeIndex();
// Implementation Details
private:
@@ -766,9 +782,12 @@ private:
/// Insert the specified AttributeSet into the slot table.
void CreateAttributeSetSlot(AttributeSet AS);
+ void CreateGUIDSlot(GlobalValue::GUID GUID);
+
/// Add all of the module level global variables (and their initializers)
/// and function declarations, but not the contents of those functions.
void processModule();
+ void processIndex();
/// Add all of the functions arguments, basic blocks, and instructions.
void processFunction();
@@ -869,6 +888,9 @@ SlotTracker::SlotTracker(const Function *F, bool ShouldInitializeAllMetadata)
: TheModule(F ? F->getParent() : nullptr), TheFunction(F),
ShouldInitializeAllMetadata(ShouldInitializeAllMetadata) {}
+SlotTracker::SlotTracker(const ModuleSummaryIndex *Index)
+ : TheModule(nullptr), ShouldInitializeAllMetadata(false), TheIndex(Index) {}
+
inline void SlotTracker::initialize() {
if (TheModule) {
processModule();
@@ -879,6 +901,13 @@ inline void SlotTracker::initialize() {
processFunction();
}
+void SlotTracker::initializeIndex() {
+ if (!TheIndex)
+ return;
+ processIndex();
+ TheIndex = nullptr; ///< Prevent re-processing next time we're called.
+}
+
// Iterate through all the global variables, functions, and global
// variable initializers and create slots for them.
void SlotTracker::processModule() {
@@ -970,6 +999,24 @@ void SlotTracker::processFunction() {
ST_DEBUG("end processFunction!\n");
}
+// Iterate through all the GUID in the index and create slots for them.
+void SlotTracker::processIndex() {
+ ST_DEBUG("begin processIndex!\n");
+ assert(TheIndex);
+
+ // The first block of slots are just the module ids, which start at 0 and are
+ // assigned consecutively. Start numbering the GUIDs after the module ids.
+ GUIDNext = TheIndex->modulePaths().size();
+
+ for (auto &GlobalList : *TheIndex)
+ CreateGUIDSlot(GlobalList.first);
+
+ for (auto &TId : TheIndex->typeIds())
+ CreateGUIDSlot(GlobalValue::getGUID(TId.first));
+
+ ST_DEBUG("end processIndex!\n");
+}
+
void SlotTracker::processGlobalObjectMetadata(const GlobalObject &GO) {
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
GO.getAllMetadata(MDs);
@@ -1053,6 +1100,15 @@ int SlotTracker::getAttributeGroupSlot(AttributeSet AS) {
return AI == asMap.end() ? -1 : (int)AI->second;
}
+int SlotTracker::getGUIDSlot(GlobalValue::GUID GUID) {
+ // Check for uninitialized state and do lazy initialization.
+ initializeIndex();
+
+ // Find the GUID in the map
+ guid_iterator I = GUIDMap.find(GUID);
+ return I == GUIDMap.end() ? -1 : (int)I->second;
+}
+
/// CreateModuleSlot - Insert the specified GlobalValue* into the slot table.
void SlotTracker::CreateModuleSlot(const GlobalValue *V) {
assert(V && "Can't insert a null Value into SlotTracker!");
@@ -1113,6 +1169,11 @@ void SlotTracker::CreateAttributeSetSlot(AttributeSet AS) {
asMap[AS] = DestSlot;
}
+/// Create a new slot for the specified GUID
+void SlotTracker::CreateGUIDSlot(GlobalValue::GUID GUID) {
+ GUIDMap[GUID] = GUIDNext++;
+}
+
//===----------------------------------------------------------------------===//
// AsmWriter Implementation
//===----------------------------------------------------------------------===//
@@ -2193,11 +2254,12 @@ namespace {
class AssemblyWriter {
formatted_raw_ostream &Out;
- const Module *TheModule;
+ const Module *TheModule = nullptr;
+ const ModuleSummaryIndex *TheIndex = nullptr;
std::unique_ptr<SlotTracker> SlotTrackerStorage;
SlotTracker &Machine;
TypePrinting TypePrinter;
- AssemblyAnnotationWriter *AnnotationWriter;
+ AssemblyAnnotationWriter *AnnotationWriter = nullptr;
SetVector<const Comdat *> Comdats;
bool IsForDebug;
bool ShouldPreserveUseListOrder;
@@ -2205,6 +2267,7 @@ class AssemblyWriter {
SmallVector<StringRef, 8> MDNames;
/// Synchronization scope names registered with LLVMContext.
SmallVector<StringRef, 8> SSNs;
+ DenseMap<const GlobalValueSummary *, GlobalValue::GUID> SummaryToGUIDMap;
public:
/// Construct an AssemblyWriter with an external SlotTracker
@@ -2212,6 +2275,9 @@ public:
AssemblyAnnotationWriter *AAW, bool IsForDebug,
bool ShouldPreserveUseListOrder = false);
+ AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
+ const ModuleSummaryIndex *Index, bool IsForDebug);
+
void printMDNodeBody(const MDNode *MD);
void printNamedMDNode(const NamedMDNode *NMD);
@@ -2247,6 +2313,25 @@ public:
void printUseListOrder(const UseListOrder &Order);
void printUseLists(const Function *F);
+ void printModuleSummaryIndex();
+ void printSummaryInfo(unsigned Slot, const ValueInfo &VI);
+ void printSummary(const GlobalValueSummary &Summary);
+ void printAliasSummary(const AliasSummary *AS);
+ void printGlobalVarSummary(const GlobalVarSummary *GS);
+ void printFunctionSummary(const FunctionSummary *FS);
+ void printTypeIdSummary(const TypeIdSummary &TIS);
+ void printTypeTestResolution(const TypeTestResolution &TTRes);
+ void printArgs(const std::vector<uint64_t> &Args);
+ void printWPDRes(const WholeProgramDevirtResolution &WPDRes);
+ void printTypeIdInfo(const FunctionSummary::TypeIdInfo &TIDInfo);
+ void printVFuncId(const FunctionSummary::VFuncId VFId);
+ void
+ printNonConstVCalls(const std::vector<FunctionSummary::VFuncId> VCallList,
+ const char *Tag);
+ void
+ printConstVCalls(const std::vector<FunctionSummary::ConstVCall> VCallList,
+ const char *Tag);
+
private:
/// Print out metadata attachments.
void printMetadataAttachments(
@@ -2277,6 +2362,11 @@ AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
Comdats.insert(C);
}
+AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
+ const ModuleSummaryIndex *Index, bool IsForDebug)
+ : Out(o), TheIndex(Index), Machine(Mac), TypePrinter(/*Module=*/nullptr),
+ IsForDebug(IsForDebug), ShouldPreserveUseListOrder(false) {}
+
void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) {
if (!Operand) {
Out << "<null operand!>";
@@ -2478,6 +2568,210 @@ void AssemblyWriter::printModule(const Module *M) {
}
}
+void AssemblyWriter::printModuleSummaryIndex() {
+ assert(TheIndex);
+ Machine.initializeIndex();
+
+ Out << "\n";
+
+ // Print module path entries, using the module id as the slot number. To
+ // print in order, add paths to a vector indexed by module id.
+ std::vector<std::pair<StringRef, ModuleHash>> moduleVec;
+ std::string RegularLTOModuleName = "[Regular LTO]";
+ moduleVec.resize(TheIndex->modulePaths().size());
+ for (auto &ModPath : TheIndex->modulePaths()) {
+ // A module id of -1 is a special entry for a regular LTO module created
+ // during the thin link.
+ if (ModPath.second.first == -1u)
+ moduleVec[TheIndex->modulePaths().size() - 1] =
+ std::make_pair(RegularLTOModuleName, ModPath.second.second);
+ else {
+ assert(ModPath.second.first < moduleVec.size());
+ moduleVec[ModPath.second.first] =
+ std::make_pair(ModPath.first(), ModPath.second.second);
+ }
+ }
+ unsigned i = 0;
+ for (auto &ModPair : moduleVec) {
+ Out << "^" << i++ << " = module: (";
+ Out << "path: \"" << ModPair.first << "\"";
+ Out << ", hash: (";
+ FieldSeparator FS;
+ for (auto Hash : ModPair.second)
+ Out << FS << Hash;
+ Out << "))\n";
+ }
+
+ // FIXME: Change AliasSummary to hold a ValueInfo instead of summary pointer
+ // for aliasee (then update BitcodeWriter.cpp and remove get/setAliaseeGUID).
+ for (auto &GlobalList : *TheIndex) {
+ auto GUID = GlobalList.first;
+ for (auto &Summary : GlobalList.second.SummaryList)
+ SummaryToGUIDMap[Summary.get()] = GUID;
+ }
+
+ // Print the global value summary entries.
+ for (auto &GlobalList : *TheIndex) {
+ auto GUID = GlobalList.first;
+ auto VI = TheIndex->getValueInfo(GlobalList);
+ printSummaryInfo(Machine.getGUIDSlot(GUID), VI);
+ }
+
+ // Print the TypeIdMap entries.
+ for (auto &TId : TheIndex->typeIds()) {
+ auto GUID = GlobalValue::getGUID(TId.first);
+ Out << "^" << Machine.getGUIDSlot(GUID) << " = typeid: (name: \""
+ << TId.first << "\"";
+ printTypeIdSummary(TId.second);
+ Out << ") ; guid = " << GUID << "\n";
+ }
+}
+
+static const char *
+getWholeProgDevirtResKindName(WholeProgramDevirtResolution::Kind K) {
+ switch (K) {
+ case WholeProgramDevirtResolution::Indir:
+ return "indir";
+ case WholeProgramDevirtResolution::SingleImpl:
+ return "singleImpl";
+ case WholeProgramDevirtResolution::BranchFunnel:
+ return "branchFunnel";
+ }
+ llvm_unreachable("invalid WholeProgramDevirtResolution kind");
+}
+
+static const char *getWholeProgDevirtResByArgKindName(
+ WholeProgramDevirtResolution::ByArg::Kind K) {
+ switch (K) {
+ case WholeProgramDevirtResolution::ByArg::Indir:
+ return "indir";
+ case WholeProgramDevirtResolution::ByArg::UniformRetVal:
+ return "uniformRetVal";
+ case WholeProgramDevirtResolution::ByArg::UniqueRetVal:
+ return "uniqueRetVal";
+ case WholeProgramDevirtResolution::ByArg::VirtualConstProp:
+ return "virtualConstProp";
+ }
+ llvm_unreachable("invalid WholeProgramDevirtResolution::ByArg kind");
+}
+
+static const char *getTTResKindName(TypeTestResolution::Kind K) {
+ switch (K) {
+ case TypeTestResolution::Unsat:
+ return "unsat";
+ case TypeTestResolution::ByteArray:
+ return "byteArray";
+ case TypeTestResolution::Inline:
+ return "inline";
+ case TypeTestResolution::Single:
+ return "single";
+ case TypeTestResolution::AllOnes:
+ return "allOnes";
+ }
+ llvm_unreachable("invalid TypeTestResolution kind");
+}
+
+void AssemblyWriter::printTypeTestResolution(const TypeTestResolution &TTRes) {
+ Out << "typeTestRes: (kind: " << getTTResKindName(TTRes.TheKind)
+ << ", sizeM1BitWidth: " << TTRes.SizeM1BitWidth;
+
+ // The following fields are only used if the target does not support the use
+ // of absolute symbols to store constants. Print only if non-zero.
+ if (TTRes.AlignLog2)
+ Out << ", alignLog2: " << TTRes.AlignLog2;
+ if (TTRes.SizeM1)
+ Out << ", sizeM1: " << TTRes.SizeM1;
+ if (TTRes.BitMask)
+ // BitMask is uint8_t which causes it to print the corresponding char.
+ Out << ", bitMask: " << (unsigned)TTRes.BitMask;
+ if (TTRes.InlineBits)
+ Out << ", inlineBits: " << TTRes.InlineBits;
+
+ Out << ")";
+}
+
+void AssemblyWriter::printTypeIdSummary(const TypeIdSummary &TIS) {
+ Out << ", summary: (";
+ printTypeTestResolution(TIS.TTRes);
+ if (!TIS.WPDRes.empty()) {
+ Out << ", wpdResolutions: (";
+ FieldSeparator FS;
+ for (auto &WPDRes : TIS.WPDRes) {
+ Out << FS;
+ Out << "(offset: " << WPDRes.first << ", ";
+ printWPDRes(WPDRes.second);
+ Out << ")";
+ }
+ Out << ")";
+ }
+ Out << ")";
+}
+
+void AssemblyWriter::printArgs(const std::vector<uint64_t> &Args) {
+ Out << "args: (";
+ FieldSeparator FS;
+ for (auto arg : Args) {
+ Out << FS;
+ Out << arg;
+ }
+ Out << ")";
+}
+
+void AssemblyWriter::printWPDRes(const WholeProgramDevirtResolution &WPDRes) {
+ Out << "wpdRes: (kind: ";
+ Out << getWholeProgDevirtResKindName(WPDRes.TheKind);
+
+ if (WPDRes.TheKind == WholeProgramDevirtResolution::SingleImpl)
+ Out << ", singleImplName: \"" << WPDRes.SingleImplName << "\"";
+
+ if (!WPDRes.ResByArg.empty()) {
+ Out << ", resByArg: (";
+ FieldSeparator FS;
+ for (auto &ResByArg : WPDRes.ResByArg) {
+ Out << FS;
+ printArgs(ResByArg.first);
+ Out << ", byArg: (kind: ";
+ Out << getWholeProgDevirtResByArgKindName(ResByArg.second.TheKind);
+ if (ResByArg.second.TheKind ==
+ WholeProgramDevirtResolution::ByArg::UniformRetVal ||
+ ResByArg.second.TheKind ==
+ WholeProgramDevirtResolution::ByArg::UniqueRetVal)
+ Out << ", info: " << ResByArg.second.Info;
+
+ // The following fields are only used if the target does not support the
+ // use of absolute symbols to store constants. Print only if non-zero.
+ if (ResByArg.second.Byte || ResByArg.second.Bit)
+ Out << ", byte: " << ResByArg.second.Byte
+ << ", bit: " << ResByArg.second.Bit;
+
+ Out << ")";
+ }
+ Out << ")";
+ }
+ Out << ")";
+}
+
+static const char *getSummaryKindName(GlobalValueSummary::SummaryKind SK) {
+ switch (SK) {
+ case GlobalValueSummary::AliasKind:
+ return "alias";
+ case GlobalValueSummary::FunctionKind:
+ return "function";
+ case GlobalValueSummary::GlobalVarKind:
+ return "variable";
+ }
+ llvm_unreachable("invalid summary kind");
+}
+
+void AssemblyWriter::printAliasSummary(const AliasSummary *AS) {
+ Out << ", aliasee: ^"
+ << Machine.getGUIDSlot(SummaryToGUIDMap[&AS->getAliasee()]);
+}
+
+void AssemblyWriter::printGlobalVarSummary(const GlobalVarSummary *GS) {
+ // Nothing for now
+}
+
static std::string getLinkageName(GlobalValue::LinkageTypes LT) {
switch (LT) {
case GlobalValue::ExternalLinkage:
@@ -2515,6 +2809,184 @@ static std::string getLinkageNameWithSpace(GlobalValue::LinkageTypes LT) {
return getLinkageName(LT) + " ";
}
+static const char *getHotnessName(CalleeInfo::HotnessType HT) {
+ switch (HT) {
+ case CalleeInfo::HotnessType::Unknown:
+ return "unknown";
+ case CalleeInfo::HotnessType::Cold:
+ return "cold";
+ case CalleeInfo::HotnessType::None:
+ return "none";
+ case CalleeInfo::HotnessType::Hot:
+ return "hot";
+ case CalleeInfo::HotnessType::Critical:
+ return "critical";
+ }
+ llvm_unreachable("invalid hotness");
+}
+
+void AssemblyWriter::printFunctionSummary(const FunctionSummary *FS) {
+ Out << ", insts: " << FS->instCount();
+
+ FunctionSummary::FFlags FFlags = FS->fflags();
+ if (FFlags.ReadNone | FFlags.ReadOnly | FFlags.NoRecurse |
+ FFlags.ReturnDoesNotAlias) {
+ Out << ", funcFlags: (";
+ Out << "readNone: " << FFlags.ReadNone;
+ Out << ", readOnly: " << FFlags.ReadOnly;
+ Out << ", noRecurse: " << FFlags.NoRecurse;
+ Out << ", returnDoesNotAlias: " << FFlags.ReturnDoesNotAlias;
+ Out << ")";
+ }
+ if (!FS->calls().empty()) {
+ Out << ", calls: (";
+ FieldSeparator IFS;
+ for (auto &Call : FS->calls()) {
+ Out << IFS;
+ Out << "(callee: ^" << Machine.getGUIDSlot(Call.first.getGUID());
+ if (Call.second.getHotness() != CalleeInfo::HotnessType::Unknown)
+ Out << ", hotness: " << getHotnessName(Call.second.getHotness());
+ else if (Call.second.RelBlockFreq)
+ Out << ", relbf: " << Call.second.RelBlockFreq;
+ Out << ")";
+ }
+ Out << ")";
+ }
+
+ if (const auto *TIdInfo = FS->getTypeIdInfo())
+ printTypeIdInfo(*TIdInfo);
+}
+
+void AssemblyWriter::printTypeIdInfo(
+ const FunctionSummary::TypeIdInfo &TIDInfo) {
+ Out << ", typeIdInfo: (";
+ FieldSeparator TIDFS;
+ if (!TIDInfo.TypeTests.empty()) {
+ Out << TIDFS;
+ Out << "typeTests: (";
+ FieldSeparator FS;
+ for (auto &GUID : TIDInfo.TypeTests) {
+ Out << FS;
+ auto Slot = Machine.getGUIDSlot(GUID);
+ if (Slot != -1)
+ Out << "^" << Slot;
+ else
+ Out << GUID;
+ }
+ Out << ")";
+ }
+ if (!TIDInfo.TypeTestAssumeVCalls.empty()) {
+ Out << TIDFS;
+ printNonConstVCalls(TIDInfo.TypeTestAssumeVCalls, "typeTestAssumeVCalls");
+ }
+ if (!TIDInfo.TypeCheckedLoadVCalls.empty()) {
+ Out << TIDFS;
+ printNonConstVCalls(TIDInfo.TypeCheckedLoadVCalls, "typeCheckedLoadVCalls");
+ }
+ if (!TIDInfo.TypeTestAssumeConstVCalls.empty()) {
+ Out << TIDFS;
+ printConstVCalls(TIDInfo.TypeTestAssumeConstVCalls,
+ "typeTestAssumeConstVCalls");
+ }
+ if (!TIDInfo.TypeCheckedLoadConstVCalls.empty()) {
+ Out << TIDFS;
+ printConstVCalls(TIDInfo.TypeCheckedLoadConstVCalls,
+ "typeCheckedLoadConstVCalls");
+ }
+ Out << ")";
+}
+
+void AssemblyWriter::printVFuncId(const FunctionSummary::VFuncId VFId) {
+ Out << "vFuncId: (";
+ auto Slot = Machine.getGUIDSlot(VFId.GUID);
+ if (Slot != -1)
+ Out << "^" << Slot;
+ else
+ Out << "guid: " << VFId.GUID;
+ Out << ", offset: " << VFId.Offset;
+ Out << ")";
+}
+
+void AssemblyWriter::printNonConstVCalls(
+ const std::vector<FunctionSummary::VFuncId> VCallList, const char *Tag) {
+ Out << Tag << ": (";
+ FieldSeparator FS;
+ for (auto &VFuncId : VCallList) {
+ Out << FS;
+ printVFuncId(VFuncId);
+ }
+ Out << ")";
+}
+
+void AssemblyWriter::printConstVCalls(
+ const std::vector<FunctionSummary::ConstVCall> VCallList, const char *Tag) {
+ Out << Tag << ": (";
+ FieldSeparator FS;
+ for (auto &ConstVCall : VCallList) {
+ Out << FS;
+ printVFuncId(ConstVCall.VFunc);
+ if (!ConstVCall.Args.empty()) {
+ Out << ", ";
+ printArgs(ConstVCall.Args);
+ }
+ }
+ Out << ")";
+}
+
+void AssemblyWriter::printSummary(const GlobalValueSummary &Summary) {
+ GlobalValueSummary::GVFlags GVFlags = Summary.flags();
+ GlobalValue::LinkageTypes LT = (GlobalValue::LinkageTypes)GVFlags.Linkage;
+ Out << getSummaryKindName(Summary.getSummaryKind()) << ": ";
+ Out << "(module: ^" << TheIndex->getModuleId(Summary.modulePath())
+ << ", flags: (";
+ Out << "linkage: " << getLinkageName(LT);
+ Out << ", notEligibleToImport: " << GVFlags.NotEligibleToImport;
+ Out << ", live: " << GVFlags.Live;
+ Out << ", dsoLocal: " << GVFlags.DSOLocal;
+ Out << ")";
+
+ if (Summary.getSummaryKind() == GlobalValueSummary::AliasKind)
+ printAliasSummary(cast<AliasSummary>(&Summary));
+ else if (Summary.getSummaryKind() == GlobalValueSummary::FunctionKind)
+ printFunctionSummary(cast<FunctionSummary>(&Summary));
+ else
+ printGlobalVarSummary(cast<GlobalVarSummary>(&Summary));
+
+ auto RefList = Summary.refs();
+ if (!RefList.empty()) {
+ Out << ", refs: (";
+ FieldSeparator FS;
+ for (auto &Ref : RefList) {
+ Out << FS;
+ Out << "^" << Machine.getGUIDSlot(Ref.getGUID());
+ }
+ Out << ")";
+ }
+
+ Out << ")";
+}
+
+void AssemblyWriter::printSummaryInfo(unsigned Slot, const ValueInfo &VI) {
+ Out << "^" << Slot << " = gv: (";
+ if (!VI.name().empty())
+ Out << "name: \"" << VI.name() << "\"";
+ else
+ Out << "guid: " << VI.getGUID();
+ if (!VI.getSummaryList().empty()) {
+ Out << ", summaries: (";
+ FieldSeparator FS;
+ for (auto &Summary : VI.getSummaryList()) {
+ Out << FS;
+ printSummary(*Summary);
+ }
+ Out << ")";
+ }
+ Out << ")";
+ if (!VI.name().empty())
+ Out << " ; guid = " << VI.getGUID();
+ Out << "\n";
+}
+
static void printMetadataIdentifier(StringRef Name,
formatted_raw_ostream &Out) {
if (Name.empty()) {
@@ -3700,6 +4172,13 @@ void Metadata::print(raw_ostream &OS, ModuleSlotTracker &MST,
printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ false);
}
+void ModuleSummaryIndex::print(raw_ostream &ROS, bool IsForDebug) const {
+ SlotTracker SlotTable(this);
+ formatted_raw_ostream OS(ROS);
+ AssemblyWriter W(OS, SlotTable, this, IsForDebug);
+ W.printModuleSummaryIndex();
+}
+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
// Value::dump - allow easy printing of Values from the debugger.
LLVM_DUMP_METHOD
@@ -3732,4 +4211,8 @@ void Metadata::dump(const Module *M) const {
print(dbgs(), M, /*IsForDebug=*/true);
dbgs() << '\n';
}
+
+// Allow printing of ModuleSummaryIndex from the debugger.
+LLVM_DUMP_METHOD
+void ModuleSummaryIndex::dump() const { print(dbgs(), /*IsForDebug=*/true); }
#endif
OpenPOWER on IntegriCloud