diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Sparc/MCTargetDesc')
11 files changed, 1465 insertions, 0 deletions
diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp new file mode 100644 index 000000000000..f2438ee43075 --- /dev/null +++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -0,0 +1,309 @@ +//===-- SparcAsmBackend.cpp - Sparc Assembler Backend ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/SparcFixupKinds.h" +#include "MCTargetDesc/SparcMCTargetDesc.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCValue.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_wplt30: + case Sparc::fixup_sparc_call30: + return (Value >> 2) & 0x3fffffff; + + case Sparc::fixup_sparc_br22: + return (Value >> 2) & 0x3fffff; + + case Sparc::fixup_sparc_br19: + return (Value >> 2) & 0x7ffff; + + case Sparc::fixup_sparc_br16_2: + return (Value >> 2) & 0xc000; + + case Sparc::fixup_sparc_br16_14: + return (Value >> 2) & 0x3fff; + + case Sparc::fixup_sparc_pc22: + case Sparc::fixup_sparc_got22: + case Sparc::fixup_sparc_tls_gd_hi22: + case Sparc::fixup_sparc_tls_ldm_hi22: + case Sparc::fixup_sparc_tls_ie_hi22: + case Sparc::fixup_sparc_hi22: + return (Value >> 10) & 0x3fffff; + + case Sparc::fixup_sparc_pc10: + case Sparc::fixup_sparc_got10: + case Sparc::fixup_sparc_tls_gd_lo10: + case Sparc::fixup_sparc_tls_ldm_lo10: + case Sparc::fixup_sparc_tls_ie_lo10: + 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; + + case Sparc::fixup_sparc_tls_ldo_hix22: + case Sparc::fixup_sparc_tls_le_hix22: + case Sparc::fixup_sparc_tls_ldo_lox10: + case Sparc::fixup_sparc_tls_le_lox10: + assert(Value == 0 && "Sparc TLS relocs expect zero Value"); + return 0; + + case Sparc::fixup_sparc_tls_gd_add: + case Sparc::fixup_sparc_tls_gd_call: + case Sparc::fixup_sparc_tls_ldm_add: + case Sparc::fixup_sparc_tls_ldm_call: + case Sparc::fixup_sparc_tls_ldo_add: + case Sparc::fixup_sparc_tls_ie_ld: + case Sparc::fixup_sparc_tls_ie_ldx: + case Sparc::fixup_sparc_tls_ie_add: + return 0; + } +} + +namespace { + class SparcAsmBackend : public MCAsmBackend { + protected: + const Target &TheTarget; + bool IsLittleEndian; + bool Is64Bit; + + public: + SparcAsmBackend(const Target &T) + : MCAsmBackend(), TheTarget(T), + IsLittleEndian(StringRef(TheTarget.getName()) == "sparcel"), + Is64Bit(StringRef(TheTarget.getName()) == "sparcv9") {} + + unsigned getNumFixupKinds() const override { + return Sparc::NumTargetFixupKinds; + } + + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { + const static MCFixupKindInfo InfosBE[Sparc::NumTargetFixupKinds] = { + // name offset bits flags + { "fixup_sparc_call30", 2, 30, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_br22", 10, 22, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_br19", 13, 19, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_br16_2", 10, 2, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_br16_14", 18, 14, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_hi22", 10, 22, 0 }, + { "fixup_sparc_lo10", 22, 10, 0 }, + { "fixup_sparc_h44", 10, 22, 0 }, + { "fixup_sparc_m44", 22, 10, 0 }, + { "fixup_sparc_l44", 20, 12, 0 }, + { "fixup_sparc_hh", 10, 22, 0 }, + { "fixup_sparc_hm", 22, 10, 0 }, + { "fixup_sparc_pc22", 10, 22, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_pc10", 22, 10, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_got22", 10, 22, 0 }, + { "fixup_sparc_got10", 22, 10, 0 }, + { "fixup_sparc_wplt30", 2, 30, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_tls_gd_hi22", 10, 22, 0 }, + { "fixup_sparc_tls_gd_lo10", 22, 10, 0 }, + { "fixup_sparc_tls_gd_add", 0, 0, 0 }, + { "fixup_sparc_tls_gd_call", 0, 0, 0 }, + { "fixup_sparc_tls_ldm_hi22", 10, 22, 0 }, + { "fixup_sparc_tls_ldm_lo10", 22, 10, 0 }, + { "fixup_sparc_tls_ldm_add", 0, 0, 0 }, + { "fixup_sparc_tls_ldm_call", 0, 0, 0 }, + { "fixup_sparc_tls_ldo_hix22", 10, 22, 0 }, + { "fixup_sparc_tls_ldo_lox10", 22, 10, 0 }, + { "fixup_sparc_tls_ldo_add", 0, 0, 0 }, + { "fixup_sparc_tls_ie_hi22", 10, 22, 0 }, + { "fixup_sparc_tls_ie_lo10", 22, 10, 0 }, + { "fixup_sparc_tls_ie_ld", 0, 0, 0 }, + { "fixup_sparc_tls_ie_ldx", 0, 0, 0 }, + { "fixup_sparc_tls_ie_add", 0, 0, 0 }, + { "fixup_sparc_tls_le_hix22", 0, 0, 0 }, + { "fixup_sparc_tls_le_lox10", 0, 0, 0 } + }; + + const static MCFixupKindInfo InfosLE[Sparc::NumTargetFixupKinds] = { + // 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_br16_2", 20, 2, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_br16_14", 0, 14, 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, 22, 0 }, + { "fixup_sparc_hm", 0, 10, 0 }, + { "fixup_sparc_pc22", 0, 22, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_pc10", 0, 10, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_got22", 0, 22, 0 }, + { "fixup_sparc_got10", 0, 10, 0 }, + { "fixup_sparc_wplt30", 0, 30, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_tls_gd_hi22", 0, 22, 0 }, + { "fixup_sparc_tls_gd_lo10", 0, 10, 0 }, + { "fixup_sparc_tls_gd_add", 0, 0, 0 }, + { "fixup_sparc_tls_gd_call", 0, 0, 0 }, + { "fixup_sparc_tls_ldm_hi22", 0, 22, 0 }, + { "fixup_sparc_tls_ldm_lo10", 0, 10, 0 }, + { "fixup_sparc_tls_ldm_add", 0, 0, 0 }, + { "fixup_sparc_tls_ldm_call", 0, 0, 0 }, + { "fixup_sparc_tls_ldo_hix22", 0, 22, 0 }, + { "fixup_sparc_tls_ldo_lox10", 0, 10, 0 }, + { "fixup_sparc_tls_ldo_add", 0, 0, 0 }, + { "fixup_sparc_tls_ie_hi22", 0, 22, 0 }, + { "fixup_sparc_tls_ie_lo10", 0, 10, 0 }, + { "fixup_sparc_tls_ie_ld", 0, 0, 0 }, + { "fixup_sparc_tls_ie_ldx", 0, 0, 0 }, + { "fixup_sparc_tls_ie_add", 0, 0, 0 }, + { "fixup_sparc_tls_le_hix22", 0, 0, 0 }, + { "fixup_sparc_tls_le_lox10", 0, 0, 0 } + }; + + if (Kind < FirstTargetFixupKind) + return MCAsmBackend::getFixupKindInfo(Kind); + + assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && + "Invalid kind!"); + if (IsLittleEndian) + return InfosLE[Kind - FirstTargetFixupKind]; + + return InfosBE[Kind - FirstTargetFixupKind]; + } + + bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target) override { + switch ((Sparc::Fixups)Fixup.getKind()) { + default: + return false; + case Sparc::fixup_sparc_wplt30: + if (Target.getSymA()->getSymbol().isTemporary()) + return false; + LLVM_FALLTHROUGH; + case Sparc::fixup_sparc_tls_gd_hi22: + case Sparc::fixup_sparc_tls_gd_lo10: + case Sparc::fixup_sparc_tls_gd_add: + case Sparc::fixup_sparc_tls_gd_call: + case Sparc::fixup_sparc_tls_ldm_hi22: + case Sparc::fixup_sparc_tls_ldm_lo10: + case Sparc::fixup_sparc_tls_ldm_add: + case Sparc::fixup_sparc_tls_ldm_call: + case Sparc::fixup_sparc_tls_ldo_hix22: + case Sparc::fixup_sparc_tls_ldo_lox10: + case Sparc::fixup_sparc_tls_ldo_add: + case Sparc::fixup_sparc_tls_ie_hi22: + case Sparc::fixup_sparc_tls_ie_lo10: + case Sparc::fixup_sparc_tls_ie_ld: + case Sparc::fixup_sparc_tls_ie_ldx: + case Sparc::fixup_sparc_tls_ie_add: + case Sparc::fixup_sparc_tls_le_hix22: + case Sparc::fixup_sparc_tls_le_lox10: + return true; + } + } + + bool mayNeedRelaxation(const MCInst &Inst) const override { + // FIXME. + return false; + } + + /// fixupNeedsRelaxation - Target specific predicate for whether a given + /// fixup requires the associated instruction to be relaxed. + bool fixupNeedsRelaxation(const MCFixup &Fixup, + uint64_t Value, + const MCRelaxableFragment *DF, + const MCAsmLayout &Layout) const override { + // FIXME. + llvm_unreachable("fixupNeedsRelaxation() unimplemented"); + return false; + } + void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, + MCInst &Res) const override { + // FIXME. + llvm_unreachable("relaxInstruction() unimplemented"); + } + + bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override { + // Cannot emit NOP with size not multiple of 32 bits. + if (Count % 4 != 0) + return false; + + uint64_t NumNops = Count / 4; + for (uint64_t i = 0; i != NumNops; ++i) + OW->write32(0x01000000); + + return true; + } + }; + + class ELFSparcAsmBackend : public SparcAsmBackend { + Triple::OSType OSType; + public: + ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) : + SparcAsmBackend(T), OSType(OSType) { } + + void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target, MutableArrayRef<char> Data, + uint64_t Value, bool IsResolved) const override { + + 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) { + unsigned Idx = IsLittleEndian ? i : 3 - i; + Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff); + } + } + + std::unique_ptr<MCObjectWriter> + createObjectWriter(raw_pwrite_stream &OS) const override { + uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType); + return createSparcELFObjectWriter(OS, Is64Bit, IsLittleEndian, OSABI); + } + }; + +} // end anonymous namespace + +MCAsmBackend *llvm::createSparcAsmBackend(const Target &T, + const MCSubtargetInfo &STI, + const MCRegisterInfo &MRI, + const MCTargetOptions &Options) { + return new ELFSparcAsmBackend(T, STI.getTargetTriple().getOS()); +} diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp new file mode 100644 index 000000000000..a204036a0975 --- /dev/null +++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp @@ -0,0 +1,140 @@ +//===-- 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/SparcFixupKinds.h" +#include "MCTargetDesc/SparcMCExpr.h" +#include "MCTargetDesc/SparcMCTargetDesc.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCObjectWriter.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) {} + + ~SparcELFObjectWriter() override {} + + protected: + unsigned getRelocType(MCContext &Ctx, const MCValue &Target, + const MCFixup &Fixup, bool IsPCRel) const override; + + bool needsRelocateWithSymbol(const MCSymbol &Sym, + unsigned Type) const override; + + }; +} + +unsigned SparcELFObjectWriter::getRelocType(MCContext &Ctx, + const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel) const { + + if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Fixup.getValue())) { + if (SExpr->getKind() == SparcMCExpr::VK_Sparc_R_DISP32) + return ELF::R_SPARC_DISP32; + } + + 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; + case Sparc::fixup_sparc_pc22: return ELF::R_SPARC_PC22; + case Sparc::fixup_sparc_pc10: return ELF::R_SPARC_PC10; + case Sparc::fixup_sparc_wplt30: return ELF::R_SPARC_WPLT30; + } + } + + 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; + case Sparc::fixup_sparc_got22: return ELF::R_SPARC_GOT22; + case Sparc::fixup_sparc_got10: return ELF::R_SPARC_GOT10; + case Sparc::fixup_sparc_tls_gd_hi22: return ELF::R_SPARC_TLS_GD_HI22; + case Sparc::fixup_sparc_tls_gd_lo10: return ELF::R_SPARC_TLS_GD_LO10; + case Sparc::fixup_sparc_tls_gd_add: return ELF::R_SPARC_TLS_GD_ADD; + case Sparc::fixup_sparc_tls_gd_call: return ELF::R_SPARC_TLS_GD_CALL; + case Sparc::fixup_sparc_tls_ldm_hi22: return ELF::R_SPARC_TLS_LDM_HI22; + case Sparc::fixup_sparc_tls_ldm_lo10: return ELF::R_SPARC_TLS_LDM_LO10; + case Sparc::fixup_sparc_tls_ldm_add: return ELF::R_SPARC_TLS_LDM_ADD; + case Sparc::fixup_sparc_tls_ldm_call: return ELF::R_SPARC_TLS_LDM_CALL; + case Sparc::fixup_sparc_tls_ldo_hix22: return ELF::R_SPARC_TLS_LDO_HIX22; + case Sparc::fixup_sparc_tls_ldo_lox10: return ELF::R_SPARC_TLS_LDO_LOX10; + case Sparc::fixup_sparc_tls_ldo_add: return ELF::R_SPARC_TLS_LDO_ADD; + case Sparc::fixup_sparc_tls_ie_hi22: return ELF::R_SPARC_TLS_IE_HI22; + case Sparc::fixup_sparc_tls_ie_lo10: return ELF::R_SPARC_TLS_IE_LO10; + case Sparc::fixup_sparc_tls_ie_ld: return ELF::R_SPARC_TLS_IE_LD; + case Sparc::fixup_sparc_tls_ie_ldx: return ELF::R_SPARC_TLS_IE_LDX; + case Sparc::fixup_sparc_tls_ie_add: return ELF::R_SPARC_TLS_IE_ADD; + case Sparc::fixup_sparc_tls_le_hix22: return ELF::R_SPARC_TLS_LE_HIX22; + case Sparc::fixup_sparc_tls_le_lox10: return ELF::R_SPARC_TLS_LE_LOX10; + } + + return ELF::R_SPARC_NONE; +} + +bool SparcELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym, + unsigned Type) const { + switch (Type) { + default: + return false; + + // All relocations that use a GOT need a symbol, not an offset, as + // the offset of the symbol within the section is irrelevant to + // where the GOT entry is. Don't need to list all the TLS entries, + // as they're all marked as requiring a symbol anyways. + case ELF::R_SPARC_GOT10: + case ELF::R_SPARC_GOT13: + case ELF::R_SPARC_GOT22: + case ELF::R_SPARC_GOTDATA_HIX22: + case ELF::R_SPARC_GOTDATA_LOX10: + case ELF::R_SPARC_GOTDATA_OP_HIX22: + case ELF::R_SPARC_GOTDATA_OP_LOX10: + return true; + } +} + +std::unique_ptr<MCObjectWriter> +llvm::createSparcELFObjectWriter(raw_pwrite_stream &OS, bool Is64Bit, + bool IsLittleEndian, uint8_t OSABI) { + auto MOTW = llvm::make_unique<SparcELFObjectWriter>(Is64Bit, OSABI); + return createELFObjectWriter(std::move(MOTW), OS, IsLittleEndian); +} diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h new file mode 100644 index 000000000000..8d79396d936e --- /dev/null +++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h @@ -0,0 +1,97 @@ +//===-- SparcFixupKinds.h - Sparc Specific Fixup Entries --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCFIXUPKINDS_H +#define LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCFIXUPKINDS_H + +#include "llvm/MC/MCFixup.h" + +namespace llvm { + namespace Sparc { + enum Fixups { + // fixup_sparc_call30 - 30-bit PC relative relocation for call + fixup_sparc_call30 = FirstTargetFixupKind, + + /// fixup_sparc_br22 - 22-bit PC relative relocation for + /// branches + fixup_sparc_br22, + + /// fixup_sparc_br19 - 19-bit PC relative relocation for + /// branches on icc/xcc + fixup_sparc_br19, + + /// fixup_sparc_bpr - 16-bit fixup for bpr + fixup_sparc_br16_2, + fixup_sparc_br16_14, + + /// 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, + + /// fixup_sparc_pc22 - 22-bit fixup corresponding to %pc22(foo) + fixup_sparc_pc22, + + /// fixup_sparc_pc10 - 10-bit fixup corresponding to %pc10(foo) + fixup_sparc_pc10, + + /// fixup_sparc_got22 - 22-bit fixup corresponding to %got22(foo) + fixup_sparc_got22, + + /// fixup_sparc_got10 - 10-bit fixup corresponding to %got10(foo) + fixup_sparc_got10, + + /// fixup_sparc_wplt30 + fixup_sparc_wplt30, + + /// fixups for Thread Local Storage + fixup_sparc_tls_gd_hi22, + fixup_sparc_tls_gd_lo10, + fixup_sparc_tls_gd_add, + fixup_sparc_tls_gd_call, + fixup_sparc_tls_ldm_hi22, + fixup_sparc_tls_ldm_lo10, + fixup_sparc_tls_ldm_add, + fixup_sparc_tls_ldm_call, + fixup_sparc_tls_ldo_hix22, + fixup_sparc_tls_ldo_lox10, + fixup_sparc_tls_ldo_add, + fixup_sparc_tls_ie_hi22, + fixup_sparc_tls_ie_lo10, + fixup_sparc_tls_ie_ld, + fixup_sparc_tls_ie_ldx, + fixup_sparc_tls_ie_add, + fixup_sparc_tls_le_hix22, + fixup_sparc_tls_le_lox10, + + // Marker + LastTargetFixupKind, + NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind + }; + } +} + +#endif diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp new file mode 100644 index 000000000000..50e8825b15e8 --- /dev/null +++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp @@ -0,0 +1,73 @@ +//===- SparcMCAsmInfo.cpp - Sparc asm properties --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations of the SparcMCAsmInfo properties. +// +//===----------------------------------------------------------------------===// + +#include "SparcMCAsmInfo.h" +#include "SparcMCExpr.h" +#include "llvm/ADT/Triple.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCTargetOptions.h" + +using namespace llvm; + +void SparcELFMCAsmInfo::anchor() {} + +SparcELFMCAsmInfo::SparcELFMCAsmInfo(const Triple &TheTriple) { + bool isV9 = (TheTriple.getArch() == Triple::sparcv9); + IsLittleEndian = (TheTriple.getArch() == Triple::sparcel); + + if (isV9) { + CodePointerSize = CalleeSaveStackSlotSize = 8; + } + + Data16bitsDirective = "\t.half\t"; + Data32bitsDirective = "\t.word\t"; + // .xword is only supported by V9. + Data64bitsDirective = (isV9) ? "\t.xword\t" : nullptr; + ZeroDirective = "\t.skip\t"; + CommentString = "!"; + SupportsDebugInformation = true; + + ExceptionsType = ExceptionHandling::DwarfCFI; + + SunStyleELFSectionSwitchSyntax = true; + UsesELFSectionDirectiveForBSS = true; + + UseIntegratedAssembler = true; +} + +const MCExpr* +SparcELFMCAsmInfo::getExprForPersonalitySymbol(const MCSymbol *Sym, + unsigned Encoding, + MCStreamer &Streamer) const { + if (Encoding & dwarf::DW_EH_PE_pcrel) { + MCContext &Ctx = Streamer.getContext(); + return SparcMCExpr::create(SparcMCExpr::VK_Sparc_R_DISP32, + MCSymbolRefExpr::create(Sym, Ctx), Ctx); + } + + return MCAsmInfo::getExprForPersonalitySymbol(Sym, Encoding, Streamer); +} + +const MCExpr* +SparcELFMCAsmInfo::getExprForFDESymbol(const MCSymbol *Sym, + unsigned Encoding, + MCStreamer &Streamer) const { + if (Encoding & dwarf::DW_EH_PE_pcrel) { + MCContext &Ctx = Streamer.getContext(); + return SparcMCExpr::create(SparcMCExpr::VK_Sparc_R_DISP32, + MCSymbolRefExpr::create(Sym, Ctx), Ctx); + } + return MCAsmInfo::getExprForFDESymbol(Sym, Encoding, Streamer); +} diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h new file mode 100644 index 000000000000..5e8d0cb50312 --- /dev/null +++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h @@ -0,0 +1,40 @@ +//===- SparcMCAsmInfo.h - Sparc asm properties -----------------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the SparcMCAsmInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCMCASMINFO_H +#define LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCMCASMINFO_H + +#include "llvm/MC/MCAsmInfoELF.h" + +namespace llvm { + +class Triple; + +class SparcELFMCAsmInfo : public MCAsmInfoELF { + void anchor() override; + +public: + explicit SparcELFMCAsmInfo(const Triple &TheTriple); + + const MCExpr* + getExprForPersonalitySymbol(const MCSymbol *Sym, unsigned Encoding, + MCStreamer &Streamer) const override; + const MCExpr* getExprForFDESymbol(const MCSymbol *Sym, + unsigned Encoding, + MCStreamer &Streamer) const override; + +}; + +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCMCASMINFO_H diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp new file mode 100644 index 000000000000..684f66970dbe --- /dev/null +++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp @@ -0,0 +1,238 @@ +//===-- SparcMCCodeEmitter.cpp - Convert Sparc code to machine code -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SparcMCCodeEmitter class. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/SparcFixupKinds.h" +#include "SparcMCExpr.h" +#include "SparcMCTargetDesc.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/EndianStream.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstdint> + +using namespace llvm; + +#define DEBUG_TYPE "mccodeemitter" + +STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); + +namespace { + +class SparcMCCodeEmitter : public MCCodeEmitter { + const MCInstrInfo &MCII; + MCContext &Ctx; + +public: + SparcMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) + : MCII(mcii), Ctx(ctx) {} + SparcMCCodeEmitter(const SparcMCCodeEmitter &) = delete; + SparcMCCodeEmitter &operator=(const SparcMCCodeEmitter &) = delete; + ~SparcMCCodeEmitter() override = default; + + void encodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const override; + + // getBinaryCodeForInstr - TableGen'erated function for getting the + // binary encoding for an instruction. + uint64_t getBinaryCodeForInstr(const MCInst &MI, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + + /// getMachineOpValue - Return binary encoding of operand. If the machine + /// operand requires relocation, record the relocation and return zero. + unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + +private: + uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; + void verifyInstructionPredicates(const MCInst &MI, + uint64_t AvailableFeatures) const; +}; + +} // end anonymous namespace + +void SparcMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + verifyInstructionPredicates(MI, + computeAvailableFeatures(STI.getFeatureBits())); + + unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI); + + if (Ctx.getAsmInfo()->isLittleEndian()) { + // Output the bits in little-endian byte order. + support::endian::Writer<support::little>(OS).write<uint32_t>(Bits); + } else { + // Output the bits in big-endian byte order. + support::endian::Writer<support::big>(OS).write<uint32_t>(Bits); + } + unsigned tlsOpNo = 0; + switch (MI.getOpcode()) { + default: break; + case SP::TLS_CALL: tlsOpNo = 1; break; + case SP::TLS_ADDrr: + case SP::TLS_ADDXrr: + case SP::TLS_LDrr: + case SP::TLS_LDXrr: tlsOpNo = 3; break; + } + if (tlsOpNo != 0) { + const MCOperand &MO = MI.getOperand(tlsOpNo); + uint64_t op = getMachineOpValue(MI, MO, Fixups, STI); + assert(op == 0 && "Unexpected operand value!"); + (void)op; // suppress warning. + } + + ++MCNumEmitted; // Keep track of the # of mi's emitted. +} + +unsigned SparcMCCodeEmitter:: +getMachineOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + if (MO.isReg()) + return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); + + if (MO.isImm()) + return MO.getImm(); + + assert(MO.isExpr()); + const MCExpr *Expr = MO.getExpr(); + if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) { + MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind(); + Fixups.push_back(MCFixup::create(0, Expr, Kind)); + return 0; + } + + int64_t Res; + if (Expr->evaluateAsAbsolute(Res)) + return Res; + + llvm_unreachable("Unhandled expression!"); + return 0; +} + +unsigned SparcMCCodeEmitter:: +getCallTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + if (MO.isReg() || MO.isImm()) + return getMachineOpValue(MI, MO, Fixups, STI); + + if (MI.getOpcode() == SP::TLS_CALL) { + // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in + // encodeInstruction. +#ifndef NDEBUG + // Verify that the callee is actually __tls_get_addr. + const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr()); + assert(SExpr && SExpr->getSubExpr()->getKind() == MCExpr::SymbolRef && + "Unexpected expression in TLS_CALL"); + const MCSymbolRefExpr *SymExpr = cast<MCSymbolRefExpr>(SExpr->getSubExpr()); + assert(SymExpr->getSymbol().getName() == "__tls_get_addr" && + "Unexpected function for TLS_CALL"); +#endif + return 0; + } + + MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30; + + if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr())) { + if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30) + fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30; + } + + Fixups.push_back(MCFixup::create(0, MO.getExpr(), fixupKind)); + + return 0; +} + +unsigned SparcMCCodeEmitter:: +getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + if (MO.isReg() || MO.isImm()) + return getMachineOpValue(MI, MO, Fixups, STI); + + Fixups.push_back(MCFixup::create(0, MO.getExpr(), + (MCFixupKind)Sparc::fixup_sparc_br22)); + return 0; +} + +unsigned SparcMCCodeEmitter:: +getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + if (MO.isReg() || MO.isImm()) + return getMachineOpValue(MI, MO, Fixups, STI); + + Fixups.push_back(MCFixup::create(0, MO.getExpr(), + (MCFixupKind)Sparc::fixup_sparc_br19)); + return 0; +} + +unsigned SparcMCCodeEmitter:: +getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + if (MO.isReg() || MO.isImm()) + return getMachineOpValue(MI, MO, Fixups, STI); + + Fixups.push_back(MCFixup::create(0, MO.getExpr(), + (MCFixupKind)Sparc::fixup_sparc_br16_2)); + Fixups.push_back(MCFixup::create(0, MO.getExpr(), + (MCFixupKind)Sparc::fixup_sparc_br16_14)); + + return 0; +} + +#define ENABLE_INSTR_PREDICATE_VERIFIER +#include "SparcGenMCCodeEmitter.inc" + +MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + MCContext &Ctx) { + return new SparcMCCodeEmitter(MCII, Ctx); +} diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp new file mode 100644 index 000000000000..a77f760d9eff --- /dev/null +++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp @@ -0,0 +1,220 @@ +//===-- SparcMCExpr.cpp - Sparc specific MC expression classes --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the implementation of the assembly expression modifiers +// accepted by the Sparc architecture (e.g. "%hi", "%lo", ...). +// +//===----------------------------------------------------------------------===// + +#include "SparcMCExpr.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCSymbolELF.h" +#include "llvm/Object/ELF.h" + +using namespace llvm; + +#define DEBUG_TYPE "sparcmcexpr" + +const SparcMCExpr* +SparcMCExpr::create(VariantKind Kind, const MCExpr *Expr, + MCContext &Ctx) { + return new (Ctx) SparcMCExpr(Kind, Expr); +} + +void SparcMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { + + bool closeParen = printVariantKind(OS, Kind); + + const MCExpr *Expr = getSubExpr(); + Expr->print(OS, MAI); + + if (closeParen) + OS << ')'; +} + +bool SparcMCExpr::printVariantKind(raw_ostream &OS, VariantKind Kind) +{ + bool closeParen = true; + switch (Kind) { + case VK_Sparc_None: closeParen = false; break; + case VK_Sparc_LO: OS << "%lo("; break; + case VK_Sparc_HI: OS << "%hi("; break; + case VK_Sparc_H44: OS << "%h44("; break; + case VK_Sparc_M44: OS << "%m44("; break; + case VK_Sparc_L44: OS << "%l44("; break; + case VK_Sparc_HH: OS << "%hh("; break; + case VK_Sparc_HM: OS << "%hm("; break; + // FIXME: use %pc22/%pc10, if system assembler supports them. + case VK_Sparc_PC22: OS << "%hi("; break; + case VK_Sparc_PC10: OS << "%lo("; break; + // FIXME: use %got22/%got10, if system assembler supports them. + case VK_Sparc_GOT22: OS << "%hi("; break; + case VK_Sparc_GOT10: OS << "%lo("; break; + case VK_Sparc_WPLT30: closeParen = false; break; + case VK_Sparc_R_DISP32: OS << "%r_disp32("; break; + case VK_Sparc_TLS_GD_HI22: OS << "%tgd_hi22("; break; + case VK_Sparc_TLS_GD_LO10: OS << "%tgd_lo10("; break; + case VK_Sparc_TLS_GD_ADD: OS << "%tgd_add("; break; + case VK_Sparc_TLS_GD_CALL: OS << "%tgd_call("; break; + case VK_Sparc_TLS_LDM_HI22: OS << "%tldm_hi22("; break; + case VK_Sparc_TLS_LDM_LO10: OS << "%tldm_lo10("; break; + case VK_Sparc_TLS_LDM_ADD: OS << "%tldm_add("; break; + case VK_Sparc_TLS_LDM_CALL: OS << "%tldm_call("; break; + case VK_Sparc_TLS_LDO_HIX22: OS << "%tldo_hix22("; break; + case VK_Sparc_TLS_LDO_LOX10: OS << "%tldo_lox10("; break; + case VK_Sparc_TLS_LDO_ADD: OS << "%tldo_add("; break; + case VK_Sparc_TLS_IE_HI22: OS << "%tie_hi22("; break; + case VK_Sparc_TLS_IE_LO10: OS << "%tie_lo10("; break; + case VK_Sparc_TLS_IE_LD: OS << "%tie_ld("; break; + case VK_Sparc_TLS_IE_LDX: OS << "%tie_ldx("; break; + case VK_Sparc_TLS_IE_ADD: OS << "%tie_add("; break; + case VK_Sparc_TLS_LE_HIX22: OS << "%tle_hix22("; break; + case VK_Sparc_TLS_LE_LOX10: OS << "%tle_lox10("; break; + } + return closeParen; +} + +SparcMCExpr::VariantKind SparcMCExpr::parseVariantKind(StringRef name) +{ + return StringSwitch<SparcMCExpr::VariantKind>(name) + .Case("lo", VK_Sparc_LO) + .Case("hi", VK_Sparc_HI) + .Case("h44", VK_Sparc_H44) + .Case("m44", VK_Sparc_M44) + .Case("l44", VK_Sparc_L44) + .Case("hh", VK_Sparc_HH) + .Case("hm", VK_Sparc_HM) + .Case("pc22", VK_Sparc_PC22) + .Case("pc10", VK_Sparc_PC10) + .Case("got22", VK_Sparc_GOT22) + .Case("got10", VK_Sparc_GOT10) + .Case("r_disp32", VK_Sparc_R_DISP32) + .Case("tgd_hi22", VK_Sparc_TLS_GD_HI22) + .Case("tgd_lo10", VK_Sparc_TLS_GD_LO10) + .Case("tgd_add", VK_Sparc_TLS_GD_ADD) + .Case("tgd_call", VK_Sparc_TLS_GD_CALL) + .Case("tldm_hi22", VK_Sparc_TLS_LDM_HI22) + .Case("tldm_lo10", VK_Sparc_TLS_LDM_LO10) + .Case("tldm_add", VK_Sparc_TLS_LDM_ADD) + .Case("tldm_call", VK_Sparc_TLS_LDM_CALL) + .Case("tldo_hix22", VK_Sparc_TLS_LDO_HIX22) + .Case("tldo_lox10", VK_Sparc_TLS_LDO_LOX10) + .Case("tldo_add", VK_Sparc_TLS_LDO_ADD) + .Case("tie_hi22", VK_Sparc_TLS_IE_HI22) + .Case("tie_lo10", VK_Sparc_TLS_IE_LO10) + .Case("tie_ld", VK_Sparc_TLS_IE_LD) + .Case("tie_ldx", VK_Sparc_TLS_IE_LDX) + .Case("tie_add", VK_Sparc_TLS_IE_ADD) + .Case("tle_hix22", VK_Sparc_TLS_LE_HIX22) + .Case("tle_lox10", VK_Sparc_TLS_LE_LOX10) + .Default(VK_Sparc_None); +} + +Sparc::Fixups SparcMCExpr::getFixupKind(SparcMCExpr::VariantKind Kind) { + switch (Kind) { + default: llvm_unreachable("Unhandled SparcMCExpr::VariantKind"); + case VK_Sparc_LO: return Sparc::fixup_sparc_lo10; + case VK_Sparc_HI: return Sparc::fixup_sparc_hi22; + case VK_Sparc_H44: return Sparc::fixup_sparc_h44; + case VK_Sparc_M44: return Sparc::fixup_sparc_m44; + case VK_Sparc_L44: return Sparc::fixup_sparc_l44; + case VK_Sparc_HH: return Sparc::fixup_sparc_hh; + case VK_Sparc_HM: return Sparc::fixup_sparc_hm; + case VK_Sparc_PC22: return Sparc::fixup_sparc_pc22; + case VK_Sparc_PC10: return Sparc::fixup_sparc_pc10; + case VK_Sparc_GOT22: return Sparc::fixup_sparc_got22; + case VK_Sparc_GOT10: return Sparc::fixup_sparc_got10; + case VK_Sparc_WPLT30: return Sparc::fixup_sparc_wplt30; + case VK_Sparc_TLS_GD_HI22: return Sparc::fixup_sparc_tls_gd_hi22; + case VK_Sparc_TLS_GD_LO10: return Sparc::fixup_sparc_tls_gd_lo10; + case VK_Sparc_TLS_GD_ADD: return Sparc::fixup_sparc_tls_gd_add; + case VK_Sparc_TLS_GD_CALL: return Sparc::fixup_sparc_tls_gd_call; + case VK_Sparc_TLS_LDM_HI22: return Sparc::fixup_sparc_tls_ldm_hi22; + case VK_Sparc_TLS_LDM_LO10: return Sparc::fixup_sparc_tls_ldm_lo10; + case VK_Sparc_TLS_LDM_ADD: return Sparc::fixup_sparc_tls_ldm_add; + case VK_Sparc_TLS_LDM_CALL: return Sparc::fixup_sparc_tls_ldm_call; + case VK_Sparc_TLS_LDO_HIX22: return Sparc::fixup_sparc_tls_ldo_hix22; + case VK_Sparc_TLS_LDO_LOX10: return Sparc::fixup_sparc_tls_ldo_lox10; + case VK_Sparc_TLS_LDO_ADD: return Sparc::fixup_sparc_tls_ldo_add; + case VK_Sparc_TLS_IE_HI22: return Sparc::fixup_sparc_tls_ie_hi22; + case VK_Sparc_TLS_IE_LO10: return Sparc::fixup_sparc_tls_ie_lo10; + case VK_Sparc_TLS_IE_LD: return Sparc::fixup_sparc_tls_ie_ld; + case VK_Sparc_TLS_IE_LDX: return Sparc::fixup_sparc_tls_ie_ldx; + case VK_Sparc_TLS_IE_ADD: return Sparc::fixup_sparc_tls_ie_add; + case VK_Sparc_TLS_LE_HIX22: return Sparc::fixup_sparc_tls_le_hix22; + case VK_Sparc_TLS_LE_LOX10: return Sparc::fixup_sparc_tls_le_lox10; + } +} + +bool +SparcMCExpr::evaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout, + const MCFixup *Fixup) const { + return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup); +} + +static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { + switch (Expr->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>(Expr); + fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); + fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); + break; + } + + case MCExpr::SymbolRef: { + const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr); + cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS); + break; + } + + case MCExpr::Unary: + fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm); + break; + } + +} + +void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { + 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); +} + +void SparcMCExpr::visitUsedExpr(MCStreamer &Streamer) const { + Streamer.visitUsedExpr(*getSubExpr()); +} diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h new file mode 100644 index 000000000000..13f08195c764 --- /dev/null +++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h @@ -0,0 +1,112 @@ +//====- SparcMCExpr.h - Sparc specific MC expression classes --*- C++ -*-=====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes Sparc-specific MCExprs, used for modifiers like +// "%hi" or "%lo" etc., +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCMCEXPR_H +#define LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCMCEXPR_H + +#include "SparcFixupKinds.h" +#include "llvm/MC/MCExpr.h" + +namespace llvm { + +class StringRef; +class SparcMCExpr : public MCTargetExpr { +public: + enum VariantKind { + VK_Sparc_None, + VK_Sparc_LO, + VK_Sparc_HI, + VK_Sparc_H44, + VK_Sparc_M44, + VK_Sparc_L44, + VK_Sparc_HH, + VK_Sparc_HM, + VK_Sparc_PC22, + VK_Sparc_PC10, + VK_Sparc_GOT22, + VK_Sparc_GOT10, + VK_Sparc_WPLT30, + VK_Sparc_R_DISP32, + VK_Sparc_TLS_GD_HI22, + VK_Sparc_TLS_GD_LO10, + VK_Sparc_TLS_GD_ADD, + VK_Sparc_TLS_GD_CALL, + VK_Sparc_TLS_LDM_HI22, + VK_Sparc_TLS_LDM_LO10, + VK_Sparc_TLS_LDM_ADD, + VK_Sparc_TLS_LDM_CALL, + VK_Sparc_TLS_LDO_HIX22, + VK_Sparc_TLS_LDO_LOX10, + VK_Sparc_TLS_LDO_ADD, + VK_Sparc_TLS_IE_HI22, + VK_Sparc_TLS_IE_LO10, + VK_Sparc_TLS_IE_LD, + VK_Sparc_TLS_IE_LDX, + VK_Sparc_TLS_IE_ADD, + VK_Sparc_TLS_LE_HIX22, + VK_Sparc_TLS_LE_LOX10 + }; + +private: + const VariantKind Kind; + const MCExpr *Expr; + + explicit SparcMCExpr(VariantKind Kind, const MCExpr *Expr) + : Kind(Kind), Expr(Expr) {} + +public: + /// @name Construction + /// @{ + + static const SparcMCExpr *create(VariantKind Kind, const MCExpr *Expr, + MCContext &Ctx); + /// @} + /// @name Accessors + /// @{ + + /// getOpcode - Get the kind of this expression. + VariantKind getKind() const { return Kind; } + + /// getSubExpr - Get the child of this expression. + const MCExpr *getSubExpr() const { return Expr; } + + /// getFixupKind - Get the fixup kind of this expression. + Sparc::Fixups getFixupKind() const { return getFixupKind(Kind); } + + /// @} + void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override; + bool evaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout, + const MCFixup *Fixup) const override; + void visitUsedExpr(MCStreamer &Streamer) const override; + MCFragment *findAssociatedFragment() const override { + return getSubExpr()->findAssociatedFragment(); + } + + void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override; + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Target; + } + + static bool classof(const SparcMCExpr *) { return true; } + + static VariantKind parseVariantKind(StringRef name); + static bool printVariantKind(raw_ostream &OS, VariantKind Kind); + static Sparc::Fixups getFixupKind(VariantKind Kind); +}; + +} // end namespace llvm. + +#endif diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp new file mode 100644 index 000000000000..bd6596faee5d --- /dev/null +++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp @@ -0,0 +1,125 @@ +//===-- SparcMCTargetDesc.cpp - Sparc Target Descriptions -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Sparc specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#include "SparcMCTargetDesc.h" +#include "InstPrinter/SparcInstPrinter.h" +#include "SparcMCAsmInfo.h" +#include "SparcTargetStreamer.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +#define GET_INSTRINFO_MC_DESC +#include "SparcGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "SparcGenSubtargetInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "SparcGenRegisterInfo.inc" + +static MCAsmInfo *createSparcMCAsmInfo(const MCRegisterInfo &MRI, + const Triple &TT) { + MCAsmInfo *MAI = new SparcELFMCAsmInfo(TT); + unsigned Reg = MRI.getDwarfRegNum(SP::O6, true); + MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(nullptr, Reg, 0); + MAI->addInitialFrameState(Inst); + return MAI; +} + +static MCAsmInfo *createSparcV9MCAsmInfo(const MCRegisterInfo &MRI, + const Triple &TT) { + MCAsmInfo *MAI = new SparcELFMCAsmInfo(TT); + unsigned Reg = MRI.getDwarfRegNum(SP::O6, true); + MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(nullptr, Reg, 2047); + MAI->addInitialFrameState(Inst); + return MAI; +} + +static MCInstrInfo *createSparcMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitSparcMCInstrInfo(X); + return X; +} + +static MCRegisterInfo *createSparcMCRegisterInfo(const Triple &TT) { + MCRegisterInfo *X = new MCRegisterInfo(); + InitSparcMCRegisterInfo(X, SP::O7); + return X; +} + +static MCSubtargetInfo * +createSparcMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { + if (CPU.empty()) + CPU = (TT.getArch() == Triple::sparcv9) ? "v9" : "v8"; + return createSparcMCSubtargetInfoImpl(TT, CPU, FS); +} + +static MCTargetStreamer * +createObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { + return new SparcTargetELFStreamer(S); +} + +static MCTargetStreamer *createTargetAsmStreamer(MCStreamer &S, + formatted_raw_ostream &OS, + MCInstPrinter *InstPrint, + bool isVerboseAsm) { + return new SparcTargetAsmStreamer(S, OS); +} + +static MCInstPrinter *createSparcMCInstPrinter(const Triple &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + const MCInstrInfo &MII, + const MCRegisterInfo &MRI) { + return new SparcInstPrinter(MAI, MII, MRI); +} + +extern "C" void LLVMInitializeSparcTargetMC() { + // Register the MC asm info. + RegisterMCAsmInfoFn X(getTheSparcTarget(), createSparcMCAsmInfo); + RegisterMCAsmInfoFn Y(getTheSparcV9Target(), createSparcV9MCAsmInfo); + RegisterMCAsmInfoFn Z(getTheSparcelTarget(), createSparcMCAsmInfo); + + for (Target *T : + {&getTheSparcTarget(), &getTheSparcV9Target(), &getTheSparcelTarget()}) { + // Register the MC instruction info. + TargetRegistry::RegisterMCInstrInfo(*T, createSparcMCInstrInfo); + + // Register the MC register info. + TargetRegistry::RegisterMCRegInfo(*T, createSparcMCRegisterInfo); + + // Register the MC subtarget info. + TargetRegistry::RegisterMCSubtargetInfo(*T, createSparcMCSubtargetInfo); + + // Register the MC Code Emitter. + TargetRegistry::RegisterMCCodeEmitter(*T, createSparcMCCodeEmitter); + + // Register the asm backend. + TargetRegistry::RegisterMCAsmBackend(*T, createSparcAsmBackend); + + // Register the object target streamer. + TargetRegistry::RegisterObjectTargetStreamer(*T, + createObjectTargetStreamer); + + // Register the asm streamer. + TargetRegistry::RegisterAsmTargetStreamer(*T, createTargetAsmStreamer); + + // Register the MCInstPrinter + TargetRegistry::RegisterMCInstPrinter(*T, createSparcMCInstPrinter); + } +} diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h new file mode 100644 index 000000000000..8390198479ba --- /dev/null +++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h @@ -0,0 +1,65 @@ +//===-- SparcMCTargetDesc.h - Sparc Target Descriptions ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Sparc specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCMCTARGETDESC_H +#define LLVM_LIB_TARGET_SPARC_MCTARGETDESC_SPARCMCTARGETDESC_H + +#include "llvm/Support/DataTypes.h" + +#include <memory> + +namespace llvm { +class MCAsmBackend; +class MCCodeEmitter; +class MCContext; +class MCInstrInfo; +class MCObjectWriter; +class MCRegisterInfo; +class MCSubtargetInfo; +class MCTargetOptions; +class Target; +class Triple; +class StringRef; +class raw_pwrite_stream; +class raw_ostream; + +Target &getTheSparcTarget(); +Target &getTheSparcV9Target(); +Target &getTheSparcelTarget(); + +MCCodeEmitter *createSparcMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + MCContext &Ctx); +MCAsmBackend *createSparcAsmBackend(const Target &T, const MCSubtargetInfo &STI, + const MCRegisterInfo &MRI, + const MCTargetOptions &Options); +std::unique_ptr<MCObjectWriter> +createSparcELFObjectWriter(raw_pwrite_stream &OS, bool Is64Bit, + bool IsLIttleEndian, uint8_t OSABI); +} // End llvm namespace + +// Defines symbolic names for Sparc registers. This defines a mapping from +// register name to register number. +// +#define GET_REGINFO_ENUM +#include "SparcGenRegisterInfo.inc" + +// Defines symbolic names for the Sparc instructions. +// +#define GET_INSTRINFO_ENUM +#include "SparcGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "SparcGenSubtargetInfo.inc" + +#endif diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp new file mode 100644 index 000000000000..94af791e0e75 --- /dev/null +++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp @@ -0,0 +1,46 @@ +//===-- SparcTargetStreamer.cpp - Sparc Target Streamer Methods -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Sparc specific target streamer methods. +// +//===----------------------------------------------------------------------===// + +#include "SparcTargetStreamer.h" +#include "InstPrinter/SparcInstPrinter.h" +#include "llvm/Support/FormattedStream.h" + +using namespace llvm; + +// pin vtable to this file +SparcTargetStreamer::SparcTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {} + +void SparcTargetStreamer::anchor() {} + +SparcTargetAsmStreamer::SparcTargetAsmStreamer(MCStreamer &S, + formatted_raw_ostream &OS) + : SparcTargetStreamer(S), OS(OS) {} + +void SparcTargetAsmStreamer::emitSparcRegisterIgnore(unsigned reg) { + OS << "\t.register " + << "%" << StringRef(SparcInstPrinter::getRegisterName(reg)).lower() + << ", #ignore\n"; +} + +void SparcTargetAsmStreamer::emitSparcRegisterScratch(unsigned reg) { + OS << "\t.register " + << "%" << StringRef(SparcInstPrinter::getRegisterName(reg)).lower() + << ", #scratch\n"; +} + +SparcTargetELFStreamer::SparcTargetELFStreamer(MCStreamer &S) + : SparcTargetStreamer(S) {} + +MCELFStreamer &SparcTargetELFStreamer::getStreamer() { + return static_cast<MCELFStreamer &>(Streamer); +} |