1//===-- SystemZMCObjectWriter.cpp - SystemZ ELF writer --------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "MCTargetDesc/SystemZMCTargetDesc.h" 11#include "MCTargetDesc/SystemZMCFixups.h" 12#include "llvm/MC/MCELFObjectWriter.h" 13#include "llvm/MC/MCExpr.h" 14#include "llvm/MC/MCValue.h" 15 16using namespace llvm; 17 18namespace { 19class SystemZObjectWriter : public MCELFObjectTargetWriter { 20public: 21 SystemZObjectWriter(uint8_t OSABI); 22 23 virtual ~SystemZObjectWriter(); 24 25protected: 26 // Override MCELFObjectTargetWriter. 27 unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 28 bool IsPCRel) const override; 29}; 30} // end anonymous namespace 31 32SystemZObjectWriter::SystemZObjectWriter(uint8_t OSABI) 33 : MCELFObjectTargetWriter(/*Is64Bit=*/true, OSABI, ELF::EM_S390, 34 /*HasRelocationAddend=*/ true) {} 35 36SystemZObjectWriter::~SystemZObjectWriter() { 37} 38 39// Return the relocation type for an absolute value of MCFixupKind Kind. 40static unsigned getAbsoluteReloc(unsigned Kind) { 41 switch (Kind) { 42 case FK_Data_1: return ELF::R_390_8; 43 case FK_Data_2: return ELF::R_390_16; 44 case FK_Data_4: return ELF::R_390_32; 45 case FK_Data_8: return ELF::R_390_64; 46 } 47 llvm_unreachable("Unsupported absolute address"); 48} 49 50// Return the relocation type for a PC-relative value of MCFixupKind Kind. 51static unsigned getPCRelReloc(unsigned Kind) { 52 switch (Kind) { 53 case FK_Data_2: return ELF::R_390_PC16; 54 case FK_Data_4: return ELF::R_390_PC32; 55 case FK_Data_8: return ELF::R_390_PC64; 56 case SystemZ::FK_390_PC16DBL: return ELF::R_390_PC16DBL; 57 case SystemZ::FK_390_PC32DBL: return ELF::R_390_PC32DBL; 58 case SystemZ::FK_390_PLT16DBL: return ELF::R_390_PLT16DBL; 59 case SystemZ::FK_390_PLT32DBL: return ELF::R_390_PLT32DBL; 60 } 61 llvm_unreachable("Unsupported PC-relative address"); 62} 63 64// Return the R_390_TLS_LE* relocation type for MCFixupKind Kind. 65static unsigned getTLSLEReloc(unsigned Kind) { 66 switch (Kind) { 67 case FK_Data_4: return ELF::R_390_TLS_LE32; 68 case FK_Data_8: return ELF::R_390_TLS_LE64; 69 } 70 llvm_unreachable("Unsupported absolute address"); 71} 72 73// Return the PLT relocation counterpart of MCFixupKind Kind. 74static unsigned getPLTReloc(unsigned Kind) { 75 switch (Kind) { 76 case SystemZ::FK_390_PC16DBL: return ELF::R_390_PLT16DBL; 77 case SystemZ::FK_390_PC32DBL: return ELF::R_390_PLT32DBL; 78 } 79 llvm_unreachable("Unsupported absolute address"); 80} 81 82unsigned SystemZObjectWriter::GetRelocType(const MCValue &Target, 83 const MCFixup &Fixup, 84 bool IsPCRel) const { 85 MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); 86 unsigned Kind = Fixup.getKind(); 87 switch (Modifier) { 88 case MCSymbolRefExpr::VK_None: 89 if (IsPCRel) 90 return getPCRelReloc(Kind); 91 return getAbsoluteReloc(Kind); 92 93 case MCSymbolRefExpr::VK_NTPOFF: 94 assert(!IsPCRel && "NTPOFF shouldn't be PC-relative"); 95 return getTLSLEReloc(Kind); 96 97 case MCSymbolRefExpr::VK_GOT: 98 if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL) 99 return ELF::R_390_GOTENT; 100 llvm_unreachable("Only PC-relative GOT accesses are supported for now"); 101 102 case MCSymbolRefExpr::VK_PLT: 103 assert(IsPCRel && "@PLT shouldt be PC-relative"); 104 return getPLTReloc(Kind); 105 106 default: 107 llvm_unreachable("Modifier not supported"); 108 } 109} 110 111MCObjectWriter *llvm::createSystemZObjectWriter(raw_ostream &OS, 112 uint8_t OSABI) { 113 MCELFObjectTargetWriter *MOTW = new SystemZObjectWriter(OSABI); 114 return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false); 115} 116