[clang] [llvm] PPC: Read the ELF ABI from the "target-abi" module flag (PR #221669)

via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 7 00:56:33 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-powerpc

Author: Matt Arsenault (arsenm)

<details>
<summary>Changes</summary>

Resolve the ELFv2 ABI from the effective ABI name module flag,
rather than strictly relying on the -target-abi flag.

Also start emitting "target-abi" for PPC from clang.

Co-authored-by: Claude (Claude-Opus-4.8) <noreply@<!-- -->anthropic.com>

---
Full diff: https://github.com/llvm/llvm-project/pull/221669.diff


11 Files Affected:

- (modified) clang/lib/CodeGen/CodeGenModule.cpp (+2-1) 
- (modified) clang/test/CodeGen/stack-protector-guard.c (+1-1) 
- (modified) llvm/lib/Target/PowerPC/PPC.h (+4) 
- (modified) llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp (+2-1) 
- (modified) llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp (+1-1) 
- (modified) llvm/lib/Target/PowerPC/PPCSubtarget.cpp (+5-3) 
- (modified) llvm/lib/Target/PowerPC/PPCSubtarget.h (+4-1) 
- (modified) llvm/lib/Target/PowerPC/PPCTargetMachine.cpp (+18-17) 
- (modified) llvm/lib/Target/PowerPC/PPCTargetMachine.h (+4-3) 
- (modified) llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp (+1-2) 
- (added) llvm/test/CodeGen/PowerPC/target-abi-module-flag.ll (+37) 


``````````diff
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 8890d2a4b1b7e..cbf64364b3a38 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1490,7 +1490,8 @@ void CodeGenModule::Release() {
   // Other targets have no apparent need for the ABI name, but set a non-empty
   // value.
   if (StringRef ABIStr = Target.getABI();
-      !ABIStr.empty() && (T.isARM() || T.isThumb() || T.isRISCV())) {
+      !ABIStr.empty() &&
+      (T.isARM() || T.isThumb() || T.isRISCV() || T.isPPC())) {
     getModule().addModuleFlag(llvm::Module::Error, "target-abi",
                               llvm::MDString::get(VMContext, ABIStr));
   }
diff --git a/clang/test/CodeGen/stack-protector-guard.c b/clang/test/CodeGen/stack-protector-guard.c
index 5438671483aff..e90b2070f630f 100644
--- a/clang/test/CodeGen/stack-protector-guard.c
+++ b/clang/test/CodeGen/stack-protector-guard.c
@@ -67,7 +67,7 @@ void bar(int x) {
 // RISCV: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"tp"}
 // RISCV: [[ATTR3]] = !{i32 1, !"stack-protector-guard-offset", i32 44}
 
-// POWERPC64: !llvm.module.flags = !{[[ATTR1:![0-9]+]], [[ATTR2:![0-9]+]], [[ATTR3:![0-9]+]]}
+// POWERPC64: !llvm.module.flags = !{{{.*}}[[ATTR1:![0-9]+]], [[ATTR2:![0-9]+]], [[ATTR3:![0-9]+]]}
 // POWERPC64: [[ATTR1]] = !{i32 1, !"stack-protector-guard", !"tls"}
 // POWERPC64: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"r13"}
 // POWERPC64: [[ATTR3]] = !{i32 1, !"stack-protector-guard-offset", i32 52}
diff --git a/llvm/lib/Target/PowerPC/PPC.h b/llvm/lib/Target/PowerPC/PPC.h
index cf60a23aa5b4a..7fe80d5ba52f3 100644
--- a/llvm/lib/Target/PowerPC/PPC.h
+++ b/llvm/lib/Target/PowerPC/PPC.h
@@ -97,6 +97,10 @@ class ModulePass;
   InstructionSelector *
   createPPCInstructionSelector(const PPCTargetMachine &, const PPCSubtarget &,
                                const PPCRegisterBankInfo &);
+
+  /// The PowerPC ABI variant.
+  enum PPCABI { PPC_ABI_UNKNOWN, PPC_ABI_ELFv1, PPC_ABI_ELFv2 };
+
   namespace PPCII {
 
   /// Target Operand Flag enum.
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index f4b7a7d701e65..e78eb5239871f 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -1941,7 +1941,8 @@ void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) {
 }
 
 void PPCLinuxAsmPrinter::emitStartOfAsmFile(Module &M) {
-  if (static_cast<const PPCTargetMachine &>(TM).isELFv2ABI()) {
+  if (PPCTargetMachine::computeABI(M.getTargetTriple(),
+                                   TM.getTargetABIName(M)) == PPC_ABI_ELFv2) {
     PPCTargetStreamer *TS =
       static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
     TS->emitAbiVersion(2);
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
index 1f6c9e4c4a7a8..ea96394f97ff3 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
@@ -687,7 +687,7 @@ PPCRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
     // For Power9 we allow the user to enable GPR to vector spills.
     // FIXME: Currently limited to spilling GP8RC. A follow on patch will add
     // support to spill GPRC.
-    if (TM.isELFv2ABI() || Subtarget.isAIXABI()) {
+    if (Subtarget.isELFv2ABI() || Subtarget.isAIXABI()) {
       if (Subtarget.hasP9Vector() && EnableGPRToVecSpills &&
           RC == &PPC::G8RCRegClass) {
         InflateGP8RC++;
diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp
index 1641e335159a7..2dfb67ff4c33d 100644
--- a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp
+++ b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp
@@ -52,8 +52,10 @@ PPCSubtarget &PPCSubtarget::initializeSubtargetDependencies(StringRef CPU,
 }
 
 PPCSubtarget::PPCSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,
-                           StringRef FS, const PPCTargetMachine &TM)
-    : PPCGenSubtargetInfo(TT, CPU, TuneCPU, FS), TM(TM),
+                           StringRef FS, StringRef ABIName,
+                           const PPCTargetMachine &TM)
+    : PPCGenSubtargetInfo(TT, CPU, TuneCPU, FS),
+      TargetABI(PPCTargetMachine::computeABI(TT, ABIName)), TM(TM),
       FrameLowering(initializeSubtargetDependencies(CPU, TuneCPU, FS)),
       InstrInfo(*this), TLInfo(TM, *this) {
   TSInfo = std::make_unique<PPCSelectionDAGInfo>();
@@ -247,7 +249,7 @@ CodeModel::Model PPCSubtarget::getCodeModel(const TargetMachine &TM,
   return ModuleModel;
 }
 
-bool PPCSubtarget::isELFv2ABI() const { return TM.isELFv2ABI(); }
+bool PPCSubtarget::isELFv2ABI() const { return TargetABI == PPC_ABI_ELFv2; }
 
 bool PPCSubtarget::isUsingPCRelativeCalls() const {
   return isPPC64() && hasPCRelativeMemops() && isELFv2ABI() &&
diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.h b/llvm/lib/Target/PowerPC/PPCSubtarget.h
index eec0e141debd4..f303a3e7ee217 100644
--- a/llvm/lib/Target/PowerPC/PPCSubtarget.h
+++ b/llvm/lib/Target/PowerPC/PPCSubtarget.h
@@ -94,6 +94,9 @@ class PPCSubtarget : public PPCGenSubtargetInfo {
 
   bool IsLittleEndian;
 
+  /// The selected ABI variant.
+  PPCABI TargetABI = PPC_ABI_UNKNOWN;
+
   POPCNTDKind HasPOPCNTD;
 
   const PPCTargetMachine &TM;
@@ -115,7 +118,7 @@ class PPCSubtarget : public PPCGenSubtargetInfo {
   /// of the specified triple.
   ///
   PPCSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS,
-               const PPCTargetMachine &TM);
+               StringRef ABIName, const PPCTargetMachine &TM);
 
   ~PPCSubtarget() override;
 
diff --git a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp
index 0778da6cdab41..47358a39b6fb4 100644
--- a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp
+++ b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp
@@ -192,26 +192,23 @@ static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
   return std::make_unique<PPC64LinuxTargetObjectFile>();
 }
 
-static PPCTargetMachine::PPCABI computeTargetABI(const Triple &TT,
-                                                 const TargetOptions &Options) {
-  if (Options.MCOptions.getABIName().starts_with("elfv1"))
-    return PPCTargetMachine::PPC_ABI_ELFv1;
-  else if (Options.MCOptions.getABIName().starts_with("elfv2"))
-    return PPCTargetMachine::PPC_ABI_ELFv2;
+// An explicit ABI name takes precedence; otherwise use the triple default.
+PPCABI PPCTargetMachine::computeABI(const Triple &TT, StringRef ABIName) {
+  if (ABIName.starts_with("elfv1"))
+    return PPC_ABI_ELFv1;
+  if (ABIName.starts_with("elfv2"))
+    return PPC_ABI_ELFv2;
 
-  assert(Options.MCOptions.getABIName().empty() &&
-         "Unknown target-abi option!");
+  if (TT.isOSAIX())
+    return PPC_ABI_UNKNOWN;
 
   switch (TT.getArch()) {
   case Triple::ppc64le:
-    return PPCTargetMachine::PPC_ABI_ELFv2;
+    return PPC_ABI_ELFv2;
   case Triple::ppc64:
-    if (TT.isPPC64ELFv2ABI())
-      return PPCTargetMachine::PPC_ABI_ELFv2;
-    else
-      return PPCTargetMachine::PPC_ABI_ELFv1;
+    return TT.isPPC64ELFv2ABI() ? PPC_ABI_ELFv2 : PPC_ABI_ELFv1;
   default:
-    return PPCTargetMachine::PPC_ABI_UNKNOWN;
+    return PPC_ABI_UNKNOWN;
   }
 }
 
@@ -306,7 +303,6 @@ PPCTargetMachine::PPCTargetMachine(const Target &T, const Triple &TT,
                                getEffectiveRelocModel(TT, RM),
                                getEffectivePPCCodeModel(TT, CM, JIT), OL),
       TLOF(createTLOF(getTargetTriple())),
-      TargetABI(computeTargetABI(TT, Options)),
       Endianness(TT.isLittleEndian() ? Endian::LITTLE : Endian::BIG) {
   initAsmInfo();
 }
@@ -337,7 +333,11 @@ PPCTargetMachine::getSubtargetImpl(const Function &F) const {
   if (SoftFloat)
     FS += FS.empty() ? "-hard-float" : ",-hard-float";
 
-  auto &I = SubtargetMap[CPU + TuneCPU + FS];
+  // Prefer the "target-abi" module flag, falling back to the -target-abi
+  // option.
+  StringRef ABIName = getTargetABIName(*F.getParent());
+
+  auto &I = SubtargetMap[CPU + TuneCPU + FS + ABIName.str()];
   if (!I) {
     I = std::make_unique<PPCSubtarget>(
         TargetTriple, CPU, TuneCPU,
@@ -347,7 +347,8 @@ PPCTargetMachine::getSubtargetImpl(const Function &F) const {
         // shouldn't require adding them. Fixing this means pulling Feature64Bit
         // out of most of the target cpus in the .td file and making it set only
         // as part of initialization via the TargetTriple.
-        computeFSAdditions(FS, getOptLevel(), getTargetTriple()), *this);
+        computeFSAdditions(FS, getOptLevel(), getTargetTriple()), ABIName,
+        *this);
   }
   return I.get();
 }
diff --git a/llvm/lib/Target/PowerPC/PPCTargetMachine.h b/llvm/lib/Target/PowerPC/PPCTargetMachine.h
index cb02b446fadb3..660f47b355648 100644
--- a/llvm/lib/Target/PowerPC/PPCTargetMachine.h
+++ b/llvm/lib/Target/PowerPC/PPCTargetMachine.h
@@ -25,12 +25,10 @@ namespace llvm {
 ///
 class PPCTargetMachine final : public CodeGenTargetMachineImpl {
 public:
-  enum PPCABI { PPC_ABI_UNKNOWN, PPC_ABI_ELFv1, PPC_ABI_ELFv2 };
   enum Endian { NOT_DETECTED, LITTLE, BIG };
 
 private:
   std::unique_ptr<TargetLoweringObjectFile> TLOF;
-  PPCABI TargetABI;
   Endian Endianness = Endian::NOT_DETECTED;
   mutable bool HasGlibcHWCAPAccess = false;
 
@@ -68,7 +66,10 @@ class PPCTargetMachine final : public CodeGenTargetMachineImpl {
   ScheduleDAGInstrs *
   createPostMachineScheduler(MachineSchedContext *C) const override;
 
-  bool isELFv2ABI() const { return TargetABI == PPC_ABI_ELFv2; }
+  /// Compute the ABI variant for \p TT and \p ABIName (the "target-abi" module
+  /// flag), falling back to the triple default.
+  static PPCABI computeABI(const Triple &TT, StringRef ABIName);
+
   bool hasGlibcHWCAPAccess() const { return HasGlibcHWCAPAccess; }
   void setGlibcHWCAPAccess(bool Val = true) const { HasGlibcHWCAPAccess = Val; }
   bool isPPC64() const {
diff --git a/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp b/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp
index 32a7f3701f9f2..3b2c5b06e0cfa 100644
--- a/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp
@@ -983,9 +983,8 @@ bool PPCTTIImpl::isLSRCostLess(const TargetTransformInfo::LSRCost &C1,
 bool PPCTTIImpl::isNumRegsMajorCostOfLSR() const { return false; }
 
 bool PPCTTIImpl::shouldBuildRelLookupTables() const {
-  const PPCTargetMachine &TM = ST->getTargetMachine();
   // XCOFF hasn't implemented lowerRelativeReference, disable non-ELF for now.
-  if (!TM.isELFv2ABI())
+  if (!ST->isELFv2ABI())
     return false;
   return BaseT::shouldBuildRelLookupTables();
 }
diff --git a/llvm/test/CodeGen/PowerPC/target-abi-module-flag.ll b/llvm/test/CodeGen/PowerPC/target-abi-module-flag.ll
new file mode 100644
index 0000000000000..b2b778f0e25e4
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/target-abi-module-flag.ll
@@ -0,0 +1,37 @@
+; Check that the "target-abi" module flag selects the PPC ELF ABI, so the ABI
+; is taken from the IR when no -target-abi option is given. The flag overrides
+; the triple default in both directions (.abiversion 2 is emitted for ELFv2).
+
+; RUN: split-file %s %t
+
+; powerpc64 big-endian defaults to ELFv1; an elfv2 module flag overrides that.
+; RUN: llc -mtriple=powerpc64-unknown-linux < %t/elfv2.ll | FileCheck %s --check-prefix=ELFv2
+
+; powerpc64le defaults to ELFv2; an elfv1 module flag overrides that.
+; RUN: llc -mtriple=powerpc64le-unknown-linux < %t/elfv1.ll | FileCheck %s --check-prefix=ELFv1
+
+; A matching -target-abi option is accepted.
+; RUN: llc -mtriple=powerpc64-unknown-linux -target-abi elfv2 < %t/elfv2.ll | FileCheck %s --check-prefix=ELFv2
+
+; A conflicting -target-abi option is rejected.
+; RUN: not llc -mtriple=powerpc64-unknown-linux -target-abi elfv1 < %t/elfv2.ll 2>&1 | FileCheck %s --check-prefix=CONFLICT
+
+; ELFv2: .abiversion 2
+; ELFv1-NOT: .abiversion 2
+; CONFLICT: -target-abi option != target-abi module flag
+
+;--- elfv1.ll
+define void @f() {
+  ret void
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"target-abi", !"elfv1"}
+
+;--- elfv2.ll
+define void @g() {
+  ret void
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"target-abi", !"elfv2"}

``````````

</details>


https://github.com/llvm/llvm-project/pull/221669


More information about the cfe-commits mailing list