LLVM  13.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 
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 
300 DumpObjects::DumpObjects(std::string DumpDir, std::string IdentifierOverride)
301  : DumpDir(std::move(DumpDir)),
302  IdentifierOverride(std::move(IdentifierOverride)) {
303 
304  /// Discard any trailing separators.
305  while (!this->DumpDir.empty() &&
306  sys::path::is_separator(this->DumpDir.back()))
307  this->DumpDir.pop_back();
308 }
309 
311 DumpObjects::operator()(std::unique_ptr<MemoryBuffer> Obj) {
312  size_t Idx = 1;
313 
314  std::string DumpPathStem;
315  raw_string_ostream(DumpPathStem)
316  << DumpDir << (DumpDir.empty() ? "" : "/") << getBufferIdentifier(*Obj);
317 
318  std::string DumpPath = DumpPathStem + ".o";
319  while (sys::fs::exists(DumpPath)) {
320  DumpPath.clear();
321  raw_string_ostream(DumpPath) << DumpPathStem << "." << (++Idx) << ".o";
322  }
323 
324  LLVM_DEBUG({
325  dbgs() << "Dumping object buffer [ " << (const void *)Obj->getBufferStart()
326  << " -- " << (const void *)(Obj->getBufferEnd() - 1) << " ] to "
327  << DumpPath << "\n";
328  });
329 
330  std::error_code EC;
331  raw_fd_ostream DumpStream(DumpPath, EC);
332  if (EC)
333  return errorCodeToError(EC);
334  DumpStream.write(Obj->getBufferStart(), Obj->getBufferSize());
335 
336  return std::move(Obj);
337 }
338 
339 StringRef DumpObjects::getBufferIdentifier(MemoryBuffer &B) {
340  if (!IdentifierOverride.empty())
341  return IdentifierOverride;
342  StringRef Identifier = B.getBufferIdentifier();
343  Identifier.consume_back(".o");
344  return Identifier;
345 }
346 
347 } // End namespace orc.
348 } // 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
Definition: AllocatorList.h:23
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:266
llvm::orc::SymbolState::Materializing
@ Materializing
Added to the symbol table, never queried.
FileSystem.h
llvm::orc::DumpObjects::DumpObjects
DumpObjects(std::string DumpDir="", std::string IdentifierOverride="")
Construct a DumpObjects transform that will dump objects to disk.
Definition: DebugUtils.cpp:300
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:614
Path.h
llvm::orc::SymbolLookupSet
A set of symbols to look up, each associated with a SymbolLookupFlags value.
Definition: Core.h:173
llvm::orc::LookupKind::Static
@ Static
llvm::orc::SymbolStringPtr
Pointer to a pooled string representing a symbol name.
Definition: SymbolStringPool.h:50
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:143
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:311
T
#define T
Definition: Mips16ISelLowering.cpp:341
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:42
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:147
llvm::JITSymbolFlags
Flags for symbols in the JIT.
Definition: JITSymbol.h:74
llvm::MachO::SymbolFlags
SymbolFlags
Symbol flags.
Definition: Symbol.h:25
llvm::orc::MaterializationUnit
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group,...
Definition: Core.h:636
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:122
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:132
CommandLine.h
Printer
print alias Alias Set Printer
Definition: AliasSetTracker.cpp:762
llvm::orc::SymbolState
SymbolState
Represents the state that a symbol has reached during materialization.
Definition: Core.h:786
llvm::orc::SymbolLookupFlags
SymbolLookupFlags
Lookup flags that apply to each symbol in a lookup.
Definition: Core.h:135
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::errorCodeToError
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:87
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:220
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:50
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:1073
llvm::orc::SymbolLookupSet::value_type
std::pair< SymbolStringPtr, SymbolLookupFlags > value_type
Definition: Core.h:175
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:68
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:714
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
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:658
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:1540
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:152
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:136
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:432
llvm::orc::SymbolDependenceMap
DenseMap< JITDylib *, SymbolNameSet > SymbolDependenceMap
A map from JITDylibs to sets of symbols.
Definition: Core.h:117
std
Definition: BitVector.h:838
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:599
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:125
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:365
llvm::cl::desc
Definition: CommandLine.h:414
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:107
Debug.h