1 //===- AMDGPU.cpp ---------------------------------------------------------===//
2 //
3 // The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "InputFiles.h"
11 #include "Symbols.h"
12 #include "Target.h"
13 #include "lld/Common/ErrorHandler.h"
14 #include "llvm/Object/ELF.h"
15 #include "llvm/Support/Endian.h"
16
17 using namespace llvm;
18 using namespace llvm::object;
19 using namespace llvm::support::endian;
20 using namespace llvm::ELF;
21 using namespace lld;
22 using namespace lld::elf;
23
24 namespace {
25 class AMDGPU final : public TargetInfo {
26 public:
27 AMDGPU();
28 uint32_t calcEFlags() const override;
29 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;
30 RelExpr getRelExpr(RelType Type, const Symbol &S,
31 const uint8_t *Loc) const override;
32 };
33 } // namespace
34
AMDGPU()35 AMDGPU::AMDGPU() {
36 RelativeRel = R_AMDGPU_RELATIVE64;
37 GotRel = R_AMDGPU_ABS64;
38 GotEntrySize = 8;
39 }
40
getEFlags(InputFile * File)41 static uint32_t getEFlags(InputFile *File) {
42 return cast<ObjFile<ELF64LE>>(File)->getObj().getHeader()->e_flags;
43 }
44
calcEFlags() const45 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
relocateOne(uint8_t * Loc,RelType Type,uint64_t Val) const59 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 error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));
78 }
79 }
80
getRelExpr(RelType Type,const Symbol & S,const uint8_t * Loc) const81 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 return R_INVALID;
98 }
99 }
100
getAMDGPUTargetInfo()101 TargetInfo *elf::getAMDGPUTargetInfo() {
102 static AMDGPU Target;
103 return &Target;
104 }
105