diff options
22 files changed, 1007 insertions, 560 deletions
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h index aebd55563e6..7470cca4980 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h @@ -324,14 +324,14 @@ private: } static Symbol &constructExternal(void *SymStorage, Addressable &Base, - StringRef Name, JITTargetAddress Size) { + StringRef Name, JITTargetAddress Size, + Linkage L) { assert(SymStorage && "Storage cannot be null"); assert(!Base.isDefined() && "Cannot create external symbol from defined block"); assert(!Name.empty() && "External symbol name cannot be empty"); auto *Sym = reinterpret_cast<Symbol *>(SymStorage); - new (Sym) Symbol(Base, 0, Name, Size, Linkage::Strong, Scope::Default, - false, false); + new (Sym) Symbol(Base, 0, Name, Size, L, Scope::Default, false, false); return *Sym; } @@ -477,7 +477,7 @@ public: /// Set the linkage for this Symbol. void setLinkage(Linkage L) { - assert((L == Linkage::Strong || (Base->isDefined() && !Name.empty())) && + assert((L == Linkage::Strong || (!Base->isAbsolute() && !Name.empty())) && "Linkage can only be applied to defined named symbols"); this->L = static_cast<uint8_t>(L); } @@ -849,9 +849,14 @@ public: /// Add an external symbol. /// Some formats (e.g. ELF) allow Symbols to have sizes. For Symbols whose /// size is not known, you should substitute '0'. - Symbol &addExternalSymbol(StringRef Name, uint64_t Size) { - auto &Sym = Symbol::constructExternal( - Allocator.Allocate<Symbol>(), createAddressable(0, false), Name, Size); + /// For external symbols Linkage determines whether the symbol must be + /// present during lookup: Externals with strong linkage must be found or + /// an error will be emitted. Externals with weak linkage are permitted to + /// be undefined, in which case they are assigned a value of 0. + Symbol &addExternalSymbol(StringRef Name, uint64_t Size, Linkage L) { + auto &Sym = + Symbol::constructExternal(Allocator.Allocate<Symbol>(), + createAddressable(0, false), Name, Size, L); ExternalSymbols.insert(&Sym); return Sym; } @@ -1189,6 +1194,14 @@ struct PassConfiguration { LinkGraphPassList PostFixupPasses; }; +/// Flags for symbol lookup. +/// +/// FIXME: These basically duplicate orc::SymbolLookupFlags -- We should merge +/// the two types once we have an OrcSupport library. +enum class SymbolLookupFlags { RequiredSymbol, WeaklyReferencedSymbol }; + +raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LF); + /// A map of symbol names to resolved addresses. using AsyncLookupResult = DenseMap<StringRef, JITEvaluatedSymbol>; @@ -1223,6 +1236,8 @@ createLookupContinuation(Continuation Cont) { /// Holds context for a single jitLink invocation. class JITLinkContext { public: + using LookupMap = DenseMap<StringRef, SymbolLookupFlags>; + /// Destroy a JITLinkContext. virtual ~JITLinkContext(); @@ -1240,7 +1255,7 @@ public: /// Called by JITLink to resolve external symbols. This method is passed a /// lookup continutation which it must call with a result to continue the /// linking process. - virtual void lookup(const DenseSet<StringRef> &Symbols, + virtual void lookup(const LookupMap &Symbols, std::unique_ptr<JITLinkAsyncLookupContinuation> LC) = 0; /// Called by JITLink once all defined symbols in the graph have been assigned diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/llvm/include/llvm/ExecutionEngine/Orc/Core.h index 4f22a4c3879..8f92b7ab766 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Core.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h @@ -45,8 +45,11 @@ using VModuleKey = uint64_t; // efficiency). using SymbolNameSet = DenseSet<SymbolStringPtr>; +/// A vector of symbol names. +using SymbolNameVector = std::vector<SymbolStringPtr>; + /// A map from symbol names (as SymbolStringPtrs) to JITSymbols -/// (address/flags pairs). +/// (address/flags pairs). using SymbolMap = DenseMap<SymbolStringPtr, JITEvaluatedSymbol>; /// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags. @@ -55,8 +58,244 @@ using SymbolFlagsMap = DenseMap<SymbolStringPtr, JITSymbolFlags>; /// A map from JITDylibs to sets of symbols. using SymbolDependenceMap = DenseMap<JITDylib *, SymbolNameSet>; -/// A list of (JITDylib*, bool) pairs. -using JITDylibSearchList = std::vector<std::pair<JITDylib *, bool>>; +/// Lookup flags that apply to each dylib in the search order for a lookup. +/// +/// If MatchHiddenSymbolsOnly is used (the default) for a given dylib, then +/// only symbols in that Dylib's interface will be searched. If +/// MatchHiddenSymbols is used then symbols with hidden visibility will match +/// as well. +enum class JITDylibLookupFlags { MatchExportedSymbolsOnly, MatchAllSymbols }; + +/// Lookup flags that apply to each symbol in a lookup. +/// +/// If RequiredSymbol is used (the default) for a given symbol then that symbol +/// must be found during the lookup or the lookup will fail returning a +/// SymbolNotFound error. If WeaklyReferencedSymbol is used and the given +/// symbol is not found then the query will continue, and no result for the +/// missing symbol will be present in the result (assuming the rest of the +/// lookup succeeds). +enum class SymbolLookupFlags { RequiredSymbol, WeaklyReferencedSymbol }; + +/// Describes the kind of lookup being performed. The lookup kind is passed to +/// symbol generators (if they're invoked) to help them determine what +/// definitions to generate. +/// +/// Static -- Lookup is being performed as-if at static link time (e.g. +/// generators representing static archives should pull in new +/// definitions). +/// +/// DLSym -- Lookup is being performed as-if at runtime (e.g. generators +/// representing static archives should not pull in new definitions). +enum class LookupKind { Static, DLSym }; + +/// A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search +/// order during symbol lookup. +using JITDylibSearchOrder = + std::vector<std::pair<JITDylib *, JITDylibLookupFlags>>; + +/// Convenience function for creating a search order from an ArrayRef of +/// JITDylib*, all with the same flags. +inline JITDylibSearchOrder makeJITDylibSearchOrder( + ArrayRef<JITDylib *> JDs, + JITDylibLookupFlags Flags = JITDylibLookupFlags::MatchExportedSymbolsOnly) { + JITDylibSearchOrder O; + O.reserve(JDs.size()); + for (auto *JD : JDs) + O.push_back(std::make_pair(JD, Flags)); + return O; +} + +/// A set of symbols to look up, each associated with a SymbolLookupFlags +/// value. +/// +/// This class is backed by a vector and optimized for fast insertion, +/// deletion and iteration. It does not guarantee a stable order between +/// operations, and will not automatically detect duplicate elements (they +/// can be manually checked by calling the validate method). +class SymbolLookupSet { +public: + using value_type = std::pair<SymbolStringPtr, SymbolLookupFlags>; + using UnderlyingVector = std::vector<value_type>; + using iterator = UnderlyingVector::iterator; + using const_iterator = UnderlyingVector::const_iterator; + + SymbolLookupSet() = default; + + explicit SymbolLookupSet( + SymbolStringPtr Name, + SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) { + add(std::move(Name), Flags); + } + + /// Construct a SymbolLookupSet from an initializer list of SymbolStringPtrs. + explicit SymbolLookupSet( + std::initializer_list<SymbolStringPtr> Names, + SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) { + Symbols.reserve(Names.size()); + for (auto &Name : Names) + add(std::move(Name), Flags); + } + + /// Construct a SymbolLookupSet from a SymbolNameSet with the given + /// Flags used for each value. + explicit SymbolLookupSet( + const SymbolNameSet &Names, + SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) { + Symbols.reserve(Names.size()); + for (const auto &Name : Names) + add(Name, Flags); + } + + /// Construct a SymbolLookupSet from a vector of symbols with the given Flags + /// used for each value. + /// If the ArrayRef contains duplicates it is up to the client to remove these + /// before using this instance for lookup. + explicit SymbolLookupSet( + ArrayRef<SymbolStringPtr> Names, + SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) { + Symbols.reserve(Names.size()); + for (const auto &Name : Names) + add(Name, Flags); + } + + /// Add an element to the set. The client is responsible for checking that + /// duplicates are not added. + void add(SymbolStringPtr Name, + SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) { + Symbols.push_back(std::make_pair(std::move(Name), Flags)); + } + + bool empty() const { return Symbols.empty(); } + UnderlyingVector::size_type size() const { return Symbols.size(); } + iterator begin() { return Symbols.begin(); } + iterator end() { return Symbols.end(); } + const_iterator begin() const { return Symbols.begin(); } + const_iterator end() const { return Symbols.end(); } + + /// Removes the Ith element of the vector, replacing it with the last element. + void remove(UnderlyingVector::size_type I) { + std::swap(Symbols[I], Symbols.back()); + Symbols.pop_back(); + } + + /// Removes the element pointed to by the given iterator. This iterator and + /// all subsequent ones (including end()) are invalidated. + void remove(iterator I) { remove(I - begin()); } + + /// Removes all elements matching the given predicate, which must be callable + /// as bool(const SymbolStringPtr &, SymbolLookupFlags Flags). + template <typename PredFn> void remove_if(PredFn &&Pred) { + UnderlyingVector::size_type I = 0; + while (I != Symbols.size()) { + const auto &Name = Symbols[I].first; + auto Flags = Symbols[I].second; + if (Pred(Name, Flags)) + remove(I); + else + ++I; + } + } + + /// Loop over the elements of this SymbolLookupSet, applying the Body function + /// to each one. Body must be callable as + /// bool(const SymbolStringPtr &, SymbolLookupFlags). + /// If Body returns true then the element just passed in is removed from the + /// set. If Body returns false then the element is retained. + template <typename BodyFn> + auto forEachWithRemoval(BodyFn &&Body) -> typename std::enable_if< + std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(), + std::declval<SymbolLookupFlags>())), + bool>::value>::type { + UnderlyingVector::size_type I = 0; + while (I != Symbols.size()) { + const auto &Name = Symbols[I].first; + auto Flags = Symbols[I].second; + if (Body(Name, Flags)) + remove(I); + else + ++I; + } + } + + /// Loop over the elements of this SymbolLookupSet, applying the Body function + /// to each one. Body must be callable as + /// Expected<bool>(const SymbolStringPtr &, SymbolLookupFlags). + /// If Body returns a failure value, the loop exits immediately. If Body + /// returns true then the element just passed in is removed from the set. If + /// Body returns false then the element is retained. + template <typename BodyFn> + auto forEachWithRemoval(BodyFn &&Body) -> typename std::enable_if< + std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(), + std::declval<SymbolLookupFlags>())), + Expected<bool>>::value, + Error>::type { + UnderlyingVector::size_type I = 0; + while (I != Symbols.size()) { + const auto &Name = Symbols[I].first; + auto Flags = Symbols[I].second; + auto Remove = Body(Name, Flags); + if (!Remove) + return Remove.takeError(); + if (*Remove) + remove(I); + else + ++I; + } + return Error::success(); + } + + /// Construct a SymbolNameVector from this instance by dropping the Flags + /// values. + SymbolNameVector getSymbolNames() const { + SymbolNameVector Names; + Names.reserve(Symbols.size()); + for (auto &KV : Symbols) + Names.push_back(KV.first); + return Names; + } + + /// Sort the lookup set by pointer value. This sort is fast but sensitive to + /// allocation order and so should not be used where a consistent order is + /// required. + void sortByAddress() { + llvm::sort(Symbols, [](const value_type &LHS, const value_type &RHS) { + return LHS.first < RHS.first; + }); + } + + /// Sort the lookup set lexicographically. This sort is slow but the order + /// is unaffected by allocation order. + void sortByName() { + llvm::sort(Symbols, [](const value_type &LHS, const value_type &RHS) { + return *LHS.first < *RHS.first; + }); + } + + /// Remove any duplicate elements. If a SymbolLookupSet is not duplicate-free + /// by construction, this method can be used to turn it into a proper set. + void removeDuplicates() { + sortByAddress(); + auto LastI = std::unique(Symbols.begin(), Symbols.end()); + Symbols.erase(LastI, Symbols.end()); + } + +#ifndef NDEBUG + /// Returns true if this set contains any duplicates. This should only be used + /// in assertions. + bool containsDuplicates() { + if (Symbols.size() < 2) + return false; + sortByAddress(); + for (UnderlyingVector::size_type I = 1; I != Symbols.size(); ++I) + if (Symbols[I].first == Symbols[I - 1].first) + return true; + return true; + } +#endif + +private: + UnderlyingVector Symbols; +}; struct SymbolAliasMapEntry { SymbolAliasMapEntry() = default; @@ -76,6 +315,9 @@ raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym); /// Render a SymbolNameSet. raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols); +/// Render a SymbolNameVector. +raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols); + /// Render a SymbolFlagsMap entry. raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV); @@ -98,8 +340,25 @@ raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps); /// Render a MaterializationUnit. raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU); -/// Render a JITDylibSearchList. -raw_ostream &operator<<(raw_ostream &OS, const JITDylibSearchList &JDs); +//// Render a JITDylibLookupFlags instance. +raw_ostream &operator<<(raw_ostream &OS, + const JITDylibLookupFlags &JDLookupFlags); + +/// Rendar a SymbolLookupFlags instance. +raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LookupFlags); + +/// Render a JITDylibLookupFlags instance. +raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K); + +/// Render a SymbolLookupSet entry. +raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet::value_type &KV); + +/// Render a SymbolLookupSet. +raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet &LookupSet); + +/// Render a JITDylibSearchOrder. +raw_ostream &operator<<(raw_ostream &OS, + const JITDylibSearchOrder &SearchOrder); /// Render a SymbolAliasMap. raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases); @@ -107,6 +366,9 @@ raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases); /// Render a SymbolState. raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S); +/// Render a LookupKind. +raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K); + /// Callback to notify client that symbols have been resolved. using SymbolsResolvedCallback = unique_function<void(Expected<SymbolMap>)>; @@ -139,12 +401,13 @@ public: static char ID; SymbolsNotFound(SymbolNameSet Symbols); + SymbolsNotFound(SymbolNameVector Symbols); std::error_code convertToErrorCode() const override; void log(raw_ostream &OS) const override; - const SymbolNameSet &getSymbols() const { return Symbols; } + const SymbolNameVector &getSymbols() const { return Symbols; } private: - SymbolNameSet Symbols; + SymbolNameVector Symbols; }; /// Used to notify clients that a set of symbols could not be removed. @@ -376,7 +639,8 @@ public: /// Note: Care must be taken that no sets of aliases form a cycle, as such /// a cycle will result in a deadlock when any symbol in the cycle is /// resolved. - ReExportsMaterializationUnit(JITDylib *SourceJD, bool MatchNonExported, + ReExportsMaterializationUnit(JITDylib *SourceJD, + JITDylibLookupFlags SourceJDLookupFlags, SymbolAliasMap Aliases, VModuleKey K); StringRef getName() const override; @@ -387,7 +651,7 @@ private: static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases); JITDylib *SourceJD = nullptr; - bool MatchNonExported = false; + JITDylibLookupFlags SourceJDLookupFlags; SymbolAliasMap Aliases; }; @@ -405,25 +669,26 @@ private: inline std::unique_ptr<ReExportsMaterializationUnit> symbolAliases(SymbolAliasMap Aliases, VModuleKey K = VModuleKey()) { return std::make_unique<ReExportsMaterializationUnit>( - nullptr, true, std::move(Aliases), std::move(K)); + nullptr, JITDylibLookupFlags::MatchAllSymbols, std::move(Aliases), + std::move(K)); } /// Create a materialization unit for re-exporting symbols from another JITDylib /// with alternative names/flags. -/// If MatchNonExported is true then non-exported symbols from SourceJD can be -/// re-exported. If it is false, attempts to re-export a non-exported symbol -/// will result in a "symbol not found" error. +/// SourceJD will be searched using the given JITDylibLookupFlags. inline std::unique_ptr<ReExportsMaterializationUnit> reexports(JITDylib &SourceJD, SymbolAliasMap Aliases, - bool MatchNonExported = false, VModuleKey K = VModuleKey()) { + JITDylibLookupFlags SourceJDLookupFlags = + JITDylibLookupFlags::MatchExportedSymbolsOnly, + VModuleKey K = VModuleKey()) { return std::make_unique<ReExportsMaterializationUnit>( - &SourceJD, MatchNonExported, std::move(Aliases), std::move(K)); + &SourceJD, SourceJDLookupFlags, std::move(Aliases), std::move(K)); } /// Build a SymbolAliasMap for the common case where you want to re-export /// symbols from another JITDylib with the same linkage/flags. Expected<SymbolAliasMap> -buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols); +buildSimpleReexportsAAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols); /// Represents the state that a symbol has reached during materialization. enum class SymbolState : uint8_t { @@ -448,7 +713,7 @@ public: /// Create a query for the given symbols. The NotifyComplete /// callback will be called once all queried symbols reach the given /// minimum state. - AsynchronousSymbolQuery(const SymbolNameSet &Symbols, + AsynchronousSymbolQuery(const SymbolLookupSet &Symbols, SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete); @@ -456,6 +721,15 @@ public: void notifySymbolMetRequiredState(const SymbolStringPtr &Name, JITEvaluatedSymbol Sym); + /// Remove a symbol from the query. This is used to drop weakly referenced + /// symbols that are not found. + void dropSymbol(const SymbolStringPtr &Name) { + assert(ResolvedSymbols.count(Name) && + "Redundant removal of weakly-referenced symbol"); + ResolvedSymbols.erase(Name); + --OutstandingSymbolsCount; + } + /// Returns true if all symbols covered by this query have been /// resolved. bool isComplete() const { return OutstandingSymbolsCount == 0; } @@ -497,11 +771,21 @@ class JITDylib { friend class ExecutionSession; friend class MaterializationResponsibility; public: + /// Definition generators can be attached to JITDylibs to generate new + /// definitions for otherwise unresolved symbols during lookup. class DefinitionGenerator { public: virtual ~DefinitionGenerator(); - virtual Expected<SymbolNameSet> - tryToGenerate(JITDylib &Parent, const SymbolNameSet &Names) = 0; + + /// DefinitionGenerators should override this method to insert new + /// definitions into the parent JITDylib. K specifies the kind of this + /// lookup. JD specifies the target JITDylib being searched, and + /// JDLookupFlags specifies whether the search should match against + /// hidden symbols. Finally, Symbols describes the set of unresolved + /// symbols and their associated lookup flags. + virtual Error tryToGenerate(LookupKind K, JITDylib &JD, + JITDylibLookupFlags JDLookupFlags, + const SymbolLookupSet &LookupSet) = 0; }; using AsynchronousSymbolQuerySet = @@ -552,18 +836,20 @@ public: /// as the first in the search order (instead of this dylib) ensures that /// definitions within this dylib resolve to the lazy-compiling stubs, /// rather than immediately materializing the definitions in this dylib. - void setSearchOrder(JITDylibSearchList NewSearchOrder, - bool SearchThisJITDylibFirst = true, - bool MatchNonExportedInThisDylib = true); + void setSearchOrder(JITDylibSearchOrder NewSearchOrder, + bool SearchThisJITDylibFirst = true); /// Add the given JITDylib to the search order for definitions in this /// JITDylib. - void addToSearchOrder(JITDylib &JD, bool MatcNonExported = false); + void addToSearchOrder(JITDylib &JD, + JITDylibLookupFlags JDLookupFlags = + JITDylibLookupFlags::MatchExportedSymbolsOnly); /// Replace OldJD with NewJD in the search order if OldJD is present. /// Otherwise this operation is a no-op. void replaceInSearchOrder(JITDylib &OldJD, JITDylib &NewJD, - bool MatchNonExported = false); + JITDylibLookupFlags JDLookupFlags = + JITDylibLookupFlags::MatchExportedSymbolsOnly); /// Remove the given JITDylib from the search order for this JITDylib if it is /// present. Otherwise this operation is a no-op. @@ -572,7 +858,7 @@ public: /// Do something with the search order (run under the session lock). template <typename Func> auto withSearchOrderDo(Func &&F) - -> decltype(F(std::declval<const JITDylibSearchList &>())); + -> decltype(F(std::declval<const JITDylibSearchOrder &>())); /// Define all symbols provided by the materialization unit to be part of this /// JITDylib. @@ -605,8 +891,11 @@ public: Error remove(const SymbolNameSet &Names); /// Search the given JITDylib for the symbols in Symbols. If found, store - /// the flags for each symbol in Flags. Returns any unresolved symbols. - Expected<SymbolFlagsMap> lookupFlags(const SymbolNameSet &Names); + /// the flags for each symbol in Flags. If any required symbols are not found + /// then an error will be returned. + Expected<SymbolFlagsMap> lookupFlags(LookupKind K, + JITDylibLookupFlags JDLookupFlags, + SymbolLookupSet LookupSet); /// Dump current JITDylib state to OS. void dump(raw_ostream &OS); @@ -709,20 +998,23 @@ private: Error defineImpl(MaterializationUnit &MU); - Expected<SymbolNameSet> lookupFlagsImpl(SymbolFlagsMap &Flags, - const SymbolNameSet &Names); + void lookupFlagsImpl(SymbolFlagsMap &Result, LookupKind K, + JITDylibLookupFlags JDLookupFlags, + SymbolLookupSet &Unresolved); - Error lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q, - SymbolNameSet &Unresolved, bool MatchNonExported, - MaterializationUnitList &MUs); + Error lodgeQuery(MaterializationUnitList &MUs, + std::shared_ptr<AsynchronousSymbolQuery> &Q, LookupKind K, + JITDylibLookupFlags JDLookupFlags, + SymbolLookupSet &Unresolved); - Error lodgeQueryImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q, - SymbolNameSet &Unresolved, bool MatchNonExported, - MaterializationUnitList &MUs); + Error lodgeQueryImpl(MaterializationUnitList &MUs, + std::shared_ptr<AsynchronousSymbolQuery> &Q, + LookupKind K, JITDylibLookupFlags JDLookupFlags, + SymbolLookupSet &Unresolved); bool lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q, std::vector<std::unique_ptr<MaterializationUnit>> &MUs, - SymbolNameSet &Unresolved); + SymbolLookupSet &Unresolved); void detachQueryHelper(AsynchronousSymbolQuery &Q, const SymbolNameSet &QuerySymbols); @@ -754,7 +1046,7 @@ private: UnmaterializedInfosMap UnmaterializedInfos; MaterializingInfosMap MaterializingInfos; std::vector<std::unique_ptr<DefinitionGenerator>> DefGenerators; - JITDylibSearchList SearchOrder; + JITDylibSearchOrder SearchOrder; }; /// An ExecutionSession represents a running JIT program. @@ -863,8 +1155,9 @@ public: /// dependenant symbols for this query (e.g. it is being made by a top level /// client to get an address to call) then the value NoDependenciesToRegister /// can be used. - void lookup(const JITDylibSearchList &SearchOrder, SymbolNameSet Symbols, - SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete, + void lookup(LookupKind K, const JITDylibSearchOrder &SearchOrder, + SymbolLookupSet Symbols, SymbolState RequiredState, + SymbolsResolvedCallback NotifyComplete, RegisterDependenciesFunction RegisterDependencies); /// Blocking version of lookup above. Returns the resolved symbol map. @@ -874,8 +1167,9 @@ public: /// or an error occurs. If WaitUntilReady is false and an error occurs /// after resolution, the function will return a success value, but the /// error will be reported via reportErrors. - Expected<SymbolMap> lookup(const JITDylibSearchList &SearchOrder, - const SymbolNameSet &Symbols, + Expected<SymbolMap> lookup(const JITDylibSearchOrder &SearchOrder, + const SymbolLookupSet &Symbols, + LookupKind K = LookupKind::Static, SymbolState RequiredState = SymbolState::Ready, RegisterDependenciesFunction RegisterDependencies = NoDependenciesToRegister); @@ -883,7 +1177,7 @@ public: /// Convenience version of blocking lookup. /// Searches each of the JITDylibs in the search order in turn for the given /// symbol. - Expected<JITEvaluatedSymbol> lookup(const JITDylibSearchList &SearchOrder, + Expected<JITEvaluatedSymbol> lookup(const JITDylibSearchOrder &SearchOrder, SymbolStringPtr Symbol); /// Convenience version of blocking lookup. @@ -951,7 +1245,7 @@ GeneratorT &JITDylib::addGenerator(std::unique_ptr<GeneratorT> DefGenerator) { template <typename Func> auto JITDylib::withSearchOrderDo(Func &&F) - -> decltype(F(std::declval<const JITDylibSearchList &>())) { + -> decltype(F(std::declval<const JITDylibSearchOrder &>())) { return ES.runSessionLocked([&]() { return F(SearchOrder); }); } @@ -997,15 +1291,17 @@ public: /// Create a reexports generator. If an Allow predicate is passed, only /// symbols for which the predicate returns true will be reexported. If no /// Allow predicate is passed, all symbols will be exported. - ReexportsGenerator(JITDylib &SourceJD, bool MatchNonExported = false, + ReexportsGenerator(JITDylib &SourceJD, + JITDylibLookupFlags SourceJDLookupFlags, SymbolPredicate Allow = SymbolPredicate()); - Expected<SymbolNameSet> tryToGenerate(JITDylib &JD, - const SymbolNameSet &Names) override; + Error tryToGenerate(LookupKind K, JITDylib &JD, + JITDylibLookupFlags JDLookupFlags, + const SymbolLookupSet &LookupSet) override; private: JITDylib &SourceJD; - bool MatchNonExported = false; + JITDylibLookupFlags SourceJDLookupFlags; SymbolPredicate Allow; }; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h index b9bbace6f63..7d051ed9906 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h @@ -268,8 +268,9 @@ public: return Load(nullptr, GlobalPrefix, std::move(Allow)); } - Expected<SymbolNameSet> tryToGenerate(JITDylib &JD, - const SymbolNameSet &Names) override; + Error tryToGenerate(LookupKind K, JITDylib &JD, + JITDylibLookupFlags JDLookupFlags, + const SymbolLookupSet &Symbols) override; private: sys::DynamicLibrary Dylib; @@ -297,8 +298,9 @@ public: static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer); - Expected<SymbolNameSet> tryToGenerate(JITDylib &JD, - const SymbolNameSet &Names) override; + Error tryToGenerate(LookupKind K, JITDylib &JD, + JITDylibLookupFlags JDLookupFlags, + const SymbolLookupSet &Symbols) override; private: StaticLibraryDefinitionGenerator(ObjectLayer &L, @@ -307,8 +309,7 @@ private: ObjectLayer &L; std::unique_ptr<MemoryBuffer> ArchiveBuffer; - object::Archive Archive; - size_t UnrealizedObjects = 0; + std::unique_ptr<object::Archive> Archive; }; } // end namespace orc diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Speculation.h b/llvm/include/llvm/ExecutionEngine/Orc/Speculation.h index 766a6b070f1..f6b86bb2316 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Speculation.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Speculation.h @@ -100,23 +100,27 @@ private: 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; + 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(JITDylibSearchList({{LookupPair.first, true}}), - LookupPair.second, SymbolState::Ready, - [this](Expected<SymbolMap> Result) { - if (auto Err = Result.takeError()) - ES.reportError(std::move(Err)); - }, - NoDependenciesToRegister); + 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: @@ -151,8 +155,11 @@ public: this->getES().reportError(ReadySymbol.takeError()); }; // Include non-exported symbols also. - ES.lookup(JITDylibSearchList({{JD, true}}), SymbolNameSet({Target}), - SymbolState::Ready, OnReadyFixUp, NoDependenciesToRegister); + ES.lookup( + LookupKind::Static, + makeJITDylibSearchOrder(JD, JITDylibLookupFlags::MatchAllSymbols), + SymbolLookupSet(Target, SymbolLookupFlags::WeaklyReferencedSymbol), + SymbolState::Ready, OnReadyFixUp, NoDependenciesToRegister); } } diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp index 9df79670d9f..6c924f88957 100644 --- a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp @@ -266,6 +266,16 @@ void LinkGraph::dump(raw_ostream &OS, << "\n"; } +raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LF) { + switch (LF) { + case SymbolLookupFlags::RequiredSymbol: + return OS << "RequiredSymbol"; + case SymbolLookupFlags::WeaklyReferencedSymbol: + return OS << "WeaklyReferencedSymbol"; + } + llvm_unreachable("Unrecognized lookup flags"); +} + void JITLinkAsyncLookupContinuation::anchor() {} JITLinkContext::~JITLinkContext() {} diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp index 9707b9624d9..7b594fd2c0e 100644 --- a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp @@ -257,25 +257,35 @@ Error JITLinkerBase::allocateSegments(const SegmentLayoutMap &Layout) { return Error::success(); } -DenseSet<StringRef> JITLinkerBase::getExternalSymbolNames() const { +JITLinkContext::LookupMap JITLinkerBase::getExternalSymbolNames() const { // Identify unresolved external symbols. - DenseSet<StringRef> UnresolvedExternals; + JITLinkContext::LookupMap UnresolvedExternals; for (auto *Sym : G->external_symbols()) { assert(Sym->getAddress() == 0 && "External has already been assigned an address"); assert(Sym->getName() != StringRef() && Sym->getName() != "" && "Externals must be named"); - UnresolvedExternals.insert(Sym->getName()); + SymbolLookupFlags LookupFlags = + Sym->getLinkage() == Linkage::Weak + ? SymbolLookupFlags::WeaklyReferencedSymbol + : SymbolLookupFlags::RequiredSymbol; + UnresolvedExternals[Sym->getName()] = LookupFlags; } return UnresolvedExternals; } void JITLinkerBase::applyLookupResult(AsyncLookupResult Result) { for (auto *Sym : G->external_symbols()) { + assert(Sym->getOffset() == 0 && + "External symbol is not at the start of its addressable block"); assert(Sym->getAddress() == 0 && "Symbol already resolved"); assert(!Sym->isDefined() && "Symbol being resolved is already defined"); - assert(Result.count(Sym->getName()) && "Missing resolution for symbol"); - Sym->getAddressable().setAddress(Result[Sym->getName()].getAddress()); + auto ResultI = Result.find(Sym->getName()); + if (ResultI != Result.end()) + Sym->getAddressable().setAddress(ResultI->second.getAddress()); + else + assert(Sym->getLinkage() == Linkage::Weak && + "Failed to resolve non-weak reference"); } LLVM_DEBUG({ @@ -285,8 +295,11 @@ void JITLinkerBase::applyLookupResult(AsyncLookupResult Result) { << formatv("{0:x16}", Sym->getAddress()) << "\n"; }); assert(llvm::all_of(G->external_symbols(), - [](Symbol *Sym) { return Sym->getAddress() != 0; }) && - "All symbols should have been resolved by this point"); + [](Symbol *Sym) { + return Sym->getAddress() != 0 || + Sym->getLinkage() == Linkage::Weak; + }) && + "All strong external symbols should have been resolved by now"); } void JITLinkerBase::deallocateAndBailOut(Error Err) { diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h index 07dee6cee20..d5687b7afc9 100644 --- a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h +++ b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h @@ -106,7 +106,7 @@ private: SegmentLayoutMap layOutBlocks(); Error allocateSegments(const SegmentLayoutMap &Layout); - DenseSet<StringRef> getExternalSymbolNames() const; + JITLinkContext::LookupMap getExternalSymbolNames() const; void applyLookupResult(AsyncLookupResult LR); void deallocateAndBailOut(Error Err); diff --git a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp index c1dc138ee70..1881bd0b287 100644 --- a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp @@ -321,7 +321,9 @@ Error MachOLinkGraphBuilder::graphifyRegularSymbols() { return make_error<JITLinkError>("Anonymous external symbol at " "index " + Twine(KV.first)); - NSym.GraphSymbol = &G->addExternalSymbol(*NSym.Name, 0); + NSym.GraphSymbol = &G->addExternalSymbol( + *NSym.Name, 0, + NSym.Desc & MachO::N_WEAK_REF ? Linkage::Weak : Linkage::Strong); } break; case MachO::N_ABS: diff --git a/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp b/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp index 75ddbc30445..b8e42922027 100644 --- a/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp +++ b/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp @@ -162,7 +162,8 @@ void CompileOnDemandLayer::emit(MaterializationResponsibility R, return; } - R.replace(reexports(PDR.getImplDylib(), std::move(NonCallables), true)); + R.replace(reexports(PDR.getImplDylib(), std::move(NonCallables), + JITDylibLookupFlags::MatchAllSymbols)); R.replace(lazyReexports(LCTMgr, PDR.getISManager(), PDR.getImplDylib(), std::move(Callables), AliaseeImpls)); } @@ -173,16 +174,20 @@ CompileOnDemandLayer::getPerDylibResources(JITDylib &TargetD) { if (I == DylibResources.end()) { auto &ImplD = getExecutionSession().createJITDylib( TargetD.getName() + ".impl", false); - TargetD.withSearchOrderDo([&](const JITDylibSearchList &TargetSearchOrder) { - auto NewSearchOrder = TargetSearchOrder; - assert(!NewSearchOrder.empty() && - NewSearchOrder.front().first == &TargetD && - NewSearchOrder.front().second == true && - "TargetD must be at the front of its own search order and match " - "non-exported symbol"); - NewSearchOrder.insert(std::next(NewSearchOrder.begin()), {&ImplD, true}); - ImplD.setSearchOrder(std::move(NewSearchOrder), false); - }); + TargetD.withSearchOrderDo( + [&](const JITDylibSearchOrder &TargetSearchOrder) { + auto NewSearchOrder = TargetSearchOrder; + assert( + !NewSearchOrder.empty() && + NewSearchOrder.front().first == &TargetD && + NewSearchOrder.front().second == + JITDylibLookupFlags::MatchAllSymbols && + "TargetD must be at the front of its own search order and match " + "non-exported symbol"); + NewSearchOrder.insert(std::next(NewSearchOrder.begin()), + {&ImplD, JITDylibLookupFlags::MatchAllSymbols}); + ImplD.setSearchOrder(std::move(NewSearchOrder), false); + }); PerDylibResources PDR(ImplD, BuildIndirectStubsManager()); I = DylibResources.insert(std::make_pair(&TargetD, std::move(PDR))).first; } diff --git a/llvm/lib/ExecutionEngine/Orc/Core.cpp b/llvm/lib/ExecutionEngine/Orc/Core.cpp index 9e024ba0f10..0814ec1c5f8 100644 --- a/llvm/lib/ExecutionEngine/Orc/Core.cpp +++ b/llvm/lib/ExecutionEngine/Orc/Core.cpp @@ -7,6 +7,8 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Orc/Core.h" + +#include "llvm/ADT/STLExtras.h" #include "llvm/Config/llvm-config.h" #include "llvm/ExecutionEngine/Orc/OrcError.h" #include "llvm/IR/Mangler.h" @@ -77,16 +79,19 @@ bool flagsMatchCLOpts(const JITSymbolFlags &Flags) { #endif // NDEBUG } -// Prints a set of items, filtered by an user-supplied predicate. -template <typename Set, typename Pred = PrintAll<typename Set::value_type>> -class SetPrinter { +// Prints a sequence of items, filtered by an user-supplied predicate. +template <typename Sequence, + typename Pred = PrintAll<typename Sequence::value_type>> +class SequencePrinter { public: - SetPrinter(const Set &S, Pred ShouldPrint = Pred()) - : S(S), ShouldPrint(std::move(ShouldPrint)) {} + SequencePrinter(const Sequence &S, char OpenSeq, char CloseSeq, + Pred ShouldPrint = Pred()) + : S(S), OpenSeq(OpenSeq), CloseSeq(CloseSeq), + ShouldPrint(std::move(ShouldPrint)) {} void printTo(llvm::raw_ostream &OS) const { bool PrintComma = false; - OS << "{"; + OS << OpenSeq; for (auto &E : S) { if (ShouldPrint(E)) { if (PrintComma) @@ -95,23 +100,26 @@ public: PrintComma = true; } } - OS << " }"; + OS << ' ' << CloseSeq; } private: - const Set &S; + const Sequence &S; + char OpenSeq; + char CloseSeq; mutable Pred ShouldPrint; }; -template <typename Set, typename Pred> -SetPrinter<Set, Pred> printSet(const Set &S, Pred P = Pred()) { - return SetPrinter<Set, Pred>(S, std::move(P)); +template <typename Sequence, typename Pred> +SequencePrinter<Sequence, Pred> printSequence(const Sequence &S, char OpenSeq, + char CloseSeq, Pred P = Pred()) { + return SequencePrinter<Sequence, Pred>(S, OpenSeq, CloseSeq, std::move(P)); } -// Render a SetPrinter by delegating to its printTo method. -template <typename Set, typename Pred> +// Render a SequencePrinter by delegating to its printTo method. +template <typename Sequence, typename Pred> llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const SetPrinter<Set, Pred> &Printer) { + const SequencePrinter<Sequence, Pred> &Printer) { Printer.printTo(OS); return OS; } @@ -147,7 +155,11 @@ raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym) { } raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols) { - return OS << printSet(Symbols, PrintAll<SymbolStringPtr>()); + return OS << printSequence(Symbols, '{', '}', PrintAll<SymbolStringPtr>()); +} + +raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols) { + return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>()); } raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) { @@ -182,11 +194,13 @@ raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV) { } raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags) { - return OS << printSet(SymbolFlags, PrintSymbolFlagsMapElemsMatchingCLOpts()); + return OS << printSequence(SymbolFlags, '{', '}', + PrintSymbolFlagsMapElemsMatchingCLOpts()); } raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols) { - return OS << printSet(Symbols, PrintSymbolMapElemsMatchingCLOpts()); + return OS << printSequence(Symbols, '{', '}', + PrintSymbolMapElemsMatchingCLOpts()); } raw_ostream &operator<<(raw_ostream &OS, @@ -195,7 +209,8 @@ raw_ostream &operator<<(raw_ostream &OS, } raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) { - return OS << printSet(Deps, PrintAll<SymbolDependenceMap::value_type>()); + return OS << printSequence(Deps, '{', '}', + PrintAll<SymbolDependenceMap::value_type>()); } raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU) { @@ -205,16 +220,59 @@ raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU) { return OS << ")"; } -raw_ostream &operator<<(raw_ostream &OS, const JITDylibSearchList &JDs) { +raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K) { + switch (K) { + case LookupKind::Static: + return OS << "Static"; + case LookupKind::DLSym: + return OS << "DLSym"; + } + llvm_unreachable("Invalid lookup kind"); +} + +raw_ostream &operator<<(raw_ostream &OS, + const JITDylibLookupFlags &JDLookupFlags) { + switch (JDLookupFlags) { + case JITDylibLookupFlags::MatchExportedSymbolsOnly: + return OS << "MatchExportedSymbolsOnly"; + case JITDylibLookupFlags::MatchAllSymbols: + return OS << "MatchAllSymbols"; + } + llvm_unreachable("Invalid JITDylib lookup flags"); +} + +raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupFlags &LookupFlags) { + switch (LookupFlags) { + case SymbolLookupFlags::RequiredSymbol: + return OS << "RequiredSymbol"; + case SymbolLookupFlags::WeaklyReferencedSymbol: + return OS << "WeaklyReferencedSymbol"; + } + llvm_unreachable("Invalid symbol lookup flags"); +} + +raw_ostream &operator<<(raw_ostream &OS, + const SymbolLookupSet::value_type &KV) { + return OS << "(" << KV.first << ", " << KV.second << ")"; +} + +raw_ostream &operator<<(raw_ostream &OS, const SymbolLookupSet &LookupSet) { + return OS << printSequence(LookupSet, '{', '}', + PrintAll<SymbolLookupSet::value_type>()); +} + +raw_ostream &operator<<(raw_ostream &OS, + const JITDylibSearchOrder &SearchOrder) { OS << "["; - if (!JDs.empty()) { - assert(JDs.front().first && "JITDylibList entries must not be null"); - OS << " (\"" << JDs.front().first->getName() << "\", " - << (JDs.front().second ? "true" : "false") << ")"; - for (auto &KV : make_range(std::next(JDs.begin()), JDs.end())) { + if (!SearchOrder.empty()) { + assert(SearchOrder.front().first && + "JITDylibList entries must not be null"); + OS << " (\"" << SearchOrder.front().first->getName() << "\", " + << SearchOrder.begin()->second << ")"; + for (auto &KV : + make_range(std::next(SearchOrder.begin(), 1), SearchOrder.end())) { assert(KV.first && "JITDylibList entries must not be null"); - OS << ", (\"" << KV.first->getName() << "\", " - << (KV.second ? "true" : "false") << ")"; + OS << ", (\"" << KV.first->getName() << "\", " << KV.second << ")"; } } OS << " ]"; @@ -262,7 +320,13 @@ void FailedToMaterialize::log(raw_ostream &OS) const { OS << "Failed to materialize symbols: " << *Symbols; } -SymbolsNotFound::SymbolsNotFound(SymbolNameSet Symbols) +SymbolsNotFound::SymbolsNotFound(SymbolNameSet Symbols) { + for (auto &Sym : Symbols) + this->Symbols.push_back(Sym); + assert(!this->Symbols.empty() && "Can not fail to resolve an empty set"); +} + +SymbolsNotFound::SymbolsNotFound(SymbolNameVector Symbols) : Symbols(std::move(Symbols)) { assert(!this->Symbols.empty() && "Can not fail to resolve an empty set"); } @@ -289,7 +353,7 @@ void SymbolsCouldNotBeRemoved::log(raw_ostream &OS) const { } AsynchronousSymbolQuery::AsynchronousSymbolQuery( - const SymbolNameSet &Symbols, SymbolState RequiredState, + const SymbolLookupSet &Symbols, SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete) : NotifyComplete(std::move(NotifyComplete)), RequiredState(RequiredState) { assert(RequiredState >= SymbolState::Resolved && @@ -298,8 +362,8 @@ AsynchronousSymbolQuery::AsynchronousSymbolQuery( OutstandingSymbolsCount = Symbols.size(); - for (auto &S : Symbols) - ResolvedSymbols[S] = nullptr; + for (auto &KV : Symbols) + ResolvedSymbols[KV.first] = nullptr; } void AsynchronousSymbolQuery::notifySymbolMetRequiredState( @@ -511,10 +575,10 @@ AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) { } ReExportsMaterializationUnit::ReExportsMaterializationUnit( - JITDylib *SourceJD, bool MatchNonExported, SymbolAliasMap Aliases, - VModuleKey K) + JITDylib *SourceJD, JITDylibLookupFlags SourceJDLookupFlags, + SymbolAliasMap Aliases, VModuleKey K) : MaterializationUnit(extractFlags(Aliases), std::move(K)), - SourceJD(SourceJD), MatchNonExported(MatchNonExported), + SourceJD(SourceJD), SourceJDLookupFlags(SourceJDLookupFlags), Aliases(std::move(Aliases)) {} StringRef ReExportsMaterializationUnit::getName() const { @@ -551,7 +615,7 @@ void ReExportsMaterializationUnit::materialize( if (!Aliases.empty()) { if (SourceJD) - R.replace(reexports(*SourceJD, std::move(Aliases), MatchNonExported)); + R.replace(reexports(*SourceJD, std::move(Aliases), SourceJDLookupFlags)); else R.replace(symbolAliases(std::move(Aliases))); } @@ -572,11 +636,11 @@ void ReExportsMaterializationUnit::materialize( // be waitin on a symbol that it itself had to resolve. Usually this will just // involve one round and a single query. - std::vector<std::pair<SymbolNameSet, std::shared_ptr<OnResolveInfo>>> + std::vector<std::pair<SymbolLookupSet, std::shared_ptr<OnResolveInfo>>> QueryInfos; while (!RequestedAliases.empty()) { SymbolNameSet ResponsibilitySymbols; - SymbolNameSet QuerySymbols; + SymbolLookupSet QuerySymbols; SymbolAliasMap QueryAliases; // Collect as many aliases as we can without including a chain. @@ -587,7 +651,7 @@ void ReExportsMaterializationUnit::materialize( continue; ResponsibilitySymbols.insert(KV.first); - QuerySymbols.insert(KV.second.Aliasee); + QuerySymbols.add(KV.second.Aliasee); QueryAliases[KV.first] = std::move(KV.second); } @@ -657,8 +721,9 @@ void ReExportsMaterializationUnit::materialize( } }; - ES.lookup(JITDylibSearchList({{&SrcJD, MatchNonExported}}), QuerySymbols, - SymbolState::Resolved, std::move(OnComplete), + ES.lookup(LookupKind::Static, + JITDylibSearchOrder({{&SrcJD, SourceJDLookupFlags}}), + QuerySymbols, SymbolState::Resolved, std::move(OnComplete), std::move(RegisterDependencies)); } } @@ -681,16 +746,16 @@ ReExportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) { Expected<SymbolAliasMap> buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols) { - auto Flags = SourceJD.lookupFlags(Symbols); + SymbolLookupSet LookupSet(Symbols); + auto Flags = SourceJD.lookupFlags( + LookupKind::Static, JITDylibLookupFlags::MatchAllSymbols, LookupSet); if (!Flags) return Flags.takeError(); - if (Flags->size() != Symbols.size()) { - SymbolNameSet Unresolved = Symbols; - for (auto &KV : *Flags) - Unresolved.erase(KV.first); - return make_error<SymbolsNotFound>(std::move(Unresolved)); + if (!LookupSet.empty()) { + LookupSet.sortByName(); + return make_error<SymbolsNotFound>(LookupSet.getSymbolNames()); } SymbolAliasMap Result; @@ -703,32 +768,32 @@ buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols) { } ReexportsGenerator::ReexportsGenerator(JITDylib &SourceJD, - bool MatchNonExported, + JITDylibLookupFlags SourceJDLookupFlags, SymbolPredicate Allow) - : SourceJD(SourceJD), MatchNonExported(MatchNonExported), + : SourceJD(SourceJD), SourceJDLookupFlags(SourceJDLookupFlags), Allow(std::move(Allow)) {} -Expected<SymbolNameSet> -ReexportsGenerator::tryToGenerate(JITDylib &JD, const SymbolNameSet &Names) { - orc::SymbolNameSet Added; - orc::SymbolAliasMap AliasMap; - - auto Flags = SourceJD.lookupFlags(Names); +Error ReexportsGenerator::tryToGenerate(LookupKind K, JITDylib &JD, + JITDylibLookupFlags JDLookupFlags, + const SymbolLookupSet &LookupSet) { + assert(&JD != &SourceJD && "Cannot re-export from the same dylib"); + // Use lookupFlags to find the subset of symbols that match our lookup. + auto Flags = SourceJD.lookupFlags(K, JDLookupFlags, LookupSet); if (!Flags) return Flags.takeError(); - for (auto &KV : *Flags) { - if (Allow && !Allow(KV.first)) - continue; - AliasMap[KV.first] = SymbolAliasMapEntry(KV.first, KV.second); - Added.insert(KV.first); - } + // Create an alias map. + orc::SymbolAliasMap AliasMap; + for (auto &KV : *Flags) + if (!Allow || Allow(KV.first)) + AliasMap[KV.first] = SymbolAliasMapEntry(KV.first, KV.second); - if (!Added.empty()) - cantFail(JD.define(reexports(SourceJD, AliasMap, MatchNonExported))); + if (AliasMap.empty()) + return Error::success(); - return Added; + // Define the re-exports. + return JD.define(reexports(SourceJD, AliasMap, SourceJDLookupFlags)); } JITDylib::DefinitionGenerator::~DefinitionGenerator() {} @@ -1252,41 +1317,41 @@ void JITDylib::notifyFailed(FailedSymbolsWorklist Worklist) { Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbolsMap)); } -void JITDylib::setSearchOrder(JITDylibSearchList NewSearchOrder, - bool SearchThisJITDylibFirst, - bool MatchNonExportedInThisDylib) { - if (SearchThisJITDylibFirst) { - if (NewSearchOrder.empty() || NewSearchOrder.front().first != this) - NewSearchOrder.insert(NewSearchOrder.begin(), - {this, MatchNonExportedInThisDylib}); - } - - ES.runSessionLocked([&]() { SearchOrder = std::move(NewSearchOrder); }); -} - -void JITDylib::addToSearchOrder(JITDylib &JD, bool MatchNonExported) { +void JITDylib::setSearchOrder(JITDylibSearchOrder NewSearchOrder, + bool SearchThisJITDylibFirst) { ES.runSessionLocked([&]() { - SearchOrder.push_back({&JD, MatchNonExported}); + if (SearchThisJITDylibFirst) { + SearchOrder.clear(); + if (NewSearchOrder.empty() || NewSearchOrder.front().first != this) + SearchOrder.push_back( + std::make_pair(this, JITDylibLookupFlags::MatchAllSymbols)); + SearchOrder.insert(SearchOrder.end(), NewSearchOrder.begin(), + NewSearchOrder.end()); + } else + SearchOrder = std::move(NewSearchOrder); }); } +void JITDylib::addToSearchOrder(JITDylib &JD, + JITDylibLookupFlags JDLookupFlags) { + ES.runSessionLocked([&]() { SearchOrder.push_back({&JD, JDLookupFlags}); }); +} + void JITDylib::replaceInSearchOrder(JITDylib &OldJD, JITDylib &NewJD, - bool MatchNonExported) { + JITDylibLookupFlags JDLookupFlags) { ES.runSessionLocked([&]() { - auto I = std::find_if(SearchOrder.begin(), SearchOrder.end(), - [&](const JITDylibSearchList::value_type &KV) { - return KV.first == &OldJD; - }); - - if (I != SearchOrder.end()) - *I = {&NewJD, MatchNonExported}; + for (auto &KV : SearchOrder) + if (KV.first == &OldJD) { + KV = {&NewJD, JDLookupFlags}; + break; + } }); } void JITDylib::removeFromSearchOrder(JITDylib &JD) { ES.runSessionLocked([&]() { auto I = std::find_if(SearchOrder.begin(), SearchOrder.end(), - [&](const JITDylibSearchList::value_type &KV) { + [&](const JITDylibSearchOrder::value_type &KV) { return KV.first == &JD; }); if (I != SearchOrder.end()) @@ -1349,63 +1414,54 @@ Error JITDylib::remove(const SymbolNameSet &Names) { }); } -Expected<SymbolFlagsMap> JITDylib::lookupFlags(const SymbolNameSet &Names) { +Expected<SymbolFlagsMap> +JITDylib::lookupFlags(LookupKind K, JITDylibLookupFlags JDLookupFlags, + SymbolLookupSet LookupSet) { return ES.runSessionLocked([&, this]() -> Expected<SymbolFlagsMap> { SymbolFlagsMap Result; - auto Unresolved = lookupFlagsImpl(Result, Names); - if (!Unresolved) - return Unresolved.takeError(); + lookupFlagsImpl(Result, K, JDLookupFlags, LookupSet); - /// Run any definition generators. + // Run any definition generators. for (auto &DG : DefGenerators) { - // Bail out early if we've resolved everything. - if (Unresolved->empty()) + // Bail out early if we found everything. + if (LookupSet.empty()) break; // Run this generator. - auto NewDefs = DG->tryToGenerate(*this, *Unresolved); - if (!NewDefs) - return NewDefs.takeError(); - - if (!NewDefs->empty()) { - auto Unresolved2 = lookupFlagsImpl(Result, *NewDefs); - if (!Unresolved2) - return Unresolved2.takeError(); - (void)Unresolved2; - assert(Unresolved2->empty() && - "All fallback defs should have been found by lookupFlagsImpl"); - } + if (auto Err = DG->tryToGenerate(K, *this, JDLookupFlags, LookupSet)) + return std::move(Err); - for (auto &Name : *NewDefs) - Unresolved->erase(Name); + // Re-try the search. + lookupFlagsImpl(Result, K, JDLookupFlags, LookupSet); } + return Result; }); } -Expected<SymbolNameSet> JITDylib::lookupFlagsImpl(SymbolFlagsMap &Flags, - const SymbolNameSet &Names) { - SymbolNameSet Unresolved; +void JITDylib::lookupFlagsImpl(SymbolFlagsMap &Result, LookupKind K, + JITDylibLookupFlags JDLookupFlags, + SymbolLookupSet &LookupSet) { - for (auto &Name : Names) { - auto I = Symbols.find(Name); - if (I != Symbols.end()) { - assert(!Flags.count(Name) && "Symbol already present in Flags map"); - Flags[Name] = I->second.getFlags(); - } else - Unresolved.insert(Name); - } - - return Unresolved; + LookupSet.forEachWithRemoval( + [&](const SymbolStringPtr &Name, SymbolLookupFlags Flags) -> bool { + auto I = Symbols.find(Name); + if (I == Symbols.end()) + return false; + assert(!Result.count(Name) && "Symbol already present in Flags map"); + Result[Name] = I->second.getFlags(); + return true; + }); } -Error JITDylib::lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q, - SymbolNameSet &Unresolved, bool MatchNonExported, - MaterializationUnitList &MUs) { +Error JITDylib::lodgeQuery(MaterializationUnitList &MUs, + std::shared_ptr<AsynchronousSymbolQuery> &Q, + LookupKind K, JITDylibLookupFlags JDLookupFlags, + SymbolLookupSet &Unresolved) { assert(Q && "Query can not be null"); - if (auto Err = lodgeQueryImpl(Q, Unresolved, MatchNonExported, MUs)) + if (auto Err = lodgeQueryImpl(MUs, Q, K, JDLookupFlags, Unresolved)) return Err; // Run any definition generators. @@ -1416,104 +1472,86 @@ Error JITDylib::lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q, break; // Run the generator. - auto NewDefs = DG->tryToGenerate(*this, Unresolved); - - // If the generator returns an error then bail out. - if (!NewDefs) - return NewDefs.takeError(); - - // If the generator was able to generate new definitions for any of the - // unresolved symbols then lodge the query against them. - if (!NewDefs->empty()) { - for (auto &D : *NewDefs) - Unresolved.erase(D); - - // Lodge query. This can not fail as any new definitions were added - // by the generator under the session locked. Since they can't have - // started materializing yet the can not have failed. - cantFail(lodgeQueryImpl(Q, *NewDefs, MatchNonExported, MUs)); + if (auto Err = DG->tryToGenerate(K, *this, JDLookupFlags, Unresolved)) + return Err; - assert(NewDefs->empty() && - "All fallback defs should have been found by lookupImpl"); - } + // Lodge query. This can not fail as any new definitions were added + // by the generator under the session locked. Since they can't have + // started materializing yet they can not have failed. + cantFail(lodgeQueryImpl(MUs, Q, K, JDLookupFlags, Unresolved)); } return Error::success(); } -Error JITDylib::lodgeQueryImpl( - std::shared_ptr<AsynchronousSymbolQuery> &Q, SymbolNameSet &Unresolved, - bool MatchNonExported, - std::vector<std::unique_ptr<MaterializationUnit>> &MUs) { - - std::vector<SymbolStringPtr> ToRemove; - for (auto Name : Unresolved) { - - // Search for the name in Symbols. Skip it if not found. - auto SymI = Symbols.find(Name); - if (SymI == Symbols.end()) - continue; - - // If this is a non exported symbol and we're skipping those then skip it. - if (!SymI->second.getFlags().isExported() && !MatchNonExported) - continue; - - // If we matched against Name in JD, mark it to be removed from the - // Unresolved set. - ToRemove.push_back(Name); - - // If we matched against this symbol but it is in the error state then - // bail out and treat it as a failure to materialize. - if (SymI->second.getFlags().hasError()) { - auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>(); - (*FailedSymbolsMap)[this] = {Name}; - return make_error<FailedToMaterialize>(std::move(FailedSymbolsMap)); - } - - // If this symbol already meets the required state for then notify the - // query and continue. - if (SymI->second.getState() >= Q->getRequiredState()) { - Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol()); - continue; - } - - // Otherwise this symbol does not yet meet the required state. Check whether - // it has a materializer attached, and if so prepare to run it. - if (SymI->second.hasMaterializerAttached()) { - assert(SymI->second.getAddress() == 0 && - "Symbol not resolved but already has address?"); - auto UMII = UnmaterializedInfos.find(Name); - assert(UMII != UnmaterializedInfos.end() && - "Lazy symbol should have UnmaterializedInfo"); - auto MU = std::move(UMII->second->MU); - assert(MU != nullptr && "Materializer should not be null"); - - // Move all symbols associated with this MaterializationUnit into - // materializing state. - for (auto &KV : MU->getSymbols()) { - auto SymK = Symbols.find(KV.first); - SymK->second.setMaterializerAttached(false); - SymK->second.setState(SymbolState::Materializing); - UnmaterializedInfos.erase(KV.first); - } +Error JITDylib::lodgeQueryImpl(MaterializationUnitList &MUs, + std::shared_ptr<AsynchronousSymbolQuery> &Q, + LookupKind K, JITDylibLookupFlags JDLookupFlags, + SymbolLookupSet &Unresolved) { + + return Unresolved.forEachWithRemoval( + [&](const SymbolStringPtr &Name, + SymbolLookupFlags SymLookupFlags) -> Expected<bool> { + // Search for name in symbols. If not found then continue without + // removal. + auto SymI = Symbols.find(Name); + if (SymI == Symbols.end()) + return false; + + // If this is a non exported symbol and we're matching exported symbols + // only then skip this symbol without removal. + if (!SymI->second.getFlags().isExported() && + JDLookupFlags == JITDylibLookupFlags::MatchExportedSymbolsOnly) + return false; + + // If we matched against this symbol but it is in the error state then + // bail out and treat it as a failure to materialize. + if (SymI->second.getFlags().hasError()) { + auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>(); + (*FailedSymbolsMap)[this] = {Name}; + return make_error<FailedToMaterialize>(std::move(FailedSymbolsMap)); + } - // Add MU to the list of MaterializationUnits to be materialized. - MUs.push_back(std::move(MU)); - } + // If this symbol already meets the required state for then notify the + // query, then remove the symbol and continue. + if (SymI->second.getState() >= Q->getRequiredState()) { + Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol()); + return true; + } - // Add the query to the PendingQueries list. - assert(SymI->second.isInMaterializationPhase() && - "By this line the symbol should be materializing"); - auto &MI = MaterializingInfos[Name]; - MI.addQuery(Q); - Q->addQueryDependence(*this, Name); - } + // Otherwise this symbol does not yet meet the required state. Check + // whether it has a materializer attached, and if so prepare to run it. + if (SymI->second.hasMaterializerAttached()) { + assert(SymI->second.getAddress() == 0 && + "Symbol not resolved but already has address?"); + auto UMII = UnmaterializedInfos.find(Name); + assert(UMII != UnmaterializedInfos.end() && + "Lazy symbol should have UnmaterializedInfo"); + auto MU = std::move(UMII->second->MU); + assert(MU != nullptr && "Materializer should not be null"); + + // Move all symbols associated with this MaterializationUnit into + // materializing state. + for (auto &KV : MU->getSymbols()) { + auto SymK = Symbols.find(KV.first); + SymK->second.setMaterializerAttached(false); + SymK->second.setState(SymbolState::Materializing); + UnmaterializedInfos.erase(KV.first); + } - // Remove any symbols that we found. - for (auto &Name : ToRemove) - Unresolved.erase(Name); + // Add MU to the list of MaterializationUnits to be materialized. + MUs.push_back(std::move(MU)); + } - return Error::success(); + // Add the query to the PendingQueries list and continue, deleting the + // element. + assert(SymI->second.isInMaterializationPhase() && + "By this line the symbol should be materializing"); + auto &MI = MaterializingInfos[Name]; + MI.addQuery(Q); + Q->addQueryDependence(*this, Name); + return true; + }); } Expected<SymbolNameSet> @@ -1526,7 +1564,7 @@ JITDylib::legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q, bool QueryComplete = false; std::vector<std::unique_ptr<MaterializationUnit>> MUs; - SymbolNameSet Unresolved = std::move(Names); + SymbolLookupSet Unresolved(Names); auto Err = ES.runSessionLocked([&, this]() -> Error { QueryComplete = lookupImpl(Q, MUs, Unresolved); @@ -1538,16 +1576,13 @@ JITDylib::legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q, break; assert(!QueryComplete && "query complete but unresolved symbols remain?"); - auto NewDefs = DG->tryToGenerate(*this, Unresolved); - if (!NewDefs) - return NewDefs.takeError(); - if (!NewDefs->empty()) { - for (auto &D : *NewDefs) - Unresolved.erase(D); - QueryComplete = lookupImpl(Q, MUs, *NewDefs); - assert(NewDefs->empty() && - "All fallback defs should have been found by lookupImpl"); - } + if (auto Err = DG->tryToGenerate(LookupKind::Static, *this, + JITDylibLookupFlags::MatchAllSymbols, + Unresolved)) + return Err; + + if (!Unresolved.empty()) + QueryComplete = lookupImpl(Q, MUs, Unresolved); } return Error::success(); }); @@ -1575,68 +1610,68 @@ JITDylib::legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q, // for (auto &MU : MUs) // ES.dispatchMaterialization(*this, std::move(MU)); - return Unresolved; + SymbolNameSet RemainingSymbols; + for (auto &KV : Unresolved) + RemainingSymbols.insert(KV.first); + + return RemainingSymbols; } bool JITDylib::lookupImpl( std::shared_ptr<AsynchronousSymbolQuery> &Q, std::vector<std::unique_ptr<MaterializationUnit>> &MUs, - SymbolNameSet &Unresolved) { + SymbolLookupSet &Unresolved) { bool QueryComplete = false; std::vector<SymbolStringPtr> ToRemove; - for (auto Name : Unresolved) { - - // Search for the name in Symbols. Skip it if not found. - auto SymI = Symbols.find(Name); - if (SymI == Symbols.end()) - continue; - - // If we found Name, mark it to be removed from the Unresolved set. - ToRemove.push_back(Name); - - if (SymI->second.getState() >= Q->getRequiredState()) { - Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol()); - if (Q->isComplete()) - QueryComplete = true; - continue; - } - - // If the symbol is lazy, get the MaterialiaztionUnit for it. - if (SymI->second.hasMaterializerAttached()) { - assert(SymI->second.getAddress() == 0 && - "Lazy symbol should not have a resolved address"); - auto UMII = UnmaterializedInfos.find(Name); - assert(UMII != UnmaterializedInfos.end() && - "Lazy symbol should have UnmaterializedInfo"); - auto MU = std::move(UMII->second->MU); - assert(MU != nullptr && "Materializer should not be null"); - - // Kick all symbols associated with this MaterializationUnit into - // materializing state. - for (auto &KV : MU->getSymbols()) { - auto SymK = Symbols.find(KV.first); - assert(SymK != Symbols.end() && "Missing symbol table entry"); - SymK->second.setState(SymbolState::Materializing); - SymK->second.setMaterializerAttached(false); - UnmaterializedInfos.erase(KV.first); - } + Unresolved.forEachWithRemoval( + [&](const SymbolStringPtr &Name, SymbolLookupFlags Flags) -> bool { + // Search for the name in Symbols. Skip without removing if not found. + auto SymI = Symbols.find(Name); + if (SymI == Symbols.end()) + return false; + + // If the symbol is already in the required state then notify the query + // and remove. + if (SymI->second.getState() >= Q->getRequiredState()) { + Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol()); + if (Q->isComplete()) + QueryComplete = true; + return true; + } - // Add MU to the list of MaterializationUnits to be materialized. - MUs.push_back(std::move(MU)); - } + // If the symbol is lazy, get the MaterialiaztionUnit for it. + if (SymI->second.hasMaterializerAttached()) { + assert(SymI->second.getAddress() == 0 && + "Lazy symbol should not have a resolved address"); + auto UMII = UnmaterializedInfos.find(Name); + assert(UMII != UnmaterializedInfos.end() && + "Lazy symbol should have UnmaterializedInfo"); + auto MU = std::move(UMII->second->MU); + assert(MU != nullptr && "Materializer should not be null"); + + // Kick all symbols associated with this MaterializationUnit into + // materializing state. + for (auto &KV : MU->getSymbols()) { + auto SymK = Symbols.find(KV.first); + assert(SymK != Symbols.end() && "Missing symbol table entry"); + SymK->second.setState(SymbolState::Materializing); + SymK->second.setMaterializerAttached(false); + UnmaterializedInfos.erase(KV.first); + } - // Add the query to the PendingQueries list. - assert(SymI->second.isInMaterializationPhase() && - "By this line the symbol should be materializing"); - auto &MI = MaterializingInfos[Name]; - MI.addQuery(Q); - Q->addQueryDependence(*this, Name); - } + // Add MU to the list of MaterializationUnits to be materialized. + MUs.push_back(std::move(MU)); + } - // Remove any marked symbols from the Unresolved set. - for (auto &Name : ToRemove) - Unresolved.erase(Name); + // Add the query to the PendingQueries list. + assert(SymI->second.isInMaterializationPhase() && + "By this line the symbol should be materializing"); + auto &MI = MaterializingInfos[Name]; + MI.addQuery(Q); + Q->addQueryDependence(*this, Name); + return true; + }); return QueryComplete; } @@ -1645,11 +1680,7 @@ void JITDylib::dump(raw_ostream &OS) { ES.runSessionLocked([&, this]() { OS << "JITDylib \"" << JITDylibName << "\" (ES: " << format("0x%016" PRIx64, reinterpret_cast<uintptr_t>(&ES)) << "):\n" - << "Search order: ["; - for (auto &KV : SearchOrder) - OS << " (\"" << KV.first->getName() << "\", " - << (KV.second ? "all" : "exported only") << ")"; - OS << " ]\n" + << "Search order: " << SearchOrder << "\n" << "Symbol table:\n"; for (auto &KV : Symbols) { @@ -1730,7 +1761,7 @@ JITDylib::MaterializingInfo::takeQueriesMeeting(SymbolState RequiredState) { JITDylib::JITDylib(ExecutionSession &ES, std::string Name) : ES(ES), JITDylibName(std::move(Name)) { - SearchOrder.push_back({this, true}); + SearchOrder.push_back({this, JITDylibLookupFlags::MatchAllSymbols}); } Error JITDylib::defineImpl(MaterializationUnit &MU) { @@ -1898,7 +1929,7 @@ Expected<SymbolMap> ExecutionSession::legacyLookup( #endif auto Query = std::make_shared<AsynchronousSymbolQuery>( - Names, RequiredState, std::move(NotifyComplete)); + SymbolLookupSet(Names), RequiredState, std::move(NotifyComplete)); // FIXME: This should be run session locked along with the registration code // and error reporting below. SymbolNameSet UnresolvedSymbols = AsyncLookup(Query, std::move(Names)); @@ -1935,8 +1966,9 @@ Expected<SymbolMap> ExecutionSession::legacyLookup( } void ExecutionSession::lookup( - const JITDylibSearchList &SearchOrder, SymbolNameSet Symbols, - SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete, + LookupKind K, const JITDylibSearchOrder &SearchOrder, + SymbolLookupSet Symbols, SymbolState RequiredState, + SymbolsResolvedCallback NotifyComplete, RegisterDependenciesFunction RegisterDependencies) { LLVM_DEBUG({ @@ -1965,14 +1997,24 @@ void ExecutionSession::lookup( "JITDylibList should not contain duplicate entries"); auto &JD = *KV.first; - auto MatchNonExported = KV.second; - if (auto Err = JD.lodgeQuery(Q, Unresolved, MatchNonExported, - CollectedMUsMap[&JD])) + auto JDLookupFlags = KV.second; + if (auto Err = JD.lodgeQuery(CollectedMUsMap[&JD], Q, K, JDLookupFlags, + Unresolved)) return Err; } + // Strip any weakly referenced symbols that were not found. + Unresolved.forEachWithRemoval( + [&](const SymbolStringPtr &Name, SymbolLookupFlags Flags) { + if (Flags == SymbolLookupFlags::WeaklyReferencedSymbol) { + Q->dropSymbol(Name); + return true; + } + return false; + }); + if (!Unresolved.empty()) - return make_error<SymbolsNotFound>(std::move(Unresolved)); + return make_error<SymbolsNotFound>(Unresolved.getSymbolNames()); return Error::success(); }; @@ -2026,8 +2068,8 @@ void ExecutionSession::lookup( } Expected<SymbolMap> -ExecutionSession::lookup(const JITDylibSearchList &SearchOrder, - const SymbolNameSet &Symbols, +ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder, + const SymbolLookupSet &Symbols, LookupKind K, SymbolState RequiredState, RegisterDependenciesFunction RegisterDependencies) { #if LLVM_ENABLE_THREADS @@ -2059,7 +2101,7 @@ ExecutionSession::lookup(const JITDylibSearchList &SearchOrder, #endif // Perform the asynchronous lookup. - lookup(SearchOrder, Symbols, RequiredState, NotifyComplete, + lookup(K, SearchOrder, Symbols, RequiredState, NotifyComplete, RegisterDependencies); #if LLVM_ENABLE_THREADS @@ -2080,12 +2122,12 @@ ExecutionSession::lookup(const JITDylibSearchList &SearchOrder, } Expected<JITEvaluatedSymbol> -ExecutionSession::lookup(const JITDylibSearchList &SearchOrder, +ExecutionSession::lookup(const JITDylibSearchOrder &SearchOrder, SymbolStringPtr Name) { - SymbolNameSet Names({Name}); + SymbolLookupSet Names({Name}); - if (auto ResultMap = lookup(SearchOrder, std::move(Names), SymbolState::Ready, - NoDependenciesToRegister)) { + if (auto ResultMap = lookup(SearchOrder, std::move(Names), LookupKind::Static, + SymbolState::Ready, NoDependenciesToRegister)) { assert(ResultMap->size() == 1 && "Unexpected number of results"); assert(ResultMap->count(Name) && "Missing result for symbol"); return std::move(ResultMap->begin()->second); @@ -2096,14 +2138,7 @@ ExecutionSession::lookup(const JITDylibSearchList &SearchOrder, Expected<JITEvaluatedSymbol> ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, SymbolStringPtr Name) { - SymbolNameSet Names({Name}); - - JITDylibSearchList FullSearchOrder; - FullSearchOrder.reserve(SearchOrder.size()); - for (auto *JD : SearchOrder) - FullSearchOrder.push_back({JD, false}); - - return lookup(FullSearchOrder, Name); + return lookup(makeJITDylibSearchOrder(SearchOrder), Name); } Expected<JITEvaluatedSymbol> diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp index 4a886ac0597..4a3482242db 100644 --- a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp @@ -118,19 +118,17 @@ void CtorDtorRunner::add(iterator_range<CtorDtorIterator> CtorDtors) { Error CtorDtorRunner::run() { using CtorDtorTy = void (*)(); - SymbolNameSet Names; - - for (auto &KV : CtorDtorsByPriority) { - for (auto &Name : KV.second) { - auto Added = Names.insert(Name).second; - (void)Added; - assert(Added && "Ctor/Dtor names clashed"); - } - } + SymbolLookupSet LookupSet; + for (auto &KV : CtorDtorsByPriority) + for (auto &Name : KV.second) + LookupSet.add(Name); + assert(!LookupSet.containsDuplicates() && + "Ctor/Dtor list contains duplicates"); auto &ES = JD.getExecutionSession(); - if (auto CtorDtorMap = - ES.lookup(JITDylibSearchList({{&JD, true}}), std::move(Names))) { + if (auto CtorDtorMap = ES.lookup( + makeJITDylibSearchOrder(&JD, JITDylibLookupFlags::MatchAllSymbols), + std::move(LookupSet))) { for (auto &KV : CtorDtorsByPriority) { for (auto &Name : KV.second) { assert(CtorDtorMap->count(Name) && "No entry for Name"); @@ -190,15 +188,16 @@ DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix, std::move(Lib), GlobalPrefix, std::move(Allow)); } -Expected<SymbolNameSet> -DynamicLibrarySearchGenerator::tryToGenerate(JITDylib &JD, - const SymbolNameSet &Names) { - orc::SymbolNameSet Added; +Error DynamicLibrarySearchGenerator::tryToGenerate( + LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags, + const SymbolLookupSet &Symbols) { orc::SymbolMap NewSymbols; bool HasGlobalPrefix = (GlobalPrefix != '\0'); - for (auto &Name : Names) { + for (auto &KV : Symbols) { + auto &Name = KV.first; + if ((*Name).empty()) continue; @@ -211,20 +210,16 @@ DynamicLibrarySearchGenerator::tryToGenerate(JITDylib &JD, std::string Tmp((*Name).data() + HasGlobalPrefix, (*Name).size() - HasGlobalPrefix); if (void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str())) { - Added.insert(Name); NewSymbols[Name] = JITEvaluatedSymbol( static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Addr)), JITSymbolFlags::Exported); } } - // Add any new symbols to JD. Since the generator is only called for symbols - // that are not already defined, this will never trigger a duplicate - // definition error, so we can wrap this call in a 'cantFail'. - if (!NewSymbols.empty()) - cantFail(JD.define(absoluteSymbols(std::move(NewSymbols)))); + if (NewSymbols.empty()) + return Error::success(); - return Added; + return JD.define(absoluteSymbols(std::move(NewSymbols))); } Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> @@ -251,15 +246,24 @@ StaticLibraryDefinitionGenerator::Create( return std::move(ADG); } -Expected<SymbolNameSet> -StaticLibraryDefinitionGenerator::tryToGenerate(JITDylib &JD, - const SymbolNameSet &Names) { +Error StaticLibraryDefinitionGenerator::tryToGenerate( + LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags, + const SymbolLookupSet &Symbols) { + + // Don't materialize symbols from static archives unless this is a static + // lookup. + if (K != LookupKind::Static) + return Error::success(); + + // Bail out early if we've already freed the archive. + if (!Archive) + return Error::success(); DenseSet<std::pair<StringRef, StringRef>> ChildBufferInfos; - SymbolNameSet NewDefs; - for (const auto &Name : Names) { - auto Child = Archive.findSym(*Name); + for (const auto &KV : Symbols) { + const auto &Name = KV.first; + auto Child = Archive->findSym(*Name); if (!Child) return Child.takeError(); if (*Child == None) @@ -269,7 +273,6 @@ StaticLibraryDefinitionGenerator::tryToGenerate(JITDylib &JD, return ChildBuffer.takeError(); ChildBufferInfos.insert( {ChildBuffer->getBuffer(), ChildBuffer->getBufferIdentifier()}); - NewDefs.insert(Name); } for (auto ChildBufferInfo : ChildBufferInfos) { @@ -278,31 +281,16 @@ StaticLibraryDefinitionGenerator::tryToGenerate(JITDylib &JD, if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef), VModuleKey())) - return std::move(Err); - - --UnrealizedObjects; + return Err; } - return NewDefs; + return Error::success(); } StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator( ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, Error &Err) : L(L), ArchiveBuffer(std::move(ArchiveBuffer)), - Archive(*this->ArchiveBuffer, Err) { - - if (Err) - return; - - Error Err2 = Error::success(); - for (auto _ : Archive.children(Err2)) { - (void)_; - ++UnrealizedObjects; - } - - // No need to check this: We will leave it to the caller. - Err = std::move(Err2); -} + Archive(std::make_unique<object::Archive>(*this->ArchiveBuffer, Err)) {} } // End namespace orc. } // End namespace llvm. diff --git a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp index 0295db7633d..440935ffe9f 100644 --- a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp @@ -101,7 +101,10 @@ JITTargetAddress JITCompileCallbackManager::executeCompileCallback( Name = I->second; } - if (auto Sym = ES.lookup(JITDylibSearchList({{&CallbacksJD, true}}), Name)) + if (auto Sym = + ES.lookup(makeJITDylibSearchOrder( + &CallbacksJD, JITDylibLookupFlags::MatchAllSymbols), + Name)) return Sym->getAddress(); else { llvm::dbgs() << "Didn't find callback.\n"; diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp index 03f22e0c2a2..fb5515ca64d 100644 --- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp +++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp @@ -56,7 +56,9 @@ Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) { Expected<JITEvaluatedSymbol> LLJIT::lookupLinkerMangled(JITDylib &JD, StringRef Name) { - return ES->lookup(JITDylibSearchList({{&JD, true}}), ES->intern(Name)); + return ES->lookup( + makeJITDylibSearchOrder(&JD, JITDylibLookupFlags::MatchAllSymbols), + ES->intern(Name)); } std::unique_ptr<ObjectLayer> diff --git a/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp b/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp index 93aabd817d6..aab490feb8e 100644 --- a/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp +++ b/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp @@ -50,8 +50,10 @@ LazyCallThroughManager::callThroughToSymbol(JITTargetAddress TrampolineAddr) { SourceJD = I->second.first; SymbolName = I->second.second; } - auto LookupResult = - ES.lookup(JITDylibSearchList({{SourceJD, true}}), SymbolName); + + auto LookupResult = ES.lookup( + makeJITDylibSearchOrder(SourceJD, JITDylibLookupFlags::MatchAllSymbols), + SymbolName); if (!LookupResult) { ES.reportError(LookupResult.takeError()); diff --git a/llvm/lib/ExecutionEngine/Orc/Legacy.cpp b/llvm/lib/ExecutionEngine/Orc/Legacy.cpp index 9f9a6730b2c..67b804c3728 100644 --- a/llvm/lib/ExecutionEngine/Orc/Legacy.cpp +++ b/llvm/lib/ExecutionEngine/Orc/Legacy.cpp @@ -37,7 +37,8 @@ void JITSymbolResolverAdapter::lookup(const LookupSet &Symbols, }; auto Q = std::make_shared<AsynchronousSymbolQuery>( - InternedSymbols, SymbolState::Resolved, std::move(OnResolvedWithUnwrap)); + SymbolLookupSet(InternedSymbols), SymbolState::Resolved, + std::move(OnResolvedWithUnwrap)); auto Unresolved = R.lookup(Q, InternedSymbols); if (Unresolved.empty()) { diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp index 874decb2ade..be0ce4a1d75 100644 --- a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp +++ b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp @@ -47,18 +47,28 @@ public: MR.failMaterialization(); } - void lookup(const DenseSet<StringRef> &Symbols, + void lookup(const LookupMap &Symbols, std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override { - JITDylibSearchList SearchOrder; + JITDylibSearchOrder SearchOrder; MR.getTargetJITDylib().withSearchOrderDo( - [&](const JITDylibSearchList &JDs) { SearchOrder = JDs; }); + [&](const JITDylibSearchOrder &O) { SearchOrder = O; }); auto &ES = Layer.getExecutionSession(); - SymbolNameSet InternedSymbols; - for (auto &S : Symbols) - InternedSymbols.insert(ES.intern(S)); + SymbolLookupSet LookupSet; + for (auto &KV : Symbols) { + orc::SymbolLookupFlags LookupFlags; + switch (KV.second) { + case jitlink::SymbolLookupFlags::RequiredSymbol: + LookupFlags = orc::SymbolLookupFlags::RequiredSymbol; + break; + case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol: + LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol; + break; + } + LookupSet.add(ES.intern(KV.first), LookupFlags); + } // OnResolve -- De-intern the symbols and pass the result to the linker. auto OnResolve = [this, LookupContinuation = std::move(LC)]( @@ -74,8 +84,9 @@ public: } }; - ES.lookup(SearchOrder, std::move(InternedSymbols), SymbolState::Resolved, - std::move(OnResolve), [this](const SymbolDependenceMap &Deps) { + ES.lookup(LookupKind::Static, SearchOrder, std::move(LookupSet), + SymbolState::Resolved, std::move(OnResolve), + [this](const SymbolDependenceMap &Deps) { registerDependencies(Deps); }); } diff --git a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp index 939cd539d1f..3344bd4d53f 100644 --- a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp +++ b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp @@ -19,11 +19,11 @@ public: void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) { auto &ES = MR.getTargetJITDylib().getExecutionSession(); - SymbolNameSet InternedSymbols; + SymbolLookupSet InternedSymbols; // Intern the requested symbols: lookup takes interned strings. for (auto &S : Symbols) - InternedSymbols.insert(ES.intern(S)); + InternedSymbols.add(ES.intern(S)); // Build an OnResolve callback to unwrap the interned strings and pass them // to the OnResolved callback. @@ -46,11 +46,12 @@ public: MR.addDependenciesForAll(Deps); }; - JITDylibSearchList SearchOrder; + JITDylibSearchOrder SearchOrder; MR.getTargetJITDylib().withSearchOrderDo( - [&](const JITDylibSearchList &JDs) { SearchOrder = JDs; }); - ES.lookup(SearchOrder, InternedSymbols, SymbolState::Resolved, - std::move(OnResolvedWithUnwrap), RegisterDependencies); + [&](const JITDylibSearchOrder &JDs) { SearchOrder = JDs; }); + ES.lookup(LookupKind::Static, SearchOrder, InternedSymbols, + SymbolState::Resolved, std::move(OnResolvedWithUnwrap), + RegisterDependencies); } Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) { diff --git a/llvm/test/ExecutionEngine/JITLink/X86/MachO_weak_references.s b/llvm/test/ExecutionEngine/JITLink/X86/MachO_weak_references.s new file mode 100644 index 00000000000..20fa5536302 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/X86/MachO_weak_references.s @@ -0,0 +1,19 @@ +# RUN: rm -rf %t && mkdir -p %t +# RUN: llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj -o %t/macho_weak_refs.o %s +# RUN: llvm-jitlink -noexec -check-name=jitlink-check-bar-present -define-abs bar=0x1 -check=%s %t/macho_weak_refs.o +# RUN: llvm-jitlink -noexec -check-name=jitlink-check-bar-absent -check=%s %t/macho_weak_refs.o + +# Test weak reference handling by linking with and without a definition of 'bar' available. + + .section __TEXT,__text,regular,pure_instructions + .build_version macos, 10, 14 sdk_version 10, 14 + .globl _main + .p2align 4, 0x90 +_main: +# jitlink-check-bar-present: *{8}(got_addr(macho_weak_refs.o, bar)) = bar +# jitlink-check-bar-absent: *{8}(got_addr(macho_weak_refs.o, bar)) = 0 + cmpq $0, bar@GOTPCREL(%rip) + + .weak_reference bar + +.subsections_via_symbols diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp index 251e79cf56d..003a333d956 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp +++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp @@ -57,6 +57,10 @@ static cl::list<std::string> cl::ZeroOrMore); static cl::opt<std::string> + CheckName("check-name", cl::desc("Name of checks to match against"), + cl::init("jitlink-check")); + +static cl::opt<std::string> EntryPointName("entry", cl::desc("Symbol to call as main entry point"), cl::init("")); @@ -604,11 +608,12 @@ Error loadObjects(Session &S) { // Set every dylib to link against every other, in command line order. for (auto *JD : S.JDSearchOrder) { - JITDylibSearchList O; + auto LookupFlags = JITDylibLookupFlags::MatchExportedSymbolsOnly; + JITDylibSearchOrder O; for (auto *JD2 : S.JDSearchOrder) { if (JD2 == JD) continue; - O.push_back(std::make_pair(JD2, false)); + O.push_back(std::make_pair(JD2, LookupFlags)); } JD->setSearchOrder(std::move(O)); } @@ -741,10 +746,11 @@ Error runChecks(Session &S) { S.TT.isLittleEndian() ? support::little : support::big, Disassembler.get(), InstPrinter.get(), dbgs()); + std::string CheckLineStart = "# " + CheckName + ":"; for (auto &CheckFile : CheckFiles) { auto CheckerFileBuf = ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(CheckFile))); - if (!Checker.checkAllRulesInBuffer("# jitlink-check:", &*CheckerFileBuf)) + if (!Checker.checkAllRulesInBuffer(CheckLineStart, &*CheckerFileBuf)) ExitOnErr(make_error<StringError>( "Some checks in " + CheckFile + " failed", inconvertibleErrorCode())); } diff --git a/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp b/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp index 3e16a50d07b..68a6d2ed2ca 100644 --- a/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp @@ -43,8 +43,9 @@ TEST_F(CoreAPIsStandardTest, BasicSuccessfulLookup) { FooMR = std::make_shared<MaterializationResponsibility>(std::move(R)); }))); - ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, - OnCompletion, NoDependenciesToRegister); + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet(Foo), SymbolState::Ready, OnCompletion, + NoDependenciesToRegister); EXPECT_FALSE(OnCompletionRun) << "Should not have been resolved yet"; @@ -67,7 +68,7 @@ TEST_F(CoreAPIsStandardTest, ExecutionSessionFailQuery) { OnCompletionRun = true; }; - AsynchronousSymbolQuery Q(SymbolNameSet({Foo}), SymbolState::Ready, + AsynchronousSymbolQuery Q(SymbolLookupSet(Foo), SymbolState::Ready, OnCompletion); ES.legacyFailQuery(Q, @@ -84,8 +85,8 @@ TEST_F(CoreAPIsStandardTest, EmptyLookup) { OnCompletionRun = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), {}, SymbolState::Ready, - OnCompletion, NoDependenciesToRegister); + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(), + SymbolState::Ready, OnCompletion, NoDependenciesToRegister); EXPECT_TRUE(OnCompletionRun) << "OnCompletion was not run for empty query"; } @@ -131,7 +132,8 @@ TEST_F(CoreAPIsStandardTest, RemoveSymbolsTest) { bool OnCompletionRun = false; ES.lookup( - JITDylibSearchList({{&JD, false}}), {Foo, Baz}, SymbolState::Ready, + LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet({Foo, Baz}), SymbolState::Ready, [&](Expected<SymbolMap> Result) { cantFail(Result.takeError()); OnCompletionRun = true; @@ -179,7 +181,7 @@ TEST_F(CoreAPIsStandardTest, ChainedJITDylibLookup) { bool OnCompletionRun = false; auto Q = std::make_shared<AsynchronousSymbolQuery>( - SymbolNameSet({Foo}), SymbolState::Ready, + SymbolLookupSet({Foo}), SymbolState::Ready, [&](Expected<SymbolMap> Result) { cantFail(std::move(Result)); OnCompletionRun = true; @@ -200,8 +202,8 @@ TEST_F(CoreAPIsStandardTest, LookupWithHiddenSymbols) { cantFail(JD2.define(absoluteSymbols({{Bar, QuxSym}}))); /// Try a blocking lookup. - auto Result = cantFail( - ES.lookup(JITDylibSearchList({{&JD, false}, {&JD2, false}}), {Foo, Bar})); + auto Result = cantFail(ES.lookup(makeJITDylibSearchOrder({&JD, &JD2}), + SymbolLookupSet({Foo, Bar}))); EXPECT_EQ(Result.size(), 2U) << "Unexpected number of results"; EXPECT_EQ(Result.count(Foo), 1U) << "Missing result for \"Foo\""; @@ -226,9 +228,9 @@ TEST_F(CoreAPIsStandardTest, LookupFlagsTest) { cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); cantFail(JD.define(std::move(MU))); - SymbolNameSet Names({Foo, Bar, Baz}); - - auto SymbolFlags = cantFail(JD.lookupFlags(Names)); + auto SymbolFlags = cantFail(JD.lookupFlags( + LookupKind::Static, JITDylibLookupFlags::MatchExportedSymbolsOnly, + SymbolLookupSet({Foo, Bar, Baz}))); EXPECT_EQ(SymbolFlags.size(), 2U) << "Returned symbol flags contains unexpected results"; @@ -245,20 +247,24 @@ TEST_F(CoreAPIsStandardTest, LookupWithGeneratorFailure) { class BadGenerator : public JITDylib::DefinitionGenerator { public: - Expected<SymbolNameSet> tryToGenerate(JITDylib &, - const SymbolNameSet &) override { + Error tryToGenerate(LookupKind K, JITDylib &, JITDylibLookupFlags, + const SymbolLookupSet &) override { return make_error<StringError>("BadGenerator", inconvertibleErrorCode()); } }; JD.addGenerator(std::make_unique<BadGenerator>()); - EXPECT_THAT_ERROR(JD.lookupFlags({Foo}).takeError(), Failed<StringError>()) + EXPECT_THAT_ERROR( + JD.lookupFlags(LookupKind::Static, + JITDylibLookupFlags::MatchExportedSymbolsOnly, + SymbolLookupSet(Foo)) + .takeError(), + Failed<StringError>()) << "Generator failure did not propagate through lookupFlags"; EXPECT_THAT_ERROR( - ES.lookup(JITDylibSearchList({{&JD, false}}), SymbolNameSet({Foo})) - .takeError(), + ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo)).takeError(), Failed<StringError>()) << "Generator failure did not propagate through lookup"; } @@ -269,7 +275,8 @@ TEST_F(CoreAPIsStandardTest, TestBasicAliases) { {Qux, {Bar, JITSymbolFlags::Weak}}}))); cantFail(JD.define(absoluteSymbols({{Qux, QuxSym}}))); - auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), {Baz, Qux}); + auto Result = + ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Baz, Qux})); EXPECT_TRUE(!!Result) << "Unexpected lookup failure"; EXPECT_EQ(Result->count(Baz), 1U) << "No result for \"baz\""; EXPECT_EQ(Result->count(Qux), 1U) << "No result for \"qux\""; @@ -284,7 +291,8 @@ TEST_F(CoreAPIsStandardTest, TestChainedAliases) { cantFail(JD.define(symbolAliases( {{Baz, {Bar, BazSym.getFlags()}}, {Bar, {Foo, BarSym.getFlags()}}}))); - auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar, Baz}); + auto Result = + ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Bar, Baz})); EXPECT_TRUE(!!Result) << "Unexpected lookup failure"; EXPECT_EQ(Result->count(Bar), 1U) << "No result for \"bar\""; EXPECT_EQ(Result->count(Baz), 1U) << "No result for \"baz\""; @@ -303,7 +311,7 @@ TEST_F(CoreAPIsStandardTest, TestBasicReExports) { cantFail(JD2.define(reexports(JD, {{Bar, {Foo, BarSym.getFlags()}}}))); - auto Result = cantFail(ES.lookup(JITDylibSearchList({{&JD2, false}}), Bar)); + auto Result = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD2), Bar)); EXPECT_EQ(Result.getAddress(), FooSym.getAddress()) << "Re-export Bar for symbol Foo should match FooSym's address"; } @@ -329,7 +337,7 @@ TEST_F(CoreAPIsStandardTest, TestThatReExportsDontUnnecessarilyMaterialize) { cantFail(JD2.define(reexports( JD, {{Baz, {Foo, BazSym.getFlags()}}, {Qux, {Bar, QuxSym.getFlags()}}}))); - auto Result = cantFail(ES.lookup(JITDylibSearchList({{&JD2, false}}), Baz)); + auto Result = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD2), Baz)); EXPECT_EQ(Result.getAddress(), FooSym.getAddress()) << "Re-export Baz for symbol Foo should match FooSym's address"; @@ -344,13 +352,16 @@ TEST_F(CoreAPIsStandardTest, TestReexportsGenerator) { auto Filter = [this](SymbolStringPtr Name) { return Name != Bar; }; - JD.addGenerator(std::make_unique<ReexportsGenerator>(JD2, false, Filter)); + JD.addGenerator(std::make_unique<ReexportsGenerator>( + JD2, JITDylibLookupFlags::MatchExportedSymbolsOnly, Filter)); - auto Flags = cantFail(JD.lookupFlags({Foo, Bar, Baz})); + auto Flags = cantFail(JD.lookupFlags( + LookupKind::Static, JITDylibLookupFlags::MatchExportedSymbolsOnly, + SymbolLookupSet({Foo, Bar, Baz}))); EXPECT_EQ(Flags.size(), 1U) << "Unexpected number of results"; EXPECT_EQ(Flags[Foo], FooSym.getFlags()) << "Unexpected flags for Foo"; - auto Result = cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); + auto Result = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Foo)); EXPECT_EQ(Result.getAddress(), FooSym.getAddress()) << "Incorrect reexported symbol address"; @@ -370,8 +381,9 @@ TEST_F(CoreAPIsStandardTest, TestTrivialCircularDependency) { FooReady = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, - OnCompletion, NoDependenciesToRegister); + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet({Foo}), SymbolState::Ready, OnCompletion, + NoDependenciesToRegister); FooR->addDependenciesForAll({{&JD, SymbolNameSet({Foo})}}); EXPECT_THAT_ERROR(FooR->notifyResolved({{Foo, FooSym}}), Succeeded()) @@ -430,11 +442,13 @@ TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneJITDylib) { // Issue lookups for Foo. Use NoDependenciesToRegister: We're going to add // the dependencies manually below. - ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Resolved, + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet(Foo), SymbolState::Resolved, std::move(OnFooResolution), NoDependenciesToRegister); - ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, - std::move(OnFooReady), NoDependenciesToRegister); + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet(Foo), SymbolState::Ready, std::move(OnFooReady), + NoDependenciesToRegister); bool BarResolved = false; bool BarReady = false; @@ -448,11 +462,13 @@ TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneJITDylib) { BarReady = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Resolved, + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet(Bar), SymbolState::Resolved, std::move(OnBarResolution), NoDependenciesToRegister); - ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Ready, - std::move(OnBarReady), NoDependenciesToRegister); + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet(Bar), SymbolState::Ready, std::move(OnBarReady), + NoDependenciesToRegister); bool BazResolved = false; bool BazReady = false; @@ -467,11 +483,13 @@ TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneJITDylib) { BazReady = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), {Baz}, SymbolState::Resolved, + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet(Baz), SymbolState::Resolved, std::move(OnBazResolution), NoDependenciesToRegister); - ES.lookup(JITDylibSearchList({{&JD, false}}), {Baz}, SymbolState::Ready, - std::move(OnBazReady), NoDependenciesToRegister); + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet(Baz), SymbolState::Ready, std::move(OnBazReady), + NoDependenciesToRegister); // Add a circular dependency: Foo -> Bar, Bar -> Baz, Baz -> Foo. FooR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}}); @@ -551,8 +569,9 @@ TEST_F(CoreAPIsStandardTest, FailureInDependency) { OnFooReadyRun = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, - std::move(OnFooReady), NoDependenciesToRegister); + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet(Foo), SymbolState::Ready, std::move(OnFooReady), + NoDependenciesToRegister); bool OnBarReadyRun = false; auto OnBarReady = [&](Expected<SymbolMap> Result) { @@ -560,8 +579,9 @@ TEST_F(CoreAPIsStandardTest, FailureInDependency) { OnBarReadyRun = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Ready, - std::move(OnBarReady), NoDependenciesToRegister); + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet(Bar), SymbolState::Ready, std::move(OnBarReady), + NoDependenciesToRegister); // Add a dependency by Foo on Bar. FooR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}}); @@ -614,8 +634,9 @@ TEST_F(CoreAPIsStandardTest, FailureInCircularDependency) { OnFooReadyRun = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, - std::move(OnFooReady), NoDependenciesToRegister); + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet(Foo), SymbolState::Ready, std::move(OnFooReady), + NoDependenciesToRegister); bool OnBarReadyRun = false; auto OnBarReady = [&](Expected<SymbolMap> Result) { @@ -623,8 +644,9 @@ TEST_F(CoreAPIsStandardTest, FailureInCircularDependency) { OnBarReadyRun = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Ready, - std::move(OnBarReady), NoDependenciesToRegister); + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet(Bar), SymbolState::Ready, std::move(OnBarReady), + NoDependenciesToRegister); // Add a dependency by Foo on Bar and vice-versa. FooR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}}); @@ -678,8 +700,9 @@ TEST_F(CoreAPIsStandardTest, AddDependencyOnFailedSymbol) { OnFooReadyRun = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, - std::move(OnFooReady), NoDependenciesToRegister); + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet(Foo), SymbolState::Ready, std::move(OnFooReady), + NoDependenciesToRegister); bool OnBarReadyRun = false; auto OnBarReady = [&](Expected<SymbolMap> Result) { @@ -687,8 +710,9 @@ TEST_F(CoreAPIsStandardTest, AddDependencyOnFailedSymbol) { OnBarReadyRun = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Ready, - std::move(OnBarReady), NoDependenciesToRegister); + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet(Bar), SymbolState::Ready, std::move(OnBarReady), + NoDependenciesToRegister); // Fail bar. BarR->failMaterialization(); @@ -742,8 +766,9 @@ TEST_F(CoreAPIsStandardTest, FailAfterMaterialization) { OnFooReadyRun = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, - std::move(OnFooReady), NoDependenciesToRegister); + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet(Foo), SymbolState::Ready, std::move(OnFooReady), + NoDependenciesToRegister); bool OnBarReadyRun = false; auto OnBarReady = [&](Expected<SymbolMap> Result) { @@ -751,8 +776,9 @@ TEST_F(CoreAPIsStandardTest, FailAfterMaterialization) { OnBarReadyRun = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Ready, - std::move(OnBarReady), NoDependenciesToRegister); + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet(Bar), SymbolState::Ready, std::move(OnBarReady), + NoDependenciesToRegister); // Add a dependency by Foo on Bar and vice-versa. FooR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}}); @@ -854,8 +880,6 @@ TEST_F(CoreAPIsStandardTest, AddAndMaterializeLazySymbol) { cantFail(JD.define(MU)); cantFail(JD.define(absoluteSymbols({{Bar, BarSym}}))); - SymbolNameSet Names({Foo}); - bool OnCompletionRun = false; auto OnCompletion = [&](Expected<SymbolMap> Result) { @@ -867,8 +891,9 @@ TEST_F(CoreAPIsStandardTest, AddAndMaterializeLazySymbol) { OnCompletionRun = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), Names, SymbolState::Ready, - std::move(OnCompletion), NoDependenciesToRegister); + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet(Foo), SymbolState::Ready, std::move(OnCompletion), + NoDependenciesToRegister); EXPECT_TRUE(FooMaterialized) << "Foo was not materialized"; EXPECT_TRUE(BarDiscarded) << "Bar was not discarded"; @@ -910,8 +935,9 @@ TEST_F(CoreAPIsStandardTest, TestBasicWeakSymbolMaterialization) { OnCompletionRun = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Ready, - std::move(OnCompletion), NoDependenciesToRegister); + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet(Bar), SymbolState::Ready, std::move(OnCompletion), + NoDependenciesToRegister); EXPECT_TRUE(OnCompletionRun) << "OnCompletion not run"; EXPECT_TRUE(BarMaterialized) << "Bar was not materialized at all"; @@ -938,13 +964,13 @@ TEST_F(CoreAPIsStandardTest, DefineMaterializingSymbol) { }); cantFail(JD.define(MU)); - cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); + cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Foo)); // Assert that materialization is complete by now. ExpectNoMoreMaterialization = true; // Look up bar to verify that no further materialization happens. - auto BarResult = cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Bar)); + auto BarResult = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Bar)); EXPECT_EQ(BarResult.getAddress(), BarSym.getAddress()) << "Expected Bar == BarSym"; } @@ -955,19 +981,19 @@ TEST_F(CoreAPIsStandardTest, GeneratorTest) { class TestGenerator : public JITDylib::DefinitionGenerator { public: TestGenerator(SymbolMap Symbols) : Symbols(std::move(Symbols)) {} - Expected<SymbolNameSet> tryToGenerate(JITDylib &JD, - const SymbolNameSet &Names) { + Error tryToGenerate(LookupKind K, JITDylib &JD, + JITDylibLookupFlags JDLookupFlags, + const SymbolLookupSet &Names) { SymbolMap NewDefs; - SymbolNameSet NewNames; - for (auto &Name : Names) { - if (Symbols.count(Name)) { + for (const auto &KV : Names) { + const auto &Name = KV.first; + if (Symbols.count(Name)) NewDefs[Name] = Symbols[Name]; - NewNames.insert(Name); - } } + cantFail(JD.define(absoluteSymbols(std::move(NewDefs)))); - return NewNames; + return Error::success(); }; private: @@ -976,8 +1002,8 @@ TEST_F(CoreAPIsStandardTest, GeneratorTest) { JD.addGenerator(std::make_unique<TestGenerator>(SymbolMap({{Bar, BarSym}}))); - auto Result = - cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo, Bar})); + auto Result = cantFail( + ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Foo, Bar}))); EXPECT_EQ(Result.count(Bar), 1U) << "Expected to find fallback def for 'bar'"; EXPECT_EQ(Result[Bar].getAddress(), BarSym.getAddress()) @@ -995,7 +1021,7 @@ TEST_F(CoreAPIsStandardTest, FailResolution) { cantFail(JD.define(MU)); SymbolNameSet Names({Foo, Bar}); - auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), Names); + auto Result = ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet(Names)); EXPECT_FALSE(!!Result) << "Expected failure"; if (!Result) { @@ -1028,8 +1054,8 @@ TEST_F(CoreAPIsStandardTest, FailEmissionAfterResolution) { cantFail(R.notifyResolved(SymbolMap({{Foo, FooSym}, {Bar, BarSym}}))); ES.lookup( - JITDylibSearchList({{&JD, false}}), SymbolNameSet({Baz}), - SymbolState::Resolved, + LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet({Baz}), SymbolState::Resolved, [&R](Expected<SymbolMap> Result) { // Called when "baz" is resolved. We don't actually depend // on or care about baz, but use it to trigger failure of @@ -1046,8 +1072,8 @@ TEST_F(CoreAPIsStandardTest, FailEmissionAfterResolution) { cantFail(JD.define(MU)); - SymbolNameSet Names({Foo, Bar}); - auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), Names); + auto Result = + ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Foo, Bar})); EXPECT_THAT_EXPECTED(std::move(Result), Failed()) << "Unexpected success while trying to test error propagation"; @@ -1066,8 +1092,8 @@ TEST_F(CoreAPIsStandardTest, FailAfterPartialResolution) { bool QueryHandlerRun = false; ES.lookup( - JITDylibSearchList({{&JD, false}}), SymbolNameSet({Foo, Bar}), - SymbolState::Resolved, + LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet({Foo, Bar}), SymbolState::Resolved, [&](Expected<SymbolMap> Result) { EXPECT_THAT_EXPECTED(std::move(Result), Failed()) << "Expected query to fail"; @@ -1087,8 +1113,7 @@ TEST_F(CoreAPIsStandardTest, TestLookupWithUnthreadedMaterialization) { cantFail(JD.define(MU)); - auto FooLookupResult = - cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); + auto FooLookupResult = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Foo)); EXPECT_EQ(FooLookupResult.getAddress(), FooSym.getAddress()) << "lookup returned an incorrect address"; @@ -1108,8 +1133,7 @@ TEST_F(CoreAPIsStandardTest, TestLookupWithThreadedMaterialization) { cantFail(JD.define(absoluteSymbols({{Foo, FooSym}}))); - auto FooLookupResult = - cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); + auto FooLookupResult = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Foo)); EXPECT_EQ(FooLookupResult.getAddress(), FooSym.getAddress()) << "lookup returned an incorrect address"; @@ -1157,16 +1181,14 @@ TEST_F(CoreAPIsStandardTest, TestGetRequestedSymbolsAndReplace) { EXPECT_FALSE(FooMaterialized) << "Foo should not be materialized yet"; EXPECT_FALSE(BarMaterialized) << "Bar should not be materialized yet"; - auto FooSymResult = - cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Foo)); + auto FooSymResult = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Foo)); EXPECT_EQ(FooSymResult.getAddress(), FooSym.getAddress()) << "Address mismatch for Foo"; EXPECT_TRUE(FooMaterialized) << "Foo should be materialized now"; EXPECT_FALSE(BarMaterialized) << "Bar still should not be materialized"; - auto BarSymResult = - cantFail(ES.lookup(JITDylibSearchList({{&JD, false}}), Bar)); + auto BarSymResult = cantFail(ES.lookup(makeJITDylibSearchOrder(&JD), Bar)); EXPECT_EQ(BarSymResult.getAddress(), BarSym.getAddress()) << "Address mismatch for Bar"; EXPECT_TRUE(BarMaterialized) << "Bar should be materialized now"; @@ -1186,7 +1208,8 @@ TEST_F(CoreAPIsStandardTest, TestMaterializationResponsibilityDelegation) { cantFail(JD.define(MU)); - auto Result = ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo, Bar}); + auto Result = + ES.lookup(makeJITDylibSearchOrder(&JD), SymbolLookupSet({Foo, Bar})); EXPECT_TRUE(!!Result) << "Result should be a success value"; EXPECT_EQ(Result->count(Foo), 1U) << "\"Foo\" entry missing"; @@ -1216,8 +1239,9 @@ TEST_F(CoreAPIsStandardTest, TestMaterializeWeakSymbol) { cantFail(std::move(Result)); }; - ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, - std::move(OnCompletion), NoDependenciesToRegister); + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet({Foo}), SymbolState::Ready, std::move(OnCompletion), + NoDependenciesToRegister); auto MU2 = std::make_unique<SimpleMaterializationUnit>( SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}), diff --git a/llvm/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp b/llvm/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp index f79d721b812..7b6d4b078fb 100644 --- a/llvm/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp @@ -24,7 +24,9 @@ TEST_F(LegacyAPIsStandardTest, TestLambdaSymbolResolver) { auto Resolver = createSymbolResolver( [&](const SymbolNameSet &Symbols) { - auto FlagsMap = cantFail(JD.lookupFlags(Symbols)); + auto FlagsMap = cantFail(JD.lookupFlags( + LookupKind::Static, JITDylibLookupFlags::MatchExportedSymbolsOnly, + SymbolLookupSet(Symbols))); SymbolNameSet Result; for (auto &KV : FlagsMap) if (!KV.second.isStrong()) @@ -57,7 +59,7 @@ TEST_F(LegacyAPIsStandardTest, TestLambdaSymbolResolver) { }; auto Q = std::make_shared<AsynchronousSymbolQuery>( - SymbolNameSet({Foo, Bar}), SymbolState::Resolved, OnCompletion); + SymbolLookupSet({Foo, Bar}), SymbolState::Resolved, OnCompletion); auto Unresolved = Resolver->lookup(std::move(Q), SymbolNameSet({Foo, Bar, Baz})); @@ -111,7 +113,8 @@ TEST_F(LegacyAPIsStandardTest, LegacyLookupHelpersFn) { << "Wrong flags for bar"; }; - AsynchronousSymbolQuery Q({Foo, Bar}, SymbolState::Resolved, OnCompletion); + AsynchronousSymbolQuery Q(SymbolLookupSet({Foo, Bar}), SymbolState::Resolved, + OnCompletion); auto Unresolved = lookupWithLegacyFn(ES, Q, SymbolNameSet({Foo, Bar, Baz}), LegacyLookup); diff --git a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp index ecb8cf65393..f1c0da6a9ab 100644 --- a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp @@ -63,8 +63,9 @@ static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj, ObjLayer.setProcessAllSections(ProcessAllSections); cantFail(ObjLayer.add(JD, std::move(Obj), ES.allocateVModule())); - ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Resolved, - OnResolveDoNothing, NoDependenciesToRegister); + ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), + SymbolLookupSet(Foo), SymbolState::Resolved, OnResolveDoNothing, + NoDependenciesToRegister); return DebugSectionSeen; } @@ -160,7 +161,8 @@ TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) { cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule())); ES.lookup( - JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Resolved, + LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo), + SymbolState::Resolved, [](Expected<SymbolMap> R) { cantFail(std::move(R)); }, NoDependenciesToRegister); } @@ -225,7 +227,8 @@ TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) { cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule())); ES.lookup( - JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Resolved, + LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo), + SymbolState::Resolved, [](Expected<SymbolMap> R) { cantFail(std::move(R)); }, NoDependenciesToRegister); } |