[llvm] [ORC] Unify symbol mapping and allow custom mapping functions (PR #79616)

Lucas Reis via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 26 09:26:29 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/3] [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/3] [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/3] 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;



More information about the llvm-commits mailing list