1 //===-- VEELFObjectWriter.cpp - VE ELF Writer -----------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "MCTargetDesc/VEMCAsmInfo.h" 10 #include "VEFixupKinds.h" 11 #include "VEMCAsmInfo.h" 12 #include "VEMCTargetDesc.h" 13 #include "llvm/MC/MCContext.h" 14 #include "llvm/MC/MCELFObjectWriter.h" 15 #include "llvm/MC/MCExpr.h" 16 #include "llvm/MC/MCObjectWriter.h" 17 #include "llvm/MC/MCValue.h" 18 #include "llvm/Support/ErrorHandling.h" 19 20 using namespace llvm; 21 22 namespace { 23 class VEELFObjectWriter : public MCELFObjectTargetWriter { 24 public: 25 VEELFObjectWriter(uint8_t OSABI) 26 : MCELFObjectTargetWriter(/* Is64Bit */ true, OSABI, ELF::EM_VE, 27 /* HasRelocationAddend */ true) {} 28 29 ~VEELFObjectWriter() override = default; 30 31 protected: 32 unsigned getRelocType(const MCFixup &, const MCValue &, 33 bool IsPCRel) const override; 34 35 bool needsRelocateWithSymbol(const MCValue &, unsigned Type) const override; 36 }; 37 } // namespace 38 39 unsigned VEELFObjectWriter::getRelocType(const MCFixup &Fixup, 40 const MCValue &Target, 41 bool IsPCRel) const { 42 switch (Target.getSpecifier()) { 43 case VE::S_TLS_GD_HI32: 44 case VE::S_TLS_GD_LO32: 45 case VE::S_TPOFF_HI32: 46 case VE::S_TPOFF_LO32: 47 if (auto *SA = Target.getAddSym()) 48 cast<MCSymbolELF>(SA)->setType(ELF::STT_TLS); 49 break; 50 default: 51 break; 52 } 53 if (auto *SExpr = dyn_cast<MCSpecifierExpr>(Fixup.getValue())) { 54 if (SExpr->getSpecifier() == VE::S_PC_LO32) 55 return ELF::R_VE_PC_LO32; 56 } 57 58 if (IsPCRel) { 59 switch (Fixup.getKind()) { 60 default: 61 reportError(Fixup.getLoc(), "Unsupported pc-relative fixup kind"); 62 return ELF::R_VE_NONE; 63 case FK_Data_1: 64 reportError(Fixup.getLoc(), 65 "1-byte pc-relative data relocation is not supported"); 66 return ELF::R_VE_NONE; 67 case FK_Data_2: 68 reportError(Fixup.getLoc(), 69 "2-byte pc-relative data relocation is not supported"); 70 return ELF::R_VE_NONE; 71 case FK_Data_4: 72 return ELF::R_VE_SREL32; 73 case FK_Data_8: 74 reportError(Fixup.getLoc(), 75 "8-byte pc-relative data relocation is not supported"); 76 return ELF::R_VE_NONE; 77 case VE::fixup_ve_reflong: 78 case VE::fixup_ve_srel32: 79 return ELF::R_VE_SREL32; 80 case VE::fixup_ve_pc_hi32: 81 return ELF::R_VE_PC_HI32; 82 case VE::fixup_ve_pc_lo32: 83 return ELF::R_VE_PC_LO32; 84 } 85 } 86 87 switch (Fixup.getKind()) { 88 default: 89 reportError(Fixup.getLoc(), "Unknown ELF relocation type"); 90 return ELF::R_VE_NONE; 91 case FK_Data_1: 92 reportError(Fixup.getLoc(), "1-byte data relocation is not supported"); 93 return ELF::R_VE_NONE; 94 case FK_Data_2: 95 reportError(Fixup.getLoc(), "2-byte data relocation is not supported"); 96 return ELF::R_VE_NONE; 97 case FK_Data_4: 98 return ELF::R_VE_REFLONG; 99 case FK_Data_8: 100 return ELF::R_VE_REFQUAD; 101 case VE::fixup_ve_reflong: 102 return ELF::R_VE_REFLONG; 103 case VE::fixup_ve_srel32: 104 reportError(Fixup.getLoc(), 105 "A non pc-relative srel32 relocation is not supported"); 106 return ELF::R_VE_NONE; 107 case VE::fixup_ve_hi32: 108 return ELF::R_VE_HI32; 109 case VE::fixup_ve_lo32: 110 return ELF::R_VE_LO32; 111 case VE::fixup_ve_pc_hi32: 112 reportError(Fixup.getLoc(), 113 "A non pc-relative pc_hi32 relocation is not supported"); 114 return ELF::R_VE_NONE; 115 case VE::fixup_ve_pc_lo32: 116 reportError(Fixup.getLoc(), 117 "A non pc-relative pc_lo32 relocation is not supported"); 118 return ELF::R_VE_NONE; 119 case VE::fixup_ve_got_hi32: 120 return ELF::R_VE_GOT_HI32; 121 case VE::fixup_ve_got_lo32: 122 return ELF::R_VE_GOT_LO32; 123 case VE::fixup_ve_gotoff_hi32: 124 return ELF::R_VE_GOTOFF_HI32; 125 case VE::fixup_ve_gotoff_lo32: 126 return ELF::R_VE_GOTOFF_LO32; 127 case VE::fixup_ve_plt_hi32: 128 return ELF::R_VE_PLT_HI32; 129 case VE::fixup_ve_plt_lo32: 130 return ELF::R_VE_PLT_LO32; 131 case VE::fixup_ve_tls_gd_hi32: 132 return ELF::R_VE_TLS_GD_HI32; 133 case VE::fixup_ve_tls_gd_lo32: 134 return ELF::R_VE_TLS_GD_LO32; 135 case VE::fixup_ve_tpoff_hi32: 136 return ELF::R_VE_TPOFF_HI32; 137 case VE::fixup_ve_tpoff_lo32: 138 return ELF::R_VE_TPOFF_LO32; 139 } 140 141 return ELF::R_VE_NONE; 142 } 143 144 bool VEELFObjectWriter::needsRelocateWithSymbol(const MCValue &, 145 unsigned Type) const { 146 switch (Type) { 147 default: 148 return false; 149 150 // All relocations that use a GOT need a symbol, not an offset, as 151 // the offset of the symbol within the section is irrelevant to 152 // where the GOT entry is. Don't need to list all the TLS entries, 153 // as they're all marked as requiring a symbol anyways. 154 case ELF::R_VE_GOT_HI32: 155 case ELF::R_VE_GOT_LO32: 156 case ELF::R_VE_GOTOFF_HI32: 157 case ELF::R_VE_GOTOFF_LO32: 158 case ELF::R_VE_TLS_GD_HI32: 159 case ELF::R_VE_TLS_GD_LO32: 160 return true; 161 } 162 } 163 164 std::unique_ptr<MCObjectTargetWriter> 165 llvm::createVEELFObjectWriter(uint8_t OSABI) { 166 return std::make_unique<VEELFObjectWriter>(OSABI); 167 } 168