brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.4 KiB · 52fc779 Raw
222 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "InputFiles.h"10#include "Symbols.h"11#include "Target.h"12#include "lld/Common/ErrorHandler.h"13#include "llvm/BinaryFormat/ELF.h"14#include "llvm/Support/Endian.h"15 16using namespace llvm;17using namespace llvm::object;18using namespace llvm::support::endian;19using namespace llvm::ELF;20using namespace lld;21using namespace lld::elf;22 23namespace {24class AMDGPU final : public TargetInfo {25private:26  uint32_t calcEFlagsV3() const;27  uint32_t calcEFlagsV4() const;28  uint32_t calcEFlagsV6() const;29 30public:31  AMDGPU(Ctx &);32  uint32_t calcEFlags() const override;33  void relocate(uint8_t *loc, const Relocation &rel,34                uint64_t val) const override;35  RelExpr getRelExpr(RelType type, const Symbol &s,36                     const uint8_t *loc) const override;37  RelType getDynRel(RelType type) const override;38  int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;39};40} // namespace41 42AMDGPU::AMDGPU(Ctx &ctx) : TargetInfo(ctx) {43  relativeRel = R_AMDGPU_RELATIVE64;44  gotRel = R_AMDGPU_ABS64;45  symbolicRel = R_AMDGPU_ABS64;46}47 48static uint32_t getEFlags(InputFile *file) {49  return cast<ObjFile<ELF64LE>>(file)->getObj().getHeader().e_flags;50}51 52uint32_t AMDGPU::calcEFlagsV3() const {53  uint32_t ret = getEFlags(ctx.objectFiles[0]);54 55  // Verify that all input files have the same e_flags.56  for (InputFile *f : ArrayRef(ctx.objectFiles).slice(1)) {57    if (ret == getEFlags(f))58      continue;59    ErrAlways(ctx) << "incompatible e_flags: " << f;60    return 0;61  }62  return ret;63}64 65uint32_t AMDGPU::calcEFlagsV4() const {66  uint32_t retMach = getEFlags(ctx.objectFiles[0]) & EF_AMDGPU_MACH;67  uint32_t retXnack =68      getEFlags(ctx.objectFiles[0]) & EF_AMDGPU_FEATURE_XNACK_V4;69  uint32_t retSramEcc =70      getEFlags(ctx.objectFiles[0]) & EF_AMDGPU_FEATURE_SRAMECC_V4;71 72  // Verify that all input files have compatible e_flags (same mach, all73  // features in the same category are either ANY, ANY and ON, or ANY and OFF).74  for (InputFile *f : ArrayRef(ctx.objectFiles).slice(1)) {75    if (retMach != (getEFlags(f) & EF_AMDGPU_MACH)) {76      Err(ctx) << "incompatible mach: " << f;77      return 0;78    }79 80    if (retXnack == EF_AMDGPU_FEATURE_XNACK_UNSUPPORTED_V4 ||81        (retXnack != EF_AMDGPU_FEATURE_XNACK_ANY_V4 &&82            (getEFlags(f) & EF_AMDGPU_FEATURE_XNACK_V4)83                != EF_AMDGPU_FEATURE_XNACK_ANY_V4)) {84      if (retXnack != (getEFlags(f) & EF_AMDGPU_FEATURE_XNACK_V4)) {85        Err(ctx) << "incompatible xnack: " << f;86        return 0;87      }88    } else {89      if (retXnack == EF_AMDGPU_FEATURE_XNACK_ANY_V4)90        retXnack = getEFlags(f) & EF_AMDGPU_FEATURE_XNACK_V4;91    }92 93    if (retSramEcc == EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4 ||94        (retSramEcc != EF_AMDGPU_FEATURE_SRAMECC_ANY_V4 &&95            (getEFlags(f) & EF_AMDGPU_FEATURE_SRAMECC_V4) !=96                EF_AMDGPU_FEATURE_SRAMECC_ANY_V4)) {97      if (retSramEcc != (getEFlags(f) & EF_AMDGPU_FEATURE_SRAMECC_V4)) {98        Err(ctx) << "incompatible sramecc: " << f;99        return 0;100      }101    } else {102      if (retSramEcc == EF_AMDGPU_FEATURE_SRAMECC_ANY_V4)103        retSramEcc = getEFlags(f) & EF_AMDGPU_FEATURE_SRAMECC_V4;104    }105  }106 107  return retMach | retXnack | retSramEcc;108}109 110uint32_t AMDGPU::calcEFlagsV6() const {111  uint32_t flags = calcEFlagsV4();112 113  uint32_t genericVersion =114      getEFlags(ctx.objectFiles[0]) & EF_AMDGPU_GENERIC_VERSION;115 116  // Verify that all input files have compatible generic version.117  for (InputFile *f : ArrayRef(ctx.objectFiles).slice(1)) {118    if (genericVersion != (getEFlags(f) & EF_AMDGPU_GENERIC_VERSION)) {119      ErrAlways(ctx) << "incompatible generic version: " << f;120      return 0;121    }122  }123 124  flags |= genericVersion;125  return flags;126}127 128uint32_t AMDGPU::calcEFlags() const {129  if (ctx.objectFiles.empty())130    return 0;131 132  uint8_t abiVersion = cast<ObjFile<ELF64LE>>(ctx.objectFiles[0])133                           ->getObj()134                           .getHeader()135                           .e_ident[EI_ABIVERSION];136  switch (abiVersion) {137  case ELFABIVERSION_AMDGPU_HSA_V2:138  case ELFABIVERSION_AMDGPU_HSA_V3:139    return calcEFlagsV3();140  case ELFABIVERSION_AMDGPU_HSA_V4:141  case ELFABIVERSION_AMDGPU_HSA_V5:142    return calcEFlagsV4();143  case ELFABIVERSION_AMDGPU_HSA_V6:144    return calcEFlagsV6();145  default:146    Err(ctx) << "unknown abi version: " << abiVersion;147    return 0;148  }149}150 151void AMDGPU::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {152  switch (rel.type) {153  case R_AMDGPU_ABS32:154  case R_AMDGPU_GOTPCREL:155  case R_AMDGPU_GOTPCREL32_LO:156  case R_AMDGPU_REL32:157  case R_AMDGPU_REL32_LO:158    write32le(loc, val);159    break;160  case R_AMDGPU_ABS64:161  case R_AMDGPU_REL64:162    write64le(loc, val);163    break;164  case R_AMDGPU_GOTPCREL32_HI:165  case R_AMDGPU_REL32_HI:166    write32le(loc, val >> 32);167    break;168  case R_AMDGPU_REL16: {169    int64_t simm = (static_cast<int64_t>(val) - 4) / 4;170    checkInt(ctx, loc, simm, 16, rel);171    write16le(loc, simm);172    break;173  }174  default:175    llvm_unreachable("unknown relocation");176  }177}178 179RelExpr AMDGPU::getRelExpr(RelType type, const Symbol &s,180                           const uint8_t *loc) const {181  switch (type) {182  case R_AMDGPU_ABS32:183  case R_AMDGPU_ABS64:184    return R_ABS;185  case R_AMDGPU_REL32:186  case R_AMDGPU_REL32_LO:187  case R_AMDGPU_REL32_HI:188  case R_AMDGPU_REL64:189  case R_AMDGPU_REL16:190    return R_PC;191  case R_AMDGPU_GOTPCREL:192  case R_AMDGPU_GOTPCREL32_LO:193  case R_AMDGPU_GOTPCREL32_HI:194    return R_GOT_PC;195  default:196    Err(ctx) << getErrorLoc(ctx, loc) << "unknown relocation (" << type.v197             << ") against symbol " << &s;198    return R_NONE;199  }200}201 202RelType AMDGPU::getDynRel(RelType type) const {203  if (type == R_AMDGPU_ABS64)204    return type;205  return R_AMDGPU_NONE;206}207 208int64_t AMDGPU::getImplicitAddend(const uint8_t *buf, RelType type) const {209  switch (type) {210  case R_AMDGPU_NONE:211    return 0;212  case R_AMDGPU_ABS64:213  case R_AMDGPU_RELATIVE64:214    return read64(ctx, buf);215  default:216    InternalErr(ctx, buf) << "cannot read addend for relocation " << type;217    return 0;218  }219}220 221void elf::setAMDGPUTargetInfo(Ctx &ctx) { ctx.target.reset(new AMDGPU(ctx)); }222