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 {
operator ()__anond87a13940111::PrintAll475ffd83dbSDimitry Andric bool operator()(const T &E) { return true; }
485ffd83dbSDimitry Andric };
495ffd83dbSDimitry Andric
anyPrintSymbolOptionSet()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
flagsMatchCLOpts(const JITSymbolFlags & Flags)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:
SequencePrinter(const Sequence & S,char OpenSeq,char CloseSeq,Pred ShouldPrint=Pred ())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
printTo(llvm::raw_ostream & OS) const895ffd83dbSDimitry 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>
printSequence(const Sequence & S,char OpenSeq,char CloseSeq,Pred P=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>
operator <<(llvm::raw_ostream & OS,const SequencePrinter<Sequence,Pred> & Printer)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 {
operator ()__anond87a13940111::PrintSymbolFlagsMapElemsMatchingCLOpts1255ffd83dbSDimitry 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 {
operator ()__anond87a13940111::PrintSymbolMapElemsMatchingCLOpts1315ffd83dbSDimitry 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
operator <<(raw_ostream & OS,const SymbolStringPtr & Sym)1415ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym) {
1425ffd83dbSDimitry Andric return OS << *Sym;
1435ffd83dbSDimitry Andric }
1445ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,NonOwningSymbolStringPtr Sym)145*0fca6ea1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, NonOwningSymbolStringPtr Sym) {
146*0fca6ea1SDimitry Andric return OS << *Sym;
147*0fca6ea1SDimitry Andric }
148*0fca6ea1SDimitry Andric
operator <<(raw_ostream & OS,const SymbolNameSet & Symbols)1495ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) {
1505ffd83dbSDimitry Andric return OS << printSequence(Symbols, '{', '}', PrintAll<SymbolStringPtr>());
1515ffd83dbSDimitry Andric }
1525ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const SymbolNameVector & Symbols)1535ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols) {
1545ffd83dbSDimitry Andric return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
1555ffd83dbSDimitry Andric }
1565ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,ArrayRef<SymbolStringPtr> Symbols)1575ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, ArrayRef<SymbolStringPtr> Symbols) {
1585ffd83dbSDimitry Andric return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
1595ffd83dbSDimitry Andric }
1605ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const JITSymbolFlags & Flags)1615ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
1625ffd83dbSDimitry Andric if (Flags.hasError())
1635ffd83dbSDimitry Andric OS << "[*ERROR*]";
1645ffd83dbSDimitry Andric if (Flags.isCallable())
1655ffd83dbSDimitry Andric OS << "[Callable]";
1665ffd83dbSDimitry Andric else
1675ffd83dbSDimitry Andric OS << "[Data]";
1685ffd83dbSDimitry Andric if (Flags.isWeak())
1695ffd83dbSDimitry Andric OS << "[Weak]";
1705ffd83dbSDimitry Andric else if (Flags.isCommon())
1715ffd83dbSDimitry Andric OS << "[Common]";
1725ffd83dbSDimitry Andric
1735ffd83dbSDimitry Andric if (!Flags.isExported())
1745ffd83dbSDimitry Andric OS << "[Hidden]";
1755ffd83dbSDimitry Andric
1765ffd83dbSDimitry Andric return OS;
1775ffd83dbSDimitry Andric }
1785ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const ExecutorSymbolDef & Sym)17906c3fb27SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const ExecutorSymbolDef &Sym) {
18006c3fb27SDimitry Andric return OS << Sym.getAddress() << " " << Sym.getFlags();
1815ffd83dbSDimitry Andric }
1825ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const SymbolFlagsMap::value_type & KV)1835ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV) {
1845ffd83dbSDimitry Andric return OS << "(\"" << KV.first << "\", " << KV.second << ")";
1855ffd83dbSDimitry Andric }
1865ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const SymbolMap::value_type & KV)1875ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) {
1885ffd83dbSDimitry Andric return OS << "(\"" << KV.first << "\": " << KV.second << ")";
1895ffd83dbSDimitry Andric }
1905ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const SymbolFlagsMap & SymbolFlags)1915ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) {
1925ffd83dbSDimitry Andric return OS << printSequence(SymbolFlags, '{', '}',
1935ffd83dbSDimitry Andric PrintSymbolFlagsMapElemsMatchingCLOpts());
1945ffd83dbSDimitry Andric }
1955ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const SymbolMap & Symbols)1965ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) {
1975ffd83dbSDimitry Andric return OS << printSequence(Symbols, '{', '}',
1985ffd83dbSDimitry Andric PrintSymbolMapElemsMatchingCLOpts());
1995ffd83dbSDimitry Andric }
2005ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const SymbolDependenceMap::value_type & KV)2015ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS,
2025ffd83dbSDimitry Andric const SymbolDependenceMap::value_type &KV) {
2035ffd83dbSDimitry Andric return OS << "(" << KV.first->getName() << ", " << KV.second << ")";
2045ffd83dbSDimitry Andric }
2055ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const SymbolDependenceMap & Deps)2065ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) {
2075ffd83dbSDimitry Andric return OS << printSequence(Deps, '{', '}',
2085ffd83dbSDimitry Andric PrintAll<SymbolDependenceMap::value_type>());
2095ffd83dbSDimitry Andric }
2105ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const MaterializationUnit & MU)2115ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU) {
2125ffd83dbSDimitry Andric OS << "MU@" << &MU << " (\"" << MU.getName() << "\"";
2135ffd83dbSDimitry Andric if (anyPrintSymbolOptionSet())
2145ffd83dbSDimitry Andric OS << ", " << MU.getSymbols();
2155ffd83dbSDimitry Andric return OS << ")";
2165ffd83dbSDimitry Andric }
2175ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const LookupKind & K)2185ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K) {
2195ffd83dbSDimitry Andric switch (K) {
2205ffd83dbSDimitry Andric case LookupKind::Static:
2215ffd83dbSDimitry Andric return OS << "Static";
2225ffd83dbSDimitry Andric case LookupKind::DLSym:
2235ffd83dbSDimitry Andric return OS << "DLSym";
2245ffd83dbSDimitry Andric }
2255ffd83dbSDimitry Andric llvm_unreachable("Invalid lookup kind");
2265ffd83dbSDimitry Andric }
2275ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const JITDylibLookupFlags & JDLookupFlags)2285ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS,
2295ffd83dbSDimitry Andric const JITDylibLookupFlags &JDLookupFlags) {
2305ffd83dbSDimitry Andric switch (JDLookupFlags) {
2315ffd83dbSDimitry Andric case JITDylibLookupFlags::MatchExportedSymbolsOnly:
2325ffd83dbSDimitry Andric return OS << "MatchExportedSymbolsOnly";
2335ffd83dbSDimitry Andric case JITDylibLookupFlags::MatchAllSymbols:
2345ffd83dbSDimitry Andric return OS << "MatchAllSymbols";
2355ffd83dbSDimitry Andric }
2365ffd83dbSDimitry Andric llvm_unreachable("Invalid JITDylib lookup flags");
2375ffd83dbSDimitry Andric }
2385ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const SymbolLookupFlags & LookupFlags)2395ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LookupFlags) {
2405ffd83dbSDimitry Andric switch (LookupFlags) {
2415ffd83dbSDimitry Andric case SymbolLookupFlags::RequiredSymbol:
2425ffd83dbSDimitry Andric return OS << "RequiredSymbol";
2435ffd83dbSDimitry Andric case SymbolLookupFlags::WeaklyReferencedSymbol:
2445ffd83dbSDimitry Andric return OS << "WeaklyReferencedSymbol";
2455ffd83dbSDimitry Andric }
2465ffd83dbSDimitry Andric llvm_unreachable("Invalid symbol lookup flags");
2475ffd83dbSDimitry Andric }
2485ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const SymbolLookupSet::value_type & KV)2495ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS,
2505ffd83dbSDimitry Andric const SymbolLookupSet::value_type &KV) {
2515ffd83dbSDimitry Andric return OS << "(" << KV.first << ", " << KV.second << ")";
2525ffd83dbSDimitry Andric }
2535ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const SymbolLookupSet & LookupSet)2545ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet &LookupSet) {
2555ffd83dbSDimitry Andric return OS << printSequence(LookupSet, '{', '}',
2565ffd83dbSDimitry Andric PrintAll<SymbolLookupSet::value_type>());
2575ffd83dbSDimitry Andric }
2585ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const JITDylibSearchOrder & SearchOrder)2595ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS,
2605ffd83dbSDimitry Andric const JITDylibSearchOrder &SearchOrder) {
2615ffd83dbSDimitry Andric OS << "[";
2625ffd83dbSDimitry Andric if (!SearchOrder.empty()) {
2635ffd83dbSDimitry Andric assert(SearchOrder.front().first &&
2645ffd83dbSDimitry Andric "JITDylibList entries must not be null");
2655ffd83dbSDimitry Andric OS << " (\"" << SearchOrder.front().first->getName() << "\", "
2665ffd83dbSDimitry Andric << SearchOrder.begin()->second << ")";
267fe6060f1SDimitry Andric for (auto &KV : llvm::drop_begin(SearchOrder)) {
2685ffd83dbSDimitry Andric assert(KV.first && "JITDylibList entries must not be null");
2695ffd83dbSDimitry Andric OS << ", (\"" << KV.first->getName() << "\", " << KV.second << ")";
2705ffd83dbSDimitry Andric }
2715ffd83dbSDimitry Andric }
2725ffd83dbSDimitry Andric OS << " ]";
2735ffd83dbSDimitry Andric return OS;
2745ffd83dbSDimitry Andric }
2755ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const SymbolAliasMap & Aliases)2765ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases) {
2775ffd83dbSDimitry Andric OS << "{";
2785ffd83dbSDimitry Andric for (auto &KV : Aliases)
2795ffd83dbSDimitry Andric OS << " " << *KV.first << ": " << KV.second.Aliasee << " "
2805ffd83dbSDimitry Andric << KV.second.AliasFlags;
2815ffd83dbSDimitry Andric OS << " }";
2825ffd83dbSDimitry Andric return OS;
2835ffd83dbSDimitry Andric }
2845ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const SymbolState & S)2855ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S) {
2865ffd83dbSDimitry Andric switch (S) {
2875ffd83dbSDimitry Andric case SymbolState::Invalid:
2885ffd83dbSDimitry Andric return OS << "Invalid";
2895ffd83dbSDimitry Andric case SymbolState::NeverSearched:
2905ffd83dbSDimitry Andric return OS << "Never-Searched";
2915ffd83dbSDimitry Andric case SymbolState::Materializing:
2925ffd83dbSDimitry Andric return OS << "Materializing";
2935ffd83dbSDimitry Andric case SymbolState::Resolved:
2945ffd83dbSDimitry Andric return OS << "Resolved";
2955ffd83dbSDimitry Andric case SymbolState::Emitted:
2965ffd83dbSDimitry Andric return OS << "Emitted";
2975ffd83dbSDimitry Andric case SymbolState::Ready:
2985ffd83dbSDimitry Andric return OS << "Ready";
2995ffd83dbSDimitry Andric }
3005ffd83dbSDimitry Andric llvm_unreachable("Invalid state");
3015ffd83dbSDimitry Andric }
3025ffd83dbSDimitry Andric
operator <<(raw_ostream & OS,const SymbolStringPool & SSP)30381ad6265SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPool &SSP) {
30481ad6265SDimitry Andric std::lock_guard<std::mutex> Lock(SSP.PoolMutex);
30506c3fb27SDimitry Andric SmallVector<std::pair<StringRef, int>, 0> Vec;
30681ad6265SDimitry Andric for (auto &KV : SSP.Pool)
30706c3fb27SDimitry Andric Vec.emplace_back(KV.first(), KV.second);
30806c3fb27SDimitry Andric llvm::sort(Vec, less_first());
30906c3fb27SDimitry Andric for (auto &[K, V] : Vec)
31006c3fb27SDimitry Andric OS << K << ": " << V << "\n";
31181ad6265SDimitry Andric return OS;
31281ad6265SDimitry Andric }
31381ad6265SDimitry Andric
DumpObjects(std::string DumpDir,std::string IdentifierOverride)314480093f4SDimitry Andric DumpObjects::DumpObjects(std::string DumpDir, std::string IdentifierOverride)
315480093f4SDimitry Andric : DumpDir(std::move(DumpDir)),
316480093f4SDimitry Andric IdentifierOverride(std::move(IdentifierOverride)) {
317480093f4SDimitry Andric
318480093f4SDimitry Andric /// Discard any trailing separators.
319480093f4SDimitry Andric while (!this->DumpDir.empty() &&
320480093f4SDimitry Andric sys::path::is_separator(this->DumpDir.back()))
321480093f4SDimitry Andric this->DumpDir.pop_back();
322480093f4SDimitry Andric }
323480093f4SDimitry Andric
324480093f4SDimitry Andric Expected<std::unique_ptr<MemoryBuffer>>
operator ()(std::unique_ptr<MemoryBuffer> Obj)325480093f4SDimitry Andric DumpObjects::operator()(std::unique_ptr<MemoryBuffer> Obj) {
326480093f4SDimitry Andric size_t Idx = 1;
327480093f4SDimitry Andric
328480093f4SDimitry Andric std::string DumpPathStem;
329480093f4SDimitry Andric raw_string_ostream(DumpPathStem)
330480093f4SDimitry Andric << DumpDir << (DumpDir.empty() ? "" : "/") << getBufferIdentifier(*Obj);
331480093f4SDimitry Andric
332480093f4SDimitry Andric std::string DumpPath = DumpPathStem + ".o";
333480093f4SDimitry Andric while (sys::fs::exists(DumpPath)) {
334480093f4SDimitry Andric DumpPath.clear();
335480093f4SDimitry Andric raw_string_ostream(DumpPath) << DumpPathStem << "." << (++Idx) << ".o";
336480093f4SDimitry Andric }
337480093f4SDimitry Andric
338480093f4SDimitry Andric LLVM_DEBUG({
339480093f4SDimitry Andric dbgs() << "Dumping object buffer [ " << (const void *)Obj->getBufferStart()
340480093f4SDimitry Andric << " -- " << (const void *)(Obj->getBufferEnd() - 1) << " ] to "
341480093f4SDimitry Andric << DumpPath << "\n";
342480093f4SDimitry Andric });
343480093f4SDimitry Andric
344480093f4SDimitry Andric std::error_code EC;
345480093f4SDimitry Andric raw_fd_ostream DumpStream(DumpPath, EC);
346480093f4SDimitry Andric if (EC)
347480093f4SDimitry Andric return errorCodeToError(EC);
348480093f4SDimitry Andric DumpStream.write(Obj->getBufferStart(), Obj->getBufferSize());
349480093f4SDimitry Andric
350480093f4SDimitry Andric return std::move(Obj);
351480093f4SDimitry Andric }
352480093f4SDimitry Andric
getBufferIdentifier(MemoryBuffer & B)353480093f4SDimitry Andric StringRef DumpObjects::getBufferIdentifier(MemoryBuffer &B) {
354480093f4SDimitry Andric if (!IdentifierOverride.empty())
355480093f4SDimitry Andric return IdentifierOverride;
356480093f4SDimitry Andric StringRef Identifier = B.getBufferIdentifier();
357480093f4SDimitry Andric Identifier.consume_back(".o");
358480093f4SDimitry Andric return Identifier;
359480093f4SDimitry Andric }
360480093f4SDimitry Andric
361480093f4SDimitry Andric } // End namespace orc.
362480093f4SDimitry Andric } // End namespace llvm.
363