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( + getParser().getStreamer().getTargetStreamer()); + if (TStreamer != nullptr) + TStreamer->emitEndianSet(false); + } else if (IDVal == ".little") { + PPCTargetStreamer *TStreamer = static_cast( + 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( + 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(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 ...||......|