[llvm] Orc two towers draft PR (PR #152485)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 7 05:17:07 PDT 2025


https://github.com/sonar3d created https://github.com/llvm/llvm-project/pull/152485

None

>From 94f8fb63eb6c27886625531da4aa0b2bd8f45db5 Mon Sep 17 00:00:00 2001
From: Sona Reddy <sonareddy at hotmail.com>
Date: Thu, 7 Aug 2025 21:56:31 +1000
Subject: [PATCH 1/7] updated debug obj manager plugin cpp file

---
 .../Orc/DebugObjectManagerPlugin.cpp          | 459 +++---------------
 1 file changed, 65 insertions(+), 394 deletions(-)

diff --git a/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp b/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp
index 15e583ca7685d..5203453041911 100644
--- a/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp
@@ -36,68 +36,6 @@ using namespace llvm::object;
 namespace llvm {
 namespace orc {
 
-class DebugObjectSection {
-public:
-  virtual void setTargetMemoryRange(SectionRange Range) = 0;
-  virtual void dump(raw_ostream &OS, StringRef Name) {}
-  virtual ~DebugObjectSection() = default;
-};
-
-template <typename ELFT>
-class ELFDebugObjectSection : public DebugObjectSection {
-public:
-  // BinaryFormat ELF is not meant as a mutable format. We can only make changes
-  // that don't invalidate the file structure.
-  ELFDebugObjectSection(const typename ELFT::Shdr *Header)
-      : Header(const_cast<typename ELFT::Shdr *>(Header)) {}
-
-  void setTargetMemoryRange(SectionRange Range) override;
-  void dump(raw_ostream &OS, StringRef Name) override;
-
-  Error validateInBounds(StringRef Buffer, const char *Name) const;
-
-private:
-  typename ELFT::Shdr *Header;
-};
-
-template <typename ELFT>
-void ELFDebugObjectSection<ELFT>::setTargetMemoryRange(SectionRange Range) {
-  // All recorded sections are candidates for load-address patching.
-  Header->sh_addr =
-      static_cast<typename ELFT::uint>(Range.getStart().getValue());
-}
-
-template <typename ELFT>
-Error ELFDebugObjectSection<ELFT>::validateInBounds(StringRef Buffer,
-                                                    const char *Name) const {
-  const uint8_t *Start = Buffer.bytes_begin();
-  const uint8_t *End = Buffer.bytes_end();
-  const uint8_t *HeaderPtr = reinterpret_cast<uint8_t *>(Header);
-  if (HeaderPtr < Start || HeaderPtr + sizeof(typename ELFT::Shdr) > End)
-    return make_error<StringError>(
-        formatv("{0} section header at {1:x16} not within bounds of the "
-                "given debug object buffer [{2:x16} - {3:x16}]",
-                Name, &Header->sh_addr, Start, End),
-        inconvertibleErrorCode());
-  if (Header->sh_offset + Header->sh_size > Buffer.size())
-    return make_error<StringError>(
-        formatv("{0} section data [{1:x16} - {2:x16}] not within bounds of "
-                "the given debug object buffer [{3:x16} - {4:x16}]",
-                Name, Start + Header->sh_offset,
-                Start + Header->sh_offset + Header->sh_size, Start, End),
-        inconvertibleErrorCode());
-  return Error::success();
-}
-
-template <typename ELFT>
-void ELFDebugObjectSection<ELFT>::dump(raw_ostream &OS, StringRef Name) {
-  if (uint64_t Addr = Header->sh_addr) {
-    OS << formatv("  {0:x16} {1}\n", Addr, Name);
-  } else {
-    OS << formatv("                     {0}\n", Name);
-  }
-}
-
 enum DebugObjectFlags : int {
   // Request final target memory load-addresses for all sections.
   ReportFinalSectionLoadAddresses = 1 << 0,
@@ -106,121 +44,6 @@ enum DebugObjectFlags : int {
   HasDebugSections = 1 << 1,
 };
 
-/// The plugin creates a debug object from when JITLink starts processing the
-/// corresponding LinkGraph. It provides access to the pass configuration of
-/// the LinkGraph and calls the finalization function, once the resulting link
-/// artifact was emitted.
-///
-class DebugObject {
-public:
-  DebugObject(JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD,
-              ExecutionSession &ES)
-      : MemMgr(MemMgr), JD(JD), ES(ES), Flags(DebugObjectFlags{}) {}
-
-  bool hasFlags(DebugObjectFlags F) const { return Flags & F; }
-  void setFlags(DebugObjectFlags F) {
-    Flags = static_cast<DebugObjectFlags>(Flags | F);
-  }
-  void clearFlags(DebugObjectFlags F) {
-    Flags = static_cast<DebugObjectFlags>(Flags & ~F);
-  }
-
-  using FinalizeContinuation = std::function<void(Expected<ExecutorAddrRange>)>;
-
-  void finalizeAsync(FinalizeContinuation OnFinalize);
-
-  virtual ~DebugObject() {
-    if (Alloc) {
-      std::vector<FinalizedAlloc> Allocs;
-      Allocs.push_back(std::move(Alloc));
-      if (Error Err = MemMgr.deallocate(std::move(Allocs)))
-        ES.reportError(std::move(Err));
-    }
-  }
-
-  virtual void reportSectionTargetMemoryRange(StringRef Name,
-                                              SectionRange TargetMem) {}
-
-protected:
-  using InFlightAlloc = JITLinkMemoryManager::InFlightAlloc;
-  using FinalizedAlloc = JITLinkMemoryManager::FinalizedAlloc;
-
-  virtual Expected<SimpleSegmentAlloc> finalizeWorkingMemory() = 0;
-
-  JITLinkMemoryManager &MemMgr;
-  const JITLinkDylib *JD = nullptr;
-  ExecutionSession &ES;
-
-private:
-  DebugObjectFlags Flags;
-  FinalizedAlloc Alloc;
-};
-
-// Finalize working memory and take ownership of the resulting allocation. Start
-// copying memory over to the target and pass on the result once we're done.
-// Ownership of the allocation remains with us for the rest of our lifetime.
-void DebugObject::finalizeAsync(FinalizeContinuation OnFinalize) {
-  assert(!Alloc && "Cannot finalize more than once");
-
-  if (auto SimpleSegAlloc = finalizeWorkingMemory()) {
-    auto ROSeg = SimpleSegAlloc->getSegInfo(MemProt::Read);
-    ExecutorAddrRange DebugObjRange(ROSeg.Addr, ROSeg.WorkingMem.size());
-    SimpleSegAlloc->finalize(
-        [this, DebugObjRange,
-         OnFinalize = std::move(OnFinalize)](Expected<FinalizedAlloc> FA) {
-          if (FA) {
-            Alloc = std::move(*FA);
-            OnFinalize(DebugObjRange);
-          } else
-            OnFinalize(FA.takeError());
-        });
-  } else
-    OnFinalize(SimpleSegAlloc.takeError());
-}
-
-/// The current implementation of ELFDebugObject replicates the approach used in
-/// RuntimeDyld: It patches executable and data section headers in the given
-/// object buffer with load-addresses of their corresponding sections in target
-/// memory.
-///
-class ELFDebugObject : public DebugObject {
-public:
-  static Expected<std::unique_ptr<DebugObject>>
-  Create(MemoryBufferRef Buffer, JITLinkContext &Ctx, ExecutionSession &ES);
-
-  void reportSectionTargetMemoryRange(StringRef Name,
-                                      SectionRange TargetMem) override;
-
-  StringRef getBuffer() const { return Buffer->getMemBufferRef().getBuffer(); }
-
-protected:
-  Expected<SimpleSegmentAlloc> finalizeWorkingMemory() override;
-
-  template <typename ELFT>
-  Error recordSection(StringRef Name,
-                      std::unique_ptr<ELFDebugObjectSection<ELFT>> Section);
-  DebugObjectSection *getSection(StringRef Name);
-
-private:
-  template <typename ELFT>
-  static Expected<std::unique_ptr<ELFDebugObject>>
-  CreateArchType(MemoryBufferRef Buffer, JITLinkMemoryManager &MemMgr,
-                 const JITLinkDylib *JD, ExecutionSession &ES);
-
-  static std::unique_ptr<WritableMemoryBuffer>
-  CopyBuffer(MemoryBufferRef Buffer, Error &Err);
-
-  ELFDebugObject(std::unique_ptr<WritableMemoryBuffer> Buffer,
-                 JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD,
-                 ExecutionSession &ES)
-      : DebugObject(MemMgr, JD, ES), Buffer(std::move(Buffer)) {
-    setFlags(ReportFinalSectionLoadAddresses);
-  }
-
-  std::unique_ptr<WritableMemoryBuffer> Buffer;
-  StringMap<std::unique_ptr<DebugObjectSection>> Sections;
-};
-
 static const std::set<StringRef> DwarfSectionNames = {
 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
   ELF_NAME,
@@ -232,43 +55,21 @@ static bool isDwarfSection(StringRef SectionName) {
   return DwarfSectionNames.count(SectionName) == 1;
 }
 
-std::unique_ptr<WritableMemoryBuffer>
-ELFDebugObject::CopyBuffer(MemoryBufferRef Buffer, Error &Err) {
-  ErrorAsOutParameter _(Err);
-  size_t Size = Buffer.getBufferSize();
-  StringRef Name = Buffer.getBufferIdentifier();
-  if (auto Copy = WritableMemoryBuffer::getNewUninitMemBuffer(Size, Name)) {
-    memcpy(Copy->getBufferStart(), Buffer.getBufferStart(), Size);
-    return Copy;
-  }
-
-  Err = errorCodeToError(make_error_code(errc::not_enough_memory));
-  return nullptr;
-}
-
-template <typename ELFT>
-Expected<std::unique_ptr<ELFDebugObject>>
-ELFDebugObject::CreateArchType(MemoryBufferRef Buffer,
-                               JITLinkMemoryManager &MemMgr,
-                               const JITLinkDylib *JD, ExecutionSession &ES) {
-  using SectionHeader = typename ELFT::Shdr;
+template <typename ELFT> Error fixUp(StringRef Buffer, LinkGraph &LG) {
 
   Error Err = Error::success();
-  std::unique_ptr<ELFDebugObject> DebugObj(
-      new ELFDebugObject(CopyBuffer(Buffer, Err), MemMgr, JD, ES));
-  if (Err)
-    return std::move(Err);
 
-  Expected<ELFFile<ELFT>> ObjRef = ELFFile<ELFT>::create(DebugObj->getBuffer());
-  if (!ObjRef)
-    return ObjRef.takeError();
+  // TODO:replace debugObj
+  // Expected<ELFFile<ELFT>> Buffer = ELFFile<ELFT>::create(LG.g);
+  // if (!Buffer)
+  //   return Buffer.takeError();
 
-  Expected<ArrayRef<SectionHeader>> Sections = ObjRef->sections();
+  Expected<ArrayRef<SectionHeader>> Sections = Buffer->sections();
   if (!Sections)
     return Sections.takeError();
 
   for (const SectionHeader &Header : *Sections) {
-    Expected<StringRef> Name = ObjRef->getSectionName(Header);
+    Expected<StringRef> Name = Buffer->getSectionName(Header);
     if (!Name)
       return Name.takeError();
     if (Name->empty())
@@ -283,108 +84,13 @@ ELFDebugObject::CreateArchType(MemoryBufferRef Buffer,
     if (!(Header.sh_flags & ELF::SHF_ALLOC))
       continue;
 
-    auto Wrapped = std::make_unique<ELFDebugObjectSection<ELFT>>(&Header);
-    if (Error Err = DebugObj->recordSection(*Name, std::move(Wrapped)))
-      return std::move(Err);
-  }
+    if (auto *GraphSec = LG.findSectionByName(*Name))
+      Header->sh_addr =
+        static_cast<typename ELFT::uint>(SectionRange(*GraphSec).getStart().getValue());
 
   return std::move(DebugObj);
 }
 
-Expected<std::unique_ptr<DebugObject>>
-ELFDebugObject::Create(MemoryBufferRef Buffer, JITLinkContext &Ctx,
-                       ExecutionSession &ES) {
-  unsigned char Class, Endian;
-  std::tie(Class, Endian) = getElfArchType(Buffer.getBuffer());
-
-  if (Class == ELF::ELFCLASS32) {
-    if (Endian == ELF::ELFDATA2LSB)
-      return CreateArchType<ELF32LE>(Buffer, Ctx.getMemoryManager(),
-                                     Ctx.getJITLinkDylib(), ES);
-    if (Endian == ELF::ELFDATA2MSB)
-      return CreateArchType<ELF32BE>(Buffer, Ctx.getMemoryManager(),
-                                     Ctx.getJITLinkDylib(), ES);
-    return nullptr;
-  }
-  if (Class == ELF::ELFCLASS64) {
-    if (Endian == ELF::ELFDATA2LSB)
-      return CreateArchType<ELF64LE>(Buffer, Ctx.getMemoryManager(),
-                                     Ctx.getJITLinkDylib(), ES);
-    if (Endian == ELF::ELFDATA2MSB)
-      return CreateArchType<ELF64BE>(Buffer, Ctx.getMemoryManager(),
-                                     Ctx.getJITLinkDylib(), ES);
-    return nullptr;
-  }
-  return nullptr;
-}
-
-Expected<SimpleSegmentAlloc> ELFDebugObject::finalizeWorkingMemory() {
-  LLVM_DEBUG({
-    dbgs() << "Section load-addresses in debug object for \""
-           << Buffer->getBufferIdentifier() << "\":\n";
-    for (const auto &KV : Sections)
-      KV.second->dump(dbgs(), KV.first());
-  });
-
-  // TODO: This works, but what actual alignment requirements do we have?
-  unsigned PageSize = sys::Process::getPageSizeEstimate();
-  size_t Size = Buffer->getBufferSize();
-
-  // Allocate working memory for debug object in read-only segment.
-  auto Alloc = SimpleSegmentAlloc::Create(
-      MemMgr, ES.getSymbolStringPool(), ES.getTargetTriple(), JD,
-      {{MemProt::Read, {Size, Align(PageSize)}}});
-  if (!Alloc)
-    return Alloc;
-
-  // Initialize working memory with a copy of our object buffer.
-  auto SegInfo = Alloc->getSegInfo(MemProt::Read);
-  memcpy(SegInfo.WorkingMem.data(), Buffer->getBufferStart(), Size);
-  Buffer.reset();
-
-  return Alloc;
-}
-
-void ELFDebugObject::reportSectionTargetMemoryRange(StringRef Name,
-                                                    SectionRange TargetMem) {
-  if (auto *DebugObjSection = getSection(Name))
-    DebugObjSection->setTargetMemoryRange(TargetMem);
-}
-
-template <typename ELFT>
-Error ELFDebugObject::recordSection(
-    StringRef Name, std::unique_ptr<ELFDebugObjectSection<ELFT>> Section) {
-  if (Error Err = Section->validateInBounds(this->getBuffer(), Name.data()))
-    return Err;
-  bool Inserted = Sections.try_emplace(Name, std::move(Section)).second;
-  if (!Inserted)
-    LLVM_DEBUG(dbgs() << "Skipping debug registration for section '" << Name
-                      << "' in object " << Buffer->getBufferIdentifier()
-                      << " (duplicate name)\n");
-  return Error::success();
-}
-
-DebugObjectSection *ELFDebugObject::getSection(StringRef Name) {
-  auto It = Sections.find(Name);
-  return It == Sections.end() ? nullptr : It->second.get();
-}
-
-/// Creates a debug object based on the input object file from
-/// ObjectLinkingLayerJITLinkContext.
-///
-static Expected<std::unique_ptr<DebugObject>>
-createDebugObjectFromBuffer(ExecutionSession &ES, LinkGraph &G,
-                            JITLinkContext &Ctx, MemoryBufferRef ObjBuffer) {
-  switch (G.getTargetTriple().getObjectFormat()) {
-  case Triple::ELF:
-    return ELFDebugObject::Create(ObjBuffer, Ctx, ES);
-
-  default:
-    // TODO: Once we add support for other formats, we might want to split this
-    // into multiple files.
-    return nullptr;
-  }
-}
 
 DebugObjectManagerPlugin::DebugObjectManagerPlugin(
     ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target,
@@ -399,119 +105,84 @@ DebugObjectManagerPlugin::DebugObjectManagerPlugin(
 
 DebugObjectManagerPlugin::~DebugObjectManagerPlugin() = default;
 
-void DebugObjectManagerPlugin::notifyMaterializing(
-    MaterializationResponsibility &MR, LinkGraph &G, JITLinkContext &Ctx,
-    MemoryBufferRef ObjBuffer) {
-  std::lock_guard<std::mutex> Lock(PendingObjsLock);
-  assert(PendingObjs.count(&MR) == 0 &&
-         "Cannot have more than one pending debug object per "
-         "MaterializationResponsibility");
-
-  if (auto DebugObj = createDebugObjectFromBuffer(ES, G, Ctx, ObjBuffer)) {
-    // Not all link artifacts allow debugging.
-    if (*DebugObj == nullptr)
-      return;
-    if (RequireDebugSections && !(**DebugObj).hasFlags(HasDebugSections)) {
-      LLVM_DEBUG(dbgs() << "Skipping debug registration for LinkGraph '"
-                        << G.getName() << "': no debug info\n");
-      return;
-    }
-    PendingObjs[&MR] = std::move(*DebugObj);
-  } else {
-    ES.reportError(DebugObj.takeError());
+void fixUpDebugObject(LinkGraph &LG) {
+  auto *DebugObjSec = LG.getOriginalObjectContentSection();
+  assert(DebugObjSec && "No ELF debug object section?");
+  assert(DebugObjSec.blocks_size() == 1 && "ELF debug object contains multiple blocks?");
+  auto DebugObjContent = (*DebugObjSec.blocks_begin())->getAlreadyMutableContent();
+
+  // StringRef DebugObj(DebugObjContent.data(), DebugObjContent.size());
+
+  unsigned char Class, Endian;
+  std::tie(Class, Endian) = getElfArchType(DebugObjContent);
+  if (Class == ELF::ELFCLASS32) {
+    if (Endian == ELF::ELFDATA2LSB)
+      return fixUp<ELF32LE>(DebugObjContent, LG);
+    else if (Endian == ELF::ELFDATA2MSB)
+      return fixUp<ELF32BE>(DebugObjContent, LG);
+  } else if (Class == ELF::ELFCLASS64) {
+    if (Endian == ELF::ELFDATA2LSB)
+      return fixUp<ELF64LE>(DebugObjContent, LG);
+    else if (Endian == ELF::ELFDATA2MSB)
+      return fixUp<ELF64BE>(DebugObjContent, LG);
   }
-}
+  // Unsupported combo. Remove the debug object section.
+  LG.removeSection(*DebugObjSec);
+  LLVM_DEBUG({
+    dbgs() << "Can't emit debug object for " << LG.getName()
+           << ": Unsupported ELF class / endianness.\n";
+  });
+  return Error::success();
+}                                                                 
 
-void DebugObjectManagerPlugin::modifyPassConfig(
-    MaterializationResponsibility &MR, LinkGraph &G,
-    PassConfiguration &PassConfig) {
+void DebugObjectManagerPlugin::modifyPassConfig(MaterializationResponsibility &MR,
+  jitlink::LinkGraph &LG,
+  jitlink::PassConfiguration &PassConfig) {
   // Not all link artifacts have associated debug objects.
-  std::lock_guard<std::mutex> Lock(PendingObjsLock);
+  // std::lock_guard<std::mutex> Lock(PendingObjsLock);
   auto It = PendingObjs.find(&MR);
   if (It == PendingObjs.end())
     return;
 
-  DebugObject &DebugObj = *It->second;
-  if (DebugObj.hasFlags(ReportFinalSectionLoadAddresses)) {
+  PassConfig.PrePrunePasses.push_back([](LinkGraph &LG) -> Error {
+    
+    // Copy existing object content into the new debug object section
+    auto DebugObjContent = LG.getOriginalObjectContentSection();
+    // Create new debug section in LinkGraph
+    
+    // Memory protection for reading graph
+    orc::MemProt Prot = MemProt::Read;
+    // Create debug section
+    LG.createSection(DebugObjContent, Prot);
+
+    return Error::success();
+  });
+  
+  if (DebugObjContent.hasFlags(ReportFinalSectionLoadAddresses)) {
+  // patch up the addresses in the debug object
     PassConfig.PostAllocationPasses.push_back(
-        [&DebugObj](LinkGraph &Graph) -> Error {
-          for (const Section &GraphSection : Graph.sections())
-            DebugObj.reportSectionTargetMemoryRange(GraphSection.getName(),
+        [&DebugObjContent](LinkGraph &LG) -> Error {
+          for (const Section &GraphSection : LG.sections())
+            DebugObjContent.reportSectionTargetMemoryRange(GraphSection.getName(),
                                                     SectionRange(GraphSection));
+          fixUpDebugObject(LG)
           return Error::success();
         });
   }
 }
 
-Error DebugObjectManagerPlugin::notifyEmitted(
-    MaterializationResponsibility &MR) {
-  std::lock_guard<std::mutex> Lock(PendingObjsLock);
-  auto It = PendingObjs.find(&MR);
-  if (It == PendingObjs.end())
-    return Error::success();
-
-  // During finalization the debug object is registered with the target.
-  // Materialization must wait for this process to finish. Otherwise we might
-  // start running code before the debugger processed the corresponding debug
-  // info.
-  std::promise<MSVCPError> FinalizePromise;
-  std::future<MSVCPError> FinalizeErr = FinalizePromise.get_future();
-
-  It->second->finalizeAsync(
-      [this, &FinalizePromise, &MR](Expected<ExecutorAddrRange> TargetMem) {
-        // Any failure here will fail materialization.
-        if (!TargetMem) {
-          FinalizePromise.set_value(TargetMem.takeError());
-          return;
-        }
-        if (Error Err =
-                Target->registerDebugObject(*TargetMem, AutoRegisterCode)) {
-          FinalizePromise.set_value(std::move(Err));
-          return;
-        }
-
-        // Once our tracking info is updated, notifyEmitted() can return and
-        // finish materialization.
-        FinalizePromise.set_value(MR.withResourceKeyDo([&](ResourceKey K) {
-          assert(PendingObjs.count(&MR) && "We still hold PendingObjsLock");
-          std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
-          auto It = PendingObjs.find(&MR);
-          RegisteredObjs[K].push_back(std::move(It->second));
-          PendingObjs.erase(It);
-        }));
-      });
-
-  return FinalizeErr.get();
-}
-
 Error DebugObjectManagerPlugin::notifyFailed(
     MaterializationResponsibility &MR) {
-  std::lock_guard<std::mutex> Lock(PendingObjsLock);
+  // std::lock_guard<std::mutex> Lock(PendingObjsLock);
   PendingObjs.erase(&MR);
   return Error::success();
 }
 
-void DebugObjectManagerPlugin::notifyTransferringResources(JITDylib &JD,
-                                                           ResourceKey DstKey,
-                                                           ResourceKey SrcKey) {
-  // Debug objects are stored by ResourceKey only after registration.
-  // Thus, pending objects don't need to be updated here.
-  std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
-  auto SrcIt = RegisteredObjs.find(SrcKey);
-  if (SrcIt != RegisteredObjs.end()) {
-    // Resources from distinct MaterializationResponsibilitys can get merged
-    // after emission, so we can have multiple debug objects per resource key.
-    for (std::unique_ptr<DebugObject> &DebugObj : SrcIt->second)
-      RegisteredObjs[DstKey].push_back(std::move(DebugObj));
-    RegisteredObjs.erase(SrcIt);
-  }
-}
-
 Error DebugObjectManagerPlugin::notifyRemovingResources(JITDylib &JD,
                                                         ResourceKey Key) {
   // Removing the resource for a pending object fails materialization, so they
   // get cleaned up in the notifyFailed() handler.
-  std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
+  // std::lock_guard<std::mutex> Lock(RegisteredObjsLock);
   RegisteredObjs.erase(Key);
 
   // TODO: Implement unregister notifications.
@@ -519,4 +190,4 @@ Error DebugObjectManagerPlugin::notifyRemovingResources(JITDylib &JD,
 }
 
 } // namespace orc
-} // namespace llvm
+} // namespace llvm
\ No newline at end of file

>From 7be63051e1b4a187347803d148bbebcc77f95fb1 Mon Sep 17 00:00:00 2001
From: Sona Reddy <sonareddy at hotmail.com>
Date: Thu, 7 Aug 2025 22:00:34 +1000
Subject: [PATCH 2/7] link graph linking layer cpp

---
 .../Orc/LinkGraphLinkingLayer.cpp             | 29 ++++++++++---------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/llvm/lib/ExecutionEngine/Orc/LinkGraphLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/LinkGraphLinkingLayer.cpp
index d1a6eaf914a78..32e57b2a61dce 100644
--- a/llvm/lib/ExecutionEngine/Orc/LinkGraphLinkingLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LinkGraphLinkingLayer.cpp
@@ -64,13 +64,6 @@ class LinkGraphLinkingLayer::JITLinkCtx final : public JITLinkContext {
 
   JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
 
-  void notifyMaterializing(LinkGraph &G) {
-    for (auto &P : Plugins)
-      P->notifyMaterializing(*MR, G, *this,
-                             ObjBuffer ? ObjBuffer->getMemBufferRef()
-                                       : MemoryBufferRef());
-  }
-
   void notifyFailed(Error Err) override {
     for (auto &P : Plugins)
       Err = joinErrors(std::move(Err), P->notifyFailed(*MR));
@@ -108,7 +101,8 @@ class LinkGraphLinkingLayer::JITLinkCtx final : public JITLinkContext {
         LookupContinuation->run(Result.takeError());
       else {
         AsyncLookupResult LR;
-        LR.insert_range(*Result);
+        for (auto &KV : *Result)
+          LR[KV.first] = KV.second;
         LookupContinuation->run(std::move(LR));
       }
     };
@@ -207,6 +201,7 @@ class LinkGraphLinkingLayer::JITLinkCtx final : public JITLinkContext {
     if (auto Err = MR->notifyResolved(InternedResult))
       return Err;
 
+    notifyLoaded();
     return Error::success();
   }
 
@@ -243,6 +238,11 @@ class LinkGraphLinkingLayer::JITLinkCtx final : public JITLinkContext {
     return Error::success();
   }
 
+  void notifyLoaded() {
+    for (auto &P : Plugins)
+      P->notifyLoaded(*MR);
+  }
+
   Error notifyEmitted(jitlink::JITLinkMemoryManager::FinalizedAlloc FA) {
     Error Err = Error::success();
     for (auto &P : Plugins)
@@ -389,13 +389,16 @@ class LinkGraphLinkingLayer::JITLinkCtx final : public JITLinkContext {
 
         for (auto *FB : BI.AnonEdges) {
           auto &FBI = BlockInfos[FB];
-          FBI.AnonBackEdges.insert_range(BI.AnonBackEdges);
+          for (auto *BB : BI.AnonBackEdges)
+            FBI.AnonBackEdges.insert(BB);
         }
 
         for (auto *BB : BI.AnonBackEdges) {
           auto &BBI = BlockInfos[BB];
-          BBI.SymbolDeps.insert_range(BI.SymbolDeps);
-          BBI.AnonEdges.insert_range(BI.AnonEdges);
+          for (auto *SD : BI.SymbolDeps)
+            BBI.SymbolDeps.insert(SD);
+          for (auto *FB : BI.AnonEdges)
+            BBI.AnonEdges.insert(FB);
         }
       }
 
@@ -502,7 +505,6 @@ void LinkGraphLinkingLayer::emit(
   assert(R && "R must not be null");
   assert(G && "G must not be null");
   auto Ctx = std::make_unique<JITLinkCtx>(*this, std::move(R), nullptr);
-  Ctx->notifyMaterializing(*G);
   link(std::move(G), std::move(Ctx));
 }
 
@@ -514,7 +516,6 @@ void LinkGraphLinkingLayer::emit(
   assert(ObjBuf && "Object must not be null");
   auto Ctx =
       std::make_unique<JITLinkCtx>(*this, std::move(R), std::move(ObjBuf));
-  Ctx->notifyMaterializing(*G);
   link(std::move(G), std::move(Ctx));
 }
 
@@ -575,4 +576,4 @@ void LinkGraphLinkingLayer::handleTransferResources(JITDylib &JD,
 }
 
 } // End namespace orc.
-} // End namespace llvm.
+} // End namespace llvm.
\ No newline at end of file

>From d315e38533f7623abe998fb8f9920f4fa3018d03 Mon Sep 17 00:00:00 2001
From: Sona Reddy <sonareddy at hotmail.com>
Date: Thu, 7 Aug 2025 22:02:40 +1000
Subject: [PATCH 3/7] object linking layer cpp

---
 .../Orc/ObjectLinkingLayer.cpp                | 745 +++++++++++++++++-
 1 file changed, 738 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
index 9bc0aa89c3533..3da46d97d3568 100644
--- a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
@@ -12,7 +12,592 @@
 
 #define DEBUG_TYPE "orc"
 
-namespace llvm::orc {
+using namespace llvm;
+using namespace llvm::jitlink;
+using namespace llvm::orc;
+
+namespace {
+
+bool hasInitializerSection(jitlink::LinkGraph &LG) {
+  bool IsMachO = LG.getTargetTriple().isOSBinFormatMachO();
+  bool IsElf = LG.getTargetTriple().isOSBinFormatELF();
+  if (!IsMachO && !IsElf)
+    return false;
+
+  for (auto &Sec : LG.sections()) {
+    if (IsMachO && isMachOInitializerSection(Sec.getName()))
+      return true;
+    if (IsElf && isELFInitializerSection(Sec.getName()))
+      return true;
+  }
+
+  return false;
+}
+
+ExecutorAddr getJITSymbolPtrForSymbol(Symbol &Sym, const Triple &TT) {
+  switch (TT.getArch()) {
+  case Triple::arm:
+  case Triple::armeb:
+  case Triple::thumb:
+  case Triple::thumbeb:
+    if (hasTargetFlags(Sym, aarch32::ThumbSymbol)) {
+      // Set LSB to indicate thumb target
+      assert(Sym.isCallable() && "Only callable symbols can have thumb flag");
+      assert((Sym.getAddress().getValue() & 0x01) == 0 && "LSB is clear");
+      return Sym.getAddress() + 0x01;
+    }
+    return Sym.getAddress();
+  default:
+    return Sym.getAddress();
+  }
+}
+
+JITSymbolFlags getJITSymbolFlagsForSymbol(Symbol &Sym) {
+  JITSymbolFlags Flags;
+
+  if (Sym.getLinkage() == Linkage::Weak)
+    Flags |= JITSymbolFlags::Weak;
+
+  if (Sym.getScope() == Scope::Default)
+    Flags |= JITSymbolFlags::Exported;
+
+  if (Sym.isCallable())
+    Flags |= JITSymbolFlags::Callable;
+
+  return Flags;
+}
+
+class LinkGraphMaterializationUnit : public MaterializationUnit {
+public:
+  static std::unique_ptr<LinkGraphMaterializationUnit>
+  Create(ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr<LinkGraph> G) {
+    auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *G);
+    return std::unique_ptr<LinkGraphMaterializationUnit>(
+        new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(G),
+                                         std::move(LGI)));
+  }
+
+  StringRef getName() const override { return G->getName(); }
+  void materialize(std::unique_ptr<MaterializationResponsibility> MR) override {
+    ObjLinkingLayer.emit(std::move(MR), std::move(G));
+  }
+
+private:
+  static Interface scanLinkGraph(ExecutionSession &ES, LinkGraph &LG) {
+
+    Interface LGI;
+
+    auto AddSymbol = [&](Symbol *Sym) {
+      // Skip local symbols.
+      if (Sym->getScope() == Scope::Local)
+        return;
+      assert(Sym->hasName() && "Anonymous non-local symbol?");
+
+      LGI.SymbolFlags[ES.intern(Sym->getName())] =
+          getJITSymbolFlagsForSymbol(*Sym);
+    };
+
+    for (auto *Sym : LG.defined_symbols())
+      AddSymbol(Sym);
+    for (auto *Sym : LG.absolute_symbols())
+      AddSymbol(Sym);
+
+    if (hasInitializerSection(LG))
+      LGI.InitSymbol = makeInitSymbol(ES, LG);
+
+    return LGI;
+  }
+
+  static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &LG) {
+    std::string InitSymString;
+    raw_string_ostream(InitSymString)
+        << "$." << LG.getName() << ".__inits" << Counter++;
+    return ES.intern(InitSymString);
+  }
+
+  LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer,
+                               std::unique_ptr<LinkGraph> G, Interface LGI)
+      : MaterializationUnit(std::move(LGI)), ObjLinkingLayer(ObjLinkingLayer),
+        G(std::move(G)) {}
+
+  void discard(const JITDylib &JD, const SymbolStringPtr &Name) override {
+    for (auto *Sym : G->defined_symbols())
+      if (Sym->getName() == *Name) {
+        assert(Sym->getLinkage() == Linkage::Weak &&
+               "Discarding non-weak definition");
+        G->makeExternal(*Sym);
+        break;
+      }
+  }
+
+  ObjectLinkingLayer &ObjLinkingLayer;
+  std::unique_ptr<LinkGraph> G;
+  static std::atomic<uint64_t> Counter;
+};
+
+std::atomic<uint64_t> LinkGraphMaterializationUnit::Counter{0};
+
+} // end anonymous namespace
+
+namespace llvm {
+namespace orc {
+
+class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {
+public:
+  ObjectLinkingLayerJITLinkContext(
+      ObjectLinkingLayer &Layer,
+      std::unique_ptr<MaterializationResponsibility> MR,
+      std::unique_ptr<MemoryBuffer> ObjBuffer)
+      : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer),
+        MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {
+    std::lock_guard<std::mutex> Lock(Layer.LayerMutex);
+    Plugins = Layer.Plugins;
+  }
+
+  ~ObjectLinkingLayerJITLinkContext() {
+    // If there is an object buffer return function then use it to
+    // return ownership of the buffer.
+    if (Layer.ReturnObjectBuffer && ObjBuffer)
+      Layer.ReturnObjectBuffer(std::move(ObjBuffer));
+  }
+
+  JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
+
+  // void notifyMaterializing(LinkGraph &G) {
+  //   for (auto &P : Plugins)
+  //     P->notifyMaterializing(*MR, G, *this,
+  //                            ObjBuffer ? ObjBuffer->getMemBufferRef()
+  //                            : MemoryBufferRef());
+  // }
+
+
+  void notifyFailed(Error Err) override {
+    for (auto &P : Plugins)
+      Err = joinErrors(std::move(Err), P->notifyFailed(*MR));
+    Layer.getExecutionSession().reportError(std::move(Err));
+    MR->failMaterialization();
+  }
+
+  void lookup(const LookupMap &Symbols,
+              std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override {
+
+    JITDylibSearchOrder LinkOrder;
+    MR->getTargetJITDylib().withLinkOrderDo(
+        [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; });
+
+    auto &ES = Layer.getExecutionSession();
+
+    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 = [LookupContinuation =
+                          std::move(LC)](Expected<SymbolMap> Result) mutable {
+      if (!Result)
+        LookupContinuation->run(Result.takeError());
+      else {
+        AsyncLookupResult LR;
+        for (auto &KV : *Result)
+          LR[*KV.first] = KV.second;
+        LookupContinuation->run(std::move(LR));
+      }
+    };
+
+    ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet),
+              SymbolState::Resolved, std::move(OnResolve),
+              [this](const SymbolDependenceMap &Deps) {
+                // Translate LookupDeps map to SymbolSourceJD.
+                for (auto &[DepJD, Deps] : Deps)
+                  for (auto &DepSym : Deps)
+                    SymbolSourceJDs[NonOwningSymbolStringPtr(DepSym)] = DepJD;
+              });
+  }
+
+  Error notifyResolved(LinkGraph &G) override {
+    auto &ES = Layer.getExecutionSession();
+
+    SymbolFlagsMap ExtraSymbolsToClaim;
+    bool AutoClaim = Layer.AutoClaimObjectSymbols;
+
+    SymbolMap InternedResult;
+    for (auto *Sym : G.defined_symbols())
+      if (Sym->hasName() && Sym->getScope() != Scope::Local) {
+        auto InternedName = ES.intern(Sym->getName());
+        auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple());
+        auto Flags = getJITSymbolFlagsForSymbol(*Sym);
+        InternedResult[InternedName] = {Ptr, Flags};
+        if (AutoClaim && !MR->getSymbols().count(InternedName)) {
+          assert(!ExtraSymbolsToClaim.count(InternedName) &&
+                 "Duplicate symbol to claim?");
+          ExtraSymbolsToClaim[InternedName] = Flags;
+        }
+      }
+
+    for (auto *Sym : G.absolute_symbols())
+      if (Sym->hasName() && Sym->getScope() != Scope::Local) {
+        auto InternedName = ES.intern(Sym->getName());
+        auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple());
+        auto Flags = getJITSymbolFlagsForSymbol(*Sym);
+        InternedResult[InternedName] = {Ptr, Flags};
+        if (AutoClaim && !MR->getSymbols().count(InternedName)) {
+          assert(!ExtraSymbolsToClaim.count(InternedName) &&
+                 "Duplicate symbol to claim?");
+          ExtraSymbolsToClaim[InternedName] = Flags;
+        }
+      }
+
+    if (!ExtraSymbolsToClaim.empty())
+      if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim))
+        return Err;
+
+    {
+
+      // Check that InternedResult matches up with MR->getSymbols(), overriding
+      // flags if requested.
+      // This guards against faulty transformations / compilers / object caches.
+
+      // First check that there aren't any missing symbols.
+      size_t NumMaterializationSideEffectsOnlySymbols = 0;
+      SymbolNameVector MissingSymbols;
+      for (auto &[Sym, Flags] : MR->getSymbols()) {
+
+        auto I = InternedResult.find(Sym);
+
+        // If this is a materialization-side-effects only symbol then bump
+        // the counter and remove in from the result, otherwise make sure that
+        // it's defined.
+        if (Flags.hasMaterializationSideEffectsOnly()) {
+          ++NumMaterializationSideEffectsOnlySymbols;
+          InternedResult.erase(Sym);
+          continue;
+        } else if (I == InternedResult.end())
+          MissingSymbols.push_back(Sym);
+        else if (Layer.OverrideObjectFlags)
+          I->second.setFlags(Flags);
+      }
+
+      // If there were missing symbols then report the error.
+      if (!MissingSymbols.empty())
+        return make_error<MissingSymbolDefinitions>(
+            Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
+            std::move(MissingSymbols));
+
+      // If there are more definitions than expected, add them to the
+      // ExtraSymbols vector.
+      SymbolNameVector ExtraSymbols;
+      if (InternedResult.size() >
+          MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {
+        for (auto &KV : InternedResult)
+          if (!MR->getSymbols().count(KV.first))
+            ExtraSymbols.push_back(KV.first);
+      }
+
+      // If there were extra definitions then report the error.
+      if (!ExtraSymbols.empty())
+        return make_error<UnexpectedSymbolDefinitions>(
+            Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
+            std::move(ExtraSymbols));
+    }
+
+    if (auto Err = MR->notifyResolved(InternedResult))
+      return Err;
+
+    notifyLoaded();
+    return Error::success();
+  }
+
+  void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override {
+    if (auto Err = notifyEmitted(std::move(A))) {
+      Layer.getExecutionSession().reportError(std::move(Err));
+      MR->failMaterialization();
+      return;
+    }
+
+    if (auto Err = MR->notifyEmitted(SymbolDepGroups)) {
+      Layer.getExecutionSession().reportError(std::move(Err));
+      MR->failMaterialization();
+    }
+  }
+
+  LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override {
+    return [this](LinkGraph &LG) { return markResponsibilitySymbolsLive(LG); };
+  }
+
+  Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override {
+    // Add passes to mark duplicate defs as should-discard, and to walk the
+    // link graph to build the symbol dependence graph.
+    Config.PrePrunePasses.push_back([this](LinkGraph &G) {
+      return claimOrExternalizeWeakAndCommonSymbols(G);
+    });
+
+    for (auto &P : Plugins)
+      P->modifyPassConfig(*MR, LG, Config);
+
+    Config.PreFixupPasses.push_back(
+        [this](LinkGraph &G) { return registerDependencies(G); });
+
+    return Error::success();
+  }
+
+  void notifyLoaded() {
+    for (auto &P : Plugins)
+      P->notifyLoaded(*MR);
+  }
+
+  Error notifyEmitted(jitlink::JITLinkMemoryManager::FinalizedAlloc FA) {
+    Error Err = Error::success();
+    for (auto &P : Plugins)
+      Err = joinErrors(std::move(Err), P->notifyEmitted(*MR));
+
+    if (Err) {
+      if (FA)
+        Err =
+            joinErrors(std::move(Err), Layer.MemMgr.deallocate(std::move(FA)));
+      return Err;
+    }
+
+    if (FA)
+      return Layer.recordFinalizedAlloc(*MR, std::move(FA));
+
+    return Error::success();
+  }
+
+private:
+  Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) {
+    auto &ES = Layer.getExecutionSession();
+
+    SymbolFlagsMap NewSymbolsToClaim;
+    std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym;
+
+    auto ProcessSymbol = [&](Symbol *Sym) {
+      if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak &&
+          Sym->getScope() != Scope::Local) {
+        auto Name = ES.intern(Sym->getName());
+        if (!MR->getSymbols().count(ES.intern(Sym->getName()))) {
+          NewSymbolsToClaim[Name] =
+              getJITSymbolFlagsForSymbol(*Sym) | JITSymbolFlags::Weak;
+          NameToSym.push_back(std::make_pair(std::move(Name), Sym));
+        }
+      }
+    };
+
+    for (auto *Sym : G.defined_symbols())
+      ProcessSymbol(Sym);
+    for (auto *Sym : G.absolute_symbols())
+      ProcessSymbol(Sym);
+
+    // Attempt to claim all weak defs that we're not already responsible for.
+    // This may fail if the resource tracker has become defunct, but should
+    // always succeed otherwise.
+    if (auto Err = MR->defineMaterializing(std::move(NewSymbolsToClaim)))
+      return Err;
+
+    // Walk the list of symbols that we just tried to claim. Symbols that we're
+    // responsible for are marked live. Symbols that we're not responsible for
+    // are turned into external references.
+    for (auto &KV : NameToSym) {
+      if (MR->getSymbols().count(KV.first))
+        KV.second->setLive(true);
+      else
+        G.makeExternal(*KV.second);
+    }
+
+    return Error::success();
+  }
+
+  Error markResponsibilitySymbolsLive(LinkGraph &G) const {
+    auto &ES = Layer.getExecutionSession();
+    for (auto *Sym : G.defined_symbols())
+      if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName())))
+        Sym->setLive(true);
+    return Error::success();
+  }
+
+  Error registerDependencies(LinkGraph &G) {
+
+    struct BlockInfo {
+      bool InWorklist = false;
+      DenseSet<Symbol *> Defs;
+      DenseSet<Symbol *> SymbolDeps;
+      DenseSet<Block *> AnonEdges, AnonBackEdges;
+    };
+
+    DenseMap<Block *, BlockInfo> BlockInfos;
+
+    // Reserve space so that BlockInfos doesn't need to resize. This is
+    // essential to avoid invalidating pointers to entries below.
+    {
+      size_t NumBlocks = 0;
+      for (auto &Sec : G.sections())
+        NumBlocks += Sec.blocks_size();
+      BlockInfos.reserve(NumBlocks);
+    }
+
+    // Identify non-locally-scoped symbols defined by each block.
+    for (auto *Sym : G.defined_symbols()) {
+      if (Sym->getScope() != Scope::Local)
+        BlockInfos[&Sym->getBlock()].Defs.insert(Sym);
+    }
+
+    // Identify the symbolic and anonymous-block dependencies for each block.
+    for (auto *B : G.blocks()) {
+      auto &BI = BlockInfos[B];
+
+      for (auto &E : B->edges()) {
+
+        // External symbols are trivially depended on.
+        if (E.getTarget().isExternal()) {
+          BI.SymbolDeps.insert(&E.getTarget());
+          continue;
+        }
+
+        // Anonymous symbols aren't depended on at all (they're assumed to be
+        // already available).
+        if (E.getTarget().isAbsolute())
+          continue;
+
+        // If we get here then we depend on a symbol defined by some other
+        // block.
+        auto &TgtBI = BlockInfos[&E.getTarget().getBlock()];
+
+        // If that block has any definitions then use the first one as the
+        // "effective" dependence here (all symbols in TgtBI will become
+        // ready at the same time, and chosing a single symbol to represent
+        // the block keeps the SymbolDepGroup size small).
+        if (!TgtBI.Defs.empty()) {
+          BI.SymbolDeps.insert(*TgtBI.Defs.begin());
+          continue;
+        }
+
+        // Otherwise we've got a dependence on an anonymous block. Record it
+        // here for back-propagating symbol dependencies below.
+        BI.AnonEdges.insert(&E.getTarget().getBlock());
+        TgtBI.AnonBackEdges.insert(B);
+      }
+    }
+
+    // Prune anonymous blocks.
+    {
+      std::vector<Block *> BlocksToRemove;
+      for (auto &[B, BI] : BlockInfos) {
+        // Skip blocks with defs. We only care about anonyous blocks.
+        if (!BI.Defs.empty())
+          continue;
+
+        BlocksToRemove.push_back(B);
+
+        for (auto *FB : BI.AnonEdges)
+          BlockInfos[FB].AnonBackEdges.erase(B);
+
+        for (auto *BB : BI.AnonBackEdges)
+          BlockInfos[BB].AnonEdges.erase(B);
+
+        for (auto *FB : BI.AnonEdges) {
+          auto &FBI = BlockInfos[FB];
+          for (auto *BB : BI.AnonBackEdges)
+            FBI.AnonBackEdges.insert(BB);
+        }
+
+        for (auto *BB : BI.AnonBackEdges) {
+          auto &BBI = BlockInfos[BB];
+          for (auto *SD : BI.SymbolDeps)
+            BBI.SymbolDeps.insert(SD);
+          for (auto *FB : BI.AnonEdges)
+            BBI.AnonEdges.insert(FB);
+        }
+      }
+
+      for (auto *B : BlocksToRemove)
+        BlockInfos.erase(B);
+    }
+
+    // Build the initial dependence propagation worklist.
+    std::deque<Block *> Worklist;
+    for (auto &[B, BI] : BlockInfos) {
+      if (!BI.SymbolDeps.empty() && !BI.AnonBackEdges.empty()) {
+        Worklist.push_back(B);
+        BI.InWorklist = true;
+      }
+    }
+
+    // Propagate symbol deps through the graph.
+    while (!Worklist.empty()) {
+      auto *B = Worklist.front();
+      Worklist.pop_front();
+
+      auto &BI = BlockInfos[B];
+      BI.InWorklist = false;
+
+      for (auto *DB : BI.AnonBackEdges) {
+        auto &DBI = BlockInfos[DB];
+        for (auto *Sym : BI.SymbolDeps) {
+          if (DBI.SymbolDeps.insert(Sym).second && !DBI.InWorklist) {
+            Worklist.push_back(DB);
+            DBI.InWorklist = true;
+          }
+        }
+      }
+    }
+
+    // Transform our local dependence information into a list of
+    // SymbolDependenceGroups (in the SymbolDepGroups member), ready for use in
+    // the upcoming notifyFinalized call.
+    auto &TargetJD = MR->getTargetJITDylib();
+    auto &ES = TargetJD.getExecutionSession();
+
+    DenseMap<Symbol *, SymbolStringPtr> InternedNames;
+    auto GetInternedName = [&](Symbol *S) {
+      auto &Name = InternedNames[S];
+      if (!Name)
+        Name = ES.intern(S->getName());
+      return Name;
+    };
+
+    for (auto &[B, BI] : BlockInfos) {
+      if (!BI.Defs.empty()) {
+        SymbolDepGroups.push_back(SymbolDependenceGroup());
+        auto &SDG = SymbolDepGroups.back();
+
+        for (auto *Def : BI.Defs)
+          SDG.Symbols.insert(GetInternedName(Def));
+
+        for (auto *Dep : BI.SymbolDeps) {
+          auto DepName = GetInternedName(Dep);
+          if (Dep->isDefined())
+            SDG.Dependencies[&TargetJD].insert(std::move(DepName));
+          else {
+            auto SourceJDItr =
+                SymbolSourceJDs.find(NonOwningSymbolStringPtr(DepName));
+            if (SourceJDItr != SymbolSourceJDs.end())
+              SDG.Dependencies[SourceJDItr->second].insert(std::move(DepName));
+          }
+        }
+      }
+    }
+
+    return Error::success();
+  }
+
+  ObjectLinkingLayer &Layer;
+  std::vector<std::shared_ptr<ObjectLinkingLayer::Plugin>> Plugins;
+  std::unique_ptr<MaterializationResponsibility> MR;
+  std::unique_ptr<MemoryBuffer> ObjBuffer;
+  DenseMap<NonOwningSymbolStringPtr, JITDylib *> SymbolSourceJDs;
+  std::vector<SymbolDependenceGroup> SymbolDepGroups;
+};
+
+ObjectLinkingLayer::Plugin::~Plugin() = default;
 
 char ObjectLinkingLayer::ID;
 
@@ -21,14 +606,160 @@ void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
   assert(O && "Object must not be null");
   MemoryBufferRef ObjBuffer = O->getMemBufferRef();
 
-  if (auto G = jitlink::createLinkGraphFromObject(
-          ObjBuffer, getExecutionSession().getSymbolStringPool())) {
-    emit(std::move(R), std::move(*G), std::move(O));
+  auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
+      *this, std::move(R), std::move(O));
+
+  if (auto G = createLinkGraphFromObject(ObjBuffer)) {
+    // Ctx->notifyMaterializing(**G);
+    link(std::move(*G), std::move(Ctx));
   } else {
-    R->getExecutionSession().reportError(G.takeError());
-    R->failMaterialization();
+    Ctx->notifyFailed(G.takeError());
+  }
+}
+
+void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
+                              std::unique_ptr<LinkGraph> G) {
+  auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
+      *this, std::move(R), nullptr);
+  // Ctx->notifyMaterializing(*G);
+  link(std::move(G), std::move(Ctx));
+}
+
+Error ObjectLinkingLayer::recordFinalizedAlloc(
+    MaterializationResponsibility &MR, FinalizedAlloc FA) {
+  auto Err = MR.withResourceKeyDo(
+      [&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); });
+
+  if (Err)
+    Err = joinErrors(std::move(Err), MemMgr.deallocate(std::move(FA)));
+
+  return Err;
+}
+
+Error ObjectLinkingLayer::handleRemoveResources(JITDylib &JD, ResourceKey K) {
+
+  {
+    Error Err = Error::success();
+    for (auto &P : Plugins)
+      Err = joinErrors(std::move(Err), P->notifyRemovingResources(JD, K));
+    if (Err)
+      return Err;
+  }
+
+  std::vector<FinalizedAlloc> AllocsToRemove;
+  getExecutionSession().runSessionLocked([&] {
+    auto I = Allocs.find(K);
+    if (I != Allocs.end()) {
+      std::swap(AllocsToRemove, I->second);
+      Allocs.erase(I);
+    }
+  });
+
+  if (AllocsToRemove.empty())
+    return Error::success();
+
+  return MemMgr.deallocate(std::move(AllocsToRemove));
+}
+
+void ObjectLinkingLayer::handleTransferResources(JITDylib &JD,
+                                                 ResourceKey DstKey,
+                                                 ResourceKey SrcKey) {
+  auto I = Allocs.find(SrcKey);
+  if (I != Allocs.end()) {
+    auto &SrcAllocs = I->second;
+    auto &DstAllocs = Allocs[DstKey];
+    DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());
+    for (auto &Alloc : SrcAllocs)
+      DstAllocs.push_back(std::move(Alloc));
+
+    // Erase SrcKey entry using value rather than iterator I: I may have been
+    // invalidated when we looked up DstKey.
+    Allocs.erase(SrcKey);
+  }
+
+  for (auto &P : Plugins)
+    P->notifyTransferringResources(JD, DstKey, SrcKey);
+}
+
+EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
+    ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar)
+    : ES(ES), Registrar(std::move(Registrar)) {}
+
+void EHFrameRegistrationPlugin::modifyPassConfig(
+    MaterializationResponsibility &MR, LinkGraph &G,
+    PassConfiguration &PassConfig) {
+
+  PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass(
+      G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) {
+        if (Addr) {
+          std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
+          assert(!InProcessLinks.count(&MR) &&
+                 "Link for MR already being tracked?");
+          InProcessLinks[&MR] = {Addr, Size};
+        }
+      }));
+}
+
+Error EHFrameRegistrationPlugin::notifyEmitted(
+    MaterializationResponsibility &MR) {
+
+  ExecutorAddrRange EmittedRange;
+  {
+    std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
+
+    auto EHFrameRangeItr = InProcessLinks.find(&MR);
+    if (EHFrameRangeItr == InProcessLinks.end())
+      return Error::success();
+
+    EmittedRange = EHFrameRangeItr->second;
+    assert(EmittedRange.Start && "eh-frame addr to register can not be null");
+    InProcessLinks.erase(EHFrameRangeItr);
+  }
+
+  if (auto Err = MR.withResourceKeyDo(
+          [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); }))
+    return Err;
+
+  return Registrar->registerEHFrames(EmittedRange);
+}
+
+Error EHFrameRegistrationPlugin::notifyFailed(
+    MaterializationResponsibility &MR) {
+  std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
+  InProcessLinks.erase(&MR);
+  return Error::success();
+}
+
+Error EHFrameRegistrationPlugin::notifyRemovingResources(JITDylib &JD,
+                                                         ResourceKey K) {
+  std::vector<ExecutorAddrRange> RangesToRemove;
+
+  ES.runSessionLocked([&] {
+    auto I = EHFrameRanges.find(K);
+    if (I != EHFrameRanges.end()) {
+      RangesToRemove = std::move(I->second);
+      EHFrameRanges.erase(I);
+    }
+  });
+
+  Error Err = Error::success();
+  while (!RangesToRemove.empty()) {
+    auto RangeToRemove = RangesToRemove.back();
+    RangesToRemove.pop_back();
+    assert(RangeToRemove.Start && "Untracked eh-frame range must not be null");
+    Err = joinErrors(std::move(Err),
+                     Registrar->deregisterEHFrames(RangeToRemove));
+  }
+
+  return Err;
+}
+
+void EHFrameRegistrationPlugin::notifyTransferringResources(
+    JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) {
+  auto SI = EHFrameRanges.find(SrcKey);
+  if (SI == EHFrameRanges.end())
     return;
   }
 }
 
