LLVM API Documentation
00001 //===-- SystemZMCObjectWriter.cpp - SystemZ ELF writer --------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "MCTargetDesc/SystemZMCTargetDesc.h" 00011 #include "MCTargetDesc/SystemZMCFixups.h" 00012 #include "llvm/MC/MCELFObjectWriter.h" 00013 #include "llvm/MC/MCExpr.h" 00014 #include "llvm/MC/MCValue.h" 00015 00016 using namespace llvm; 00017 00018 namespace { 00019 class SystemZObjectWriter : public MCELFObjectTargetWriter { 00020 public: 00021 SystemZObjectWriter(uint8_t OSABI); 00022 00023 virtual ~SystemZObjectWriter(); 00024 00025 protected: 00026 // Override MCELFObjectTargetWriter. 00027 unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 00028 bool IsPCRel) const override; 00029 }; 00030 } // end anonymous namespace 00031 00032 SystemZObjectWriter::SystemZObjectWriter(uint8_t OSABI) 00033 : MCELFObjectTargetWriter(/*Is64Bit=*/true, OSABI, ELF::EM_S390, 00034 /*HasRelocationAddend=*/ true) {} 00035 00036 SystemZObjectWriter::~SystemZObjectWriter() { 00037 } 00038 00039 // Return the relocation type for an absolute value of MCFixupKind Kind. 00040 static unsigned getAbsoluteReloc(unsigned Kind) { 00041 switch (Kind) { 00042 case FK_Data_1: return ELF::R_390_8; 00043 case FK_Data_2: return ELF::R_390_16; 00044 case FK_Data_4: return ELF::R_390_32; 00045 case FK_Data_8: return ELF::R_390_64; 00046 } 00047 llvm_unreachable("Unsupported absolute address"); 00048 } 00049 00050 // Return the relocation type for a PC-relative value of MCFixupKind Kind. 00051 static unsigned getPCRelReloc(unsigned Kind) { 00052 switch (Kind) { 00053 case FK_Data_2: return ELF::R_390_PC16; 00054 case FK_Data_4: return ELF::R_390_PC32; 00055 case FK_Data_8: return ELF::R_390_PC64; 00056 case SystemZ::FK_390_PC16DBL: return ELF::R_390_PC16DBL; 00057 case SystemZ::FK_390_PC32DBL: return ELF::R_390_PC32DBL; 00058 case SystemZ::FK_390_PLT16DBL: return ELF::R_390_PLT16DBL; 00059 case SystemZ::FK_390_PLT32DBL: return ELF::R_390_PLT32DBL; 00060 } 00061 llvm_unreachable("Unsupported PC-relative address"); 00062 } 00063 00064 // Return the R_390_TLS_LE* relocation type for MCFixupKind Kind. 00065 static unsigned getTLSLEReloc(unsigned Kind) { 00066 switch (Kind) { 00067 case FK_Data_4: return ELF::R_390_TLS_LE32; 00068 case FK_Data_8: return ELF::R_390_TLS_LE64; 00069 } 00070 llvm_unreachable("Unsupported absolute address"); 00071 } 00072 00073 // Return the PLT relocation counterpart of MCFixupKind Kind. 00074 static unsigned getPLTReloc(unsigned Kind) { 00075 switch (Kind) { 00076 case SystemZ::FK_390_PC16DBL: return ELF::R_390_PLT16DBL; 00077 case SystemZ::FK_390_PC32DBL: return ELF::R_390_PLT32DBL; 00078 } 00079 llvm_unreachable("Unsupported absolute address"); 00080 } 00081 00082 unsigned SystemZObjectWriter::GetRelocType(const MCValue &Target, 00083 const MCFixup &Fixup, 00084 bool IsPCRel) const { 00085 MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); 00086 unsigned Kind = Fixup.getKind(); 00087 switch (Modifier) { 00088 case MCSymbolRefExpr::VK_None: 00089 if (IsPCRel) 00090 return getPCRelReloc(Kind); 00091 return getAbsoluteReloc(Kind); 00092 00093 case MCSymbolRefExpr::VK_NTPOFF: 00094 assert(!IsPCRel && "NTPOFF shouldn't be PC-relative"); 00095 return getTLSLEReloc(Kind); 00096 00097 case MCSymbolRefExpr::VK_GOT: 00098 if (IsPCRel && Kind == SystemZ::FK_390_PC32DBL) 00099 return ELF::R_390_GOTENT; 00100 llvm_unreachable("Only PC-relative GOT accesses are supported for now"); 00101 00102 case MCSymbolRefExpr::VK_PLT: 00103 assert(IsPCRel && "@PLT shouldt be PC-relative"); 00104 return getPLTReloc(Kind); 00105 00106 default: 00107 llvm_unreachable("Modifier not supported"); 00108 } 00109 } 00110 00111 MCObjectWriter *llvm::createSystemZObjectWriter(raw_ostream &OS, 00112 uint8_t OSABI) { 00113 MCELFObjectTargetWriter *MOTW = new SystemZObjectWriter(OSABI); 00114 return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false); 00115 }