diff options
Diffstat (limited to 'lib/Target/PowerPC/MCTargetDesc')
-rw-r--r-- | lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp | 6 | ||||
-rw-r--r-- | lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp | 105 | ||||
-rw-r--r-- | lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h | 4 | ||||
-rw-r--r-- | lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp | 10 | ||||
-rw-r--r-- | lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp | 31 | ||||
-rw-r--r-- | lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h | 3 | ||||
-rw-r--r-- | lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h | 3 |
7 files changed, 137 insertions, 25 deletions
diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp index 631f749581..f24edf62ed 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp @@ -32,6 +32,7 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { case FK_Data_8: case PPC::fixup_ppc_toc: case PPC::fixup_ppc_tlsreg: + case PPC::fixup_ppc_nofixup: return Value; case PPC::fixup_ppc_lo14: case PPC::fixup_ppc_toc16_ds: @@ -85,7 +86,8 @@ public: { "fixup_ppc_toc", 0, 64, 0 }, { "fixup_ppc_toc16", 16, 16, 0 }, { "fixup_ppc_toc16_ds", 16, 14, 0 }, - { "fixup_ppc_tlsreg", 0, 0, 0 } + { "fixup_ppc_tlsreg", 0, 0, 0 }, + { "fixup_ppc_nofixup", 0, 0, 0 } }; if (Kind < FirstTargetFixupKind) @@ -117,7 +119,7 @@ public: bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, - const MCInstFragment *DF, + const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const { // FIXME. llvm_unreachable("relaxInstruction() unimplemented"); diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp index 462d7072b5..61868d446f 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -9,6 +9,7 @@ #include "MCTargetDesc/PPCMCTargetDesc.h" #include "MCTargetDesc/PPCFixupKinds.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCValue.h" @@ -33,9 +34,25 @@ namespace { const MCFixup &Fixup, bool IsPCRel) const; virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset); + + virtual void sortRelocs(const MCAssembler &Asm, + std::vector<ELFRelocationEntry> &Relocs); + }; + + class PPCELFRelocationEntry : public ELFRelocationEntry { + public: + PPCELFRelocationEntry(const ELFRelocationEntry &RE); + bool operator<(const PPCELFRelocationEntry &RE) const { + return (RE.r_offset < r_offset || + (RE.r_offset == r_offset && RE.Type > Type)); + } }; } +PPCELFRelocationEntry::PPCELFRelocationEntry(const ELFRelocationEntry &RE) + : ELFRelocationEntry(RE.r_offset, RE.Index, RE.Type, RE.Symbol, + RE.r_addend, *RE.Fixup) {} + PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI) : MCELFObjectTargetWriter(Is64Bit, OSABI, Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC, @@ -60,9 +77,14 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, case PPC::fixup_ppc_br24: Type = ELF::R_PPC_REL24; break; + case FK_Data_4: case FK_PCRel_4: Type = ELF::R_PPC_REL32; break; + case FK_Data_8: + case FK_PCRel_8: + Type = ELF::R_PPC64_REL64; + break; } } else { switch ((unsigned)Fixup.getKind()) { @@ -79,12 +101,24 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, case MCSymbolRefExpr::VK_PPC_TPREL16_HA: Type = ELF::R_PPC_TPREL16_HA; break; + case MCSymbolRefExpr::VK_PPC_DTPREL16_HA: + Type = ELF::R_PPC64_DTPREL16_HA; + break; case MCSymbolRefExpr::VK_None: Type = ELF::R_PPC_ADDR16_HA; break; case MCSymbolRefExpr::VK_PPC_TOC16_HA: Type = ELF::R_PPC64_TOC16_HA; break; + case MCSymbolRefExpr::VK_PPC_GOT_TPREL16_HA: + Type = ELF::R_PPC64_GOT_TPREL16_HA; + break; + case MCSymbolRefExpr::VK_PPC_GOT_TLSGD16_HA: + Type = ELF::R_PPC64_GOT_TLSGD16_HA; + break; + case MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_HA: + Type = ELF::R_PPC64_GOT_TLSLD16_HA; + break; } break; case PPC::fixup_ppc_lo16: @@ -93,12 +127,21 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, case MCSymbolRefExpr::VK_PPC_TPREL16_LO: Type = ELF::R_PPC_TPREL16_LO; break; + case MCSymbolRefExpr::VK_PPC_DTPREL16_LO: + Type = ELF::R_PPC64_DTPREL16_LO; + break; case MCSymbolRefExpr::VK_None: Type = ELF::R_PPC_ADDR16_LO; break; case MCSymbolRefExpr::VK_PPC_TOC16_LO: Type = ELF::R_PPC64_TOC16_LO; break; + case MCSymbolRefExpr::VK_PPC_GOT_TLSGD16_LO: + Type = ELF::R_PPC64_GOT_TLSGD16_LO; + break; + case MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_LO: + Type = ELF::R_PPC64_GOT_TLSLD16_LO; + break; } break; case PPC::fixup_ppc_lo14: @@ -108,7 +151,24 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, Type = ELF::R_PPC64_TOC; break; case PPC::fixup_ppc_toc16: - Type = ELF::R_PPC64_TOC16; + switch (Modifier) { + default: llvm_unreachable("Unsupported Modifier"); + case MCSymbolRefExpr::VK_PPC_TPREL16_LO: + Type = ELF::R_PPC64_TPREL16_LO; + break; + case MCSymbolRefExpr::VK_PPC_DTPREL16_LO: + Type = ELF::R_PPC64_DTPREL16_LO; + break; + case MCSymbolRefExpr::VK_None: + Type = ELF::R_PPC64_TOC16; + break; + case MCSymbolRefExpr::VK_PPC_TOC16_LO: + Type = ELF::R_PPC64_TOC16_LO; + break; + case MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_LO: + Type = ELF::R_PPC64_GOT_TLSLD16_LO; + break; + } break; case PPC::fixup_ppc_toc16_ds: switch (Modifier) { @@ -119,14 +179,25 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, case MCSymbolRefExpr::VK_PPC_TOC16_LO: Type = ELF::R_PPC64_TOC16_LO_DS; break; - case MCSymbolRefExpr::VK_PPC_GOT_TPREL16_DS: - Type = ELF::R_PPC64_GOT_TPREL16_DS; + case MCSymbolRefExpr::VK_PPC_GOT_TPREL16_LO: + Type = ELF::R_PPC64_GOT_TPREL16_LO_DS; break; } break; case PPC::fixup_ppc_tlsreg: Type = ELF::R_PPC64_TLS; break; + case PPC::fixup_ppc_nofixup: + switch (Modifier) { + default: llvm_unreachable("Unsupported Modifier"); + case MCSymbolRefExpr::VK_PPC_TLSGD: + Type = ELF::R_PPC64_TLSGD; + break; + case MCSymbolRefExpr::VK_PPC_TLSLD: + Type = ELF::R_PPC64_TLSLD; + break; + } + break; case FK_Data_8: switch (Modifier) { default: llvm_unreachable("Unsupported Modifier"); @@ -191,6 +262,34 @@ adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset) { } } +// The standard sorter only sorts on the r_offset field, but PowerPC can +// have multiple relocations at the same offset. Sort secondarily on the +// relocation type to avoid nondeterminism. +void PPCELFObjectWriter::sortRelocs(const MCAssembler &Asm, + std::vector<ELFRelocationEntry> &Relocs) { + + // Copy to a temporary vector of relocation entries having a different + // sort function. + std::vector<PPCELFRelocationEntry> TmpRelocs; + + for (std::vector<ELFRelocationEntry>::iterator R = Relocs.begin(); + R != Relocs.end(); ++R) { + TmpRelocs.push_back(PPCELFRelocationEntry(*R)); + } + + // Sort in place by ascending r_offset and descending r_type. + array_pod_sort(TmpRelocs.begin(), TmpRelocs.end()); + + // Copy back to the original vector. + unsigned I = 0; + for (std::vector<PPCELFRelocationEntry>::iterator R = TmpRelocs.begin(); + R != TmpRelocs.end(); ++R, ++I) { + Relocs[I] = ELFRelocationEntry(R->r_offset, R->Index, R->Type, + R->Symbol, R->r_addend, *R->Fixup); + } +} + + MCObjectWriter *llvm::createPPCELFObjectWriter(raw_ostream &OS, bool Is64Bit, uint8_t OSABI) { diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h b/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h index 75bb851630..7917f7736e 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h +++ b/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h @@ -47,6 +47,10 @@ enum Fixups { /// fixup_ppc_tlsreg - Insert thread-pointer register number. fixup_ppc_tlsreg, + + /// fixup_ppc_nofixup - Not a true fixup, but ties a symbol to a call + /// to __tls_get_addr for the TLS general and local dynamic models. + fixup_ppc_nofixup, // Marker LastTargetFixupKind, diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp index 215aa40c4a..a25d7fe64f 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp @@ -17,8 +17,9 @@ using namespace llvm; void PPCMCAsmInfoDarwin::anchor() { } PPCMCAsmInfoDarwin::PPCMCAsmInfoDarwin(bool is64Bit) { - if (is64Bit) - PointerSize = 8; + if (is64Bit) { + PointerSize = CalleeSaveStackSlotSize = 8; + } IsLittleEndian = false; PCSymbol = "."; @@ -35,8 +36,9 @@ PPCMCAsmInfoDarwin::PPCMCAsmInfoDarwin(bool is64Bit) { void PPCLinuxMCAsmInfo::anchor() { } PPCLinuxMCAsmInfo::PPCLinuxMCAsmInfo(bool is64Bit) { - if (is64Bit) - PointerSize = 8; + if (is64Bit) { + PointerSize = CalleeSaveStackSlotSize = 8; + } IsLittleEndian = false; // ".comm align is in bytes but .align is pow-2." diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp index 5b208d41f4..d048426d43 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp @@ -17,6 +17,7 @@ #include "MCTargetDesc/PPCFixupKinds.h" #include "llvm/ADT/Statistic.h" #include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -62,8 +63,6 @@ public: SmallVectorImpl<MCFixup> &Fixups) const; unsigned getMemRIXEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups) const; - unsigned getTLSOffsetEncoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups) const; unsigned getTLSRegEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups) const; unsigned get_crbitm_encoding(const MCInst &MI, unsigned OpNo, @@ -82,11 +81,12 @@ public: SmallVectorImpl<MCFixup> &Fixups) const { uint64_t Bits = getBinaryCodeForInstr(MI, Fixups); - // BL8_NOPELF and BLA8_NOP_ELF is both size of 8 bacause of the + // BL8_NOP_ELF, BLA8_NOP_ELF, etc., all have a size of 8 because of the // following 'nop'. unsigned Size = 4; // FIXME: Have Desc.getSize() return the correct value! unsigned Opcode = MI.getOpcode(); - if (Opcode == PPC::BL8_NOP_ELF || Opcode == PPC::BLA8_NOP_ELF) + if (Opcode == PPC::BL8_NOP_ELF || Opcode == PPC::BLA8_NOP_ELF || + Opcode == PPC::BL8_NOP_ELF_TLSGD || Opcode == PPC::BL8_NOP_ELF_TLSLD) Size = 8; // Output the constant in big endian byte order. @@ -119,6 +119,17 @@ getDirectBrEncoding(const MCInst &MI, unsigned OpNo, // Add a fixup for the branch target. Fixups.push_back(MCFixup::Create(0, MO.getExpr(), (MCFixupKind)PPC::fixup_ppc_br24)); + + // For special TLS calls, add another fixup for the symbol. Apparently + // BL8_NOP_ELF, BL8_NOP_ELF_TLSGD, and BL8_NOP_ELF_TLSLD are sufficiently + // similar that TblGen will not generate a separate case for the latter + // two, so this is the only way to get the extra fixup generated. + unsigned Opcode = MI.getOpcode(); + if (Opcode == PPC::BL8_NOP_ELF_TLSGD || Opcode == PPC::BL8_NOP_ELF_TLSLD) { + const MCOperand &MO2 = MI.getOperand(OpNo+1); + Fixups.push_back(MCFixup::Create(0, MO2.getExpr(), + (MCFixupKind)PPC::fixup_ppc_nofixup)); + } return 0; } @@ -199,17 +210,6 @@ unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo, } -unsigned PPCMCCodeEmitter::getTLSOffsetEncoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups) const { - const MCOperand &MO = MI.getOperand(OpNo); - - // Add a fixup for the GOT displacement to the TLS block offset. - Fixups.push_back(MCFixup::Create(0, MO.getExpr(), - (MCFixupKind)PPC::fixup_ppc_toc16_ds)); - return 0; -} - - unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups) const { const MCOperand &MO = MI.getOperand(OpNo); @@ -223,7 +223,6 @@ unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo, return getPPCRegisterNumbering(PPC::X13); } - unsigned PPCMCCodeEmitter:: get_crbitm_encoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups) const { diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h index a0e4cf3005..4a420929d0 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h @@ -14,6 +14,9 @@ #ifndef PPCMCTARGETDESC_H #define PPCMCTARGETDESC_H +// GCC #defines PPC on Linux but we use it as our namespace name +#undef PPC + #include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h b/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h index f872e861bf..972e13852e 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h +++ b/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h @@ -14,6 +14,9 @@ #ifndef LLVM_TARGET_POWERPC_PPCPREDICATES_H #define LLVM_TARGET_POWERPC_PPCPREDICATES_H +// GCC #defines PPC on Linux but we use it as our namespace name +#undef PPC + namespace llvm { namespace PPC { /// Predicate - These are "(BI << 5) | BO" for various predicates. |