From 038c1a1a7307a08c3ee36af511b990e766d0af6b Mon Sep 17 00:00:00 2001 From: Roman Divacky Date: Tue, 2 Aug 2011 15:51:38 +0000 Subject: [PATCH] Sketch out PowerPC ELF writer. This is enough to get clang -integrated-as to compile a working hello world on FreeBSD/PPC32. llvm-svn: 136689 --- llvm/include/llvm/Support/ELF.h | 17 +++++ llvm/lib/MC/ELFObjectWriter.cpp | 70 ++++++++++++++++++ llvm/lib/MC/ELFObjectWriter.h | 15 ++++ .../PowerPC/MCTargetDesc/PPCAsmBackend.cpp | 71 ++++++++++++++++++- .../PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp | 2 +- 5 files changed, 173 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Support/ELF.h b/llvm/include/llvm/Support/ELF.h index be48112a908b..83bc047d78c8 100644 --- a/llvm/include/llvm/Support/ELF.h +++ b/llvm/include/llvm/Support/ELF.h @@ -290,6 +290,23 @@ enum { R_MICROBLAZE_COPY = 21 }; +enum { + R_PPC_NONE = 0, /* No relocation. */ + R_PPC_ADDR32 = 1, + R_PPC_ADDR24 = 2, + R_PPC_ADDR16 = 3, + R_PPC_ADDR16_LO = 4, + R_PPC_ADDR16_HI = 5, + R_PPC_ADDR16_HA = 6, + R_PPC_ADDR14 = 7, + R_PPC_ADDR14_BRTAKEN = 8, + R_PPC_ADDR14_BRNTAKEN = 9, + R_PPC_REL24 = 10, + R_PPC_REL14 = 11, + R_PPC_REL14_BRTAKEN = 12, + R_PPC_REL14_BRNTAKEN = 13, + R_PPC_REL32 = 26 +}; // ARM Specific e_flags enum { EF_ARM_EABIMASK = 0xFF000000U }; diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index d562ac09b191..050d11ef3fcc 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -30,6 +30,7 @@ #include "../Target/X86/MCTargetDesc/X86FixupKinds.h" #include "../Target/ARM/MCTargetDesc/ARMFixupKinds.h" +#include "../Target/PowerPC/MCTargetDesc/PPCFixupKinds.h" #include using namespace llvm; @@ -446,6 +447,14 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, uint64_t RelocOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + switch ((unsigned)Fixup.getKind()) { + case PPC::fixup_ppc_ha16: + case PPC::fixup_ppc_lo16: + RelocOffset += 2; + break; + default: + break; + } if (!hasRelocationAddend()) Addend = 0; @@ -1252,6 +1261,9 @@ MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW, return new ARMELFObjectWriter(MOTW, OS, IsLittleEndian); break; case ELF::EM_MBLAZE: return new MBlazeELFObjectWriter(MOTW, OS, IsLittleEndian); break; + case ELF::EM_PPC: + case ELF::EM_PPC64: + return new PPCELFObjectWriter(MOTW, OS, IsLittleEndian); break; default: llvm_unreachable("Unsupported architecture"); break; } } @@ -1503,6 +1515,64 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, return Type; } +//===- PPCELFObjectWriter -------------------------------------------===// + +PPCELFObjectWriter::PPCELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, + bool IsLittleEndian) + : ELFObjectWriter(MOTW, _OS, IsLittleEndian) { +} + +PPCELFObjectWriter::~PPCELFObjectWriter() { +} + +unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel, + bool IsRelocWithSymbol, + int64_t Addend) { + // determine the type of the relocation + unsigned Type; + if (IsPCRel) { + switch ((unsigned)Fixup.getKind()) { + default: + llvm_unreachable("Unimplemented"); + case PPC::fixup_ppc_br24: + Type = ELF::R_PPC_REL24; + break; + case FK_PCRel_4: + Type = ELF::R_PPC_REL32; + break; + } + } else { + switch ((unsigned)Fixup.getKind()) { + default: llvm_unreachable("invalid fixup kind!"); + case PPC::fixup_ppc_br24: + Type = ELF::R_PPC_ADDR24; + break; + case PPC::fixup_ppc_brcond14: + Type = ELF::R_PPC_ADDR14_BRTAKEN; // XXX: or BRNTAKEN?_ + break; + case PPC::fixup_ppc_ha16: + Type = ELF::R_PPC_ADDR16_HA; + break; + case PPC::fixup_ppc_lo16: + Type = ELF::R_PPC_ADDR16_LO; + break; + case PPC::fixup_ppc_lo14: + Type = ELF::R_PPC_ADDR14; + break; + case FK_Data_4: + Type = ELF::R_PPC_ADDR32; + break; + case FK_Data_2: + Type = ELF::R_PPC_ADDR16; + break; + } + } + return Type; +} + //===- MBlazeELFObjectWriter -------------------------------------------===// MBlazeELFObjectWriter::MBlazeELFObjectWriter(MCELFObjectTargetWriter *MOTW, diff --git a/llvm/lib/MC/ELFObjectWriter.h b/llvm/lib/MC/ELFObjectWriter.h index 7593099fb447..45a88985c4bc 100644 --- a/llvm/lib/MC/ELFObjectWriter.h +++ b/llvm/lib/MC/ELFObjectWriter.h @@ -395,6 +395,21 @@ class ELFObjectWriter : public MCObjectWriter { }; + //===- PPCELFObjectWriter -------------------------------------------===// + + class PPCELFObjectWriter : public ELFObjectWriter { + public: + PPCELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, + bool IsLittleEndian); + + virtual ~PPCELFObjectWriter(); + protected: + virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsPCRel, bool IsRelocWithSymbol, + int64_t Addend); + }; + //===- MBlazeELFObjectWriter -------------------------------------------===// class MBlazeELFObjectWriter : public ELFObjectWriter { diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp index 290e61aa9f74..95f929a735b7 100644 --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp @@ -10,14 +10,40 @@ #include "llvm/MC/MCAsmBackend.h" #include "MCTargetDesc/PPCMCTargetDesc.h" #include "MCTargetDesc/PPCFixupKinds.h" +#include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCMachObjectWriter.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCValue.h" #include "llvm/Object/MachOFormat.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetRegistry.h" using namespace llvm; +static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { + switch (Kind) { + default: + llvm_unreachable("Unknown fixup kind!"); + case FK_Data_1: + case FK_Data_2: + case FK_Data_4: + return Value; + case PPC::fixup_ppc_brcond14: + return Value & 0x3ffc; + case PPC::fixup_ppc_br24: + return Value & 0x3fffffc; +#if 0 + case PPC::fixup_ppc_hi16: + return (Value >> 16) & 0xffff; +#endif + case PPC::fixup_ppc_ha16: + return ((Value >> 16) + ((Value & 0x8000) ? 1 : 0)) & 0xffff; + case PPC::fixup_ppc_lo16: + return Value & 0xffff; + } +} + namespace { class PPCMachObjectWriter : public MCMachObjectTargetWriter { public: @@ -31,6 +57,13 @@ public: MCValue Target, uint64_t &FixedValue) {} }; +class PPCELFObjectWriter : public MCELFObjectTargetWriter { +public: + PPCELFObjectWriter(bool Is64Bit, Triple::OSType OSType, uint16_t EMachine, + bool HasRelocationAddend, bool isLittleEndian) + : MCELFObjectTargetWriter(Is64Bit, OSType, EMachine, HasRelocationAddend) {} +}; + class PPCAsmBackend : public MCAsmBackend { const Target &TheTarget; public: @@ -109,6 +142,42 @@ namespace { return false; } }; + + class ELFPPCAsmBackend : public PPCAsmBackend { + Triple::OSType OSType; + public: + ELFPPCAsmBackend(const Target &T, Triple::OSType OSType) : + PPCAsmBackend(T), OSType(OSType) { } + + void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, + uint64_t Value) const { + Value = adjustFixupValue(Fixup.getKind(), Value); + if (!Value) return; // Doesn't change encoding. + + unsigned Offset = Fixup.getOffset(); + + // For each byte of the fragment that the fixup touches, mask in the bits from + // the fixup value. The Value has been "split up" into the appropriate + // bitfields above. + for (unsigned i = 0; i != 4; ++i) + Data[Offset + i] |= uint8_t((Value >> ((4 - i - 1)*8)) & 0xff); + } + + MCObjectWriter *createObjectWriter(raw_ostream &OS) const { + bool is64 = getPointerSize() == 8; + return createELFObjectWriter(new PPCELFObjectWriter( + /*Is64Bit=*/is64, + OSType, + is64 ? ELF::EM_PPC64 : ELF::EM_PPC, + /*addend*/ true, /*isLittleEndian*/ false), + OS, /*IsLittleEndian=*/false); + } + + virtual bool doesSectionRequireSymbols(const MCSection &Section) const { + return false; + } + }; + } // end anonymous namespace @@ -118,5 +187,5 @@ MCAsmBackend *llvm::createPPCAsmBackend(const Target &T, StringRef TT) { if (Triple(TT).isOSDarwin()) return new DarwinPPCAsmBackend(T); - return 0; + return new ELFPPCAsmBackend(T, Triple(TT).getOS()); } diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp index 3dda0b193fcd..83f9c6cf61f8 100644 --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp @@ -99,7 +99,7 @@ static MCStreamer *createMCStreamer(const Target &T, StringRef TT, if (Triple(TT).isOSDarwin()) return createMachOStreamer(Ctx, MAB, OS, Emitter, RelaxAll); - return NULL; + return createELFStreamer(Ctx, MAB, OS, Emitter, RelaxAll, NoExecStack);; } static MCInstPrinter *createPPCMCInstPrinter(const Target &T,