[llvm] [PowerPC] Add assembly directives to change endianness (PR #149811)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 21 06:11:38 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-powerpc

Author: None (DanilaZhebryakov)

<details>
<summary>Changes</summary>

Add simple assembly directives to change endianness of the code being assembled. This is useful in some edge cases to write code involving different endian modes.
Relocations in 'non-native' endian don't work.

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


5 Files Affected:

- (modified) llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp (+11-1) 
- (modified) llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h (+2) 
- (modified) llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp (+22) 
- (modified) llvm/lib/Target/PowerPC/MCTargetDesc/PPCTargetStreamer.h (+1) 
- (added) llvm/test/MC/PowerPC/endian-directive.s (+10) 


``````````diff
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 58766b16e86fe..17877954758be 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -1655,7 +1655,17 @@ bool PPCAsmParser::ParseDirective(AsmToken DirectiveID) {
     parseDirectiveTC(isPPC64() ? 8 : 4, DirectiveID);
   else if (IDVal == ".machine")
     parseDirectiveMachine(DirectiveID.getLoc());
-  else if (IDVal == ".abiversion")
+  else if (IDVal == ".big") {
+    PPCTargetStreamer *TStreamer = static_cast<PPCTargetStreamer *>(
+        getParser().getStreamer().getTargetStreamer());
+    if (TStreamer != nullptr)
+      TStreamer->emitEndianSet(false);
+  } else if (IDVal == ".little") {
+    PPCTargetStreamer *TStreamer = static_cast<PPCTargetStreamer *>(
+        getParser().getStreamer().getTargetStreamer());
+    if (TStreamer != nullptr)
+      TStreamer->emitEndianSet(true);
+  } else if (IDVal == ".abiversion")
     parseDirectiveAbiVersion(DirectiveID.getLoc());
   else if (IDVal == ".localentry")
     parseDirectiveLocalEntry(DirectiveID.getLoc());
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h
index b574557183194..a24b061eead8c 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h
@@ -125,6 +125,8 @@ class PPCMCCodeEmitter : public MCCodeEmitter {
   /// Check if Opcode corresponds to a call instruction that should be marked
   /// with the NOTOC relocation.
   bool isNoTOCCallInstr(const MCInst &MI) const;
+
+  void setLittleEndian(bool little_endian) { IsLittleEndian = little_endian; }
 };
 
 } // namespace llvm
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
index 54497d9c2fedf..68cc96c58e122 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
@@ -15,6 +15,7 @@
 #include "MCTargetDesc/PPCMCAsmInfo.h"
 #include "PPCELFStreamer.h"
 #include "PPCMCAsmInfo.h"
+#include "PPCMCCodeEmitter.h"
 #include "PPCTargetStreamer.h"
 #include "PPCXCOFFStreamer.h"
 #include "TargetInfo/PowerPCTargetInfo.h"
@@ -246,6 +247,10 @@ class PPCTargetAsmStreamer : public PPCTargetStreamer {
       OS << "\t.machine " << CPU << '\n';
   }
 
+  void emitEndianSet(bool little) override {
+    OS << (little ? "\t.little\n" : "\t.big\n");
+  }
+
   void emitAbiVersion(int AbiVersion) override {
     OS << "\t.abiversion " << AbiVersion << '\n';
   }
@@ -280,6 +285,13 @@ class PPCTargetELFStreamer : public PPCTargetStreamer {
     // limit the parser?
   }
 
+  void emitEndianSet(bool little) override {
+    PPCMCCodeEmitter *emitter = static_cast<PPCMCCodeEmitter *>(
+        getStreamer().getAssembler().getEmitterPtr());
+    if (emitter != nullptr)
+      emitter->setLittleEndian(little);
+  }
+
   void emitAbiVersion(int AbiVersion) override {
     ELFObjectWriter &W = getStreamer().getWriter();
     unsigned Flags = W.getELFHeaderEFlags();
@@ -408,6 +420,16 @@ class PPCTargetXCOFFStreamer : public PPCTargetStreamer {
         .setCPU(CPU);
   }
 
+  void emitEndianSet(bool little) override {
+    MCAssembler *assembler = getStreamer().getAssemblerPtr();
+    if (assembler == nullptr)
+      return;
+    PPCMCCodeEmitter *emitter =
+        static_cast<PPCMCCodeEmitter *>(assembler->getEmitterPtr());
+    if (emitter != nullptr)
+      emitter->setLittleEndian(little);
+  }
+
   void emitAbiVersion(int AbiVersion) override {
     llvm_unreachable("ABI-version pseudo-ops are invalid for XCOFF.");
   }
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCTargetStreamer.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCTargetStreamer.h
index 3da034d4909ff..9c8d50a300a2a 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCTargetStreamer.h
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCTargetStreamer.h
@@ -27,6 +27,7 @@ class PPCTargetStreamer : public MCTargetStreamer {
 
   virtual void emitTCEntry(const MCSymbol &S, PPCMCExpr::Specifier Kind) {}
   virtual void emitMachine(StringRef CPU){};
+  virtual void emitEndianSet(bool little) {};
   virtual void emitAbiVersion(int AbiVersion){};
   virtual void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset){};
 };
diff --git a/llvm/test/MC/PowerPC/endian-directive.s b/llvm/test/MC/PowerPC/endian-directive.s
new file mode 100644
index 0000000000000..69e225135f662
--- /dev/null
+++ b/llvm/test/MC/PowerPC/endian-directive.s
@@ -0,0 +1,10 @@
+# RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-linux-gnu %s | llvm-readobj -x .text - | FileCheck -check-prefix=CHECK-BE %s
+# RUN: llvm-mc -filetype=obj -triple=ppc32le-unknown-linux-gnu %s | llvm-readobj -x .text - | FileCheck -check-prefix=CHECK-LE %s
+add %r0, %r1, %r2
+.big
+add %r0, %r1, %r2
+.little
+add %r0, %r1, %r2
+
+# CHECK-BE: 0x00000000 7c011214 7c011214 1412017c          |...|......|
+# CHECK-LE: 0x00000000 1412017c 7c011214 1412017c          ...||......|

``````````

</details>


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


More information about the llvm-commits mailing list