[llvm] [SPARC][IAS] Add v8plus feature bit (PR #101367)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 1 05:07:37 PDT 2024


https://github.com/koachan updated https://github.com/llvm/llvm-project/pull/101367

>From ec0450f45e1bf3a78088cfd9eea1f665ee4ec6a7 Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Wed, 31 Jul 2024 23:36:23 +0700
Subject: [PATCH 1/2] [SPARC] Add v8plus feature bit

Implement handling for `v8plus` feature bit to allow the user to switch
between V8 and V8+ mode with 32-bit code.

This is done as a prerequisite for `-mv8plus` flag on clang (#98713).
---
 .../Sparc/MCTargetDesc/SparcAsmBackend.cpp      |  4 +++-
 .../Sparc/MCTargetDesc/SparcELFObjectWriter.cpp | 17 ++++++++++++-----
 .../Sparc/MCTargetDesc/SparcMCTargetDesc.h      |  6 ++++--
 llvm/lib/Target/Sparc/Sparc.td                  |  3 +++
 llvm/test/MC/Sparc/elf-sparc-machine-type.s     |  9 +++++----
 5 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
index 29282582b82bd..c2f9111375f41 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
@@ -132,6 +132,7 @@ namespace {
   class SparcAsmBackend : public MCAsmBackend {
   protected:
     bool Is64Bit;
+    bool IsV8Plus;
     bool HasV9;
 
   public:
@@ -140,6 +141,7 @@ namespace {
                            ? llvm::endianness::little
                            : llvm::endianness::big),
           Is64Bit(STI.getTargetTriple().isArch64Bit()),
+          IsV8Plus(STI.hasFeature(Sparc::FeatureV8Plus)),
           HasV9(STI.hasFeature(Sparc::FeatureV9)) {}
 
     unsigned getNumFixupKinds() const override {
@@ -359,7 +361,7 @@ namespace {
     std::unique_ptr<MCObjectTargetWriter>
     createObjectTargetWriter() const override {
       uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType);
-      return createSparcELFObjectWriter(Is64Bit, HasV9, OSABI);
+      return createSparcELFObjectWriter(Is64Bit, IsV8Plus, HasV9, OSABI);
     }
   };
 
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
index bfd71af736231..87c914326fdbf 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
@@ -21,11 +21,16 @@ using namespace llvm;
 namespace {
   class SparcELFObjectWriter : public MCELFObjectTargetWriter {
   public:
-    SparcELFObjectWriter(bool Is64Bit, bool HasV9, uint8_t OSABI)
+    SparcELFObjectWriter(bool Is64Bit, bool IsV8Plus, bool HasV9, uint8_t OSABI)
         : MCELFObjectTargetWriter(
               Is64Bit, OSABI,
-              Is64Bit ? ELF::EM_SPARCV9
-                      : (HasV9 ? ELF::EM_SPARC32PLUS : ELF::EM_SPARC),
+              Is64Bit
+                  ? ELF::EM_SPARCV9
+                  // Note that we still need to emit an EM_SPARC32PLUS object
+                  // even when V8+ isn't explicitly requested, if we're
+                  // targeting a V9-capable CPU. This matches GAS behavior upon
+                  // encountering any V9 instructions in its input.
+                  : ((IsV8Plus || HasV9) ? ELF::EM_SPARC32PLUS : ELF::EM_SPARC),
               /*HasRelocationAddend*/ true) {}
 
     ~SparcELFObjectWriter() override = default;
@@ -148,6 +153,8 @@ bool SparcELFObjectWriter::needsRelocateWithSymbol(const MCValue &,
 }
 
 std::unique_ptr<MCObjectTargetWriter>
-llvm::createSparcELFObjectWriter(bool Is64Bit, bool HasV9, uint8_t OSABI) {
-  return std::make_unique<SparcELFObjectWriter>(Is64Bit, HasV9, OSABI);
+llvm::createSparcELFObjectWriter(bool Is64Bit, bool IsV8Plus, bool HasV9,
+                                 uint8_t OSABI) {
+  return std::make_unique<SparcELFObjectWriter>(Is64Bit, IsV8Plus, HasV9,
+                                                OSABI);
 }
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
index 63419663b722c..4d195c5130c48 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
@@ -34,8 +34,10 @@ MCCodeEmitter *createSparcMCCodeEmitter(const MCInstrInfo &MCII,
 MCAsmBackend *createSparcAsmBackend(const Target &T, const MCSubtargetInfo &STI,
                                     const MCRegisterInfo &MRI,
                                     const MCTargetOptions &Options);
-std::unique_ptr<MCObjectTargetWriter>
-createSparcELFObjectWriter(bool Is64Bit, bool HasV9, uint8_t OSABI);
+std::unique_ptr<MCObjectTargetWriter> createSparcELFObjectWriter(bool Is64Bit,
+                                                                 bool IsV8Plus,
+                                                                 bool HasV9,
+                                                                 uint8_t OSABI);
 
 // Defines symbolic names for Sparc v9 ASI tag names.
 namespace SparcASITag {
diff --git a/llvm/lib/Target/Sparc/Sparc.td b/llvm/lib/Target/Sparc/Sparc.td
index 65f372f4376b1..8b1122741b661 100644
--- a/llvm/lib/Target/Sparc/Sparc.td
+++ b/llvm/lib/Target/Sparc/Sparc.td
@@ -34,6 +34,9 @@ def FeatureNoFMULS
 def FeatureV9
   : SubtargetFeature<"v9", "IsV9", "true",
                      "Enable SPARC-V9 instructions">;
+def FeatureV8Plus
+  : SubtargetFeature<"v8plus", "IsV8Plus", "true",
+                     "Enable V8+ mode, allowing use of 64-bit V9 instructions in 32-bit code">;
 def FeatureV8Deprecated
   : SubtargetFeature<"deprecated-v8", "UseV8DeprecatedInsts", "true",
                      "Enable deprecated V8 instructions in V9 mode">;
diff --git a/llvm/test/MC/Sparc/elf-sparc-machine-type.s b/llvm/test/MC/Sparc/elf-sparc-machine-type.s
index 630812394560c..a4bd3607e350d 100644
--- a/llvm/test/MC/Sparc/elf-sparc-machine-type.s
+++ b/llvm/test/MC/Sparc/elf-sparc-machine-type.s
@@ -1,11 +1,12 @@
 ## Emit correct machine type depending on triple and cpu options.
 ## - `-triple sparc` emits an object of type EM_SPARC;
-## - `-triple sparc -mcpu=v9` emits EM_SPARC32PLUS; and
+## - `-triple sparc -mcpu=v9` or `-triple sparc -mattr=+v8plus` emits EM_SPARC32PLUS; and
 ## - `-triple sparcv9` emits EM_SPARCV9.
 
-# RUN: llvm-mc -filetype=obj -triple sparc            %s -o - | llvm-readobj -h - | FileCheck --check-prefixes=SPARC       %s
-# RUN: llvm-mc -filetype=obj -triple sparc   -mcpu=v9 %s -o - | llvm-readobj -h - | FileCheck --check-prefixes=SPARC32PLUS %s
-# RUN: llvm-mc -filetype=obj -triple sparcv9          %s -o - | llvm-readobj -h - | FileCheck --check-prefixes=SPARCV9     %s
+# RUN: llvm-mc -filetype=obj -triple sparc                  %s -o - | llvm-readobj -h - | FileCheck --check-prefixes=SPARC       %s
+# RUN: llvm-mc -filetype=obj -triple sparc         -mcpu=v9 %s -o - | llvm-readobj -h - | FileCheck --check-prefixes=SPARC32PLUS %s
+# RUN: llvm-mc -filetype=obj -triple sparc   -mattr=+v8plus %s -o - | llvm-readobj -h - | FileCheck --check-prefixes=SPARC32PLUS %s
+# RUN: llvm-mc -filetype=obj -triple sparcv9                %s -o - | llvm-readobj -h - | FileCheck --check-prefixes=SPARCV9     %s
 
 # SPARC:       Machine: EM_SPARC (0x2)
 # SPARC32PLUS: Machine: EM_SPARC32PLUS (0x12)

>From c1068d5c819cd7f384249b6a5de4e140af1951bc Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Thu, 1 Aug 2024 19:07:13 +0700
Subject: [PATCH 2/2] Only emit EM_SPARC32PLUS objects on explicit request

---
 llvm/include/llvm/BinaryFormat/ELF.h          | 13 ++++++++++
 .../Sparc/MCTargetDesc/SparcAsmBackend.cpp    |  6 ++---
 .../MCTargetDesc/SparcELFObjectWriter.cpp     | 17 ++++---------
 .../Sparc/MCTargetDesc/SparcMCTargetDesc.cpp  |  2 +-
 .../Sparc/MCTargetDesc/SparcMCTargetDesc.h    |  6 ++---
 .../MCTargetDesc/SparcTargetStreamer.cpp      | 25 +++++++++++++++++--
 .../Sparc/MCTargetDesc/SparcTargetStreamer.h  |  2 +-
 llvm/test/MC/Sparc/elf-sparc-machine-type.s   |  3 +--
 8 files changed, 48 insertions(+), 26 deletions(-)

diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 456cffff6b4a7..fb39bb4b10b37 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -697,6 +697,19 @@ enum {
 #include "ELFRelocs/SystemZ.def"
 };
 
+// SPARC Specific e_flags
+enum : unsigned {
+  EF_SPARC_EXT_MASK = 0xffff00,
+  EF_SPARC_32PLUS = 0x000100,
+  EF_SPARC_SUN_US1 = 0x000200,
+  EF_SPARC_HAL_R1 = 0x000400,
+  EF_SPARC_SUN_US3 = 0x000800,
+  EF_SPARCV9_MM = 0x3,
+  EF_SPARCV9_TSO = 0x0,
+  EF_SPARCV9_PSO = 0x1,
+  EF_SPARCV9_RMO = 0x2,
+};
+
 // ELF Relocation type for Sparc.
 enum {
 #include "ELFRelocs/Sparc.def"
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
index c2f9111375f41..66826fadddd2e 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
@@ -133,7 +133,6 @@ namespace {
   protected:
     bool Is64Bit;
     bool IsV8Plus;
-    bool HasV9;
 
   public:
     SparcAsmBackend(const MCSubtargetInfo &STI)
@@ -141,8 +140,7 @@ namespace {
                            ? llvm::endianness::little
                            : llvm::endianness::big),
           Is64Bit(STI.getTargetTriple().isArch64Bit()),
-          IsV8Plus(STI.hasFeature(Sparc::FeatureV8Plus)),
-          HasV9(STI.hasFeature(Sparc::FeatureV9)) {}
+          IsV8Plus(STI.hasFeature(Sparc::FeatureV8Plus)) {}
 
     unsigned getNumFixupKinds() const override {
       return Sparc::NumTargetFixupKinds;
@@ -361,7 +359,7 @@ namespace {
     std::unique_ptr<MCObjectTargetWriter>
     createObjectTargetWriter() const override {
       uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType);
-      return createSparcELFObjectWriter(Is64Bit, IsV8Plus, HasV9, OSABI);
+      return createSparcELFObjectWriter(Is64Bit, IsV8Plus, OSABI);
     }
   };
 
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
index 87c914326fdbf..601199d7170a7 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
@@ -21,16 +21,11 @@ using namespace llvm;
 namespace {
   class SparcELFObjectWriter : public MCELFObjectTargetWriter {
   public:
-    SparcELFObjectWriter(bool Is64Bit, bool IsV8Plus, bool HasV9, uint8_t OSABI)
+    SparcELFObjectWriter(bool Is64Bit, bool IsV8Plus, uint8_t OSABI)
         : MCELFObjectTargetWriter(
               Is64Bit, OSABI,
-              Is64Bit
-                  ? ELF::EM_SPARCV9
-                  // Note that we still need to emit an EM_SPARC32PLUS object
-                  // even when V8+ isn't explicitly requested, if we're
-                  // targeting a V9-capable CPU. This matches GAS behavior upon
-                  // encountering any V9 instructions in its input.
-                  : ((IsV8Plus || HasV9) ? ELF::EM_SPARC32PLUS : ELF::EM_SPARC),
+              Is64Bit ? ELF::EM_SPARCV9
+                      : (IsV8Plus ? ELF::EM_SPARC32PLUS : ELF::EM_SPARC),
               /*HasRelocationAddend*/ true) {}
 
     ~SparcELFObjectWriter() override = default;
@@ -153,8 +148,6 @@ bool SparcELFObjectWriter::needsRelocateWithSymbol(const MCValue &,
 }
 
 std::unique_ptr<MCObjectTargetWriter>
-llvm::createSparcELFObjectWriter(bool Is64Bit, bool IsV8Plus, bool HasV9,
-                                 uint8_t OSABI) {
-  return std::make_unique<SparcELFObjectWriter>(Is64Bit, IsV8Plus, HasV9,
-                                                OSABI);
+llvm::createSparcELFObjectWriter(bool Is64Bit, bool IsV8Plus, uint8_t OSABI) {
+  return std::make_unique<SparcELFObjectWriter>(Is64Bit, IsV8Plus, OSABI);
 }
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
index ad6ca0911adb9..8561e95f24f38 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
@@ -86,7 +86,7 @@ createSparcMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
 
 static MCTargetStreamer *
 createObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
-  return new SparcTargetELFStreamer(S);
+  return new SparcTargetELFStreamer(S, STI);
 }
 
 static MCTargetStreamer *createTargetAsmStreamer(MCStreamer &S,
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
index 4d195c5130c48..a7b0538d683b6 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
@@ -34,10 +34,8 @@ MCCodeEmitter *createSparcMCCodeEmitter(const MCInstrInfo &MCII,
 MCAsmBackend *createSparcAsmBackend(const Target &T, const MCSubtargetInfo &STI,
                                     const MCRegisterInfo &MRI,
                                     const MCTargetOptions &Options);
-std::unique_ptr<MCObjectTargetWriter> createSparcELFObjectWriter(bool Is64Bit,
-                                                                 bool IsV8Plus,
-                                                                 bool HasV9,
-                                                                 uint8_t OSABI);
+std::unique_ptr<MCObjectTargetWriter>
+createSparcELFObjectWriter(bool Is64Bit, bool IsV8Plus, uint8_t OSABI);
 
 // Defines symbolic names for Sparc v9 ASI tag names.
 namespace SparcASITag {
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp
index d2dcf200aef04..747bdad510e41 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp
@@ -12,11 +12,24 @@
 
 #include "SparcTargetStreamer.h"
 #include "SparcInstPrinter.h"
+#include "SparcMCTargetDesc.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCRegister.h"
+#include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/Support/FormattedStream.h"
 
 using namespace llvm;
 
+static unsigned getEFlagsForFeatureSet(const MCSubtargetInfo &STI) {
+  unsigned EFlags = 0;
+
+  if (STI.hasFeature(Sparc::FeatureV8Plus))
+    EFlags |= ELF::EF_SPARC_32PLUS;
+
+  return EFlags;
+}
+
 // pin vtable to this file
 SparcTargetStreamer::SparcTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
 
@@ -38,8 +51,16 @@ void SparcTargetAsmStreamer::emitSparcRegisterScratch(unsigned reg) {
      << ", #scratch\n";
 }
 
-SparcTargetELFStreamer::SparcTargetELFStreamer(MCStreamer &S)
-    : SparcTargetStreamer(S) {}
+SparcTargetELFStreamer::SparcTargetELFStreamer(MCStreamer &S,
+                                               const MCSubtargetInfo &STI)
+    : SparcTargetStreamer(S) {
+  MCAssembler &MCA = getStreamer().getAssembler();
+  unsigned EFlags = MCA.getELFHeaderEFlags();
+
+  EFlags |= getEFlagsForFeatureSet(STI);
+
+  MCA.setELFHeaderEFlags(EFlags);
+}
 
 MCELFStreamer &SparcTargetELFStreamer::getStreamer() {
   return static_cast<MCELFStreamer &>(Streamer);
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.h b/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.h
index ef28afa06bffb..bd9954ffb687b 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.h
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.h
@@ -40,7 +40,7 @@ class SparcTargetAsmStreamer : public SparcTargetStreamer {
 // This part is for ELF object output
 class SparcTargetELFStreamer : public SparcTargetStreamer {
 public:
-  SparcTargetELFStreamer(MCStreamer &S);
+  SparcTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI);
   MCELFStreamer &getStreamer();
   void emitSparcRegisterIgnore(unsigned reg) override {}
   void emitSparcRegisterScratch(unsigned reg) override {}
diff --git a/llvm/test/MC/Sparc/elf-sparc-machine-type.s b/llvm/test/MC/Sparc/elf-sparc-machine-type.s
index a4bd3607e350d..85edec5dbaea5 100644
--- a/llvm/test/MC/Sparc/elf-sparc-machine-type.s
+++ b/llvm/test/MC/Sparc/elf-sparc-machine-type.s
@@ -1,10 +1,9 @@
 ## Emit correct machine type depending on triple and cpu options.
 ## - `-triple sparc` emits an object of type EM_SPARC;
-## - `-triple sparc -mcpu=v9` or `-triple sparc -mattr=+v8plus` emits EM_SPARC32PLUS; and
+## - `-triple sparc -mattr=+v8plus` emits EM_SPARC32PLUS; and
 ## - `-triple sparcv9` emits EM_SPARCV9.
 
 # RUN: llvm-mc -filetype=obj -triple sparc                  %s -o - | llvm-readobj -h - | FileCheck --check-prefixes=SPARC       %s
-# RUN: llvm-mc -filetype=obj -triple sparc         -mcpu=v9 %s -o - | llvm-readobj -h - | FileCheck --check-prefixes=SPARC32PLUS %s
 # RUN: llvm-mc -filetype=obj -triple sparc   -mattr=+v8plus %s -o - | llvm-readobj -h - | FileCheck --check-prefixes=SPARC32PLUS %s
 # RUN: llvm-mc -filetype=obj -triple sparcv9                %s -o - | llvm-readobj -h - | FileCheck --check-prefixes=SPARCV9     %s
 



More information about the llvm-commits mailing list