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