[llvm] [ORC] Unify symbol mapping and allow custom mapping functions (PR #79616)
Lucas Reis via llvm-commits
llvm-commits at lists.llvm.org
Sat Jan 27 13:48:35 PST 2024
https://github.com/lucasreis1 updated https://github.com/llvm/llvm-project/pull/79616
>From 1892f8d8df88b80e4a19563a686ae52970b2a5ca Mon Sep 17 00:00:00 2001
From: Lucas <lucas.reis091997 at gmail.com>
Date: Fri, 26 Jan 2024 12:36:36 -0400
Subject: [PATCH 1/5] [ORC] Unify symbol mapping and allow custom mapping
functions
This commit makes three changes:
1. Unify symbol mapping into IRLayer and discard the old IRSymbolMapper
class
2. Allow for clients to provide their own symbol mapper function to
provide custom mappings
3. Skip adding linkonce_odr symbols to the symbol map on the default
mapper (fixes llvm/llvm-project#64907)
---
.../llvm/ExecutionEngine/Orc/CompileUtils.h | 6 +-
.../llvm/ExecutionEngine/Orc/IRCompileLayer.h | 10 +-
llvm/include/llvm/ExecutionEngine/Orc/Layer.h | 107 +++++++++++++++---
.../llvm/ExecutionEngine/Orc/Mangling.h | 23 +---
.../Orc/CompileOnDemandLayer.cpp | 96 ++++++++--------
llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp | 4 +-
llvm/lib/ExecutionEngine/Orc/Layer.cpp | 59 ++++++++--
llvm/lib/ExecutionEngine/Orc/Mangling.cpp | 53 ---------
8 files changed, 204 insertions(+), 154 deletions(-)
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h
index a55aa3d71db2a14..843916f2f001f26 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h
@@ -27,8 +27,7 @@ class TargetMachine;
namespace orc {
-IRSymbolMapper::ManglingOptions
-irManglingOptionsFromTargetOptions(const TargetOptions &Opts);
+ManglingOptions irManglingOptionsFromTargetOptions(const TargetOptions &Opts);
/// Simple compile functor: Takes a single IR module and returns an ObjectFile.
/// This compiler supports a single compilation thread and LLVMContext only.
@@ -49,8 +48,7 @@ class SimpleCompiler : public IRCompileLayer::IRCompiler {
Expected<CompileResult> operator()(Module &M) override;
private:
- IRSymbolMapper::ManglingOptions
- manglingOptionsForTargetMachine(const TargetMachine &TM);
+ ManglingOptions manglingOptionsForTargetMachine(const TargetMachine &TM);
CompileResult tryToLoadFromObjectCache(const Module &M);
void notifyObjectCompiled(const Module &M, const MemoryBuffer &ObjBuffer);
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
index f493d63a7c8a991..02a18a2072853ff 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
@@ -32,18 +32,18 @@ class IRCompileLayer : public IRLayer {
public:
class IRCompiler {
public:
- IRCompiler(IRSymbolMapper::ManglingOptions MO) : MO(std::move(MO)) {}
+ IRCompiler(ManglingOptions MO) : MO(std::move(MO)) {}
virtual ~IRCompiler();
- const IRSymbolMapper::ManglingOptions &getManglingOptions() const {
+ const ManglingOptions &getManglingOptions() const {
return MO;
}
virtual Expected<std::unique_ptr<MemoryBuffer>> operator()(Module &M) = 0;
protected:
- IRSymbolMapper::ManglingOptions &manglingOptions() { return MO; }
+ ManglingOptions &manglingOptions() { return MO; }
private:
- IRSymbolMapper::ManglingOptions MO;
+ ManglingOptions MO;
};
using NotifyCompiledFunction = std::function<void(
@@ -63,7 +63,7 @@ class IRCompileLayer : public IRLayer {
mutable std::mutex IRLayerMutex;
ObjectLayer &BaseLayer;
std::unique_ptr<IRCompiler> Compile;
- const IRSymbolMapper::ManglingOptions *ManglingOpts;
+ const ManglingOptions *ManglingOpts;
NotifyCompiledFunction NotifyCompiled = NotifyCompiledFunction();
};
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Layer.h b/llvm/include/llvm/ExecutionEngine/Orc/Layer.h
index cfeedc2a0bdaab7..083a412119c1073 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Layer.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Layer.h
@@ -16,6 +16,7 @@
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/Mangling.h"
#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
+#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ExtensibleRTTI.h"
@@ -34,8 +35,7 @@ class IRMaterializationUnit : public MaterializationUnit {
/// Create an IRMaterializationLayer. Scans the module to build the
/// SymbolFlags and SymbolToDefinition maps.
- IRMaterializationUnit(ExecutionSession &ES,
- const IRSymbolMapper::ManglingOptions &MO,
+ IRMaterializationUnit(ExecutionSession &ES, const ManglingOptions &MO,
ThreadSafeModule TSM);
/// Create an IRMaterializationLayer from a module, and pre-existing
@@ -52,6 +52,15 @@ class IRMaterializationUnit : public MaterializationUnit {
/// Return a reference to the contained ThreadSafeModule.
const ThreadSafeModule &getModule() const { return TSM; }
+ struct SymbolInfo {
+ public:
+ SymbolInfo(MaterializationUnit::Interface I, SymbolNameToDefinitionMap SMap)
+ : Interface(I), SymbolToDefinition(SMap) {}
+
+ MaterializationUnit::Interface Interface;
+ SymbolNameToDefinitionMap SymbolToDefinition;
+ };
+
protected:
ThreadSafeModule TSM;
SymbolNameToDefinitionMap SymbolToDefinition;
@@ -66,8 +75,76 @@ class IRMaterializationUnit : public MaterializationUnit {
/// Interface for layers that accept LLVM IR.
class IRLayer {
public:
- IRLayer(ExecutionSession &ES, const IRSymbolMapper::ManglingOptions *&MO)
- : ES(ES), MO(MO) {}
+ using SymbolNameToDefinitionMap = std::map<SymbolStringPtr, GlobalValue *>;
+ using IRSymbolMapper = unique_function<void(
+ ArrayRef<GlobalValue *> Gvs, ExecutionSession &ES,
+ const ManglingOptions &MO, SymbolFlagsMap &SymbolFlags,
+ SymbolNameToDefinitionMap *SymbolToDef)>;
+
+ /// Add mangled symbols for the given GlobalValues to SymbolFlags.
+ /// If a SymbolToDefinitionMap pointer is supplied then it will be populated
+ /// with Name-to-GlobalValue* mappings. Note that this mapping is not
+ /// necessarily one-to-one: thread-local GlobalValues, for example, may
+ /// produce more than one symbol, in which case the map will contain duplicate
+ /// values.
+ static void
+ defaultSymbolMapper(ArrayRef<GlobalValue *> GVs, ExecutionSession &ES,
+ const ManglingOptions &MO, SymbolFlagsMap &SymbolFlags,
+ SymbolNameToDefinitionMap *SymbolToDefinition = nullptr) {
+ if (GVs.empty())
+ return;
+
+ MangleAndInterner Mangle(ES, GVs[0]->getParent()->getDataLayout());
+ for (auto *G : GVs) {
+ assert(G && "GVs cannot contain null elements");
+ // Follow static linkage behaviour to decide which GVs get a named symbol
+ if (!G->hasName() || G->isDeclaration() || G->hasLocalLinkage() ||
+ G->hasAvailableExternallyLinkage() || G->hasAppendingLinkage() ||
+ G->hasLinkOnceODRLinkage())
+ continue;
+
+ if (G->isThreadLocal() && MO.EmulatedTLS) {
+ auto *GV = cast<GlobalVariable>(G);
+
+ auto Flags = JITSymbolFlags::fromGlobalValue(*GV);
+
+ auto EmuTLSV = Mangle(("__emutls_v." + GV->getName()).str());
+ SymbolFlags[EmuTLSV] = Flags;
+ if (SymbolToDefinition)
+ (*SymbolToDefinition)[EmuTLSV] = GV;
+
+ // If this GV has a non-zero initializer we'll need to emit an
+ // __emutls.t symbol too.
+ if (GV->hasInitializer()) {
+ const auto *InitVal = GV->getInitializer();
+
+ // Skip zero-initializers.
+ if (isa<ConstantAggregateZero>(InitVal))
+ continue;
+ const auto *InitIntValue = dyn_cast<ConstantInt>(InitVal);
+ if (InitIntValue && InitIntValue->isZero())
+ continue;
+
+ auto EmuTLST = Mangle(("__emutls_t." + GV->getName()).str());
+ SymbolFlags[EmuTLST] = Flags;
+ if (SymbolToDefinition)
+ (*SymbolToDefinition)[EmuTLST] = GV;
+ }
+ continue;
+ }
+
+ // Otherwise we just need a normal linker mangling.
+ auto MangledName = Mangle(G->getName());
+ SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(*G);
+ if (G->getComdat() &&
+ G->getComdat()->getSelectionKind() != Comdat::NoDeduplicate)
+ SymbolFlags[MangledName] |= JITSymbolFlags::Weak;
+ if (SymbolToDefinition)
+ (*SymbolToDefinition)[MangledName] = G;
+ }
+ }
+
+ IRLayer(ExecutionSession &ES, const ManglingOptions *&MO) : ES(ES), MO(MO) {}
virtual ~IRLayer();
@@ -75,9 +152,7 @@ class IRLayer {
ExecutionSession &getExecutionSession() { return ES; }
/// Get the mangling options for this layer.
- const IRSymbolMapper::ManglingOptions *&getManglingOptions() const {
- return MO;
- }
+ const ManglingOptions *&getManglingOptions() const { return MO; }
/// Sets the CloneToNewContextOnEmit flag (false by default).
///
@@ -95,12 +170,17 @@ class IRLayer {
/// Returns the current value of the CloneToNewContextOnEmit flag.
bool getCloneToNewContextOnEmit() const { return CloneToNewContextOnEmit; }
- /// Add a MaterializatinoUnit representing the given IR to the JITDylib
+ Expected<IRMaterializationUnit::SymbolInfo>
+ getSymbolInfo(const Module &M, ExecutionSession &ES,
+ const ManglingOptions &MO, IRSymbolMapper &SymMapper);
+
+ /// Adds a MaterializatinoUnit representing the given IR to the JITDylib
/// targeted by the given tracker.
- virtual Error add(ResourceTrackerSP RT, ThreadSafeModule TSM);
+ virtual Error add(ResourceTrackerSP RT, ThreadSafeModule TSM,
+ IRSymbolMapper SymMapper = IRSymbolMapper());
/// Adds a MaterializationUnit representing the given IR to the given
- /// JITDylib. If RT is not specif
+ /// JITDylib. If RT is not specified, use the default tracker for this Dylib.
Error add(JITDylib &JD, ThreadSafeModule TSM) {
return add(JD.getDefaultResourceTracker(), std::move(TSM));
}
@@ -112,16 +192,15 @@ class IRLayer {
private:
bool CloneToNewContextOnEmit = false;
ExecutionSession &ES;
- const IRSymbolMapper::ManglingOptions *&MO;
+ const ManglingOptions *&MO;
};
/// MaterializationUnit that materializes modules by calling the 'emit' method
/// on the given IRLayer.
class BasicIRLayerMaterializationUnit : public IRMaterializationUnit {
public:
- BasicIRLayerMaterializationUnit(IRLayer &L,
- const IRSymbolMapper::ManglingOptions &MO,
- ThreadSafeModule TSM);
+ BasicIRLayerMaterializationUnit(IRLayer &L, const ThreadSafeModule TSM,
+ SymbolInfo SymInfo);
private:
void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h b/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h
index 77429f4b11eefe4..4a3ddfbb93f3855 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h
@@ -33,26 +33,9 @@ class MangleAndInterner {
const DataLayout &DL;
};
-/// Maps IR global values to their linker symbol names / flags.
-///
-/// This utility can be used when adding new IR globals in the JIT.
-class IRSymbolMapper {
-public:
- struct ManglingOptions {
- bool EmulatedTLS = false;
- };
-
- using SymbolNameToDefinitionMap = std::map<SymbolStringPtr, GlobalValue *>;
-
- /// Add mangled symbols for the given GlobalValues to SymbolFlags.
- /// If a SymbolToDefinitionMap pointer is supplied then it will be populated
- /// with Name-to-GlobalValue* mappings. Note that this mapping is not
- /// necessarily one-to-one: thread-local GlobalValues, for example, may
- /// produce more than one symbol, in which case the map will contain duplicate
- /// values.
- static void add(ExecutionSession &ES, const ManglingOptions &MO,
- ArrayRef<GlobalValue *> GVs, SymbolFlagsMap &SymbolFlags,
- SymbolNameToDefinitionMap *SymbolToDefinition = nullptr);
+// Stores options to guide symbol mapping for IR symbols
+struct ManglingOptions {
+ bool EmulatedTLS = false;
};
} // End namespace orc
diff --git a/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp b/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp
index 6448adaa0ceb36f..dcd38ed9625d5d7 100644
--- a/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
#include "llvm/ADT/Hashing.h"
+#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
@@ -72,7 +72,7 @@ namespace orc {
class PartitioningIRMaterializationUnit : public IRMaterializationUnit {
public:
PartitioningIRMaterializationUnit(ExecutionSession &ES,
- const IRSymbolMapper::ManglingOptions &MO,
+ const ManglingOptions &MO,
ThreadSafeModule TSM,
CompileOnDemandLayer &Parent)
: IRMaterializationUnit(ES, MO, std::move(TSM)), Parent(Parent) {}
@@ -315,53 +315,53 @@ void CompileOnDemandLayer::emitPartition(
//
// FIXME: We apply this promotion once per partitioning. It's safe, but
// overkill.
- auto ExtractedTSM =
- TSM.withModuleDo([&](Module &M) -> Expected<ThreadSafeModule> {
- auto PromotedGlobals = PromoteSymbols(M);
- if (!PromotedGlobals.empty()) {
-
- MangleAndInterner Mangle(ES, M.getDataLayout());
- SymbolFlagsMap SymbolFlags;
- IRSymbolMapper::add(ES, *getManglingOptions(),
- PromotedGlobals, SymbolFlags);
-
- if (auto Err = R->defineMaterializing(SymbolFlags))
- return std::move(Err);
- }
-
- expandPartition(*GVsToExtract);
-
- // Submodule name is given by hashing the names of the globals.
- std::string SubModuleName;
- {
- std::vector<const GlobalValue*> HashGVs;
- HashGVs.reserve(GVsToExtract->size());
- for (const auto *GV : *GVsToExtract)
- HashGVs.push_back(GV);
- llvm::sort(HashGVs, [](const GlobalValue *LHS, const GlobalValue *RHS) {
- return LHS->getName() < RHS->getName();
- });
- hash_code HC(0);
- for (const auto *GV : HashGVs) {
- assert(GV->hasName() && "All GVs to extract should be named by now");
- auto GVName = GV->getName();
- HC = hash_combine(HC, hash_combine_range(GVName.begin(), GVName.end()));
- }
- raw_string_ostream(SubModuleName)
- << ".submodule."
- << formatv(sizeof(size_t) == 8 ? "{0:x16}" : "{0:x8}",
- static_cast<size_t>(HC))
- << ".ll";
- }
-
- // Extract the requested partiton (plus any necessary aliases) and
- // put the rest back into the impl dylib.
- auto ShouldExtract = [&](const GlobalValue &GV) -> bool {
- return GVsToExtract->count(&GV);
- };
-
- return extractSubModule(TSM, SubModuleName , ShouldExtract);
+ auto ExtractedTSM = TSM.withModuleDo([&](Module &M)
+ -> Expected<ThreadSafeModule> {
+ auto PromotedGlobals = PromoteSymbols(M);
+ if (!PromotedGlobals.empty()) {
+
+ MangleAndInterner Mangle(ES, M.getDataLayout());
+ SymbolFlagsMap SymbolFlags;
+ IRLayer::defaultSymbolMapper(PromotedGlobals, ES, *getManglingOptions(),
+ SymbolFlags);
+
+ if (auto Err = R->defineMaterializing(SymbolFlags))
+ return std::move(Err);
+ }
+
+ expandPartition(*GVsToExtract);
+
+ // Submodule name is given by hashing the names of the globals.
+ std::string SubModuleName;
+ {
+ std::vector<const GlobalValue *> HashGVs;
+ HashGVs.reserve(GVsToExtract->size());
+ for (const auto *GV : *GVsToExtract)
+ HashGVs.push_back(GV);
+ llvm::sort(HashGVs, [](const GlobalValue *LHS, const GlobalValue *RHS) {
+ return LHS->getName() < RHS->getName();
});
+ hash_code HC(0);
+ for (const auto *GV : HashGVs) {
+ assert(GV->hasName() && "All GVs to extract should be named by now");
+ auto GVName = GV->getName();
+ HC = hash_combine(HC, hash_combine_range(GVName.begin(), GVName.end()));
+ }
+ raw_string_ostream(SubModuleName)
+ << ".submodule."
+ << formatv(sizeof(size_t) == 8 ? "{0:x16}" : "{0:x8}",
+ static_cast<size_t>(HC))
+ << ".ll";
+ }
+
+ // Extract the requested partiton (plus any necessary aliases) and
+ // put the rest back into the impl dylib.
+ auto ShouldExtract = [&](const GlobalValue &GV) -> bool {
+ return GVsToExtract->count(&GV);
+ };
+
+ return extractSubModule(TSM, SubModuleName, ShouldExtract);
+ });
if (!ExtractedTSM) {
ES.reportError(ExtractedTSM.takeError());
diff --git a/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp b/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp
index fad7428e1f906c6..df9c02264d10351 100644
--- a/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp
@@ -25,9 +25,9 @@
namespace llvm {
namespace orc {
-IRSymbolMapper::ManglingOptions
+ManglingOptions
irManglingOptionsFromTargetOptions(const TargetOptions &Opts) {
- IRSymbolMapper::ManglingOptions MO;
+ ManglingOptions MO;
MO.EmulatedTLS = Opts.EmulatedTLS;
diff --git a/llvm/lib/ExecutionEngine/Orc/Layer.cpp b/llvm/lib/ExecutionEngine/Orc/Layer.cpp
index 3368d3276cb373c..2a9b30cefcdba8d 100644
--- a/llvm/lib/ExecutionEngine/Orc/Layer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Layer.cpp
@@ -21,17 +21,59 @@ namespace orc {
IRLayer::~IRLayer() = default;
-Error IRLayer::add(ResourceTrackerSP RT, ThreadSafeModule TSM) {
+Expected<IRMaterializationUnit::SymbolInfo>
+IRLayer::getSymbolInfo(const Module &M, ExecutionSession &ES,
+ const ManglingOptions &MO, IRSymbolMapper &SymMapper) {
+ std::vector<GlobalValue *> GVs;
+
+ for (auto &GV : M.global_values())
+ GVs.push_back(const_cast<GlobalValue *>(&GV));
+
+ SymbolFlagsMap SymbolFlags;
+ SymbolNameToDefinitionMap SymbolToDef;
+ SymMapper(GVs, ES, MO, SymbolFlags, &SymbolToDef);
+
+ SymbolStringPtr InitSymbol;
+ // If we need an init symbol for this module then create one.
+ if (!getStaticInitGVs(const_cast<Module &>(M)).empty()) {
+ size_t Counter = 0;
+
+ do {
+ std::string InitSymbolName;
+ raw_string_ostream(InitSymbolName)
+ << "$." << M.getModuleIdentifier() << ".__inits." << Counter++;
+ InitSymbol = ES.intern(InitSymbolName);
+ } while (SymbolFlags.count(InitSymbol));
+
+ SymbolFlags[InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
+ }
+
+ return IRMaterializationUnit::SymbolInfo(
+ MaterializationUnit::Interface(SymbolFlags, InitSymbol), SymbolToDef);
+}
+
+Error IRLayer::add(ResourceTrackerSP RT, ThreadSafeModule TSM,
+ IRSymbolMapper SymMapper) {
assert(RT && "RT can not be null");
+ if (!SymMapper)
+ SymMapper = defaultSymbolMapper;
+
auto &JD = RT->getJITDylib();
+ auto SymbolInfoOrErr = TSM.withModuleDo([&](const Module &M) {
+ return getSymbolInfo(M, JD.getExecutionSession(), *getManglingOptions(),
+ SymMapper);
+ });
+ if (auto Err = SymbolInfoOrErr.takeError())
+ return Err;
+
return JD.define(std::make_unique<BasicIRLayerMaterializationUnit>(
- *this, *getManglingOptions(), std::move(TSM)),
+ *this, std::move(TSM), *SymbolInfoOrErr),
std::move(RT));
}
-IRMaterializationUnit::IRMaterializationUnit(
- ExecutionSession &ES, const IRSymbolMapper::ManglingOptions &MO,
- ThreadSafeModule TSM)
+IRMaterializationUnit::IRMaterializationUnit(ExecutionSession &ES,
+ const ManglingOptions &MO,
+ ThreadSafeModule TSM)
: MaterializationUnit(Interface()), TSM(std::move(TSM)) {
assert(this->TSM && "Module must not be null");
@@ -133,9 +175,10 @@ void IRMaterializationUnit::discard(const JITDylib &JD,
}
BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit(
- IRLayer &L, const IRSymbolMapper::ManglingOptions &MO, ThreadSafeModule TSM)
- : IRMaterializationUnit(L.getExecutionSession(), MO, std::move(TSM)), L(L) {
-}
+ IRLayer &L, ThreadSafeModule TSM, SymbolInfo SymInfo)
+ : IRMaterializationUnit(std::move(TSM), SymInfo.Interface,
+ SymInfo.SymbolToDefinition),
+ L(L) {}
void BasicIRLayerMaterializationUnit::materialize(
std::unique_ptr<MaterializationResponsibility> R) {
diff --git a/llvm/lib/ExecutionEngine/Orc/Mangling.cpp b/llvm/lib/ExecutionEngine/Orc/Mangling.cpp
index 9c243c9bf1d298d..2ffa856435b04f4 100644
--- a/llvm/lib/ExecutionEngine/Orc/Mangling.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Mangling.cpp
@@ -27,58 +27,5 @@ SymbolStringPtr MangleAndInterner::operator()(StringRef Name) {
}
return ES.intern(MangledName);
}
-
-void IRSymbolMapper::add(ExecutionSession &ES, const ManglingOptions &MO,
- ArrayRef<GlobalValue *> GVs,
- SymbolFlagsMap &SymbolFlags,
- SymbolNameToDefinitionMap *SymbolToDefinition) {
- if (GVs.empty())
- return;
-
- MangleAndInterner Mangle(ES, GVs[0]->getParent()->getDataLayout());
- for (auto *G : GVs) {
- assert(G && "GVs cannot contain null elements");
- if (!G->hasName() || G->isDeclaration() || G->hasLocalLinkage() ||
- G->hasAvailableExternallyLinkage() || G->hasAppendingLinkage())
- continue;
-
- if (G->isThreadLocal() && MO.EmulatedTLS) {
- auto *GV = cast<GlobalVariable>(G);
-
- auto Flags = JITSymbolFlags::fromGlobalValue(*GV);
-
- auto EmuTLSV = Mangle(("__emutls_v." + GV->getName()).str());
- SymbolFlags[EmuTLSV] = Flags;
- if (SymbolToDefinition)
- (*SymbolToDefinition)[EmuTLSV] = GV;
-
- // If this GV has a non-zero initializer we'll need to emit an
- // __emutls.t symbol too.
- if (GV->hasInitializer()) {
- const auto *InitVal = GV->getInitializer();
-
- // Skip zero-initializers.
- if (isa<ConstantAggregateZero>(InitVal))
- continue;
- const auto *InitIntValue = dyn_cast<ConstantInt>(InitVal);
- if (InitIntValue && InitIntValue->isZero())
- continue;
-
- auto EmuTLST = Mangle(("__emutls_t." + GV->getName()).str());
- SymbolFlags[EmuTLST] = Flags;
- if (SymbolToDefinition)
- (*SymbolToDefinition)[EmuTLST] = GV;
- }
- continue;
- }
-
- // Otherwise we just need a normal linker mangling.
- auto MangledName = Mangle(G->getName());
- SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(*G);
- if (SymbolToDefinition)
- (*SymbolToDefinition)[MangledName] = G;
- }
-}
-
} // End namespace orc.
} // End namespace llvm.
>From 77ce76b17c282a08a054294e3788d93940c0912f Mon Sep 17 00:00:00 2001
From: Lucas <lucas.reis091997 at gmail.com>
Date: Fri, 26 Jan 2024 12:44:26 -0400
Subject: [PATCH 2/5] [ORC] Add a FAQ section to Orc docs
Populate a small FAQ section with its first question related to missing symbols from IR to prepare for the new changes to symbol mapping
---
llvm/docs/ORCv2.rst | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/llvm/docs/ORCv2.rst b/llvm/docs/ORCv2.rst
index add05e05a80e5fd..b5e818585caba7c 100644
--- a/llvm/docs/ORCv2.rst
+++ b/llvm/docs/ORCv2.rst
@@ -972,3 +972,32 @@ Further Future Work
multiple dylibs provide a weak definition of a symbol then each will end
up with its own definition (similar to how weak definitions are handled
in Windows DLLs). This will be fixed in the future.
+
+Frequently Asked Questions (FAQ)
+================================
+
+Here are some frequently asked questions about Orc's JIT API.
+
+Why can't I find this symbol defined in my LLVM IR?
+---------------------------------------------------
+
+If you are faced with a ``MissingSymbolsDefinitions`` error for a symbol you have defined in your LLVM IR, it may be a symbol that Orc does not map into a ``Materialization Unit``. Symbols with linkage types such as ``linkonce_odr`` are common cases of this issue. This is the intended behaviour from the perspective of the linker interface, which is the goal of Orc-oriented JITs.
+
+While this is the standard behaviour for symbol mapping on the ``IRLayer``, you are free to provide your own custom symbol mapping function to map symbols in the way that suits your necessities:
+
+.. code-block:: c++
+
+ static void
+ mySymbolMapper(ArrayRef<GlobalValue *> GVs, ExecutionSession &ES,
+ const ManglingOptions &MO, SymbolFlagsMap &SymbolFlags,
+ SymbolNameToDefinitionMap *SymbolToDefinition = nullptr) {
+ // decide which symbols you want to map to a possible MaterializationUnit
+ }
+
+ // ...
+
+ auto RT = JD.getDefaultResourceTracker();
+ // Add a ThreadSafeModule to an IRLayer
+ MyLayer.add(RT, TSM, mySymbolMapper);
+
+More info on how symbol mapping is usually done can be seen on ``defaultSymbolMapper`` at ``llvm/include/llvm/ExecutionEngine/Orc/Layer.h``.
>From 202c49782f922e912ecd384d336170749899b706 Mon Sep 17 00:00:00 2001
From: Lucas <lucas.reis091997 at gmail.com>
Date: Fri, 26 Jan 2024 13:25:42 -0400
Subject: [PATCH 3/5] Fix formatting
---
llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h | 4 +---
llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp | 3 +--
2 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
index 02a18a2072853ff..22f9c46e4ae3703 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
@@ -34,9 +34,7 @@ class IRCompileLayer : public IRLayer {
public:
IRCompiler(ManglingOptions MO) : MO(std::move(MO)) {}
virtual ~IRCompiler();
- const ManglingOptions &getManglingOptions() const {
- return MO;
- }
+ const ManglingOptions &getManglingOptions() const { return MO; }
virtual Expected<std::unique_ptr<MemoryBuffer>> operator()(Module &M) = 0;
protected:
diff --git a/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp b/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp
index df9c02264d10351..6d9a4b0b615be6e 100644
--- a/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp
@@ -25,8 +25,7 @@
namespace llvm {
namespace orc {
-ManglingOptions
-irManglingOptionsFromTargetOptions(const TargetOptions &Opts) {
+ManglingOptions irManglingOptionsFromTargetOptions(const TargetOptions &Opts) {
ManglingOptions MO;
MO.EmulatedTLS = Opts.EmulatedTLS;
>From 5f25a268037dcedd7ebc5bb9370abf6264696f77 Mon Sep 17 00:00:00 2001
From: Lucas <lucas.reis091997 at gmail.com>
Date: Fri, 26 Jan 2024 22:34:46 -0400
Subject: [PATCH 4/5] Improve symbol mapping unification structures 1. Move
symbol mapping logic from IRLayer to IRSymbolMapper 2. Use the same logic
between all know structures that require mapping
---
llvm/docs/ORCv2.rst | 2 +-
.../llvm/ExecutionEngine/Orc/CompileUtils.h | 6 +-
.../llvm/ExecutionEngine/Orc/IRCompileLayer.h | 12 +-
llvm/include/llvm/ExecutionEngine/Orc/Layer.h | 99 +++------------
.../llvm/ExecutionEngine/Orc/Mangling.h | 27 +++-
.../Orc/CompileOnDemandLayer.cpp | 6 +-
llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp | 5 +-
llvm/lib/ExecutionEngine/Orc/Layer.cpp | 115 +++++-------------
llvm/lib/ExecutionEngine/Orc/Mangling.cpp | 57 +++++++++
9 files changed, 147 insertions(+), 182 deletions(-)
diff --git a/llvm/docs/ORCv2.rst b/llvm/docs/ORCv2.rst
index b5e818585caba7c..3ded71f59e589e3 100644
--- a/llvm/docs/ORCv2.rst
+++ b/llvm/docs/ORCv2.rst
@@ -1000,4 +1000,4 @@ While this is the standard behaviour for symbol mapping on the ``IRLayer``, you
// Add a ThreadSafeModule to an IRLayer
MyLayer.add(RT, TSM, mySymbolMapper);
-More info on how symbol mapping is usually done can be seen on ``defaultSymbolMapper`` at ``llvm/include/llvm/ExecutionEngine/Orc/Layer.h``.
+More info on how symbol mapping is usually done can be seen on ``defaultSymbolMapper`` at ``llvm/lib/ExecutionEngine/Orc/Mangling.cpp``.
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h
index 843916f2f001f26..a55aa3d71db2a14 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h
@@ -27,7 +27,8 @@ class TargetMachine;
namespace orc {
-ManglingOptions irManglingOptionsFromTargetOptions(const TargetOptions &Opts);
+IRSymbolMapper::ManglingOptions
+irManglingOptionsFromTargetOptions(const TargetOptions &Opts);
/// Simple compile functor: Takes a single IR module and returns an ObjectFile.
/// This compiler supports a single compilation thread and LLVMContext only.
@@ -48,7 +49,8 @@ class SimpleCompiler : public IRCompileLayer::IRCompiler {
Expected<CompileResult> operator()(Module &M) override;
private:
- ManglingOptions manglingOptionsForTargetMachine(const TargetMachine &TM);
+ IRSymbolMapper::ManglingOptions
+ manglingOptionsForTargetMachine(const TargetMachine &TM);
CompileResult tryToLoadFromObjectCache(const Module &M);
void notifyObjectCompiled(const Module &M, const MemoryBuffer &ObjBuffer);
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
index 22f9c46e4ae3703..f493d63a7c8a991 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
@@ -32,16 +32,18 @@ class IRCompileLayer : public IRLayer {
public:
class IRCompiler {
public:
- IRCompiler(ManglingOptions MO) : MO(std::move(MO)) {}
+ IRCompiler(IRSymbolMapper::ManglingOptions MO) : MO(std::move(MO)) {}
virtual ~IRCompiler();
- const ManglingOptions &getManglingOptions() const { return MO; }
+ const IRSymbolMapper::ManglingOptions &getManglingOptions() const {
+ return MO;
+ }
virtual Expected<std::unique_ptr<MemoryBuffer>> operator()(Module &M) = 0;
protected:
- ManglingOptions &manglingOptions() { return MO; }
+ IRSymbolMapper::ManglingOptions &manglingOptions() { return MO; }
private:
- ManglingOptions MO;
+ IRSymbolMapper::ManglingOptions MO;
};
using NotifyCompiledFunction = std::function<void(
@@ -61,7 +63,7 @@ class IRCompileLayer : public IRLayer {
mutable std::mutex IRLayerMutex;
ObjectLayer &BaseLayer;
std::unique_ptr<IRCompiler> Compile;
- const ManglingOptions *ManglingOpts;
+ const IRSymbolMapper::ManglingOptions *ManglingOpts;
NotifyCompiledFunction NotifyCompiled = NotifyCompiledFunction();
};
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Layer.h b/llvm/include/llvm/ExecutionEngine/Orc/Layer.h
index 083a412119c1073..ee8b20ec9325e5e 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Layer.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Layer.h
@@ -16,7 +16,6 @@
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/Mangling.h"
#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
-#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ExtensibleRTTI.h"
@@ -35,8 +34,11 @@ class IRMaterializationUnit : public MaterializationUnit {
/// Create an IRMaterializationLayer. Scans the module to build the
/// SymbolFlags and SymbolToDefinition maps.
- IRMaterializationUnit(ExecutionSession &ES, const ManglingOptions &MO,
- ThreadSafeModule TSM);
+ IRMaterializationUnit(ExecutionSession &ES,
+ const IRSymbolMapper::ManglingOptions &MO,
+ ThreadSafeModule TSM,
+ IRSymbolMapper::SymbolMapperFunction SymMapper =
+ IRSymbolMapper::defaultSymbolMapper);
/// Create an IRMaterializationLayer from a module, and pre-existing
/// SymbolFlags and SymbolToDefinition maps. The maps must provide
@@ -52,6 +54,7 @@ class IRMaterializationUnit : public MaterializationUnit {
/// Return a reference to the contained ThreadSafeModule.
const ThreadSafeModule &getModule() const { return TSM; }
+ // Stores Interface and SymbolToDefinitionMap
struct SymbolInfo {
public:
SymbolInfo(MaterializationUnit::Interface I, SymbolNameToDefinitionMap SMap)
@@ -61,6 +64,11 @@ class IRMaterializationUnit : public MaterializationUnit {
SymbolNameToDefinitionMap SymbolToDefinition;
};
+ static IRMaterializationUnit::SymbolInfo
+ getSymbolInfo(const Module &M, ExecutionSession &ES,
+ const IRSymbolMapper::ManglingOptions &MO,
+ IRSymbolMapper::SymbolMapperFunction &SymMapper);
+
protected:
ThreadSafeModule TSM;
SymbolNameToDefinitionMap SymbolToDefinition;
@@ -75,76 +83,8 @@ class IRMaterializationUnit : public MaterializationUnit {
/// Interface for layers that accept LLVM IR.
class IRLayer {
public:
- using SymbolNameToDefinitionMap = std::map<SymbolStringPtr, GlobalValue *>;
- using IRSymbolMapper = unique_function<void(
- ArrayRef<GlobalValue *> Gvs, ExecutionSession &ES,
- const ManglingOptions &MO, SymbolFlagsMap &SymbolFlags,
- SymbolNameToDefinitionMap *SymbolToDef)>;
-
- /// Add mangled symbols for the given GlobalValues to SymbolFlags.
- /// If a SymbolToDefinitionMap pointer is supplied then it will be populated
- /// with Name-to-GlobalValue* mappings. Note that this mapping is not
- /// necessarily one-to-one: thread-local GlobalValues, for example, may
- /// produce more than one symbol, in which case the map will contain duplicate
- /// values.
- static void
- defaultSymbolMapper(ArrayRef<GlobalValue *> GVs, ExecutionSession &ES,
- const ManglingOptions &MO, SymbolFlagsMap &SymbolFlags,
- SymbolNameToDefinitionMap *SymbolToDefinition = nullptr) {
- if (GVs.empty())
- return;
-
- MangleAndInterner Mangle(ES, GVs[0]->getParent()->getDataLayout());
- for (auto *G : GVs) {
- assert(G && "GVs cannot contain null elements");
- // Follow static linkage behaviour to decide which GVs get a named symbol
- if (!G->hasName() || G->isDeclaration() || G->hasLocalLinkage() ||
- G->hasAvailableExternallyLinkage() || G->hasAppendingLinkage() ||
- G->hasLinkOnceODRLinkage())
- continue;
-
- if (G->isThreadLocal() && MO.EmulatedTLS) {
- auto *GV = cast<GlobalVariable>(G);
-
- auto Flags = JITSymbolFlags::fromGlobalValue(*GV);
-
- auto EmuTLSV = Mangle(("__emutls_v." + GV->getName()).str());
- SymbolFlags[EmuTLSV] = Flags;
- if (SymbolToDefinition)
- (*SymbolToDefinition)[EmuTLSV] = GV;
-
- // If this GV has a non-zero initializer we'll need to emit an
- // __emutls.t symbol too.
- if (GV->hasInitializer()) {
- const auto *InitVal = GV->getInitializer();
-
- // Skip zero-initializers.
- if (isa<ConstantAggregateZero>(InitVal))
- continue;
- const auto *InitIntValue = dyn_cast<ConstantInt>(InitVal);
- if (InitIntValue && InitIntValue->isZero())
- continue;
-
- auto EmuTLST = Mangle(("__emutls_t." + GV->getName()).str());
- SymbolFlags[EmuTLST] = Flags;
- if (SymbolToDefinition)
- (*SymbolToDefinition)[EmuTLST] = GV;
- }
- continue;
- }
-
- // Otherwise we just need a normal linker mangling.
- auto MangledName = Mangle(G->getName());
- SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(*G);
- if (G->getComdat() &&
- G->getComdat()->getSelectionKind() != Comdat::NoDeduplicate)
- SymbolFlags[MangledName] |= JITSymbolFlags::Weak;
- if (SymbolToDefinition)
- (*SymbolToDefinition)[MangledName] = G;
- }
- }
-
- IRLayer(ExecutionSession &ES, const ManglingOptions *&MO) : ES(ES), MO(MO) {}
+ IRLayer(ExecutionSession &ES, const IRSymbolMapper::ManglingOptions *&MO)
+ : ES(ES), MO(MO) {}
virtual ~IRLayer();
@@ -152,7 +92,9 @@ class IRLayer {
ExecutionSession &getExecutionSession() { return ES; }
/// Get the mangling options for this layer.
- const ManglingOptions *&getManglingOptions() const { return MO; }
+ const IRSymbolMapper::ManglingOptions *&getManglingOptions() const {
+ return MO;
+ }
/// Sets the CloneToNewContextOnEmit flag (false by default).
///
@@ -170,14 +112,11 @@ class IRLayer {
/// Returns the current value of the CloneToNewContextOnEmit flag.
bool getCloneToNewContextOnEmit() const { return CloneToNewContextOnEmit; }
- Expected<IRMaterializationUnit::SymbolInfo>
- getSymbolInfo(const Module &M, ExecutionSession &ES,
- const ManglingOptions &MO, IRSymbolMapper &SymMapper);
-
/// Adds a MaterializatinoUnit representing the given IR to the JITDylib
/// targeted by the given tracker.
virtual Error add(ResourceTrackerSP RT, ThreadSafeModule TSM,
- IRSymbolMapper SymMapper = IRSymbolMapper());
+ IRSymbolMapper::SymbolMapperFunction SymMapper =
+ IRSymbolMapper::defaultSymbolMapper);
/// Adds a MaterializationUnit representing the given IR to the given
/// JITDylib. If RT is not specified, use the default tracker for this Dylib.
@@ -192,7 +131,7 @@ class IRLayer {
private:
bool CloneToNewContextOnEmit = false;
ExecutionSession &ES;
- const ManglingOptions *&MO;
+ const IRSymbolMapper::ManglingOptions *&MO;
};
/// MaterializationUnit that materializes modules by calling the 'emit' method
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h b/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h
index 4a3ddfbb93f3855..326754a1681c63e 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h
@@ -15,6 +15,7 @@
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
+#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -33,9 +34,29 @@ class MangleAndInterner {
const DataLayout &DL;
};
-// Stores options to guide symbol mapping for IR symbols
-struct ManglingOptions {
- bool EmulatedTLS = false;
+class IRSymbolMapper {
+public:
+ // Stores options to guide symbol mapping for IR symbols
+ struct ManglingOptions {
+ bool EmulatedTLS;
+ };
+
+ using SymbolNameToDefinitionMap = std::map<SymbolStringPtr, GlobalValue *>;
+ using SymbolMapperFunction = unique_function<void(
+ ArrayRef<GlobalValue *> Gvs, ExecutionSession &ES,
+ const ManglingOptions &MO, SymbolFlagsMap &SymbolFlags,
+ SymbolNameToDefinitionMap *SymbolToDef)>;
+
+ /// Add mangled symbols for the given GlobalValues to SymbolFlags.
+ /// If a SymbolToDefinitionMap pointer is supplied then it will be populated
+ /// with Name-to-GlobalValue* mappings. Note that this mapping is not
+ /// necessarily one-to-one: thread-local GlobalValues, for example, may
+ /// produce more than one symbol, in which case the map will contain duplicate
+ /// values.
+ static void
+ defaultSymbolMapper(ArrayRef<GlobalValue *> GVs, ExecutionSession &ES,
+ const ManglingOptions &MO, SymbolFlagsMap &SymbolFlags,
+ SymbolNameToDefinitionMap *SymbolToDefinition = nullptr);
};
} // End namespace orc
diff --git a/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp b/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp
index dcd38ed9625d5d7..007e19a8f876942 100644
--- a/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp
@@ -72,7 +72,7 @@ namespace orc {
class PartitioningIRMaterializationUnit : public IRMaterializationUnit {
public:
PartitioningIRMaterializationUnit(ExecutionSession &ES,
- const ManglingOptions &MO,
+ const IRSymbolMapper::ManglingOptions &MO,
ThreadSafeModule TSM,
CompileOnDemandLayer &Parent)
: IRMaterializationUnit(ES, MO, std::move(TSM)), Parent(Parent) {}
@@ -322,8 +322,8 @@ void CompileOnDemandLayer::emitPartition(
MangleAndInterner Mangle(ES, M.getDataLayout());
SymbolFlagsMap SymbolFlags;
- IRLayer::defaultSymbolMapper(PromotedGlobals, ES, *getManglingOptions(),
- SymbolFlags);
+ IRSymbolMapper::defaultSymbolMapper(PromotedGlobals, ES,
+ *getManglingOptions(), SymbolFlags);
if (auto Err = R->defineMaterializing(SymbolFlags))
return std::move(Err);
diff --git a/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp b/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp
index 6d9a4b0b615be6e..fad7428e1f906c6 100644
--- a/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp
@@ -25,8 +25,9 @@
namespace llvm {
namespace orc {
-ManglingOptions irManglingOptionsFromTargetOptions(const TargetOptions &Opts) {
- ManglingOptions MO;
+IRSymbolMapper::ManglingOptions
+irManglingOptionsFromTargetOptions(const TargetOptions &Opts) {
+ IRSymbolMapper::ManglingOptions MO;
MO.EmulatedTLS = Opts.EmulatedTLS;
diff --git a/llvm/lib/ExecutionEngine/Orc/Layer.cpp b/llvm/lib/ExecutionEngine/Orc/Layer.cpp
index 2a9b30cefcdba8d..404d9dfb45a5526 100644
--- a/llvm/lib/ExecutionEngine/Orc/Layer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Layer.cpp
@@ -21,9 +21,25 @@ namespace orc {
IRLayer::~IRLayer() = default;
-Expected<IRMaterializationUnit::SymbolInfo>
-IRLayer::getSymbolInfo(const Module &M, ExecutionSession &ES,
- const ManglingOptions &MO, IRSymbolMapper &SymMapper) {
+Error IRLayer::add(ResourceTrackerSP RT, ThreadSafeModule TSM,
+ IRSymbolMapper::SymbolMapperFunction SymMapper) {
+ assert(RT && "RT can not be null");
+
+ auto &JD = RT->getJITDylib();
+ auto SymbolInfo = TSM.withModuleDo([&](const Module &M) {
+ return IRMaterializationUnit::getSymbolInfo(
+ M, JD.getExecutionSession(), *getManglingOptions(), SymMapper);
+ });
+
+ return JD.define(std::make_unique<BasicIRLayerMaterializationUnit>(
+ *this, std::move(TSM), SymbolInfo),
+ std::move(RT));
+}
+
+IRMaterializationUnit::SymbolInfo IRMaterializationUnit::getSymbolInfo(
+ const Module &M, ExecutionSession &ES,
+ const IRSymbolMapper::ManglingOptions &MO,
+ IRSymbolMapper::SymbolMapperFunction &SymMapper) {
std::vector<GlobalValue *> GVs;
for (auto &GV : M.global_values())
@@ -52,93 +68,20 @@ IRLayer::getSymbolInfo(const Module &M, ExecutionSession &ES,
MaterializationUnit::Interface(SymbolFlags, InitSymbol), SymbolToDef);
}
-Error IRLayer::add(ResourceTrackerSP RT, ThreadSafeModule TSM,
- IRSymbolMapper SymMapper) {
- assert(RT && "RT can not be null");
- if (!SymMapper)
- SymMapper = defaultSymbolMapper;
-
- auto &JD = RT->getJITDylib();
- auto SymbolInfoOrErr = TSM.withModuleDo([&](const Module &M) {
- return getSymbolInfo(M, JD.getExecutionSession(), *getManglingOptions(),
- SymMapper);
- });
- if (auto Err = SymbolInfoOrErr.takeError())
- return Err;
-
- return JD.define(std::make_unique<BasicIRLayerMaterializationUnit>(
- *this, std::move(TSM), *SymbolInfoOrErr),
- std::move(RT));
-}
-
-IRMaterializationUnit::IRMaterializationUnit(ExecutionSession &ES,
- const ManglingOptions &MO,
- ThreadSafeModule TSM)
+IRMaterializationUnit::IRMaterializationUnit(
+ ExecutionSession &ES, const IRSymbolMapper::ManglingOptions &MO,
+ ThreadSafeModule TSM, IRSymbolMapper::SymbolMapperFunction SymMapper)
: MaterializationUnit(Interface()), TSM(std::move(TSM)) {
assert(this->TSM && "Module must not be null");
- MangleAndInterner Mangle(ES, this->TSM.getModuleUnlocked()->getDataLayout());
- this->TSM.withModuleDo([&](Module &M) {
- for (auto &G : M.global_values()) {
- // Skip globals that don't generate symbols.
-
- if (!G.hasName() || G.isDeclaration() || G.hasLocalLinkage() ||
- G.hasAvailableExternallyLinkage() || G.hasAppendingLinkage())
- continue;
-
- // thread locals generate different symbols depending on whether or not
- // emulated TLS is enabled.
- if (G.isThreadLocal() && MO.EmulatedTLS) {
- auto &GV = cast<GlobalVariable>(G);
-
- auto Flags = JITSymbolFlags::fromGlobalValue(GV);
-
- auto EmuTLSV = Mangle(("__emutls_v." + GV.getName()).str());
- SymbolFlags[EmuTLSV] = Flags;
- SymbolToDefinition[EmuTLSV] = &GV;
-
- // If this GV has a non-zero initializer we'll need to emit an
- // __emutls.t symbol too.
- if (GV.hasInitializer()) {
- const auto *InitVal = GV.getInitializer();
-
- // Skip zero-initializers.
- if (isa<ConstantAggregateZero>(InitVal))
- continue;
- const auto *InitIntValue = dyn_cast<ConstantInt>(InitVal);
- if (InitIntValue && InitIntValue->isZero())
- continue;
-
- auto EmuTLST = Mangle(("__emutls_t." + GV.getName()).str());
- SymbolFlags[EmuTLST] = Flags;
- }
- continue;
- }
-
- // Otherwise we just need a normal linker mangling.
- auto MangledName = Mangle(G.getName());
- SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G);
- if (G.getComdat() &&
- G.getComdat()->getSelectionKind() != Comdat::NoDeduplicate)
- SymbolFlags[MangledName] |= JITSymbolFlags::Weak;
- SymbolToDefinition[MangledName] = &G;
- }
-
- // If we need an init symbol for this module then create one.
- if (!getStaticInitGVs(M).empty()) {
- size_t Counter = 0;
-
- do {
- std::string InitSymbolName;
- raw_string_ostream(InitSymbolName)
- << "$." << M.getModuleIdentifier() << ".__inits." << Counter++;
- InitSymbol = ES.intern(InitSymbolName);
- } while (SymbolFlags.count(InitSymbol));
-
- SymbolFlags[InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
- }
- });
+ auto SymbolInfo = TSM.withModuleDo(
+ [&](const Module &M) { return getSymbolInfo(M, ES, MO, SymMapper); });
+
+ SymbolFlags = SymbolInfo.Interface.SymbolFlags;
+ InitSymbol = SymbolInfo.Interface.InitSymbol;
+
+ SymbolToDefinition = SymbolInfo.SymbolToDefinition;
}
IRMaterializationUnit::IRMaterializationUnit(
diff --git a/llvm/lib/ExecutionEngine/Orc/Mangling.cpp b/llvm/lib/ExecutionEngine/Orc/Mangling.cpp
index 2ffa856435b04f4..86c52f5133f0c93 100644
--- a/llvm/lib/ExecutionEngine/Orc/Mangling.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Mangling.cpp
@@ -27,5 +27,62 @@ SymbolStringPtr MangleAndInterner::operator()(StringRef Name) {
}
return ES.intern(MangledName);
}
+
+void IRSymbolMapper::defaultSymbolMapper(
+ ArrayRef<GlobalValue *> GVs, ExecutionSession &ES,
+ const ManglingOptions &MO, SymbolFlagsMap &SymbolFlags,
+ SymbolNameToDefinitionMap *SymbolToDefinition) {
+ if (GVs.empty())
+ return;
+
+ MangleAndInterner Mangle(ES, GVs[0]->getParent()->getDataLayout());
+ for (auto *G : GVs) {
+ assert(G && "GVs cannot contain null elements");
+ // Follow static linkage behaviour to decide which GVs get a named symbol
+ if (!G->hasName() || G->isDeclaration() || G->hasLocalLinkage() ||
+ G->hasAvailableExternallyLinkage() || G->hasAppendingLinkage() ||
+ G->hasLinkOnceODRLinkage())
+ continue;
+
+ if (G->isThreadLocal() && MO.EmulatedTLS) {
+ auto *GV = cast<GlobalVariable>(G);
+
+ auto Flags = JITSymbolFlags::fromGlobalValue(*GV);
+
+ auto EmuTLSV = Mangle(("__emutls_v." + GV->getName()).str());
+ SymbolFlags[EmuTLSV] = Flags;
+ if (SymbolToDefinition)
+ (*SymbolToDefinition)[EmuTLSV] = GV;
+
+ // If this GV has a non-zero initializer we'll need to emit an
+ // __emutls.t symbol too.
+ if (GV->hasInitializer()) {
+ const auto *InitVal = GV->getInitializer();
+
+ // Skip zero-initializers.
+ if (isa<ConstantAggregateZero>(InitVal))
+ continue;
+ const auto *InitIntValue = dyn_cast<ConstantInt>(InitVal);
+ if (InitIntValue && InitIntValue->isZero())
+ continue;
+
+ auto EmuTLST = Mangle(("__emutls_t." + GV->getName()).str());
+ SymbolFlags[EmuTLST] = Flags;
+ if (SymbolToDefinition)
+ (*SymbolToDefinition)[EmuTLST] = GV;
+ }
+ continue;
+ }
+
+ // Otherwise we just need a normal linker mangling.
+ auto MangledName = Mangle(G->getName());
+ SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(*G);
+ if (G->getComdat() &&
+ G->getComdat()->getSelectionKind() != Comdat::NoDeduplicate)
+ SymbolFlags[MangledName] |= JITSymbolFlags::Weak;
+ if (SymbolToDefinition)
+ (*SymbolToDefinition)[MangledName] = G;
+ }
+}
} // End namespace orc.
} // End namespace llvm.
>From 5a2bbeb4c8b25d13da9aac729f40a4a5d4b491ec Mon Sep 17 00:00:00 2001
From: Lucas <lucas.reis091997 at gmail.com>
Date: Sat, 27 Jan 2024 17:48:09 -0400
Subject: [PATCH 5/5] Esnure custom symbol mapping works for all overloads of
IRLayer::add
---
llvm/include/llvm/ExecutionEngine/Orc/Layer.h | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Layer.h b/llvm/include/llvm/ExecutionEngine/Orc/Layer.h
index ee8b20ec9325e5e..93daabc8aaeedad 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Layer.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Layer.h
@@ -120,8 +120,11 @@ class IRLayer {
/// Adds a MaterializationUnit representing the given IR to the given
/// JITDylib. If RT is not specified, use the default tracker for this Dylib.
- Error add(JITDylib &JD, ThreadSafeModule TSM) {
- return add(JD.getDefaultResourceTracker(), std::move(TSM));
+ Error add(JITDylib &JD, ThreadSafeModule TSM,
+ IRSymbolMapper::SymbolMapperFunction SymMapper =
+ IRSymbolMapper::defaultSymbolMapper) {
+ return add(JD.getDefaultResourceTracker(), std::move(TSM),
+ std::move(SymMapper));
}
/// Emit should materialize the given IR.
More information about the llvm-commits
mailing list