[ARM64] Add a big endian version of the ARM64 target machine, and update all users.

This completes the porting of r202024 (cpirker "Add AArch64 big endian Target (aarch64_be)") to ARM64.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206965 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
James Molloy 2014-04-23 10:26:40 +00:00
parent 4231346c8d
commit 57683b8aba
14 changed files with 139 additions and 44 deletions

View File

@ -593,5 +593,6 @@ void ARM64AsmPrinter::EmitInstruction(const MachineInstr *MI) {
// Force static initialization. // Force static initialization.
extern "C" void LLVMInitializeARM64AsmPrinter() { extern "C" void LLVMInitializeARM64AsmPrinter() {
RegisterAsmPrinter<ARM64AsmPrinter> X(TheARM64Target); RegisterAsmPrinter<ARM64AsmPrinter> X(TheARM64leTarget);
RegisterAsmPrinter<ARM64AsmPrinter> Y(TheARM64beTarget);
} }

View File

@ -27,11 +27,11 @@ using namespace llvm;
#include "ARM64GenSubtargetInfo.inc" #include "ARM64GenSubtargetInfo.inc"
ARM64Subtarget::ARM64Subtarget(const std::string &TT, const std::string &CPU, ARM64Subtarget::ARM64Subtarget(const std::string &TT, const std::string &CPU,
const std::string &FS) const std::string &FS, bool LittleEndian)
: ARM64GenSubtargetInfo(TT, CPU, FS), ARMProcFamily(Others), : ARM64GenSubtargetInfo(TT, CPU, FS), ARMProcFamily(Others),
HasFPARMv8(false), HasNEON(false), HasCrypto(false), HasFPARMv8(false), HasNEON(false), HasCrypto(false),
HasZeroCycleRegMove(false), HasZeroCycleZeroing(false), HasZeroCycleRegMove(false), HasZeroCycleZeroing(false),
CPUString(CPU), TargetTriple(TT) { CPUString(CPU), TargetTriple(TT), IsLittleEndian(LittleEndian) {
// Determine default and user-specified characteristics // Determine default and user-specified characteristics
if (CPUString.empty()) if (CPUString.empty())

View File

@ -48,11 +48,14 @@ protected:
/// TargetTriple - What processor and OS we're targeting. /// TargetTriple - What processor and OS we're targeting.
Triple TargetTriple; Triple TargetTriple;
/// IsLittleEndian - Is the target little endian?
bool IsLittleEndian;
public: public:
/// This constructor initializes the data members to match that /// This constructor initializes the data members to match that
/// of the specified triple. /// of the specified triple.
ARM64Subtarget(const std::string &TT, const std::string &CPU, ARM64Subtarget(const std::string &TT, const std::string &CPU,
const std::string &FS); const std::string &FS, bool LittleEndian);
bool enableMachineScheduler() const override { return true; } bool enableMachineScheduler() const override { return true; }
@ -64,6 +67,8 @@ public:
bool hasNEON() const { return HasNEON; } bool hasNEON() const { return HasNEON; }
bool hasCrypto() const { return HasCrypto; } bool hasCrypto() const { return HasCrypto; }
bool isLittleEndian() const { return IsLittleEndian; }
bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); } bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); }
bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); } bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }

View File

