File indexing completed on 2026-05-10 08:43:54
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_EXECUTIONENGINE_ORC_SPECULATION_H
0014 #define LLVM_EXECUTIONENGINE_ORC_SPECULATION_H
0015
0016 #include "llvm/ADT/DenseMap.h"
0017 #include "llvm/ExecutionEngine/Orc/Core.h"
0018 #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
0019 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
0020 #include "llvm/Support/Debug.h"
0021 #include <mutex>
0022 #include <type_traits>
0023 #include <utility>
0024
0025 namespace llvm {
0026 namespace orc {
0027
0028 class Speculator;
0029
0030
0031
0032
0033
0034 class ImplSymbolMap {
0035 friend class Speculator;
0036
0037 public:
0038 using AliaseeDetails = std::pair<SymbolStringPtr, JITDylib *>;
0039 using Alias = SymbolStringPtr;
0040 using ImapTy = DenseMap<Alias, AliaseeDetails>;
0041 void trackImpls(SymbolAliasMap ImplMaps, JITDylib *SrcJD);
0042
0043 private:
0044
0045
0046 std::optional<AliaseeDetails> getImplFor(const SymbolStringPtr &StubSymbol) {
0047 std::lock_guard<std::mutex> Lockit(ConcurrentAccess);
0048 auto Position = Maps.find(StubSymbol);
0049 if (Position != Maps.end())
0050 return Position->getSecond();
0051 else
0052 return std::nullopt;
0053 }
0054
0055 std::mutex ConcurrentAccess;
0056 ImapTy Maps;
0057 };
0058
0059
0060 class Speculator {
0061 public:
0062 using TargetFAddr = ExecutorAddr;
0063 using FunctionCandidatesMap = DenseMap<SymbolStringPtr, SymbolNameSet>;
0064 using StubAddrLikelies = DenseMap<TargetFAddr, SymbolNameSet>;
0065
0066 private:
0067 void registerSymbolsWithAddr(TargetFAddr ImplAddr,
0068 SymbolNameSet likelySymbols) {
0069 std::lock_guard<std::mutex> Lockit(ConcurrentAccess);
0070 GlobalSpecMap.insert({ImplAddr, std::move(likelySymbols)});
0071 }
0072
0073 void launchCompile(ExecutorAddr FAddr) {
0074 SymbolNameSet CandidateSet;
0075
0076
0077 {
0078 std::lock_guard<std::mutex> Lockit(ConcurrentAccess);
0079 auto It = GlobalSpecMap.find(FAddr);
0080 if (It == GlobalSpecMap.end())
0081 return;
0082 CandidateSet = It->getSecond();
0083 }
0084
0085 SymbolDependenceMap SpeculativeLookUpImpls;
0086
0087 for (auto &Callee : CandidateSet) {
0088 auto ImplSymbol = AliaseeImplTable.getImplFor(Callee);
0089
0090 if (!ImplSymbol)
0091 continue;
0092 const auto &ImplSymbolName = ImplSymbol->first;
0093 JITDylib *ImplJD = ImplSymbol->second;
0094 auto &SymbolsInJD = SpeculativeLookUpImpls[ImplJD];
0095 SymbolsInJD.insert(ImplSymbolName);
0096 }
0097
0098 DEBUG_WITH_TYPE("orc", {
0099 for (auto &I : SpeculativeLookUpImpls) {
0100 llvm::dbgs() << "\n In " << I.first->getName() << " JITDylib ";
0101 for (auto &N : I.second)
0102 llvm::dbgs() << "\n Likely Symbol : " << N;
0103 }
0104 });
0105
0106
0107
0108 for (auto &LookupPair : SpeculativeLookUpImpls)
0109 ES.lookup(
0110 LookupKind::Static,
0111 makeJITDylibSearchOrder(LookupPair.first,
0112 JITDylibLookupFlags::MatchAllSymbols),
0113 SymbolLookupSet(LookupPair.second), SymbolState::Ready,
0114 [this](Expected<SymbolMap> Result) {
0115 if (auto Err = Result.takeError())
0116 ES.reportError(std::move(Err));
0117 },
0118 NoDependenciesToRegister);
0119 }
0120
0121 public:
0122 Speculator(ImplSymbolMap &Impl, ExecutionSession &ref)
0123 : AliaseeImplTable(Impl), ES(ref), GlobalSpecMap(0) {}
0124 Speculator(const Speculator &) = delete;
0125 Speculator(Speculator &&) = delete;
0126 Speculator &operator=(const Speculator &) = delete;
0127 Speculator &operator=(Speculator &&) = delete;
0128
0129
0130
0131
0132 Error addSpeculationRuntime(JITDylib &JD, MangleAndInterner &Mangle);
0133
0134
0135
0136 void speculateFor(TargetFAddr StubAddr) { launchCompile(StubAddr); }
0137
0138
0139 void registerSymbols(FunctionCandidatesMap Candidates, JITDylib *JD) {
0140 for (auto &SymPair : Candidates) {
0141 auto Target = SymPair.first;
0142 auto Likely = SymPair.second;
0143
0144 auto OnReadyFixUp = [Likely, Target,
0145 this](Expected<SymbolMap> ReadySymbol) {
0146 if (ReadySymbol) {
0147 auto RDef = (*ReadySymbol)[Target];
0148 registerSymbolsWithAddr(RDef.getAddress(), std::move(Likely));
0149 } else
0150 this->getES().reportError(ReadySymbol.takeError());
0151 };
0152
0153 ES.lookup(
0154 LookupKind::Static,
0155 makeJITDylibSearchOrder(JD, JITDylibLookupFlags::MatchAllSymbols),
0156 SymbolLookupSet(Target, SymbolLookupFlags::WeaklyReferencedSymbol),
0157 SymbolState::Ready, OnReadyFixUp, NoDependenciesToRegister);
0158 }
0159 }
0160
0161 ExecutionSession &getES() { return ES; }
0162
0163 private:
0164 static void speculateForEntryPoint(Speculator *Ptr, uint64_t StubId);
0165 std::mutex ConcurrentAccess;
0166 ImplSymbolMap &AliaseeImplTable;
0167 ExecutionSession &ES;
0168 StubAddrLikelies GlobalSpecMap;
0169 };
0170
0171 class IRSpeculationLayer : public IRLayer {
0172 public:
0173 using IRlikiesStrRef =
0174 std::optional<DenseMap<StringRef, DenseSet<StringRef>>>;
0175 using ResultEval = std::function<IRlikiesStrRef(Function &)>;
0176 using TargetAndLikelies = DenseMap<SymbolStringPtr, SymbolNameSet>;
0177
0178 IRSpeculationLayer(ExecutionSession &ES, IRLayer &BaseLayer, Speculator &Spec,
0179 MangleAndInterner &Mangle, ResultEval Interpreter)
0180 : IRLayer(ES, BaseLayer.getManglingOptions()), NextLayer(BaseLayer),
0181 S(Spec), Mangle(Mangle), QueryAnalysis(Interpreter) {}
0182
0183 void emit(std::unique_ptr<MaterializationResponsibility> R,
0184 ThreadSafeModule TSM) override;
0185
0186 private:
0187 TargetAndLikelies
0188 internToJITSymbols(DenseMap<StringRef, DenseSet<StringRef>> IRNames) {
0189 assert(!IRNames.empty() && "No IRNames received to Intern?");
0190 TargetAndLikelies InternedNames;
0191 for (auto &NamePair : IRNames) {
0192 DenseSet<SymbolStringPtr> TargetJITNames;
0193 for (auto &TargetNames : NamePair.second)
0194 TargetJITNames.insert(Mangle(TargetNames));
0195 InternedNames[Mangle(NamePair.first)] = std::move(TargetJITNames);
0196 }
0197 return InternedNames;
0198 }
0199
0200 IRLayer &NextLayer;
0201 Speculator &S;
0202 MangleAndInterner &Mangle;
0203 ResultEval QueryAnalysis;
0204 };
0205
0206 }
0207 }
0208
0209 #endif