diff options
author | Wesley Peck <peckw@wesleypeck.com> | 2010-11-21 22:06:28 +0000 |
---|---|---|
committer | Wesley Peck <peckw@wesleypeck.com> | 2010-11-21 22:06:28 +0000 |
commit | 4b04713423c6da988db75c7546baa3db7ddfa119 (patch) | |
tree | 6af0a6e0e6c05fa1d2b7ae9acb8bd8f20df59a9d /lib/MC/ELFObjectWriter.cpp | |
parent | 46a928b864369ba9e1b8fc055d100c2fa0f97d16 (diff) |
Implement ELF object file writing support for the MBlaze backend. Its not perfect yet, but it works for many tests.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119952 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/MC/ELFObjectWriter.cpp')
-rw-r--r-- | lib/MC/ELFObjectWriter.cpp | 142 |
1 files changed, 140 insertions, 2 deletions
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 4ea6308f45..b9a0b028d1 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -30,6 +30,7 @@ #include "llvm/Target/TargetAsmBackend.h" #include "../Target/X86/X86FixupKinds.h" +#include "../Target/MBlaze/MBlazeFixupKinds.h" #include <vector> using namespace llvm; @@ -77,6 +78,16 @@ static bool isFixupKindX86PCRel(unsigned Kind) { } } +static bool isFixupKindMBlazePCRel(unsigned Kind) { + switch (Kind) { + default: + return false; + case MBlaze::reloc_pcrel_2byte: + case MBlaze::reloc_pcrel_4byte: + return true; + } +} + static bool RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant) { switch (Variant) { default: @@ -358,7 +369,7 @@ namespace { X86ELFObjectWriter(raw_ostream &_OS, bool _Is64Bit, bool IsLittleEndian, uint16_t _EMachine, bool _HasRelAddend, Triple::OSType _OSType); - + virtual ~X86ELFObjectWriter(); virtual void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, @@ -375,7 +386,7 @@ namespace { ARMELFObjectWriter(raw_ostream &_OS, bool _Is64Bit, bool IsLittleEndian, uint16_t _EMachine, bool _HasRelAddend, Triple::OSType _OSType); - + virtual ~ARMELFObjectWriter(); virtual void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, @@ -383,6 +394,22 @@ namespace { const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue); }; + + //===- MBlazeELFObjectWriter -------------------------------------------===// + + class MBlazeELFObjectWriter : public ELFObjectWriter { + public: + MBlazeELFObjectWriter(raw_ostream &_OS, bool _Is64Bit, bool IsLittleEndian, + uint16_t _EMachine, bool _HasRelAddend, + Triple::OSType _OSType); + + virtual ~MBlazeELFObjectWriter(); + virtual void RecordRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + uint64_t &FixedValue); + }; } ELFObjectWriter::~ELFObjectWriter() @@ -1349,6 +1376,9 @@ MCObjectWriter *llvm::createELFObjectWriter(raw_ostream &OS, case ELF::EM_ARM: return new ARMELFObjectWriter(OS, Is64Bit, IsLittleEndian, EMachine, HasRelocationAddend, OSType); break; + case ELF::EM_MBLAZE: + return new MBlazeELFObjectWriter(OS, Is64Bit, IsLittleEndian, EMachine, + HasRelocationAddend, OSType); break; default: llvm_unreachable("Unsupported architecture"); break; } } @@ -1377,7 +1407,115 @@ void ARMELFObjectWriter::RecordRelocation(const MCAssembler &Asm, assert(0 && "ARMELFObjectWriter::RecordRelocation() unimplemented"); } +//===- MBlazeELFObjectWriter -------------------------------------------===// + +MBlazeELFObjectWriter::MBlazeELFObjectWriter(raw_ostream &_OS, bool _Is64Bit, + bool _IsLittleEndian, + uint16_t _EMachine, + bool _HasRelocationAddend, + Triple::OSType _OSType) + : ELFObjectWriter(_OS, _Is64Bit, _IsLittleEndian, _EMachine, + _HasRelocationAddend, _OSType) { +} + +MBlazeELFObjectWriter::~MBlazeELFObjectWriter() { +} + +void MBlazeELFObjectWriter::RecordRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue) { + int64_t Addend = 0; + int Index = 0; + int64_t Value = Target.getConstant(); + const MCSymbol &Symbol = Target.getSymA()->getSymbol(); + const MCSymbol &ASymbol = Symbol.AliasedSymbol(); + const MCSymbol *RelocSymbol = SymbolToReloc(Asm, Target, *Fragment); + bool IsPCRel = isFixupKindMBlazePCRel(Fixup.getKind()); + if (!Target.isAbsolute()) { + if (const MCSymbolRefExpr *RefB = Target.getSymB()) { + const MCSymbol &SymbolB = RefB->getSymbol(); + MCSymbolData &SDB = Asm.getSymbolData(SymbolB); + IsPCRel = true; + MCSectionData *Sec = Fragment->getParent(); + + // Offset of the symbol in the section + int64_t a = Layout.getSymbolAddress(&SDB) - Layout.getSectionAddress(Sec); + + // Ofeset of the relocation in the section + int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + Value += b - a; + } + + if (!RelocSymbol) { + MCSymbolData &SD = Asm.getSymbolData(ASymbol); + MCFragment *F = SD.getFragment(); + + Index = F->getParent()->getOrdinal(); + + MCSectionData *FSD = F->getParent(); + // Offset of the symbol in the section + Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD); + } else { + if (Asm.getSymbolData(Symbol).getFlags() & ELF_Other_Weakref) + WeakrefUsedInReloc.insert(RelocSymbol); + else + UsedInReloc.insert(RelocSymbol); + Index = -1; + } + Addend = Value; + } + + FixedValue = Value; + + // determine the type of the relocation + unsigned Type; + if (IsPCRel) { + switch ((unsigned)Fixup.getKind()) { + default: + llvm_unreachable("Unimplemented"); + case MBlaze::reloc_pcrel_4byte: + Type = ELF::R_MICROBLAZE_64_PCREL; + break; + case MBlaze::reloc_pcrel_2byte: + Type = ELF::R_MICROBLAZE_32_PCREL; + break; + } + } else { + switch ((unsigned)Fixup.getKind()) { + default: llvm_unreachable("invalid fixup kind!"); + case FK_Data_4: + Type = (RelocSymbol || Addend !=0) ? ELF::R_MICROBLAZE_32 + : ELF::R_MICROBLAZE_64; + break; + case FK_Data_2: + Type = ELF::R_MICROBLAZE_32; + break; + } + } + + MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind(); + if (RelocNeedsGOT(Modifier)) + NeedsGOT = true; + + ELFRelocationEntry ERE; + + ERE.Index = Index; + ERE.Type = Type; + ERE.Symbol = RelocSymbol; + + ERE.r_offset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + + if (HasRelocationAddend) + ERE.r_addend = Addend; + else + ERE.r_addend = 0; // Silence compiler warning. + + Relocations[Fragment->getParent()].push_back(ERE); +} //===- X86ELFObjectWriter -------------------------------------------===// |