@ -49,7 +49,8 @@ EnableDeadRegisterElimination("arm64-dead-def-elimination", cl::Hidden,
extern "C" void LLVMInitializeARM64Target() { extern "C" void LLVMInitializeARM64Target() {
// Register the target. // Register the target.
RegisterTargetMachine<ARM64TargetMachine> X(TheARM64Target); RegisterTargetMachine<ARM64leTargetMachine> X(TheARM64leTarget);
RegisterTargetMachine<ARM64beTargetMachine> Y(TheARM64beTarget);
} }
/// TargetMachine ctor - Create an ARM64 architecture model. /// TargetMachine ctor - Create an ARM64 architecture model.
@ -58,16 +59,40 @@ ARM64TargetMachine::ARM64TargetMachine(const Target &T, StringRef TT,
StringRef CPU, StringRef FS, StringRef CPU, StringRef FS,
const TargetOptions &Options, const TargetOptions &Options,
Reloc::Model RM, CodeModel::Model CM, Reloc::Model RM, CodeModel::Model CM,
CodeGenOpt::Level OL) CodeGenOpt::Level OL,
bool LittleEndian)
: LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
Subtarget(TT, CPU, FS), Subtarget(TT, CPU, FS, LittleEndian),
DL(Subtarget.isTargetMachO() ? "e-m:o-i64:64-i128:128-n32:64-S128" // This nested ternary is horrible, but DL needs to be properly initialized
: "e-m:e-i64:64-i128:128-n32:64-S128"), // before TLInfo is constructed.
DL(Subtarget.isTargetMachO() ?
"e-m:o-i64:64-i128:128-n32:64-S128" :
(LittleEndian ?
"e-m:e-i64:64-i128:128-n32:64-S128" :
"E-m:e-i64:64-i128:128-n32:64-S128")),
InstrInfo(Subtarget), TLInfo(*this), FrameLowering(*this, Subtarget), InstrInfo(Subtarget), TLInfo(*this), FrameLowering(*this, Subtarget),
TSInfo(*this) { TSInfo(*this) {
initAsmInfo(); initAsmInfo();
} }
void ARM64leTargetMachine::anchor() { }
ARM64leTargetMachine::
ARM64leTargetMachine(const Target &T, StringRef TT,
StringRef CPU, StringRef FS, const TargetOptions &Options,
Reloc::Model RM, CodeModel::Model CM,
CodeGenOpt::Level OL)
: ARM64TargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
void ARM64beTargetMachine::anchor() { }
ARM64beTargetMachine::
ARM64beTargetMachine(const Target &T, StringRef TT,
StringRef CPU, StringRef FS, const TargetOptions &Options,
Reloc::Model RM, CodeModel::Model CM,
CodeGenOpt::Level OL)
: ARM64TargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
namespace { namespace {
/// ARM64 Code Generator Pass Configuration Options. /// ARM64 Code Generator Pass Configuration Options.
class ARM64PassConfig : public TargetPassConfig { class ARM64PassConfig : public TargetPassConfig {

View File

@ -39,7 +39,8 @@ private:
public: public:
ARM64TargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS, ARM64TargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS,
const TargetOptions &Options, Reloc::Model RM, const TargetOptions &Options, Reloc::Model RM,
CodeModel::Model CM, CodeGenOpt::Level OL); CodeModel::Model CM, CodeGenOpt::Level OL,
bool IsLittleEndian);
const ARM64Subtarget *getSubtargetImpl() const override { return &Subtarget; } const ARM64Subtarget *getSubtargetImpl() const override { return &Subtarget; }
const ARM64TargetLowering *getTargetLowering() const override { const ARM64TargetLowering *getTargetLowering() const override {
@ -64,6 +65,28 @@ public:
void addAnalysisPasses(PassManagerBase &PM) override; void addAnalysisPasses(PassManagerBase &PM) override;
}; };
// ARM64leTargetMachine - ARM64 little endian target machine.
//
class ARM64leTargetMachine : public ARM64TargetMachine {
virtual void anchor();
public:
ARM64leTargetMachine(const Target &T, StringRef TT,
StringRef CPU, StringRef FS, const TargetOptions &Options,
Reloc::Model RM, CodeModel::Model CM,
CodeGenOpt::Level OL);
};
// ARM64beTargetMachine - ARM64 big endian target machine.
//
class ARM64beTargetMachine : public ARM64TargetMachine {
virtual void anchor();
public:
ARM64beTargetMachine(const Target &T, StringRef TT,
StringRef CPU, StringRef FS, const TargetOptions &Options,
Reloc::Model RM, CodeModel::Model CM,
CodeGenOpt::Level OL);
};
} // end namespace llvm } // end namespace llvm
#endif #endif

View File

@ -4509,7 +4509,8 @@ ARM64AsmParser::classifySymbolRef(const MCExpr *Expr,
/// Force static initialization. /// Force static initialization.
extern "C" void LLVMInitializeARM64AsmParser() { extern "C" void LLVMInitializeARM64AsmParser() {
RegisterMCAsmParser<ARM64AsmParser> X(TheARM64Target); RegisterMCAsmParser<ARM64AsmParser> X(TheARM64leTarget);
RegisterMCAsmParser<ARM64AsmParser> Y(TheARM64beTarget);
} }
#define GET_REGISTER_MATCHER #define GET_REGISTER_MATCHER

View File

@ -229,9 +229,13 @@ createARM64ExternalSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo,
} }
extern "C" void LLVMInitializeARM64Disassembler() { extern "C" void LLVMInitializeARM64Disassembler() {
TargetRegistry::RegisterMCDisassembler(TheARM64Target, TargetRegistry::RegisterMCDisassembler(TheARM64leTarget,
createARM64Disassembler); createARM64Disassembler);
TargetRegistry::RegisterMCSymbolizer(TheARM64Target, TargetRegistry::RegisterMCDisassembler(TheARM64beTarget,
createARM64Disassembler);
TargetRegistry::RegisterMCSymbolizer(TheARM64leTarget,
createARM64ExternalSymbolizer);
TargetRegistry::RegisterMCSymbolizer(TheARM64beTarget,
createARM64ExternalSymbolizer); createARM64ExternalSymbolizer);
} }

