Sketch out PowerPC ELF writer. This is enough to get clang -integrated-as

to compile a working hello world on FreeBSD/PPC32.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136689 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Roman Divacky 2011-08-02 15:51:38 +00:00
parent 086da7e680
commit 2c0d69fad0
5 changed files with 173 additions and 2 deletions

View File

@ -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 };

View File

@ -30,6 +30,7 @@
#include "../Target/X86/MCTargetDesc/X86FixupKinds.h"
#include "../Target/ARM/MCTargetDesc/ARMFixupKinds.h"
#include "../Target/PowerPC/MCTargetDesc/PPCFixupKinds.h"
#include <vector>
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,

View File

@ -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 {

View File

@ -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());
}

View File

@ -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,