1706b4fc4SDimitry Andric //===---------- DebugUtils.cpp - Utilities for debugging ORC JITs ---------===//
2706b4fc4SDimitry Andric //
3706b4fc4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4706b4fc4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5706b4fc4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6706b4fc4SDimitry Andric //
7706b4fc4SDimitry Andric //===----------------------------------------------------------------------===//
8706b4fc4SDimitry Andric
9706b4fc4SDimitry Andric #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
10cfca06d7SDimitry Andric
11cfca06d7SDimitry Andric #include "llvm/ExecutionEngine/Orc/Core.h"
12cfca06d7SDimitry Andric #include "llvm/Support/CommandLine.h"
13706b4fc4SDimitry Andric #include "llvm/Support/Debug.h"
14cfca06d7SDimitry Andric #include "llvm/Support/FileSystem.h"
15cfca06d7SDimitry Andric #include "llvm/Support/Format.h"
16706b4fc4SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
17706b4fc4SDimitry Andric #include "llvm/Support/Path.h"
18706b4fc4SDimitry Andric #include "llvm/Support/raw_ostream.h"
19706b4fc4SDimitry Andric
20706b4fc4SDimitry Andric #define DEBUG_TYPE "orc"
21706b4fc4SDimitry Andric
22cfca06d7SDimitry Andric using namespace llvm;
23cfca06d7SDimitry Andric
24cfca06d7SDimitry Andric namespace {
25cfca06d7SDimitry Andric
26cfca06d7SDimitry Andric #ifndef NDEBUG
27cfca06d7SDimitry Andric
28cfca06d7SDimitry Andric cl::opt<bool> PrintHidden("debug-orc-print-hidden", cl::init(true),
29cfca06d7SDimitry Andric cl::desc("debug print hidden symbols defined by "
30cfca06d7SDimitry Andric "materialization units"),
31cfca06d7SDimitry Andric cl::Hidden);
32cfca06d7SDimitry Andric
33cfca06d7SDimitry Andric cl::opt<bool> PrintCallable("debug-orc-print-callable", cl::init(true),
34cfca06d7SDimitry Andric cl::desc("debug print callable symbols defined by "
35cfca06d7SDimitry Andric "materialization units"),
36cfca06d7SDimitry Andric cl::Hidden);
37cfca06d7SDimitry Andric
38cfca06d7SDimitry Andric cl::opt<bool> PrintData("debug-orc-print-data", cl::init(true),
39cfca06d7SDimitry Andric cl::desc("debug print data symbols defined by "
40cfca06d7SDimitry Andric "materialization units"),
41cfca06d7SDimitry Andric cl::Hidden);
42cfca06d7SDimitry Andric
43cfca06d7SDimitry Andric #endif // NDEBUG
44cfca06d7SDimitry Andric
45cfca06d7SDimitry Andric // SetPrinter predicate that prints every element.
46cfca06d7SDimitry Andric template <typename T> struct PrintAll {
operator ()__anon7fd272e90111::PrintAll47cfca06d7SDimitry Andric bool operator()(const T &E) { return true; }
48cfca06d7SDimitry Andric };
49cfca06d7SDimitry Andric
anyPrintSymbolOptionSet()50cfca06d7SDimitry Andric bool anyPrintSymbolOptionSet() {
51cfca06d7SDimitry Andric #ifndef NDEBUG
52cfca06d7SDimitry Andric return PrintHidden || PrintCallable || PrintData;
53cfca06d7SDimitry Andric #else
54cfca06d7SDimitry Andric return false;
55cfca06d7SDimitry Andric #endif // NDEBUG
56cfca06d7SDimitry Andric }
57cfca06d7SDimitry Andric
flagsMatchCLOpts(const JITSymbolFlags & Flags)58cfca06d7SDimitry Andric bool flagsMatchCLOpts(const JITSymbolFlags &Flags) {
59cfca06d7SDimitry Andric #ifndef NDEBUG
60cfca06d7SDimitry Andric // Bail out early if this is a hidden symbol and we're not printing hiddens.
61cfca06d7SDimitry Andric if (!PrintHidden && !Flags.isExported())
62cfca06d7SDimitry Andric return false;
63cfca06d7SDimitry Andric
64cfca06d7SDimitry Andric // Return true if this is callable and we're printing callables.
65cfca06d7SDimitry Andric if (PrintCallable && Flags.isCallable())
66cfca06d7SDimitry Andric return true;
67cfca06d7SDimitry Andric
68cfca06d7SDimitry Andric // Return true if this is data and we're printing data.
69cfca06d7SDimitry Andric if (PrintData && !Flags.isCallable())
70cfca06d7SDimitry Andric return true;
71cfca06d7SDimitry Andric
72cfca06d7SDimitry Andric // otherwise return false.
73cfca06d7SDimitry Andric return false;
74cfca06d7SDimitry Andric #else
75cfca06d7SDimitry Andric return false;
76cfca06d7SDimitry Andric #endif // NDEBUG
77cfca06d7SDimitry Andric }
78cfca06d7SDimitry Andric
79cfca06d7SDimitry Andric // Prints a sequence of items, filtered by an user-supplied predicate.
80cfca06d7SDimitry Andric template <typename Sequence,
81cfca06d7SDimitry Andric typename Pred = PrintAll<typename Sequence::value_type>>
82cfca06d7SDimitry Andric class SequencePrinter {
83cfca06d7SDimitry Andric public:
SequencePrinter(const Sequence & S,char OpenSeq,char CloseSeq,Pred ShouldPrint=Pred ())84cfca06d7SDimitry Andric SequencePrinter(const Sequence &S, char OpenSeq, char CloseSeq,
85cfca06d7SDimitry Andric Pred ShouldPrint = Pred())
86cfca06d7SDimitry Andric : S(S), OpenSeq(OpenSeq), CloseSeq(CloseSeq),
87cfca06d7SDimitry Andric ShouldPrint(std::move(ShouldPrint)) {}
88cfca06d7SDimitry Andric
printTo(llvm::raw_ostream & OS) const89cfca06d7SDimitry Andric void printTo(llvm::raw_ostream &OS) const {
90cfca06d7SDimitry Andric bool PrintComma = false;
91cfca06d7SDimitry Andric OS << OpenSeq;
92cfca06d7SDimitry Andric for (auto &E : S) {
93cfca06d7SDimitry Andric if (ShouldPrint(E)) {
94cfca06d7SDimitry Andric if (PrintComma)
95cfca06d7SDimitry Andric OS << ',';
96cfca06d7SDimitry Andric OS << ' ' << E;
97cfca06d7SDimitry Andric PrintComma = true;
98cfca06d7SDimitry Andric }
99cfca06d7SDimitry Andric }
100cfca06d7SDimitry Andric OS << ' ' << CloseSeq;
101cfca06d7SDimitry Andric }
102cfca06d7SDimitry Andric
103cfca06d7SDimitry Andric private:
104cfca06d7SDimitry Andric const Sequence &S;
105cfca06d7SDimitry Andric char OpenSeq;
106cfca06d7SDimitry Andric char CloseSeq;
107cfca06d7SDimitry Andric mutable Pred ShouldPrint;
108cfca06d7SDimitry Andric };
109cfca06d7SDimitry Andric
110cfca06d7SDimitry Andric template <typename Sequence, typename Pred>
printSequence(const Sequence & S,char OpenSeq,char CloseSeq,Pred P=Pred ())111cfca06d7SDimitry Andric SequencePrinter<Sequence, Pred> printSequence(const Sequence &S, char OpenSeq,
112cfca06d7SDimitry Andric char CloseSeq, Pred P = Pred()) {
113cfca06d7SDimitry Andric return SequencePrinter<Sequence, Pred>(S, OpenSeq, CloseSeq, std::move(P));
114cfca06d7SDimitry Andric }
115cfca06d7SDimitry Andric
116cfca06d7SDimitry Andric // Render a SequencePrinter by delegating to its printTo method.
117cfca06d7SDimitry Andric template <typename Sequence, typename Pred>
operator <<(llvm::raw_ostream & OS,const SequencePrinter<Sequence,Pred> & Printer)118cfca06d7SDimitry Andric llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
119cfca06d7SDimitry Andric const SequencePrinter<Sequence, Pred> &Printer) {
120cfca06d7SDimitry Andric Printer.printTo(OS);
121cfca06d7SDimitry Andric return OS;
122cfca06d7SDimitry Andric }
123cfca06d7SDimitry Andric
124cfca06d7SDimitry Andric struct PrintSymbolFlagsMapElemsMatchingCLOpts {
operator ()__anon7fd272e90111::PrintSymbolFlagsMapElemsMatchingCLOpts125cfca06d7SDimitry Andric bool operator()(const orc::SymbolFlagsMap::value_type &KV) {
126cfca06d7SDimitry Andric return flagsMatchCLOpts(KV.second);
127cfca06d7SDimitry Andric }
128cfca06d7SDimitry Andric };
129cfca06d7SDimitry Andric
130cfca06d7SDimitry Andric struct PrintSymbolMapElemsMatchingCLOpts {
operator ()__anon7fd272e90111::PrintSymbolMapElemsMatchingCLOpts131cfca06d7SDimitry Andric bool operator()(const orc::SymbolMap::value_type &KV) {
132cfca06d7SDimitry Andric return flagsMatchCLOpts(KV.second.getFlags());
133cfca06d7SDimitry Andric }
134cfca06d7SDimitry Andric };
135cfca06d7SDimitry Andric
136cfca06d7SDimitry Andric } // end anonymous namespace
137cfca06d7SDimitry Andric
138706b4fc4SDimitry Andric namespace llvm {
139706b4fc4SDimitry Andric namespace orc {
140706b4fc4SDimitry Andric
operator <<(raw_ostream & OS,const SymbolStringPtr & Sym)141cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym) {
142cfca06d7SDimitry Andric return OS << *Sym;
143cfca06d7SDimitry Andric }
144cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,NonOwningSymbolStringPtr Sym)145ac9a064cSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, NonOwningSymbolStringPtr Sym) {
146ac9a064cSDimitry Andric return OS << *Sym;
147ac9a064cSDimitry Andric }
148ac9a064cSDimitry Andric
operator <<(raw_ostream & OS,const SymbolNameSet & Symbols)149cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) {
150cfca06d7SDimitry Andric return OS << printSequence(Symbols, '{', '}', PrintAll<SymbolStringPtr>());
151cfca06d7SDimitry Andric }
152cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const SymbolNameVector & Symbols)153cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols) {
154cfca06d7SDimitry Andric return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
155cfca06d7SDimitry Andric }
156cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,ArrayRef<SymbolStringPtr> Symbols)157cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, ArrayRef<SymbolStringPtr> Symbols) {
158cfca06d7SDimitry Andric return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
159cfca06d7SDimitry Andric }
160cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const JITSymbolFlags & Flags)161cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
162cfca06d7SDimitry Andric if (Flags.hasError())
163cfca06d7SDimitry Andric OS << "[*ERROR*]";
164cfca06d7SDimitry Andric if (Flags.isCallable())
165cfca06d7SDimitry Andric OS << "[Callable]";
166cfca06d7SDimitry Andric else
167cfca06d7SDimitry Andric OS << "[Data]";
168cfca06d7SDimitry Andric if (Flags.isWeak())
169cfca06d7SDimitry Andric OS << "[Weak]";
170cfca06d7SDimitry Andric else if (Flags.isCommon())
171cfca06d7SDimitry Andric OS << "[Common]";
172cfca06d7SDimitry Andric
173cfca06d7SDimitry Andric if (!Flags.isExported())
174cfca06d7SDimitry Andric OS << "[Hidden]";
175cfca06d7SDimitry Andric
176cfca06d7SDimitry Andric return OS;
177cfca06d7SDimitry Andric }
178cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const ExecutorSymbolDef & Sym)1797fa27ce4SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const ExecutorSymbolDef &Sym) {
1807fa27ce4SDimitry Andric return OS << Sym.getAddress() << " " << Sym.getFlags();
181cfca06d7SDimitry Andric }
182cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const SymbolFlagsMap::value_type & KV)183cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV) {
184cfca06d7SDimitry Andric return OS << "(\"" << KV.first << "\", " << KV.second << ")";
185cfca06d7SDimitry Andric }
186cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const SymbolMap::value_type & KV)187cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) {
188cfca06d7SDimitry Andric return OS << "(\"" << KV.first << "\": " << KV.second << ")";
189cfca06d7SDimitry Andric }
190cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const SymbolFlagsMap & SymbolFlags)191cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) {
192cfca06d7SDimitry Andric return OS << printSequence(SymbolFlags, '{', '}',
193cfca06d7SDimitry Andric PrintSymbolFlagsMapElemsMatchingCLOpts());
194cfca06d7SDimitry Andric }
195cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const SymbolMap & Symbols)196cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) {
197cfca06d7SDimitry Andric return OS << printSequence(Symbols, '{', '}',
198cfca06d7SDimitry Andric PrintSymbolMapElemsMatchingCLOpts());
199cfca06d7SDimitry Andric }
200cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const SymbolDependenceMap::value_type & KV)201cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS,
202cfca06d7SDimitry Andric const SymbolDependenceMap::value_type &KV) {
203cfca06d7SDimitry Andric return OS << "(" << KV.first->getName() << ", " << KV.second << ")";
204cfca06d7SDimitry Andric }
205cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const SymbolDependenceMap & Deps)206cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) {
207cfca06d7SDimitry Andric return OS << printSequence(Deps, '{', '}',
208cfca06d7SDimitry Andric PrintAll<SymbolDependenceMap::value_type>());
209cfca06d7SDimitry Andric }
210cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const MaterializationUnit & MU)211cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU) {
212cfca06d7SDimitry Andric OS << "MU@" << &MU << " (\"" << MU.getName() << "\"";
213cfca06d7SDimitry Andric if (anyPrintSymbolOptionSet())
214cfca06d7SDimitry Andric OS << ", " << MU.getSymbols();
215cfca06d7SDimitry Andric return OS << ")";
216cfca06d7SDimitry Andric }
217cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const LookupKind & K)218cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K) {
219cfca06d7SDimitry Andric switch (K) {
220cfca06d7SDimitry Andric case LookupKind::Static:
221cfca06d7SDimitry Andric return OS << "Static";
222cfca06d7SDimitry Andric case LookupKind::DLSym:
223cfca06d7SDimitry Andric return OS << "DLSym";
224cfca06d7SDimitry Andric }
225cfca06d7SDimitry Andric llvm_unreachable("Invalid lookup kind");
226cfca06d7SDimitry Andric }
227cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const JITDylibLookupFlags & JDLookupFlags)228cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS,
229cfca06d7SDimitry Andric const JITDylibLookupFlags &JDLookupFlags) {
230cfca06d7SDimitry Andric switch (JDLookupFlags) {
231cfca06d7SDimitry Andric case JITDylibLookupFlags::MatchExportedSymbolsOnly:
232cfca06d7SDimitry Andric return OS << "MatchExportedSymbolsOnly";
233cfca06d7SDimitry Andric case JITDylibLookupFlags::MatchAllSymbols:
234cfca06d7SDimitry Andric return OS << "MatchAllSymbols";
235cfca06d7SDimitry Andric }
236cfca06d7SDimitry Andric llvm_unreachable("Invalid JITDylib lookup flags");
237cfca06d7SDimitry Andric }
238cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const SymbolLookupFlags & LookupFlags)239cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LookupFlags) {
240cfca06d7SDimitry Andric switch (LookupFlags) {
241cfca06d7SDimitry Andric case SymbolLookupFlags::RequiredSymbol:
242cfca06d7SDimitry Andric return OS << "RequiredSymbol";
243cfca06d7SDimitry Andric case SymbolLookupFlags::WeaklyReferencedSymbol:
244cfca06d7SDimitry Andric return OS << "WeaklyReferencedSymbol";
245cfca06d7SDimitry Andric }
246cfca06d7SDimitry Andric llvm_unreachable("Invalid symbol lookup flags");
247cfca06d7SDimitry Andric }
248cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const SymbolLookupSet::value_type & KV)249cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS,
250cfca06d7SDimitry Andric const SymbolLookupSet::value_type &KV) {
251cfca06d7SDimitry Andric return OS << "(" << KV.first << ", " << KV.second << ")";
252cfca06d7SDimitry Andric }
253cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const SymbolLookupSet & LookupSet)254cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet &LookupSet) {
255cfca06d7SDimitry Andric return OS << printSequence(LookupSet, '{', '}',
256cfca06d7SDimitry Andric PrintAll<SymbolLookupSet::value_type>());
257cfca06d7SDimitry Andric }
258cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const JITDylibSearchOrder & SearchOrder)259cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS,
260cfca06d7SDimitry Andric const JITDylibSearchOrder &SearchOrder) {
261cfca06d7SDimitry Andric OS << "[";
262cfca06d7SDimitry Andric if (!SearchOrder.empty()) {
263cfca06d7SDimitry Andric assert(SearchOrder.front().first &&
264cfca06d7SDimitry Andric "JITDylibList entries must not be null");
265cfca06d7SDimitry Andric OS << " (\"" << SearchOrder.front().first->getName() << "\", "
266cfca06d7SDimitry Andric << SearchOrder.begin()->second << ")";
267344a3780SDimitry Andric for (auto &KV : llvm::drop_begin(SearchOrder)) {
268cfca06d7SDimitry Andric assert(KV.first && "JITDylibList entries must not be null");
269cfca06d7SDimitry Andric OS << ", (\"" << KV.first->getName() << "\", " << KV.second << ")";
270cfca06d7SDimitry Andric }
271cfca06d7SDimitry Andric }
272cfca06d7SDimitry Andric OS << " ]";
273cfca06d7SDimitry Andric return OS;
274cfca06d7SDimitry Andric }
275cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const SymbolAliasMap & Aliases)276cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases) {
277cfca06d7SDimitry Andric OS << "{";
278cfca06d7SDimitry Andric for (auto &KV : Aliases)
279cfca06d7SDimitry Andric OS << " " << *KV.first << ": " << KV.second.Aliasee << " "
280cfca06d7SDimitry Andric << KV.second.AliasFlags;
281cfca06d7SDimitry Andric OS << " }";
282cfca06d7SDimitry Andric return OS;
283cfca06d7SDimitry Andric }
284cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const SymbolState & S)285cfca06d7SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S) {
286cfca06d7SDimitry Andric switch (S) {
287cfca06d7SDimitry Andric case SymbolState::Invalid:
288cfca06d7SDimitry Andric return OS << "Invalid";
289cfca06d7SDimitry Andric case SymbolState::NeverSearched:
290cfca06d7SDimitry Andric return OS << "Never-Searched";
291cfca06d7SDimitry Andric case SymbolState::Materializing:
292cfca06d7SDimitry Andric return OS << "Materializing";
293cfca06d7SDimitry Andric case SymbolState::Resolved:
294cfca06d7SDimitry Andric return OS << "Resolved";
295cfca06d7SDimitry Andric case SymbolState::Emitted:
296cfca06d7SDimitry Andric return OS << "Emitted";
297cfca06d7SDimitry Andric case SymbolState::Ready:
298cfca06d7SDimitry Andric return OS << "Ready";
299cfca06d7SDimitry Andric }
300cfca06d7SDimitry Andric llvm_unreachable("Invalid state");
301cfca06d7SDimitry Andric }
302cfca06d7SDimitry Andric
operator <<(raw_ostream & OS,const SymbolStringPool & SSP)303145449b1SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPool &SSP) {
304145449b1SDimitry Andric std::lock_guard<std::mutex> Lock(SSP.PoolMutex);
3057fa27ce4SDimitry Andric SmallVector<std::pair<StringRef, int>, 0> Vec;
306145449b1SDimitry Andric for (auto &KV : SSP.Pool)
3077fa27ce4SDimitry Andric Vec.emplace_back(KV.first(), KV.second);
3087fa27ce4SDimitry Andric llvm::sort(Vec, less_first());
3097fa27ce4SDimitry Andric for (auto &[K, V] : Vec)
3107fa27ce4SDimitry Andric OS << K << ": " << V << "\n";
311145449b1SDimitry Andric return OS;
312145449b1SDimitry Andric }
313145449b1SDimitry Andric
DumpObjects(std::string DumpDir,std::string IdentifierOverride)314706b4fc4SDimitry Andric DumpObjects::DumpObjects(std::string DumpDir, std::string IdentifierOverride)
315706b4fc4SDimitry Andric : DumpDir(std::move(DumpDir)),
316706b4fc4SDimitry Andric IdentifierOverride(std::move(IdentifierOverride)) {
317706b4fc4SDimitry Andric
318706b4fc4SDimitry Andric /// Discard any trailing separators.
319706b4fc4SDimitry Andric while (!this->DumpDir.empty() &&
320706b4fc4SDimitry Andric sys::path::is_separator(this->DumpDir.back()))
321706b4fc4SDimitry Andric this->DumpDir.pop_back();
322706b4fc4SDimitry Andric }
323706b4fc4SDimitry Andric
324706b4fc4SDimitry Andric Expected<std::unique_ptr<MemoryBuffer>>
operator ()(std::unique_ptr<MemoryBuffer> Obj)325706b4fc4SDimitry Andric DumpObjects::operator()(std::unique_ptr<MemoryBuffer> Obj) {
326706b4fc4SDimitry Andric size_t Idx = 1;
327706b4fc4SDimitry Andric
328706b4fc4SDimitry Andric std::string DumpPathStem;
329706b4fc4SDimitry Andric raw_string_ostream(DumpPathStem)
330706b4fc4SDimitry Andric << DumpDir << (DumpDir.empty() ? "" : "/") << getBufferIdentifier(*Obj);
331706b4fc4SDimitry Andric
332706b4fc4SDimitry Andric std::string DumpPath = DumpPathStem + ".o";
333706b4fc4SDimitry Andric while (sys::fs::exists(DumpPath)) {
334706b4fc4SDimitry Andric DumpPath.clear();
335706b4fc4SDimitry Andric raw_string_ostream(DumpPath) << DumpPathStem << "." << (++Idx) << ".o";
336706b4fc4SDimitry Andric }
337706b4fc4SDimitry Andric
338706b4fc4SDimitry Andric LLVM_DEBUG({
339706b4fc4SDimitry Andric dbgs() << "Dumping object buffer [ " << (const void *)Obj->getBufferStart()
340706b4fc4SDimitry Andric << " -- " << (const void *)(Obj->getBufferEnd() - 1) << " ] to "
341706b4fc4SDimitry Andric << DumpPath << "\n";
342706b4fc4SDimitry Andric });
343706b4fc4SDimitry Andric
344706b4fc4SDimitry Andric std::error_code EC;
345706b4fc4SDimitry Andric raw_fd_ostream DumpStream(DumpPath, EC);
346706b4fc4SDimitry Andric if (EC)
347706b4fc4SDimitry Andric return errorCodeToError(EC);
348706b4fc4SDimitry Andric DumpStream.write(Obj->getBufferStart(), Obj->getBufferSize());
349706b4fc4SDimitry Andric
350706b4fc4SDimitry Andric return std::move(Obj);
351706b4fc4SDimitry Andric }
352706b4fc4SDimitry Andric
getBufferIdentifier(MemoryBuffer & B)353706b4fc4SDimitry Andric StringRef DumpObjects::getBufferIdentifier(MemoryBuffer &B) {
354706b4fc4SDimitry Andric if (!IdentifierOverride.empty())
355706b4fc4SDimitry Andric return IdentifierOverride;
356706b4fc4SDimitry Andric StringRef Identifier = B.getBufferIdentifier();
357706b4fc4SDimitry Andric Identifier.consume_back(".o");
358706b4fc4SDimitry Andric return Identifier;
359706b4fc4SDimitry Andric }
360706b4fc4SDimitry Andric
361706b4fc4SDimitry Andric } // End namespace orc.
362706b4fc4SDimitry Andric } // End namespace llvm.
363