Path: blob/main/contrib/llvm-project/lld/ELF/Arch/AMDGPU.cpp
34878 views
//===- AMDGPU.cpp ---------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "InputFiles.h"9#include "Symbols.h"10#include "Target.h"11#include "lld/Common/ErrorHandler.h"12#include "llvm/BinaryFormat/ELF.h"13#include "llvm/Support/Endian.h"1415using namespace llvm;16using namespace llvm::object;17using namespace llvm::support::endian;18using namespace llvm::ELF;19using namespace lld;20using namespace lld::elf;2122namespace {23class AMDGPU final : public TargetInfo {24private:25uint32_t calcEFlagsV3() const;26uint32_t calcEFlagsV4() const;27uint32_t calcEFlagsV6() const;2829public:30AMDGPU();31uint32_t calcEFlags() const override;32void relocate(uint8_t *loc, const Relocation &rel,33uint64_t val) const override;34RelExpr getRelExpr(RelType type, const Symbol &s,35const uint8_t *loc) const override;36RelType getDynRel(RelType type) const override;37int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;38};39} // namespace4041AMDGPU::AMDGPU() {42relativeRel = R_AMDGPU_RELATIVE64;43gotRel = R_AMDGPU_ABS64;44symbolicRel = R_AMDGPU_ABS64;45}4647static uint32_t getEFlags(InputFile *file) {48return cast<ObjFile<ELF64LE>>(file)->getObj().getHeader().e_flags;49}5051uint32_t AMDGPU::calcEFlagsV3() const {52uint32_t ret = getEFlags(ctx.objectFiles[0]);5354// Verify that all input files have the same e_flags.55for (InputFile *f : ArrayRef(ctx.objectFiles).slice(1)) {56if (ret == getEFlags(f))57continue;58error("incompatible e_flags: " + toString(f));59return 0;60}61return ret;62}6364uint32_t AMDGPU::calcEFlagsV4() const {65uint32_t retMach = getEFlags(ctx.objectFiles[0]) & EF_AMDGPU_MACH;66uint32_t retXnack =67getEFlags(ctx.objectFiles[0]) & EF_AMDGPU_FEATURE_XNACK_V4;68uint32_t retSramEcc =69getEFlags(ctx.objectFiles[0]) & EF_AMDGPU_FEATURE_SRAMECC_V4;7071// Verify that all input files have compatible e_flags (same mach, all72// features in the same category are either ANY, ANY and ON, or ANY and OFF).73for (InputFile *f : ArrayRef(ctx.objectFiles).slice(1)) {74if (retMach != (getEFlags(f) & EF_AMDGPU_MACH)) {75error("incompatible mach: " + toString(f));76return 0;77}7879if (retXnack == EF_AMDGPU_FEATURE_XNACK_UNSUPPORTED_V4 ||80(retXnack != EF_AMDGPU_FEATURE_XNACK_ANY_V4 &&81(getEFlags(f) & EF_AMDGPU_FEATURE_XNACK_V4)82!= EF_AMDGPU_FEATURE_XNACK_ANY_V4)) {83if (retXnack != (getEFlags(f) & EF_AMDGPU_FEATURE_XNACK_V4)) {84error("incompatible xnack: " + toString(f));85return 0;86}87} else {88if (retXnack == EF_AMDGPU_FEATURE_XNACK_ANY_V4)89retXnack = getEFlags(f) & EF_AMDGPU_FEATURE_XNACK_V4;90}9192if (retSramEcc == EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4 ||93(retSramEcc != EF_AMDGPU_FEATURE_SRAMECC_ANY_V4 &&94(getEFlags(f) & EF_AMDGPU_FEATURE_SRAMECC_V4) !=95EF_AMDGPU_FEATURE_SRAMECC_ANY_V4)) {96if (retSramEcc != (getEFlags(f) & EF_AMDGPU_FEATURE_SRAMECC_V4)) {97error("incompatible sramecc: " + toString(f));98return 0;99}100} else {101if (retSramEcc == EF_AMDGPU_FEATURE_SRAMECC_ANY_V4)102retSramEcc = getEFlags(f) & EF_AMDGPU_FEATURE_SRAMECC_V4;103}104}105106return retMach | retXnack | retSramEcc;107}108109uint32_t AMDGPU::calcEFlagsV6() const {110uint32_t flags = calcEFlagsV4();111112uint32_t genericVersion =113getEFlags(ctx.objectFiles[0]) & EF_AMDGPU_GENERIC_VERSION;114115// Verify that all input files have compatible generic version.116for (InputFile *f : ArrayRef(ctx.objectFiles).slice(1)) {117if (genericVersion != (getEFlags(f) & EF_AMDGPU_GENERIC_VERSION)) {118error("incompatible generic version: " + toString(f));119return 0;120}121}122123flags |= genericVersion;124return flags;125}126127uint32_t AMDGPU::calcEFlags() const {128if (ctx.objectFiles.empty())129return 0;130131uint8_t abiVersion = cast<ObjFile<ELF64LE>>(ctx.objectFiles[0])132->getObj()133.getHeader()134.e_ident[EI_ABIVERSION];135switch (abiVersion) {136case ELFABIVERSION_AMDGPU_HSA_V2:137case ELFABIVERSION_AMDGPU_HSA_V3:138return calcEFlagsV3();139case ELFABIVERSION_AMDGPU_HSA_V4:140case ELFABIVERSION_AMDGPU_HSA_V5:141return calcEFlagsV4();142case ELFABIVERSION_AMDGPU_HSA_V6:143return calcEFlagsV6();144default:145error("unknown abi version: " + Twine(abiVersion));146return 0;147}148}149150void AMDGPU::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {151switch (rel.type) {152case R_AMDGPU_ABS32:153case R_AMDGPU_GOTPCREL:154case R_AMDGPU_GOTPCREL32_LO:155case R_AMDGPU_REL32:156case R_AMDGPU_REL32_LO:157write32le(loc, val);158break;159case R_AMDGPU_ABS64:160case R_AMDGPU_REL64:161write64le(loc, val);162break;163case R_AMDGPU_GOTPCREL32_HI:164case R_AMDGPU_REL32_HI:165write32le(loc, val >> 32);166break;167case R_AMDGPU_REL16: {168int64_t simm = (static_cast<int64_t>(val) - 4) / 4;169checkInt(loc, simm, 16, rel);170write16le(loc, simm);171break;172}173default:174llvm_unreachable("unknown relocation");175}176}177178RelExpr AMDGPU::getRelExpr(RelType type, const Symbol &s,179const uint8_t *loc) const {180switch (type) {181case R_AMDGPU_ABS32:182case R_AMDGPU_ABS64:183return R_ABS;184case R_AMDGPU_REL32:185case R_AMDGPU_REL32_LO:186case R_AMDGPU_REL32_HI:187case R_AMDGPU_REL64:188case R_AMDGPU_REL16:189return R_PC;190case R_AMDGPU_GOTPCREL:191case R_AMDGPU_GOTPCREL32_LO:192case R_AMDGPU_GOTPCREL32_HI:193return R_GOT_PC;194default:195error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +196") against symbol " + toString(s));197return R_NONE;198}199}200201RelType AMDGPU::getDynRel(RelType type) const {202if (type == R_AMDGPU_ABS64)203return type;204return R_AMDGPU_NONE;205}206207int64_t AMDGPU::getImplicitAddend(const uint8_t *buf, RelType type) const {208switch (type) {209case R_AMDGPU_NONE:210return 0;211case R_AMDGPU_ABS64:212case R_AMDGPU_RELATIVE64:213return read64(buf);214default:215internalLinkerError(getErrorLocation(buf),216"cannot read addend for relocation " + toString(type));217return 0;218}219}220221TargetInfo *elf::getAMDGPUTargetInfo() {222static AMDGPU target;223return ⌖224}225226227