LLVM  15.0.0git
DebugUtils.cpp
Go to the documentation of this file.
1 //===---------- DebugUtils.cpp - Utilities for debugging ORC JITs ---------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 
13 #include "llvm/Support/Debug.h"
15 #include "llvm/Support/Format.h"
17 #include "llvm/Support/Path.h"
19 
20 #define DEBUG_TYPE "orc"
21 
22 using namespace llvm;
23 
24 namespace {
25 
26 #ifndef NDEBUG
27 
28 cl::opt<bool> PrintHidden("debug-orc-print-hidden", cl::init(true),
29  cl::desc("debug print hidden symbols defined by "
30  "materialization units"),
31  cl::Hidden);
32 
33 cl::opt<bool> PrintCallable("debug-orc-print-callable", cl::init(true),
34  cl::desc("debug print callable symbols defined by "
35  "materialization units"),
36  cl::Hidden);
37 
38 cl::opt<bool> PrintData("debug-orc-print-data", cl::init(true),
39  cl::desc("debug print data symbols defined by "
40  "materialization units"),
41  cl::Hidden);
42 
43 #endif // NDEBUG
44 
45 // SetPrinter predicate that prints every element.
46 template <typename T> struct PrintAll {
47  bool operator()(const T &E) { return true; }
48 };
49 
50 bool anyPrintSymbolOptionSet() {
51 #ifndef NDEBUG
52  return PrintHidden || PrintCallable || PrintData;
53 #else
54  return false;
55 #endif // NDEBUG
56 }
57 
58 bool flagsMatchCLOpts(const JITSymbolFlags &Flags) {
59 #ifndef NDEBUG
60  // Bail out early if this is a hidden symbol and we're not printing hiddens.
61  if (!PrintHidden && !Flags.isExported())
62  return false;
63 
64  // Return true if this is callable and we're printing callables.
65  if (PrintCallable && Flags.isCallable())
66  return true;
67 
68  // Return true if this is data and we're printing data.
69  if (PrintData && !Flags.isCallable())
70  return true;
71 
72  // otherwise return false.
73  return false;
74 #else
75  return false;
76 #endif // NDEBUG
77 }
78 
79 // Prints a sequence of items, filtered by an user-supplied predicate.
80 template <typename Sequence,
81  typename Pred = PrintAll<typename Sequence::value_type>>
82 class SequencePrinter {
83 public:
84  SequencePrinter(const Sequence &S, char OpenSeq, char CloseSeq,
85  Pred ShouldPrint = Pred())
86  : S(S), OpenSeq(OpenSeq), CloseSeq(CloseSeq),
87  ShouldPrint(std::move(ShouldPrint)) {}
88 
89  void printTo(llvm::raw_ostream &OS) const {
90  bool PrintComma = false;
91  OS << OpenSeq;
92  for (auto &E : S) {
93  if (ShouldPrint(E)) {
94  if (PrintComma)
95  OS << ',';
96  OS << ' ' << E;
97  PrintComma = true;
98  }
99  }
100  OS << ' ' << CloseSeq;
101  }
102 
103 private:
104  const Sequence &S;
105  char OpenSeq;
106  char CloseSeq;
107  mutable Pred ShouldPrint;
108 };
109 
110 template <typename Sequence, typename Pred>
111 SequencePrinter<Sequence, Pred> printSequence(const Sequence &S, char OpenSeq,
112  char CloseSeq, Pred P = Pred()) {
113  return SequencePrinter<Sequence, Pred>(S, OpenSeq, CloseSeq, std::move(P));
114 }
115 
116 // Render a SequencePrinter by delegating to its printTo method.
117 template <typename Sequence, typename Pred>
119  const SequencePrinter<Sequence, Pred> &Printer) {
120  Printer.printTo(OS);
121  return OS;
122 }
123 
124 struct PrintSymbolFlagsMapElemsMatchingCLOpts {
125  bool operator()(const orc::SymbolFlagsMap::value_type &KV) {
126  return flagsMatchCLOpts(KV.second);
127  }
128 };
129 
130 struct PrintSymbolMapElemsMatchingCLOpts {
131  bool operator()(const orc::SymbolMap::value_type &KV) {
132  return flagsMatchCLOpts(KV.second.getFlags());
133  }
134 };
135 
136 } // end anonymous namespace
137 
138 namespace llvm {
139 namespace orc {
140 
142  return OS << *Sym;
143 }
144 
146  return OS << printSequence(Symbols, '{', '}', PrintAll<SymbolStringPtr>());
147 }
148 
150  return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
151 }
152 
154  return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
155 }
156 
158  if (Flags.hasError())
159  OS << "[*ERROR*]";
160  if (Flags.isCallable())
161  OS << "[Callable]";
162  else
163  OS << "[Data]";
164  if (Flags.isWeak())
165  OS << "[Weak]";
166  else if (Flags.isCommon())
167  OS << "[Common]";
168 
169  if (!Flags.isExported())
170  OS << "[Hidden]";
171 
172  return OS;
173 }
174 
176  return OS << format("0x%016" PRIx64, Sym.getAddress()) << " "
177  << Sym.getFlags();
178 }
179 
181  return OS << "(\"" << KV.first << "\", " << KV.second << ")";
182 }
183 
185  return OS << "(\"" << KV.first << "\": " << KV.second << ")";
186 }
187 
189  return OS << printSequence(SymbolFlags, '{', '}',
190  PrintSymbolFlagsMapElemsMatchingCLOpts());
191 }
192 
193 raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) {
194  return OS << printSequence(Symbols, '{', '}',
195  PrintSymbolMapElemsMatchingCLOpts());
196 }
197 
200  return OS << "(" << KV.first->getName() << ", " << KV.second << ")";
201 }
202 
204  return OS << printSequence(Deps, '{', '}',
205  PrintAll<SymbolDependenceMap::value_type>());
206 }
207 
209  OS << "MU@" << &MU << " (\"" << MU.getName() << "\"";
210  if (anyPrintSymbolOptionSet())
211  OS << ", " << MU.getSymbols();
212  return OS << ")";
213 }
214 
216  switch (K) {
217  case LookupKind::Static:
218  return OS << "Static";
219  case LookupKind::DLSym:
220  return OS << "DLSym";
221  }
222  llvm_unreachable("Invalid lookup kind");
223 }
224 
226  const JITDylibLookupFlags &JDLookupFlags) {
227  switch (JDLookupFlags) {
229  return OS << "MatchExportedSymbolsOnly";
231  return OS << "MatchAllSymbols";
232  }
233  llvm_unreachable("Invalid JITDylib lookup flags");
234 }
235 
237  switch (LookupFlags) {
239  return OS << "RequiredSymbol";
241  return OS << "WeaklyReferencedSymbol";
242  }
243  llvm_unreachable("Invalid symbol lookup flags");
244 }
245 
247  const SymbolLookupSet::value_type &KV) {
248  return OS << "(" << KV.first << ", " << KV.second << ")";
249 }
250 
252  return OS << printSequence(LookupSet, '{', '}',
253  PrintAll<SymbolLookupSet::value_type>());
254 }
255 
257  const JITDylibSearchOrder &SearchOrder) {
258  OS << "[";
259  if (!SearchOrder.empty()) {
260  assert(SearchOrder.front().first &&
261  "JITDylibList entries must not be null");
262  OS << " (\"" << SearchOrder.front().first->getName() << "\", "
263  << SearchOrder.begin()->second << ")";
264  for (auto &KV : llvm::drop_begin(SearchOrder)) {
265  assert(KV.first && "JITDylibList entries must not be null");
266  OS << ", (\"" << KV.first->getName() << "\", " << KV.second << ")";
267  }
268  }
269  OS << " ]";
270  return OS;
271 }
272 
274  OS << "{";
275  for (auto &KV : Aliases)
276  OS << " " << *KV.first << ": " << KV.second.Aliasee << " "
277  << KV.second.AliasFlags;
278  OS << " }";
279  return OS;
280 }
281 
283  switch (S) {
285  return OS << "Invalid";
287  return OS << "Never-Searched";
289  return OS << "Materializing";
291  return OS << "Resolved";
293  return OS << "Emitted";
294  case SymbolState::Ready:
295  return OS << "Ready";
296  }
297  llvm_unreachable("Invalid state");
298 }
299 
301  std::lock_guard<std::mutex> Lock(SSP.PoolMutex);
302  for (auto &KV : SSP.Pool)
303  OS << KV.first() << ": " << KV.second << "\n";
304  return OS;
305 }
306 
307 DumpObjects::DumpObjects(std::string DumpDir, std::string IdentifierOverride)
308  : DumpDir(std::move(DumpDir)),
309  IdentifierOverride(std::move(IdentifierOverride)) {
310 
311  /// Discard any trailing separators.
312  while (!this->DumpDir.empty() &&
313  sys::path::is_separator(this->DumpDir.back()))
314  this->DumpDir.pop_back();
315 }
316 
318 DumpObjects::operator()(std::unique_ptr<MemoryBuffer> Obj) {
319  size_t Idx = 1;
320 
321  std::string DumpPathStem;
322  raw_string_ostream(DumpPathStem)
323  << DumpDir << (DumpDir.empty() ? "" : "/") << getBufferIdentifier(*Obj);
324 
325  std::string DumpPath = DumpPathStem + ".o";
326  while (sys::fs::exists(DumpPath)) {
327  DumpPath.clear();
328  raw_string_ostream(DumpPath) << DumpPathStem << "." << (++Idx) << ".o";
329  }
330 
331  LLVM_DEBUG({
332  dbgs() << "Dumping object buffer [ " << (const void *)Obj->getBufferStart()
333  << " -- " << (const void *)(Obj->getBufferEnd() - 1) << " ] to "
334  << DumpPath << "\n";
335  });
336 
337  std::error_code EC;
338  raw_fd_ostream DumpStream(DumpPath, EC);
339  if (EC)
340  return errorCodeToError(EC);
341  DumpStream.write(Obj->getBufferStart(), Obj->getBufferSize());
342 
343  return std::move(Obj);
344 }
345 
346 StringRef DumpObjects::getBufferIdentifier(MemoryBuffer &B) {
347  if (!IdentifierOverride.empty())
348  return IdentifierOverride;
349  StringRef Identifier = B.getBufferIdentifier();
350  Identifier.consume_back(".o");
351  return Identifier;
352 }
353 
354 } // End namespace orc.
355 } // End namespace llvm.
MemoryBuffer.h
llvm::orc::operator<<
raw_ostream & operator<<(raw_ostream &OS, const SymbolStringPtr &Sym)
Render a SymbolStringPtr.
Definition: DebugUtils.cpp:141
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::objcarc::Sequence
Sequence
Definition: PtrState.h:41
llvm::drop_begin
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition: STLExtras.h:280
llvm::orc::SymbolState::Materializing
@ Materializing
Added to the symbol table, never queried.
FileSystem.h
T
llvm::orc::DumpObjects::DumpObjects
DumpObjects(std::string DumpDir="", std::string IdentifierOverride="")
Construct a DumpObjects transform that will dump objects to disk.
Definition: DebugUtils.cpp:307
P
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
Definition: README-SSE.txt:411
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:632
Path.h
llvm::orc::SymbolLookupSet
A set of symbols to look up, each associated with a SymbolLookupFlags value.
Definition: Core.h:175
llvm::orc::LookupKind::Static
@ Static
llvm::orc::SymbolStringPtr
Pointer to a pooled string representing a symbol name.
Definition: SymbolStringPool.h:57
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:139
llvm::orc::SymbolState::Invalid
@ Invalid
llvm::orc::DumpObjects::operator()
Expected< std::unique_ptr< MemoryBuffer > > operator()(std::unique_ptr< MemoryBuffer > Obj)
Dumps the given buffer to disk.
Definition: DebugUtils.cpp:318
llvm::JITSymbolFlags::isExported
bool isExported() const
Returns true if the Exported flag is set.
Definition: JITSymbol.h:144
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
llvm::JITSymbolFlags::hasError
bool hasError() const
Return true if there was an error retrieving this symbol.
Definition: JITSymbol.h:124
Format.h
llvm::orc::LookupKind
LookupKind
Describes the kind of lookup being performed.
Definition: Core.h:149
llvm::JITSymbolFlags
Flags for symbols in the JIT.
Definition: JITSymbol.h:74
llvm::MachO::SymbolFlags
SymbolFlags
Symbol flags.
Definition: Symbol.h:24
llvm::orc::MaterializationUnit
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group,...
Definition: Core.h:665
llvm::MemoryBuffer
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:50
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::JITEvaluatedSymbol
Represents a symbol that has been evaluated to an address already.
Definition: JITSymbol.h:229
DebugUtils.h
llvm::orc::MaterializationUnit::getName
virtual StringRef getName() const =0
Return the name of this materialization unit.
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
CommandLine.h
Printer
print alias Alias Set Printer
Definition: AliasSetTracker.cpp:733
llvm::orc::SymbolState
SymbolState
Represents the state that a symbol has reached during materialization.
Definition: Core.h:824
llvm::orc::SymbolLookupFlags
SymbolLookupFlags
Lookup flags that apply to each symbol in a lookup.
Definition: Core.h:137
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::orc::SymbolStringPool
String pool for symbol names used by the JIT.
Definition: SymbolStringPool.h:30
llvm::errorCodeToError
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:92
llvm::orc::SymbolMap
DenseMap< SymbolStringPtr, JITEvaluatedSymbol > SymbolMap
A map from symbol names (as SymbolStringPtrs) to JITSymbols (address/flags pairs).
Definition: Core.h:113
llvm::JITEvaluatedSymbol::getFlags
JITSymbolFlags getFlags() const
Return the flags for this symbol.
Definition: JITSymbol.h:254
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::raw_ostream::write
raw_ostream & write(unsigned char C)
Definition: raw_ostream.cpp:219
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:54
llvm::orc::LookupKind::DLSym
@ DLSym
llvm::operator<<
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
Definition: APFixedPoint.h:230
llvm::orc::SymbolLookupFlags::WeaklyReferencedSymbol
@ WeaklyReferencedSymbol
llvm::DenseSet< SymbolStringPtr >
PrintAll
static cl::opt< bool > PrintAll("print-all-alias-modref-info", cl::ReallyHidden)
llvm::cl::opt< bool >
llvm::JITSymbolFlags::isWeak
bool isWeak() const
Returns true if the Weak flag is set.
Definition: JITSymbol.h:129
llvm::sys::fs::exists
bool exists(const basic_file_status &status)
Does file exist?
Definition: Path.cpp:1077
llvm::orc::SymbolLookupSet::value_type
std::pair< SymbolStringPtr, SymbolLookupFlags > value_type
Definition: Core.h:177
llvm::DenseMapBase< DenseMap< SymbolStringPtr, JITSymbolFlags, DenseMapInfo< SymbolStringPtr >, llvm::detail::DenseMapPair< SymbolStringPtr, JITSymbolFlags > >, SymbolStringPtr, JITSymbolFlags, DenseMapInfo< SymbolStringPtr >, llvm::detail::DenseMapPair< SymbolStringPtr, JITSymbolFlags > >::value_type
llvm::detail::DenseMapPair< SymbolStringPtr, JITSymbolFlags > value_type
Definition: DenseMap.h:69
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::DenseMap
Definition: DenseMap.h:716
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:432
llvm::JITSymbolFlags::isCallable
bool isCallable() const
Returns true if the given symbol is known to be callable.
Definition: JITSymbol.h:149
llvm::orc::MaterializationUnit::getSymbols
const SymbolFlagsMap & getSymbols() const
Return the set of symbols that this source provides.
Definition: Core.h:695
llvm::orc::SymbolState::NeverSearched
@ NeverSearched
No symbol should be in this state.
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1675
llvm::orc::JITDylibSearchOrder
std::vector< std::pair< JITDylib *, JITDylibLookupFlags > > JITDylibSearchOrder
A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search order during symbol lookup.
Definition: Core.h:154
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
this
Analysis the ScalarEvolution expression for r is this
Definition: README.txt:8
llvm::orc::SymbolState::Ready
@ Ready
Emitted to memory, but waiting on transitive dependencies.
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::format
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
llvm::raw_fd_ostream
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:444
llvm::orc::SymbolDependenceMap
DenseMap< JITDylib *, SymbolNameSet > SymbolDependenceMap
A map from JITDylibs to sets of symbols.
Definition: Core.h:119
std
Definition: BitVector.h:851
llvm::orc::JITDylibLookupFlags::MatchExportedSymbolsOnly
@ MatchExportedSymbolsOnly
llvm::sys::path::is_separator
bool is_separator(char value, Style style=Style::native)
Check whether the given char is a path separator on the host OS.
Definition: Path.cpp:601
Core.h
llvm::JITSymbolFlags::isCommon
bool isCommon() const
Returns true if the Common flag is set.
Definition: JITSymbol.h:134
llvm::JITEvaluatedSymbol::getAddress
JITTargetAddress getAddress() const
Return the address of this symbol.
Definition: JITSymbol.h:251
llvm::orc::SymbolState::Emitted
@ Emitted
Assigned address, still materializing.
llvm::orc::JITDylibLookupFlags
JITDylibLookupFlags
Lookup flags that apply to each dylib in the search order for a lookup.
Definition: Core.h:127
llvm::orc::SymbolState::Resolved
@ Resolved
Queried, materialization begun.
llvm::raw_ostream::getBufferStart
const char * getBufferStart() const
Return the beginning of the current stream buffer, or 0 if the stream is unbuffered.
Definition: raw_ostream.h:377
llvm::cl::desc
Definition: CommandLine.h:405
raw_ostream.h
llvm::orc::JITDylibLookupFlags::MatchAllSymbols
@ MatchAllSymbols
llvm::orc::SymbolLookupFlags::RequiredSymbol
@ RequiredSymbol
llvm::orc::SymbolNameVector
std::vector< SymbolStringPtr > SymbolNameVector
A vector of symbol names.
Definition: Core.h:109
Debug.h