[llvm] [AMDGPU] Tolerate AMDGPUTargetELFStreamer without initializeTargetID (PR #226495)

Tim Renouf via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 25 07:01:44 PDT 2026


https://github.com/trenouf updated https://github.com/llvm/llvm-project/pull/226495

>From d0b0377a6753fd6f3fa21c0f9d401437ee7af342 Mon Sep 17 00:00:00 2001
From: Tim Renouf <tim.renouf at amd.com>
Date: Fri, 25 Sep 2026 09:35:52 +0100
Subject: [PATCH 1/2] [AMDGPU] Tolerate AMDGPUTargetELFStreamer without
 initializeTargetID

Our use case is an out-of-tree compiler component that wants to build a
data-only AMDGPU ELF using the MC layer directly, rather than
constructing IR with a GlobalVariable and running it through the normal
compiler path, to reduce static overheads for such an operation.
---
 .../MCTargetDesc/AMDGPUTargetStreamer.h       | 12 +++
 llvm/unittests/MC/AMDGPU/CMakeLists.txt       |  1 +
 llvm/unittests/MC/AMDGPU/TargetStreamer.cpp   | 75 +++++++++++++++++++
 3 files changed, 88 insertions(+)
 create mode 100644 llvm/unittests/MC/AMDGPU/TargetStreamer.cpp

diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h
index d1ef710e9b1807..a6799d9f690e7e 100644
--- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h
+++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h
@@ -209,6 +209,18 @@ class AMDGPUTargetELFStreamer final : public AMDGPUTargetStreamer {
   unsigned getEFlagsV4();
   unsigned getEFlagsV6();
 
+  // Override of AMDGPUTargetStreamer::getTargetID that tolerates
+  // initializeTargetID not having been called by initializing it here from our
+  // MCSubtargetInfo. This allows the use of AMDGPUTargetELFStreamer in an
+  // out-of-tree compiler component that directly uses the MC layer to generate
+  // a data-only AMDGPU ELF. Such an out-of-tree compiler component has no way
+  // to call initializeTargetID().
+  std::optional<AMDGPU::TargetID> &getTargetID() {
+    if (!TargetID)
+      initializeTargetID(STI);
+    return TargetID;
+  }
+
 public:
   AMDGPUTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI);
 
diff --git a/llvm/unittests/MC/AMDGPU/CMakeLists.txt b/llvm/unittests/MC/AMDGPU/CMakeLists.txt
index 029f814a7d510e..3f12e0874d01c7 100644
--- a/llvm/unittests/MC/AMDGPU/CMakeLists.txt
+++ b/llvm/unittests/MC/AMDGPU/CMakeLists.txt
@@ -17,4 +17,5 @@ set(LLVM_LINK_COMPONENTS
 add_llvm_unittest(AMDGPUMCTests
   Disassembler.cpp
   DwarfRegMappings.cpp
+  TargetStreamer.cpp
   )
diff --git a/llvm/unittests/MC/AMDGPU/TargetStreamer.cpp b/llvm/unittests/MC/AMDGPU/TargetStreamer.cpp
new file mode 100644
index 00000000000000..a8225f5988d191
--- /dev/null
+++ b/llvm/unittests/MC/AMDGPU/TargetStreamer.cpp
@@ -0,0 +1,75 @@
+//===- llvm/unittest/unittests/MC/AMDGPU/TargetStreamer.cpp ---------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/CodeGen.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Target/TargetMachine.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+static constexpr char TripleName[] = "amdgcn--amdpal";
+static constexpr char CPUName[] = "gfx1201";
+
+// Test that we can generate a data-only AMDGPU ELF directly using the MC layer,
+// without asserting due to initializeTargetID() not being called.
+TEST(AMDGPUTargetStreamer, ELFStreamerBasic) {
+  LLVMInitializeAMDGPUTargetInfo();
+  LLVMInitializeAMDGPUTargetMC();
+  LLVMInitializeAMDGPUTarget();
+
+  // Create TargetMachine.
+  std::string errMsg;
+  Triple Trpl(TripleName);
+  const Target *T = TargetRegistry::lookupTarget(Trpl, errMsg);
+  // Skip test if AMDGPU not built.
+  if (!T)
+    GTEST_SKIP();
+  std::unique_ptr<TargetMachine> TM(
+      T->createTargetMachine(Trpl, CPUName, "", {}, {}, {}, {}));
+
+  const MCSubtargetInfo &STI = TM->getMCSubtargetInfo();
+  const MCRegisterInfo &RI = TM->getMCRegisterInfo();
+  const MCAsmInfo &AI = TM->getMCAsmInfo();
+
+  MCContext Context(Trpl, AI, RI, STI);
+  std::unique_ptr<MCObjectFileInfo> ObjectFileInfo(
+      T->createMCObjectFileInfo(Context, /*PIC=*/false));
+  Context.setObjectFileInfo(ObjectFileInfo.get());
+
+  SmallString<256> OutBuffer;
+  raw_svector_ostream Outs(OutBuffer);
+
+  Expected<std::unique_ptr<MCStreamer>> StreamerOr =
+      TM->createMCStreamer(Outs, {}, CodeGenFileType::ObjectFile, Context);
+  if (Error Err = StreamerOr.takeError())
+    report_fatal_error(StringRef(toString(std::move(Err))));
+  std::unique_ptr<MCStreamer> Streamer = std::move(*StreamerOr);
+
+  Streamer->initSections(STI);
+
+  MCSymbol *TableSymbol = Context.getOrCreateSymbol("myData");
+  Streamer->switchSection(ObjectFileInfo->getReadOnlySection());
+  Streamer->emitValueToAlignment(Align(4));
+  Streamer->emitSymbolAttribute(TableSymbol, MCSA_Global);
+  Streamer->emitSymbolAttribute(TableSymbol, MCSA_ELF_TypeObject);
+  Streamer->emitLabel(TableSymbol);
+
+  StringRef DataBlob = "hatstand";
+  Streamer->emitBytes(DataBlob);
+  Streamer->emitELFSize(TableSymbol,
+                        MCConstantExpr::create(DataBlob.size(), Context));
+  Streamer->finish();
+
+  EXPECT_NE(OutBuffer.size(), 0U);
+}

>From 2b4a56db25d8165dc304b7177ce31a847ea2457c Mon Sep 17 00:00:00 2001
From: Tim Renouf <tim.renouf at amd.com>
Date: Fri, 25 Sep 2026 15:01:04 +0100
Subject: [PATCH 2/2] Fix old triple and report_fatal_error

---
 llvm/unittests/MC/AMDGPU/TargetStreamer.cpp | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/llvm/unittests/MC/AMDGPU/TargetStreamer.cpp b/llvm/unittests/MC/AMDGPU/TargetStreamer.cpp
index a8225f5988d191..c31570059916be 100644
--- a/llvm/unittests/MC/AMDGPU/TargetStreamer.cpp
+++ b/llvm/unittests/MC/AMDGPU/TargetStreamer.cpp
@@ -18,8 +18,7 @@
 
 using namespace llvm;
 
-static constexpr char TripleName[] = "amdgcn--amdpal";
-static constexpr char CPUName[] = "gfx1201";
+static constexpr char TripleName[] = "amdgpu12.01--amdpal";
 
 // Test that we can generate a data-only AMDGPU ELF directly using the MC layer,
 // without asserting due to initializeTargetID() not being called.
@@ -36,7 +35,7 @@ TEST(AMDGPUTargetStreamer, ELFStreamerBasic) {
   if (!T)
     GTEST_SKIP();
   std::unique_ptr<TargetMachine> TM(
-      T->createTargetMachine(Trpl, CPUName, "", {}, {}, {}, {}));
+      T->createTargetMachine(Trpl, "", "", {}, {}, {}, {}));
 
   const MCSubtargetInfo &STI = TM->getMCSubtargetInfo();
   const MCRegisterInfo &RI = TM->getMCRegisterInfo();
@@ -53,7 +52,7 @@ TEST(AMDGPUTargetStreamer, ELFStreamerBasic) {
   Expected<std::unique_ptr<MCStreamer>> StreamerOr =
       TM->createMCStreamer(Outs, {}, CodeGenFileType::ObjectFile, Context);
   if (Error Err = StreamerOr.takeError())
-    report_fatal_error(StringRef(toString(std::move(Err))));
+    reportFatalUsageError(std::move(Err));
   std::unique_ptr<MCStreamer> Streamer = std::move(*StreamerOr);
 
   Streamer->initSections(STI);



More information about the llvm-commits mailing list