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 relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; 29 RelExpr getRelExpr(RelType Type, const Symbol &S, 30 const uint8_t *Loc) const override; 31 }; 32 } // namespace 33 34 AMDGPU::AMDGPU() { 35 RelativeRel = R_AMDGPU_RELATIVE64; 36 GotRel = R_AMDGPU_ABS64; 37 NoneRel = R_AMDGPU_NONE; 38 } 39 40 static uint32_t getEFlags(InputFile *File) { 41 return cast<ObjFile<ELF64LE>>(File)->getObj().getHeader()->e_flags; 42 } 43 44 uint32_t AMDGPU::calcEFlags() const { 45 assert(!ObjectFiles.empty()); 46 uint32_t Ret = getEFlags(ObjectFiles[0]); 47 48 // Verify that all input files have the same e_flags. 49 for (InputFile *F : makeArrayRef(ObjectFiles).slice(1)) { 50 if (Ret == getEFlags(F)) 51 continue; 52 error("incompatible e_flags: " + toString(F)); 53 return 0; 54 } 55 return Ret; 56 } 57 58 void AMDGPU::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { 59 switch (Type) { 60 case R_AMDGPU_ABS32: 61 case R_AMDGPU_GOTPCREL: 62 case R_AMDGPU_GOTPCREL32_LO: 63 case R_AMDGPU_REL32: 64 case R_AMDGPU_REL32_LO: 65 write32le(Loc, Val); 66 break; 67 case R_AMDGPU_ABS64: 68 case R_AMDGPU_REL64: 69 write64le(Loc, Val); 70 break; 71 case R_AMDGPU_GOTPCREL32_HI: 72 case R_AMDGPU_REL32_HI: 73 write32le(Loc, Val >> 32); 74 break; 75 default: 76 llvm_unreachable("unknown relocation"); 77 } 78 } 79 80 RelExpr AMDGPU::getRelExpr(RelType Type, const Symbol &S, 81 const uint8_t *Loc) const { 82 switch (Type) { 83 case R_AMDGPU_ABS32: 84 case R_AMDGPU_ABS64: 85 return R_ABS; 86 case R_AMDGPU_REL32: 87 case R_AMDGPU_REL32_LO: 88 case R_AMDGPU_REL32_HI: 89 case R_AMDGPU_REL64: 90 return R_PC; 91 case R_AMDGPU_GOTPCREL: 92 case R_AMDGPU_GOTPCREL32_LO: 93 case R_AMDGPU_GOTPCREL32_HI: 94 return R_GOT_PC; 95 default: 96 error(getErrorLocation(Loc) + "unknown relocation (" + Twine(Type) + 97 ") against symbol " + toString(S)); 98 return R_NONE; 99 } 100 } 101 102 TargetInfo *elf::getAMDGPUTargetInfo() { 103 static AMDGPU Target; 104 return &Target; 105 } 106