1 //===- AMDGPU.cpp ---------------------------------------------------------===// 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 "InputFiles.h" 10 #include "Symbols.h" 11 #include "Target.h" 12 #include "lld/Common/ErrorHandler.h" 13 #include "llvm/Object/ELF.h" 14 #include "llvm/Support/Endian.h" 15 16 using namespace llvm; 17 using namespace llvm::object; 18 using namespace llvm::support::endian; 19 using namespace llvm::ELF; 20 using namespace lld; 21 using namespace lld::elf; 22 23 namespace { 24 class AMDGPU final : public TargetInfo { 25 public: 26 AMDGPU(); 27 uint32_t calcEFlags() const override; 28 void relocate(uint8_t *loc, const Relocation &rel, 29 uint64_t val) const override; 30 RelExpr getRelExpr(RelType type, const Symbol &s, 31 const uint8_t *loc) const override; 32 RelType getDynRel(RelType type) const override; 33 }; 34 } // namespace 35 36 AMDGPU::AMDGPU() { 37 relativeRel = R_AMDGPU_RELATIVE64; 38 gotRel = R_AMDGPU_ABS64; 39 noneRel = R_AMDGPU_NONE; 40 symbolicRel = R_AMDGPU_ABS64; 41 } 42 43 static uint32_t getEFlags(InputFile *file) { 44 return cast<ObjFile<ELF64LE>>(file)->getObj().getHeader()->e_flags; 45 } 46 47 uint32_t AMDGPU::calcEFlags() const { 48 assert(!objectFiles.empty()); 49 uint32_t ret = getEFlags(objectFiles[0]); 50 51 // Verify that all input files have the same e_flags. 52 for (InputFile *f : makeArrayRef(objectFiles).slice(1)) { 53 if (ret == getEFlags(f)) 54 continue; 55 error("incompatible e_flags: " + toString(f)); 56 return 0; 57 } 58 return ret; 59 } 60 61 void AMDGPU::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { 62 switch (rel.type) { 63 case R_AMDGPU_ABS32: 64 case R_AMDGPU_GOTPCREL: 65 case R_AMDGPU_GOTPCREL32_LO: 66 case R_AMDGPU_REL32: 67 case R_AMDGPU_REL32_LO: 68 write32le(loc, val); 69 break; 70 case R_AMDGPU_ABS64: 71 case R_AMDGPU_REL64: 72 write64le(loc, val); 73 break; 74 case R_AMDGPU_GOTPCREL32_HI: 75 case R_AMDGPU_REL32_HI: 76 write32le(loc, val >> 32); 77 break; 78 default: 79 llvm_unreachable("unknown relocation"); 80 } 81 } 82 83 RelExpr AMDGPU::getRelExpr(RelType type, const Symbol &s, 84 const uint8_t *loc) const { 85 switch (type) { 86 case R_AMDGPU_ABS32: 87 case R_AMDGPU_ABS64: 88 return R_ABS; 89 case R_AMDGPU_REL32: 90 case R_AMDGPU_REL32_LO: 91 case R_AMDGPU_REL32_HI: 92 case R_AMDGPU_REL64: 93 return R_PC; 94 case R_AMDGPU_GOTPCREL: 95 case R_AMDGPU_GOTPCREL32_LO: 96 case R_AMDGPU_GOTPCREL32_HI: 97 return R_GOT_PC; 98 default: 99 error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + 100 ") against symbol " + toString(s)); 101 return R_NONE; 102 } 103 } 104 105 RelType AMDGPU::getDynRel(RelType type) const { 106 if (type == R_AMDGPU_ABS64) 107 return type; 108 return R_AMDGPU_NONE; 109 } 110 111 TargetInfo *elf::getAMDGPUTargetInfo() { 112 static AMDGPU target; 113 return ⌖ 114 } 115