diff options
Diffstat (limited to 'contrib/llvm/lib/Target/PowerPC/MCTargetDesc')
13 files changed, 1153 insertions, 226 deletions
diff --git a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp index ec26574..0d42081 100644 --- a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp +++ b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp @@ -16,13 +16,13 @@ #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCValue.h" -#include "llvm/Object/MachOFormat.h" #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MachO.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; -static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { +static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) { switch (Kind) { default: llvm_unreachable("Unknown fixup kind!"); @@ -30,40 +30,45 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { case FK_Data_2: case FK_Data_4: case FK_Data_8: - case PPC::fixup_ppc_tlsreg: case PPC::fixup_ppc_nofixup: return Value; case PPC::fixup_ppc_brcond14: + case PPC::fixup_ppc_brcond14abs: return Value & 0xfffc; case PPC::fixup_ppc_br24: + case PPC::fixup_ppc_br24abs: 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: + case PPC::fixup_ppc_half16: return Value & 0xffff; - case PPC::fixup_ppc_lo16_ds: + case PPC::fixup_ppc_half16ds: return Value & 0xfffc; } } -namespace { -class PPCMachObjectWriter : public MCMachObjectTargetWriter { -public: - PPCMachObjectWriter(bool Is64Bit, uint32_t CPUType, - uint32_t CPUSubtype) - : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype) {} - - void RecordRelocation(MachObjectWriter *Writer, - const MCAssembler &Asm, const MCAsmLayout &Layout, - const MCFragment *Fragment, const MCFixup &Fixup, - MCValue Target, uint64_t &FixedValue) { - llvm_unreachable("Relocation emission for MachO/PPC unimplemented!"); +static unsigned getFixupKindNumBytes(unsigned Kind) { + switch (Kind) { + default: + llvm_unreachable("Unknown fixup kind!"); + case FK_Data_1: + return 1; + case FK_Data_2: + case PPC::fixup_ppc_half16: + case PPC::fixup_ppc_half16ds: + return 2; + case FK_Data_4: + case PPC::fixup_ppc_brcond14: + case PPC::fixup_ppc_brcond14abs: + case PPC::fixup_ppc_br24: + case PPC::fixup_ppc_br24abs: + return 4; + case FK_Data_8: + return 8; + case PPC::fixup_ppc_nofixup: + return 0; } -}; +} + +namespace { class PPCAsmBackend : public MCAsmBackend { const Target &TheTarget; @@ -77,10 +82,10 @@ public: // name offset bits flags { "fixup_ppc_br24", 6, 24, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_ppc_brcond14", 16, 14, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_ppc_lo16", 16, 16, 0 }, - { "fixup_ppc_ha16", 16, 16, 0 }, - { "fixup_ppc_lo16_ds", 16, 14, 0 }, - { "fixup_ppc_tlsreg", 0, 0, 0 }, + { "fixup_ppc_br24abs", 6, 24, 0 }, + { "fixup_ppc_brcond14abs", 16, 14, 0 }, + { "fixup_ppc_half16", 0, 16, 0 }, + { "fixup_ppc_half16ds", 0, 14, 0 }, { "fixup_ppc_nofixup", 0, 0, 0 } }; @@ -98,12 +103,13 @@ public: if (!Value) return; // Doesn't change encoding. unsigned Offset = Fixup.getOffset(); + unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); // 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); + for (unsigned i = 0; i != NumBytes; ++i) + Data[Offset + i] |= uint8_t((Value >> ((NumBytes - i - 1)*8)) & 0xff); } bool mayNeedRelaxation(const MCInst &Inst) const { @@ -126,16 +132,23 @@ public: } bool writeNopData(uint64_t Count, MCObjectWriter *OW) const { - // FIXME: Zero fill for now. That's not right, but at least will get the - // section size right. - for (uint64_t i = 0; i != Count; ++i) - OW->Write8(0); + uint64_t NumNops = Count / 4; + for (uint64_t i = 0; i != NumNops; ++i) + OW->Write32(0x60000000); + + switch (Count % 4) { + default: break; // No leftover bytes to write + case 1: OW->Write8(0); break; + case 2: OW->Write16(0); break; + case 3: OW->Write16(0); OW->Write8(0); break; + } + return true; } unsigned getPointerSize() const { StringRef Name = TheTarget.getName(); - if (Name == "ppc64") return 8; + if (Name == "ppc64" || Name == "ppc64le") return 8; assert(Name == "ppc32" && "Unknown target name!"); return 4; } @@ -151,12 +164,11 @@ namespace { MCObjectWriter *createObjectWriter(raw_ostream &OS) const { bool is64 = getPointerSize() == 8; - return createMachObjectWriter(new PPCMachObjectWriter( - /*Is64Bit=*/is64, - (is64 ? object::mach::CTM_PowerPC64 : - object::mach::CTM_PowerPC), - object::mach::CSPPC_ALL), - OS, /*IsLittleEndian=*/false); + return createPPCMachObjectWriter( + OS, + /*Is64Bit=*/is64, + (is64 ? MachO::CPU_TYPE_POWERPC64 : MachO::CPU_TYPE_POWERPC), + MachO::CPU_SUBTYPE_POWERPC_ALL); } virtual bool doesSectionRequireSymbols(const MCSection &Section) const { @@ -183,10 +195,9 @@ namespace { } // end anonymous namespace - - - -MCAsmBackend *llvm::createPPCAsmBackend(const Target &T, StringRef TT, StringRef CPU) { +MCAsmBackend *llvm::createPPCAsmBackend(const Target &T, + const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU) { if (Triple(TT).isOSDarwin()) return new DarwinPPCAsmBackend(T); diff --git a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp index 7a84723..54de70e 100644 --- a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -30,29 +30,17 @@ namespace { virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel, bool IsRelocWithSymbol, int64_t Addend) const; + virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F, + const MCFixup &Fixup, + bool IsPCRel) const; virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, 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, @@ -75,11 +63,30 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, default: llvm_unreachable("Unimplemented"); case PPC::fixup_ppc_br24: + case PPC::fixup_ppc_br24abs: Type = ELF::R_PPC_REL24; break; case PPC::fixup_ppc_brcond14: + case PPC::fixup_ppc_brcond14abs: Type = ELF::R_PPC_REL14; break; + case PPC::fixup_ppc_half16: + switch (Modifier) { + default: llvm_unreachable("Unsupported Modifier"); + case MCSymbolRefExpr::VK_None: + Type = ELF::R_PPC_REL16; + break; + case MCSymbolRefExpr::VK_PPC_LO: + Type = ELF::R_PPC_REL16_LO; + break; + case MCSymbolRefExpr::VK_PPC_HI: + Type = ELF::R_PPC_REL16_HI; + break; + case MCSymbolRefExpr::VK_PPC_HA: + Type = ELF::R_PPC_REL16_HA; + break; + } + break; case FK_Data_4: case FK_PCRel_4: Type = ELF::R_PPC_REL32; @@ -92,93 +99,216 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, } else { switch ((unsigned)Fixup.getKind()) { default: llvm_unreachable("invalid fixup kind!"); - case PPC::fixup_ppc_br24: + case PPC::fixup_ppc_br24abs: Type = ELF::R_PPC_ADDR24; break; - case PPC::fixup_ppc_brcond14: + case PPC::fixup_ppc_brcond14abs: Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_ break; - case PPC::fixup_ppc_ha16: + case PPC::fixup_ppc_half16: switch (Modifier) { default: llvm_unreachable("Unsupported Modifier"); - case MCSymbolRefExpr::VK_PPC_TPREL16_HA: - Type = ELF::R_PPC_TPREL16_HA; + case MCSymbolRefExpr::VK_None: + Type = ELF::R_PPC_ADDR16; break; - case MCSymbolRefExpr::VK_PPC_DTPREL16_HA: - Type = ELF::R_PPC64_DTPREL16_HA; + case MCSymbolRefExpr::VK_PPC_LO: + Type = ELF::R_PPC_ADDR16_LO; + break; + case MCSymbolRefExpr::VK_PPC_HI: + Type = ELF::R_PPC_ADDR16_HI; break; - case MCSymbolRefExpr::VK_PPC_GAS_HA16: - case MCSymbolRefExpr::VK_PPC_DARWIN_HA16: + case MCSymbolRefExpr::VK_PPC_HA: 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; + case MCSymbolRefExpr::VK_PPC_HIGHER: + Type = ELF::R_PPC64_ADDR16_HIGHER; break; - case MCSymbolRefExpr::VK_PPC_GOT_TLSGD16_HA: - Type = ELF::R_PPC64_GOT_TLSGD16_HA; + case MCSymbolRefExpr::VK_PPC_HIGHERA: + Type = ELF::R_PPC64_ADDR16_HIGHERA; break; - case MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_HA: - Type = ELF::R_PPC64_GOT_TLSLD16_HA; + case MCSymbolRefExpr::VK_PPC_HIGHEST: + Type = ELF::R_PPC64_ADDR16_HIGHEST; break; - } - break; - case PPC::fixup_ppc_lo16: - switch (Modifier) { - default: llvm_unreachable("Unsupported Modifier"); - case MCSymbolRefExpr::VK_PPC_TPREL16_LO: - Type = ELF::R_PPC_TPREL16_LO; + case MCSymbolRefExpr::VK_PPC_HIGHESTA: + Type = ELF::R_PPC64_ADDR16_HIGHESTA; break; - case MCSymbolRefExpr::VK_PPC_DTPREL16_LO: - Type = ELF::R_PPC64_DTPREL16_LO; + case MCSymbolRefExpr::VK_GOT: + Type = ELF::R_PPC_GOT16; break; - case MCSymbolRefExpr::VK_None: - Type = ELF::R_PPC_ADDR16; + case MCSymbolRefExpr::VK_PPC_GOT_LO: + Type = ELF::R_PPC_GOT16_LO; break; - case MCSymbolRefExpr::VK_PPC_GAS_LO16: - case MCSymbolRefExpr::VK_PPC_DARWIN_LO16: - Type = ELF::R_PPC_ADDR16_LO; - break; - case MCSymbolRefExpr::VK_PPC_TOC_ENTRY: + case MCSymbolRefExpr::VK_PPC_GOT_HI: + Type = ELF::R_PPC_GOT16_HI; + break; + case MCSymbolRefExpr::VK_PPC_GOT_HA: + Type = ELF::R_PPC_GOT16_HA; + break; + case MCSymbolRefExpr::VK_PPC_TOC: Type = ELF::R_PPC64_TOC16; break; - case MCSymbolRefExpr::VK_PPC_TOC16_LO: + case MCSymbolRefExpr::VK_PPC_TOC_LO: Type = ELF::R_PPC64_TOC16_LO; break; - case MCSymbolRefExpr::VK_PPC_GOT_TLSGD16_LO: + case MCSymbolRefExpr::VK_PPC_TOC_HI: + Type = ELF::R_PPC64_TOC16_HI; + break; + case MCSymbolRefExpr::VK_PPC_TOC_HA: + Type = ELF::R_PPC64_TOC16_HA; + break; + case MCSymbolRefExpr::VK_PPC_TPREL: + Type = ELF::R_PPC_TPREL16; + break; + case MCSymbolRefExpr::VK_PPC_TPREL_LO: + Type = ELF::R_PPC_TPREL16_LO; + break; + case MCSymbolRefExpr::VK_PPC_TPREL_HI: + Type = ELF::R_PPC_TPREL16_HI; + break; + case MCSymbolRefExpr::VK_PPC_TPREL_HA: + Type = ELF::R_PPC_TPREL16_HA; + break; + case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER: + Type = ELF::R_PPC64_TPREL16_HIGHER; + break; + case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA: + Type = ELF::R_PPC64_TPREL16_HIGHERA; + break; + case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST: + Type = ELF::R_PPC64_TPREL16_HIGHEST; + break; + case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA: + Type = ELF::R_PPC64_TPREL16_HIGHESTA; + break; + case MCSymbolRefExpr::VK_PPC_DTPREL: + Type = ELF::R_PPC64_DTPREL16; + break; + case MCSymbolRefExpr::VK_PPC_DTPREL_LO: + Type = ELF::R_PPC64_DTPREL16_LO; + break; + case MCSymbolRefExpr::VK_PPC_DTPREL_HI: + Type = ELF::R_PPC64_DTPREL16_HI; + break; + case MCSymbolRefExpr::VK_PPC_DTPREL_HA: + Type = ELF::R_PPC64_DTPREL16_HA; + break; + case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER: + Type = ELF::R_PPC64_DTPREL16_HIGHER; + break; + case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA: + Type = ELF::R_PPC64_DTPREL16_HIGHERA; + break; + case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST: + Type = ELF::R_PPC64_DTPREL16_HIGHEST; + break; + case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA: + Type = ELF::R_PPC64_DTPREL16_HIGHESTA; + break; + case MCSymbolRefExpr::VK_PPC_GOT_TLSGD: + Type = ELF::R_PPC64_GOT_TLSGD16; + break; + case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO: Type = ELF::R_PPC64_GOT_TLSGD16_LO; break; - case MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_LO: + case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI: + Type = ELF::R_PPC64_GOT_TLSGD16_HI; + break; + case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA: + Type = ELF::R_PPC64_GOT_TLSGD16_HA; + break; + case MCSymbolRefExpr::VK_PPC_GOT_TLSLD: + Type = ELF::R_PPC64_GOT_TLSLD16; + break; + case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO: Type = ELF::R_PPC64_GOT_TLSLD16_LO; break; + case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI: + Type = ELF::R_PPC64_GOT_TLSLD16_HI; + break; + case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA: + Type = ELF::R_PPC64_GOT_TLSLD16_HA; + break; + case MCSymbolRefExpr::VK_PPC_GOT_TPREL: + /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets + are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS. */ + Type = ELF::R_PPC64_GOT_TPREL16_DS; + break; + case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO: + /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets + are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS. */ + Type = ELF::R_PPC64_GOT_TPREL16_LO_DS; + break; + case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI: + Type = ELF::R_PPC64_GOT_TPREL16_HI; + break; + case MCSymbolRefExpr::VK_PPC_GOT_DTPREL: + /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets + are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS. */ + Type = ELF::R_PPC64_GOT_DTPREL16_DS; + break; + case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO: + /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets + are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS. */ + Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS; + break; + case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA: + Type = ELF::R_PPC64_GOT_TPREL16_HA; + break; + case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI: + Type = ELF::R_PPC64_GOT_DTPREL16_HI; + break; + case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA: + Type = ELF::R_PPC64_GOT_DTPREL16_HA; + break; } break; - case PPC::fixup_ppc_lo16_ds: + case PPC::fixup_ppc_half16ds: switch (Modifier) { default: llvm_unreachable("Unsupported Modifier"); case MCSymbolRefExpr::VK_None: Type = ELF::R_PPC64_ADDR16_DS; break; - case MCSymbolRefExpr::VK_PPC_GAS_LO16: - case MCSymbolRefExpr::VK_PPC_DARWIN_LO16: + case MCSymbolRefExpr::VK_PPC_LO: Type = ELF::R_PPC64_ADDR16_LO_DS; break; - case MCSymbolRefExpr::VK_PPC_TOC_ENTRY: + case MCSymbolRefExpr::VK_GOT: + Type = ELF::R_PPC64_GOT16_DS; + break; + case MCSymbolRefExpr::VK_PPC_GOT_LO: + Type = ELF::R_PPC64_GOT16_LO_DS; + break; + case MCSymbolRefExpr::VK_PPC_TOC: Type = ELF::R_PPC64_TOC16_DS; break; - case MCSymbolRefExpr::VK_PPC_TOC16_LO: + case MCSymbolRefExpr::VK_PPC_TOC_LO: Type = ELF::R_PPC64_TOC16_LO_DS; break; - case MCSymbolRefExpr::VK_PPC_GOT_TPREL16_LO: + case MCSymbolRefExpr::VK_PPC_TPREL: + Type = ELF::R_PPC64_TPREL16_DS; + break; + case MCSymbolRefExpr::VK_PPC_TPREL_LO: + Type = ELF::R_PPC64_TPREL16_LO_DS; + break; + case MCSymbolRefExpr::VK_PPC_DTPREL: + Type = ELF::R_PPC64_DTPREL16_DS; + break; + case MCSymbolRefExpr::VK_PPC_DTPREL_LO: + Type = ELF::R_PPC64_DTPREL16_LO_DS; + break; + case MCSymbolRefExpr::VK_PPC_GOT_TPREL: + Type = ELF::R_PPC64_GOT_TPREL16_DS; + break; + case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO: Type = ELF::R_PPC64_GOT_TPREL16_LO_DS; break; + case MCSymbolRefExpr::VK_PPC_GOT_DTPREL: + Type = ELF::R_PPC64_GOT_DTPREL16_DS; + break; + case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO: + Type = ELF::R_PPC64_GOT_DTPREL16_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"); @@ -188,17 +318,29 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, case MCSymbolRefExpr::VK_PPC_TLSLD: Type = ELF::R_PPC64_TLSLD; break; + case MCSymbolRefExpr::VK_PPC_TLS: + Type = ELF::R_PPC64_TLS; + break; } break; case FK_Data_8: switch (Modifier) { default: llvm_unreachable("Unsupported Modifier"); - case MCSymbolRefExpr::VK_PPC_TOC: + case MCSymbolRefExpr::VK_PPC_TOCBASE: Type = ELF::R_PPC64_TOC; break; case MCSymbolRefExpr::VK_None: Type = ELF::R_PPC64_ADDR64; break; + case MCSymbolRefExpr::VK_PPC_DTPMOD: + Type = ELF::R_PPC64_DTPMOD64; + break; + case MCSymbolRefExpr::VK_PPC_TPREL: + Type = ELF::R_PPC64_TPREL64; + break; + case MCSymbolRefExpr::VK_PPC_DTPREL: + Type = ELF::R_PPC64_DTPREL64; + break; } break; case FK_Data_4: @@ -220,6 +362,35 @@ unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target, return getRelocTypeInner(Target, Fixup, IsPCRel); } +const MCSymbol *PPCELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F, + const MCFixup &Fixup, + bool IsPCRel) const { + assert(Target.getSymA() && "SymA cannot be 0"); + MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ? + MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); + + bool EmitThisSym; + switch (Modifier) { + // GOT references always need a relocation, even if the + // target symbol is local. + case MCSymbolRefExpr::VK_GOT: + case MCSymbolRefExpr::VK_PPC_GOT_LO: + case MCSymbolRefExpr::VK_PPC_GOT_HI: + case MCSymbolRefExpr::VK_PPC_GOT_HA: + EmitThisSym = true; + break; + default: + EmitThisSym = false; + break; + } + + if (EmitThisSym) + return &Target.getSymA()->getSymbol().AliasedSymbol(); + return NULL; +} + const MCSymbol *PPCELFObjectWriter::undefinedExplicitRelSym(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const { @@ -240,47 +411,6 @@ const MCSymbol *PPCELFObjectWriter::undefinedExplicitRelSym(const MCValue &Targe return NULL; } -void PPCELFObjectWriter:: -adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset) { - switch ((unsigned)Fixup.getKind()) { - case PPC::fixup_ppc_ha16: - case PPC::fixup_ppc_lo16: - case PPC::fixup_ppc_lo16_ds: - RelocOffset += 2; - break; - default: - break; - } -} - -// 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/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h index 86c44f5..68de8c1 100644 --- a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h +++ b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h @@ -25,23 +25,25 @@ enum Fixups { /// branches. fixup_ppc_brcond14, - /// fixup_ppc_lo16 - A 16-bit fixup corresponding to lo16(_foo) for instrs - /// like 'li'. - fixup_ppc_lo16, - - /// fixup_ppc_ha16 - A 16-bit fixup corresponding to ha16(_foo) for instrs - /// like 'lis'. - fixup_ppc_ha16, + /// fixup_ppc_br24abs - 24-bit absolute relocation for direct branches + /// like 'ba' and 'bla'. + fixup_ppc_br24abs, + + /// fixup_ppc_brcond14abs - 14-bit absolute relocation for conditional + /// branches. + fixup_ppc_brcond14abs, + + /// fixup_ppc_half16 - A 16-bit fixup corresponding to lo16(_foo) + /// or ha16(_foo) for instrs like 'li' or 'addis'. + fixup_ppc_half16, - /// fixup_ppc_lo16_ds - A 14-bit fixup corresponding to lo16(_foo) with + /// fixup_ppc_half16ds - A 14-bit fixup corresponding to lo16(_foo) with /// implied 2 zero bits for instrs like 'std'. - fixup_ppc_lo16_ds, - - /// fixup_ppc_tlsreg - Insert thread-pointer register number. - fixup_ppc_tlsreg, + fixup_ppc_half16ds, /// 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. + /// to __tls_get_addr for the TLS general and local dynamic models, + /// or inserts the thread-pointer register number. fixup_ppc_nofixup, // Marker diff --git a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp index a25d7fe..f3dddce 100644 --- a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp +++ b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp @@ -22,7 +22,6 @@ PPCMCAsmInfoDarwin::PPCMCAsmInfoDarwin(bool is64Bit) { } IsLittleEndian = false; - PCSymbol = "."; CommentString = ";"; ExceptionsType = ExceptionHandling::DwarfCFI; @@ -47,24 +46,24 @@ PPCLinuxMCAsmInfo::PPCLinuxMCAsmInfo(bool is64Bit) { CommentString = "#"; GlobalPrefix = ""; PrivateGlobalPrefix = ".L"; - WeakRefDirective = "\t.weak\t"; - + // Uses '.section' before '.bss' directive UsesELFSectionDirectiveForBSS = true; // Debug Information SupportsDebugInformation = true; - PCSymbol = "."; + DollarIsPC = true; // Set up DWARF directives HasLEB128 = true; // Target asm supports leb128 directives (little-endian) + MinInstAlignment = 4; // Exceptions handling ExceptionsType = ExceptionHandling::DwarfCFI; ZeroDirective = "\t.space\t"; Data64bitsDirective = is64Bit ? "\t.quad\t" : 0; - AssemblerDialect = 0; // Old-Style mnemonics. + AssemblerDialect = 1; // New-Style mnemonics. } diff --git a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.h b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.h index 7b4ed9f..1530e77 100644 --- a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.h +++ b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.h @@ -15,6 +15,7 @@ #define PPCTARGETASMINFO_H #include "llvm/MC/MCAsmInfoDarwin.h" +#include "llvm/MC/MCAsmInfoELF.h" namespace llvm { @@ -24,7 +25,7 @@ namespace llvm { explicit PPCMCAsmInfoDarwin(bool is64Bit); }; - class PPCLinuxMCAsmInfo : public MCAsmInfo { + class PPCLinuxMCAsmInfo : public MCAsmInfoELF { virtual void anchor(); public: explicit PPCLinuxMCAsmInfo(bool is64Bit); diff --git a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp index 2223cd6..346a9be 100644 --- a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp +++ b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp @@ -23,6 +23,7 @@ #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetOpcodes.h" using namespace llvm; STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); @@ -48,16 +49,20 @@ public: SmallVectorImpl<MCFixup> &Fixups) const; unsigned getCondBrEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups) const; - unsigned getHA16Encoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups) const; - unsigned getLO16Encoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups) const; + unsigned getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const; + unsigned getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const; + unsigned getImm16Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const; unsigned getMemRIEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups) const; unsigned getMemRIXEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups) const; unsigned getTLSRegEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups) const; + unsigned getTLSCallEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const; unsigned get_crbitm_encoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups) const; @@ -72,13 +77,19 @@ public: SmallVectorImpl<MCFixup> &Fixups) const; void EncodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups) const { + // For fast-isel, a float COPY_TO_REGCLASS can survive this long. + // It's just a nop to keep the register classes happy, so don't + // generate anything. + unsigned Opcode = MI.getOpcode(); + if (Opcode == TargetOpcode::COPY_TO_REGCLASS) + return; + uint64_t Bits = getBinaryCodeForInstr(MI, Fixups); // BL8_NOP 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 || Opcode == PPC::BLA8_NOP || - Opcode == PPC::BL8_NOP_TLSGD || Opcode == PPC::BL8_NOP_TLSLD) + Opcode == PPC::BL8_NOP_TLS) Size = 8; // Output the constant in big endian byte order. @@ -111,17 +122,6 @@ 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, BL8_NOP_TLSGD, and BL8_NOP_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_TLSGD || Opcode == PPC::BL8_NOP_TLSLD) { - const MCOperand &MO2 = MI.getOperand(OpNo+1); - Fixups.push_back(MCFixup::Create(0, MO2.getExpr(), - (MCFixupKind)PPC::fixup_ppc_nofixup)); - } return 0; } @@ -136,25 +136,38 @@ unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo, return 0; } -unsigned PPCMCCodeEmitter::getHA16Encoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups) const { +unsigned PPCMCCodeEmitter:: +getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const { const MCOperand &MO = MI.getOperand(OpNo); if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups); - + // Add a fixup for the branch target. Fixups.push_back(MCFixup::Create(0, MO.getExpr(), - (MCFixupKind)PPC::fixup_ppc_ha16)); + (MCFixupKind)PPC::fixup_ppc_br24abs)); return 0; } -unsigned PPCMCCodeEmitter::getLO16Encoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups) const { +unsigned PPCMCCodeEmitter:: +getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const { const MCOperand &MO = MI.getOperand(OpNo); if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups); - + // Add a fixup for the branch target. Fixups.push_back(MCFixup::Create(0, MO.getExpr(), - (MCFixupKind)PPC::fixup_ppc_lo16)); + (MCFixupKind)PPC::fixup_ppc_brcond14abs)); + return 0; +} + +unsigned PPCMCCodeEmitter::getImm16Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const { + const MCOperand &MO = MI.getOperand(OpNo); + if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups); + + // Add a fixup for the immediate field. + Fixups.push_back(MCFixup::Create(2, MO.getExpr(), + (MCFixupKind)PPC::fixup_ppc_half16)); return 0; } @@ -170,8 +183,8 @@ unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo, return (getMachineOpValue(MI, MO, Fixups) & 0xFFFF) | RegBits; // Add a fixup for the displacement field. - Fixups.push_back(MCFixup::Create(0, MO.getExpr(), - (MCFixupKind)PPC::fixup_ppc_lo16)); + Fixups.push_back(MCFixup::Create(2, MO.getExpr(), + (MCFixupKind)PPC::fixup_ppc_half16)); return RegBits; } @@ -185,11 +198,11 @@ unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo, const MCOperand &MO = MI.getOperand(OpNo); if (MO.isImm()) - return (getMachineOpValue(MI, MO, Fixups) & 0x3FFF) | RegBits; + return ((getMachineOpValue(MI, MO, Fixups) >> 2) & 0x3FFF) | RegBits; // Add a fixup for the displacement field. - Fixups.push_back(MCFixup::Create(0, MO.getExpr(), - (MCFixupKind)PPC::fixup_ppc_lo16_ds)); + Fixups.push_back(MCFixup::Create(2, MO.getExpr(), + (MCFixupKind)PPC::fixup_ppc_half16ds)); return RegBits; } @@ -203,19 +216,29 @@ unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo, // hint to the linker that this statement is part of a relocation sequence. // Return the thread-pointer register's encoding. Fixups.push_back(MCFixup::Create(0, MO.getExpr(), - (MCFixupKind)PPC::fixup_ppc_tlsreg)); - return CTX.getRegisterInfo().getEncodingValue(PPC::X13); + (MCFixupKind)PPC::fixup_ppc_nofixup)); + return CTX.getRegisterInfo()->getEncodingValue(PPC::X13); +} + +unsigned PPCMCCodeEmitter::getTLSCallEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const { + // For special TLS calls, we need two fixups; one for the branch target + // (__tls_get_addr), which we create via getDirectBrEncoding as usual, + // and one for the TLSGD or TLSLD symbol, which is emitted here. + const MCOperand &MO = MI.getOperand(OpNo+1); + Fixups.push_back(MCFixup::Create(0, MO.getExpr(), + (MCFixupKind)PPC::fixup_ppc_nofixup)); + return getDirectBrEncoding(MI, OpNo, Fixups); } unsigned PPCMCCodeEmitter:: get_crbitm_encoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups) const { const MCOperand &MO = MI.getOperand(OpNo); - assert((MI.getOpcode() == PPC::MTCRF || - MI.getOpcode() == PPC::MFOCRF || - MI.getOpcode() == PPC::MTCRF8) && + assert((MI.getOpcode() == PPC::MTOCRF || MI.getOpcode() == PPC::MTOCRF8 || + MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) && (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7)); - return 0x80 >> CTX.getRegisterInfo().getEncodingValue(MO.getReg()); + return 0x80 >> CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); } @@ -223,11 +246,12 @@ unsigned PPCMCCodeEmitter:: getMachineOpValue(const MCInst &MI, const MCOperand &MO, SmallVectorImpl<MCFixup> &Fixups) const { if (MO.isReg()) { - // MTCRF/MFOCRF should go through get_crbitm_encoding for the CR operand. + // MTOCRF/MFOCRF should go through get_crbitm_encoding for the CR operand. // The GPR operand should come through here though. - assert((MI.getOpcode() != PPC::MTCRF && MI.getOpcode() != PPC::MFOCRF) || + assert((MI.getOpcode() != PPC::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 && + MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) || MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7); - return CTX.getRegisterInfo().getEncodingValue(MO.getReg()); + return CTX.getRegisterInfo()->getEncodingValue(MO.getReg()); } assert(MO.isImm() && diff --git a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp new file mode 100644 index 0000000..d7e8402 --- /dev/null +++ b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp @@ -0,0 +1,155 @@ +//===-- PPCMCExpr.cpp - PPC 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. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "ppcmcexpr" +#include "PPCMCExpr.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCAsmInfo.h" + +using namespace llvm; + +const PPCMCExpr* +PPCMCExpr::Create(VariantKind Kind, const MCExpr *Expr, + bool isDarwin, MCContext &Ctx) { + return new (Ctx) PPCMCExpr(Kind, Expr, isDarwin); +} + +void PPCMCExpr::PrintImpl(raw_ostream &OS) const { + if (isDarwinSyntax()) { + switch (Kind) { + default: llvm_unreachable("Invalid kind!"); + case VK_PPC_LO: OS << "lo16"; break; + case VK_PPC_HI: OS << "hi16"; break; + case VK_PPC_HA: OS << "ha16"; break; + } + + OS << '('; + getSubExpr()->print(OS); + OS << ')'; + } else { + getSubExpr()->print(OS); + + switch (Kind) { + default: llvm_unreachable("Invalid kind!"); + case VK_PPC_LO: OS << "@l"; break; + case VK_PPC_HI: OS << "@h"; break; + case VK_PPC_HA: OS << "@ha"; break; + case VK_PPC_HIGHER: OS << "@higher"; break; + case VK_PPC_HIGHERA: OS << "@highera"; break; + case VK_PPC_HIGHEST: OS << "@highest"; break; + case VK_PPC_HIGHESTA: OS << "@highesta"; break; + } + } +} + +bool +PPCMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout) const { + MCValue Value; + + if (!Layout || !getSubExpr()->EvaluateAsRelocatable(Value, *Layout)) + return false; + + if (Value.isAbsolute()) { + int64_t Result = Value.getConstant(); + switch (Kind) { + default: + llvm_unreachable("Invalid kind!"); + case VK_PPC_LO: + Result = Result & 0xffff; + break; + case VK_PPC_HI: + Result = (Result >> 16) & 0xffff; + break; + case VK_PPC_HA: + Result = ((Result + 0x8000) >> 16) & 0xffff; + break; + case VK_PPC_HIGHER: + Result = (Result >> 32) & 0xffff; + break; + case VK_PPC_HIGHERA: + Result = ((Result + 0x8000) >> 32) & 0xffff; + break; + case VK_PPC_HIGHEST: + Result = (Result >> 48) & 0xffff; + break; + case VK_PPC_HIGHESTA: + Result = ((Result + 0x8000) >> 48) & 0xffff; + break; + } + Res = MCValue::get(Result); + } else { + MCContext &Context = Layout->getAssembler().getContext(); + const MCSymbolRefExpr *Sym = Value.getSymA(); + MCSymbolRefExpr::VariantKind Modifier = Sym->getKind(); + if (Modifier != MCSymbolRefExpr::VK_None) + return false; + switch (Kind) { + default: + llvm_unreachable("Invalid kind!"); + case VK_PPC_LO: + Modifier = MCSymbolRefExpr::VK_PPC_LO; + break; + case VK_PPC_HI: + Modifier = MCSymbolRefExpr::VK_PPC_HI; + break; + case VK_PPC_HA: + Modifier = MCSymbolRefExpr::VK_PPC_HA; + break; + case VK_PPC_HIGHERA: + Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA; + break; + case VK_PPC_HIGHER: + Modifier = MCSymbolRefExpr::VK_PPC_HIGHER; + break; + case VK_PPC_HIGHEST: + Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST; + break; + case VK_PPC_HIGHESTA: + Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA; + break; + } + Sym = MCSymbolRefExpr::Create(&Sym->getSymbol(), Modifier, Context); + Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant()); + } + + return true; +} + +// FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps +// that method should be made public? +static void AddValueSymbols_(const MCExpr *Value, MCAssembler *Asm) { + switch (Value->getKind()) { + case MCExpr::Target: + llvm_unreachable("Can't handle nested target expr!"); + + case MCExpr::Constant: + break; + + case MCExpr::Binary: { + const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value); + AddValueSymbols_(BE->getLHS(), Asm); + AddValueSymbols_(BE->getRHS(), Asm); + break; + } + + case MCExpr::SymbolRef: + Asm->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol()); + break; + + case MCExpr::Unary: + AddValueSymbols_(cast<MCUnaryExpr>(Value)->getSubExpr(), Asm); + break; + } +} + +void PPCMCExpr::AddValueSymbols(MCAssembler *Asm) const { + AddValueSymbols_(getSubExpr(), Asm); +} diff --git a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h new file mode 100644 index 0000000..e44c7c1 --- /dev/null +++ b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h @@ -0,0 +1,96 @@ +//===-- PPCMCExpr.h - PPC 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. +// +//===----------------------------------------------------------------------===// + +#ifndef PPCMCEXPR_H +#define PPCMCEXPR_H + +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCValue.h" +#include "llvm/MC/MCAsmLayout.h" + +namespace llvm { + +class PPCMCExpr : public MCTargetExpr { +public: + enum VariantKind { + VK_PPC_None, + VK_PPC_LO, + VK_PPC_HI, + VK_PPC_HA, + VK_PPC_HIGHER, + VK_PPC_HIGHERA, + VK_PPC_HIGHEST, + VK_PPC_HIGHESTA + }; + +private: + const VariantKind Kind; + const MCExpr *Expr; + bool IsDarwin; + + explicit PPCMCExpr(VariantKind _Kind, const MCExpr *_Expr, + bool _IsDarwin) + : Kind(_Kind), Expr(_Expr), IsDarwin(_IsDarwin) {} + +public: + /// @name Construction + /// @{ + + static const PPCMCExpr *Create(VariantKind Kind, const MCExpr *Expr, + bool isDarwin, MCContext &Ctx); + + static const PPCMCExpr *CreateLo(const MCExpr *Expr, + bool isDarwin, MCContext &Ctx) { + return Create(VK_PPC_LO, Expr, isDarwin, Ctx); + } + + static const PPCMCExpr *CreateHi(const MCExpr *Expr, + bool isDarwin, MCContext &Ctx) { + return Create(VK_PPC_HI, Expr, isDarwin, Ctx); + } + + static const PPCMCExpr *CreateHa(const MCExpr *Expr, + bool isDarwin, MCContext &Ctx) { + return Create(VK_PPC_HA, Expr, isDarwin, 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; } + + /// isDarwinSyntax - True if expression is to be printed using Darwin syntax. + bool isDarwinSyntax() const { return IsDarwin; } + + + /// @} + + void PrintImpl(raw_ostream &OS) const; + bool EvaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout) const; + void AddValueSymbols(MCAssembler *) const; + const MCSection *FindAssociatedSection() const { + return getSubExpr()->FindAssociatedSection(); + } + + // There are no TLS PPCMCExprs at the moment. + void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {} + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Target; + } +}; +} // end namespace llvm + +#endif diff --git a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp index 2209f93..f18d095 100644 --- a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp +++ b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp @@ -14,13 +14,16 @@ #include "PPCMCTargetDesc.h" #include "InstPrinter/PPCInstPrinter.h" #include "PPCMCAsmInfo.h" +#include "PPCTargetStreamer.h" #include "llvm/MC/MCCodeGenInfo.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MachineLocation.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/Support/TargetRegistry.h" #define GET_INSTRINFO_MC_DESC @@ -34,6 +37,9 @@ using namespace llvm; +// Pin the vtable to this file. +PPCTargetStreamer::~PPCTargetStreamer() {} + static MCInstrInfo *createPPCMCInstrInfo() { MCInstrInfo *X = new MCInstrInfo(); InitPPCMCInstrInfo(X); @@ -42,7 +48,8 @@ static MCInstrInfo *createPPCMCInstrInfo() { static MCRegisterInfo *createPPCMCRegisterInfo(StringRef TT) { Triple TheTriple(TT); - bool isPPC64 = (TheTriple.getArch() == Triple::ppc64); + bool isPPC64 = (TheTriple.getArch() == Triple::ppc64 || + TheTriple.getArch() == Triple::ppc64le); unsigned Flavour = isPPC64 ? 0 : 1; unsigned RA = isPPC64 ? PPC::LR8 : PPC::LR; @@ -58,9 +65,10 @@ static MCSubtargetInfo *createPPCMCSubtargetInfo(StringRef TT, StringRef CPU, return X; } -static MCAsmInfo *createPPCMCAsmInfo(const Target &T, StringRef TT) { +static MCAsmInfo *createPPCMCAsmInfo(const MCRegisterInfo &MRI, StringRef TT) { Triple TheTriple(TT); - bool isPPC64 = TheTriple.getArch() == Triple::ppc64; + bool isPPC64 = (TheTriple.getArch() == Triple::ppc64 || + TheTriple.getArch() == Triple::ppc64le); MCAsmInfo *MAI; if (TheTriple.isOSDarwin()) @@ -69,9 +77,10 @@ static MCAsmInfo *createPPCMCAsmInfo(const Target &T, StringRef TT) { MAI = new PPCLinuxMCAsmInfo(isPPC64); // Initial state of the frame pointer is R1. - MachineLocation Dst(MachineLocation::VirtualFP); - MachineLocation Src(isPPC64? PPC::X1 : PPC::R1, 0); - MAI->addInitialFrameState(0, Dst, Src); + unsigned Reg = isPPC64 ? PPC::X1 : PPC::R1; + MCCFIInstruction Inst = + MCCFIInstruction::createDefCfa(0, MRI.getDwarfRegNum(Reg, true), 0); + MAI->addInitialFrameState(Inst); return MAI; } @@ -90,13 +99,37 @@ static MCCodeGenInfo *createPPCMCCodeGenInfo(StringRef TT, Reloc::Model RM, } if (CM == CodeModel::Default) { Triple T(TT); - if (!T.isOSDarwin() && T.getArch() == Triple::ppc64) + if (!T.isOSDarwin() && + (T.getArch() == Triple::ppc64 || T.getArch() == Triple::ppc64le)) CM = CodeModel::Medium; } X->InitMCCodeGenInfo(RM, CM, OL); return X; } +namespace { +class PPCTargetAsmStreamer : public PPCTargetStreamer { + formatted_raw_ostream &OS; + +public: + PPCTargetAsmStreamer(formatted_raw_ostream &OS) : OS(OS) {} + virtual void emitTCEntry(const MCSymbol &S) { + OS << "\t.tc "; + OS << S.getName(); + OS << "[TC],"; + OS << S.getName(); + OS << '\n'; + } +}; + +class PPCTargetELFStreamer : public PPCTargetStreamer { + virtual void emitTCEntry(const MCSymbol &S) { + // Creates a R_PPC64_TOC relocation + Streamer->EmitSymbolValue(&S, 8); + } +}; +} + // This is duplicated code. Refactor this. static MCStreamer *createMCStreamer(const Target &T, StringRef TT, MCContext &Ctx, MCAsmBackend &MAB, @@ -107,7 +140,20 @@ static MCStreamer *createMCStreamer(const Target &T, StringRef TT, if (Triple(TT).isOSDarwin()) return createMachOStreamer(Ctx, MAB, OS, Emitter, RelaxAll); - return createELFStreamer(Ctx, MAB, OS, Emitter, RelaxAll, NoExecStack); + PPCTargetStreamer *S = new PPCTargetELFStreamer(); + return createELFStreamer(Ctx, S, MAB, OS, Emitter, RelaxAll, NoExecStack); +} + +static MCStreamer * +createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, + bool isVerboseAsm, bool useLoc, bool useCFI, + bool useDwarfDirectory, MCInstPrinter *InstPrint, + MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst) { + PPCTargetStreamer *S = new PPCTargetAsmStreamer(OS); + + return llvm::createAsmStreamer(Ctx, S, OS, isVerboseAsm, useLoc, useCFI, + useDwarfDirectory, InstPrint, CE, TAB, + ShowInst); } static MCInstPrinter *createPPCMCInstPrinter(const Target &T, @@ -116,45 +162,65 @@ static MCInstPrinter *createPPCMCInstPrinter(const Target &T, const MCInstrInfo &MII, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI) { - return new PPCInstPrinter(MAI, MII, MRI, SyntaxVariant); + bool isDarwin = Triple(STI.getTargetTriple()).isOSDarwin(); + return new PPCInstPrinter(MAI, MII, MRI, isDarwin); } extern "C" void LLVMInitializePowerPCTargetMC() { // Register the MC asm info. RegisterMCAsmInfoFn C(ThePPC32Target, createPPCMCAsmInfo); RegisterMCAsmInfoFn D(ThePPC64Target, createPPCMCAsmInfo); + RegisterMCAsmInfoFn E(ThePPC64LETarget, createPPCMCAsmInfo); // Register the MC codegen info. TargetRegistry::RegisterMCCodeGenInfo(ThePPC32Target, createPPCMCCodeGenInfo); TargetRegistry::RegisterMCCodeGenInfo(ThePPC64Target, createPPCMCCodeGenInfo); + TargetRegistry::RegisterMCCodeGenInfo(ThePPC64LETarget, + createPPCMCCodeGenInfo); // Register the MC instruction info. TargetRegistry::RegisterMCInstrInfo(ThePPC32Target, createPPCMCInstrInfo); TargetRegistry::RegisterMCInstrInfo(ThePPC64Target, createPPCMCInstrInfo); + TargetRegistry::RegisterMCInstrInfo(ThePPC64LETarget, + createPPCMCInstrInfo); // Register the MC register info. TargetRegistry::RegisterMCRegInfo(ThePPC32Target, createPPCMCRegisterInfo); TargetRegistry::RegisterMCRegInfo(ThePPC64Target, createPPCMCRegisterInfo); + TargetRegistry::RegisterMCRegInfo(ThePPC64LETarget, createPPCMCRegisterInfo); // Register the MC subtarget info. TargetRegistry::RegisterMCSubtargetInfo(ThePPC32Target, createPPCMCSubtargetInfo); TargetRegistry::RegisterMCSubtargetInfo(ThePPC64Target, createPPCMCSubtargetInfo); + TargetRegistry::RegisterMCSubtargetInfo(ThePPC64LETarget, + createPPCMCSubtargetInfo); // Register the MC Code Emitter TargetRegistry::RegisterMCCodeEmitter(ThePPC32Target, createPPCMCCodeEmitter); TargetRegistry::RegisterMCCodeEmitter(ThePPC64Target, createPPCMCCodeEmitter); + TargetRegistry::RegisterMCCodeEmitter(ThePPC64LETarget, + createPPCMCCodeEmitter); // Register the asm backend. TargetRegistry::RegisterMCAsmBackend(ThePPC32Target, createPPCAsmBackend); TargetRegistry::RegisterMCAsmBackend(ThePPC64Target, createPPCAsmBackend); + TargetRegistry::RegisterMCAsmBackend(ThePPC64LETarget, createPPCAsmBackend); // Register the object streamer. TargetRegistry::RegisterMCObjectStreamer(ThePPC32Target, createMCStreamer); TargetRegistry::RegisterMCObjectStreamer(ThePPC64Target, createMCStreamer); + TargetRegistry::RegisterMCObjectStreamer(ThePPC64LETarget, createMCStreamer); + + // Register the asm streamer. + TargetRegistry::RegisterAsmStreamer(ThePPC32Target, createMCAsmStreamer); + TargetRegistry::RegisterAsmStreamer(ThePPC64Target, createMCAsmStreamer); + TargetRegistry::RegisterAsmStreamer(ThePPC64LETarget, createMCAsmStreamer); // Register the MCInstPrinter. TargetRegistry::RegisterMCInstPrinter(ThePPC32Target, createPPCMCInstPrinter); TargetRegistry::RegisterMCInstPrinter(ThePPC64Target, createPPCMCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(ThePPC64LETarget, + createPPCMCInstPrinter); } diff --git a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h index 38a7420..0b0ca24 100644 --- a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h +++ b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h @@ -33,18 +33,24 @@ class raw_ostream; extern Target ThePPC32Target; extern Target ThePPC64Target; +extern Target ThePPC64LETarget; MCCodeEmitter *createPPCMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx); -MCAsmBackend *createPPCAsmBackend(const Target &T, StringRef TT, StringRef CPU); +MCAsmBackend *createPPCAsmBackend(const Target &T, const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU); /// createPPCELFObjectWriter - Construct an PPC ELF object writer. MCObjectWriter *createPPCELFObjectWriter(raw_ostream &OS, bool Is64Bit, uint8_t OSABI); +/// createPPCELFObjectWriter - Construct a PPC Mach-O object writer. +MCObjectWriter *createPPCMachObjectWriter(raw_ostream &OS, bool Is64Bit, + uint32_t CPUType, + uint32_t CPUSubtype); } // End llvm namespace // Generated files will use "namespace PPC". To avoid symbol clash, diff --git a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp new file mode 100644 index 0000000..bbafe2e --- /dev/null +++ b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp @@ -0,0 +1,389 @@ +//===-- PPCMachObjectWriter.cpp - PPC Mach-O Writer -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/PPCMCTargetDesc.h" +#include "MCTargetDesc/PPCFixupKinds.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCMachObjectWriter.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/MachO.h" + +using namespace llvm; + +namespace { +class PPCMachObjectWriter : public MCMachObjectTargetWriter { + bool RecordScatteredRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + unsigned Log2Size, uint64_t &FixedValue); + + void RecordPPCRelocation(MachObjectWriter *Writer, const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue); + +public: + PPCMachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype) + : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype, + /*UseAggressiveSymbolFolding=*/Is64Bit) {} + + void RecordRelocation(MachObjectWriter *Writer, const MCAssembler &Asm, + const MCAsmLayout &Layout, const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + uint64_t &FixedValue) { + if (Writer->is64Bit()) { + report_fatal_error("Relocation emission for MachO/PPC64 unimplemented."); + } else + RecordPPCRelocation(Writer, Asm, Layout, Fragment, Fixup, Target, + FixedValue); + } +}; +} + +/// computes the log2 of the size of the relocation, +/// used for relocation_info::r_length. +static unsigned getFixupKindLog2Size(unsigned Kind) { + switch (Kind) { + default: + report_fatal_error("log2size(FixupKind): Unhandled fixup kind!"); + case FK_PCRel_1: + case FK_Data_1: + return 0; + case FK_PCRel_2: + case FK_Data_2: + return 1; + case FK_PCRel_4: + case PPC::fixup_ppc_brcond14: + case PPC::fixup_ppc_half16: + case PPC::fixup_ppc_br24: + case FK_Data_4: + return 2; + case FK_PCRel_8: + case FK_Data_8: + return 3; + } + return 0; +} + +/// Translates generic PPC fixup kind to Mach-O/PPC relocation type enum. +/// Outline based on PPCELFObjectWriter::getRelocTypeInner(). +static unsigned getRelocType(const MCValue &Target, + const MCFixupKind FixupKind, // from + // Fixup.getKind() + const bool IsPCRel) { + const MCSymbolRefExpr::VariantKind Modifier = + Target.isAbsolute() ? MCSymbolRefExpr::VK_None + : Target.getSymA()->getKind(); + // determine the type of the relocation + unsigned Type = MachO::GENERIC_RELOC_VANILLA; + if (IsPCRel) { // relative to PC + switch ((unsigned)FixupKind) { + default: + report_fatal_error("Unimplemented fixup kind (relative)"); + case PPC::fixup_ppc_br24: + Type = MachO::PPC_RELOC_BR24; // R_PPC_REL24 + break; + case PPC::fixup_ppc_brcond14: + Type = MachO::PPC_RELOC_BR14; + break; + case PPC::fixup_ppc_half16: + switch (Modifier) { + default: + llvm_unreachable("Unsupported modifier for half16 fixup"); + case MCSymbolRefExpr::VK_PPC_HA: + Type = MachO::PPC_RELOC_HA16; + break; + case MCSymbolRefExpr::VK_PPC_LO: + Type = MachO::PPC_RELOC_LO16; + break; + case MCSymbolRefExpr::VK_PPC_HI: + Type = MachO::PPC_RELOC_HI16; + break; + } + break; + } + } else { + switch ((unsigned)FixupKind) { + default: + report_fatal_error("Unimplemented fixup kind (absolute)!"); + case PPC::fixup_ppc_half16: + switch (Modifier) { + default: + llvm_unreachable("Unsupported modifier for half16 fixup"); + case MCSymbolRefExpr::VK_PPC_HA: + Type = MachO::PPC_RELOC_HA16_SECTDIFF; + break; + case MCSymbolRefExpr::VK_PPC_LO: + Type = MachO::PPC_RELOC_LO16_SECTDIFF; + break; + case MCSymbolRefExpr::VK_PPC_HI: + Type = MachO::PPC_RELOC_HI16_SECTDIFF; + break; + } + break; + case FK_Data_4: + break; + case FK_Data_2: + break; + } + } + return Type; +} + +static void makeRelocationInfo(MachO::any_relocation_info &MRE, + const uint32_t FixupOffset, const uint32_t Index, + const unsigned IsPCRel, const unsigned Log2Size, + const unsigned IsExtern, const unsigned Type) { + MRE.r_word0 = FixupOffset; + // The bitfield offsets that work (as determined by trial-and-error) + // are different than what is documented in the mach-o manuals. + // This appears to be an endianness issue; reversing the order of the + // documented bitfields in <llvm/Support/MachO.h> fixes this (but + // breaks x86/ARM assembly). + MRE.r_word1 = ((Index << 8) | // was << 0 + (IsPCRel << 7) | // was << 24 + (Log2Size << 5) | // was << 25 + (IsExtern << 4) | // was << 27 + (Type << 0)); // was << 28 +} + +static void +makeScatteredRelocationInfo(MachO::any_relocation_info &MRE, + const uint32_t Addr, const unsigned Type, + const unsigned Log2Size, const unsigned IsPCRel, + const uint32_t Value2) { + // For notes on bitfield positions and endianness, see: + // https://developer.apple.com/library/mac/documentation/developertools/conceptual/MachORuntime/Reference/reference.html#//apple_ref/doc/uid/20001298-scattered_relocation_entry + MRE.r_word0 = ((Addr << 0) | (Type << 24) | (Log2Size << 28) | + (IsPCRel << 30) | MachO::R_SCATTERED); + MRE.r_word1 = Value2; +} + +/// Compute fixup offset (address). +static uint32_t getFixupOffset(const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup) { + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + // On Mach-O, ppc_fixup_half16 relocations must refer to the + // start of the instruction, not the second halfword, as ELF does + if (unsigned(Fixup.getKind()) == PPC::fixup_ppc_half16) + FixupOffset &= ~uint32_t(3); + return FixupOffset; +} + +/// \return false if falling back to using non-scattered relocation, +/// otherwise true for normal scattered relocation. +/// based on X86MachObjectWriter::RecordScatteredRelocation +/// and ARMMachObjectWriter::RecordScatteredRelocation +bool PPCMachObjectWriter::RecordScatteredRelocation( + MachObjectWriter *Writer, const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, + unsigned Log2Size, uint64_t &FixedValue) { + // caller already computes these, can we just pass and reuse? + const uint32_t FixupOffset = getFixupOffset(Layout, Fragment, Fixup); + const MCFixupKind FK = Fixup.getKind(); + const unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, FK); + const unsigned Type = getRelocType(Target, FK, IsPCRel); + + // Is this a local or SECTDIFF relocation entry? + // SECTDIFF relocation entries have symbol subtractions, + // and require two entries, the first for the add-symbol value, + // the second for the subtract-symbol value. + + // See <reloc.h>. + const MCSymbol *A = &Target.getSymA()->getSymbol(); + MCSymbolData *A_SD = &Asm.getSymbolData(*A); + + if (!A_SD->getFragment()) + report_fatal_error("symbol '" + A->getName() + + "' can not be undefined in a subtraction expression"); + + uint32_t Value = Writer->getSymbolAddress(A_SD, Layout); + uint64_t SecAddr = + Writer->getSectionAddress(A_SD->getFragment()->getParent()); + FixedValue += SecAddr; + uint32_t Value2 = 0; + + if (const MCSymbolRefExpr *B = Target.getSymB()) { + MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); + + if (!B_SD->getFragment()) + report_fatal_error("symbol '" + B->getSymbol().getName() + + "' can not be undefined in a subtraction expression"); + + // FIXME: is Type correct? see include/llvm/Support/MachO.h + Value2 = Writer->getSymbolAddress(B_SD, Layout); + FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent()); + } + // FIXME: does FixedValue get used?? + + // Relocations are written out in reverse order, so the PAIR comes first. + if (Type == MachO::PPC_RELOC_SECTDIFF || + Type == MachO::PPC_RELOC_HI16_SECTDIFF || + Type == MachO::PPC_RELOC_LO16_SECTDIFF || + Type == MachO::PPC_RELOC_HA16_SECTDIFF || + Type == MachO::PPC_RELOC_LO14_SECTDIFF || + Type == MachO::PPC_RELOC_LOCAL_SECTDIFF) { + // X86 had this piece, but ARM does not + // If the offset is too large to fit in a scattered relocation, + // we're hosed. It's an unfortunate limitation of the MachO format. + if (FixupOffset > 0xffffff) { + char Buffer[32]; + format("0x%x", FixupOffset).print(Buffer, sizeof(Buffer)); + Asm.getContext().FatalError(Fixup.getLoc(), + Twine("Section too large, can't encode " + "r_address (") + + Buffer + ") into 24 bits of scattered " + "relocation entry."); + llvm_unreachable("fatal error returned?!"); + } + + // Is this supposed to follow MCTarget/PPCAsmBackend.cpp:adjustFixupValue()? + // see PPCMCExpr::EvaluateAsRelocatableImpl() + uint32_t other_half = 0; + switch (Type) { + case MachO::PPC_RELOC_LO16_SECTDIFF: + other_half = (FixedValue >> 16) & 0xffff; + // applyFixupOffset longer extracts the high part because it now assumes + // this was already done. + // It looks like this is not true for the FixedValue needed with Mach-O + // relocs. + // So we need to adjust FixedValue again here. + FixedValue &= 0xffff; + break; + case MachO::PPC_RELOC_HA16_SECTDIFF: + other_half = FixedValue & 0xffff; + FixedValue = + ((FixedValue >> 16) + ((FixedValue & 0x8000) ? 1 : 0)) & 0xffff; + break; + case MachO::PPC_RELOC_HI16_SECTDIFF: + other_half = FixedValue & 0xffff; + FixedValue = (FixedValue >> 16) & 0xffff; + break; + default: + llvm_unreachable("Invalid PPC scattered relocation type."); + break; + } + + MachO::any_relocation_info MRE; + makeScatteredRelocationInfo(MRE, other_half, MachO::GENERIC_RELOC_PAIR, + Log2Size, IsPCRel, Value2); + Writer->addRelocation(Fragment->getParent(), MRE); + } else { + // If the offset is more than 24-bits, it won't fit in a scattered + // relocation offset field, so we fall back to using a non-scattered + // relocation. This is a bit risky, as if the offset reaches out of + // the block and the linker is doing scattered loading on this + // symbol, things can go badly. + // + // Required for 'as' compatibility. + if (FixupOffset > 0xffffff) + return false; + } + MachO::any_relocation_info MRE; + makeScatteredRelocationInfo(MRE, FixupOffset, Type, Log2Size, IsPCRel, Value); + Writer->addRelocation(Fragment->getParent(), MRE); + return true; +} + +// see PPCELFObjectWriter for a general outline of cases +void PPCMachObjectWriter::RecordPPCRelocation( + MachObjectWriter *Writer, const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, + uint64_t &FixedValue) { + const MCFixupKind FK = Fixup.getKind(); // unsigned + const unsigned Log2Size = getFixupKindLog2Size(FK); + const bool IsPCRel = Writer->isFixupKindPCRel(Asm, FK); + const unsigned RelocType = getRelocType(Target, FK, IsPCRel); + + // If this is a difference or a defined symbol plus an offset, then we need a + // scattered relocation entry. Differences always require scattered + // relocations. + if (Target.getSymB() && + // Q: are branch targets ever scattered? + RelocType != MachO::PPC_RELOC_BR24 && + RelocType != MachO::PPC_RELOC_BR14) { + RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, Target, + Log2Size, FixedValue); + return; + } + + // this doesn't seem right for RIT_PPC_BR24 + // Get the symbol data, if any. + MCSymbolData *SD = 0; + if (Target.getSymA()) + SD = &Asm.getSymbolData(Target.getSymA()->getSymbol()); + + // See <reloc.h>. + const uint32_t FixupOffset = getFixupOffset(Layout, Fragment, Fixup); + unsigned Index = 0; + unsigned IsExtern = 0; + unsigned Type = RelocType; + + if (Target.isAbsolute()) { // constant + // SymbolNum of 0 indicates the absolute section. + // + // FIXME: Currently, these are never generated (see code below). I cannot + // find a case where they are actually emitted. + report_fatal_error("FIXME: relocations to absolute targets " + "not yet implemented"); + // the above line stolen from ARM, not sure + } else { + // Resolve constant variables. + if (SD->getSymbol().isVariable()) { + int64_t Res; + if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( + Res, Layout, Writer->getSectionAddressMap())) { + FixedValue = Res; + return; + } + } + + // Check whether we need an external or internal relocation. + if (Writer->doesSymbolRequireExternRelocation(SD)) { + IsExtern = 1; + Index = SD->getIndex(); + // For external relocations, make sure to offset the fixup value to + // compensate for the addend of the symbol address, if it was + // undefined. This occurs with weak definitions, for example. + if (!SD->Symbol->isUndefined()) + FixedValue -= Layout.getSymbolOffset(SD); + } else { + // The index is the section ordinal (1-based). + const MCSectionData &SymSD = + Asm.getSectionData(SD->getSymbol().getSection()); + Index = SymSD.getOrdinal() + 1; + FixedValue += Writer->getSectionAddress(&SymSD); + } + if (IsPCRel) + FixedValue -= Writer->getSectionAddress(Fragment->getParent()); + } + + // struct relocation_info (8 bytes) + MachO::any_relocation_info MRE; + makeRelocationInfo(MRE, FixupOffset, Index, IsPCRel, Log2Size, IsExtern, + Type); + Writer->addRelocation(Fragment->getParent(), MRE); +} + +MCObjectWriter *llvm::createPPCMachObjectWriter(raw_ostream &OS, bool Is64Bit, + uint32_t CPUType, + uint32_t CPUSubtype) { + return createMachObjectWriter( + new PPCMachObjectWriter(Is64Bit, CPUType, CPUSubtype), OS, + /*IsLittleEndian=*/false); +} diff --git a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.cpp b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.cpp index 853e505..63facc5 100644 --- a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.cpp +++ b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.cpp @@ -26,6 +26,22 @@ PPC::Predicate PPC::InvertPredicate(PPC::Predicate Opcode) { case PPC::PRED_LE: return PPC::PRED_GT; case PPC::PRED_NU: return PPC::PRED_UN; case PPC::PRED_UN: return PPC::PRED_NU; + case PPC::PRED_EQ_MINUS: return PPC::PRED_NE_PLUS; + case PPC::PRED_NE_MINUS: return PPC::PRED_EQ_PLUS; + case PPC::PRED_LT_MINUS: return PPC::PRED_GE_PLUS; + case PPC::PRED_GE_MINUS: return PPC::PRED_LT_PLUS; + case PPC::PRED_GT_MINUS: return PPC::PRED_LE_PLUS; + case PPC::PRED_LE_MINUS: return PPC::PRED_GT_PLUS; + case PPC::PRED_NU_MINUS: return PPC::PRED_UN_PLUS; + case PPC::PRED_UN_MINUS: return PPC::PRED_NU_PLUS; + case PPC::PRED_EQ_PLUS: return PPC::PRED_NE_MINUS; + case PPC::PRED_NE_PLUS: return PPC::PRED_EQ_MINUS; + case PPC::PRED_LT_PLUS: return PPC::PRED_GE_MINUS; + case PPC::PRED_GE_PLUS: return PPC::PRED_LT_MINUS; + case PPC::PRED_GT_PLUS: return PPC::PRED_LE_MINUS; + case PPC::PRED_LE_PLUS: return PPC::PRED_GT_MINUS; + case PPC::PRED_NU_PLUS: return PPC::PRED_UN_MINUS; + case PPC::PRED_UN_PLUS: return PPC::PRED_NU_MINUS; } llvm_unreachable("Unknown PPC branch opcode!"); } @@ -40,6 +56,22 @@ PPC::Predicate PPC::getSwappedPredicate(PPC::Predicate Opcode) { case PPC::PRED_LE: return PPC::PRED_GE; case PPC::PRED_NU: return PPC::PRED_NU; case PPC::PRED_UN: return PPC::PRED_UN; + case PPC::PRED_EQ_MINUS: return PPC::PRED_EQ_MINUS; + case PPC::PRED_NE_MINUS: return PPC::PRED_NE_MINUS; + case PPC::PRED_LT_MINUS: return PPC::PRED_GT_MINUS; + case PPC::PRED_GE_MINUS: return PPC::PRED_LE_MINUS; + case PPC::PRED_GT_MINUS: return PPC::PRED_LT_MINUS; + case PPC::PRED_LE_MINUS: return PPC::PRED_GE_MINUS; + case PPC::PRED_NU_MINUS: return PPC::PRED_NU_MINUS; + case PPC::PRED_UN_MINUS: return PPC::PRED_UN_MINUS; + case PPC::PRED_EQ_PLUS: return PPC::PRED_EQ_PLUS; + case PPC::PRED_NE_PLUS: return PPC::PRED_NE_PLUS; + case PPC::PRED_LT_PLUS: return PPC::PRED_GT_PLUS; + case PPC::PRED_GE_PLUS: return PPC::PRED_LE_PLUS; + case PPC::PRED_GT_PLUS: return PPC::PRED_LT_PLUS; + case PPC::PRED_LE_PLUS: return PPC::PRED_GE_PLUS; + case PPC::PRED_NU_PLUS: return PPC::PRED_NU_PLUS; + case PPC::PRED_UN_PLUS: return PPC::PRED_UN_PLUS; } llvm_unreachable("Unknown PPC branch opcode!"); } diff --git a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h index 444758c..d498c2f 100644 --- a/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h +++ b/contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h @@ -25,14 +25,30 @@ namespace llvm { namespace PPC { /// Predicate - These are "(BI << 5) | BO" for various predicates. enum Predicate { - PRED_LT = (0 << 5) | 12, - PRED_LE = (1 << 5) | 4, - PRED_EQ = (2 << 5) | 12, - PRED_GE = (0 << 5) | 4, - PRED_GT = (1 << 5) | 12, - PRED_NE = (2 << 5) | 4, - PRED_UN = (3 << 5) | 12, - PRED_NU = (3 << 5) | 4 + PRED_LT = (0 << 5) | 12, + PRED_LE = (1 << 5) | 4, + PRED_EQ = (2 << 5) | 12, + PRED_GE = (0 << 5) | 4, + PRED_GT = (1 << 5) | 12, + PRED_NE = (2 << 5) | 4, + PRED_UN = (3 << 5) | 12, + PRED_NU = (3 << 5) | 4, + PRED_LT_MINUS = (0 << 5) | 14, + PRED_LE_MINUS = (1 << 5) | 6, + PRED_EQ_MINUS = (2 << 5) | 14, + PRED_GE_MINUS = (0 << 5) | 6, + PRED_GT_MINUS = (1 << 5) | 14, + PRED_NE_MINUS = (2 << 5) | 6, + PRED_UN_MINUS = (3 << 5) | 14, + PRED_NU_MINUS = (3 << 5) | 6, + PRED_LT_PLUS = (0 << 5) | 15, + PRED_LE_PLUS = (1 << 5) | 7, + PRED_EQ_PLUS = (2 << 5) | 15, + PRED_GE_PLUS = (0 << 5) | 7, + PRED_GT_PLUS = (1 << 5) | 15, + PRED_NE_PLUS = (2 << 5) | 7, + PRED_UN_PLUS = (3 << 5) | 15, + PRED_NU_PLUS = (3 << 5) | 7 }; /// Invert the specified predicate. != -> ==, < -> >=. |