View File

@ -483,12 +483,13 @@ namespace {
class ELFARM64AsmBackend : public ARM64AsmBackend { class ELFARM64AsmBackend : public ARM64AsmBackend {
public: public:
uint8_t OSABI; uint8_t OSABI;
bool IsLittleEndian;
ELFARM64AsmBackend(const Target &T, uint8_t OSABI) ELFARM64AsmBackend(const Target &T, uint8_t OSABI, bool IsLittleEndian)
: ARM64AsmBackend(T), OSABI(OSABI) {} : ARM64AsmBackend(T), OSABI(OSABI), IsLittleEndian(IsLittleEndian) {}
MCObjectWriter *createObjectWriter(raw_ostream &OS) const { MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
return createARM64ELFObjectWriter(OS, OSABI); return createARM64ELFObjectWriter(OS, OSABI, IsLittleEndian);
} }
void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout,
@ -520,14 +521,23 @@ void ELFARM64AsmBackend::processFixupValue(const MCAssembler &Asm,
} }
} }
MCAsmBackend *llvm::createARM64AsmBackend(const Target &T, MCAsmBackend *llvm::createARM64leAsmBackend(const Target &T,
const MCRegisterInfo &MRI, const MCRegisterInfo &MRI,
StringRef TT, StringRef CPU) { StringRef TT, StringRef CPU) {
Triple TheTriple(TT); Triple TheTriple(TT);
if (TheTriple.isOSDarwin()) if (TheTriple.isOSDarwin())
return new DarwinARM64AsmBackend(T, MRI); return new DarwinARM64AsmBackend(T, MRI);
assert(TheTriple.isOSBinFormatELF() && "Expect either MachO or ELF target"); assert(TheTriple.isOSBinFormatELF() && "Expect either MachO or ELF target");
return new ELFARM64AsmBackend(T, TheTriple.getOS()); return new ELFARM64AsmBackend(T, TheTriple.getOS(), /*IsLittleEndian=*/true);
}
MCAsmBackend *llvm::createARM64beAsmBackend(const Target &T,
const MCRegisterInfo &MRI,
StringRef TT, StringRef CPU) {
Triple TheTriple(TT);
assert(TheTriple.isOSBinFormatELF() && "Big endian is only supported for ELF targets!");
return new ELFARM64AsmBackend(T, TheTriple.getOS(), /*IsLittleEndian=*/false);
} }

View File

@ -24,7 +24,7 @@ using namespace llvm;
namespace { namespace {
class ARM64ELFObjectWriter : public MCELFObjectTargetWriter { class ARM64ELFObjectWriter : public MCELFObjectTargetWriter {
public: public:
ARM64ELFObjectWriter(uint8_t OSABI); ARM64ELFObjectWriter(uint8_t OSABI, bool IsLittleEndian);
virtual ~ARM64ELFObjectWriter(); virtual ~ARM64ELFObjectWriter();
@ -36,7 +36,7 @@ private:
}; };
} }
ARM64ELFObjectWriter::ARM64ELFObjectWriter(uint8_t OSABI) ARM64ELFObjectWriter::ARM64ELFObjectWriter(uint8_t OSABI, bool IsLittleEndian)
: MCELFObjectTargetWriter(/*Is64Bit*/ true, OSABI, ELF::EM_AARCH64, : MCELFObjectTargetWriter(/*Is64Bit*/ true, OSABI, ELF::EM_AARCH64,
/*HasRelocationAddend*/ true) {} /*HasRelocationAddend*/ true) {}
@ -235,7 +235,8 @@ unsigned ARM64ELFObjectWriter::GetRelocType(const MCValue &Target,
} }
MCObjectWriter *llvm::createARM64ELFObjectWriter(raw_ostream &OS, MCObjectWriter *llvm::createARM64ELFObjectWriter(raw_ostream &OS,
uint8_t OSABI) { uint8_t OSABI,
MCELFObjectTargetWriter *MOTW = new ARM64ELFObjectWriter(OSABI); bool IsLittleEndian) {
return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/true); MCELFObjectTargetWriter *MOTW = new ARM64ELFObjectWriter(OSABI, IsLittleEndian);
return createELFObjectWriter(MOTW, OS, IsLittleEndian);
} }

