1480093f4SDimitry Andric //===---------- DebugUtils.cpp - Utilities for debugging ORC JITs ---------===// 2480093f4SDimitry Andric // 3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6480093f4SDimitry Andric // 7480093f4SDimitry Andric //===----------------------------------------------------------------------===// 8480093f4SDimitry Andric 9480093f4SDimitry Andric #include "llvm/ExecutionEngine/Orc/DebugUtils.h" 10*5ffd83dbSDimitry Andric 11*5ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/Orc/Core.h" 12*5ffd83dbSDimitry Andric #include "llvm/Support/CommandLine.h" 13480093f4SDimitry Andric #include "llvm/Support/Debug.h" 14*5ffd83dbSDimitry Andric #include "llvm/Support/FileSystem.h" 15*5ffd83dbSDimitry Andric #include "llvm/Support/Format.h" 16480093f4SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 17480093f4SDimitry Andric #include "llvm/Support/Path.h" 18480093f4SDimitry Andric #include "llvm/Support/raw_ostream.h" 19480093f4SDimitry Andric 20480093f4SDimitry Andric #define DEBUG_TYPE "orc" 21480093f4SDimitry Andric 22*5ffd83dbSDimitry Andric using namespace llvm; 23*5ffd83dbSDimitry Andric 24*5ffd83dbSDimitry Andric namespace { 25*5ffd83dbSDimitry Andric 26*5ffd83dbSDimitry Andric #ifndef NDEBUG 27*5ffd83dbSDimitry Andric 28*5ffd83dbSDimitry Andric cl::opt<bool> PrintHidden("debug-orc-print-hidden", cl::init(true), 29*5ffd83dbSDimitry Andric cl::desc("debug print hidden symbols defined by " 30*5ffd83dbSDimitry Andric "materialization units"), 31*5ffd83dbSDimitry Andric cl::Hidden); 32*5ffd83dbSDimitry Andric 33*5ffd83dbSDimitry Andric cl::opt<bool> PrintCallable("debug-orc-print-callable", cl::init(true), 34*5ffd83dbSDimitry Andric cl::desc("debug print callable symbols defined by " 35*5ffd83dbSDimitry Andric "materialization units"), 36*5ffd83dbSDimitry Andric cl::Hidden); 37*5ffd83dbSDimitry Andric 38*5ffd83dbSDimitry Andric cl::opt<bool> PrintData("debug-orc-print-data", cl::init(true), 39*5ffd83dbSDimitry Andric cl::desc("debug print data symbols defined by " 40*5ffd83dbSDimitry Andric "materialization units"), 41*5ffd83dbSDimitry Andric cl::Hidden); 42*5ffd83dbSDimitry Andric 43*5ffd83dbSDimitry Andric #endif // NDEBUG 44*5ffd83dbSDimitry Andric 45*5ffd83dbSDimitry Andric // SetPrinter predicate that prints every element. 46*5ffd83dbSDimitry Andric template <typename T> struct PrintAll { 47*5ffd83dbSDimitry Andric bool operator()(const T &E) { return true; } 48*5ffd83dbSDimitry Andric }; 49*5ffd83dbSDimitry Andric 50*5ffd83dbSDimitry Andric bool anyPrintSymbolOptionSet() { 51*5ffd83dbSDimitry Andric #ifndef NDEBUG 52*5ffd83dbSDimitry Andric return PrintHidden || PrintCallable || PrintData; 53*5ffd83dbSDimitry Andric #else 54*5ffd83dbSDimitry Andric return false; 55*5ffd83dbSDimitry Andric #endif // NDEBUG 56*5ffd83dbSDimitry Andric } 57*5ffd83dbSDimitry Andric 58*5ffd83dbSDimitry Andric bool flagsMatchCLOpts(const JITSymbolFlags &Flags) { 59*5ffd83dbSDimitry Andric #ifndef NDEBUG 60*5ffd83dbSDimitry Andric // Bail out early if this is a hidden symbol and we're not printing hiddens. 61*5ffd83dbSDimitry Andric if (!PrintHidden && !Flags.isExported()) 62*5ffd83dbSDimitry Andric return false; 63*5ffd83dbSDimitry Andric 64*5ffd83dbSDimitry Andric // Return true if this is callable and we're printing callables. 65*5ffd83dbSDimitry Andric if (PrintCallable && Flags.isCallable()) 66*5ffd83dbSDimitry Andric return true; 67*5ffd83dbSDimitry Andric 68*5ffd83dbSDimitry Andric // Return true if this is data and we're printing data. 69*5ffd83dbSDimitry Andric if (PrintData && !Flags.isCallable()) 70*5ffd83dbSDimitry Andric return true; 71*5ffd83dbSDimitry Andric 72*5ffd83dbSDimitry Andric // otherwise return false. 73*5ffd83dbSDimitry Andric return false; 74*5ffd83dbSDimitry Andric #else 75*5ffd83dbSDimitry Andric return false; 76*5ffd83dbSDimitry Andric #endif // NDEBUG 77*5ffd83dbSDimitry Andric } 78*5ffd83dbSDimitry Andric 79*5ffd83dbSDimitry Andric // Prints a sequence of items, filtered by an user-supplied predicate. 80*5ffd83dbSDimitry Andric template <typename Sequence, 81*5ffd83dbSDimitry Andric typename Pred = PrintAll<typename Sequence::value_type>> 82*5ffd83dbSDimitry Andric class SequencePrinter { 83*5ffd83dbSDimitry Andric public: 84*5ffd83dbSDimitry Andric SequencePrinter(const Sequence &S, char OpenSeq, char CloseSeq, 85*5ffd83dbSDimitry Andric Pred ShouldPrint = Pred()) 86*5ffd83dbSDimitry Andric : S(S), OpenSeq(OpenSeq), CloseSeq(CloseSeq), 87*5ffd83dbSDimitry Andric ShouldPrint(std::move(ShouldPrint)) {} 88*5ffd83dbSDimitry Andric 89*5ffd83dbSDimitry Andric void printTo(llvm::raw_ostream &OS) const { 90*5ffd83dbSDimitry Andric bool PrintComma = false; 91*5ffd83dbSDimitry Andric OS << OpenSeq; 92*5ffd83dbSDimitry Andric for (auto &E : S) { 93*5ffd83dbSDimitry Andric if (ShouldPrint(E)) { 94*5ffd83dbSDimitry Andric if (PrintComma) 95*5ffd83dbSDimitry Andric OS << ','; 96*5ffd83dbSDimitry Andric OS << ' ' << E; 97*5ffd83dbSDimitry Andric PrintComma = true; 98*5ffd83dbSDimitry Andric } 99*5ffd83dbSDimitry Andric } 100*5ffd83dbSDimitry Andric OS << ' ' << CloseSeq; 101*5ffd83dbSDimitry Andric } 102*5ffd83dbSDimitry Andric 103*5ffd83dbSDimitry Andric private: 104*5ffd83dbSDimitry Andric const Sequence &S; 105*5ffd83dbSDimitry Andric char OpenSeq; 106*5ffd83dbSDimitry Andric char CloseSeq; 107*5ffd83dbSDimitry Andric mutable Pred ShouldPrint; 108*5ffd83dbSDimitry Andric }; 109*5ffd83dbSDimitry Andric 110*5ffd83dbSDimitry Andric template <typename Sequence, typename Pred> 111*5ffd83dbSDimitry Andric SequencePrinter<Sequence, Pred> printSequence(const Sequence &S, char OpenSeq, 112*5ffd83dbSDimitry Andric char CloseSeq, Pred P = Pred()) { 113*5ffd83dbSDimitry Andric return SequencePrinter<Sequence, Pred>(S, OpenSeq, CloseSeq, std::move(P)); 114*5ffd83dbSDimitry Andric } 115*5ffd83dbSDimitry Andric 116*5ffd83dbSDimitry Andric // Render a SequencePrinter by delegating to its printTo method. 117*5ffd83dbSDimitry Andric template <typename Sequence, typename Pred> 118*5ffd83dbSDimitry Andric llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, 119*5ffd83dbSDimitry Andric const SequencePrinter<Sequence, Pred> &Printer) { 120*5ffd83dbSDimitry Andric Printer.printTo(OS); 121*5ffd83dbSDimitry Andric return OS; 122*5ffd83dbSDimitry Andric } 123*5ffd83dbSDimitry Andric 124*5ffd83dbSDimitry Andric struct PrintSymbolFlagsMapElemsMatchingCLOpts { 125*5ffd83dbSDimitry Andric bool operator()(const orc::SymbolFlagsMap::value_type &KV) { 126*5ffd83dbSDimitry Andric return flagsMatchCLOpts(KV.second); 127*5ffd83dbSDimitry Andric } 128*5ffd83dbSDimitry Andric }; 129*5ffd83dbSDimitry Andric 130*5ffd83dbSDimitry Andric struct PrintSymbolMapElemsMatchingCLOpts { 131*5ffd83dbSDimitry Andric bool operator()(const orc::SymbolMap::value_type &KV) { 132*5ffd83dbSDimitry Andric return flagsMatchCLOpts(KV.second.getFlags()); 133*5ffd83dbSDimitry Andric } 134*5ffd83dbSDimitry Andric }; 135*5ffd83dbSDimitry Andric 136*5ffd83dbSDimitry Andric } // end anonymous namespace 137*5ffd83dbSDimitry Andric 138480093f4SDimitry Andric namespace llvm { 139480093f4SDimitry Andric namespace orc { 140480093f4SDimitry Andric 141*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym) { 142*5ffd83dbSDimitry Andric return OS << *Sym; 143*5ffd83dbSDimitry Andric } 144*5ffd83dbSDimitry Andric 145*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) { 146*5ffd83dbSDimitry Andric return OS << printSequence(Symbols, '{', '}', PrintAll<SymbolStringPtr>()); 147*5ffd83dbSDimitry Andric } 148*5ffd83dbSDimitry Andric 149*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols) { 150*5ffd83dbSDimitry Andric return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>()); 151*5ffd83dbSDimitry Andric } 152*5ffd83dbSDimitry Andric 153*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, ArrayRef<SymbolStringPtr> Symbols) { 154*5ffd83dbSDimitry Andric return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>()); 155*5ffd83dbSDimitry Andric } 156*5ffd83dbSDimitry Andric 157*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) { 158*5ffd83dbSDimitry Andric if (Flags.hasError()) 159*5ffd83dbSDimitry Andric OS << "[*ERROR*]"; 160*5ffd83dbSDimitry Andric if (Flags.isCallable()) 161*5ffd83dbSDimitry Andric OS << "[Callable]"; 162*5ffd83dbSDimitry Andric else 163*5ffd83dbSDimitry Andric OS << "[Data]"; 164*5ffd83dbSDimitry Andric if (Flags.isWeak()) 165*5ffd83dbSDimitry Andric OS << "[Weak]"; 166*5ffd83dbSDimitry Andric else if (Flags.isCommon()) 167*5ffd83dbSDimitry Andric OS << "[Common]"; 168*5ffd83dbSDimitry Andric 169*5ffd83dbSDimitry Andric if (!Flags.isExported()) 170*5ffd83dbSDimitry Andric OS << "[Hidden]"; 171*5ffd83dbSDimitry Andric 172*5ffd83dbSDimitry Andric return OS; 173*5ffd83dbSDimitry Andric } 174*5ffd83dbSDimitry Andric 175*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const JITEvaluatedSymbol &Sym) { 176*5ffd83dbSDimitry Andric return OS << format("0x%016" PRIx64, Sym.getAddress()) << " " 177*5ffd83dbSDimitry Andric << Sym.getFlags(); 178*5ffd83dbSDimitry Andric } 179*5ffd83dbSDimitry Andric 180*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV) { 181*5ffd83dbSDimitry Andric return OS << "(\"" << KV.first << "\", " << KV.second << ")"; 182*5ffd83dbSDimitry Andric } 183*5ffd83dbSDimitry Andric 184*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) { 185*5ffd83dbSDimitry Andric return OS << "(\"" << KV.first << "\": " << KV.second << ")"; 186*5ffd83dbSDimitry Andric } 187*5ffd83dbSDimitry Andric 188*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) { 189*5ffd83dbSDimitry Andric return OS << printSequence(SymbolFlags, '{', '}', 190*5ffd83dbSDimitry Andric PrintSymbolFlagsMapElemsMatchingCLOpts()); 191*5ffd83dbSDimitry Andric } 192*5ffd83dbSDimitry Andric 193*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) { 194*5ffd83dbSDimitry Andric return OS << printSequence(Symbols, '{', '}', 195*5ffd83dbSDimitry Andric PrintSymbolMapElemsMatchingCLOpts()); 196*5ffd83dbSDimitry Andric } 197*5ffd83dbSDimitry Andric 198*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, 199*5ffd83dbSDimitry Andric const SymbolDependenceMap::value_type &KV) { 200*5ffd83dbSDimitry Andric return OS << "(" << KV.first->getName() << ", " << KV.second << ")"; 201*5ffd83dbSDimitry Andric } 202*5ffd83dbSDimitry Andric 203*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) { 204*5ffd83dbSDimitry Andric return OS << printSequence(Deps, '{', '}', 205*5ffd83dbSDimitry Andric PrintAll<SymbolDependenceMap::value_type>()); 206*5ffd83dbSDimitry Andric } 207*5ffd83dbSDimitry Andric 208*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU) { 209*5ffd83dbSDimitry Andric OS << "MU@" << &MU << " (\"" << MU.getName() << "\""; 210*5ffd83dbSDimitry Andric if (anyPrintSymbolOptionSet()) 211*5ffd83dbSDimitry Andric OS << ", " << MU.getSymbols(); 212*5ffd83dbSDimitry Andric return OS << ")"; 213*5ffd83dbSDimitry Andric } 214*5ffd83dbSDimitry Andric 215*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K) { 216*5ffd83dbSDimitry Andric switch (K) { 217*5ffd83dbSDimitry Andric case LookupKind::Static: 218*5ffd83dbSDimitry Andric return OS << "Static"; 219*5ffd83dbSDimitry Andric case LookupKind::DLSym: 220*5ffd83dbSDimitry Andric return OS << "DLSym"; 221*5ffd83dbSDimitry Andric } 222*5ffd83dbSDimitry Andric llvm_unreachable("Invalid lookup kind"); 223*5ffd83dbSDimitry Andric } 224*5ffd83dbSDimitry Andric 225*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, 226*5ffd83dbSDimitry Andric const JITDylibLookupFlags &JDLookupFlags) { 227*5ffd83dbSDimitry Andric switch (JDLookupFlags) { 228*5ffd83dbSDimitry Andric case JITDylibLookupFlags::MatchExportedSymbolsOnly: 229*5ffd83dbSDimitry Andric return OS << "MatchExportedSymbolsOnly"; 230*5ffd83dbSDimitry Andric case JITDylibLookupFlags::MatchAllSymbols: 231*5ffd83dbSDimitry Andric return OS << "MatchAllSymbols"; 232*5ffd83dbSDimitry Andric } 233*5ffd83dbSDimitry Andric llvm_unreachable("Invalid JITDylib lookup flags"); 234*5ffd83dbSDimitry Andric } 235*5ffd83dbSDimitry Andric 236*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LookupFlags) { 237*5ffd83dbSDimitry Andric switch (LookupFlags) { 238*5ffd83dbSDimitry Andric case SymbolLookupFlags::RequiredSymbol: 239*5ffd83dbSDimitry Andric return OS << "RequiredSymbol"; 240*5ffd83dbSDimitry Andric case SymbolLookupFlags::WeaklyReferencedSymbol: 241*5ffd83dbSDimitry Andric return OS << "WeaklyReferencedSymbol"; 242*5ffd83dbSDimitry Andric } 243*5ffd83dbSDimitry Andric llvm_unreachable("Invalid symbol lookup flags"); 244*5ffd83dbSDimitry Andric } 245*5ffd83dbSDimitry Andric 246*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, 247*5ffd83dbSDimitry Andric const SymbolLookupSet::value_type &KV) { 248*5ffd83dbSDimitry Andric return OS << "(" << KV.first << ", " << KV.second << ")"; 249*5ffd83dbSDimitry Andric } 250*5ffd83dbSDimitry Andric 251*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet &LookupSet) { 252*5ffd83dbSDimitry Andric return OS << printSequence(LookupSet, '{', '}', 253*5ffd83dbSDimitry Andric PrintAll<SymbolLookupSet::value_type>()); 254*5ffd83dbSDimitry Andric } 255*5ffd83dbSDimitry Andric 256*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, 257*5ffd83dbSDimitry Andric const JITDylibSearchOrder &SearchOrder) { 258*5ffd83dbSDimitry Andric OS << "["; 259*5ffd83dbSDimitry Andric if (!SearchOrder.empty()) { 260*5ffd83dbSDimitry Andric assert(SearchOrder.front().first && 261*5ffd83dbSDimitry Andric "JITDylibList entries must not be null"); 262*5ffd83dbSDimitry Andric OS << " (\"" << SearchOrder.front().first->getName() << "\", " 263*5ffd83dbSDimitry Andric << SearchOrder.begin()->second << ")"; 264*5ffd83dbSDimitry Andric for (auto &KV : 265*5ffd83dbSDimitry Andric make_range(std::next(SearchOrder.begin(), 1), SearchOrder.end())) { 266*5ffd83dbSDimitry Andric assert(KV.first && "JITDylibList entries must not be null"); 267*5ffd83dbSDimitry Andric OS << ", (\"" << KV.first->getName() << "\", " << KV.second << ")"; 268*5ffd83dbSDimitry Andric } 269*5ffd83dbSDimitry Andric } 270*5ffd83dbSDimitry Andric OS << " ]"; 271*5ffd83dbSDimitry Andric return OS; 272*5ffd83dbSDimitry Andric } 273*5ffd83dbSDimitry Andric 274*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases) { 275*5ffd83dbSDimitry Andric OS << "{"; 276*5ffd83dbSDimitry Andric for (auto &KV : Aliases) 277*5ffd83dbSDimitry Andric OS << " " << *KV.first << ": " << KV.second.Aliasee << " " 278*5ffd83dbSDimitry Andric << KV.second.AliasFlags; 279*5ffd83dbSDimitry Andric OS << " }"; 280*5ffd83dbSDimitry Andric return OS; 281*5ffd83dbSDimitry Andric } 282*5ffd83dbSDimitry Andric 283*5ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S) { 284*5ffd83dbSDimitry Andric switch (S) { 285*5ffd83dbSDimitry Andric case SymbolState::Invalid: 286*5ffd83dbSDimitry Andric return OS << "Invalid"; 287*5ffd83dbSDimitry Andric case SymbolState::NeverSearched: 288*5ffd83dbSDimitry Andric return OS << "Never-Searched"; 289*5ffd83dbSDimitry Andric case SymbolState::Materializing: 290*5ffd83dbSDimitry Andric return OS << "Materializing"; 291*5ffd83dbSDimitry Andric case SymbolState::Resolved: 292*5ffd83dbSDimitry Andric return OS << "Resolved"; 293*5ffd83dbSDimitry Andric case SymbolState::Emitted: 294*5ffd83dbSDimitry Andric return OS << "Emitted"; 295*5ffd83dbSDimitry Andric case SymbolState::Ready: 296*5ffd83dbSDimitry Andric return OS << "Ready"; 297*5ffd83dbSDimitry Andric } 298*5ffd83dbSDimitry Andric llvm_unreachable("Invalid state"); 299*5ffd83dbSDimitry Andric } 300*5ffd83dbSDimitry Andric 301480093f4SDimitry Andric DumpObjects::DumpObjects(std::string DumpDir, std::string IdentifierOverride) 302480093f4SDimitry Andric : DumpDir(std::move(DumpDir)), 303480093f4SDimitry Andric IdentifierOverride(std::move(IdentifierOverride)) { 304480093f4SDimitry Andric 305480093f4SDimitry Andric /// Discard any trailing separators. 306480093f4SDimitry Andric while (!this->DumpDir.empty() && 307480093f4SDimitry Andric sys::path::is_separator(this->DumpDir.back())) 308480093f4SDimitry Andric this->DumpDir.pop_back(); 309480093f4SDimitry Andric } 310480093f4SDimitry Andric 311480093f4SDimitry Andric Expected<std::unique_ptr<MemoryBuffer>> 312480093f4SDimitry Andric DumpObjects::operator()(std::unique_ptr<MemoryBuffer> Obj) { 313480093f4SDimitry Andric size_t Idx = 1; 314480093f4SDimitry Andric 315480093f4SDimitry Andric std::string DumpPathStem; 316480093f4SDimitry Andric raw_string_ostream(DumpPathStem) 317480093f4SDimitry Andric << DumpDir << (DumpDir.empty() ? "" : "/") << getBufferIdentifier(*Obj); 318480093f4SDimitry Andric 319480093f4SDimitry Andric std::string DumpPath = DumpPathStem + ".o"; 320480093f4SDimitry Andric while (sys::fs::exists(DumpPath)) { 321480093f4SDimitry Andric DumpPath.clear(); 322480093f4SDimitry Andric raw_string_ostream(DumpPath) << DumpPathStem << "." << (++Idx) << ".o"; 323480093f4SDimitry Andric } 324480093f4SDimitry Andric 325480093f4SDimitry Andric LLVM_DEBUG({ 326480093f4SDimitry Andric dbgs() << "Dumping object buffer [ " << (const void *)Obj->getBufferStart() 327480093f4SDimitry Andric << " -- " << (const void *)(Obj->getBufferEnd() - 1) << " ] to " 328480093f4SDimitry Andric << DumpPath << "\n"; 329480093f4SDimitry Andric }); 330480093f4SDimitry Andric 331480093f4SDimitry Andric std::error_code EC; 332480093f4SDimitry Andric raw_fd_ostream DumpStream(DumpPath, EC); 333480093f4SDimitry Andric if (EC) 334480093f4SDimitry Andric return errorCodeToError(EC); 335480093f4SDimitry Andric DumpStream.write(Obj->getBufferStart(), Obj->getBufferSize()); 336480093f4SDimitry Andric 337480093f4SDimitry Andric return std::move(Obj); 338480093f4SDimitry Andric } 339480093f4SDimitry Andric 340480093f4SDimitry Andric StringRef DumpObjects::getBufferIdentifier(MemoryBuffer &B) { 341480093f4SDimitry Andric if (!IdentifierOverride.empty()) 342480093f4SDimitry Andric return IdentifierOverride; 343480093f4SDimitry Andric StringRef Identifier = B.getBufferIdentifier(); 344480093f4SDimitry Andric Identifier.consume_back(".o"); 345480093f4SDimitry Andric return Identifier; 346480093f4SDimitry Andric } 347480093f4SDimitry Andric 348480093f4SDimitry Andric } // End namespace orc. 349480093f4SDimitry Andric } // End namespace llvm. 350