forked from OSchip/llvm-project
[Sparc] Add ELF Object Writer for Sparc.
llvm-svn: 198580
This commit is contained in:
parent
908bf814e7
commit
b73aeca888
|
@ -1,5 +1,6 @@
|
|||
add_llvm_library(LLVMSparcDesc
|
||||
SparcAsmBackend.cpp
|
||||
SparcELFObjectWriter.cpp
|
||||
SparcMCAsmInfo.cpp
|
||||
SparcMCCodeEmitter.cpp
|
||||
SparcMCTargetDesc.cpp
|
||||
|
|
|
@ -10,17 +10,50 @@
|
|||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "MCTargetDesc/SparcMCTargetDesc.h"
|
||||
#include "MCTargetDesc/SparcFixupKinds.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
#include "llvm/MC/MCFixupKindInfo.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
#include "llvm/Support/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:
|
||||
case FK_Data_8:
|
||||
return Value;
|
||||
case Sparc::fixup_sparc_call30:
|
||||
return Value & 0x3fffffff;
|
||||
case Sparc::fixup_sparc_br22:
|
||||
return Value & 0x3fffff;
|
||||
case Sparc::fixup_sparc_br19:
|
||||
return Value & 0x1ffff;
|
||||
case Sparc::fixup_sparc_hi22:
|
||||
return (Value >> 10) & 0x3fffff;
|
||||
case Sparc::fixup_sparc_lo10:
|
||||
return Value & 0x3ff;
|
||||
case Sparc::fixup_sparc_h44:
|
||||
return (Value >> 22) & 0x3fffff;
|
||||
case Sparc::fixup_sparc_m44:
|
||||
return (Value >> 12) & 0x3ff;
|
||||
case Sparc::fixup_sparc_l44:
|
||||
return Value & 0xfff;
|
||||
case Sparc::fixup_sparc_hh:
|
||||
return (Value >> 42) & 0x3fffff;
|
||||
case Sparc::fixup_sparc_hm:
|
||||
return (Value >>32) & 0x3ff;
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
class SparcAsmBackend : public MCAsmBackend {
|
||||
|
||||
const Target &TheTarget;
|
||||
public:
|
||||
SparcAsmBackend(const Target &T) : MCAsmBackend() {}
|
||||
SparcAsmBackend(const Target &T) : MCAsmBackend(), TheTarget(T) {}
|
||||
|
||||
unsigned getNumFixupKinds() const {
|
||||
return Sparc::NumTargetFixupKinds;
|
||||
|
@ -31,7 +64,14 @@ namespace {
|
|||
// name offset bits flags
|
||||
{ "fixup_sparc_call30", 0, 30, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_sparc_br22", 0, 22, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel }
|
||||
{ "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_sparc_hi22", 0, 22, 0 },
|
||||
{ "fixup_sparc_lo10", 0, 10, 0 },
|
||||
{ "fixup_sparc_h44", 0, 22, 0 },
|
||||
{ "fixup_sparc_m44", 0, 10, 0 },
|
||||
{ "fixup_sparc_l44", 0, 12, 0 },
|
||||
{ "fixup_sparc_hh", 0, 21, 0 },
|
||||
{ "fixup_sparc_hm", 0, 10, 0 },
|
||||
};
|
||||
|
||||
if (Kind < FirstTargetFixupKind)
|
||||
|
@ -68,21 +108,38 @@ namespace {
|
|||
OW->Write8(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is64Bit() const {
|
||||
StringRef name = TheTarget.getName();
|
||||
return name == "sparcv9";
|
||||
}
|
||||
};
|
||||
|
||||
class ELFSparcAsmBackend : public SparcAsmBackend {
|
||||
Triple::OSType OSType;
|
||||
public:
|
||||
ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) :
|
||||
SparcAsmBackend(T) { }
|
||||
SparcAsmBackend(T), OSType(OSType) { }
|
||||
|
||||
void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
|
||||
uint64_t Value) const {
|
||||
assert(0 && "applyFixup not implemented yet");
|
||||
|
||||
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 {
|
||||
assert(0 && "Object Writer not implemented yet");
|
||||
return 0;
|
||||
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType);
|
||||
return createSparcELFObjectWriter(OS, is64Bit(), OSABI);
|
||||
}
|
||||
|
||||
virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
//===-- SparcELFObjectWriter.cpp - Sparc ELF Writer -----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/SparcMCTargetDesc.h"
|
||||
#include "MCTargetDesc/SparcFixupKinds.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class SparcELFObjectWriter : public MCELFObjectTargetWriter {
|
||||
public:
|
||||
SparcELFObjectWriter(bool Is64Bit, uint8_t OSABI)
|
||||
: MCELFObjectTargetWriter(Is64Bit, OSABI,
|
||||
Is64Bit ? ELF::EM_SPARCV9 : ELF::EM_SPARC,
|
||||
/*HasRelocationAddend*/ true) {}
|
||||
|
||||
virtual ~SparcELFObjectWriter() {}
|
||||
protected:
|
||||
virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
|
||||
bool IsPCRel, bool IsRelocWithSymbol,
|
||||
int64_t Addend) const;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
unsigned SparcELFObjectWriter::GetRelocType(const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel,
|
||||
bool IsRelocWithSymbol,
|
||||
int64_t Addend) const {
|
||||
if (IsPCRel) {
|
||||
switch((unsigned)Fixup.getKind()) {
|
||||
default:
|
||||
llvm_unreachable("Unimplemented fixup -> relocation");
|
||||
case FK_Data_1: return ELF::R_SPARC_DISP8;
|
||||
case FK_Data_2: return ELF::R_SPARC_DISP16;
|
||||
case FK_Data_4: return ELF::R_SPARC_DISP32;
|
||||
case FK_Data_8: return ELF::R_SPARC_DISP64;
|
||||
case Sparc::fixup_sparc_call30: return ELF::R_SPARC_WDISP30;
|
||||
case Sparc::fixup_sparc_br22: return ELF::R_SPARC_WDISP22;
|
||||
case Sparc::fixup_sparc_br19: return ELF::R_SPARC_WDISP19;
|
||||
}
|
||||
}
|
||||
|
||||
switch((unsigned)Fixup.getKind()) {
|
||||
default:
|
||||
llvm_unreachable("Unimplemented fixup -> relocation");
|
||||
case FK_Data_1: return ELF::R_SPARC_8;
|
||||
case FK_Data_2: return ((Fixup.getOffset() % 2)
|
||||
? ELF::R_SPARC_UA16
|
||||
: ELF::R_SPARC_16);
|
||||
case FK_Data_4: return ((Fixup.getOffset() % 4)
|
||||
? ELF::R_SPARC_UA32
|
||||
: ELF::R_SPARC_32);
|
||||
case FK_Data_8: return ((Fixup.getOffset() % 8)
|
||||
? ELF::R_SPARC_UA64
|
||||
: ELF::R_SPARC_64);
|
||||
case Sparc::fixup_sparc_hi22: return ELF::R_SPARC_HI22;
|
||||
case Sparc::fixup_sparc_lo10: return ELF::R_SPARC_LO10;
|
||||
case Sparc::fixup_sparc_h44: return ELF::R_SPARC_H44;
|
||||
case Sparc::fixup_sparc_m44: return ELF::R_SPARC_M44;
|
||||
case Sparc::fixup_sparc_l44: return ELF::R_SPARC_L44;
|
||||
case Sparc::fixup_sparc_hh: return ELF::R_SPARC_HH22;
|
||||
case Sparc::fixup_sparc_hm: return ELF::R_SPARC_HM10;
|
||||
}
|
||||
return ELF::R_SPARC_NONE;
|
||||
}
|
||||
|
||||
MCObjectWriter *llvm::createSparcELFObjectWriter(raw_ostream &OS,
|
||||
bool Is64Bit,
|
||||
uint8_t OSABI) {
|
||||
MCELFObjectTargetWriter *MOTW = new SparcELFObjectWriter(Is64Bit, OSABI);
|
||||
return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false);
|
||||
}
|
|
@ -22,10 +22,32 @@ namespace llvm {
|
|||
/// branches
|
||||
fixup_sparc_br22,
|
||||
|
||||
/// fixup_sparc_br22 - 22-bit PC relative relocation for
|
||||
/// fixup_sparc_br19 - 19-bit PC relative relocation for
|
||||
/// branches on icc/xcc
|
||||
fixup_sparc_br19,
|
||||
|
||||
/// fixup_sparc_hi22 - 22-bit fixup corresponding to %hi(foo)
|
||||
/// for sethi
|
||||
fixup_sparc_hi22,
|
||||
|
||||
/// fixup_sparc_lo10 - 10-bit fixup corresponding to %lo(foo)
|
||||
fixup_sparc_lo10,
|
||||
|
||||
/// fixup_sparc_h44 - 22-bit fixup corresponding to %h44(foo)
|
||||
fixup_sparc_h44,
|
||||
|
||||
/// fixup_sparc_m44 - 10-bit fixup corresponding to %m44(foo)
|
||||
fixup_sparc_m44,
|
||||
|
||||
/// fixup_sparc_l44 - 12-bit fixup corresponding to %l44(foo)
|
||||
fixup_sparc_l44,
|
||||
|
||||
/// fixup_sparc_hh - 22-bit fixup corresponding to %hh(foo)
|
||||
fixup_sparc_hh,
|
||||
|
||||
/// fixup_sparc_hm - 10-bit fixup corresponding to %hm(foo)
|
||||
fixup_sparc_hm,
|
||||
|
||||
// Marker
|
||||
LastTargetFixupKind,
|
||||
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "mccodeemitter"
|
||||
#include "SparcMCExpr.h"
|
||||
#include "SparcMCTargetDesc.h"
|
||||
#include "MCTargetDesc/SparcFixupKinds.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
|
@ -92,6 +93,41 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
|
|||
|
||||
assert(MO.isExpr());
|
||||
const MCExpr *Expr = MO.getExpr();
|
||||
if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
|
||||
switch(SExpr->getKind()) {
|
||||
default: assert(0 && "Unhandled sparc expression!"); break;
|
||||
case SparcMCExpr::VK_Sparc_LO:
|
||||
Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
(MCFixupKind)Sparc::fixup_sparc_lo10));
|
||||
break;
|
||||
case SparcMCExpr::VK_Sparc_HI:
|
||||
Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
(MCFixupKind)Sparc::fixup_sparc_hi22));
|
||||
break;
|
||||
case SparcMCExpr::VK_Sparc_H44:
|
||||
Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
(MCFixupKind)Sparc::fixup_sparc_h44));
|
||||
break;
|
||||
case SparcMCExpr::VK_Sparc_M44:
|
||||
Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
(MCFixupKind)Sparc::fixup_sparc_m44));
|
||||
break;
|
||||
case SparcMCExpr::VK_Sparc_L44:
|
||||
Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
(MCFixupKind)Sparc::fixup_sparc_l44));
|
||||
break;
|
||||
case SparcMCExpr::VK_Sparc_HH:
|
||||
Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
(MCFixupKind)Sparc::fixup_sparc_hh));
|
||||
break;
|
||||
case SparcMCExpr::VK_Sparc_HM:
|
||||
Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
(MCFixupKind)Sparc::fixup_sparc_hm));
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t Res;
|
||||
if (Expr->EvaluateAsAbsolute(Res))
|
||||
return Res;
|
||||
|
|
|
@ -70,15 +70,67 @@ void SparcMCExpr::PrintImpl(raw_ostream &OS) const
|
|||
bool
|
||||
SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
|
||||
const MCAsmLayout *Layout) const {
|
||||
assert(0 && "FIXME: Implement SparcMCExpr::EvaluateAsRelocatableImpl");
|
||||
return getSubExpr()->EvaluateAsRelocatable(Res, *Layout);
|
||||
}
|
||||
|
||||
static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
|
||||
assert(0 && "Implement fixELFSymbolsInTLSFixupsImpl!");
|
||||
}
|
||||
|
||||
void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
|
||||
assert(0 && "FIXME: Implement SparcMCExpr::fixELFSymbolsInTLSFixups");
|
||||
switch(getKind()) {
|
||||
default: return;
|
||||
case VK_Sparc_TLS_GD_HI22:
|
||||
case VK_Sparc_TLS_GD_LO10:
|
||||
case VK_Sparc_TLS_GD_ADD:
|
||||
case VK_Sparc_TLS_GD_CALL:
|
||||
case VK_Sparc_TLS_LDM_HI22:
|
||||
case VK_Sparc_TLS_LDM_LO10:
|
||||
case VK_Sparc_TLS_LDM_ADD:
|
||||
case VK_Sparc_TLS_LDM_CALL:
|
||||
case VK_Sparc_TLS_LDO_HIX22:
|
||||
case VK_Sparc_TLS_LDO_LOX10:
|
||||
case VK_Sparc_TLS_LDO_ADD:
|
||||
case VK_Sparc_TLS_IE_HI22:
|
||||
case VK_Sparc_TLS_IE_LO10:
|
||||
case VK_Sparc_TLS_IE_LD:
|
||||
case VK_Sparc_TLS_IE_LDX:
|
||||
case VK_Sparc_TLS_IE_ADD:
|
||||
case VK_Sparc_TLS_LE_HIX22:
|
||||
case VK_Sparc_TLS_LE_LOX10: break;
|
||||
}
|
||||
fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
|
||||
}
|
||||
|
||||
// FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps
|
||||
// that method should be made public?
|
||||
// FIXME: really do above: now that at least three other backends are using it.
|
||||
static void AddValueSymbolsImpl(const MCExpr *Value, MCAssembler *Asm) {
|
||||
switch (Value->getKind()) {
|
||||
case MCExpr::Target:
|
||||
llvm_unreachable("Can't handle nested target expr!");
|
||||
break;
|
||||
|
||||
case MCExpr::Constant:
|
||||
break;
|
||||
|
||||
case MCExpr::Binary: {
|
||||
const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value);
|
||||
AddValueSymbolsImpl(BE->getLHS(), Asm);
|
||||
AddValueSymbolsImpl(BE->getRHS(), Asm);
|
||||
break;
|
||||
}
|
||||
|
||||
case MCExpr::SymbolRef:
|
||||
Asm->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol());
|
||||
break;
|
||||
|
||||
case MCExpr::Unary:
|
||||
AddValueSymbolsImpl(cast<MCUnaryExpr>(Value)->getSubExpr(), Asm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SparcMCExpr::AddValueSymbols(MCAssembler *Asm) const {
|
||||
assert(0 && "FIXME: Implement SparcMCExpr::AddValueSymbols");
|
||||
AddValueSymbolsImpl(getSubExpr(), Asm);
|
||||
}
|
||||
|
|
|
@ -89,6 +89,14 @@ static MCCodeGenInfo *createSparcV9MCCodeGenInfo(StringRef TT, Reloc::Model RM,
|
|||
return X;
|
||||
}
|
||||
|
||||
static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
|
||||
MCContext &Context, MCAsmBackend &MAB,
|
||||
raw_ostream &OS, MCCodeEmitter *Emitter,
|
||||
bool RelaxAll, bool NoExecStack) {
|
||||
SparcTargetELFStreamer *S = new SparcTargetELFStreamer();
|
||||
return createELFStreamer(Context, S, MAB, OS, Emitter, RelaxAll, NoExecStack);
|
||||
}
|
||||
|
||||
static MCStreamer *
|
||||
createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
|
||||
bool isVerboseAsm, bool useLoc, bool useCFI,
|
||||
|
@ -148,6 +156,13 @@ extern "C" void LLVMInitializeSparcTargetMC() {
|
|||
TargetRegistry::RegisterMCAsmBackend(TheSparcV9Target,
|
||||
createSparcAsmBackend);
|
||||
|
||||
// Register the object streamer.
|
||||
TargetRegistry::RegisterMCObjectStreamer(TheSparcTarget,
|
||||
createMCStreamer);
|
||||
TargetRegistry::RegisterMCObjectStreamer(TheSparcV9Target,
|
||||
createMCStreamer);
|
||||
|
||||
// Register the asm streamer.
|
||||
TargetRegistry::RegisterAsmStreamer(TheSparcTarget,
|
||||
createMCAsmStreamer);
|
||||
TargetRegistry::RegisterAsmStreamer(TheSparcV9Target,
|
||||
|
|
|
@ -14,15 +14,19 @@
|
|||
#ifndef SPARCMCTARGETDESC_H
|
||||
#define SPARCMCTARGETDESC_H
|
||||
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCAsmBackend;
|
||||
class MCCodeEmitter;
|
||||
class MCContext;
|
||||
class MCInstrInfo;
|
||||
class MCObjectWriter;
|
||||
class MCRegisterInfo;
|
||||
class MCSubtargetInfo;
|
||||
class Target;
|
||||
class StringRef;
|
||||
class raw_ostream;
|
||||
|
||||
extern Target TheSparcTarget;
|
||||
extern Target TheSparcV9Target;
|
||||
|
@ -35,7 +39,9 @@ MCAsmBackend *createSparcAsmBackend(const Target &T,
|
|||
const MCRegisterInfo &MRI,
|
||||
StringRef TT,
|
||||
StringRef CPU);
|
||||
|
||||
MCObjectWriter *createSparcELFObjectWriter(raw_ostream &OS,
|
||||
bool Is64Bit,
|
||||
uint8_t OSABI);
|
||||
} // End llvm namespace
|
||||
|
||||
// Defines symbolic names for Sparc registers. This defines a mapping from
|
||||
|
|
Loading…
Reference in New Issue