View File

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "ARM64MCAsmInfo.h" #include "ARM64MCAsmInfo.h"
#include "llvm/ADT/Triple.h"
#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCContext.h" #include "llvm/MC/MCContext.h"
#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCStreamer.h"
@ -63,7 +64,11 @@ const MCExpr *ARM64MCAsmInfoDarwin::getExprForPersonalitySymbol(
return MCBinaryExpr::CreateSub(Res, PC, Context); return MCBinaryExpr::CreateSub(Res, PC, Context);
} }
ARM64MCAsmInfoELF::ARM64MCAsmInfoELF() { ARM64MCAsmInfoELF::ARM64MCAsmInfoELF(StringRef TT) {
Triple T(TT);
if (T.getArch() == Triple::aarch64_be)
IsLittleEndian = false;
// We prefer NEON instructions to be printed in the short form. // We prefer NEON instructions to be printed in the short form.
AssemblerDialect = AsmWriterVariant == Default ? 0 : AsmWriterVariant; AssemblerDialect = AsmWriterVariant == Default ? 0 : AsmWriterVariant;

View File

@ -28,7 +28,7 @@ struct ARM64MCAsmInfoDarwin : public MCAsmInfoDarwin {
}; };
struct ARM64MCAsmInfoELF : public MCAsmInfo { struct ARM64MCAsmInfoELF : public MCAsmInfo {
explicit ARM64MCAsmInfoELF(); explicit ARM64MCAsmInfoELF(StringRef TT);
}; };
} // namespace llvm } // namespace llvm

View File

