1 //===----- Core.cpp - Core ORC APIs (MaterializationUnit, VSO, etc.) ------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/ExecutionEngine/Orc/Core.h"
11 #include "llvm/ExecutionEngine/Orc/OrcError.h"
12 #include "llvm/Support/Format.h"
13 
14 #if LLVM_ENABLE_THREADS
15 #include <future>
16 #endif
17 
18 namespace llvm {
19 namespace orc {
20 
21 char FailedToMaterialize::ID = 0;
22 char FailedToResolve::ID = 0;
23 char FailedToFinalize::ID = 0;
24 
25 void MaterializationUnit::anchor() {}
26 void SymbolResolver::anchor() {}
27 
28 raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
29   if (Flags.isWeak())
30     OS << 'W';
31   else if (Flags.isCommon())
32     OS << 'C';
33   else
34     OS << 'S';
35 
36   if (Flags.isExported())
37     OS << 'E';
38   else
39     OS << 'H';
40 
41   return OS;
42 }
43 
44 raw_ostream &operator<<(raw_ostream &OS, const JITEvaluatedSymbol &Sym) {
45   OS << format("0x%016x", Sym.getAddress()) << " " << Sym.getFlags();
46   return OS;
47 }
48 
49 raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) {
50   OS << "\"" << *KV.first << "\": " << KV.second;
51   return OS;
52 }
53 
54 raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) {
55   OS << "{";
56   if (!Symbols.empty()) {
57     OS << " \"" << **Symbols.begin() << "\"";
58     for (auto &Sym : make_range(std::next(Symbols.begin()), Symbols.end()))
59       OS << ", \"" << *Sym << "\"";
60   }
61   OS << " }";
62   return OS;
63 }
64 
65 raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) {
66   OS << "{";
67   if (!Symbols.empty()) {
68     OS << " {" << *Symbols.begin() << "}";
69     for (auto &Sym : make_range(std::next(Symbols.begin()), Symbols.end()))
70       OS << ", {" << Sym << "}";
71   }
72   OS << " }";
73   return OS;
74 }
75 
76 raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) {
77   OS << "{";
78   if (SymbolFlags.empty()) {
79     OS << " {\"" << *SymbolFlags.begin()->first
80        << "\": " << SymbolFlags.begin()->second << "}";
81     for (auto &KV :
82          make_range(std::next(SymbolFlags.begin()), SymbolFlags.end()))
83       OS << ", {\"" << *KV.first << "\": " << KV.second << "}";
84   }
85   OS << " }";
86   return OS;
87 }
88 
89 FailedToResolve::FailedToResolve(SymbolNameSet Symbols)
90     : Symbols(std::move(Symbols)) {
91   assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
92 }
93 
94 std::error_code FailedToResolve::convertToErrorCode() const {
95   return orcError(OrcErrorCode::UnknownORCError);
96 }
97 
98 void FailedToResolve::log(raw_ostream &OS) const {
99   OS << "Failed to resolve symbols: " << Symbols;
100 }
101 
102 FailedToFinalize::FailedToFinalize(SymbolNameSet Symbols)
103     : Symbols(std::move(Symbols)) {
104   assert(!this->Symbols.empty() && "Can not fail to finalize an empty set");
105 }
106 
107 std::error_code FailedToFinalize::convertToErrorCode() const {
108   return orcError(OrcErrorCode::UnknownORCError);
109 }
110 
111 void FailedToFinalize::log(raw_ostream &OS) const {
112   OS << "Failed to finalize symbols: " << Symbols;
113 }
114 
115 AsynchronousSymbolQuery::AsynchronousSymbolQuery(
116     const SymbolNameSet &Symbols, SymbolsResolvedCallback NotifySymbolsResolved,
117     SymbolsReadyCallback NotifySymbolsReady)
118     : NotifySymbolsResolved(std::move(NotifySymbolsResolved)),
119       NotifySymbolsReady(std::move(NotifySymbolsReady)) {
120   assert(this->NotifySymbolsResolved &&
121          "Symbols resolved callback must be set");
122   assert(this->NotifySymbolsReady && "Symbols ready callback must be set");
123   OutstandingResolutions = OutstandingFinalizations = Symbols.size();
124 }
125 
126 void AsynchronousSymbolQuery::notifyFailed(Error Err) {
127   if (OutstandingResolutions != 0)
128     NotifySymbolsResolved(std::move(Err));
129   else if (OutstandingFinalizations != 0)
130     NotifySymbolsReady(std::move(Err));
131   else
132     consumeError(std::move(Err));
133   OutstandingResolutions = OutstandingFinalizations = 0;
134 }
135 
136 void AsynchronousSymbolQuery::resolve(SymbolStringPtr Name,
137                                       JITEvaluatedSymbol Sym) {
138   // If OutstandingResolutions is zero we must have errored out already. Just
139   // ignore this.
140   if (OutstandingResolutions == 0)
141     return;
142 
143   assert(!Symbols.count(Name) && "Symbol has already been assigned an address");
144   Symbols.insert(std::make_pair(std::move(Name), std::move(Sym)));
145   --OutstandingResolutions;
146   if (OutstandingResolutions == 0)
147     NotifySymbolsResolved(std::move(Symbols));
148 }
149 
150 void AsynchronousSymbolQuery::finalizeSymbol() {
151   // If OutstandingFinalizations is zero we must have errored out already. Just
152   // ignore this.
153   if (OutstandingFinalizations == 0)
154     return;
155 
156   assert(OutstandingFinalizations > 0 && "All symbols already finalized");
157   --OutstandingFinalizations;
158   if (OutstandingFinalizations == 0)
159     NotifySymbolsReady(Error::success());
160 }
161 
162 VSO::UnmaterializedInfo::UnmaterializedInfo(
163     size_t SymbolsRemaining, std::unique_ptr<MaterializationUnit> MU)
164     : SymbolsRemaining(SymbolsRemaining), MU(std::move(MU)) {}
165 
166 VSO::SymbolTableEntry::SymbolTableEntry(JITSymbolFlags Flags,
167                                         UnmaterializedInfoIterator UMII)
168     : Flags(Flags), UMII(std::move(UMII)) {
169   // We *don't* expect isLazy to be set here. That's for the VSO to do.
170   assert(!Flags.isLazy() && "Initial flags include lazy?");
171   assert(!Flags.isMaterializing() && "Initial flags include materializing");
172   this->Flags |= JITSymbolFlags::Lazy;
173 }
174 
175 VSO::SymbolTableEntry::SymbolTableEntry(JITEvaluatedSymbol Sym)
176     : Flags(Sym.getFlags()), Address(Sym.getAddress()) {
177   assert(!Flags.isLazy() && !Flags.isMaterializing() &&
178          "This constructor is for final symbols only");
179 }
180 
181 VSO::SymbolTableEntry::SymbolTableEntry(SymbolTableEntry &&Other)
182     : Flags(Other.Flags), Address(0) {
183   if (this->Flags.isLazy())
184     UMII = std::move(Other.UMII);
185   else
186     Address = Other.Address;
187 }
188 
189 VSO::SymbolTableEntry &VSO::SymbolTableEntry::
190 operator=(SymbolTableEntry &&Other) {
191   destroy();
192   Flags = std::move(Other.Flags);
193   if (Other.Flags.isLazy()) {
194     UMII = std::move(Other.UMII);
195   } else
196     Address = Other.Address;
197   return *this;
198 }
199 
200 VSO::SymbolTableEntry::~SymbolTableEntry() { destroy(); }
201 
202 void VSO::SymbolTableEntry::replaceWith(VSO &V, SymbolStringPtr Name,
203                                         JITEvaluatedSymbol Sym) {
204   assert(!Flags.isMaterializing() &&
205          "Attempting to replace definition during materialization?");
206   if (Flags.isLazy()) {
207     if (UMII->MU)
208       UMII->MU->discard(V, Name);
209     V.detach(UMII);
210   }
211   destroy();
212   Flags = Sym.getFlags();
213   Address = Sym.getAddress();
214 }
215 
216 void VSO::SymbolTableEntry::replaceWith(VSO &V, SymbolStringPtr Name,
217                                         JITSymbolFlags NewFlags,
218                                         UnmaterializedInfoIterator NewUMII) {
219   assert(!Flags.isMaterializing() &&
220          "Attempting to replace definition during materialization?");
221   if (Flags.isLazy()) {
222     if (UMII->MU)
223       UMII->MU->discard(V, Name);
224     V.detach(UMII);
225   }
226   destroy();
227   Flags = NewFlags;
228   UMII = std::move(NewUMII);
229 }
230 
231 std::unique_ptr<MaterializationUnit>
232 VSO::SymbolTableEntry::initMaterialize(VSO &V) {
233   assert(Flags.isLazy() && "Can't materialize non-lazy symbol");
234   auto TmpMU = std::move(UMII->MU);
235   V.detach(UMII);
236   destroy();
237   Flags &= ~JITSymbolFlags::Lazy;
238   Flags |= JITSymbolFlags::Materializing;
239   Address = 0;
240   return TmpMU;
241 }
242 
243 void VSO::SymbolTableEntry::resolve(VSO &V, JITEvaluatedSymbol Sym) {
244   if (Flags.isLazy()) {
245     assert(!UMII->MU && "Resolving with MaterializationUnit still attached?");
246     V.detach(UMII);
247   }
248   destroy();
249   Flags = Sym.getFlags();
250   Flags |= JITSymbolFlags::Materializing;
251   Address = Sym.getAddress();
252 }
253 
254 void VSO::SymbolTableEntry::finalize() {
255   assert(Flags.isMaterializing() && !Flags.isLazy() &&
256          "Symbol should be in materializing state");
257   Flags &= ~JITSymbolFlags::Materializing;
258 }
259 
260 void VSO::SymbolTableEntry::destroy() {
261   if (Flags.isLazy())
262     UMII.~UnmaterializedInfoIterator();
263 }
264 
265 void VSO::detach(UnmaterializedInfoIterator UMII) {
266   assert(UMII->SymbolsRemaining > 0 &&
267          "Detaching from empty UnmaterializedInfo?");
268   --UMII->SymbolsRemaining;
269   if (UMII->SymbolsRemaining == 0)
270     UnmaterializedInfos.erase(UMII);
271 }
272 
273 VSO::RelativeLinkageStrength VSO::compareLinkage(Optional<JITSymbolFlags> Old,
274                                                  JITSymbolFlags New) {
275   if (Old == None)
276     return llvm::orc::VSO::NewDefinitionIsStronger;
277 
278   if (Old->isStrong()) {
279     if (New.isStrong())
280       return llvm::orc::VSO::DuplicateDefinition;
281     else
282       return llvm::orc::VSO::ExistingDefinitionIsStronger;
283   } else {
284     if (New.isStrong())
285       return llvm::orc::VSO::NewDefinitionIsStronger;
286     else
287       return llvm::orc::VSO::ExistingDefinitionIsStronger;
288   }
289 }
290 
291 VSO::RelativeLinkageStrength
292 VSO::compareLinkage(SymbolStringPtr Name, JITSymbolFlags NewFlags) const {
293   auto I = Symbols.find(Name);
294   return compareLinkage(
295       I == Symbols.end() ? None : Optional<JITSymbolFlags>(I->second.Flags),
296       NewFlags);
297 }
298 
299 Error VSO::define(SymbolMap NewSymbols) {
300   Error Err = Error::success();
301   for (auto &KV : NewSymbols) {
302     auto I = Symbols.find(KV.first);
303     auto LinkageResult = compareLinkage(
304         I == Symbols.end() ? None : Optional<JITSymbolFlags>(I->second.Flags),
305         KV.second.getFlags());
306 
307     // Silently discard weaker definitions.
308     if (LinkageResult == ExistingDefinitionIsStronger)
309       continue;
310 
311     // Report duplicate definition errors.
312     if (LinkageResult == DuplicateDefinition) {
313       Err = joinErrors(std::move(Err),
314                        make_error<orc::DuplicateDefinition>(*KV.first));
315       continue;
316     }
317 
318     if (I != Symbols.end())
319       I->second.replaceWith(*this, I->first, KV.second);
320     else
321       Symbols.insert(std::make_pair(KV.first, std::move(KV.second)));
322   }
323   return Err;
324 }
325 
326 Error VSO::defineLazy(std::unique_ptr<MaterializationUnit> MU) {
327 
328   auto NewSymbols = MU->getSymbols();
329 
330   auto UMII = UnmaterializedInfos.insert(
331       UnmaterializedInfos.end(),
332       UnmaterializedInfo(NewSymbols.size(), std::move(MU)));
333 
334   Error Err = Error::success();
335   for (auto &KV : NewSymbols) {
336     auto I = Symbols.find(KV.first);
337 
338     assert(I == Symbols.end() ||
339            !I->second.Flags.isMaterializing() &&
340                "Attempt to replace materializing symbol definition");
341 
342     auto LinkageResult = compareLinkage(
343         I == Symbols.end() ? None : Optional<JITSymbolFlags>(I->second.Flags),
344         KV.second);
345 
346     // Discard weaker definitions.
347     if (LinkageResult == ExistingDefinitionIsStronger) {
348       UMII->MU->discard(*this, KV.first);
349       detach(UMII);
350       continue;
351     }
352 
353     // Report duplicate definition errors.
354     if (LinkageResult == DuplicateDefinition) {
355       Err = joinErrors(std::move(Err),
356                        make_error<orc::DuplicateDefinition>(*KV.first));
357       // Duplicate definitions are discarded, so remove the duplicates from
358       // materializer.
359       detach(UMII);
360       continue;
361     }
362 
363     // Existing definition was weaker. Replace it.
364     if (I != Symbols.end())
365       I->second.replaceWith(*this, KV.first, KV.second, UMII);
366     else
367       Symbols.insert(
368           std::make_pair(KV.first, SymbolTableEntry(KV.second, UMII)));
369   }
370 
371   return Err;
372 }
373 
374 void VSO::resolve(const SymbolMap &SymbolValues) {
375   for (auto &KV : SymbolValues) {
376     auto I = Symbols.find(KV.first);
377     assert(I != Symbols.end() && "Resolving symbol not present in this dylib");
378     I->second.resolve(*this, KV.second);
379 
380     auto J = MaterializingInfos.find(KV.first);
381     if (J == MaterializingInfos.end())
382       continue;
383 
384     assert(J->second.PendingFinalization.empty() &&
385            "Queries already pending finalization?");
386     for (auto &Q : J->second.PendingResolution)
387       Q->resolve(KV.first, KV.second);
388     J->second.PendingFinalization = std::move(J->second.PendingResolution);
389     J->second.PendingResolution = MaterializingInfo::QueryList();
390   }
391 }
392 
393 void VSO::notifyResolutionFailed(const SymbolNameSet &Names) {
394   assert(!Names.empty() && "Failed to resolve empty set?");
395 
396   std::map<std::shared_ptr<AsynchronousSymbolQuery>, SymbolNameSet>
397       QueriesToFail;
398 
399   for (auto &S : Names) {
400     auto I = Symbols.find(S);
401     assert(I != Symbols.end() && "Symbol not present in this VSO");
402 
403     auto J = MaterializingInfos.find(S);
404     if (J != MaterializingInfos.end()) {
405       assert(J->second.PendingFinalization.empty() &&
406              "Failed during resolution, but queries pending finalization?");
407       for (auto &Q : J->second.PendingResolution)
408         QueriesToFail[Q].insert(S);
409       MaterializingInfos.erase(J);
410     }
411     Symbols.erase(I);
412   }
413 
414   for (auto &KV : QueriesToFail)
415     KV.first->notifyFailed(make_error<FailedToResolve>(std::move(KV.second)));
416 }
417 
418 void VSO::finalize(const SymbolNameSet &SymbolsToFinalize) {
419   for (auto &S : SymbolsToFinalize) {
420     auto I = Symbols.find(S);
421     assert(I != Symbols.end() && "Finalizing symbol not present in this dylib");
422 
423     auto J = MaterializingInfos.find(S);
424     if (J != MaterializingInfos.end()) {
425       assert(J->second.PendingResolution.empty() &&
426              "Queries still pending resolution?");
427       for (auto &Q : J->second.PendingFinalization)
428         Q->finalizeSymbol();
429       MaterializingInfos.erase(J);
430     }
431     I->second.finalize();
432   }
433 }
434 
435 void VSO::notifyFinalizationFailed(const SymbolNameSet &Names) {
436   assert(!Names.empty() && "Failed to finalize empty set?");
437 
438   std::map<std::shared_ptr<AsynchronousSymbolQuery>, SymbolNameSet>
439       QueriesToFail;
440 
441   for (auto &S : Names) {
442     auto I = Symbols.find(S);
443     assert(I != Symbols.end() && "Symbol not present in this VSO");
444     assert((I->second.Flags & JITSymbolFlags::Materializing) &&
445            "Failed to finalize symbol that was not materializing");
446 
447     auto J = MaterializingInfos.find(S);
448     if (J != MaterializingInfos.end()) {
449       assert(J->second.PendingResolution.empty() &&
450              "Failed during finalization, but queries pending resolution?");
451       for (auto &Q : J->second.PendingFinalization)
452         QueriesToFail[Q].insert(S);
453       MaterializingInfos.erase(J);
454     }
455     Symbols.erase(I);
456   }
457 
458   for (auto &KV : QueriesToFail)
459     KV.first->notifyFailed(make_error<FailedToFinalize>(std::move(KV.second)));
460 }
461 
462 SymbolNameSet VSO::lookupFlags(SymbolFlagsMap &Flags, SymbolNameSet Names) {
463 
464   for (SymbolNameSet::iterator I = Names.begin(), E = Names.end(); I != E;) {
465     auto Tmp = I++;
466     auto SymI = Symbols.find(*Tmp);
467 
468     // If the symbol isn't in this dylib then just continue.
469     if (SymI == Symbols.end())
470       continue;
471 
472     Names.erase(Tmp);
473 
474     Flags[SymI->first] =
475         JITSymbolFlags::stripTransientFlags(SymI->second.Flags);
476   }
477 
478   return Names;
479 }
480 
481 VSO::LookupResult VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
482                               SymbolNameSet Names) {
483   MaterializationUnitList MaterializationUnits;
484 
485   for (SymbolNameSet::iterator I = Names.begin(), E = Names.end(); I != E;) {
486     auto Tmp = I++;
487     auto SymI = Symbols.find(*Tmp);
488 
489     // If the symbol isn't in this dylib then just continue.
490     if (SymI == Symbols.end())
491       continue;
492 
493     // The symbol is in the VSO. Erase it from Names and proceed.
494     Names.erase(Tmp);
495 
496     // If this symbol has not been materialized yet, move it to materializing,
497     // then fall through to the materializing case below.
498     if (SymI->second.Flags.isLazy()) {
499       if (auto MU = SymI->second.initMaterialize(*this))
500         MaterializationUnits.push_back(std::move(MU));
501     }
502 
503     // If this symbol already has a fully materialized value, just use it.
504     if (!SymI->second.Flags.isMaterializing()) {
505       Query->resolve(SymI->first, JITEvaluatedSymbol(SymI->second.Address,
506                                                      SymI->second.Flags));
507       Query->finalizeSymbol();
508       continue;
509     }
510 
511     // If this symbol is materializing, then get (or create) its
512     // MaterializingInfo struct and appaend the query.
513     auto J = MaterializingInfos.find(SymI->first);
514     if (J == MaterializingInfos.end())
515       J = MaterializingInfos
516               .insert(std::make_pair(SymI->first, MaterializingInfo()))
517               .first;
518 
519     if (SymI->second.Address) {
520       auto Sym = JITEvaluatedSymbol(SymI->second.Address, SymI->second.Flags);
521       Query->resolve(SymI->first, Sym);
522       assert(J->second.PendingResolution.empty() &&
523              "Queries still pending resolution on resolved symbol?");
524       J->second.PendingFinalization.push_back(Query);
525     } else {
526       assert(J->second.PendingFinalization.empty() &&
527              "Queries pendiing finalization on unresolved symbol?");
528       J->second.PendingResolution.push_back(Query);
529     }
530   }
531 
532   return {std::move(MaterializationUnits), std::move(Names)};
533 }
534 
535 Expected<SymbolMap> lookup(const std::vector<VSO *> &VSOs, SymbolNameSet Names,
536                            MaterializationDispatcher DispatchMaterialization) {
537 #if LLVM_ENABLE_THREADS
538   // In the threaded case we use promises to return the results.
539   std::promise<SymbolMap> PromisedResult;
540   std::mutex ErrMutex;
541   Error ResolutionError = Error::success();
542   std::promise<void> PromisedReady;
543   Error ReadyError = Error::success();
544   auto OnResolve = [&](Expected<SymbolMap> Result) {
545     if (Result)
546       PromisedResult.set_value(std::move(*Result));
547     else {
548       {
549         ErrorAsOutParameter _(&ResolutionError);
550         std::lock_guard<std::mutex> Lock(ErrMutex);
551         ResolutionError = Result.takeError();
552       }
553       PromisedResult.set_value(SymbolMap());
554     }
555   };
556   auto OnReady = [&](Error Err) {
557     if (Err) {
558       ErrorAsOutParameter _(&ReadyError);
559       std::lock_guard<std::mutex> Lock(ErrMutex);
560       ReadyError = std::move(Err);
561     }
562     PromisedReady.set_value();
563   };
564 #else
565   SymbolMap Result;
566   Error ResolutionError = Error::success();
567   Error ReadyError = Error::success();
568 
569   auto OnResolve = [&](Expected<SymbolMap> R) {
570     ErrorAsOutParameter _(&ResolutionError);
571     if (R)
572       Result = std::move(*R);
573     else
574       ResolutionError = R.takeError();
575   };
576   auto OnReady = [&](Error Err) {
577     ErrorAsOutParameter _(&ReadyError);
578     if (Err)
579       ReadyError = std::move(Err);
580   };
581 #endif
582 
583   auto Query = std::make_shared<AsynchronousSymbolQuery>(
584       Names, std::move(OnResolve), std::move(OnReady));
585   SymbolNameSet UnresolvedSymbols(std::move(Names));
586 
587   for (auto *V : VSOs) {
588 
589     if (UnresolvedSymbols.empty())
590       break;
591 
592     assert(V && "VSO pointers in VSOs list should be non-null");
593     auto LR = V->lookup(Query, UnresolvedSymbols);
594     UnresolvedSymbols = std::move(LR.UnresolvedSymbols);
595 
596     for (auto &MU : LR.MaterializationUnits)
597       DispatchMaterialization(*V, std::move(MU));
598   }
599 
600 #if LLVM_ENABLE_THREADS
601   auto ResultFuture = PromisedResult.get_future();
602   auto Result = ResultFuture.get();
603 
604   {
605     std::lock_guard<std::mutex> Lock(ErrMutex);
606     if (ResolutionError) {
607       // ReadyError will never be assigned. Consume the success value.
608       cantFail(std::move(ReadyError));
609       return std::move(ResolutionError);
610     }
611   }
612 
613   auto ReadyFuture = PromisedReady.get_future();
614   ReadyFuture.get();
615 
616   {
617     std::lock_guard<std::mutex> Lock(ErrMutex);
618     if (ReadyError)
619       return std::move(ReadyError);
620   }
621 
622   return std::move(Result);
623 
624 #else
625   if (ResolutionError) {
626     // ReadyError will never be assigned. Consume the success value.
627     cantFail(std::move(ReadyError));
628     return std::move(ResolutionError);
629   }
630 
631   if (ReadyError)
632     return std::move(ReadyError);
633 
634   return Result;
635 #endif
636 }
637 
638 /// @brief Look up a symbol by searching a list of VSOs.
639 Expected<JITEvaluatedSymbol>
640 lookup(const std::vector<VSO *> VSOs, SymbolStringPtr Name,
641        MaterializationDispatcher DispatchMaterialization) {
642   SymbolNameSet Names({Name});
643   if (auto ResultMap =
644           lookup(VSOs, std::move(Names), std::move(DispatchMaterialization))) {
645     assert(ResultMap->size() == 1 && "Unexpected number of results");
646     assert(ResultMap->count(Name) && "Missing result for symbol");
647     return ResultMap->begin()->second;
648   } else
649     return ResultMap.takeError();
650 }
651 
652 void ExecutionSession::logErrorsToStdErr(Error Err) {
653   logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: ");
654 }
655 
656 } // End namespace orc.
657 } // End namespace llvm.
658