15f613dfdSUlrich Weigand //===-- SystemZMCObjectWriter.cpp - SystemZ ELF writer --------------------===// 25f613dfdSUlrich Weigand // 35f613dfdSUlrich Weigand // The LLVM Compiler Infrastructure 45f613dfdSUlrich Weigand // 55f613dfdSUlrich Weigand // This file is distributed under the University of Illinois Open Source 65f613dfdSUlrich Weigand // License. See LICENSE.TXT for details. 75f613dfdSUlrich Weigand // 85f613dfdSUlrich Weigand //===----------------------------------------------------------------------===// 95f613dfdSUlrich Weigand 105f613dfdSUlrich Weigand #include "MCTargetDesc/SystemZMCTargetDesc.h" 115f613dfdSUlrich Weigand #include "MCTargetDesc/SystemZMCFixups.h" 125f613dfdSUlrich Weigand #include "llvm/MC/MCELFObjectWriter.h" 135f613dfdSUlrich Weigand #include "llvm/MC/MCExpr.h" 145f613dfdSUlrich Weigand #include "llvm/MC/MCValue.h" 155f613dfdSUlrich Weigand 165f613dfdSUlrich Weigand using namespace llvm; 175f613dfdSUlrich Weigand 185f613dfdSUlrich Weigand namespace { 195f613dfdSUlrich Weigand class SystemZObjectWriter : public MCELFObjectTargetWriter { 205f613dfdSUlrich Weigand public: 215f613dfdSUlrich Weigand SystemZObjectWriter(uint8_t OSABI); 225f613dfdSUlrich Weigand 235f613dfdSUlrich Weigand virtual ~SystemZObjectWriter(); 245f613dfdSUlrich Weigand 255f613dfdSUlrich Weigand protected: 265f613dfdSUlrich Weigand // Override MCELFObjectTargetWriter. 27b4d67b59SRichard Sandiford unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 28c03f44caSRafael Espindola bool IsPCRel) const override; 295f613dfdSUlrich Weigand }; 30c231269fSRichard Sandiford } // end anonymous namespace 315f613dfdSUlrich Weigand 325f613dfdSUlrich Weigand SystemZObjectWriter::SystemZObjectWriter(uint8_t OSABI) 335f613dfdSUlrich Weigand : MCELFObjectTargetWriter(/*Is64Bit=*/true, OSABI, ELF::EM_S390, 345f613dfdSUlrich Weigand /*HasRelocationAddend=*/ true) {} 355f613dfdSUlrich Weigand 365f613dfdSUlrich Weigand SystemZObjectWriter::~SystemZObjectWriter() { 375f613dfdSUlrich Weigand } 385f613dfdSUlrich Weigand 395f613dfdSUlrich Weigand // Return the relocation type for an absolute value of MCFixupKind Kind. 405f613dfdSUlrich Weigand static unsigned getAbsoluteReloc(unsigned Kind) { 415f613dfdSUlrich Weigand switch (Kind) { 425f613dfdSUlrich Weigand case FK_Data_1: return ELF::R_390_8; 435f613dfdSUlrich Weigand case FK_Data_2: return ELF::R_390_16; 445f613dfdSUlrich Weigand case FK_Data_4: return ELF::R_390_32; 455f613dfdSUlrich Weigand case FK_Data_8: return ELF::R_390_64; 465f613dfdSUlrich Weigand } 475f613dfdSUlrich Weigand llvm_unreachable("Unsupported absolute address"); 485f613dfdSUlrich Weigand } 495f613dfdSUlrich Weigand 505f613dfdSUlrich Weigand // Return the relocation type for a PC-relative value of MCFixupKind Kind. 515f613dfdSUlrich Weigand static unsigned getPCRelReloc(unsigned Kind) { 525f613dfdSUlrich Weigand switch (Kind) { 535f613dfdSUlrich Weigand case FK_Data_2: return ELF::R_390_PC16; 545f613dfdSUlrich Weigand case FK_Data_4: return ELF::R_390_PC32; 555f613dfdSUlrich Weigand case FK_Data_8: return ELF::R_390_PC64; 565f613dfdSUlrich Weigand case SystemZ::FK_390_PC16DBL: return ELF::R_390_PC16DBL; 575f613dfdSUlrich Weigand case SystemZ::FK_390_PC32DBL: return ELF::R_390_PC32DBL; 585f613dfdSUlrich Weigand case SystemZ::FK_390_PLT16DBL: return ELF::R_390_PLT16DBL; 595f613dfdSUlrich Weigand case SystemZ::FK_390_PLT32DBL: return ELF::R_390_PLT32DBL; 605f613dfdSUlrich Weigand } 615f613dfdSUlrich Weigand llvm_unreachable("Unsupported PC-relative address"); 625f613dfdSUlrich Weigand } 635f613dfdSUlrich Weigand 645f613dfdSUlrich Weigand // Return the R_390_TLS_LE* relocation type for MCFixupKind Kind. 655f613dfdSUlrich Weigand static unsigned getTLSLEReloc(unsigned Kind) { 665f613dfdSUlrich Weigand switch (Kind) { 675f613dfdSUlrich Weigand case FK_Data_4: return ELF::R_390_TLS_LE32; 685f613dfdSUlrich Weigand case FK_Data_8: return ELF::R_390_TLS_LE64; 695f613dfdSUlrich Weigand } 705f613dfdSUlrich Weigand llvm_unreachable("Unsupported absolute address"); 715f613dfdSUlrich Weigand } 725f613dfdSUlrich Weigand 735f613dfdSUlrich Weigand // Return the PLT relocation counterpart of MCFixupKind Kind. 745f613dfdSUlrich Weigand static unsigned getPLTReloc(unsigned Kind) { 755f613dfdSUlrich Weigand switch (Kind) { 765f613dfdSUlrich Weigand case SystemZ::FK_390_PC16DBL: return ELF::R_390_PLT16DBL; 775f613dfdSUlrich Weigand case SystemZ::FK_390_PC32DBL: return ELF::R_390_PLT32DBL; 785f613dfdSUlrich Weigand } 795f613dfdSUlrich Weigand llvm_unreachable("Unsupported absolute address"); 805f613dfdSUlrich Weigand } 815f613dfdSUlrich Weigand 825f613dfdSUlrich Weigand unsigned SystemZObjectWriter::GetRelocType(const MCValue &Target, 83c03f44caSRafael Espindola const MCFixup &Fixup, 84c03f44caSRafael Espindola bool IsPCRel) const { 85*3d082fa5SRafael Espindola MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); 865f613dfdSUlrich Weigand unsigned Kind = Fixup.getKind(); 875f613dfdSUlrich Weigand switch (Modifier) { 885f613dfdSUlrich Weigand case MCSymbolRefExpr::VK_None: 895f613dfdSUlrich Weigand if (IsPCRel) 905f613dfdSUlrich Weigand return getPCRelReloc(Kind); 915f613dfdSUlrich Weigand return getAbsoluteReloc(Kind); 925f613dfdSUlrich Weigand 935f613dfdSUlrich Weigand case MCSymbolRefExpr::VK_NTPOFF: 945f613dfdSUlrich Weigand assert(!IsPCRel && "NTPOFF shouldn't be PC-relative"); 955f613dfdSUlrich Weigand return getTLSLEReloc(Kind); 965f613dfdSUlrich Weigand 975f613dfdSUlrich Weigand case MCSymbolRefExpr::VK_GOT: 985f613dfdSUlrich Weigand if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL) 995f613dfdSUlrich Weigand return ELF::R_390_GOTENT; 1005f613dfdSUlrich Weigand llvm_unreachable("Only PC-relative GOT accesses are supported for now"); 1015f613dfdSUlrich Weigand 1025f613dfdSUlrich Weigand case MCSymbolRefExpr::VK_PLT: 1035f613dfdSUlrich Weigand assert(IsPCRel && "@PLT shouldt be PC-relative"); 1045f613dfdSUlrich Weigand return getPLTReloc(Kind); 1055f613dfdSUlrich Weigand 1065f613dfdSUlrich Weigand default: 1075f613dfdSUlrich Weigand llvm_unreachable("Modifier not supported"); 1085f613dfdSUlrich Weigand } 1095f613dfdSUlrich Weigand } 1105f613dfdSUlrich Weigand 1115f613dfdSUlrich Weigand MCObjectWriter *llvm::createSystemZObjectWriter(raw_ostream &OS, 1125f613dfdSUlrich Weigand uint8_t OSABI) { 1135f613dfdSUlrich Weigand MCELFObjectTargetWriter *MOTW = new SystemZObjectWriter(OSABI); 1145f613dfdSUlrich Weigand return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false); 1155f613dfdSUlrich Weigand } 116