[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