-} // namespace llvm::orc
+} // namespace llvm::orc
\ No newline at end of file

>From 73dcbf20835718e81c46349fce6a9c70ec0f501c Mon Sep 17 00:00:00 2001
From: Sona Reddy <sonareddy at hotmail.com>
Date: Thu, 7 Aug 2025 22:08:46 +1000
Subject: [PATCH 4/7] elf linkgraph builder cpp

---
 llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.cpp | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.cpp b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.cpp
index e081f47ca42fd..d5caac4aa3da5 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.cpp
@@ -9,25 +9,21 @@
 // Generic ELF LinkGraph building code.
 //
 //===----------------------------------------------------------------------===//
-
 #include "ELFLinkGraphBuilder.h"
-
 #define DEBUG_TYPE "jitlink"
-
 static const char *DWSecNames[] = {
 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
   ELF_NAME,
 #include "llvm/BinaryFormat/Dwarf.def"
 #undef HANDLE_DWARF_SECTION
 };
-
 namespace llvm {
 namespace jitlink {
-
 StringRef ELFLinkGraphBuilderBase::CommonSectionName(".common");
 ArrayRef<const char *> ELFLinkGraphBuilderBase::DwarfSectionNames = DWSecNames;
 
 ELFLinkGraphBuilderBase::~ELFLinkGraphBuilderBase() = default;
 
+
 } // end namespace jitlink
-} // end namespace llvm
+} // end namespace llvm
\ No newline at end of file

