xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/DebugUtils.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
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"
105ffd83dbSDimitry Andric 
115ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/Orc/Core.h"
125ffd83dbSDimitry Andric #include "llvm/Support/CommandLine.h"
13480093f4SDimitry Andric #include "llvm/Support/Debug.h"
145ffd83dbSDimitry Andric #include "llvm/Support/FileSystem.h"
155ffd83dbSDimitry 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 
225ffd83dbSDimitry Andric using namespace llvm;
235ffd83dbSDimitry Andric 
245ffd83dbSDimitry Andric namespace {
255ffd83dbSDimitry Andric 
265ffd83dbSDimitry Andric #ifndef NDEBUG
275ffd83dbSDimitry Andric 
285ffd83dbSDimitry Andric cl::opt<bool> PrintHidden("debug-orc-print-hidden", cl::init(true),
295ffd83dbSDimitry Andric                           cl::desc("debug print hidden symbols defined by "
305ffd83dbSDimitry Andric                                    "materialization units"),
315ffd83dbSDimitry Andric                           cl::Hidden);
325ffd83dbSDimitry Andric 
335ffd83dbSDimitry Andric cl::opt<bool> PrintCallable("debug-orc-print-callable", cl::init(true),
345ffd83dbSDimitry Andric                             cl::desc("debug print callable symbols defined by "
355ffd83dbSDimitry Andric                                      "materialization units"),
365ffd83dbSDimitry Andric                             cl::Hidden);
375ffd83dbSDimitry Andric 
385ffd83dbSDimitry Andric cl::opt<bool> PrintData("debug-orc-print-data", cl::init(true),
395ffd83dbSDimitry Andric                         cl::desc("debug print data symbols defined by "
405ffd83dbSDimitry Andric                                  "materialization units"),
415ffd83dbSDimitry Andric                         cl::Hidden);
425ffd83dbSDimitry Andric 
435ffd83dbSDimitry Andric #endif // NDEBUG
445ffd83dbSDimitry Andric 
455ffd83dbSDimitry Andric // SetPrinter predicate that prints every element.
465ffd83dbSDimitry Andric template <typename T> struct PrintAll {
475ffd83dbSDimitry Andric   bool operator()(const T &E) { return true; }
485ffd83dbSDimitry Andric };
495ffd83dbSDimitry Andric 
505ffd83dbSDimitry Andric bool anyPrintSymbolOptionSet() {
515ffd83dbSDimitry Andric #ifndef NDEBUG
525ffd83dbSDimitry Andric   return PrintHidden || PrintCallable || PrintData;
535ffd83dbSDimitry Andric #else
545ffd83dbSDimitry Andric   return false;
555ffd83dbSDimitry Andric #endif // NDEBUG
565ffd83dbSDimitry Andric }
575ffd83dbSDimitry Andric 
585ffd83dbSDimitry Andric bool flagsMatchCLOpts(const JITSymbolFlags &Flags) {
595ffd83dbSDimitry Andric #ifndef NDEBUG
605ffd83dbSDimitry Andric   // Bail out early if this is a hidden symbol and we're not printing hiddens.
615ffd83dbSDimitry Andric   if (!PrintHidden && !Flags.isExported())
625ffd83dbSDimitry Andric     return false;
635ffd83dbSDimitry Andric 
645ffd83dbSDimitry Andric   // Return true if this is callable and we're printing callables.
655ffd83dbSDimitry Andric   if (PrintCallable && Flags.isCallable())
665ffd83dbSDimitry Andric     return true;
675ffd83dbSDimitry Andric 
685ffd83dbSDimitry Andric   // Return true if this is data and we're printing data.
695ffd83dbSDimitry Andric   if (PrintData && !Flags.isCallable())
705ffd83dbSDimitry Andric     return true;
715ffd83dbSDimitry Andric 
725ffd83dbSDimitry Andric   // otherwise return false.
735ffd83dbSDimitry Andric   return false;
745ffd83dbSDimitry Andric #else
755ffd83dbSDimitry Andric   return false;
765ffd83dbSDimitry Andric #endif // NDEBUG
775ffd83dbSDimitry Andric }
785ffd83dbSDimitry Andric 
795ffd83dbSDimitry Andric // Prints a sequence of items, filtered by an user-supplied predicate.
805ffd83dbSDimitry Andric template <typename Sequence,
815ffd83dbSDimitry Andric           typename Pred = PrintAll<typename Sequence::value_type>>
825ffd83dbSDimitry Andric class SequencePrinter {
835ffd83dbSDimitry Andric public:
845ffd83dbSDimitry Andric   SequencePrinter(const Sequence &S, char OpenSeq, char CloseSeq,
855ffd83dbSDimitry Andric                   Pred ShouldPrint = Pred())
865ffd83dbSDimitry Andric       : S(S), OpenSeq(OpenSeq), CloseSeq(CloseSeq),
875ffd83dbSDimitry Andric         ShouldPrint(std::move(ShouldPrint)) {}
885ffd83dbSDimitry Andric 
895ffd83dbSDimitry Andric   void printTo(llvm::raw_ostream &OS) const {
905ffd83dbSDimitry Andric     bool PrintComma = false;
915ffd83dbSDimitry Andric     OS << OpenSeq;
925ffd83dbSDimitry Andric     for (auto &E : S) {
935ffd83dbSDimitry Andric       if (ShouldPrint(E)) {
945ffd83dbSDimitry Andric         if (PrintComma)
955ffd83dbSDimitry Andric           OS << ',';
965ffd83dbSDimitry Andric         OS << ' ' << E;
975ffd83dbSDimitry Andric         PrintComma = true;
985ffd83dbSDimitry Andric       }
995ffd83dbSDimitry Andric     }
1005ffd83dbSDimitry Andric     OS << ' ' << CloseSeq;
1015ffd83dbSDimitry Andric   }
1025ffd83dbSDimitry Andric 
1035ffd83dbSDimitry Andric private:
1045ffd83dbSDimitry Andric   const Sequence &S;
1055ffd83dbSDimitry Andric   char OpenSeq;
1065ffd83dbSDimitry Andric   char CloseSeq;
1075ffd83dbSDimitry Andric   mutable Pred ShouldPrint;
1085ffd83dbSDimitry Andric };
1095ffd83dbSDimitry Andric 
1105ffd83dbSDimitry Andric template <typename Sequence, typename Pred>
1115ffd83dbSDimitry Andric SequencePrinter<Sequence, Pred> printSequence(const Sequence &S, char OpenSeq,
1125ffd83dbSDimitry Andric                                               char CloseSeq, Pred P = Pred()) {
1135ffd83dbSDimitry Andric   return SequencePrinter<Sequence, Pred>(S, OpenSeq, CloseSeq, std::move(P));
1145ffd83dbSDimitry Andric }
1155ffd83dbSDimitry Andric 
1165ffd83dbSDimitry Andric // Render a SequencePrinter by delegating to its printTo method.
1175ffd83dbSDimitry Andric template <typename Sequence, typename Pred>
1185ffd83dbSDimitry Andric llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
1195ffd83dbSDimitry Andric                               const SequencePrinter<Sequence, Pred> &Printer) {
1205ffd83dbSDimitry Andric   Printer.printTo(OS);
1215ffd83dbSDimitry Andric   return OS;
1225ffd83dbSDimitry Andric }
1235ffd83dbSDimitry Andric 
1245ffd83dbSDimitry Andric struct PrintSymbolFlagsMapElemsMatchingCLOpts {
1255ffd83dbSDimitry Andric   bool operator()(const orc::SymbolFlagsMap::value_type &KV) {
1265ffd83dbSDimitry Andric     return flagsMatchCLOpts(KV.second);
1275ffd83dbSDimitry Andric   }
1285ffd83dbSDimitry Andric };
1295ffd83dbSDimitry Andric 
1305ffd83dbSDimitry Andric struct PrintSymbolMapElemsMatchingCLOpts {
1315ffd83dbSDimitry Andric   bool operator()(const orc::SymbolMap::value_type &KV) {
1325ffd83dbSDimitry Andric     return flagsMatchCLOpts(KV.second.getFlags());
1335ffd83dbSDimitry Andric   }
1345ffd83dbSDimitry Andric };
1355ffd83dbSDimitry Andric 
1365ffd83dbSDimitry Andric } // end anonymous namespace
1375ffd83dbSDimitry Andric 
138480093f4SDimitry Andric namespace llvm {
139480093f4SDimitry Andric namespace orc {
140480093f4SDimitry Andric 
1415ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym) {
1425ffd83dbSDimitry Andric   return OS << *Sym;
1435ffd83dbSDimitry Andric }
1445ffd83dbSDimitry Andric 
1455ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) {
1465ffd83dbSDimitry Andric   return OS << printSequence(Symbols, '{', '}', PrintAll<SymbolStringPtr>());
1475ffd83dbSDimitry Andric }
1485ffd83dbSDimitry Andric 
1495ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols) {
1505ffd83dbSDimitry Andric   return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
1515ffd83dbSDimitry Andric }
1525ffd83dbSDimitry Andric 
1535ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, ArrayRef<SymbolStringPtr> Symbols) {
1545ffd83dbSDimitry Andric   return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
1555ffd83dbSDimitry Andric }
1565ffd83dbSDimitry Andric 
1575ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
1585ffd83dbSDimitry Andric   if (Flags.hasError())
1595ffd83dbSDimitry Andric     OS << "[*ERROR*]";
1605ffd83dbSDimitry Andric   if (Flags.isCallable())
1615ffd83dbSDimitry Andric     OS << "[Callable]";
1625ffd83dbSDimitry Andric   else
1635ffd83dbSDimitry Andric     OS << "[Data]";
1645ffd83dbSDimitry Andric   if (Flags.isWeak())
1655ffd83dbSDimitry Andric     OS << "[Weak]";
1665ffd83dbSDimitry Andric   else if (Flags.isCommon())
1675ffd83dbSDimitry Andric     OS << "[Common]";
1685ffd83dbSDimitry Andric 
1695ffd83dbSDimitry Andric   if (!Flags.isExported())
1705ffd83dbSDimitry Andric     OS << "[Hidden]";
1715ffd83dbSDimitry Andric 
1725ffd83dbSDimitry Andric   return OS;
1735ffd83dbSDimitry Andric }
1745ffd83dbSDimitry Andric 
1755ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const JITEvaluatedSymbol &Sym) {
1765ffd83dbSDimitry Andric   return OS << format("0x%016" PRIx64, Sym.getAddress()) << " "
1775ffd83dbSDimitry Andric             << Sym.getFlags();
1785ffd83dbSDimitry Andric }
1795ffd83dbSDimitry Andric 
1805ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV) {
1815ffd83dbSDimitry Andric   return OS << "(\"" << KV.first << "\", " << KV.second << ")";
1825ffd83dbSDimitry Andric }
1835ffd83dbSDimitry Andric 
1845ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) {
1855ffd83dbSDimitry Andric   return OS << "(\"" << KV.first << "\": " << KV.second << ")";
1865ffd83dbSDimitry Andric }
1875ffd83dbSDimitry Andric 
1885ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) {
1895ffd83dbSDimitry Andric   return OS << printSequence(SymbolFlags, '{', '}',
1905ffd83dbSDimitry Andric                              PrintSymbolFlagsMapElemsMatchingCLOpts());
1915ffd83dbSDimitry Andric }
1925ffd83dbSDimitry Andric 
1935ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) {
1945ffd83dbSDimitry Andric   return OS << printSequence(Symbols, '{', '}',
1955ffd83dbSDimitry Andric                              PrintSymbolMapElemsMatchingCLOpts());
1965ffd83dbSDimitry Andric }
1975ffd83dbSDimitry Andric 
1985ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS,
1995ffd83dbSDimitry Andric                         const SymbolDependenceMap::value_type &KV) {
2005ffd83dbSDimitry Andric   return OS << "(" << KV.first->getName() << ", " << KV.second << ")";
2015ffd83dbSDimitry Andric }
2025ffd83dbSDimitry Andric 
2035ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) {
2045ffd83dbSDimitry Andric   return OS << printSequence(Deps, '{', '}',
2055ffd83dbSDimitry Andric                              PrintAll<SymbolDependenceMap::value_type>());
2065ffd83dbSDimitry Andric }
2075ffd83dbSDimitry Andric 
2085ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU) {
2095ffd83dbSDimitry Andric   OS << "MU@" << &MU << " (\"" << MU.getName() << "\"";
2105ffd83dbSDimitry Andric   if (anyPrintSymbolOptionSet())
2115ffd83dbSDimitry Andric     OS << ", " << MU.getSymbols();
2125ffd83dbSDimitry Andric   return OS << ")";
2135ffd83dbSDimitry Andric }
2145ffd83dbSDimitry Andric 
2155ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K) {
2165ffd83dbSDimitry Andric   switch (K) {
2175ffd83dbSDimitry Andric   case LookupKind::Static:
2185ffd83dbSDimitry Andric     return OS << "Static";
2195ffd83dbSDimitry Andric   case LookupKind::DLSym:
2205ffd83dbSDimitry Andric     return OS << "DLSym";
2215ffd83dbSDimitry Andric   }
2225ffd83dbSDimitry Andric   llvm_unreachable("Invalid lookup kind");
2235ffd83dbSDimitry Andric }
2245ffd83dbSDimitry Andric 
2255ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS,
2265ffd83dbSDimitry Andric                         const JITDylibLookupFlags &JDLookupFlags) {
2275ffd83dbSDimitry Andric   switch (JDLookupFlags) {
2285ffd83dbSDimitry Andric   case JITDylibLookupFlags::MatchExportedSymbolsOnly:
2295ffd83dbSDimitry Andric     return OS << "MatchExportedSymbolsOnly";
2305ffd83dbSDimitry Andric   case JITDylibLookupFlags::MatchAllSymbols:
2315ffd83dbSDimitry Andric     return OS << "MatchAllSymbols";
2325ffd83dbSDimitry Andric   }
2335ffd83dbSDimitry Andric   llvm_unreachable("Invalid JITDylib lookup flags");
2345ffd83dbSDimitry Andric }
2355ffd83dbSDimitry Andric 
2365ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LookupFlags) {
2375ffd83dbSDimitry Andric   switch (LookupFlags) {
2385ffd83dbSDimitry Andric   case SymbolLookupFlags::RequiredSymbol:
2395ffd83dbSDimitry Andric     return OS << "RequiredSymbol";
2405ffd83dbSDimitry Andric   case SymbolLookupFlags::WeaklyReferencedSymbol:
2415ffd83dbSDimitry Andric     return OS << "WeaklyReferencedSymbol";
2425ffd83dbSDimitry Andric   }
2435ffd83dbSDimitry Andric   llvm_unreachable("Invalid symbol lookup flags");
2445ffd83dbSDimitry Andric }
2455ffd83dbSDimitry Andric 
2465ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS,
2475ffd83dbSDimitry Andric                         const SymbolLookupSet::value_type &KV) {
2485ffd83dbSDimitry Andric   return OS << "(" << KV.first << ", " << KV.second << ")";
2495ffd83dbSDimitry Andric }
2505ffd83dbSDimitry Andric 
2515ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet &LookupSet) {
2525ffd83dbSDimitry Andric   return OS << printSequence(LookupSet, '{', '}',
2535ffd83dbSDimitry Andric                              PrintAll<SymbolLookupSet::value_type>());
2545ffd83dbSDimitry Andric }
2555ffd83dbSDimitry Andric 
2565ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS,
2575ffd83dbSDimitry Andric                         const JITDylibSearchOrder &SearchOrder) {
2585ffd83dbSDimitry Andric   OS << "[";
2595ffd83dbSDimitry Andric   if (!SearchOrder.empty()) {
2605ffd83dbSDimitry Andric     assert(SearchOrder.front().first &&
2615ffd83dbSDimitry Andric            "JITDylibList entries must not be null");
2625ffd83dbSDimitry Andric     OS << " (\"" << SearchOrder.front().first->getName() << "\", "
2635ffd83dbSDimitry Andric        << SearchOrder.begin()->second << ")";
264*fe6060f1SDimitry Andric     for (auto &KV : llvm::drop_begin(SearchOrder)) {
2655ffd83dbSDimitry Andric       assert(KV.first && "JITDylibList entries must not be null");
2665ffd83dbSDimitry Andric       OS << ", (\"" << KV.first->getName() << "\", " << KV.second << ")";
2675ffd83dbSDimitry Andric     }
2685ffd83dbSDimitry Andric   }
2695ffd83dbSDimitry Andric   OS << " ]";
2705ffd83dbSDimitry Andric   return OS;
2715ffd83dbSDimitry Andric }
2725ffd83dbSDimitry Andric 
2735ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases) {
2745ffd83dbSDimitry Andric   OS << "{";
2755ffd83dbSDimitry Andric   for (auto &KV : Aliases)
2765ffd83dbSDimitry Andric     OS << " " << *KV.first << ": " << KV.second.Aliasee << " "
2775ffd83dbSDimitry Andric        << KV.second.AliasFlags;
2785ffd83dbSDimitry Andric   OS << " }";
2795ffd83dbSDimitry Andric   return OS;
2805ffd83dbSDimitry Andric }
2815ffd83dbSDimitry Andric 
2825ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S) {
2835ffd83dbSDimitry Andric   switch (S) {
2845ffd83dbSDimitry Andric   case SymbolState::Invalid:
2855ffd83dbSDimitry Andric     return OS << "Invalid";
2865ffd83dbSDimitry Andric   case SymbolState::NeverSearched:
2875ffd83dbSDimitry Andric     return OS << "Never-Searched";
2885ffd83dbSDimitry Andric   case SymbolState::Materializing:
2895ffd83dbSDimitry Andric     return OS << "Materializing";
2905ffd83dbSDimitry Andric   case SymbolState::Resolved:
2915ffd83dbSDimitry Andric     return OS << "Resolved";
2925ffd83dbSDimitry Andric   case SymbolState::Emitted:
2935ffd83dbSDimitry Andric     return OS << "Emitted";
2945ffd83dbSDimitry Andric   case SymbolState::Ready:
2955ffd83dbSDimitry Andric     return OS << "Ready";
2965ffd83dbSDimitry Andric   }
2975ffd83dbSDimitry Andric   llvm_unreachable("Invalid state");
2985ffd83dbSDimitry Andric }
2995ffd83dbSDimitry Andric 
300480093f4SDimitry Andric DumpObjects::DumpObjects(std::string DumpDir, std::string IdentifierOverride)
301480093f4SDimitry Andric     : DumpDir(std::move(DumpDir)),
302480093f4SDimitry Andric       IdentifierOverride(std::move(IdentifierOverride)) {
303480093f4SDimitry Andric 
304480093f4SDimitry Andric   /// Discard any trailing separators.
305480093f4SDimitry Andric   while (!this->DumpDir.empty() &&
306480093f4SDimitry Andric          sys::path::is_separator(this->DumpDir.back()))
307480093f4SDimitry Andric     this->DumpDir.pop_back();
308480093f4SDimitry Andric }
309480093f4SDimitry Andric 
310480093f4SDimitry Andric Expected<std::unique_ptr<MemoryBuffer>>
311480093f4SDimitry Andric DumpObjects::operator()(std::unique_ptr<MemoryBuffer> Obj) {
312480093f4SDimitry Andric   size_t Idx = 1;
313480093f4SDimitry Andric 
314480093f4SDimitry Andric   std::string DumpPathStem;
315480093f4SDimitry Andric   raw_string_ostream(DumpPathStem)
316480093f4SDimitry Andric       << DumpDir << (DumpDir.empty() ? "" : "/") << getBufferIdentifier(*Obj);
317480093f4SDimitry Andric 
318480093f4SDimitry Andric   std::string DumpPath = DumpPathStem + ".o";
319480093f4SDimitry Andric   while (sys::fs::exists(DumpPath)) {
320480093f4SDimitry Andric     DumpPath.clear();
321480093f4SDimitry Andric     raw_string_ostream(DumpPath) << DumpPathStem << "." << (++Idx) << ".o";
322480093f4SDimitry Andric   }
323480093f4SDimitry Andric 
324480093f4SDimitry Andric   LLVM_DEBUG({
325480093f4SDimitry Andric     dbgs() << "Dumping object buffer [ " << (const void *)Obj->getBufferStart()
326480093f4SDimitry Andric            << " -- " << (const void *)(Obj->getBufferEnd() - 1) << " ] to "
327480093f4SDimitry Andric            << DumpPath << "\n";
328480093f4SDimitry Andric   });
329480093f4SDimitry Andric 
330480093f4SDimitry Andric   std::error_code EC;
331480093f4SDimitry Andric   raw_fd_ostream DumpStream(DumpPath, EC);
332480093f4SDimitry Andric   if (EC)
333480093f4SDimitry Andric     return errorCodeToError(EC);
334480093f4SDimitry Andric   DumpStream.write(Obj->getBufferStart(), Obj->getBufferSize());
335480093f4SDimitry Andric 
336480093f4SDimitry Andric   return std::move(Obj);
337480093f4SDimitry Andric }
338480093f4SDimitry Andric 
339480093f4SDimitry Andric StringRef DumpObjects::getBufferIdentifier(MemoryBuffer &B) {
340480093f4SDimitry Andric   if (!IdentifierOverride.empty())
341480093f4SDimitry Andric     return IdentifierOverride;
342480093f4SDimitry Andric   StringRef Identifier = B.getBufferIdentifier();
343480093f4SDimitry Andric   Identifier.consume_back(".o");
344480093f4SDimitry Andric   return Identifier;
345480093f4SDimitry Andric }
346480093f4SDimitry Andric 
347480093f4SDimitry Andric } // End namespace orc.
348480093f4SDimitry Andric } // End namespace llvm.
349