@ -66,7 +66,7 @@ static MCAsmInfo *createARM64MCAsmInfo(const MCRegisterInfo &MRI,
MAI = new ARM64MCAsmInfoDarwin(); MAI = new ARM64MCAsmInfoDarwin();
else { else {
assert(TheTriple.isOSBinFormatELF() && "Only expect Darwin or ELF"); assert(TheTriple.isOSBinFormatELF() && "Only expect Darwin or ELF");
MAI = new ARM64MCAsmInfoELF(); MAI = new ARM64MCAsmInfoELF(TT);
} }
// Initial state of the frame pointer is SP. // Initial state of the frame pointer is SP.
@ -139,33 +139,46 @@ static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
// Force static initialization. // Force static initialization.
extern "C" void LLVMInitializeARM64TargetMC() { extern "C" void LLVMInitializeARM64TargetMC() {
// Register the MC asm info. // Register the MC asm info.
RegisterMCAsmInfoFn X(TheARM64Target, createARM64MCAsmInfo); RegisterMCAsmInfoFn X(TheARM64leTarget, createARM64MCAsmInfo);
RegisterMCAsmInfoFn Y(TheARM64beTarget, createARM64MCAsmInfo);
// Register the MC codegen info. // Register the MC codegen info.
TargetRegistry::RegisterMCCodeGenInfo(TheARM64Target, TargetRegistry::RegisterMCCodeGenInfo(TheARM64leTarget,
createARM64MCCodeGenInfo);
TargetRegistry::RegisterMCCodeGenInfo(TheARM64beTarget,
createARM64MCCodeGenInfo); createARM64MCCodeGenInfo);
// Register the MC instruction info. // Register the MC instruction info.
TargetRegistry::RegisterMCInstrInfo(TheARM64Target, createARM64MCInstrInfo); TargetRegistry::RegisterMCInstrInfo(TheARM64leTarget, createARM64MCInstrInfo);
TargetRegistry::RegisterMCInstrInfo(TheARM64beTarget, createARM64MCInstrInfo);
// Register the MC register info. // Register the MC register info.
TargetRegistry::RegisterMCRegInfo(TheARM64Target, createARM64MCRegisterInfo); TargetRegistry::RegisterMCRegInfo(TheARM64leTarget, createARM64MCRegisterInfo);
TargetRegistry::RegisterMCRegInfo(TheARM64beTarget, createARM64MCRegisterInfo);
// Register the MC subtarget info. // Register the MC subtarget info.
TargetRegistry::RegisterMCSubtargetInfo(TheARM64Target, TargetRegistry::RegisterMCSubtargetInfo(TheARM64leTarget,
createARM64MCSubtargetInfo);
TargetRegistry::RegisterMCSubtargetInfo(TheARM64beTarget,
createARM64MCSubtargetInfo); createARM64MCSubtargetInfo);
// Register the asm backend. // Register the asm backend.
TargetRegistry::RegisterMCAsmBackend(TheARM64Target, createARM64AsmBackend); TargetRegistry::RegisterMCAsmBackend(TheARM64leTarget, createARM64leAsmBackend);
TargetRegistry::RegisterMCAsmBackend(TheARM64beTarget, createARM64beAsmBackend);
// Register the MC Code Emitter // Register the MC Code Emitter
TargetRegistry::RegisterMCCodeEmitter(TheARM64Target, TargetRegistry::RegisterMCCodeEmitter(TheARM64leTarget,
createARM64MCCodeEmitter);
TargetRegistry::RegisterMCCodeEmitter(TheARM64beTarget,
createARM64MCCodeEmitter); createARM64MCCodeEmitter);
// Register the object streamer. // Register the object streamer.
TargetRegistry::RegisterMCObjectStreamer(TheARM64Target, createMCStreamer); TargetRegistry::RegisterMCObjectStreamer(TheARM64leTarget, createMCStreamer);
TargetRegistry::RegisterMCObjectStreamer(TheARM64beTarget, createMCStreamer);
// Register the MCInstPrinter. // Register the MCInstPrinter.
TargetRegistry::RegisterMCInstPrinter(TheARM64Target, TargetRegistry::RegisterMCInstPrinter(TheARM64leTarget,
createARM64MCInstPrinter);
TargetRegistry::RegisterMCInstPrinter(TheARM64beTarget,
createARM64MCInstPrinter); createARM64MCInstPrinter);
} }

View File

@ -29,16 +29,20 @@ class StringRef;
class Target; class Target;
class raw_ostream; class raw_ostream;
extern Target TheARM64Target; extern Target TheARM64leTarget;
extern Target TheARM64beTarget;
MCCodeEmitter *createARM64MCCodeEmitter(const MCInstrInfo &MCII, MCCodeEmitter *createARM64MCCodeEmitter(const MCInstrInfo &MCII,
const MCRegisterInfo &MRI, const MCRegisterInfo &MRI,
const MCSubtargetInfo &STI, const MCSubtargetInfo &STI,
MCContext &Ctx); MCContext &Ctx);
MCAsmBackend *createARM64AsmBackend(const Target &T, const MCRegisterInfo &MRI, MCAsmBackend *createARM64leAsmBackend(const Target &T, const MCRegisterInfo &MRI,
StringRef TT, StringRef CPU); StringRef TT, StringRef CPU);
MCAsmBackend *createARM64beAsmBackend(const Target &T, const MCRegisterInfo &MRI,
StringRef TT, StringRef CPU);
MCObjectWriter *createARM64ELFObjectWriter(raw_ostream &OS, uint8_t OSABI); MCObjectWriter *createARM64ELFObjectWriter(raw_ostream &OS, uint8_t OSABI,
bool IsLittleEndian);
MCObjectWriter *createARM64MachObjectWriter(raw_ostream &OS, uint32_t CPUType, MCObjectWriter *createARM64MachObjectWriter(raw_ostream &OS, uint32_t CPUType,
uint32_t CPUSubtype); uint32_t CPUSubtype);

View File

@ -12,10 +12,13 @@
using namespace llvm; using namespace llvm;
namespace llvm { namespace llvm {
Target TheARM64Target; Target TheARM64leTarget;
Target TheARM64beTarget;
} // end namespace llvm } // end namespace llvm
extern "C" void LLVMInitializeARM64TargetInfo() { extern "C" void LLVMInitializeARM64TargetInfo() {
RegisterTarget<Triple::arm64, /*HasJIT=*/true> X(TheARM64Target, "arm64", RegisterTarget<Triple::arm64, /*HasJIT=*/true> X(TheARM64leTarget, "arm64",
"ARM64"); "ARM64 (little endian)");
RegisterTarget<Triple::arm64_be, /*HasJIT=*/true> Y(TheARM64beTarget, "arm64_be",
"ARM64 (big endian)");
} }