>From 871d0ee6ad144c929fa3d5f88d2d2b5c13bced78 Mon Sep 17 00:00:00 2001
From: Sona Reddy <sonareddy at hotmail.com>
Date: Thu, 7 Aug 2025 22:09:18 +1000
Subject: [PATCH 5/7] elf linkgraph builder h

---
 .../lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h
index 8dd176cd07f92..9d4411ff9b7ee 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h
+++ b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h
@@ -42,13 +42,22 @@ class ELFLinkGraphBuilderBase {
     return *CommonSection;
   }
 
+  Section &getOriginalObjectContentSection() {
+    if (!OriginalObjectContentSection)
+      OriginalObjectContentSection = &G->createSection(
+          OriginalObjectContentSectionName, orc::MemProt::Read | orc::MemProt::Write);
+    return *OriginalObjectContentSection;
+  }
+
   std::unique_ptr<LinkGraph> G;
 
 private:
   static StringRef CommonSectionName;
+  static StringRef OriginalObjectContentSectionName;
   static ArrayRef<const char *> DwarfSectionNames;
 
   Section *CommonSection = nullptr;
+  Section *OriginalObjectContentSection = nullptr;
 };
 
 /// LinkGraph building code that's specific to the given ELFT, but common
@@ -696,4 +705,4 @@ Error ELFLinkGraphBuilder<ELFT>::forEachRelRelocation(
 
 #undef DEBUG_TYPE
 
-#endif // LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
+#endif // LIB_EXECUTIONENGINE_JITLINK_ELFLINKGRAPHBUILDER_H
\ No newline at end of file

>From 58e4c7521bce953fc9dddca10692abed33ea4a89 Mon Sep 17 00:00:00 2001
From: Sona Reddy <sonareddy at hotmail.com>
Date: Thu, 7 Aug 2025 22:11:53 +1000
Subject: [PATCH 6/7] updated debug obj manager plugin h include file

---
 .../Orc/DebugObjectManagerPlugin.h            | 55 ++++++-------------
 1 file changed, 17 insertions(+), 38 deletions(-)

diff --git a/llvm/include/llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h b/llvm/include/llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h
index 254b897bca614..20ae0ab96ff21 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h
@@ -15,24 +15,12 @@
 
 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
 #include "llvm/ExecutionEngine/Orc/Core.h"
-#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
-#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
-#include "llvm/Support/Compiler.h"
+#include "llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h"
 #include "llvm/Support/Error.h"
-#include "llvm/Support/Memory.h"
-#include "llvm/Support/MemoryBufferRef.h"
-#include "llvm/TargetParser/Triple.h"
-
-#include <functional>
-#include <map>
-#include <memory>
-#include <mutex>
 
 namespace llvm {
 namespace orc {
 
-class DebugObject;
-
 /// Creates and manages DebugObjects for JITLink artifacts.
 ///
 /// DebugObjects are created when linking for a MaterializationResponsibility
@@ -46,11 +34,10 @@ class DebugObject;
 /// DebugObjectRegistrar is notified. Ownership of DebugObjects remains with the
 /// plugin.
 ///
-class LLVM_ABI DebugObjectManagerPlugin : public ObjectLinkingLayer::Plugin {
+class DebugObjectManagerPlugin : public LinkGraphLinkingLayer::Plugin {
 public:
   // DEPRECATED - Please specify options explicitly
-  DebugObjectManagerPlugin(ExecutionSession &ES,
-                           std::unique_ptr<DebugObjectRegistrar> Target);
+  DebugObjectManagerPlugin(ExecutionSession &ES);
 
   /// Create the plugin to submit DebugObjects for JITLink artifacts. For all
   /// options the recommended setting is true.
@@ -67,42 +54,34 @@ class LLVM_ABI DebugObjectManagerPlugin : public ObjectLinkingLayer::Plugin {
   ///   sequence. When turning this off, the user has to issue the call to
   ///   __jit_debug_register_code() on the executor side manually.
   ///
-  DebugObjectManagerPlugin(ExecutionSession &ES,
-                           std::unique_ptr<DebugObjectRegistrar> Target,
+  DebugObjectManagerPlugin(ExecutorSymbolDef RegisterDebugObject,
+                           ExecutorSymbolDef DeregisterDebugObject,
                            bool RequireDebugSections, bool AutoRegisterCode);
   ~DebugObjectManagerPlugin();
 
-  void notifyMaterializing(MaterializationResponsibility &MR,
-                           jitlink::LinkGraph &G, jitlink::JITLinkContext &Ctx,
-                           MemoryBufferRef InputObject) override;
+  Error fixUpDebugObject(jitlink::LinkGraph &LG);
+
+  Error notifyFailed(MaterializationResponsibility &MR) override {
+    return Error::success();
+  }
 
-  Error notifyEmitted(MaterializationResponsibility &MR) override;
-  Error notifyFailed(MaterializationResponsibility &MR) override;
-  Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override;
+  Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
+    return Error::success();
+  }
 
   void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
-                                   ResourceKey SrcKey) override;
+                                   ResourceKey SrcKey) override {}
 
   void modifyPassConfig(MaterializationResponsibility &MR,
                         jitlink::LinkGraph &LG,
                         jitlink::PassConfiguration &PassConfig) override;
 
 private:
-  ExecutionSession &ES;
-
-  using OwnedDebugObject = std::unique_ptr<DebugObject>;
-  std::map<MaterializationResponsibility *, OwnedDebugObject> PendingObjs;
-  std::map<ResourceKey, std::vector<OwnedDebugObject>> RegisteredObjs;
-
-  std::mutex PendingObjsLock;
-  std::mutex RegisteredObjsLock;
-
-  std::unique_ptr<DebugObjectRegistrar> Target;
-  bool RequireDebugSections;
-  bool AutoRegisterCode;
+  ExecutorSymbolDef RegisterDebugObject;
+  ExecutorSymbolDef DeregisterDebugObject;
 };
 
 } // namespace orc
 } // namespace llvm
 
-#endif // LLVM_EXECUTIONENGINE_ORC_DEBUGOBJECTMANAGERPLUGIN_H
+#endif // LLVM_EXECUTIONENGINE_ORC_DEBUGOBJECTMANAGERPLUGIN_H
\ No newline at end of file

>From 3f25854b1efacbc26d34fe82404e124b30f82a2c Mon Sep 17 00:00:00 2001
From: Sona Reddy <sonareddy at hotmail.com>
Date: Thu, 7 Aug 2025 22:12:38 +1000
Subject: [PATCH 7/7] updated link graph linking layer h include file

---
 .../ExecutionEngine/Orc/LinkGraphLinkingLayer.h  | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h
index d3643f9301134..1fe4ae6ff9102 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h
@@ -19,7 +19,6 @@
 #include "llvm/ExecutionEngine/Orc/Core.h"
 #include "llvm/ExecutionEngine/Orc/Layer.h"
 #include "llvm/ExecutionEngine/Orc/LinkGraphLayer.h"
-#include "llvm/Support/Compiler.h"
 #include "llvm/Support/Error.h"
 #include <algorithm>
 #include <cassert>
@@ -41,28 +40,21 @@ namespace orc {
 ///
 /// Clients can use this class to add LinkGraphs to an ExecutionSession, and it
 /// serves as a base for the ObjectLinkingLayer that can link object files.
-class LLVM_ABI LinkGraphLinkingLayer : public LinkGraphLayer,
-                                       private ResourceManager {
+class LinkGraphLinkingLayer : public LinkGraphLayer, private ResourceManager {
   class JITLinkCtx;
 
 public:
   /// Plugin instances can be added to the ObjectLinkingLayer to receive
   /// callbacks when code is loaded or emitted, and when JITLink is being
   /// configured.
-  class LLVM_ABI Plugin {
+  class Plugin {
   public:
     virtual ~Plugin();
     virtual void modifyPassConfig(MaterializationResponsibility &MR,
                                   jitlink::LinkGraph &G,
                                   jitlink::PassConfiguration &Config) {}
 
-    // Deprecated. Don't use this in new code. There will be a proper mechanism
-    // for capturing object buffers.
-    virtual void notifyMaterializing(MaterializationResponsibility &MR,
-                                     jitlink::LinkGraph &G,
-                                     jitlink::JITLinkContext &Ctx,
-                                     MemoryBufferRef InputObject) {}
-
+    virtual void notifyLoaded(MaterializationResponsibility &MR) {}
     virtual Error notifyEmitted(MaterializationResponsibility &MR) {
       return Error::success();
     }
@@ -177,4 +169,4 @@ class LLVM_ABI LinkGraphLinkingLayer : public LinkGraphLayer,
 } // end namespace orc
 } // end namespace llvm
 
-#endif // LLVM_EXECUTIONENGINE_ORC_LINKGRAPHLINKINGLAYER_H
+#endif // LLVM_EXECUTIONENGINE_ORC_LINKGRAPHLINKINGLAYER_H
\ No newline at end of file



More information about the llvm-commits mailing list