xref: /llvm-project-15.0.7/lld/ELF/Arch/AMDGPU.cpp (revision 9a572164)
121c0a9ceSRui Ueyama //===- AMDGPU.cpp ---------------------------------------------------------===//
221c0a9ceSRui Ueyama //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
621c0a9ceSRui Ueyama //
721c0a9ceSRui Ueyama //===----------------------------------------------------------------------===//
821c0a9ceSRui Ueyama 
938fbedabSFangrui Song #include "InputFiles.h"
1021c0a9ceSRui Ueyama #include "Symbols.h"
1121c0a9ceSRui Ueyama #include "Target.h"
12b8a59c8aSBob Haarman #include "lld/Common/ErrorHandler.h"
1327bb7990SFangrui Song #include "llvm/BinaryFormat/ELF.h"
1421c0a9ceSRui Ueyama #include "llvm/Support/Endian.h"
1521c0a9ceSRui Ueyama 
1621c0a9ceSRui Ueyama using namespace llvm;
1721c0a9ceSRui Ueyama using namespace llvm::object;
1821c0a9ceSRui Ueyama using namespace llvm::support::endian;
1921c0a9ceSRui Ueyama using namespace llvm::ELF;
2007837b8fSFangrui Song using namespace lld;
2107837b8fSFangrui Song using namespace lld::elf;
2221c0a9ceSRui Ueyama 
2321c0a9ceSRui Ueyama namespace {
2421c0a9ceSRui Ueyama class AMDGPU final : public TargetInfo {
254f283031SKonstantin Zhuravlyov private:
264f283031SKonstantin Zhuravlyov   uint32_t calcEFlagsV3() const;
274f283031SKonstantin Zhuravlyov   uint32_t calcEFlagsV4() const;
284f283031SKonstantin Zhuravlyov 
2921c0a9ceSRui Ueyama public:
3021c0a9ceSRui Ueyama   AMDGPU();
31b71d1b8aSKonstantin Zhuravlyov   uint32_t calcEFlags() const override;
32deb5819dSFangrui Song   void relocate(uint8_t *loc, const Relocation &rel,
33deb5819dSFangrui Song                 uint64_t val) const override;
343837f427SRui Ueyama   RelExpr getRelExpr(RelType type, const Symbol &s,
353837f427SRui Ueyama                      const uint8_t *loc) const override;
363837f427SRui Ueyama   RelType getDynRel(RelType type) const override;
3721c0a9ceSRui Ueyama };
3821c0a9ceSRui Ueyama } // namespace
3921c0a9ceSRui Ueyama 
AMDGPU()4021c0a9ceSRui Ueyama AMDGPU::AMDGPU() {
413837f427SRui Ueyama   relativeRel = R_AMDGPU_RELATIVE64;
423837f427SRui Ueyama   gotRel = R_AMDGPU_ABS64;
433837f427SRui Ueyama   symbolicRel = R_AMDGPU_ABS64;
4421c0a9ceSRui Ueyama }
4521c0a9ceSRui Ueyama 
getEFlags(InputFile * file)463837f427SRui Ueyama static uint32_t getEFlags(InputFile *file) {
474845531fSGeorgii Rymar   return cast<ObjFile<ELF64LE>>(file)->getObj().getHeader().e_flags;
4851f604ceSRui Ueyama }
49b71d1b8aSKonstantin Zhuravlyov 
calcEFlagsV3() const504f283031SKonstantin Zhuravlyov uint32_t AMDGPU::calcEFlagsV3() const {
51*9a572164SFangrui Song   uint32_t ret = getEFlags(ctx->objectFiles[0]);
52b71d1b8aSKonstantin Zhuravlyov 
53b71d1b8aSKonstantin Zhuravlyov   // Verify that all input files have the same e_flags.
54*9a572164SFangrui Song   for (InputFile *f : makeArrayRef(ctx->objectFiles).slice(1)) {
553837f427SRui Ueyama     if (ret == getEFlags(f))
5651f604ceSRui Ueyama       continue;
573837f427SRui Ueyama     error("incompatible e_flags: " + toString(f));
58b71d1b8aSKonstantin Zhuravlyov     return 0;
59b71d1b8aSKonstantin Zhuravlyov   }
603837f427SRui Ueyama   return ret;
61b71d1b8aSKonstantin Zhuravlyov }
62b71d1b8aSKonstantin Zhuravlyov 
calcEFlagsV4() const634f283031SKonstantin Zhuravlyov uint32_t AMDGPU::calcEFlagsV4() const {
64*9a572164SFangrui Song   uint32_t retMach = getEFlags(ctx->objectFiles[0]) & EF_AMDGPU_MACH;
65*9a572164SFangrui Song   uint32_t retXnack =
66*9a572164SFangrui Song       getEFlags(ctx->objectFiles[0]) & EF_AMDGPU_FEATURE_XNACK_V4;
674f283031SKonstantin Zhuravlyov   uint32_t retSramEcc =
68*9a572164SFangrui Song       getEFlags(ctx->objectFiles[0]) & EF_AMDGPU_FEATURE_SRAMECC_V4;
694f283031SKonstantin Zhuravlyov 
704f283031SKonstantin Zhuravlyov   // Verify that all input files have compatible e_flags (same mach, all
714f283031SKonstantin Zhuravlyov   // features in the same category are either ANY, ANY and ON, or ANY and OFF).
72*9a572164SFangrui Song   for (InputFile *f : makeArrayRef(ctx->objectFiles).slice(1)) {
734f283031SKonstantin Zhuravlyov     if (retMach != (getEFlags(f) & EF_AMDGPU_MACH)) {
744f283031SKonstantin Zhuravlyov       error("incompatible mach: " + toString(f));
754f283031SKonstantin Zhuravlyov       return 0;
764f283031SKonstantin Zhuravlyov     }
774f283031SKonstantin Zhuravlyov 
784f283031SKonstantin Zhuravlyov     if (retXnack == EF_AMDGPU_FEATURE_XNACK_UNSUPPORTED_V4 ||
794f283031SKonstantin Zhuravlyov         (retXnack != EF_AMDGPU_FEATURE_XNACK_ANY_V4 &&
804f283031SKonstantin Zhuravlyov             (getEFlags(f) & EF_AMDGPU_FEATURE_XNACK_V4)
814f283031SKonstantin Zhuravlyov                 != EF_AMDGPU_FEATURE_XNACK_ANY_V4)) {
824f283031SKonstantin Zhuravlyov       if (retXnack != (getEFlags(f) & EF_AMDGPU_FEATURE_XNACK_V4)) {
834f283031SKonstantin Zhuravlyov         error("incompatible xnack: " + toString(f));
844f283031SKonstantin Zhuravlyov         return 0;
854f283031SKonstantin Zhuravlyov       }
864f283031SKonstantin Zhuravlyov     } else {
874f283031SKonstantin Zhuravlyov       if (retXnack == EF_AMDGPU_FEATURE_XNACK_ANY_V4)
884f283031SKonstantin Zhuravlyov         retXnack = getEFlags(f) & EF_AMDGPU_FEATURE_XNACK_V4;
894f283031SKonstantin Zhuravlyov     }
904f283031SKonstantin Zhuravlyov 
914f283031SKonstantin Zhuravlyov     if (retSramEcc == EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4 ||
924f283031SKonstantin Zhuravlyov         (retSramEcc != EF_AMDGPU_FEATURE_SRAMECC_ANY_V4 &&
934f283031SKonstantin Zhuravlyov             (getEFlags(f) & EF_AMDGPU_FEATURE_SRAMECC_V4) !=
944f283031SKonstantin Zhuravlyov                 EF_AMDGPU_FEATURE_SRAMECC_ANY_V4)) {
954f283031SKonstantin Zhuravlyov       if (retSramEcc != (getEFlags(f) & EF_AMDGPU_FEATURE_SRAMECC_V4)) {
964f283031SKonstantin Zhuravlyov         error("incompatible sramecc: " + toString(f));
974f283031SKonstantin Zhuravlyov         return 0;
984f283031SKonstantin Zhuravlyov       }
994f283031SKonstantin Zhuravlyov     } else {
1004f283031SKonstantin Zhuravlyov       if (retSramEcc == EF_AMDGPU_FEATURE_SRAMECC_ANY_V4)
1014f283031SKonstantin Zhuravlyov         retSramEcc = getEFlags(f) & EF_AMDGPU_FEATURE_SRAMECC_V4;
1024f283031SKonstantin Zhuravlyov     }
1034f283031SKonstantin Zhuravlyov   }
1044f283031SKonstantin Zhuravlyov 
1054f283031SKonstantin Zhuravlyov   return retMach | retXnack | retSramEcc;
1064f283031SKonstantin Zhuravlyov }
1074f283031SKonstantin Zhuravlyov 
calcEFlags() const1084f283031SKonstantin Zhuravlyov uint32_t AMDGPU::calcEFlags() const {
109*9a572164SFangrui Song   if (ctx->objectFiles.empty())
11063fe6d7eSMatt Arsenault     return 0;
1114f283031SKonstantin Zhuravlyov 
112*9a572164SFangrui Song   uint8_t abiVersion = cast<ObjFile<ELF64LE>>(ctx->objectFiles[0])
113*9a572164SFangrui Song                            ->getObj()
114*9a572164SFangrui Song                            .getHeader()
115*9a572164SFangrui Song                            .e_ident[EI_ABIVERSION];
1164f283031SKonstantin Zhuravlyov   switch (abiVersion) {
1174f283031SKonstantin Zhuravlyov   case ELFABIVERSION_AMDGPU_HSA_V2:
1184f283031SKonstantin Zhuravlyov   case ELFABIVERSION_AMDGPU_HSA_V3:
1194f283031SKonstantin Zhuravlyov     return calcEFlagsV3();
1204f283031SKonstantin Zhuravlyov   case ELFABIVERSION_AMDGPU_HSA_V4:
12171b162c4SJacob Lambert   case ELFABIVERSION_AMDGPU_HSA_V5:
1224f283031SKonstantin Zhuravlyov     return calcEFlagsV4();
1234f283031SKonstantin Zhuravlyov   default:
1244f283031SKonstantin Zhuravlyov     error("unknown abi version: " + Twine(abiVersion));
1254f283031SKonstantin Zhuravlyov     return 0;
1264f283031SKonstantin Zhuravlyov   }
1274f283031SKonstantin Zhuravlyov }
1284f283031SKonstantin Zhuravlyov 
relocate(uint8_t * loc,const Relocation & rel,uint64_t val) const129deb5819dSFangrui Song void AMDGPU::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
130deb5819dSFangrui Song   switch (rel.type) {
13121c0a9ceSRui Ueyama   case R_AMDGPU_ABS32:
13221c0a9ceSRui Ueyama   case R_AMDGPU_GOTPCREL:
13321c0a9ceSRui Ueyama   case R_AMDGPU_GOTPCREL32_LO:
13421c0a9ceSRui Ueyama   case R_AMDGPU_REL32:
13521c0a9ceSRui Ueyama   case R_AMDGPU_REL32_LO:
1363837f427SRui Ueyama     write32le(loc, val);
13721c0a9ceSRui Ueyama     break;
13821c0a9ceSRui Ueyama   case R_AMDGPU_ABS64:
139d70c3672SKonstantin Zhuravlyov   case R_AMDGPU_REL64:
1403837f427SRui Ueyama     write64le(loc, val);
14121c0a9ceSRui Ueyama     break;
14221c0a9ceSRui Ueyama   case R_AMDGPU_GOTPCREL32_HI:
14321c0a9ceSRui Ueyama   case R_AMDGPU_REL32_HI:
1443837f427SRui Ueyama     write32le(loc, val >> 32);
14521c0a9ceSRui Ueyama     break;
146fb9c5c3dSHafiz Abid Qadeer   case R_AMDGPU_REL16: {
147fb9c5c3dSHafiz Abid Qadeer     int64_t simm = (static_cast<int64_t>(val) - 4) / 4;
148fb9c5c3dSHafiz Abid Qadeer     checkInt(loc, simm, 16, rel);
149fb9c5c3dSHafiz Abid Qadeer     write16le(loc, simm);
150fb9c5c3dSHafiz Abid Qadeer     break;
151fb9c5c3dSHafiz Abid Qadeer   }
15221c0a9ceSRui Ueyama   default:
153b8b81e9bSRui Ueyama     llvm_unreachable("unknown relocation");
15421c0a9ceSRui Ueyama   }
15521c0a9ceSRui Ueyama }
15621c0a9ceSRui Ueyama 
getRelExpr(RelType type,const Symbol & s,const uint8_t * loc) const1573837f427SRui Ueyama RelExpr AMDGPU::getRelExpr(RelType type, const Symbol &s,
1583837f427SRui Ueyama                            const uint8_t *loc) const {
1593837f427SRui Ueyama   switch (type) {
16021c0a9ceSRui Ueyama   case R_AMDGPU_ABS32:
16121c0a9ceSRui Ueyama   case R_AMDGPU_ABS64:
16221c0a9ceSRui Ueyama     return R_ABS;
16321c0a9ceSRui Ueyama   case R_AMDGPU_REL32:
16421c0a9ceSRui Ueyama   case R_AMDGPU_REL32_LO:
16521c0a9ceSRui Ueyama   case R_AMDGPU_REL32_HI:
166d70c3672SKonstantin Zhuravlyov   case R_AMDGPU_REL64:
167fb9c5c3dSHafiz Abid Qadeer   case R_AMDGPU_REL16:
16821c0a9ceSRui Ueyama     return R_PC;
16921c0a9ceSRui Ueyama   case R_AMDGPU_GOTPCREL:
17021c0a9ceSRui Ueyama   case R_AMDGPU_GOTPCREL32_LO:
17121c0a9ceSRui Ueyama   case R_AMDGPU_GOTPCREL32_HI:
17221c0a9ceSRui Ueyama     return R_GOT_PC;
17321c0a9ceSRui Ueyama   default:
1743837f427SRui Ueyama     error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
1753837f427SRui Ueyama           ") against symbol " + toString(s));
176b8b81e9bSRui Ueyama     return R_NONE;
17721c0a9ceSRui Ueyama   }
17821c0a9ceSRui Ueyama }
17921c0a9ceSRui Ueyama 
getDynRel(RelType type) const1803837f427SRui Ueyama RelType AMDGPU::getDynRel(RelType type) const {
1813837f427SRui Ueyama   if (type == R_AMDGPU_ABS64)
1823837f427SRui Ueyama     return type;
183249fde85SFangrui Song   return R_AMDGPU_NONE;
184249fde85SFangrui Song }
185249fde85SFangrui Song 
getAMDGPUTargetInfo()18607837b8fSFangrui Song TargetInfo *elf::getAMDGPUTargetInfo() {
1873837f427SRui Ueyama   static AMDGPU target;
1883837f427SRui Ueyama   return &target;
189e145bc22SRui Ueyama }
190