Add gfx950 mfma instructions to ROCDL dialect (#123361)
[llvm-project.git] / llvm / lib / ExecutionEngine / Orc / DebugUtils.cpp
blob6ced8c76b037c4389f4fb9e691eaaa6706ac70ce
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 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
11 #include "llvm/ExecutionEngine/Orc/Core.h"
12 #include "llvm/Support/CommandLine.h"
13 #include "llvm/Support/Debug.h"
14 #include "llvm/Support/FileSystem.h"
15 #include "llvm/Support/MemoryBuffer.h"
16 #include "llvm/Support/Path.h"
17 #include "llvm/Support/raw_ostream.h"
19 #define DEBUG_TYPE "orc"
21 using namespace llvm;
23 namespace {
25 #ifndef NDEBUG
27 cl::opt<bool> PrintHidden("debug-orc-print-hidden", cl::init(true),
28 cl::desc("debug print hidden symbols defined by "
29 "materialization units"),
30 cl::Hidden);
32 cl::opt<bool> PrintCallable("debug-orc-print-callable", cl::init(true),
33 cl::desc("debug print callable symbols defined by "
34 "materialization units"),
35 cl::Hidden);
37 cl::opt<bool> PrintData("debug-orc-print-data", cl::init(true),
38 cl::desc("debug print data symbols defined by "
39 "materialization units"),
40 cl::Hidden);
42 #endif // NDEBUG
44 // SetPrinter predicate that prints every element.
45 template <typename T> struct PrintAll {
46 bool operator()(const T &E) { return true; }
49 bool anyPrintSymbolOptionSet() {
50 #ifndef NDEBUG
51 return PrintHidden || PrintCallable || PrintData;
52 #else
53 return false;
54 #endif // NDEBUG
57 bool flagsMatchCLOpts(const JITSymbolFlags &Flags) {
58 #ifndef NDEBUG
59 // Bail out early if this is a hidden symbol and we're not printing hiddens.
60 if (!PrintHidden && !Flags.isExported())
61 return false;
63 // Return true if this is callable and we're printing callables.
64 if (PrintCallable && Flags.isCallable())
65 return true;
67 // Return true if this is data and we're printing data.
68 if (PrintData && !Flags.isCallable())
69 return true;
71 // otherwise return false.
72 return false;
73 #else
74 return false;
75 #endif // NDEBUG
78 // Prints a sequence of items, filtered by an user-supplied predicate.
79 template <typename Sequence,
80 typename Pred = PrintAll<typename Sequence::value_type>>
81 class SequencePrinter {
82 public:
83 SequencePrinter(const Sequence &S, char OpenSeq, char CloseSeq,
84 Pred ShouldPrint = Pred())
85 : S(S), OpenSeq(OpenSeq), CloseSeq(CloseSeq),
86 ShouldPrint(std::move(ShouldPrint)) {}
88 void printTo(llvm::raw_ostream &OS) const {
89 bool PrintComma = false;
90 OS << OpenSeq;
91 for (auto &E : S) {
92 if (ShouldPrint(E)) {
93 if (PrintComma)
94 OS << ',';
95 OS << ' ' << E;
96 PrintComma = true;
99 OS << ' ' << CloseSeq;
102 private:
103 const Sequence &S;
104 char OpenSeq;
105 char CloseSeq;
106 mutable Pred ShouldPrint;
109 template <typename Sequence, typename Pred>
110 SequencePrinter<Sequence, Pred> printSequence(const Sequence &S, char OpenSeq,
111 char CloseSeq, Pred P = Pred()) {
112 return SequencePrinter<Sequence, Pred>(S, OpenSeq, CloseSeq, std::move(P));
115 // Render a SequencePrinter by delegating to its printTo method.
116 template <typename Sequence, typename Pred>
117 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
118 const SequencePrinter<Sequence, Pred> &Printer) {
119 Printer.printTo(OS);
120 return OS;
123 struct PrintSymbolFlagsMapElemsMatchingCLOpts {
124 bool operator()(const orc::SymbolFlagsMap::value_type &KV) {
125 return flagsMatchCLOpts(KV.second);
129 struct PrintSymbolMapElemsMatchingCLOpts {
130 bool operator()(const orc::SymbolMap::value_type &KV) {
131 return flagsMatchCLOpts(KV.second.getFlags());
135 } // end anonymous namespace
137 namespace llvm {
138 namespace orc {
140 raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) {
141 return OS << printSequence(Symbols, '{', '}', PrintAll<SymbolStringPtr>());
144 raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols) {
145 return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
148 raw_ostream &operator<<(raw_ostream &OS, ArrayRef<SymbolStringPtr> Symbols) {
149 return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
152 raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
153 if (Flags.hasError())
154 OS << "[*ERROR*]";
155 if (Flags.isCallable())
156 OS << "[Callable]";
157 else
158 OS << "[Data]";
159 if (Flags.isWeak())
160 OS << "[Weak]";
161 else if (Flags.isCommon())
162 OS << "[Common]";
164 if (!Flags.isExported())
165 OS << "[Hidden]";
167 return OS;
170 raw_ostream &operator<<(raw_ostream &OS, const ExecutorSymbolDef &Sym) {
171 return OS << Sym.getAddress() << " " << Sym.getFlags();
174 raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV) {
175 return OS << "(\"" << KV.first << "\", " << KV.second << ")";
178 raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) {
179 return OS << "(\"" << KV.first << "\": " << KV.second << ")";
182 raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) {
183 return OS << printSequence(SymbolFlags, '{', '}',
184 PrintSymbolFlagsMapElemsMatchingCLOpts());
187 raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) {
188 return OS << printSequence(Symbols, '{', '}',
189 PrintSymbolMapElemsMatchingCLOpts());
192 raw_ostream &operator<<(raw_ostream &OS,
193 const SymbolDependenceMap::value_type &KV) {
194 return OS << "(" << KV.first->getName() << ", " << KV.second << ")";
197 raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) {
198 return OS << printSequence(Deps, '{', '}',
199 PrintAll<SymbolDependenceMap::value_type>());
202 raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU) {
203 OS << "MU@" << &MU << " (\"" << MU.getName() << "\"";
204 if (anyPrintSymbolOptionSet())
205 OS << ", " << MU.getSymbols();
206 return OS << ")";
209 raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K) {
210 switch (K) {
211 case LookupKind::Static:
212 return OS << "Static";
213 case LookupKind::DLSym:
214 return OS << "DLSym";
216 llvm_unreachable("Invalid lookup kind");
219 raw_ostream &operator<<(raw_ostream &OS,
220 const JITDylibLookupFlags &JDLookupFlags) {
221 switch (JDLookupFlags) {
222 case JITDylibLookupFlags::MatchExportedSymbolsOnly:
223 return OS << "MatchExportedSymbolsOnly";
224 case JITDylibLookupFlags::MatchAllSymbols:
225 return OS << "MatchAllSymbols";
227 llvm_unreachable("Invalid JITDylib lookup flags");
230 raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LookupFlags) {
231 switch (LookupFlags) {
232 case SymbolLookupFlags::RequiredSymbol:
233 return OS << "RequiredSymbol";
234 case SymbolLookupFlags::WeaklyReferencedSymbol:
235 return OS << "WeaklyReferencedSymbol";
237 llvm_unreachable("Invalid symbol lookup flags");
240 raw_ostream &operator<<(raw_ostream &OS,
241 const SymbolLookupSet::value_type &KV) {
242 return OS << "(" << KV.first << ", " << KV.second << ")";
245 raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet &LookupSet) {
246 return OS << printSequence(LookupSet, '{', '}',
247 PrintAll<SymbolLookupSet::value_type>());
250 raw_ostream &operator<<(raw_ostream &OS,
251 const JITDylibSearchOrder &SearchOrder) {
252 OS << "[";
253 if (!SearchOrder.empty()) {
254 assert(SearchOrder.front().first &&
255 "JITDylibList entries must not be null");
256 OS << " (\"" << SearchOrder.front().first->getName() << "\", "
257 << SearchOrder.begin()->second << ")";
258 for (auto &KV : llvm::drop_begin(SearchOrder)) {
259 assert(KV.first && "JITDylibList entries must not be null");
260 OS << ", (\"" << KV.first->getName() << "\", " << KV.second << ")";
263 OS << " ]";
264 return OS;
267 raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases) {
268 OS << "{";
269 for (auto &KV : Aliases)
270 OS << " " << *KV.first << ": " << KV.second.Aliasee << " "
271 << KV.second.AliasFlags;
272 OS << " }";
273 return OS;
276 raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S) {
277 switch (S) {
278 case SymbolState::Invalid:
279 return OS << "Invalid";
280 case SymbolState::NeverSearched:
281 return OS << "Never-Searched";
282 case SymbolState::Materializing:
283 return OS << "Materializing";
284 case SymbolState::Resolved:
285 return OS << "Resolved";
286 case SymbolState::Emitted:
287 return OS << "Emitted";
288 case SymbolState::Ready:
289 return OS << "Ready";
291 llvm_unreachable("Invalid state");
294 raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPool &SSP) {
295 std::lock_guard<std::mutex> Lock(SSP.PoolMutex);
296 SmallVector<std::pair<StringRef, int>, 0> Vec;
297 for (auto &KV : SSP.Pool)
298 Vec.emplace_back(KV.first(), KV.second);
299 llvm::sort(Vec, less_first());
300 for (auto &[K, V] : Vec)
301 OS << K << ": " << V << "\n";
302 return OS;
305 DumpObjects::DumpObjects(std::string DumpDir, std::string IdentifierOverride)
306 : DumpDir(std::move(DumpDir)),
307 IdentifierOverride(std::move(IdentifierOverride)) {
309 /// Discard any trailing separators.
310 while (!this->DumpDir.empty() &&
311 sys::path::is_separator(this->DumpDir.back()))
312 this->DumpDir.pop_back();
315 Expected<std::unique_ptr<MemoryBuffer>>
316 DumpObjects::operator()(std::unique_ptr<MemoryBuffer> Obj) {
317 size_t Idx = 1;
319 std::string DumpPathStem;
320 raw_string_ostream(DumpPathStem)
321 << DumpDir << (DumpDir.empty() ? "" : "/") << getBufferIdentifier(*Obj);
323 std::string DumpPath = DumpPathStem + ".o";
324 while (sys::fs::exists(DumpPath)) {
325 DumpPath.clear();
326 raw_string_ostream(DumpPath) << DumpPathStem << "." << (++Idx) << ".o";
329 LLVM_DEBUG({
330 dbgs() << "Dumping object buffer [ " << (const void *)Obj->getBufferStart()
331 << " -- " << (const void *)(Obj->getBufferEnd() - 1) << " ] to "
332 << DumpPath << "\n";
335 std::error_code EC;
336 raw_fd_ostream DumpStream(DumpPath, EC);
337 if (EC)
338 return errorCodeToError(EC);
339 DumpStream.write(Obj->getBufferStart(), Obj->getBufferSize());
341 return std::move(Obj);
344 StringRef DumpObjects::getBufferIdentifier(MemoryBuffer &B) {
345 if (!IdentifierOverride.empty())
346 return IdentifierOverride;
347 StringRef Identifier = B.getBufferIdentifier();
348 Identifier.consume_back(".o");
349 return Identifier;
352 } // End namespace orc.
353 } // End namespace llvm.