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

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 21 06:10:48 PDT 2025


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

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.

>From 82cdd9692615f52c77eeb0cbb593f17384557003 Mon Sep 17 00:00:00 2001
From: Danila Zhebryakov <d.zhebryakov at yandex.ru>
Date: Mon, 21 Jul 2025 15:58:10 +0300
Subject: [PATCH] [PowerPC] Add assembly directives to change endianness

---
 .../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 12 +++++++++-
 .../PowerPC/MCTargetDesc/PPCMCCodeEmitter.h   |  2 ++
 .../PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp  | 22 +++++++++++++++++++
 .../PowerPC/MCTargetDesc/PPCTargetStreamer.h  |  1 +
 llvm/test/MC/PowerPC/endian-directive.s       | 10 +++++++++
 5 files changed, 46 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/MC/PowerPC/endian-directive.s

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          ...||......|



More information about the llvm-commits mailing list