diff options
Diffstat (limited to 'lib/Target/PowerPC')
-rw-r--r-- | lib/Target/PowerPC/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp | 36 | ||||
-rw-r--r-- | lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp | 58 | ||||
-rw-r--r-- | lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp | 8 | ||||
-rw-r--r-- | lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp | 9 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCFrameLowering.cpp | 1 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCISelLowering.cpp | 5 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCISelLowering.h | 34 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCInstrFormats.td | 13 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCInstrInfo.td | 10 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCTargetMachine.cpp | 1 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCTargetObjectFile.cpp | 57 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCTargetObjectFile.h | 32 |
13 files changed, 178 insertions, 87 deletions
diff --git a/lib/Target/PowerPC/CMakeLists.txt b/lib/Target/PowerPC/CMakeLists.txt index 71803cdac9..e5c5204708 100644 --- a/lib/Target/PowerPC/CMakeLists.txt +++ b/lib/Target/PowerPC/CMakeLists.txt @@ -27,6 +27,7 @@ add_llvm_target(PowerPCCodeGen PPCRegisterInfo.cpp PPCSubtarget.cpp PPCTargetMachine.cpp + PPCTargetObjectFile.cpp PPCTargetTransformInfo.cpp PPCSelectionDAGInfo.cpp ) diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp index ec2657403e..b1ac4a6f27 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp @@ -22,7 +22,7 @@ #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!"); @@ -50,6 +50,29 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { } } +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_ha16: + case PPC::fixup_ppc_lo16: + case PPC::fixup_ppc_lo16_ds: + return 2; + case FK_Data_4: + case PPC::fixup_ppc_brcond14: + case PPC::fixup_ppc_br24: + return 4; + case FK_Data_8: + return 8; + case PPC::fixup_ppc_tlsreg: + case PPC::fixup_ppc_nofixup: + return 0; + } +} + namespace { class PPCMachObjectWriter : public MCMachObjectTargetWriter { public: @@ -77,9 +100,9 @@ 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_lo16", 0, 16, 0 }, + { "fixup_ppc_ha16", 0, 16, 0 }, + { "fixup_ppc_lo16_ds", 0, 14, 0 }, { "fixup_ppc_tlsreg", 0, 0, 0 }, { "fixup_ppc_nofixup", 0, 0, 0 } }; @@ -98,12 +121,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 { diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp index 7a84723ed5..2508cc2f37 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -33,26 +33,9 @@ namespace { 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, @@ -240,47 +223,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/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp index 2223cd623c..3f04a4ec0a 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp @@ -142,7 +142,7 @@ unsigned PPCMCCodeEmitter::getHA16Encoding(const MCInst &MI, unsigned 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(), + Fixups.push_back(MCFixup::Create(2, MO.getExpr(), (MCFixupKind)PPC::fixup_ppc_ha16)); return 0; } @@ -153,7 +153,7 @@ unsigned PPCMCCodeEmitter::getLO16Encoding(const MCInst &MI, unsigned 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(), + Fixups.push_back(MCFixup::Create(2, MO.getExpr(), (MCFixupKind)PPC::fixup_ppc_lo16)); return 0; } @@ -170,7 +170,7 @@ 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(), + Fixups.push_back(MCFixup::Create(2, MO.getExpr(), (MCFixupKind)PPC::fixup_ppc_lo16)); return RegBits; } @@ -188,7 +188,7 @@ unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo, return (getMachineOpValue(MI, MO, Fixups) & 0x3FFF) | RegBits; // Add a fixup for the displacement field. - Fixups.push_back(MCFixup::Create(0, MO.getExpr(), + Fixups.push_back(MCFixup::Create(2, MO.getExpr(), (MCFixupKind)PPC::fixup_ppc_lo16_ds)); return RegBits; } diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp index a01fa44a9a..2da30f9038 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp @@ -58,7 +58,7 @@ static MCSubtargetInfo *createPPCMCSubtargetInfo(StringRef TT, StringRef CPU, return X; } -static MCAsmInfo *createPPCMCAsmInfo(StringRef TT) { +static MCAsmInfo *createPPCMCAsmInfo(const MCRegisterInfo &MRI, StringRef TT) { Triple TheTriple(TT); bool isPPC64 = TheTriple.getArch() == Triple::ppc64; @@ -69,9 +69,10 @@ static MCAsmInfo *createPPCMCAsmInfo(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; } diff --git a/lib/Target/PowerPC/PPCFrameLowering.cpp b/lib/Target/PowerPC/PPCFrameLowering.cpp index cd70aeed87..1f0c3c4b5d 100644 --- a/lib/Target/PowerPC/PPCFrameLowering.cpp +++ b/lib/Target/PowerPC/PPCFrameLowering.cpp @@ -1168,6 +1168,7 @@ PPCFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, FuncInfo->addMustSaveCR(Reg); } else { CRSpilled = true; + FuncInfo->setSpillsCR(); // 32-bit: FP-relative. Note that we made sure CR2-CR4 all have // the same frame index in PPCRegisterInfo::hasReservedSpillSlot. diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 3819bc8f15..eee2bb87de 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -16,6 +16,7 @@ #include "PPCMachineFunctionInfo.h" #include "PPCPerfectShuffle.h" #include "PPCTargetMachine.h" +#include "PPCTargetObjectFile.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -64,6 +65,9 @@ static TargetLoweringObjectFile *CreateTLOF(const PPCTargetMachine &TM) { if (TM.getSubtargetImpl()->isDarwin()) return new TargetLoweringObjectFileMachO(); + if (TM.getSubtargetImpl()->isSVR4ABI()) + return new PPC64LinuxTargetObjectFile(); + return new TargetLoweringObjectFileELF(); } @@ -662,6 +666,7 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const { case PPCISD::ADDIS_DTPREL_HA: return "PPCISD::ADDIS_DTPREL_HA"; case PPCISD::ADDI_DTPREL_L: return "PPCISD::ADDI_DTPREL_L"; case PPCISD::VADD_SPLAT: return "PPCISD::VADD_SPLAT"; + case PPCISD::SC: return "PPCISD::SC"; } } diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h index b219de38d5..2a1cc121da 100644 --- a/lib/Target/PowerPC/PPCISelLowering.h +++ b/lib/Target/PowerPC/PPCISelLowering.h @@ -175,61 +175,61 @@ namespace llvm { /// G8RC = ADDIS_GOT_TPREL_HA %X2, Symbol - Used by the initial-exec /// TLS model, produces an ADDIS8 instruction that adds the GOT - /// base to sym@got@tprel@ha. + /// base to sym\@got\@tprel\@ha. ADDIS_GOT_TPREL_HA, /// G8RC = LD_GOT_TPREL_L Symbol, G8RReg - Used by the initial-exec /// TLS model, produces a LD instruction with base register G8RReg - /// and offset sym@got@tprel@l. This completes the addition that + /// and offset sym\@got\@tprel\@l. This completes the addition that /// finds the offset of "sym" relative to the thread pointer. LD_GOT_TPREL_L, /// G8RC = ADD_TLS G8RReg, Symbol - Used by the initial-exec TLS /// model, produces an ADD instruction that adds the contents of /// G8RReg to the thread pointer. Symbol contains a relocation - /// sym@tls which is to be replaced by the thread pointer and + /// sym\@tls which is to be replaced by the thread pointer and /// identifies to the linker that the instruction is part of a /// TLS sequence. ADD_TLS, /// G8RC = ADDIS_TLSGD_HA %X2, Symbol - For the general-dynamic TLS /// model, produces an ADDIS8 instruction that adds the GOT base - /// register to sym@got@tlsgd@ha. + /// register to sym\@got\@tlsgd\@ha. ADDIS_TLSGD_HA, /// G8RC = ADDI_TLSGD_L G8RReg, Symbol - For the general-dynamic TLS /// model, produces an ADDI8 instruction that adds G8RReg to - /// sym@got@tlsgd@l. + /// sym\@got\@tlsgd\@l. ADDI_TLSGD_L, /// G8RC = GET_TLS_ADDR %X3, Symbol - For the general-dynamic TLS - /// model, produces a call to __tls_get_addr(sym@tlsgd). + /// model, produces a call to __tls_get_addr(sym\@tlsgd). GET_TLS_ADDR, /// G8RC = ADDIS_TLSLD_HA %X2, Symbol - For the local-dynamic TLS /// model, produces an ADDIS8 instruction that adds the GOT base - /// register to sym@got@tlsld@ha. + /// register to sym\@got\@tlsld\@ha. ADDIS_TLSLD_HA, /// G8RC = ADDI_TLSLD_L G8RReg, Symbol - For the local-dynamic TLS /// model, produces an ADDI8 instruction that adds G8RReg to - /// sym@got@tlsld@l. + /// sym\@got\@tlsld\@l. ADDI_TLSLD_L, /// G8RC = GET_TLSLD_ADDR %X3, Symbol - For the local-dynamic TLS - /// model, produces a call to __tls_get_addr(sym@tlsld). + /// model, produces a call to __tls_get_addr(sym\@tlsld). GET_TLSLD_ADDR, /// G8RC = ADDIS_DTPREL_HA %X3, Symbol, Chain - For the /// local-dynamic TLS model, produces an ADDIS8 instruction - /// that adds X3 to sym@dtprel@ha. The Chain operand is needed + /// that adds X3 to sym\@dtprel\@ha. The Chain operand is needed /// to tie this in place following a copy to %X3 from the result /// of a GET_TLSLD_ADDR. ADDIS_DTPREL_HA, /// G8RC = ADDI_DTPREL_L G8RReg, Symbol - For the local-dynamic TLS /// model, produces an ADDI8 instruction that adds G8RReg to - /// sym@got@dtprel@l. + /// sym\@got\@dtprel\@l. ADDI_DTPREL_L, /// VRRC = VADD_SPLAT Elt, EltSize - Temporary node to be expanded @@ -238,6 +238,10 @@ namespace llvm { /// optimizations due to constant folding. VADD_SPLAT, + /// CHAIN = SC CHAIN, Imm128 - System call. The 7-bit unsigned + /// operand identifies the operating system entry point. + SC, + /// CHAIN = STBRX CHAIN, GPRC, Ptr, Type - This is a /// byte-swapping store instruction. It byte-swaps the low "Type" bits of /// the GPRC input, then stores it through Ptr. Type can be either i16 or @@ -266,16 +270,16 @@ namespace llvm { /// G8RC = ADDIS_TOC_HA %X2, Symbol - For medium and large code model, /// produces an ADDIS8 instruction that adds the TOC base register to - /// sym@toc@ha. + /// sym\@toc\@ha. ADDIS_TOC_HA, /// G8RC = LD_TOC_L Symbol, G8RReg - For medium and large code model, /// produces a LD instruction with base register G8RReg and offset - /// sym@toc@l. Preceded by an ADDIS_TOC_HA to form a full 32-bit offset. + /// sym\@toc\@l. Preceded by an ADDIS_TOC_HA to form a full 32-bit offset. LD_TOC_L, /// G8RC = ADDI_TOC_L G8RReg, Symbol - For medium code model, produces - /// an ADDI8 instruction that adds G8RReg to sym@toc@l. + /// an ADDI8 instruction that adds G8RReg to sym\@toc\@l. /// Preceded by an ADDIS_TOC_HA to form a full 32-bit offset. ADDI_TOC_L }; @@ -450,7 +454,7 @@ namespace llvm { /// It returns EVT::Other if the type should be determined using generic /// target-independent logic. virtual EVT - getOptimalMemOpType(uint64_t Size, unsigned DstAlign, unsigned SrcAlign, + getOptimalMemOpType(uint64_t Size, unsigned DstAlign, unsigned SrcAlign, bool IsMemset, bool ZeroMemset, bool MemcpyStrSrc, MachineFunction &MF) const; diff --git a/lib/Target/PowerPC/PPCInstrFormats.td b/lib/Target/PowerPC/PPCInstrFormats.td index b6f4e85215..a24405851c 100644 --- a/lib/Target/PowerPC/PPCInstrFormats.td +++ b/lib/Target/PowerPC/PPCInstrFormats.td @@ -145,6 +145,19 @@ class BForm_2<bits<6> opcode, bits<5> bo, bits<5> bi, bit aa, bit lk, let Inst{31} = lk; } +// 1.7.3 SC-Form +class SCForm<bits<6> opcode, bits<1> xo, + dag OOL, dag IOL, string asmstr, InstrItinClass itin, + list<dag> pattern> + : I<opcode, OOL, IOL, asmstr, itin> { + bits<7> LEV; + + let Pattern = pattern; + + let Inst{20-26} = LEV; + let Inst{30} = xo; +} + // 1.7.4 D-Form class DForm_base<bits<6> opcode, dag OOL, dag IOL, string asmstr, InstrItinClass itin, list<dag> pattern> diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td index 4763069f25..9c39b34ab0 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.td +++ b/lib/Target/PowerPC/PPCInstrInfo.td @@ -162,6 +162,10 @@ def PPCeh_sjlj_longjmp : SDNode<"PPCISD::EH_SJLJ_LONGJMP", SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>, [SDNPHasChain, SDNPSideEffect]>; +def SDT_PPCsc : SDTypeProfile<0, 1, [SDTCisInt<0>]>; +def PPCsc : SDNode<"PPCISD::SC", SDT_PPCsc, + [SDNPHasChain, SDNPSideEffect]>; + def PPCvcmp : SDNode<"PPCISD::VCMP" , SDT_PPCvcmp, []>; def PPCvcmp_o : SDNode<"PPCISD::VCMPo", SDT_PPCvcmp, [SDNPOutGlue]>; @@ -987,6 +991,12 @@ let isBranch = 1, isTerminator = 1 in { "#EH_SjLj_Setup\t$dst", []>; } +// System call. +let PPC970_Unit = 7 in { + def SC : SCForm<17, 1, (outs), (ins i32imm:$lev), + "sc $lev", BrB, [(PPCsc (i32 imm:$lev))]>; +} + // DCB* instructions. def DCBA : DCB_Form<758, 0, (outs), (ins memrr:$dst), "dcba $dst", LdStDCBF, [(int_ppc_dcba xoaddr:$dst)]>, diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp index 14dc794195..0b099edff4 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -48,6 +48,7 @@ PPCTargetMachine::PPCTargetMachine(const Target &T, StringRef TT, // The binutils for the BG/P are too old for CFI. if (Subtarget.isBGP()) setMCUseCFI(false); + initAsmInfo(); } void PPC32TargetMachine::anchor() { } diff --git a/lib/Target/PowerPC/PPCTargetObjectFile.cpp b/lib/Target/PowerPC/PPCTargetObjectFile.cpp new file mode 100644 index 0000000000..90e4f15452 --- /dev/null +++ b/lib/Target/PowerPC/PPCTargetObjectFile.cpp @@ -0,0 +1,57 @@ +//===-- PPCTargetObjectFile.cpp - PPC Object Info -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PPCTargetObjectFile.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/Target/Mangler.h" + +using namespace llvm; + +void +PPC64LinuxTargetObjectFile:: +Initialize(MCContext &Ctx, const TargetMachine &TM) { + TargetLoweringObjectFileELF::Initialize(Ctx, TM); + InitializeELF(TM.Options.UseInitArray); +} + +const MCSection * PPC64LinuxTargetObjectFile:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + + const MCSection *DefaultSection = + TargetLoweringObjectFileELF::SelectSectionForGlobal(GV, Kind, Mang, TM); + + if (DefaultSection != ReadOnlySection) + return DefaultSection; + + // Here override ReadOnlySection to DataRelROSection for PPC64 SVR4 ABI + // when we have a constant that contains global relocations. This is + // necessary because of this ABI's handling of pointers to functions in + // a shared library. The address of a function is actually the address + // of a function descriptor, which resides in the .opd section. Generated + // code uses the descriptor directly rather than going via the GOT as some + // other ABIs do, which means that initialized function pointers must + // reference the descriptor. The linker must convert copy relocs of + // pointers to functions in shared libraries into dynamic relocations, + // because of an ordering problem with initialization of copy relocs and + // PLT entries. The dynamic relocation will be initialized by the dynamic + // linker, so we must use DataRelROSection instead of ReadOnlySection. + // For more information, see the description of ELIMINATE_COPY_RELOCS in + // GNU ld. + const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); + + if (GVar && GVar->isConstant() && + (GVar->getInitializer()->getRelocationInfo() == + Constant::GlobalRelocations)) + return DataRelROSection; + + return DefaultSection; +} diff --git a/lib/Target/PowerPC/PPCTargetObjectFile.h b/lib/Target/PowerPC/PPCTargetObjectFile.h new file mode 100644 index 0000000000..9203e23574 --- /dev/null +++ b/lib/Target/PowerPC/PPCTargetObjectFile.h @@ -0,0 +1,32 @@ +//===-- PPCTargetObjectFile.h - PPC Object Info -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_PPC_TARGETOBJECTFILE_H +#define LLVM_TARGET_PPC_TARGETOBJECTFILE_H + +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + + /// PPC64LinuxTargetObjectFile - This implementation is used for + /// 64-bit PowerPC Linux. + class PPC64LinuxTargetObjectFile : public TargetLoweringObjectFileELF { + + virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); + + virtual const MCSection * + SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const; + }; + +} // end namespace llvm + +#endif |