- //===-- Speculation.h - Speculative Compilation --*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // Contains the definition to support speculative compilation when laziness is 
- // enabled. 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_EXECUTIONENGINE_ORC_SPECULATION_H 
- #define LLVM_EXECUTIONENGINE_ORC_SPECULATION_H 
-   
- #include "llvm/ADT/DenseMap.h" 
- #include "llvm/ExecutionEngine/Orc/Core.h" 
- #include "llvm/ExecutionEngine/Orc/DebugUtils.h" 
- #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" 
- #include "llvm/Support/Debug.h" 
- #include <mutex> 
- #include <type_traits> 
- #include <utility> 
-   
- namespace llvm { 
- namespace orc { 
-   
- class Speculator; 
-   
- // Track the Impls (JITDylib,Symbols) of Symbols while lazy call through 
- // trampolines are created. Operations are guarded by locks tp ensure that Imap 
- // stays in consistent state after read/write 
-   
- class ImplSymbolMap { 
-   friend class Speculator; 
-   
- public: 
-   using AliaseeDetails = std::pair<SymbolStringPtr, JITDylib *>; 
-   using Alias = SymbolStringPtr; 
-   using ImapTy = DenseMap<Alias, AliaseeDetails>; 
-   void trackImpls(SymbolAliasMap ImplMaps, JITDylib *SrcJD); 
-   
- private: 
-   // FIX ME: find a right way to distinguish the pre-compile Symbols, and update 
-   // the callsite 
-   std::optional<AliaseeDetails> getImplFor(const SymbolStringPtr &StubSymbol) { 
-     std::lock_guard<std::mutex> Lockit(ConcurrentAccess); 
-     auto Position = Maps.find(StubSymbol); 
-     if (Position != Maps.end()) 
-       return Position->getSecond(); 
-     else 
-       return std::nullopt; 
-   } 
-   
-   std::mutex ConcurrentAccess; 
-   ImapTy Maps; 
- }; 
-   
- // Defines Speculator Concept, 
- class Speculator { 
- public: 
-   using TargetFAddr = JITTargetAddress; 
-   using FunctionCandidatesMap = DenseMap<SymbolStringPtr, SymbolNameSet>; 
-   using StubAddrLikelies = DenseMap<TargetFAddr, SymbolNameSet>; 
-   
- private: 
-   void registerSymbolsWithAddr(TargetFAddr ImplAddr, 
-                                SymbolNameSet likelySymbols) { 
-     std::lock_guard<std::mutex> Lockit(ConcurrentAccess); 
-     GlobalSpecMap.insert({ImplAddr, std::move(likelySymbols)}); 
-   } 
-   
-   void launchCompile(JITTargetAddress FAddr) { 
-     SymbolNameSet CandidateSet; 
-     // Copy CandidateSet is necessary, to avoid unsynchronized access to 
-     // the datastructure. 
-     { 
-       std::lock_guard<std::mutex> Lockit(ConcurrentAccess); 
-       auto It = GlobalSpecMap.find(FAddr); 
-       if (It == GlobalSpecMap.end()) 
-         return; 
-       CandidateSet = It->getSecond(); 
-     } 
-   
-     SymbolDependenceMap SpeculativeLookUpImpls; 
-   
-     for (auto &Callee : CandidateSet) { 
-       auto ImplSymbol = AliaseeImplTable.getImplFor(Callee); 
-       // try to distinguish already compiled & library symbols 
-       if (!ImplSymbol) 
-         continue; 
-       const auto &ImplSymbolName = ImplSymbol->first; 
-       JITDylib *ImplJD = ImplSymbol->second; 
-       auto &SymbolsInJD = SpeculativeLookUpImpls[ImplJD]; 
-       SymbolsInJD.insert(ImplSymbolName); 
-     } 
-   
-     DEBUG_WITH_TYPE("orc", { 
-       for (auto &I : SpeculativeLookUpImpls) { 
-         llvm::dbgs() << "\n In " << I.first->getName() << " JITDylib "; 
-         for (auto &N : I.second) 
-           llvm::dbgs() << "\n Likely Symbol : " << N; 
-       } 
-     }); 
-   
-     // for a given symbol, there may be no symbol qualified for speculatively 
-     // compile try to fix this before jumping to this code if possible. 
-     for (auto &LookupPair : SpeculativeLookUpImpls) 
-       ES.lookup( 
-           LookupKind::Static, 
-           makeJITDylibSearchOrder(LookupPair.first, 
-                                   JITDylibLookupFlags::MatchAllSymbols), 
-           SymbolLookupSet(LookupPair.second), SymbolState::Ready, 
-           [this](Expected<SymbolMap> Result) { 
-             if (auto Err = Result.takeError()) 
-               ES.reportError(std::move(Err)); 
-           }, 
-           NoDependenciesToRegister); 
-   } 
-   
- public: 
-   Speculator(ImplSymbolMap &Impl, ExecutionSession &ref) 
-       : AliaseeImplTable(Impl), ES(ref), GlobalSpecMap(0) {} 
-   Speculator(const Speculator &) = delete; 
-   Speculator(Speculator &&) = delete; 
-   Speculator &operator=(const Speculator &) = delete; 
-   Speculator &operator=(Speculator &&) = delete; 
-   
-   /// Define symbols for this Speculator object (__orc_speculator) and the 
-   /// speculation runtime entry point symbol (__orc_speculate_for) in the 
-   /// given JITDylib. 
-   Error addSpeculationRuntime(JITDylib &JD, MangleAndInterner &Mangle); 
-   
-   // Speculatively compile likely functions for the given Stub Address. 
-   // destination of __orc_speculate_for jump 
-   void speculateFor(TargetFAddr StubAddr) { launchCompile(StubAddr); } 
-   
-   // FIXME : Register with Stub Address, after JITLink Fix. 
-   void registerSymbols(FunctionCandidatesMap Candidates, JITDylib *JD) { 
-     for (auto &SymPair : Candidates) { 
-       auto Target = SymPair.first; 
-       auto Likely = SymPair.second; 
-   
-       auto OnReadyFixUp = [Likely, Target, 
-                            this](Expected<SymbolMap> ReadySymbol) { 
-         if (ReadySymbol) { 
-           auto RAddr = (*ReadySymbol)[Target].getAddress(); 
-           registerSymbolsWithAddr(RAddr, std::move(Likely)); 
-         } else 
-           this->getES().reportError(ReadySymbol.takeError()); 
-       }; 
-       // Include non-exported symbols also. 
-       ES.lookup( 
-           LookupKind::Static, 
-           makeJITDylibSearchOrder(JD, JITDylibLookupFlags::MatchAllSymbols), 
-           SymbolLookupSet(Target, SymbolLookupFlags::WeaklyReferencedSymbol), 
-           SymbolState::Ready, OnReadyFixUp, NoDependenciesToRegister); 
-     } 
-   } 
-   
-   ExecutionSession &getES() { return ES; } 
-   
- private: 
-   static void speculateForEntryPoint(Speculator *Ptr, uint64_t StubId); 
-   std::mutex ConcurrentAccess; 
-   ImplSymbolMap &AliaseeImplTable; 
-   ExecutionSession &ES; 
-   StubAddrLikelies GlobalSpecMap; 
- }; 
-   
- class IRSpeculationLayer : public IRLayer { 
- public: 
-   using IRlikiesStrRef = 
-       std::optional<DenseMap<StringRef, DenseSet<StringRef>>>; 
-   using ResultEval = std::function<IRlikiesStrRef(Function &)>; 
-   using TargetAndLikelies = DenseMap<SymbolStringPtr, SymbolNameSet>; 
-   
-   IRSpeculationLayer(ExecutionSession &ES, IRLayer &BaseLayer, Speculator &Spec, 
-                      MangleAndInterner &Mangle, ResultEval Interpreter) 
-       : IRLayer(ES, BaseLayer.getManglingOptions()), NextLayer(BaseLayer), 
-         S(Spec), Mangle(Mangle), QueryAnalysis(Interpreter) {} 
-   
-   void emit(std::unique_ptr<MaterializationResponsibility> R, 
-             ThreadSafeModule TSM) override; 
-   
- private: 
-   TargetAndLikelies 
-   internToJITSymbols(DenseMap<StringRef, DenseSet<StringRef>> IRNames) { 
-     assert(!IRNames.empty() && "No IRNames received to Intern?"); 
-     TargetAndLikelies InternedNames; 
-     for (auto &NamePair : IRNames) { 
-       DenseSet<SymbolStringPtr> TargetJITNames; 
-       for (auto &TargetNames : NamePair.second) 
-         TargetJITNames.insert(Mangle(TargetNames)); 
-       InternedNames[Mangle(NamePair.first)] = std::move(TargetJITNames); 
-     } 
-     return InternedNames; 
-   } 
-   
-   IRLayer &NextLayer; 
-   Speculator &S; 
-   MangleAndInterner &Mangle; 
-   ResultEval QueryAnalysis; 
- }; 
-   
- } // namespace orc 
- } // namespace llvm 
-   
- #endif // LLVM_EXECUTIONENGINE_ORC_SPECULATION_H 
-