[llvm] [JITLink][XCOFF] Setup initial build support for XCOFF (PR #127266)

Henry Jiang via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 24 21:01:02 PST 2025


https://github.com/mustartt updated https://github.com/llvm/llvm-project/pull/127266

>From f7983454c8687c37304030152228ea9735fbab6a Mon Sep 17 00:00:00 2001
From: Henry Jiang <henry.jiang1 at ibm.com>
Date: Fri, 14 Feb 2025 16:37:25 -0500
Subject: [PATCH 1/5] Setup build support for XCOFF

---
 .../llvm/ExecutionEngine/JITLink/XCOFF.h      | 37 +++++++++++++
 .../ExecutionEngine/JITLink/XCOFF_ppc64.h     | 37 +++++++++++++
 .../ExecutionEngine/JITLink/CMakeLists.txt    |  4 ++
 llvm/lib/ExecutionEngine/JITLink/JITLink.cpp  |  3 ++
 llvm/lib/ExecutionEngine/JITLink/XCOFF.cpp    | 43 +++++++++++++++
 .../ExecutionEngine/JITLink/XCOFF_ppc64.cpp   | 53 +++++++++++++++++++
 .../ExecutionEngine/Orc/LoadLinkableFile.cpp  | 16 ++++++
 7 files changed, 193 insertions(+)
 create mode 100644 llvm/include/llvm/ExecutionEngine/JITLink/XCOFF.h
 create mode 100644 llvm/include/llvm/ExecutionEngine/JITLink/XCOFF_ppc64.h
 create mode 100644 llvm/lib/ExecutionEngine/JITLink/XCOFF.cpp
 create mode 100644 llvm/lib/ExecutionEngine/JITLink/XCOFF_ppc64.cpp

diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/XCOFF.h b/llvm/include/llvm/ExecutionEngine/JITLink/XCOFF.h
new file mode 100644
index 0000000000000..3d181d0786eb7
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/XCOFF.h
@@ -0,0 +1,37 @@
+//===------- XCOFF.h - Generic JIT link function for XCOFF ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// jit-link functions for XCOFF.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_JITLINK_XCOFF_H
+#define LLVM_EXECUTIONENGINE_JITLINK_XCOFF_H
+
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+
+namespace llvm {
+namespace jitlink {
+
+/// Create a LinkGraph from an XCOFF relocatable object.
+///
+/// Note: The graph does not take ownership of the underlying buffer, nor copy
+/// its contents. The caller is responsible for ensuring that the object buffer
+/// outlives the graph.
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromXCOFFObject(MemoryBufferRef ObjectBuffer,
+                               std::shared_ptr<orc::SymbolStringPool> SSP);
+
+/// Link the given graph.
+void link_XCOFF(std::unique_ptr<LinkGraph> G,
+                std::unique_ptr<JITLinkContext> Ctx);
+
+} // namespace jitlink
+} // namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_JITLINK_XCOFF_H
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/XCOFF_ppc64.h b/llvm/include/llvm/ExecutionEngine/JITLink/XCOFF_ppc64.h
new file mode 100644
index 0000000000000..ec5c8a37bda27
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/XCOFF_ppc64.h
@@ -0,0 +1,37 @@
+//===------ XCOFF_ppc64.h - JIT link functions for XCOFF/ppc64 ------*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// jit-link functions for XCOFF/ppc64.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_JITLINK_XCOFF_PPC64_H
+#define LLVM_EXECUTIONENGINE_JITLINK_XCOFF_PPC64_H
+
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+
+namespace llvm::jitlink {
+
+/// Create a LinkGraph from an XCOFF/ppc64 relocatable object.
+///
+/// Note: The graph does not take ownership of the underlying buffer, nor copy
+/// its contents. The caller is responsible for ensuring that the object buffer
+/// outlives the graph.
+///
+Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromXCOFFObject_ppc64(
+    MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP);
+
+/// jit-link the given object buffer, which must be a XCOFF ppc64 object file.
+///
+void link_XCOFF_ppc64(std::unique_ptr<LinkGraph> G,
+                      std::unique_ptr<JITLinkContext> Ctx);
+
+} // end namespace llvm::jitlink
+
+#endif // LLVM_EXECUTIONENGINE_JITLINK_XCOFF_PPC64_H
diff --git a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
index 65dd0c7468ae1..031222f3d8910 100644
--- a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
@@ -35,6 +35,10 @@ add_llvm_component_library(LLVMJITLink
   COFFLinkGraphBuilder.cpp
   COFF_x86_64.cpp
 
+  # XCOFF
+  XCOFF.cpp
+  XCOFF_ppc64.cpp
+
   # Architectures:
   aarch32.cpp
   aarch64.cpp
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
index e8ce9b2b9527d..c68adff8631ee 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
@@ -13,6 +13,7 @@
 #include "llvm/ExecutionEngine/JITLink/COFF.h"
 #include "llvm/ExecutionEngine/JITLink/ELF.h"
 #include "llvm/ExecutionEngine/JITLink/MachO.h"
+#include "llvm/ExecutionEngine/JITLink/XCOFF.h"
 #include "llvm/ExecutionEngine/JITLink/aarch64.h"
 #include "llvm/ExecutionEngine/JITLink/i386.h"
 #include "llvm/ExecutionEngine/JITLink/loongarch.h"
@@ -501,6 +502,8 @@ createLinkGraphFromObject(MemoryBufferRef ObjectBuffer,
     return createLinkGraphFromELFObject(ObjectBuffer, std::move(SSP));
   case file_magic::coff_object:
     return createLinkGraphFromCOFFObject(ObjectBuffer, std::move(SSP));
+  case file_magic::xcoff_object_64:
+    return createLinkGraphFromXCOFFObject(ObjectBuffer, std::move(SSP));
   default:
     return make_error<JITLinkError>("Unsupported file format");
   };
diff --git a/llvm/lib/ExecutionEngine/JITLink/XCOFF.cpp b/llvm/lib/ExecutionEngine/JITLink/XCOFF.cpp
new file mode 100644
index 0000000000000..66b31e33108ca
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/XCOFF.cpp
@@ -0,0 +1,43 @@
+//===-------------- XCOFF.cpp - JIT linker function for XCOFF -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// XCOFF jit-link function.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/JITLink/XCOFF.h"
+#include "llvm/ExecutionEngine/JITLink/XCOFF_ppc64.h"
+#include "llvm/Object/XCOFFObjectFile.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "jitlink"
+
+namespace llvm {
+namespace jitlink {
+
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromXCOFFObject(MemoryBufferRef ObjectBuffer,
+                               std::shared_ptr<orc::SymbolStringPool> SSP) {
+  // Check magic
+  file_magic Magic = identify_magic(ObjectBuffer.getBuffer());
+  if (Magic != file_magic::xcoff_object_64)
+    return make_error<JITLinkError>("Invalid XCOFF 64 Header");
+
+  // TODO: See if we need to add more checks
+  //
+  return createLinkGraphFromXCOFFObject_ppc64(ObjectBuffer, std::move(SSP));
+}
+
+void link_XCOFF(std::unique_ptr<LinkGraph> G,
+                std::unique_ptr<JITLinkContext> Ctx) {
+  llvm_unreachable("Not implmeneted for XCOFF yet");
+}
+
+} // namespace jitlink
+} // namespace llvm
diff --git a/llvm/lib/ExecutionEngine/JITLink/XCOFF_ppc64.cpp b/llvm/lib/ExecutionEngine/JITLink/XCOFF_ppc64.cpp
new file mode 100644
index 0000000000000..81f35ca0a5a2a
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/XCOFF_ppc64.cpp
@@ -0,0 +1,53 @@
+//===------- XCOFF_ppc64.cpp -JIT linker implementation for XCOFF/ppc64
+//-------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// XCOFF/ppc64 jit-link implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/JITLink/XCOFF_ppc64.h"
+#include "llvm/Object/ObjectFile.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "jitlink"
+
+namespace llvm {
+namespace jitlink {
+
+Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromXCOFFObject_ppc64(
+    MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) {
+  LLVM_DEBUG({
+    dbgs() << "Building jitlink graph for new input "
+           << ObjectBuffer.getBufferIdentifier() << "...\n";
+  });
+
+  auto Obj = object::ObjectFile::createObjectFile(ObjectBuffer);
+  if (!Obj)
+    return Obj.takeError();
+  assert((**Obj).isXCOFF() && "Expects and XCOFF Object");
+
+  auto Features = (*Obj)->getFeatures();
+  if (!Features)
+    return Features.takeError();
+  LLVM_DEBUG({
+    dbgs() << " Features: ";
+    (*Features).print(dbgs());
+  });
+
+  llvm_unreachable("Graph builder not implemented for XCOFF yet");
+}
+
+void link_XCOFF_ppc64(std::unique_ptr<LinkGraph> G,
+                      std::unique_ptr<JITLinkContext> Ctx) {
+  llvm_unreachable("Link implemented for XCOFF yet");
+}
+
+} // namespace jitlink
+} // namespace llvm
diff --git a/llvm/lib/ExecutionEngine/Orc/LoadLinkableFile.cpp b/llvm/lib/ExecutionEngine/Orc/LoadLinkableFile.cpp
index 77ae7c7ca2e0e..4f01c01da4b9f 100644
--- a/llvm/lib/ExecutionEngine/Orc/LoadLinkableFile.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LoadLinkableFile.cpp
@@ -25,6 +25,13 @@ checkCOFFRelocatableObject(std::unique_ptr<MemoryBuffer> Obj,
   return std::move(Obj);
 }
 
+static Expected<std::unique_ptr<MemoryBuffer>>
+checkXCOFFRelocatableObject(std::unique_ptr<MemoryBuffer> Obj,
+                            const Triple &TT) {
+  // TODO: Actually check the architecture of the file.
+  return std::move(Obj);
+}
+
 static Expected<std::unique_ptr<MemoryBuffer>>
 checkELFRelocatableObject(std::unique_ptr<MemoryBuffer> Obj, const Triple &TT) {
   // TODO: Actually check the architecture of the file.
@@ -105,6 +112,15 @@ loadLinkableFile(StringRef Path, const Triple &TT, LoadArchives LA,
       return loadLinkableSliceFromMachOUniversalBinary(
           FD, std::move(*Buf), TT, LA, Path, *IdentifierOverride);
     break;
+  case file_magic::xcoff_object_64:
+    if (!RequireFormat || *RequireFormat == Triple::XCOFF) {
+      auto CheckedBuf = checkXCOFFRelocatableObject(std::move(*Buf), TT);
+      if (!CheckedBuf)
+        return CheckedBuf.takeError();
+      return std::make_pair(std::move(*CheckedBuf),
+                            LinkableFileKind::RelocatableObject);
+    }
+    break;
   default:
     break;
   }

>From 9e26f2f2adeed50a0347eff5e12ccff9ddcc6b27 Mon Sep 17 00:00:00 2001
From: Henry Jiang <henry.jiang1 at ibm.com>
Date: Sat, 15 Feb 2025 17:25:03 -0500
Subject: [PATCH 2/5] xcoff jitlink

---
 llvm/include/llvm/ExecutionEngine/Orc/Core.h  |  65 +--
 .../ExecutionEngine/JITLink/CMakeLists.txt    |   1 +
 llvm/lib/ExecutionEngine/JITLink/JITLink.cpp  |   2 +
 llvm/lib/ExecutionEngine/JITLink/XCOFF.cpp    |   2 +-
 .../JITLink/XCOFFLinkGraphBuilder.cpp         | 468 ++++++++++++++++++
 .../JITLink/XCOFFLinkGraphBuilder.h           |  59 +++
 .../ExecutionEngine/JITLink/XCOFF_ppc64.cpp   |  71 ++-
 llvm/lib/ExecutionEngine/Orc/Core.cpp         | 129 ++---
 .../ExecutionEngine/Orc/LinkGraphLayer.cpp    |   3 +
 llvm/lib/Object/XCOFFObjectFile.cpp           |  23 +-
 .../JITLink/ppc64/XCOFF_ppc64.c               |  12 +
 11 files changed, 736 insertions(+), 99 deletions(-)
 create mode 100644 llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.cpp
 create mode 100644 llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.h
 create mode 100644 llvm/test/ExecutionEngine/JITLink/ppc64/XCOFF_ppc64.c

diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/llvm/include/llvm/ExecutionEngine/Orc/Core.h
index cecb4094c9a57..49fd0599c4336 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Core.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h
@@ -308,10 +308,11 @@ class SymbolLookupSet {
   /// If Body returns true then the element just passed in is removed from the
   /// set. If Body returns false then the element is retained.
   template <typename BodyFn>
-  auto forEachWithRemoval(BodyFn &&Body) -> std::enable_if_t<
-      std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
-                                 std::declval<SymbolLookupFlags>())),
-                   bool>::value> {
+  auto forEachWithRemoval(BodyFn &&Body)
+      -> std::enable_if_t<
+          std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
+                                     std::declval<SymbolLookupFlags>())),
+                       bool>::value> {
     UnderlyingVector::size_type I = 0;
     while (I != Symbols.size()) {
       const auto &Name = Symbols[I].first;
@@ -330,11 +331,12 @@ class SymbolLookupSet {
   /// returns true then the element just passed in is removed from the set. If
   /// Body returns false then the element is retained.
   template <typename BodyFn>
-  auto forEachWithRemoval(BodyFn &&Body) -> std::enable_if_t<
-      std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
-                                 std::declval<SymbolLookupFlags>())),
-                   Expected<bool>>::value,
-      Error> {
+  auto forEachWithRemoval(BodyFn &&Body)
+      -> std::enable_if_t<
+          std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
+                                     std::declval<SymbolLookupFlags>())),
+                       Expected<bool>>::value,
+          Error> {
     UnderlyingVector::size_type I = 0;
     while (I != Symbols.size()) {
       const auto &Name = Symbols[I].first;
@@ -525,6 +527,7 @@ class MissingSymbolDefinitions : public ErrorInfo<MissingSymbolDefinitions> {
   std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; }
   const std::string &getModuleName() const { return ModuleName; }
   const SymbolNameVector &getSymbols() const { return Symbols; }
+
 private:
   std::shared_ptr<SymbolStringPool> SSP;
   std::string ModuleName;
@@ -535,7 +538,8 @@ class MissingSymbolDefinitions : public ErrorInfo<MissingSymbolDefinitions> {
 /// symbols that are not claimed by the module's associated
 /// MaterializationResponsibility. If this error is returned it is indicative of
 /// a broken transformation / compiler / object cache.
-class UnexpectedSymbolDefinitions : public ErrorInfo<UnexpectedSymbolDefinitions> {
+class UnexpectedSymbolDefinitions
+    : public ErrorInfo<UnexpectedSymbolDefinitions> {
 public:
   static char ID;
 
@@ -548,6 +552,7 @@ class UnexpectedSymbolDefinitions : public ErrorInfo<UnexpectedSymbolDefinitions
   std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; }
   const std::string &getModuleName() const { return ModuleName; }
   const SymbolNameVector &getSymbols() const { return Symbols; }
+
 private:
   std::shared_ptr<SymbolStringPool> SSP;
   std::string ModuleName;
@@ -693,6 +698,10 @@ class MaterializationResponsibility {
       : JD(RT->getJITDylib()), RT(std::move(RT)),
         SymbolFlags(std::move(SymbolFlags)), InitSymbol(std::move(InitSymbol)) {
     assert(!this->SymbolFlags.empty() && "Materializing nothing?");
+    for (auto &KV : this->SymbolFlags) {
+      dbgs() << "@@@ Init MR " << KV.first << " "
+             << format_hex(KV.second.getRawFlagsValue(), 8) << "\n";
+    }
   }
 
   JITDylib &JD;
@@ -800,7 +809,6 @@ class AsynchronousSymbolQuery {
   ///        resolved.
   bool isComplete() const { return OutstandingSymbolsCount == 0; }
 
-
 private:
   void handleComplete(ExecutionSession &ES);
 
@@ -899,8 +907,8 @@ class JITDylib : public ThreadSafeRefCountedBase<JITDylib>,
   friend class ExecutionSession;
   friend class Platform;
   friend class MaterializationResponsibility;
-public:
 
+public:
   JITDylib(const JITDylib &) = delete;
   JITDylib &operator=(const JITDylib &) = delete;
   JITDylib(JITDylib &&) = delete;
@@ -1104,7 +1112,7 @@ class JITDylib : public ThreadSafeRefCountedBase<JITDylib>,
 
 private:
   using AsynchronousSymbolQuerySet =
-    std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
+      std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
 
   using AsynchronousSymbolQueryList =
       std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
@@ -1160,6 +1168,7 @@ class JITDylib : public ThreadSafeRefCountedBase<JITDylib>,
     const AsynchronousSymbolQueryList &pendingQueries() const {
       return PendingQueries;
     }
+
   private:
     AsynchronousSymbolQueryList PendingQueries;
   };
@@ -1355,13 +1364,13 @@ class ExecutionSession {
   using ErrorReporter = unique_function<void(Error)>;
 
   /// Send a result to the remote.
-  using SendResultFunction = unique_function<void(shared::WrapperFunctionResult)>;
+  using SendResultFunction =
+      unique_function<void(shared::WrapperFunctionResult)>;
 
   /// An asynchronous wrapper-function callable from the executor via
   /// jit-dispatch.
   using JITDispatchHandlerFunction = unique_function<void(
-      SendResultFunction SendResult,
-      const char *ArgData, size_t ArgSize)>;
+      SendResultFunction SendResult, const char *ArgData, size_t ArgSize)>;
 
   /// A map associating tag names with asynchronous wrapper function
   /// implementations in the JIT.
@@ -1589,8 +1598,7 @@ class ExecutionSession {
   /// \endcode{.cpp}
   ///
   /// The given OnComplete function will be called to return the result.
-  template <typename... ArgTs>
-  void callWrapperAsync(ArgTs &&... Args) {
+  template <typename... ArgTs> void callWrapperAsync(ArgTs &&...Args) {
     EPC->callWrapperAsync(std::forward<ArgTs>(Args)...);
   }
 
@@ -1635,9 +1643,9 @@ class ExecutionSession {
   /// (using registerJITDispatchHandler) and called from the executor.
   template <typename SPSSignature, typename HandlerT>
   static JITDispatchHandlerFunction wrapAsyncWithSPS(HandlerT &&H) {
-    return [H = std::forward<HandlerT>(H)](
-               SendResultFunction SendResult,
-               const char *ArgData, size_t ArgSize) mutable {
+    return [H = std::forward<HandlerT>(H)](SendResultFunction SendResult,
+                                           const char *ArgData,
+                                           size_t ArgSize) mutable {
       shared::WrapperFunction<SPSSignature>::handleAsync(ArgData, ArgSize, H,
                                                          std::move(SendResult));
     };
@@ -1742,8 +1750,8 @@ class ExecutionSession {
       unique_function<void(Expected<SymbolFlagsMap>)> OnComplete);
 
   // State machine functions for MaterializationResponsibility.
-  void OL_destroyMaterializationResponsibility(
-      MaterializationResponsibility &MR);
+  void
+  OL_destroyMaterializationResponsibility(MaterializationResponsibility &MR);
   SymbolNameSet OL_getRequestedSymbols(const MaterializationResponsibility &MR);
   Error OL_notifyResolved(MaterializationResponsibility &MR,
                           const SymbolMap &Symbols);
@@ -1965,12 +1973,13 @@ inline MaterializationResponsibility::~MaterializationResponsibility() {
   getExecutionSession().OL_destroyMaterializationResponsibility(*this);
 }
 
-inline SymbolNameSet MaterializationResponsibility::getRequestedSymbols() const {
+inline SymbolNameSet
+MaterializationResponsibility::getRequestedSymbols() const {
   return getExecutionSession().OL_getRequestedSymbols(*this);
 }
 
-inline Error MaterializationResponsibility::notifyResolved(
-    const SymbolMap &Symbols) {
+inline Error
+MaterializationResponsibility::notifyResolved(const SymbolMap &Symbols) {
   return getExecutionSession().OL_notifyResolved(*this, Symbols);
 }
 
@@ -1979,8 +1988,8 @@ inline Error MaterializationResponsibility::notifyEmitted(
   return getExecutionSession().OL_notifyEmitted(*this, EmittedDeps);
 }
 
-inline Error MaterializationResponsibility::defineMaterializing(
-    SymbolFlagsMap SymbolFlags) {
+inline Error
+MaterializationResponsibility::defineMaterializing(SymbolFlagsMap SymbolFlags) {
   return getExecutionSession().OL_defineMaterializing(*this,
                                                       std::move(SymbolFlags));
 }
diff --git a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
index 031222f3d8910..22e4513e1374c 100644
--- a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
@@ -38,6 +38,7 @@ add_llvm_component_library(LLVMJITLink
   # XCOFF
   XCOFF.cpp
   XCOFF_ppc64.cpp
+  XCOFFLinkGraphBuilder.cpp
 
   # Architectures:
   aarch32.cpp
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
index c68adff8631ee..15a8fcf312ade 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
@@ -535,6 +535,8 @@ void link(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx) {
     return link_ELF(std::move(G), std::move(Ctx));
   case Triple::COFF:
     return link_COFF(std::move(G), std::move(Ctx));
+  case Triple::XCOFF:
+    return link_XCOFF(std::move(G), std::move(Ctx));
   default:
     Ctx->notifyFailed(make_error<JITLinkError>("Unsupported object format"));
   };
diff --git a/llvm/lib/ExecutionEngine/JITLink/XCOFF.cpp b/llvm/lib/ExecutionEngine/JITLink/XCOFF.cpp
index 66b31e33108ca..cb026538632a9 100644
--- a/llvm/lib/ExecutionEngine/JITLink/XCOFF.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/XCOFF.cpp
@@ -36,7 +36,7 @@ createLinkGraphFromXCOFFObject(MemoryBufferRef ObjectBuffer,
 
 void link_XCOFF(std::unique_ptr<LinkGraph> G,
                 std::unique_ptr<JITLinkContext> Ctx) {
-  llvm_unreachable("Not implmeneted for XCOFF yet");
+  link_XCOFF_ppc64(std::move(G), std::move(Ctx));
 }
 
 } // namespace jitlink
diff --git a/llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.cpp b/llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.cpp
new file mode 100644
index 0000000000000..298284c82b18f
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.cpp
@@ -0,0 +1,468 @@
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Generic XCOFF LinkGraph building code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "XCOFFLinkGraphBuilder.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/BinaryFormat/XCOFF.h"
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/ExecutionEngine/JITLink/ppc64.h"
+#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
+#include "llvm/ExecutionEngine/Orc/Shared/MemoryFlags.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/XCOFFObjectFile.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <memory>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "jitlink"
+
+namespace llvm {
+namespace jitlink {
+
+XCOFFLinkGraphBuilder::XCOFFLinkGraphBuilder(
+    const object::XCOFFObjectFile &Obj,
+    std::shared_ptr<orc::SymbolStringPool> SSP, Triple TT,
+    SubtargetFeatures Features,
+    LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
+    : Obj(Obj),
+      G(std::make_unique<LinkGraph>(
+          std::string(Obj.getFileName()), std::move(SSP), std::move(TT),
+          std::move(Features), std::move(GetEdgeKindName))) {}
+
+static llvm::raw_ostream &debugStorageClass(llvm::raw_ostream &OS,
+                                            XCOFF::StorageClass SC) {
+  switch (SC) {
+    // Debug symbols
+  case XCOFF::StorageClass::C_FILE:
+    OS << "C_FILE (File name)";
+    break;
+  case XCOFF::StorageClass::C_BINCL:
+    OS << "C_BINCL (Beginning of include file)";
+    break;
+  case XCOFF::StorageClass::C_EINCL:
+    OS << "C_EINCL (Ending of include file)";
+    break;
+  case XCOFF::StorageClass::C_GSYM:
+    OS << "C_GSYM (Global variable)";
+    break;
+  case XCOFF::StorageClass::C_STSYM:
+    OS << "C_STSYM (Statically allocated symbol)";
+    break;
+  case XCOFF::StorageClass::C_BCOMM:
+    OS << "C_BCOMM (Beginning of common block)";
+    break;
+  case XCOFF::StorageClass::C_ECOMM:
+    OS << "C_ECOMM (End of common block)";
+    break;
+  case XCOFF::StorageClass::C_ENTRY:
+    OS << "C_ENTRY (Alternate entry)";
+    break;
+  case XCOFF::StorageClass::C_BSTAT:
+    OS << "C_BSTAT (Beginning of static block)";
+    break;
+  case XCOFF::StorageClass::C_ESTAT:
+    OS << "C_ESTAT (End of static block)";
+    break;
+  case XCOFF::StorageClass::C_GTLS:
+    OS << "C_GTLS (Global thread-local variable)";
+    break;
+  case XCOFF::StorageClass::C_STTLS:
+    OS << "C_STTLS (Static thread-local variable)";
+    break;
+
+    // DWARF symbols
+  case XCOFF::StorageClass::C_DWARF:
+    OS << "C_DWARF (DWARF section symbol)";
+    break;
+
+    // Absolute symbols
+  case XCOFF::StorageClass::C_LSYM:
+    OS << "C_LSYM (Automatic variable allocated on stack)";
+    break;
+  case XCOFF::StorageClass::C_PSYM:
+    OS << "C_PSYM (Argument to subroutine allocated on stack)";
+    break;
+  case XCOFF::StorageClass::C_RSYM:
+    OS << "C_RSYM (Register variable)";
+    break;
+  case XCOFF::StorageClass::C_RPSYM:
+    OS << "C_RPSYM (Argument to function stored in register)";
+    break;
+  case XCOFF::StorageClass::C_ECOML:
+    OS << "C_ECOML (Local member of common block)";
+    break;
+  case XCOFF::StorageClass::C_FUN:
+    OS << "C_FUN (Function or procedure)";
+    break;
+
+    // External symbols
+  case XCOFF::StorageClass::C_EXT:
+    OS << "C_EXT (External symbol)";
+    break;
+  case XCOFF::StorageClass::C_WEAKEXT:
+    OS << "C_WEAKEXT (Weak external symbol)";
+    break;
+
+    // General sections
+  case XCOFF::StorageClass::C_NULL:
+    OS << "C_NULL";
+    break;
+  case XCOFF::StorageClass::C_STAT:
+    OS << "C_STAT (Static)";
+    break;
+  case XCOFF::StorageClass::C_BLOCK:
+    OS << "C_BLOCK (\".bb\" or \".eb\")";
+    break;
+  case XCOFF::StorageClass::C_FCN:
+    OS << "C_FCN (\".bf\" or \".ef\")";
+    break;
+  case XCOFF::StorageClass::C_HIDEXT:
+    OS << "C_HIDEXT (Un-named external symbol)";
+    break;
+  case XCOFF::StorageClass::C_INFO:
+    OS << "C_INFO (Comment string in .info section)";
+    break;
+  case XCOFF::StorageClass::C_DECL:
+    OS << "C_DECL (Declaration of object)";
+    break;
+
+    // Obsolete/Undocumented
+  case XCOFF::StorageClass::C_AUTO:
+    OS << "C_AUTO (Automatic variable)";
+    break;
+  case XCOFF::StorageClass::C_REG:
+    OS << "C_REG (Register variable)";
+    break;
+  case XCOFF::StorageClass::C_EXTDEF:
+    OS << "C_EXTDEF (External definition)";
+    break;
+  case XCOFF::StorageClass::C_LABEL:
+    OS << "C_LABEL (Label)";
+    break;
+  case XCOFF::StorageClass::C_ULABEL:
+    OS << "C_ULABEL (Undefined label)";
+    break;
+  case XCOFF::StorageClass::C_MOS:
+    OS << "C_MOS (Member of structure)";
+    break;
+  case XCOFF::StorageClass::C_ARG:
+    OS << "C_ARG (Function argument)";
+    break;
+  case XCOFF::StorageClass::C_STRTAG:
+    OS << "C_STRTAG (Structure tag)";
+    break;
+  case XCOFF::StorageClass::C_MOU:
+    OS << "C_MOU (Member of union)";
+    break;
+  case XCOFF::StorageClass::C_UNTAG:
+    OS << "C_UNTAG (Union tag)";
+    break;
+  case XCOFF::StorageClass::C_TPDEF:
+    OS << "C_TPDEF (Type definition)";
+    break;
+  case XCOFF::StorageClass::C_USTATIC:
+    OS << "C_USTATIC (Undefined static)";
+    break;
+  case XCOFF::StorageClass::C_ENTAG:
+    OS << "C_ENTAG (Enumeration tag)";
+    break;
+  case XCOFF::StorageClass::C_MOE:
+    OS << "C_MOE (Member of enumeration)";
+    break;
+  case XCOFF::StorageClass::C_REGPARM:
+    OS << "C_REGPARM (Register parameter)";
+    break;
+  case XCOFF::StorageClass::C_FIELD:
+    OS << "C_FIELD (Bit field)";
+    break;
+  case XCOFF::StorageClass::C_EOS:
+    OS << "C_EOS (End of structure)";
+    break;
+  case XCOFF::StorageClass::C_LINE:
+    OS << "C_LINE";
+    break;
+  case XCOFF::StorageClass::C_ALIAS:
+    OS << "C_ALIAS (Duplicate tag)";
+    break;
+  case XCOFF::StorageClass::C_HIDDEN:
+    OS << "C_HIDDEN (Special storage class for external)";
+    break;
+  case XCOFF::StorageClass::C_EFCN:
+    OS << "C_EFCN (Physical end of function)";
+    break;
+
+    // Reserved
+  case XCOFF::StorageClass::C_TCSYM:
+    OS << "C_TCSYM (Reserved)";
+    break;
+  }
+  return OS;
+}
+
+Error XCOFFLinkGraphBuilder::processSections() {
+  LLVM_DEBUG(dbgs() << "  Creating graph sections...\n");
+
+  // Create undefined section to contain all external symbols
+  UndefSection = &G->createSection("*UND*", orc::MemProt::None);
+
+  for (auto Section : Obj.sections()) {
+    LLVM_DEBUG({
+      dbgs() << "    section = " << cantFail(Section.getName())
+             << ", idx = " << Section.getIndex()
+             << ", size = " << format_hex_no_prefix(Section.getSize(), 8)
+             << ", vma = " << format_hex(Section.getAddress(), 16) << "\n";
+    });
+
+    // We can skip debug (including dawrf) and pad sections
+    if (Section.isDebugSection() || cantFail(Section.getName()) == "pad") {
+      LLVM_DEBUG(dbgs() << "      skipping...\n");
+      continue;
+    }
+
+    auto SectionName = cantFail(Section.getName());
+    LLVM_DEBUG(dbgs() << "        creating graph section...\n");
+
+    orc::MemProt Prot = orc::MemProt::Read;
+    if (Section.isText())
+      Prot |= orc::MemProt::Exec;
+    if (Section.isData() || Section.isBSS())
+      Prot |= orc::MemProt::Write;
+
+    auto *GraphSec = &G->createSection(SectionName, Prot);
+    // TODO(HJ): Check for memory lifetime no alloc for certain sections
+
+    SectionDataMap[Section.getIndex()] = Section;
+    SectionMap[Section.getIndex()] = GraphSec;
+  }
+
+  return Error::success();
+}
+
+static std::optional<object::XCOFFSymbolRef>
+getXCOFFSymbolContainingSymbolRef(const object::XCOFFObjectFile &Obj,
+                                  const object::SymbolRef &Sym) {
+  const object::XCOFFSymbolRef SymRef =
+      Obj.toSymbolRef(Sym.getRawDataRefImpl());
+  if (!SymRef.isCsectSymbol())
+    return std::nullopt;
+
+  Expected<object::XCOFFCsectAuxRef> CsectAuxEntOrErr =
+      SymRef.getXCOFFCsectAuxRef();
+  if (!CsectAuxEntOrErr || !CsectAuxEntOrErr.get().isLabel())
+    return std::nullopt;
+  uint32_t Idx =
+      static_cast<uint32_t>(CsectAuxEntOrErr.get().getSectionOrLength());
+  object::DataRefImpl DRI;
+  DRI.p = Obj.getSymbolByIndex(Idx);
+  return object::XCOFFSymbolRef(DRI, &Obj);
+}
+
+static void printSymbolEntry(raw_ostream &OS,
+                             const object::XCOFFObjectFile &Obj,
+                             const object::XCOFFSymbolRef &Sym) {
+  OS << "    " << format_hex(cantFail(Sym.getAddress()), 16);
+  OS << " " << left_justify(cantFail(Sym.getName()), 10);
+  if (Sym.isCsectSymbol()) {
+    auto CsectAuxEntry = cantFail(Sym.getXCOFFCsectAuxRef());
+    if (!CsectAuxEntry.isLabel()) {
+      std::string MCStr =
+          "[" +
+          XCOFF::getMappingClassString(CsectAuxEntry.getStorageMappingClass())
+              .str() +
+          "]";
+      OS << left_justify(MCStr, 3);
+    }
+  }
+  OS << " " << format_hex(Sym.getSize(), 8);
+  OS << " " << Sym.getSectionNumber();
+  OS << " ";
+  debugStorageClass(dbgs(), Sym.getStorageClass());
+  OS << " (idx: " << Obj.getSymbolIndex(Sym.getRawDataRefImpl().p) << ")";
+  if (Sym.isCsectSymbol()) {
+    if (auto ParentSym = getXCOFFSymbolContainingSymbolRef(Obj, Sym)) {
+      OS << " (csect idx: "
+         << Obj.getSymbolIndex(ParentSym->getRawDataRefImpl().p) << ")";
+    }
+  }
+  OS << "\n";
+}
+
+Error XCOFFLinkGraphBuilder::processCsectsAndSymbols() {
+  LLVM_DEBUG(dbgs() << "  Creating graph blocks and symbols...\n");
+
+  for (auto [K, V] : SectionMap) {
+    LLVM_DEBUG(dbgs() << "    section entry(idx: " << K
+                      << " section: " << V->getName() << ")\n");
+  }
+
+  for (object::XCOFFSymbolRef Symbol : Obj.symbols()) {
+    LLVM_DEBUG({ printSymbolEntry(dbgs(), Obj, Symbol); });
+
+    auto Flags = cantFail(Symbol.getFlags());
+    bool External = Flags & object::SymbolRef::SF_Undefined;
+    bool Weak = Flags & object::SymbolRef::SF_Weak;
+    bool Hidden = Flags & object::SymbolRef::SF_Hidden;
+    bool Global = Flags & object::SymbolRef::SF_Global;
+    // bool Exported = Flags & object::SymbolRef::SF_Exported;
+    // bool Absolute = Flags & object::SymbolRef::SF_Absolute;
+
+    auto SymbolIndex = Obj.getSymbolIndex(Symbol.getEntryAddress());
+
+    if (External) {
+      LLVM_DEBUG(dbgs() << "      created external symbol\n");
+      SymbolIdxMap[SymbolIndex] = &G->addExternalSymbol(
+          cantFail(Symbol.getName()), Symbol.getSize(), Weak);
+      continue;
+    }
+
+    if (!Symbol.isCsectSymbol()) {
+      LLVM_DEBUG(dbgs() << "      skipped: not a csect symbol\n");
+      continue;
+    }
+
+    auto ParentSym = getXCOFFSymbolContainingSymbolRef(Obj, Symbol);
+    object::XCOFFSymbolRef CsectSymbol = ParentSym ? *ParentSym : Symbol;
+
+    auto CsectSymbolIndex = Obj.getSymbolIndex(CsectSymbol.getEntryAddress());
+    auto ParentSectionNumber = CsectSymbol.getSectionNumber();
+
+    bool IsUndefinedSection = !SectionMap.contains(ParentSectionNumber);
+    Section *ParentSection =
+        !IsUndefinedSection ? SectionMap[ParentSectionNumber] : UndefSection;
+    Block *B = nullptr;
+
+    if (!CsectMap.contains(CsectSymbolIndex) && !IsUndefinedSection) {
+      auto SectionRef = SectionDataMap[ParentSectionNumber];
+      auto Data = SectionRef.getContents();
+      if (!Data)
+        return Data.takeError();
+      ArrayRef<char> SectionBuffer{Data->data(), Data->size()};
+      auto Offset =
+          cantFail(CsectSymbol.getAddress()) - SectionRef.getAddress();
+
+      LLVM_DEBUG({
+        dbgs() << "      symbol entry: offset = " << Offset
+               << ", size = " << CsectSymbol.getSize() << ", storage class = ";
+        debugStorageClass(dbgs(), CsectSymbol.getStorageClass()) << "\n";
+      });
+
+      B = &G->createContentBlock(
+          *ParentSection, SectionBuffer.slice(Offset, CsectSymbol.getSize()),
+          orc::ExecutorAddr(cantFail(CsectSymbol.getAddress())),
+          CsectSymbol.getAlignment(), 0);
+
+      CsectMap[CsectSymbolIndex] = B;
+    } else {
+      B = CsectMap[CsectSymbolIndex];
+    }
+
+    Scope S{Scope::Default};
+    if (Hidden)
+      S = Scope::Hidden;
+    // TODO(HJ): Got this from llvm-objdump.cpp:2938 not sure if its correct
+    if (!Weak) {
+      if (Global)
+        S = Scope::Default;
+      else
+        S = Scope::Local;
+    }
+
+    // TODO(HJ): not sure what is Scope::SideEffectsOnly
+    Linkage L = Weak ? Linkage::Weak : Linkage::Strong;
+    auto BlockOffset =
+        cantFail(Symbol.getAddress()) - B->getAddress().getValue();
+
+    LLVM_DEBUG(dbgs() << "      creating with linkage = " << getLinkageName(L)
+                      << ", scope = " << getScopeName(S) << ", B = "
+                      << format_hex(B->getAddress().getValue(), 16) << "\n");
+
+    SymbolIdxMap[SymbolIndex] = &G->addDefinedSymbol(
+        *B, BlockOffset, cantFail(Symbol.getName()), Symbol.getSize(), L, S,
+        cantFail(Symbol.isFunction()), true);
+  }
+
+  return Error::success();
+}
+
+Error XCOFFLinkGraphBuilder::processRelocations() {
+  LLVM_DEBUG(dbgs() << "  Creating relocations...\n");
+
+  for (object::SectionRef Section : Obj.sections()) {
+
+    LLVM_DEBUG(dbgs() << "    Relocations for section "
+                      << cantFail(Section.getName()) << ":\n");
+    for (object::RelocationRef Relocation : Section.relocations()) {
+      SmallString<16> RelocName;
+      Relocation.getTypeName(RelocName);
+      object::SymbolRef Symbol = *Relocation.getSymbol();
+      StringRef TargetSymbol = cantFail(Symbol.getName());
+      auto SymbolIndex = Obj.getSymbolIndex(Symbol.getRawDataRefImpl().p);
+
+      LLVM_DEBUG(dbgs() << "      " << format_hex(Relocation.getOffset(), 16)
+                        << " (idx: " << SymbolIndex << ")"
+                        << " " << RelocName << " " << TargetSymbol << "\n";);
+
+      assert(SymbolIdxMap.contains(SymbolIndex) &&
+             "Relocation needs a record in the symbol table");
+      auto *S = SymbolIdxMap[SymbolIndex];
+      auto It = find_if(G->blocks(),
+                        [Target = orc::ExecutorAddr(Section.getAddress() +
+                                                    Relocation.getOffset())](
+                            const Block *B) -> bool {
+                          return B->getRange().contains(Target);
+                        });
+      assert(It != G->blocks().end() &&
+             "Cannot find the target relocation block");
+      Block *B = *It;
+      LLVM_DEBUG(dbgs() << "        found target relocation block: "
+                        << format_hex(B->getAddress().getValue(), 16) << "\n");
+
+      // TODO(HJ): correctly map edge kind and figure out if we need addend
+      auto TargetBlockOffset = Section.getAddress() + Relocation.getOffset() -
+                               B->getAddress().getValue();
+      switch (Relocation.getType()) {
+      case XCOFF::R_POS:
+        B->addEdge(ppc64::EdgeKind_ppc64::Pointer64, TargetBlockOffset, *S, 0);
+        break;
+      default:
+        SmallString<16> RelocType;
+        Relocation.getTypeName(RelocType);
+        return make_error<StringError>(
+            "Unsupported Relocation Type: " + RelocType, std::error_code());
+      }
+    }
+  }
+
+  return Error::success();
+}
+
+Expected<std::unique_ptr<LinkGraph>> XCOFFLinkGraphBuilder::buildGraph() {
+  LLVM_DEBUG(dbgs() << "Building XCOFFLinkGraph...\n");
+
+  // TODO(HJ): Check for for relocation
+  // if (Obj.isRelocatableObject())
+  //   return make_error<JITLinkError>("XCOFF object is not relocatable");
+
+  if (auto Err = processSections())
+    return Err;
+  if (auto Err = processCsectsAndSymbols())
+    return Err;
+  if (auto Err = processRelocations())
+    return Err;
+
+  return std::move(G);
+}
+
+} // namespace jitlink
+} // namespace llvm
diff --git a/llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.h
new file mode 100644
index 0000000000000..a2bbd6ce99f3c
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.h
@@ -0,0 +1,59 @@
+//===----- XCOFFLinkGraphBuilder.h - XCOFF LinkGraph builder ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Generic XCOFF LinkGraph building code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LIB_EXECUTIONENGINE_JITLINK_XCOFFLINKGRAPHBUILDER_H
+#define LIB_EXECUTIONENGINE_JITLINK_XCOFFLINKGRAPHBUILDER_H
+
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/XCOFFObjectFile.h"
+#include "llvm/TargetParser/SubtargetFeature.h"
+#include <memory>
+
+namespace llvm {
+namespace jitlink {
+
+class XCOFFLinkGraphBuilder {
+public:
+  virtual ~XCOFFLinkGraphBuilder() = default;
+  Expected<std::unique_ptr<LinkGraph>> buildGraph();
+
+public:
+  XCOFFLinkGraphBuilder(const object::XCOFFObjectFile &Obj,
+                        std::shared_ptr<orc::SymbolStringPool> SSP, Triple TT,
+                        SubtargetFeatures Features,
+                        LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
+  LinkGraph &getGraph() const { return *G; }
+  const object::XCOFFObjectFile &getObject() const { return Obj; }
+
+private:
+  Error processSections();
+  Error processCsectsAndSymbols();
+  Error processRelocations();
+
+private:
+  const object::XCOFFObjectFile &Obj;
+  std::unique_ptr<LinkGraph> G;
+
+  Section* UndefSection;
+
+  DenseMap<uint16_t, Section *> SectionMap;
+  DenseMap<uint16_t, object::SectionRef> SectionDataMap;
+  DenseMap<uint32_t, Block *> CsectMap;
+  DenseMap<uint32_t, Symbol *> SymbolIdxMap;
+};
+
+} // namespace jitlink
+} // namespace llvm
+
+#endif // LIB_EXECUTIONENGINE_JITLINK_XCOFFLINKGRAPHBUILDER_H
diff --git a/llvm/lib/ExecutionEngine/JITLink/XCOFF_ppc64.cpp b/llvm/lib/ExecutionEngine/JITLink/XCOFF_ppc64.cpp
index 81f35ca0a5a2a..22aa6c020416e 100644
--- a/llvm/lib/ExecutionEngine/JITLink/XCOFF_ppc64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/XCOFF_ppc64.cpp
@@ -12,7 +12,16 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ExecutionEngine/JITLink/XCOFF_ppc64.h"
+#include "JITLinkGeneric.h"
+#include "XCOFFLinkGraphBuilder.h"
+#include "llvm/ADT/bit.h"
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/ExecutionEngine/JITLink/ppc64.h"
 #include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/XCOFFObjectFile.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <system_error>
 
 using namespace llvm;
 
@@ -41,12 +50,70 @@ Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromXCOFFObject_ppc64(
     (*Features).print(dbgs());
   });
 
-  llvm_unreachable("Graph builder not implemented for XCOFF yet");
+  return XCOFFLinkGraphBuilder(cast<object::XCOFFObjectFile>(**Obj),
+                               std::move(SSP), Triple("powerpc64-ibm-aix"),
+                               std::move(*Features), ppc64::getEdgeKindName)
+      .buildGraph();
 }
 
+class XCOFFJITLinker_ppc64 : public JITLinker<XCOFFJITLinker_ppc64> {
+  using JITLinkerBase = JITLinker<XCOFFJITLinker_ppc64>;
+  friend JITLinkerBase;
+
+public:
+  XCOFFJITLinker_ppc64(std::unique_ptr<JITLinkContext> Ctx,
+                       std::unique_ptr<LinkGraph> G,
+                       PassConfiguration PassConfig)
+      : JITLinkerBase(std::move(Ctx), std::move(G), std::move(PassConfig)) {
+    // Post allocation pass define TOC base
+    defineTOCSymbol(getGraph());
+  }
+
+  Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
+    LLVM_DEBUG(dbgs() << "  Applying fixup for " << G.getName()
+                      << ", address = " << B.getAddress()
+                      << ", target = " << E.getTarget().getName() << ", kind = "
+                      << ppc64::getEdgeKindName(E.getKind()) << "\n");
+    switch (E.getKind()) {
+    case ppc64::Pointer64:
+      if (auto Err = ppc64::applyFixup<endianness::big>(G, B, E, TOCSymbol))
+        return Err;
+      break;
+    default:
+      return make_error<StringError>("Unsupported relocation type",
+                                     std::error_code());
+    }
+    return Error::success();
+  }
+
+private:
+  void defineTOCSymbol(LinkGraph &G) {
+    for (Symbol *S : G.defined_symbols()) {
+      if (S->hasName() && *S->getName() == StringRef("TOC")) {
+        TOCSymbol = S;
+        return;
+      }
+    }
+    llvm_unreachable("LinkGraph does not contan an TOC Symbol");
+  }
+
+private:
+  Symbol *TOCSymbol = nullptr;
+};
+
 void link_XCOFF_ppc64(std::unique_ptr<LinkGraph> G,
                       std::unique_ptr<JITLinkContext> Ctx) {
-  llvm_unreachable("Link implemented for XCOFF yet");
+  // Ctx->notifyFailed(make_error<StringError>(
+  //     "link_XCOFF_ppc64 is not implemented", std::error_code()));
+
+  PassConfiguration Config;
+
+  // Pass insertions
+
+  if (auto Err = Ctx->modifyPassConfig(*G, Config))
+    return Ctx->notifyFailed(std::move(Err));
+
+  XCOFFJITLinker_ppc64::link(std::move(Ctx), std::move(G), std::move(Config));
 }
 
 } // namespace jitlink
diff --git a/llvm/lib/ExecutionEngine/Orc/Core.cpp b/llvm/lib/ExecutionEngine/Orc/Core.cpp
index 9f466e725668a..5d9915ba7cfc9 100644
--- a/llvm/lib/ExecutionEngine/Orc/Core.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Core.cpp
@@ -12,6 +12,7 @@
 #include "llvm/Config/llvm-config.h"
 #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
 #include "llvm/ExecutionEngine/Orc/Shared/OrcError.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/MSVCErrorWorkarounds.h"
 #include "llvm/Support/raw_ostream.h"
@@ -165,8 +166,7 @@ std::error_code MissingSymbolDefinitions::convertToErrorCode() const {
 }
 
 void MissingSymbolDefinitions::log(raw_ostream &OS) const {
-  OS << "Missing definitions in module " << ModuleName
-     << ": " << Symbols;
+  OS << "Missing definitions in module " << ModuleName << ": " << Symbols;
 }
 
 std::error_code UnexpectedSymbolDefinitions::convertToErrorCode() const {
@@ -174,8 +174,7 @@ std::error_code UnexpectedSymbolDefinitions::convertToErrorCode() const {
 }
 
 void UnexpectedSymbolDefinitions::log(raw_ostream &OS) const {
-  OS << "Unexpected definitions in module " << ModuleName
-     << ": " << Symbols;
+  OS << "Unexpected definitions in module " << ModuleName << ": " << Symbols;
 }
 
 void SymbolInstance::lookupAsync(LookupAsyncOnCompleteFn OnComplete) const {
@@ -740,7 +739,7 @@ JITDylib::defineMaterializing(MaterializationResponsibility &FromMR,
         continue;
       } else
         EntryItr =
-          Symbols.insert(std::make_pair(Name, SymbolTableEntry(Flags))).first;
+            Symbols.insert(std::make_pair(Name, SymbolTableEntry(Flags))).first;
 
       AddedSyms.push_back(NonOwningSymbolStringPtr(Name));
       EntryItr->second.setState(SymbolState::Materializing);
@@ -762,63 +761,62 @@ Error JITDylib::replace(MaterializationResponsibility &FromMR,
   std::unique_ptr<MaterializationUnit> MustRunMU;
   std::unique_ptr<MaterializationResponsibility> MustRunMR;
 
-  auto Err =
-      ES.runSessionLocked([&, this]() -> Error {
-        if (FromMR.RT->isDefunct())
-          return make_error<ResourceTrackerDefunct>(std::move(FromMR.RT));
+  auto Err = ES.runSessionLocked([&, this]() -> Error {
+    if (FromMR.RT->isDefunct())
+      return make_error<ResourceTrackerDefunct>(std::move(FromMR.RT));
 
 #ifndef NDEBUG
-        for (auto &KV : MU->getSymbols()) {
-          auto SymI = Symbols.find(KV.first);
-          assert(SymI != Symbols.end() && "Replacing unknown symbol");
-          assert(SymI->second.getState() == SymbolState::Materializing &&
-                 "Can not replace a symbol that ha is not materializing");
-          assert(!SymI->second.hasMaterializerAttached() &&
-                 "Symbol should not have materializer attached already");
-          assert(UnmaterializedInfos.count(KV.first) == 0 &&
-                 "Symbol being replaced should have no UnmaterializedInfo");
-        }
+    for (auto &KV : MU->getSymbols()) {
+      auto SymI = Symbols.find(KV.first);
+      assert(SymI != Symbols.end() && "Replacing unknown symbol");
+      assert(SymI->second.getState() == SymbolState::Materializing &&
+             "Can not replace a symbol that ha is not materializing");
+      assert(!SymI->second.hasMaterializerAttached() &&
+             "Symbol should not have materializer attached already");
+      assert(UnmaterializedInfos.count(KV.first) == 0 &&
+             "Symbol being replaced should have no UnmaterializedInfo");
+    }
 #endif // NDEBUG
 
-        // If the tracker is defunct we need to bail out immediately.
-
-        // If any symbol has pending queries against it then we need to
-        // materialize MU immediately.
-        for (auto &KV : MU->getSymbols()) {
-          auto MII = MaterializingInfos.find(KV.first);
-          if (MII != MaterializingInfos.end()) {
-            if (MII->second.hasQueriesPending()) {
-              MustRunMR = ES.createMaterializationResponsibility(
-                  *FromMR.RT, std::move(MU->SymbolFlags),
-                  std::move(MU->InitSymbol));
-              MustRunMU = std::move(MU);
-              return Error::success();
-            }
-          }
+    // If the tracker is defunct we need to bail out immediately.
+
+    // If any symbol has pending queries against it then we need to
+    // materialize MU immediately.
+    for (auto &KV : MU->getSymbols()) {
+      auto MII = MaterializingInfos.find(KV.first);
+      if (MII != MaterializingInfos.end()) {
+        if (MII->second.hasQueriesPending()) {
+          MustRunMR = ES.createMaterializationResponsibility(
+              *FromMR.RT, std::move(MU->SymbolFlags),
+              std::move(MU->InitSymbol));
+          MustRunMU = std::move(MU);
+          return Error::success();
         }
+      }
+    }
 
-        // Otherwise, make MU responsible for all the symbols.
-        auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU),
-                                                        FromMR.RT.get());
-        for (auto &KV : UMI->MU->getSymbols()) {
-          auto SymI = Symbols.find(KV.first);
-          assert(SymI->second.getState() == SymbolState::Materializing &&
-                 "Can not replace a symbol that is not materializing");
-          assert(!SymI->second.hasMaterializerAttached() &&
-                 "Can not replace a symbol that has a materializer attached");
-          assert(UnmaterializedInfos.count(KV.first) == 0 &&
-                 "Unexpected materializer entry in map");
-          SymI->second.setAddress(SymI->second.getAddress());
-          SymI->second.setMaterializerAttached(true);
-
-          auto &UMIEntry = UnmaterializedInfos[KV.first];
-          assert((!UMIEntry || !UMIEntry->MU) &&
-                 "Replacing symbol with materializer still attached");
-          UMIEntry = UMI;
-        }
+    // Otherwise, make MU responsible for all the symbols.
+    auto UMI =
+        std::make_shared<UnmaterializedInfo>(std::move(MU), FromMR.RT.get());
+    for (auto &KV : UMI->MU->getSymbols()) {
+      auto SymI = Symbols.find(KV.first);
+      assert(SymI->second.getState() == SymbolState::Materializing &&
+             "Can not replace a symbol that is not materializing");
+      assert(!SymI->second.hasMaterializerAttached() &&
+             "Can not replace a symbol that has a materializer attached");
+      assert(UnmaterializedInfos.count(KV.first) == 0 &&
+             "Unexpected materializer entry in map");
+      SymI->second.setAddress(SymI->second.getAddress());
+      SymI->second.setMaterializerAttached(true);
+
+      auto &UMIEntry = UnmaterializedInfos[KV.first];
+      assert((!UMIEntry || !UMIEntry->MU) &&
+             "Replacing symbol with materializer still attached");
+      UMIEntry = UMI;
+    }
 
-        return Error::success();
-      });
+    return Error::success();
+  });
 
   if (Err)
     return Err;
@@ -922,9 +920,12 @@ Error JITDylib::resolve(MaterializationResponsibility &MR,
                          (SymI->second.getFlags() & ~JITSymbolFlags::Common) &&
                      "Resolving symbol with incorrect flags");
 
-            } else
+            } else {
+              /*
               assert(KV.second.getFlags() == SymI->second.getFlags() &&
                      "Resolved flags should match the declared flags");
+                     */
+            }
 
             Worklist.push_back(
                 {SymI, {KV.second.getAddress(), SymI->second.getFlags()}});
@@ -2055,7 +2056,8 @@ bool ExecutionSession::verifySessionState(Twine Phase) {
           // Pending queries should be for subsequent states.
           auto CurState = static_cast<SymbolState>(
               static_cast<std::underlying_type_t<SymbolState>>(
-                  SymItr->second.getState()) + 1);
+                  SymItr->second.getState()) +
+              1);
           for (auto &Q : MII.PendingQueries) {
             if (Q->getRequiredState() != CurState) {
               if (Q->getRequiredState() > CurState)
@@ -2899,6 +2901,14 @@ Error ExecutionSession::OL_notifyResolved(MaterializationResponsibility &MR,
 #ifndef NDEBUG
   for (auto &KV : Symbols) {
     auto I = MR.SymbolFlags.find(KV.first);
+
+    LLVM_DEBUG(dbgs() << "  Flags for " << KV.first << ": "
+                      << formatv("expected {0:x}", I->second.getRawFlagsValue())
+                      << " "
+                      << formatv("found {0:x}",
+                                 KV.second.getFlags().getRawFlagsValue())
+                      << "\n");
+
     assert(I != MR.SymbolFlags.end() &&
            "Resolving symbol outside this responsibility set");
     assert(!I->second.hasMaterializationSideEffectsOnly() &&
@@ -2910,9 +2920,12 @@ Error ExecutionSession::OL_notifyResolved(MaterializationResponsibility &MR,
       assert((KV.second.getFlags() & ~WeakOrCommon) ==
                  (I->second & ~JITSymbolFlags::Common) &&
              "Resolving symbol with incorrect flags");
-    } else
+    } else {
+      /*
       assert(KV.second.getFlags() == I->second &&
              "Resolving symbol with incorrect flags");
+      */
+    }
   }
 #endif
 
diff --git a/llvm/lib/ExecutionEngine/Orc/LinkGraphLayer.cpp b/llvm/lib/ExecutionEngine/Orc/LinkGraphLayer.cpp
index 5789079c2bf6c..2a3cbc1a16e4a 100644
--- a/llvm/lib/ExecutionEngine/Orc/LinkGraphLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LinkGraphLayer.cpp
@@ -86,6 +86,9 @@ JITSymbolFlags LinkGraphLayer::getJITSymbolFlagsForSymbol(Symbol &Sym) {
   if (Sym.isCallable())
     Flags |= JITSymbolFlags::Callable;
 
+  LLVM_DEBUG(dbgs() << " Symbol Flag for " << Sym.getName()
+                    << formatv(" {0:x}\n", Flags.getRawFlagsValue()));
+
   return Flags;
 }
 
diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp
index df3b2a091aec2..881b53dad8d10 100644
--- a/llvm/lib/Object/XCOFFObjectFile.cpp
+++ b/llvm/lib/Object/XCOFFObjectFile.cpp
@@ -201,14 +201,12 @@ template <typename T> const T *XCOFFObjectFile::sectionHeaderTable() const {
   return static_cast<const T *>(SectionHeaderTable);
 }
 
-const XCOFFSectionHeader32 *
-XCOFFObjectFile::sectionHeaderTable32() const {
+const XCOFFSectionHeader32 *XCOFFObjectFile::sectionHeaderTable32() const {
   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
   return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable);
 }
 
-const XCOFFSectionHeader64 *
-XCOFFObjectFile::sectionHeaderTable64() const {
+const XCOFFSectionHeader64 *XCOFFObjectFile::sectionHeaderTable64() const {
   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
   return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable);
 }
@@ -416,7 +414,7 @@ XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
   else
     OffsetToRaw = toSection32(Sec)->FileOffsetToRawData;
 
-  const uint8_t * ContentStart = base() + OffsetToRaw;
+  const uint8_t *ContentStart = base() + OffsetToRaw;
   uint64_t SectionSize = getSectionSize(Sec);
   if (Error E = Binary::checkOffset(
           Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize))
@@ -429,9 +427,14 @@ XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
 }
 
 uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
-  uint64_t Result = 0;
-  llvm_unreachable("Not yet implemented!");
-  return Result;
+  // SCUI - Copied from MC/XCOFFObjectWriter.cpp
+  // Sections other than DWARF section use DefaultSectionAlign as the default
+  // alignment, while DWARF sections have their own alignments. DWARF section
+  // alignment is bigger than DefaultSectionAlign.
+  if (isDebugSection(Sec)) {
+    return 8; // SCUI - just a number for now.
+  }
+  return 4;
 }
 
 uint64_t XCOFFObjectFile::getSectionFileOffsetToRawData(DataRefImpl Sec) const {
@@ -766,8 +769,8 @@ size_t XCOFFObjectFile::getFileHeaderSize() const {
 }
 
 size_t XCOFFObjectFile::getSectionHeaderSize() const {
-  return is64Bit() ? sizeof(XCOFFSectionHeader64) :
-                     sizeof(XCOFFSectionHeader32);
+  return is64Bit() ? sizeof(XCOFFSectionHeader64)
+                   : sizeof(XCOFFSectionHeader32);
 }
 
 bool XCOFFObjectFile::is64Bit() const {
diff --git a/llvm/test/ExecutionEngine/JITLink/ppc64/XCOFF_ppc64.c b/llvm/test/ExecutionEngine/JITLink/ppc64/XCOFF_ppc64.c
new file mode 100644
index 0000000000000..9a2e92de5398a
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/ppc64/XCOFF_ppc64.c
@@ -0,0 +1,12 @@
+// AIX's support for llvm-mc does not have enough support for directives like .csect
+// so we can't use the tool. llvm-jitlink -check is not available as it requries
+// implementation of registerXCOFFGraphInfo. Will revisit this testcase once support
+// is more complete.
+
+// REQUIRES: target=powerpc64-ibm-aix{{.*}}
+
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: clang --target=powerpc64-ibm-aix -c -O3 -fPIC -o %t/xcoff_ppc64.o %s
+// RUN: llvm-jitlink -triple=powerpc64-ibm-aix %t/xcoff_ppc64.o
+
+int main(void) { return 0; }

>From 5ae500c9d9dce3de552c6b55334c8e54bbf6a194 Mon Sep 17 00:00:00 2001
From: Henry Jiang <henry.jiang1 at ibm.com>
Date: Mon, 24 Feb 2025 21:31:04 -0500
Subject: [PATCH 3/5] revert fmt

---
 llvm/include/llvm/ExecutionEngine/Orc/Core.h  |  61 ++++-----
 llvm/lib/ExecutionEngine/Orc/Core.cpp         | 129 ++++++++----------
 .../ExecutionEngine/Orc/LinkGraphLayer.cpp    |   3 -
 llvm/lib/Object/XCOFFObjectFile.cpp           |  12 +-
 4 files changed, 93 insertions(+), 112 deletions(-)

diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/llvm/include/llvm/ExecutionEngine/Orc/Core.h
index 49fd0599c4336..8c933e24f6669 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Core.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h
@@ -308,11 +308,10 @@ class SymbolLookupSet {
   /// If Body returns true then the element just passed in is removed from the
   /// set. If Body returns false then the element is retained.
   template <typename BodyFn>
-  auto forEachWithRemoval(BodyFn &&Body)
-      -> std::enable_if_t<
-          std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
-                                     std::declval<SymbolLookupFlags>())),
-                       bool>::value> {
+  auto forEachWithRemoval(BodyFn &&Body) -> std::enable_if_t<
+      std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
+                                 std::declval<SymbolLookupFlags>())),
+                   bool>::value> {
     UnderlyingVector::size_type I = 0;
     while (I != Symbols.size()) {
       const auto &Name = Symbols[I].first;
@@ -331,12 +330,11 @@ class SymbolLookupSet {
   /// returns true then the element just passed in is removed from the set. If
   /// Body returns false then the element is retained.
   template <typename BodyFn>
-  auto forEachWithRemoval(BodyFn &&Body)
-      -> std::enable_if_t<
-          std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
-                                     std::declval<SymbolLookupFlags>())),
-                       Expected<bool>>::value,
-          Error> {
+  auto forEachWithRemoval(BodyFn &&Body) -> std::enable_if_t<
+      std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
+                                 std::declval<SymbolLookupFlags>())),
+                   Expected<bool>>::value,
+      Error> {
     UnderlyingVector::size_type I = 0;
     while (I != Symbols.size()) {
       const auto &Name = Symbols[I].first;
@@ -527,7 +525,6 @@ class MissingSymbolDefinitions : public ErrorInfo<MissingSymbolDefinitions> {
   std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; }
   const std::string &getModuleName() const { return ModuleName; }
   const SymbolNameVector &getSymbols() const { return Symbols; }
-
 private:
   std::shared_ptr<SymbolStringPool> SSP;
   std::string ModuleName;
@@ -538,8 +535,7 @@ class MissingSymbolDefinitions : public ErrorInfo<MissingSymbolDefinitions> {
 /// symbols that are not claimed by the module's associated
 /// MaterializationResponsibility. If this error is returned it is indicative of
 /// a broken transformation / compiler / object cache.
-class UnexpectedSymbolDefinitions
-    : public ErrorInfo<UnexpectedSymbolDefinitions> {
+class UnexpectedSymbolDefinitions : public ErrorInfo<UnexpectedSymbolDefinitions> {
 public:
   static char ID;
 
@@ -552,7 +548,6 @@ class UnexpectedSymbolDefinitions
   std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; }
   const std::string &getModuleName() const { return ModuleName; }
   const SymbolNameVector &getSymbols() const { return Symbols; }
-
 private:
   std::shared_ptr<SymbolStringPool> SSP;
   std::string ModuleName;
@@ -809,6 +804,7 @@ class AsynchronousSymbolQuery {
   ///        resolved.
   bool isComplete() const { return OutstandingSymbolsCount == 0; }
 
+
 private:
   void handleComplete(ExecutionSession &ES);
 
@@ -907,8 +903,8 @@ class JITDylib : public ThreadSafeRefCountedBase<JITDylib>,
   friend class ExecutionSession;
   friend class Platform;
   friend class MaterializationResponsibility;
-
 public:
+
   JITDylib(const JITDylib &) = delete;
   JITDylib &operator=(const JITDylib &) = delete;
   JITDylib(JITDylib &&) = delete;
@@ -1112,7 +1108,7 @@ class JITDylib : public ThreadSafeRefCountedBase<JITDylib>,
 
 private:
   using AsynchronousSymbolQuerySet =
-      std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
+    std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
 
   using AsynchronousSymbolQueryList =
       std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
@@ -1168,7 +1164,6 @@ class JITDylib : public ThreadSafeRefCountedBase<JITDylib>,
     const AsynchronousSymbolQueryList &pendingQueries() const {
       return PendingQueries;
     }
-
   private:
     AsynchronousSymbolQueryList PendingQueries;
   };
@@ -1364,13 +1359,13 @@ class ExecutionSession {
   using ErrorReporter = unique_function<void(Error)>;
 
   /// Send a result to the remote.
-  using SendResultFunction =
-      unique_function<void(shared::WrapperFunctionResult)>;
+  using SendResultFunction = unique_function<void(shared::WrapperFunctionResult)>;
 
   /// An asynchronous wrapper-function callable from the executor via
   /// jit-dispatch.
   using JITDispatchHandlerFunction = unique_function<void(
-      SendResultFunction SendResult, const char *ArgData, size_t ArgSize)>;
+      SendResultFunction SendResult,
+      const char *ArgData, size_t ArgSize)>;
 
   /// A map associating tag names with asynchronous wrapper function
   /// implementations in the JIT.
@@ -1598,7 +1593,8 @@ class ExecutionSession {
   /// \endcode{.cpp}
   ///
   /// The given OnComplete function will be called to return the result.
-  template <typename... ArgTs> void callWrapperAsync(ArgTs &&...Args) {
+  template <typename... ArgTs>
+  void callWrapperAsync(ArgTs &&... Args) {
     EPC->callWrapperAsync(std::forward<ArgTs>(Args)...);
   }
 
@@ -1643,9 +1639,9 @@ class ExecutionSession {
   /// (using registerJITDispatchHandler) and called from the executor.
   template <typename SPSSignature, typename HandlerT>
   static JITDispatchHandlerFunction wrapAsyncWithSPS(HandlerT &&H) {
-    return [H = std::forward<HandlerT>(H)](SendResultFunction SendResult,
-                                           const char *ArgData,
-                                           size_t ArgSize) mutable {
+    return [H = std::forward<HandlerT>(H)](
+               SendResultFunction SendResult,
+               const char *ArgData, size_t ArgSize) mutable {
       shared::WrapperFunction<SPSSignature>::handleAsync(ArgData, ArgSize, H,
                                                          std::move(SendResult));
     };
@@ -1750,8 +1746,8 @@ class ExecutionSession {
       unique_function<void(Expected<SymbolFlagsMap>)> OnComplete);
 
   // State machine functions for MaterializationResponsibility.
-  void
-  OL_destroyMaterializationResponsibility(MaterializationResponsibility &MR);
+  void OL_destroyMaterializationResponsibility(
+      MaterializationResponsibility &MR);
   SymbolNameSet OL_getRequestedSymbols(const MaterializationResponsibility &MR);
   Error OL_notifyResolved(MaterializationResponsibility &MR,
                           const SymbolMap &Symbols);
@@ -1973,13 +1969,12 @@ inline MaterializationResponsibility::~MaterializationResponsibility() {
   getExecutionSession().OL_destroyMaterializationResponsibility(*this);
 }
 
-inline SymbolNameSet
-MaterializationResponsibility::getRequestedSymbols() const {
+inline SymbolNameSet MaterializationResponsibility::getRequestedSymbols() const {
   return getExecutionSession().OL_getRequestedSymbols(*this);
 }
 
-inline Error
-MaterializationResponsibility::notifyResolved(const SymbolMap &Symbols) {
+inline Error MaterializationResponsibility::notifyResolved(
+    const SymbolMap &Symbols) {
   return getExecutionSession().OL_notifyResolved(*this, Symbols);
 }
 
@@ -1988,8 +1983,8 @@ inline Error MaterializationResponsibility::notifyEmitted(
   return getExecutionSession().OL_notifyEmitted(*this, EmittedDeps);
 }
 
-inline Error
-MaterializationResponsibility::defineMaterializing(SymbolFlagsMap SymbolFlags) {
+inline Error MaterializationResponsibility::defineMaterializing(
+    SymbolFlagsMap SymbolFlags) {
   return getExecutionSession().OL_defineMaterializing(*this,
                                                       std::move(SymbolFlags));
 }
diff --git a/llvm/lib/ExecutionEngine/Orc/Core.cpp b/llvm/lib/ExecutionEngine/Orc/Core.cpp
index 5d9915ba7cfc9..9f466e725668a 100644
--- a/llvm/lib/ExecutionEngine/Orc/Core.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Core.cpp
@@ -12,7 +12,6 @@
 #include "llvm/Config/llvm-config.h"
 #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
 #include "llvm/ExecutionEngine/Orc/Shared/OrcError.h"
-#include "llvm/Support/Debug.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/MSVCErrorWorkarounds.h"
 #include "llvm/Support/raw_ostream.h"
@@ -166,7 +165,8 @@ std::error_code MissingSymbolDefinitions::convertToErrorCode() const {
 }
 
 void MissingSymbolDefinitions::log(raw_ostream &OS) const {
-  OS << "Missing definitions in module " << ModuleName << ": " << Symbols;
+  OS << "Missing definitions in module " << ModuleName
+     << ": " << Symbols;
 }
 
 std::error_code UnexpectedSymbolDefinitions::convertToErrorCode() const {
@@ -174,7 +174,8 @@ std::error_code UnexpectedSymbolDefinitions::convertToErrorCode() const {
 }
 
 void UnexpectedSymbolDefinitions::log(raw_ostream &OS) const {
-  OS << "Unexpected definitions in module " << ModuleName << ": " << Symbols;
+  OS << "Unexpected definitions in module " << ModuleName
+     << ": " << Symbols;
 }
 
 void SymbolInstance::lookupAsync(LookupAsyncOnCompleteFn OnComplete) const {
@@ -739,7 +740,7 @@ JITDylib::defineMaterializing(MaterializationResponsibility &FromMR,
         continue;
       } else
         EntryItr =
-            Symbols.insert(std::make_pair(Name, SymbolTableEntry(Flags))).first;
+          Symbols.insert(std::make_pair(Name, SymbolTableEntry(Flags))).first;
 
       AddedSyms.push_back(NonOwningSymbolStringPtr(Name));
       EntryItr->second.setState(SymbolState::Materializing);
@@ -761,62 +762,63 @@ Error JITDylib::replace(MaterializationResponsibility &FromMR,
   std::unique_ptr<MaterializationUnit> MustRunMU;
   std::unique_ptr<MaterializationResponsibility> MustRunMR;
 
-  auto Err = ES.runSessionLocked([&, this]() -> Error {
-    if (FromMR.RT->isDefunct())
-      return make_error<ResourceTrackerDefunct>(std::move(FromMR.RT));
+  auto Err =
+      ES.runSessionLocked([&, this]() -> Error {
+        if (FromMR.RT->isDefunct())
+          return make_error<ResourceTrackerDefunct>(std::move(FromMR.RT));
 
 #ifndef NDEBUG
-    for (auto &KV : MU->getSymbols()) {
-      auto SymI = Symbols.find(KV.first);
-      assert(SymI != Symbols.end() && "Replacing unknown symbol");
-      assert(SymI->second.getState() == SymbolState::Materializing &&
-             "Can not replace a symbol that ha is not materializing");
-      assert(!SymI->second.hasMaterializerAttached() &&
-             "Symbol should not have materializer attached already");
-      assert(UnmaterializedInfos.count(KV.first) == 0 &&
-             "Symbol being replaced should have no UnmaterializedInfo");
-    }
+        for (auto &KV : MU->getSymbols()) {
+          auto SymI = Symbols.find(KV.first);
+          assert(SymI != Symbols.end() && "Replacing unknown symbol");
+          assert(SymI->second.getState() == SymbolState::Materializing &&
+                 "Can not replace a symbol that ha is not materializing");
+          assert(!SymI->second.hasMaterializerAttached() &&
+                 "Symbol should not have materializer attached already");
+          assert(UnmaterializedInfos.count(KV.first) == 0 &&
+                 "Symbol being replaced should have no UnmaterializedInfo");
+        }
 #endif // NDEBUG
 
-    // If the tracker is defunct we need to bail out immediately.
-
-    // If any symbol has pending queries against it then we need to
-    // materialize MU immediately.
-    for (auto &KV : MU->getSymbols()) {
-      auto MII = MaterializingInfos.find(KV.first);
-      if (MII != MaterializingInfos.end()) {
-        if (MII->second.hasQueriesPending()) {
-          MustRunMR = ES.createMaterializationResponsibility(
-              *FromMR.RT, std::move(MU->SymbolFlags),
-              std::move(MU->InitSymbol));
-          MustRunMU = std::move(MU);
-          return Error::success();
+        // If the tracker is defunct we need to bail out immediately.
+
+        // If any symbol has pending queries against it then we need to
+        // materialize MU immediately.
+        for (auto &KV : MU->getSymbols()) {
+          auto MII = MaterializingInfos.find(KV.first);
+          if (MII != MaterializingInfos.end()) {
+            if (MII->second.hasQueriesPending()) {
+              MustRunMR = ES.createMaterializationResponsibility(
+                  *FromMR.RT, std::move(MU->SymbolFlags),
+                  std::move(MU->InitSymbol));
+              MustRunMU = std::move(MU);
+              return Error::success();
+            }
+          }
         }
-      }
-    }
 
-    // Otherwise, make MU responsible for all the symbols.
-    auto UMI =
-        std::make_shared<UnmaterializedInfo>(std::move(MU), FromMR.RT.get());
-    for (auto &KV : UMI->MU->getSymbols()) {
-      auto SymI = Symbols.find(KV.first);
-      assert(SymI->second.getState() == SymbolState::Materializing &&
-             "Can not replace a symbol that is not materializing");
-      assert(!SymI->second.hasMaterializerAttached() &&
-             "Can not replace a symbol that has a materializer attached");
-      assert(UnmaterializedInfos.count(KV.first) == 0 &&
-             "Unexpected materializer entry in map");
-      SymI->second.setAddress(SymI->second.getAddress());
-      SymI->second.setMaterializerAttached(true);
-
-      auto &UMIEntry = UnmaterializedInfos[KV.first];
-      assert((!UMIEntry || !UMIEntry->MU) &&
-             "Replacing symbol with materializer still attached");
-      UMIEntry = UMI;
-    }
+        // Otherwise, make MU responsible for all the symbols.
+        auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU),
+                                                        FromMR.RT.get());
+        for (auto &KV : UMI->MU->getSymbols()) {
+          auto SymI = Symbols.find(KV.first);
+          assert(SymI->second.getState() == SymbolState::Materializing &&
+                 "Can not replace a symbol that is not materializing");
+          assert(!SymI->second.hasMaterializerAttached() &&
+                 "Can not replace a symbol that has a materializer attached");
+          assert(UnmaterializedInfos.count(KV.first) == 0 &&
+                 "Unexpected materializer entry in map");
+          SymI->second.setAddress(SymI->second.getAddress());
+          SymI->second.setMaterializerAttached(true);
+
+          auto &UMIEntry = UnmaterializedInfos[KV.first];
+          assert((!UMIEntry || !UMIEntry->MU) &&
+                 "Replacing symbol with materializer still attached");
+          UMIEntry = UMI;
+        }
 
-    return Error::success();
-  });
+        return Error::success();
+      });
 
   if (Err)
     return Err;
@@ -920,12 +922,9 @@ Error JITDylib::resolve(MaterializationResponsibility &MR,
                          (SymI->second.getFlags() & ~JITSymbolFlags::Common) &&
                      "Resolving symbol with incorrect flags");
 
-            } else {
-              /*
+            } else
               assert(KV.second.getFlags() == SymI->second.getFlags() &&
                      "Resolved flags should match the declared flags");
-                     */
-            }
 
             Worklist.push_back(
                 {SymI, {KV.second.getAddress(), SymI->second.getFlags()}});
@@ -2056,8 +2055,7 @@ bool ExecutionSession::verifySessionState(Twine Phase) {
           // Pending queries should be for subsequent states.
           auto CurState = static_cast<SymbolState>(
               static_cast<std::underlying_type_t<SymbolState>>(
-                  SymItr->second.getState()) +
-              1);
+                  SymItr->second.getState()) + 1);
           for (auto &Q : MII.PendingQueries) {
             if (Q->getRequiredState() != CurState) {
               if (Q->getRequiredState() > CurState)
@@ -2901,14 +2899,6 @@ Error ExecutionSession::OL_notifyResolved(MaterializationResponsibility &MR,
 #ifndef NDEBUG
   for (auto &KV : Symbols) {
     auto I = MR.SymbolFlags.find(KV.first);
-
-    LLVM_DEBUG(dbgs() << "  Flags for " << KV.first << ": "
-                      << formatv("expected {0:x}", I->second.getRawFlagsValue())
-                      << " "
-                      << formatv("found {0:x}",
-                                 KV.second.getFlags().getRawFlagsValue())
-                      << "\n");
-
     assert(I != MR.SymbolFlags.end() &&
            "Resolving symbol outside this responsibility set");
     assert(!I->second.hasMaterializationSideEffectsOnly() &&
@@ -2920,12 +2910,9 @@ Error ExecutionSession::OL_notifyResolved(MaterializationResponsibility &MR,
       assert((KV.second.getFlags() & ~WeakOrCommon) ==
                  (I->second & ~JITSymbolFlags::Common) &&
              "Resolving symbol with incorrect flags");
-    } else {
-      /*
+    } else
       assert(KV.second.getFlags() == I->second &&
              "Resolving symbol with incorrect flags");
-      */
-    }
   }
 #endif
 
diff --git a/llvm/lib/ExecutionEngine/Orc/LinkGraphLayer.cpp b/llvm/lib/ExecutionEngine/Orc/LinkGraphLayer.cpp
index 2a3cbc1a16e4a..5789079c2bf6c 100644
--- a/llvm/lib/ExecutionEngine/Orc/LinkGraphLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LinkGraphLayer.cpp
@@ -86,9 +86,6 @@ JITSymbolFlags LinkGraphLayer::getJITSymbolFlagsForSymbol(Symbol &Sym) {
   if (Sym.isCallable())
     Flags |= JITSymbolFlags::Callable;
 
-  LLVM_DEBUG(dbgs() << " Symbol Flag for " << Sym.getName()
-                    << formatv(" {0:x}\n", Flags.getRawFlagsValue()));
-
   return Flags;
 }
 
diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp
index 881b53dad8d10..aef7cc2a78188 100644
--- a/llvm/lib/Object/XCOFFObjectFile.cpp
+++ b/llvm/lib/Object/XCOFFObjectFile.cpp
@@ -201,12 +201,14 @@ template <typename T> const T *XCOFFObjectFile::sectionHeaderTable() const {
   return static_cast<const T *>(SectionHeaderTable);
 }
 
-const XCOFFSectionHeader32 *XCOFFObjectFile::sectionHeaderTable32() const {
+const XCOFFSectionHeader32 *
+XCOFFObjectFile::sectionHeaderTable32() const {
   assert(!is64Bit() && "32-bit interface called on 64-bit object file.");
   return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable);
 }
 
-const XCOFFSectionHeader64 *XCOFFObjectFile::sectionHeaderTable64() const {
+const XCOFFSectionHeader64 *
+XCOFFObjectFile::sectionHeaderTable64() const {
   assert(is64Bit() && "64-bit interface called on a 32-bit object file.");
   return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable);
 }
@@ -414,7 +416,7 @@ XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
   else
     OffsetToRaw = toSection32(Sec)->FileOffsetToRawData;
 
-  const uint8_t *ContentStart = base() + OffsetToRaw;
+  const uint8_t * ContentStart = base() + OffsetToRaw;
   uint64_t SectionSize = getSectionSize(Sec);
   if (Error E = Binary::checkOffset(
           Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize))
@@ -769,8 +771,8 @@ size_t XCOFFObjectFile::getFileHeaderSize() const {
 }
 
 size_t XCOFFObjectFile::getSectionHeaderSize() const {
-  return is64Bit() ? sizeof(XCOFFSectionHeader64)
-                   : sizeof(XCOFFSectionHeader32);
+  return is64Bit() ? sizeof(XCOFFSectionHeader64) :
+                     sizeof(XCOFFSectionHeader32);
 }
 
 bool XCOFFObjectFile::is64Bit() const {

>From 3bd840953d2d71a7aba02e4ed16bf7c43d0c6c87 Mon Sep 17 00:00:00 2001
From: Henry Jiang <henry.jiang1 at ibm.com>
Date: Mon, 24 Feb 2025 23:51:27 -0500
Subject: [PATCH 4/5] clean up

---
 llvm/include/llvm/ExecutionEngine/Orc/Core.h  |   4 -
 .../JITLink/XCOFFLinkGraphBuilder.cpp         | 306 ++++++++----------
 .../JITLink/XCOFFLinkGraphBuilder.h           |  12 +-
 .../ExecutionEngine/JITLink/XCOFF_ppc64.cpp   |   3 +-
 .../Orc/ObjectFileInterface.cpp               |  45 +++
 llvm/lib/Object/XCOFFObjectFile.cpp           |   7 +-
 .../JITLink/ppc64/XCOFF_ppc64.c               |  12 -
 .../JITLink/ppc64/XCOFF_ppc64.ll              |  24 ++
 8 files changed, 211 insertions(+), 202 deletions(-)
 delete mode 100644 llvm/test/ExecutionEngine/JITLink/ppc64/XCOFF_ppc64.c
 create mode 100644 llvm/test/ExecutionEngine/JITLink/ppc64/XCOFF_ppc64.ll

diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/llvm/include/llvm/ExecutionEngine/Orc/Core.h
index 8c933e24f6669..cecb4094c9a57 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Core.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h
@@ -693,10 +693,6 @@ class MaterializationResponsibility {
       : JD(RT->getJITDylib()), RT(std::move(RT)),
         SymbolFlags(std::move(SymbolFlags)), InitSymbol(std::move(InitSymbol)) {
     assert(!this->SymbolFlags.empty() && "Materializing nothing?");
-    for (auto &KV : this->SymbolFlags) {
-      dbgs() << "@@@ Init MR " << KV.first << " "
-             << format_hex(KV.second.getRawFlagsValue(), 8) << "\n";
-    }
   }
 
   JITDylib &JD;
diff --git a/llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.cpp b/llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.cpp
index 298284c82b18f..0a76dcc77536b 100644
--- a/llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.cpp
@@ -40,198 +40,132 @@ XCOFFLinkGraphBuilder::XCOFFLinkGraphBuilder(
           std::string(Obj.getFileName()), std::move(SSP), std::move(TT),
           std::move(Features), std::move(GetEdgeKindName))) {}
 
-static llvm::raw_ostream &debugStorageClass(llvm::raw_ostream &OS,
-                                            XCOFF::StorageClass SC) {
+static llvm::StringRef getStorageClassString(XCOFF::StorageClass SC) {
   switch (SC) {
-    // Debug symbols
   case XCOFF::StorageClass::C_FILE:
-    OS << "C_FILE (File name)";
-    break;
+    return "C_FILE (File name)";
   case XCOFF::StorageClass::C_BINCL:
-    OS << "C_BINCL (Beginning of include file)";
-    break;
+    return "C_BINCL (Beginning of include file)";
   case XCOFF::StorageClass::C_EINCL:
-    OS << "C_EINCL (Ending of include file)";
-    break;
+    return "C_EINCL (Ending of include file)";
   case XCOFF::StorageClass::C_GSYM:
-    OS << "C_GSYM (Global variable)";
-    break;
+    return "C_GSYM (Global variable)";
   case XCOFF::StorageClass::C_STSYM:
-    OS << "C_STSYM (Statically allocated symbol)";
-    break;
+    return "C_STSYM (Statically allocated symbol)";
   case XCOFF::StorageClass::C_BCOMM:
-    OS << "C_BCOMM (Beginning of common block)";
-    break;
+    return "C_BCOMM (Beginning of common block)";
   case XCOFF::StorageClass::C_ECOMM:
-    OS << "C_ECOMM (End of common block)";
-    break;
+    return "C_ECOMM (End of common block)";
   case XCOFF::StorageClass::C_ENTRY:
-    OS << "C_ENTRY (Alternate entry)";
-    break;
+    return "C_ENTRY (Alternate entry)";
   case XCOFF::StorageClass::C_BSTAT:
-    OS << "C_BSTAT (Beginning of static block)";
-    break;
+    return "C_BSTAT (Beginning of static block)";
   case XCOFF::StorageClass::C_ESTAT:
-    OS << "C_ESTAT (End of static block)";
-    break;
+    return "C_ESTAT (End of static block)";
   case XCOFF::StorageClass::C_GTLS:
-    OS << "C_GTLS (Global thread-local variable)";
-    break;
+    return "C_GTLS (Global thread-local variable)";
   case XCOFF::StorageClass::C_STTLS:
-    OS << "C_STTLS (Static thread-local variable)";
-    break;
-
-    // DWARF symbols
+    return "C_STTLS (Static thread-local variable)";
   case XCOFF::StorageClass::C_DWARF:
-    OS << "C_DWARF (DWARF section symbol)";
-    break;
-
-    // Absolute symbols
+    return "C_DWARF (DWARF section symbol)";
   case XCOFF::StorageClass::C_LSYM:
-    OS << "C_LSYM (Automatic variable allocated on stack)";
-    break;
+    return "C_LSYM (Automatic variable allocated on stack)";
   case XCOFF::StorageClass::C_PSYM:
-    OS << "C_PSYM (Argument to subroutine allocated on stack)";
-    break;
+    return "C_PSYM (Argument to subroutine allocated on stack)";
   case XCOFF::StorageClass::C_RSYM:
-    OS << "C_RSYM (Register variable)";
-    break;
+    return "C_RSYM (Register variable)";
   case XCOFF::StorageClass::C_RPSYM:
-    OS << "C_RPSYM (Argument to function stored in register)";
-    break;
+    return "C_RPSYM (Argument to function stored in register)";
   case XCOFF::StorageClass::C_ECOML:
-    OS << "C_ECOML (Local member of common block)";
-    break;
+    return "C_ECOML (Local member of common block)";
   case XCOFF::StorageClass::C_FUN:
-    OS << "C_FUN (Function or procedure)";
-    break;
-
-    // External symbols
+    return "C_FUN (Function or procedure)";
   case XCOFF::StorageClass::C_EXT:
-    OS << "C_EXT (External symbol)";
-    break;
+    return "C_EXT (External symbol)";
   case XCOFF::StorageClass::C_WEAKEXT:
-    OS << "C_WEAKEXT (Weak external symbol)";
-    break;
-
-    // General sections
+    return "C_WEAKEXT (Weak external symbol)";
   case XCOFF::StorageClass::C_NULL:
-    OS << "C_NULL";
-    break;
+    return "C_NULL";
   case XCOFF::StorageClass::C_STAT:
-    OS << "C_STAT (Static)";
-    break;
+    return "C_STAT (Static)";
   case XCOFF::StorageClass::C_BLOCK:
-    OS << "C_BLOCK (\".bb\" or \".eb\")";
-    break;
+    return "C_BLOCK (\".bb\" or \".eb\")";
   case XCOFF::StorageClass::C_FCN:
-    OS << "C_FCN (\".bf\" or \".ef\")";
-    break;
+    return "C_FCN (\".bf\" or \".ef\")";
   case XCOFF::StorageClass::C_HIDEXT:
-    OS << "C_HIDEXT (Un-named external symbol)";
-    break;
+    return "C_HIDEXT (Un-named external symbol)";
   case XCOFF::StorageClass::C_INFO:
-    OS << "C_INFO (Comment string in .info section)";
-    break;
+    return "C_INFO (Comment string in .info section)";
   case XCOFF::StorageClass::C_DECL:
-    OS << "C_DECL (Declaration of object)";
-    break;
-
-    // Obsolete/Undocumented
+    return "C_DECL (Declaration of object)";
   case XCOFF::StorageClass::C_AUTO:
-    OS << "C_AUTO (Automatic variable)";
-    break;
+    return "C_AUTO (Automatic variable)";
   case XCOFF::StorageClass::C_REG:
-    OS << "C_REG (Register variable)";
-    break;
+    return "C_REG (Register variable)";
   case XCOFF::StorageClass::C_EXTDEF:
-    OS << "C_EXTDEF (External definition)";
-    break;
+    return "C_EXTDEF (External definition)";
   case XCOFF::StorageClass::C_LABEL:
-    OS << "C_LABEL (Label)";
-    break;
+    return "C_LABEL (Label)";
   case XCOFF::StorageClass::C_ULABEL:
-    OS << "C_ULABEL (Undefined label)";
-    break;
+    return "C_ULABEL (Undefined label)";
   case XCOFF::StorageClass::C_MOS:
-    OS << "C_MOS (Member of structure)";
-    break;
+    return "C_MOS (Member of structure)";
   case XCOFF::StorageClass::C_ARG:
-    OS << "C_ARG (Function argument)";
-    break;
+    return "C_ARG (Function argument)";
   case XCOFF::StorageClass::C_STRTAG:
-    OS << "C_STRTAG (Structure tag)";
-    break;
+    return "C_STRTAG (Structure tag)";
   case XCOFF::StorageClass::C_MOU:
-    OS << "C_MOU (Member of union)";
-    break;
+    return "C_MOU (Member of union)";
   case XCOFF::StorageClass::C_UNTAG:
-    OS << "C_UNTAG (Union tag)";
-    break;
+    return "C_UNTAG (Union tag)";
   case XCOFF::StorageClass::C_TPDEF:
-    OS << "C_TPDEF (Type definition)";
-    break;
+    return "C_TPDEF (Type definition)";
   case XCOFF::StorageClass::C_USTATIC:
-    OS << "C_USTATIC (Undefined static)";
-    break;
+    return "C_USTATIC (Undefined static)";
   case XCOFF::StorageClass::C_ENTAG:
-    OS << "C_ENTAG (Enumeration tag)";
-    break;
+    return "C_ENTAG (Enumeration tag)";
   case XCOFF::StorageClass::C_MOE:
-    OS << "C_MOE (Member of enumeration)";
-    break;
+    return "C_MOE (Member of enumeration)";
   case XCOFF::StorageClass::C_REGPARM:
-    OS << "C_REGPARM (Register parameter)";
-    break;
+    return "C_REGPARM (Register parameter)";
   case XCOFF::StorageClass::C_FIELD:
-    OS << "C_FIELD (Bit field)";
-    break;
+    return "C_FIELD (Bit field)";
   case XCOFF::StorageClass::C_EOS:
-    OS << "C_EOS (End of structure)";
-    break;
+    return "C_EOS (End of structure)";
   case XCOFF::StorageClass::C_LINE:
-    OS << "C_LINE";
-    break;
+    return "C_LINE";
   case XCOFF::StorageClass::C_ALIAS:
-    OS << "C_ALIAS (Duplicate tag)";
-    break;
+    return "C_ALIAS (Duplicate tag)";
   case XCOFF::StorageClass::C_HIDDEN:
-    OS << "C_HIDDEN (Special storage class for external)";
-    break;
+    return "C_HIDDEN (Special storage class for external)";
   case XCOFF::StorageClass::C_EFCN:
-    OS << "C_EFCN (Physical end of function)";
-    break;
-
-    // Reserved
+    return "C_EFCN (Physical end of function)";
   case XCOFF::StorageClass::C_TCSYM:
-    OS << "C_TCSYM (Reserved)";
-    break;
+    return "C_TCSYM (Reserved)";
   }
-  return OS;
 }
 
 Error XCOFFLinkGraphBuilder::processSections() {
   LLVM_DEBUG(dbgs() << "  Creating graph sections...\n");
 
-  // Create undefined section to contain all external symbols
   UndefSection = &G->createSection("*UND*", orc::MemProt::None);
 
-  for (auto Section : Obj.sections()) {
+  for (object::SectionRef Section : Obj.sections()) {
+    auto SectionName = Section.getName();
+    if (!SectionName)
+      return SectionName.takeError();
+
     LLVM_DEBUG({
-      dbgs() << "    section = " << cantFail(Section.getName())
+      dbgs() << "    section = " << *SectionName
              << ", idx = " << Section.getIndex()
              << ", size = " << format_hex_no_prefix(Section.getSize(), 8)
              << ", vma = " << format_hex(Section.getAddress(), 16) << "\n";
     });
 
     // We can skip debug (including dawrf) and pad sections
-    if (Section.isDebugSection() || cantFail(Section.getName()) == "pad") {
-      LLVM_DEBUG(dbgs() << "      skipping...\n");
+    if (Section.isDebugSection() || *SectionName == "pad")
       continue;
-    }
-
-    auto SectionName = cantFail(Section.getName());
-    LLVM_DEBUG(dbgs() << "        creating graph section...\n");
+    LLVM_DEBUG(dbgs() << "        creating graph section\n");
 
     orc::MemProt Prot = orc::MemProt::Read;
     if (Section.isText())
@@ -239,11 +173,12 @@ Error XCOFFLinkGraphBuilder::processSections() {
     if (Section.isData() || Section.isBSS())
       Prot |= orc::MemProt::Write;
 
-    auto *GraphSec = &G->createSection(SectionName, Prot);
-    // TODO(HJ): Check for memory lifetime no alloc for certain sections
+    jitlink::Section *GraphSec = &G->createSection(*SectionName, Prot);
+    // TODO: Check for no_alloc for certain sections
 
-    SectionDataMap[Section.getIndex()] = Section;
-    SectionMap[Section.getIndex()] = GraphSec;
+    assert(!SectionTable.contains(Section.getIndex()) &&
+           "Section with same index already exists");
+    SectionTable[Section.getIndex()] = {GraphSec, Section};
   }
 
   return Error::success();
@@ -286,8 +221,7 @@ static void printSymbolEntry(raw_ostream &OS,
   }
   OS << " " << format_hex(Sym.getSize(), 8);
   OS << " " << Sym.getSectionNumber();
-  OS << " ";
-  debugStorageClass(dbgs(), Sym.getStorageClass());
+  OS << " " << getStorageClassString(Sym.getStorageClass());
   OS << " (idx: " << Obj.getSymbolIndex(Sym.getRawDataRefImpl().p) << ")";
   if (Sym.isCsectSymbol()) {
     if (auto ParentSym = getXCOFFSymbolContainingSymbolRef(Obj, Sym)) {
@@ -301,28 +235,32 @@ static void printSymbolEntry(raw_ostream &OS,
 Error XCOFFLinkGraphBuilder::processCsectsAndSymbols() {
   LLVM_DEBUG(dbgs() << "  Creating graph blocks and symbols...\n");
 
-  for (auto [K, V] : SectionMap) {
+  for (auto [K, V] : SectionTable) {
     LLVM_DEBUG(dbgs() << "    section entry(idx: " << K
-                      << " section: " << V->getName() << ")\n");
+                      << " section: " << V.Section->getName() << ")\n");
   }
 
   for (object::XCOFFSymbolRef Symbol : Obj.symbols()) {
     LLVM_DEBUG({ printSymbolEntry(dbgs(), Obj, Symbol); });
 
-    auto Flags = cantFail(Symbol.getFlags());
-    bool External = Flags & object::SymbolRef::SF_Undefined;
-    bool Weak = Flags & object::SymbolRef::SF_Weak;
-    bool Hidden = Flags & object::SymbolRef::SF_Hidden;
-    bool Global = Flags & object::SymbolRef::SF_Global;
-    // bool Exported = Flags & object::SymbolRef::SF_Exported;
-    // bool Absolute = Flags & object::SymbolRef::SF_Absolute;
+    auto Flags = Symbol.getFlags();
+    if (!Flags)
+      return Flags.takeError();
+
+    bool External = *Flags & object::SymbolRef::SF_Undefined;
+    bool Weak = *Flags & object::SymbolRef::SF_Weak;
+    bool Hidden = *Flags & object::SymbolRef::SF_Hidden;
+    bool Global = *Flags & object::SymbolRef::SF_Global;
 
     auto SymbolIndex = Obj.getSymbolIndex(Symbol.getEntryAddress());
+    auto SymbolName = Symbol.getName();
+    if (!SymbolName)
+      return SymbolName.takeError();
 
     if (External) {
       LLVM_DEBUG(dbgs() << "      created external symbol\n");
-      SymbolIdxMap[SymbolIndex] = &G->addExternalSymbol(
-          cantFail(Symbol.getName()), Symbol.getSize(), Weak);
+      SymbolIndexTable[SymbolIndex] =
+          &G->addExternalSymbol(*SymbolName, Symbol.getSize(), Weak);
       continue;
     }
 
@@ -337,40 +275,45 @@ Error XCOFFLinkGraphBuilder::processCsectsAndSymbols() {
     auto CsectSymbolIndex = Obj.getSymbolIndex(CsectSymbol.getEntryAddress());
     auto ParentSectionNumber = CsectSymbol.getSectionNumber();
 
-    bool IsUndefinedSection = !SectionMap.contains(ParentSectionNumber);
-    Section *ParentSection =
-        !IsUndefinedSection ? SectionMap[ParentSectionNumber] : UndefSection;
+    bool IsUndefinedSection = !SectionTable.contains(ParentSectionNumber);
+    Section *ParentSection = !IsUndefinedSection
+                                 ? SectionTable[ParentSectionNumber].Section
+                                 : UndefSection;
     Block *B = nullptr;
 
-    if (!CsectMap.contains(CsectSymbolIndex) && !IsUndefinedSection) {
-      auto SectionRef = SectionDataMap[ParentSectionNumber];
+    // TODO: Clean up the logic for handling undefined symbols
+    if (!CsectTable.contains(CsectSymbolIndex) && !IsUndefinedSection) {
+      object::SectionRef &SectionRef =
+          SectionTable[ParentSectionNumber].SectionData;
       auto Data = SectionRef.getContents();
       if (!Data)
         return Data.takeError();
+      auto CsectSymbolAddr = CsectSymbol.getAddress();
+      if (!CsectSymbolAddr)
+        return CsectSymbolAddr.takeError();
+
       ArrayRef<char> SectionBuffer{Data->data(), Data->size()};
-      auto Offset =
-          cantFail(CsectSymbol.getAddress()) - SectionRef.getAddress();
+      auto Offset = *CsectSymbolAddr - SectionRef.getAddress();
 
-      LLVM_DEBUG({
-        dbgs() << "      symbol entry: offset = " << Offset
-               << ", size = " << CsectSymbol.getSize() << ", storage class = ";
-        debugStorageClass(dbgs(), CsectSymbol.getStorageClass()) << "\n";
-      });
+      LLVM_DEBUG(dbgs() << "      symbol entry: offset = " << Offset
+                        << ", size = " << CsectSymbol.getSize()
+                        << ", storage class = "
+                        << getStorageClassString(CsectSymbol.getStorageClass())
+                        << "\n");
 
       B = &G->createContentBlock(
           *ParentSection, SectionBuffer.slice(Offset, CsectSymbol.getSize()),
-          orc::ExecutorAddr(cantFail(CsectSymbol.getAddress())),
-          CsectSymbol.getAlignment(), 0);
+          orc::ExecutorAddr(*CsectSymbolAddr), CsectSymbol.getAlignment(), 0);
 
-      CsectMap[CsectSymbolIndex] = B;
+      CsectTable[CsectSymbolIndex] = B;
     } else {
-      B = CsectMap[CsectSymbolIndex];
+      B = CsectTable[CsectSymbolIndex];
     }
 
     Scope S{Scope::Default};
     if (Hidden)
       S = Scope::Hidden;
-    // TODO(HJ): Got this from llvm-objdump.cpp:2938 not sure if its correct
+    // TODO: Got this from llvm-objdump.cpp:2938 not sure if its correct
     if (!Weak) {
       if (Global)
         S = Scope::Default;
@@ -378,18 +321,24 @@ Error XCOFFLinkGraphBuilder::processCsectsAndSymbols() {
         S = Scope::Local;
     }
 
-    // TODO(HJ): not sure what is Scope::SideEffectsOnly
+    // TODO: figure out all symbols that should have Scope::SideEffectsOnly
     Linkage L = Weak ? Linkage::Weak : Linkage::Strong;
-    auto BlockOffset =
-        cantFail(Symbol.getAddress()) - B->getAddress().getValue();
+    auto SymbolAddr = Symbol.getAddress();
+    if (!SymbolAddr)
+      return SymbolAddr.takeError();
+    auto IsCallableOrErr = Symbol.isFunction();
+    if (!IsCallableOrErr)
+      return IsCallableOrErr.takeError();
+
+    auto BlockOffset = *SymbolAddr - B->getAddress().getValue();
 
     LLVM_DEBUG(dbgs() << "      creating with linkage = " << getLinkageName(L)
                       << ", scope = " << getScopeName(S) << ", B = "
                       << format_hex(B->getAddress().getValue(), 16) << "\n");
 
-    SymbolIdxMap[SymbolIndex] = &G->addDefinedSymbol(
-        *B, BlockOffset, cantFail(Symbol.getName()), Symbol.getSize(), L, S,
-        cantFail(Symbol.isFunction()), true);
+    SymbolIndexTable[SymbolIndex] =
+        &G->addDefinedSymbol(*B, BlockOffset, *SymbolName, Symbol.getSize(), L,
+                             S, *IsCallableOrErr, true);
   }
 
   return Error::success();
@@ -399,23 +348,31 @@ Error XCOFFLinkGraphBuilder::processRelocations() {
   LLVM_DEBUG(dbgs() << "  Creating relocations...\n");
 
   for (object::SectionRef Section : Obj.sections()) {
+    auto SectionName = Section.getName();
+    if (!SectionName)
+      return SectionName.takeError();
+
+    LLVM_DEBUG(dbgs() << "    Relocations for section " << *SectionName
+                      << ":\n");
 
-    LLVM_DEBUG(dbgs() << "    Relocations for section "
-                      << cantFail(Section.getName()) << ":\n");
     for (object::RelocationRef Relocation : Section.relocations()) {
       SmallString<16> RelocName;
       Relocation.getTypeName(RelocName);
       object::SymbolRef Symbol = *Relocation.getSymbol();
-      StringRef TargetSymbol = cantFail(Symbol.getName());
+
+      auto TargetSymbol = Symbol.getName();
+      if (!TargetSymbol)
+        return TargetSymbol.takeError();
+
       auto SymbolIndex = Obj.getSymbolIndex(Symbol.getRawDataRefImpl().p);
 
       LLVM_DEBUG(dbgs() << "      " << format_hex(Relocation.getOffset(), 16)
                         << " (idx: " << SymbolIndex << ")"
-                        << " " << RelocName << " " << TargetSymbol << "\n";);
+                        << " " << RelocName << " " << *TargetSymbol << "\n";);
 
-      assert(SymbolIdxMap.contains(SymbolIndex) &&
+      assert(SymbolIndexTable.contains(SymbolIndex) &&
              "Relocation needs a record in the symbol table");
-      auto *S = SymbolIdxMap[SymbolIndex];
+      auto *S = SymbolIndexTable[SymbolIndex];
       auto It = find_if(G->blocks(),
                         [Target = orc::ExecutorAddr(Section.getAddress() +
                                                     Relocation.getOffset())](
@@ -425,10 +382,7 @@ Error XCOFFLinkGraphBuilder::processRelocations() {
       assert(It != G->blocks().end() &&
              "Cannot find the target relocation block");
       Block *B = *It;
-      LLVM_DEBUG(dbgs() << "        found target relocation block: "
-                        << format_hex(B->getAddress().getValue(), 16) << "\n");
 
-      // TODO(HJ): correctly map edge kind and figure out if we need addend
       auto TargetBlockOffset = Section.getAddress() + Relocation.getOffset() -
                                B->getAddress().getValue();
       switch (Relocation.getType()) {
@@ -450,9 +404,7 @@ Error XCOFFLinkGraphBuilder::processRelocations() {
 Expected<std::unique_ptr<LinkGraph>> XCOFFLinkGraphBuilder::buildGraph() {
   LLVM_DEBUG(dbgs() << "Building XCOFFLinkGraph...\n");
 
-  // TODO(HJ): Check for for relocation
-  // if (Obj.isRelocatableObject())
-  //   return make_error<JITLinkError>("XCOFF object is not relocatable");
+  // FIXME: Check to make sure the object is relocatable
 
   if (auto Err = processSections())
     return Err;
diff --git a/llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.h
index a2bbd6ce99f3c..c182cb129097d 100644
--- a/llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.h
+++ b/llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.h
@@ -47,10 +47,14 @@ class XCOFFLinkGraphBuilder {
 
   Section* UndefSection;
 
-  DenseMap<uint16_t, Section *> SectionMap;
-  DenseMap<uint16_t, object::SectionRef> SectionDataMap;
-  DenseMap<uint32_t, Block *> CsectMap;
-  DenseMap<uint32_t, Symbol *> SymbolIdxMap;
+  struct SectionEntry {
+    jitlink::Section* Section;
+    object::SectionRef SectionData;
+  };
+
+  DenseMap<uint16_t, SectionEntry> SectionTable;
+  DenseMap<uint32_t, Block *> CsectTable;
+  DenseMap<uint32_t, Symbol *> SymbolIndexTable;
 };
 
 } // namespace jitlink
diff --git a/llvm/lib/ExecutionEngine/JITLink/XCOFF_ppc64.cpp b/llvm/lib/ExecutionEngine/JITLink/XCOFF_ppc64.cpp
index 22aa6c020416e..fd6b5f61749b5 100644
--- a/llvm/lib/ExecutionEngine/JITLink/XCOFF_ppc64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/XCOFF_ppc64.cpp
@@ -65,7 +65,8 @@ class XCOFFJITLinker_ppc64 : public JITLinker<XCOFFJITLinker_ppc64> {
                        std::unique_ptr<LinkGraph> G,
                        PassConfiguration PassConfig)
       : JITLinkerBase(std::move(Ctx), std::move(G), std::move(PassConfig)) {
-    // Post allocation pass define TOC base
+    // FIXME: Post allocation pass define TOC base, this is temporary to support
+    // building until we can build the required toc entries
     defineTOCSymbol(getGraph());
   }
 
diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp
index 0b2cafb0bff13..7f94c09ffe914 100644
--- a/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp
@@ -7,11 +7,13 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
 #include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
 #include "llvm/Object/COFF.h"
 #include "llvm/Object/ELFObjectFile.h"
 #include "llvm/Object/MachO.h"
 #include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/XCOFFObjectFile.h"
 #include <optional>
 
 #define DEBUG_TYPE "orc"
@@ -227,6 +229,47 @@ getCOFFObjectFileSymbolInfo(ExecutionSession &ES,
   return I;
 }
 
+Expected<MaterializationUnit::Interface>
+getXCOFFObjectFileSymbolInfo(ExecutionSession &ES,
+                             const object::ObjectFile &Obj) {
+
+  MaterializationUnit::Interface I;
+
+  for (auto &Sym : Obj.symbols()) {
+    Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
+    if (!SymFlagsOrErr)
+      return SymFlagsOrErr.takeError();
+    uint32_t Flags = *SymFlagsOrErr;
+
+    // Skip undefined, non global and ST_File
+    if (Flags & object::SymbolRef::SF_Undefined)
+      continue;
+    if (!(Flags & object::SymbolRef::SF_Global))
+      continue;
+
+    auto SymbolType = Sym.getType();
+    if (!SymbolType)
+      return SymbolType.takeError();
+
+    if (*SymbolType == object::SymbolRef::ST_File)
+      continue;
+
+    auto Name = Sym.getName();
+    if (!Name)
+      return Name.takeError();
+    auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
+    if (!SymFlags)
+      return SymFlags.takeError();
+
+    // TODO: Global symbols should have default visibility for now
+    *SymFlags |= JITSymbolFlags::Exported;
+
+    I.SymbolFlags[ES.intern(std::move(*Name))] = std::move(*SymFlags);
+  }
+  // TODO: Implement init sections
+  return I;
+}
+
 Expected<MaterializationUnit::Interface>
 getGenericObjectFileSymbolInfo(ExecutionSession &ES,
                                const object::ObjectFile &Obj) {
@@ -280,6 +323,8 @@ getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
     return getELFObjectFileSymbolInfo(ES, *ELFObj);
   else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get()))
     return getCOFFObjectFileSymbolInfo(ES, *COFFObj);
+  else if (auto *XCOFFObj = dyn_cast<object::XCOFFObjectFile>(Obj->get()))
+    return getXCOFFObjectFileSymbolInfo(ES, *XCOFFObj);
 
   return getGenericObjectFileSymbolInfo(ES, **Obj);
 }
diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp
index aef7cc2a78188..5a246438e2c0e 100644
--- a/llvm/lib/Object/XCOFFObjectFile.cpp
+++ b/llvm/lib/Object/XCOFFObjectFile.cpp
@@ -429,13 +429,12 @@ XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
 }
 
 uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
-  // SCUI - Copied from MC/XCOFFObjectWriter.cpp
+  // TODO: Copied from MC/XCOFFObjectWriter.cpp
   // Sections other than DWARF section use DefaultSectionAlign as the default
   // alignment, while DWARF sections have their own alignments. DWARF section
   // alignment is bigger than DefaultSectionAlign.
-  if (isDebugSection(Sec)) {
-    return 8; // SCUI - just a number for now.
-  }
+  if (isDebugSection(Sec))
+    return 8;
   return 4;
 }
 
diff --git a/llvm/test/ExecutionEngine/JITLink/ppc64/XCOFF_ppc64.c b/llvm/test/ExecutionEngine/JITLink/ppc64/XCOFF_ppc64.c
deleted file mode 100644
index 9a2e92de5398a..0000000000000
--- a/llvm/test/ExecutionEngine/JITLink/ppc64/XCOFF_ppc64.c
+++ /dev/null
@@ -1,12 +0,0 @@
-// AIX's support for llvm-mc does not have enough support for directives like .csect
-// so we can't use the tool. llvm-jitlink -check is not available as it requries
-// implementation of registerXCOFFGraphInfo. Will revisit this testcase once support
-// is more complete.
-
-// REQUIRES: target=powerpc64-ibm-aix{{.*}}
-
-// RUN: rm -rf %t && mkdir -p %t
-// RUN: clang --target=powerpc64-ibm-aix -c -O3 -fPIC -o %t/xcoff_ppc64.o %s
-// RUN: llvm-jitlink -triple=powerpc64-ibm-aix %t/xcoff_ppc64.o
-
-int main(void) { return 0; }
diff --git a/llvm/test/ExecutionEngine/JITLink/ppc64/XCOFF_ppc64.ll b/llvm/test/ExecutionEngine/JITLink/ppc64/XCOFF_ppc64.ll
new file mode 100644
index 0000000000000..659b0a8959e73
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/ppc64/XCOFF_ppc64.ll
@@ -0,0 +1,24 @@
+; AIX's support for llvm-mc does not have enough support for directives like .csect
+; so we can't use the tool. llvm-jitlink -check is not available as it requries
+; implementation of registerXCOFFGraphInfo. Will revisit this testcase once support
+; is more complete.
+
+; RUN: mkdir -p %t
+; RUN: llc --filetype=obj -o %t/xcoff_ppc64.o %s 
+; RUN: llvm-jitlink -noexec -num-threads=0 -triple=powerpc64-ibm-aix %t/xcoff_ppc64.o
+
+target datalayout = "E-m:a-Fi64-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512"
+target triple = "powerpc64-ibm-aix"
+
+define i32 @main() #0 {
+entry:
+  ret i32 0
+}
+
+attributes #0 = { "target-cpu"="pwr7" }
+
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 8, !"PIC Level", i32 2}
+

>From c11b61478b1b65344b81e5a974021c0fc68e4bc4 Mon Sep 17 00:00:00 2001
From: Henry Jiang <henry.jiang1 at ibm.com>
Date: Tue, 25 Feb 2025 00:00:45 -0500
Subject: [PATCH 5/5] fix clang-format

---
 llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.h
index c182cb129097d..c6481170637c2 100644
--- a/llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.h
+++ b/llvm/lib/ExecutionEngine/JITLink/XCOFFLinkGraphBuilder.h
@@ -45,10 +45,10 @@ class XCOFFLinkGraphBuilder {
   const object::XCOFFObjectFile &Obj;
   std::unique_ptr<LinkGraph> G;
 
-  Section* UndefSection;
+  Section *UndefSection;
 
   struct SectionEntry {
-    jitlink::Section* Section;
+    jitlink::Section *Section;
     object::SectionRef SectionData;
   };
 



More information about the llvm-commits mailing list