116f38ddaSLang Hames //===---------- DebugUtils.cpp - Utilities for debugging ORC JITs ---------===//
216f38ddaSLang Hames //
316f38ddaSLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
416f38ddaSLang Hames // See https://llvm.org/LICENSE.txt for license information.
516f38ddaSLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
616f38ddaSLang Hames //
716f38ddaSLang Hames //===----------------------------------------------------------------------===//
816f38ddaSLang Hames
916f38ddaSLang Hames #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
1038a8760bSLang Hames
1138a8760bSLang Hames #include "llvm/ExecutionEngine/Orc/Core.h"
1238a8760bSLang Hames #include "llvm/Support/CommandLine.h"
1316f38ddaSLang Hames #include "llvm/Support/Debug.h"
14af450eabSReid Kleckner #include "llvm/Support/FileSystem.h"
1538a8760bSLang Hames #include "llvm/Support/Format.h"
1616f38ddaSLang Hames #include "llvm/Support/MemoryBuffer.h"
1716f38ddaSLang Hames #include "llvm/Support/Path.h"
1816f38ddaSLang Hames #include "llvm/Support/raw_ostream.h"
1916f38ddaSLang Hames
2016f38ddaSLang Hames #define DEBUG_TYPE "orc"
2116f38ddaSLang Hames
2238a8760bSLang Hames using namespace llvm;
2338a8760bSLang Hames
2438a8760bSLang Hames namespace {
2538a8760bSLang Hames
2638a8760bSLang Hames #ifndef NDEBUG
2738a8760bSLang Hames
2838a8760bSLang Hames cl::opt<bool> PrintHidden("debug-orc-print-hidden", cl::init(true),
2938a8760bSLang Hames cl::desc("debug print hidden symbols defined by "
3038a8760bSLang Hames "materialization units"),
3138a8760bSLang Hames cl::Hidden);
3238a8760bSLang Hames
3338a8760bSLang Hames cl::opt<bool> PrintCallable("debug-orc-print-callable", cl::init(true),
3438a8760bSLang Hames cl::desc("debug print callable symbols defined by "
3538a8760bSLang Hames "materialization units"),
3638a8760bSLang Hames cl::Hidden);
3738a8760bSLang Hames
3838a8760bSLang Hames cl::opt<bool> PrintData("debug-orc-print-data", cl::init(true),
3938a8760bSLang Hames cl::desc("debug print data symbols defined by "
4038a8760bSLang Hames "materialization units"),
4138a8760bSLang Hames cl::Hidden);
4238a8760bSLang Hames
4338a8760bSLang Hames #endif // NDEBUG
4438a8760bSLang Hames
4538a8760bSLang Hames // SetPrinter predicate that prints every element.
4638a8760bSLang Hames template <typename T> struct PrintAll {
operator ()__anon8d3c5ec40111::PrintAll4738a8760bSLang Hames bool operator()(const T &E) { return true; }
4838a8760bSLang Hames };
4938a8760bSLang Hames
anyPrintSymbolOptionSet()5038a8760bSLang Hames bool anyPrintSymbolOptionSet() {
5138a8760bSLang Hames #ifndef NDEBUG
5238a8760bSLang Hames return PrintHidden || PrintCallable || PrintData;
5338a8760bSLang Hames #else
5438a8760bSLang Hames return false;
5538a8760bSLang Hames #endif // NDEBUG
5638a8760bSLang Hames }
5738a8760bSLang Hames
flagsMatchCLOpts(const JITSymbolFlags & Flags)5838a8760bSLang Hames bool flagsMatchCLOpts(const JITSymbolFlags &Flags) {
5938a8760bSLang Hames #ifndef NDEBUG
6038a8760bSLang Hames // Bail out early if this is a hidden symbol and we're not printing hiddens.
6138a8760bSLang Hames if (!PrintHidden && !Flags.isExported())
6238a8760bSLang Hames return false;
6338a8760bSLang Hames
6438a8760bSLang Hames // Return true if this is callable and we're printing callables.
6538a8760bSLang Hames if (PrintCallable && Flags.isCallable())
6638a8760bSLang Hames return true;
6738a8760bSLang Hames
6838a8760bSLang Hames // Return true if this is data and we're printing data.
6938a8760bSLang Hames if (PrintData && !Flags.isCallable())
7038a8760bSLang Hames return true;
7138a8760bSLang Hames
7238a8760bSLang Hames // otherwise return false.
7338a8760bSLang Hames return false;
7438a8760bSLang Hames #else
7538a8760bSLang Hames return false;
7638a8760bSLang Hames #endif // NDEBUG
7738a8760bSLang Hames }
7838a8760bSLang Hames
7938a8760bSLang Hames // Prints a sequence of items, filtered by an user-supplied predicate.
8038a8760bSLang Hames template <typename Sequence,
8138a8760bSLang Hames typename Pred = PrintAll<typename Sequence::value_type>>
8238a8760bSLang Hames class SequencePrinter {
8338a8760bSLang Hames public:
SequencePrinter(const Sequence & S,char OpenSeq,char CloseSeq,Pred ShouldPrint=Pred ())8438a8760bSLang Hames SequencePrinter(const Sequence &S, char OpenSeq, char CloseSeq,
8538a8760bSLang Hames Pred ShouldPrint = Pred())
8638a8760bSLang Hames : S(S), OpenSeq(OpenSeq), CloseSeq(CloseSeq),
8738a8760bSLang Hames ShouldPrint(std::move(ShouldPrint)) {}
8838a8760bSLang Hames
printTo(llvm::raw_ostream & OS) const8938a8760bSLang Hames void printTo(llvm::raw_ostream &OS) const {
9038a8760bSLang Hames bool PrintComma = false;
9138a8760bSLang Hames OS << OpenSeq;
9238a8760bSLang Hames for (auto &E : S) {
9338a8760bSLang Hames if (ShouldPrint(E)) {
9438a8760bSLang Hames if (PrintComma)
9538a8760bSLang Hames OS << ',';
9638a8760bSLang Hames OS << ' ' << E;
9738a8760bSLang Hames PrintComma = true;
9838a8760bSLang Hames }
9938a8760bSLang Hames }
10038a8760bSLang Hames OS << ' ' << CloseSeq;
10138a8760bSLang Hames }
10238a8760bSLang Hames
10338a8760bSLang Hames private:
10438a8760bSLang Hames const Sequence &S;
10538a8760bSLang Hames char OpenSeq;
10638a8760bSLang Hames char CloseSeq;
10738a8760bSLang Hames mutable Pred ShouldPrint;
10838a8760bSLang Hames };
10938a8760bSLang Hames
11038a8760bSLang Hames template <typename Sequence, typename Pred>
printSequence(const Sequence & S,char OpenSeq,char CloseSeq,Pred P=Pred ())11138a8760bSLang Hames SequencePrinter<Sequence, Pred> printSequence(const Sequence &S, char OpenSeq,
11238a8760bSLang Hames char CloseSeq, Pred P = Pred()) {
11338a8760bSLang Hames return SequencePrinter<Sequence, Pred>(S, OpenSeq, CloseSeq, std::move(P));
11438a8760bSLang Hames }
11538a8760bSLang Hames
11638a8760bSLang Hames // Render a SequencePrinter by delegating to its printTo method.
11738a8760bSLang Hames template <typename Sequence, typename Pred>
operator <<(llvm::raw_ostream & OS,const SequencePrinter<Sequence,Pred> & Printer)11838a8760bSLang Hames llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
11938a8760bSLang Hames const SequencePrinter<Sequence, Pred> &Printer) {
12038a8760bSLang Hames Printer.printTo(OS);
12138a8760bSLang Hames return OS;
12238a8760bSLang Hames }
12338a8760bSLang Hames
12438a8760bSLang Hames struct PrintSymbolFlagsMapElemsMatchingCLOpts {
operator ()__anon8d3c5ec40111::PrintSymbolFlagsMapElemsMatchingCLOpts12538a8760bSLang Hames bool operator()(const orc::SymbolFlagsMap::value_type &KV) {
12638a8760bSLang Hames return flagsMatchCLOpts(KV.second);
12738a8760bSLang Hames }
12838a8760bSLang Hames };
12938a8760bSLang Hames
13038a8760bSLang Hames struct PrintSymbolMapElemsMatchingCLOpts {
operator ()__anon8d3c5ec40111::PrintSymbolMapElemsMatchingCLOpts13138a8760bSLang Hames bool operator()(const orc::SymbolMap::value_type &KV) {
13238a8760bSLang Hames return flagsMatchCLOpts(KV.second.getFlags());
13338a8760bSLang Hames }
13438a8760bSLang Hames };
13538a8760bSLang Hames
13638a8760bSLang Hames } // end anonymous namespace
13738a8760bSLang Hames
13816f38ddaSLang Hames namespace llvm {
13916f38ddaSLang Hames namespace orc {
14016f38ddaSLang Hames
operator <<(raw_ostream & OS,const SymbolStringPtr & Sym)14138a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym) {
14238a8760bSLang Hames return OS << *Sym;
14338a8760bSLang Hames }
14438a8760bSLang Hames
operator <<(raw_ostream & OS,const SymbolNameSet & Symbols)14538a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) {
14638a8760bSLang Hames return OS << printSequence(Symbols, '{', '}', PrintAll<SymbolStringPtr>());
14738a8760bSLang Hames }
14838a8760bSLang Hames
operator <<(raw_ostream & OS,const SymbolNameVector & Symbols)14938a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols) {
15038a8760bSLang Hames return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
15138a8760bSLang Hames }
15238a8760bSLang Hames
operator <<(raw_ostream & OS,ArrayRef<SymbolStringPtr> Symbols)153cb84e482SLang Hames raw_ostream &operator<<(raw_ostream &OS, ArrayRef<SymbolStringPtr> Symbols) {
154cb84e482SLang Hames return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
155cb84e482SLang Hames }
156cb84e482SLang Hames
operator <<(raw_ostream & OS,const JITSymbolFlags & Flags)15738a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
15838a8760bSLang Hames if (Flags.hasError())
15938a8760bSLang Hames OS << "[*ERROR*]";
16038a8760bSLang Hames if (Flags.isCallable())
16138a8760bSLang Hames OS << "[Callable]";
16238a8760bSLang Hames else
16338a8760bSLang Hames OS << "[Data]";
16438a8760bSLang Hames if (Flags.isWeak())
16538a8760bSLang Hames OS << "[Weak]";
16638a8760bSLang Hames else if (Flags.isCommon())
16738a8760bSLang Hames OS << "[Common]";
16838a8760bSLang Hames
16938a8760bSLang Hames if (!Flags.isExported())
17038a8760bSLang Hames OS << "[Hidden]";
17138a8760bSLang Hames
17238a8760bSLang Hames return OS;
17338a8760bSLang Hames }
17438a8760bSLang Hames
operator <<(raw_ostream & OS,const JITEvaluatedSymbol & Sym)17538a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const JITEvaluatedSymbol &Sym) {
17638a8760bSLang Hames return OS << format("0x%016" PRIx64, Sym.getAddress()) << " "
17738a8760bSLang Hames << Sym.getFlags();
17838a8760bSLang Hames }
17938a8760bSLang Hames
operator <<(raw_ostream & OS,const SymbolFlagsMap::value_type & KV)18038a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV) {
18138a8760bSLang Hames return OS << "(\"" << KV.first << "\", " << KV.second << ")";
18238a8760bSLang Hames }
18338a8760bSLang Hames
operator <<(raw_ostream & OS,const SymbolMap::value_type & KV)18438a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) {
18538a8760bSLang Hames return OS << "(\"" << KV.first << "\": " << KV.second << ")";
18638a8760bSLang Hames }
18738a8760bSLang Hames
operator <<(raw_ostream & OS,const SymbolFlagsMap & SymbolFlags)18838a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) {
18938a8760bSLang Hames return OS << printSequence(SymbolFlags, '{', '}',
19038a8760bSLang Hames PrintSymbolFlagsMapElemsMatchingCLOpts());
19138a8760bSLang Hames }
19238a8760bSLang Hames
operator <<(raw_ostream & OS,const SymbolMap & Symbols)19338a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) {
19438a8760bSLang Hames return OS << printSequence(Symbols, '{', '}',
19538a8760bSLang Hames PrintSymbolMapElemsMatchingCLOpts());
19638a8760bSLang Hames }
19738a8760bSLang Hames
operator <<(raw_ostream & OS,const SymbolDependenceMap::value_type & KV)19838a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS,
19938a8760bSLang Hames const SymbolDependenceMap::value_type &KV) {
20038a8760bSLang Hames return OS << "(" << KV.first->getName() << ", " << KV.second << ")";
20138a8760bSLang Hames }
20238a8760bSLang Hames
operator <<(raw_ostream & OS,const SymbolDependenceMap & Deps)20338a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) {
20438a8760bSLang Hames return OS << printSequence(Deps, '{', '}',
20538a8760bSLang Hames PrintAll<SymbolDependenceMap::value_type>());
20638a8760bSLang Hames }
20738a8760bSLang Hames
operator <<(raw_ostream & OS,const MaterializationUnit & MU)20838a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU) {
20938a8760bSLang Hames OS << "MU@" << &MU << " (\"" << MU.getName() << "\"";
21038a8760bSLang Hames if (anyPrintSymbolOptionSet())
21138a8760bSLang Hames OS << ", " << MU.getSymbols();
21238a8760bSLang Hames return OS << ")";
21338a8760bSLang Hames }
21438a8760bSLang Hames
operator <<(raw_ostream & OS,const LookupKind & K)21538a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K) {
21638a8760bSLang Hames switch (K) {
21738a8760bSLang Hames case LookupKind::Static:
21838a8760bSLang Hames return OS << "Static";
21938a8760bSLang Hames case LookupKind::DLSym:
22038a8760bSLang Hames return OS << "DLSym";
22138a8760bSLang Hames }
22238a8760bSLang Hames llvm_unreachable("Invalid lookup kind");
22338a8760bSLang Hames }
22438a8760bSLang Hames
operator <<(raw_ostream & OS,const JITDylibLookupFlags & JDLookupFlags)22538a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS,
22638a8760bSLang Hames const JITDylibLookupFlags &JDLookupFlags) {
22738a8760bSLang Hames switch (JDLookupFlags) {
22838a8760bSLang Hames case JITDylibLookupFlags::MatchExportedSymbolsOnly:
22938a8760bSLang Hames return OS << "MatchExportedSymbolsOnly";
23038a8760bSLang Hames case JITDylibLookupFlags::MatchAllSymbols:
23138a8760bSLang Hames return OS << "MatchAllSymbols";
23238a8760bSLang Hames }
23338a8760bSLang Hames llvm_unreachable("Invalid JITDylib lookup flags");
23438a8760bSLang Hames }
23538a8760bSLang Hames
operator <<(raw_ostream & OS,const SymbolLookupFlags & LookupFlags)23638a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LookupFlags) {
23738a8760bSLang Hames switch (LookupFlags) {
23838a8760bSLang Hames case SymbolLookupFlags::RequiredSymbol:
23938a8760bSLang Hames return OS << "RequiredSymbol";
24038a8760bSLang Hames case SymbolLookupFlags::WeaklyReferencedSymbol:
24138a8760bSLang Hames return OS << "WeaklyReferencedSymbol";
24238a8760bSLang Hames }
24338a8760bSLang Hames llvm_unreachable("Invalid symbol lookup flags");
24438a8760bSLang Hames }
24538a8760bSLang Hames
operator <<(raw_ostream & OS,const SymbolLookupSet::value_type & KV)24638a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS,
24738a8760bSLang Hames const SymbolLookupSet::value_type &KV) {
24838a8760bSLang Hames return OS << "(" << KV.first << ", " << KV.second << ")";
24938a8760bSLang Hames }
25038a8760bSLang Hames
operator <<(raw_ostream & OS,const SymbolLookupSet & LookupSet)25138a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet &LookupSet) {
25238a8760bSLang Hames return OS << printSequence(LookupSet, '{', '}',
25338a8760bSLang Hames PrintAll<SymbolLookupSet::value_type>());
25438a8760bSLang Hames }
25538a8760bSLang Hames
operator <<(raw_ostream & OS,const JITDylibSearchOrder & SearchOrder)25638a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS,
25738a8760bSLang Hames const JITDylibSearchOrder &SearchOrder) {
25838a8760bSLang Hames OS << "[";
25938a8760bSLang Hames if (!SearchOrder.empty()) {
26038a8760bSLang Hames assert(SearchOrder.front().first &&
26138a8760bSLang Hames "JITDylibList entries must not be null");
26238a8760bSLang Hames OS << " (\"" << SearchOrder.front().first->getName() << "\", "
26338a8760bSLang Hames << SearchOrder.begin()->second << ")";
2644ed47858SKazu Hirata for (auto &KV : llvm::drop_begin(SearchOrder)) {
26538a8760bSLang Hames assert(KV.first && "JITDylibList entries must not be null");
26638a8760bSLang Hames OS << ", (\"" << KV.first->getName() << "\", " << KV.second << ")";
26738a8760bSLang Hames }
26838a8760bSLang Hames }
26938a8760bSLang Hames OS << " ]";
27038a8760bSLang Hames return OS;
27138a8760bSLang Hames }
27238a8760bSLang Hames
operator <<(raw_ostream & OS,const SymbolAliasMap & Aliases)27338a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases) {
27438a8760bSLang Hames OS << "{";
27538a8760bSLang Hames for (auto &KV : Aliases)
27638a8760bSLang Hames OS << " " << *KV.first << ": " << KV.second.Aliasee << " "
27738a8760bSLang Hames << KV.second.AliasFlags;
27838a8760bSLang Hames OS << " }";
27938a8760bSLang Hames return OS;
28038a8760bSLang Hames }
28138a8760bSLang Hames
operator <<(raw_ostream & OS,const SymbolState & S)28238a8760bSLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S) {
28338a8760bSLang Hames switch (S) {
28438a8760bSLang Hames case SymbolState::Invalid:
28538a8760bSLang Hames return OS << "Invalid";
28638a8760bSLang Hames case SymbolState::NeverSearched:
28738a8760bSLang Hames return OS << "Never-Searched";
28838a8760bSLang Hames case SymbolState::Materializing:
28938a8760bSLang Hames return OS << "Materializing";
29038a8760bSLang Hames case SymbolState::Resolved:
29138a8760bSLang Hames return OS << "Resolved";
29238a8760bSLang Hames case SymbolState::Emitted:
29338a8760bSLang Hames return OS << "Emitted";
29438a8760bSLang Hames case SymbolState::Ready:
29538a8760bSLang Hames return OS << "Ready";
29638a8760bSLang Hames }
29738a8760bSLang Hames llvm_unreachable("Invalid state");
29838a8760bSLang Hames }
29938a8760bSLang Hames
operator <<(raw_ostream & OS,const SymbolStringPool & SSP)300*3fcd3669SLang Hames raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPool &SSP) {
301*3fcd3669SLang Hames std::lock_guard<std::mutex> Lock(SSP.PoolMutex);
302*3fcd3669SLang Hames for (auto &KV : SSP.Pool)
303*3fcd3669SLang Hames OS << KV.first() << ": " << KV.second << "\n";
304*3fcd3669SLang Hames return OS;
305*3fcd3669SLang Hames }
306*3fcd3669SLang Hames
DumpObjects(std::string DumpDir,std::string IdentifierOverride)30716f38ddaSLang Hames DumpObjects::DumpObjects(std::string DumpDir, std::string IdentifierOverride)
30816f38ddaSLang Hames : DumpDir(std::move(DumpDir)),
30916f38ddaSLang Hames IdentifierOverride(std::move(IdentifierOverride)) {
31016f38ddaSLang Hames
31116f38ddaSLang Hames /// Discard any trailing separators.
31216f38ddaSLang Hames while (!this->DumpDir.empty() &&
31316f38ddaSLang Hames sys::path::is_separator(this->DumpDir.back()))
31416f38ddaSLang Hames this->DumpDir.pop_back();
31516f38ddaSLang Hames }
31616f38ddaSLang Hames
31716f38ddaSLang Hames Expected<std::unique_ptr<MemoryBuffer>>
operator ()(std::unique_ptr<MemoryBuffer> Obj)31816f38ddaSLang Hames DumpObjects::operator()(std::unique_ptr<MemoryBuffer> Obj) {
31916f38ddaSLang Hames size_t Idx = 1;
32016f38ddaSLang Hames
32116f38ddaSLang Hames std::string DumpPathStem;
32216f38ddaSLang Hames raw_string_ostream(DumpPathStem)
32316f38ddaSLang Hames << DumpDir << (DumpDir.empty() ? "" : "/") << getBufferIdentifier(*Obj);
32416f38ddaSLang Hames
32516f38ddaSLang Hames std::string DumpPath = DumpPathStem + ".o";
32616f38ddaSLang Hames while (sys::fs::exists(DumpPath)) {
32716f38ddaSLang Hames DumpPath.clear();
32816f38ddaSLang Hames raw_string_ostream(DumpPath) << DumpPathStem << "." << (++Idx) << ".o";
32916f38ddaSLang Hames }
33016f38ddaSLang Hames
33116f38ddaSLang Hames LLVM_DEBUG({
332c42e3851SHans Wennborg dbgs() << "Dumping object buffer [ " << (const void *)Obj->getBufferStart()
333c42e3851SHans Wennborg << " -- " << (const void *)(Obj->getBufferEnd() - 1) << " ] to "
33416f38ddaSLang Hames << DumpPath << "\n";
33516f38ddaSLang Hames });
33616f38ddaSLang Hames
33716f38ddaSLang Hames std::error_code EC;
33816f38ddaSLang Hames raw_fd_ostream DumpStream(DumpPath, EC);
33916f38ddaSLang Hames if (EC)
34016f38ddaSLang Hames return errorCodeToError(EC);
34116f38ddaSLang Hames DumpStream.write(Obj->getBufferStart(), Obj->getBufferSize());
34216f38ddaSLang Hames
343c55cf4afSBill Wendling return std::move(Obj);
34416f38ddaSLang Hames }
34516f38ddaSLang Hames
getBufferIdentifier(MemoryBuffer & B)34616f38ddaSLang Hames StringRef DumpObjects::getBufferIdentifier(MemoryBuffer &B) {
34716f38ddaSLang Hames if (!IdentifierOverride.empty())
34816f38ddaSLang Hames return IdentifierOverride;
34916f38ddaSLang Hames StringRef Identifier = B.getBufferIdentifier();
35016f38ddaSLang Hames Identifier.consume_back(".o");
35116f38ddaSLang Hames return Identifier;
35216f38ddaSLang Hames }
35316f38ddaSLang Hames
35416f38ddaSLang Hames } // End namespace orc.
35516f38ddaSLang Hames } // End namespace llvm.
356