brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.2 KiB · 4e4660c Raw
261 lines · cpp
1//===-- AMDGPUAsmBackend.cpp - AMDGPU Assembler Backend -------------------===//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/// \file8//===----------------------------------------------------------------------===//9 10#include "MCTargetDesc/AMDGPUFixupKinds.h"11#include "MCTargetDesc/AMDGPUMCTargetDesc.h"12#include "Utils/AMDGPUBaseInfo.h"13#include "llvm/ADT/StringSwitch.h"14#include "llvm/BinaryFormat/ELF.h"15#include "llvm/MC/MCAsmBackend.h"16#include "llvm/MC/MCAsmInfo.h"17#include "llvm/MC/MCAssembler.h"18#include "llvm/MC/MCContext.h"19#include "llvm/MC/MCObjectWriter.h"20#include "llvm/MC/MCSubtargetInfo.h"21#include "llvm/MC/MCValue.h"22#include "llvm/MC/TargetRegistry.h"23#include "llvm/Support/EndianStream.h"24#include "llvm/TargetParser/TargetParser.h"25 26using namespace llvm;27using namespace llvm::AMDGPU;28 29namespace {30 31class AMDGPUAsmBackend : public MCAsmBackend {32public:33  AMDGPUAsmBackend(const Target &T) : MCAsmBackend(llvm::endianness::little) {}34 35  void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,36                  uint8_t *Data, uint64_t Value, bool IsResolved) override;37  bool fixupNeedsRelaxation(const MCFixup &Fixup,38                            uint64_t Value) const override;39 40  void relaxInstruction(MCInst &Inst,41                        const MCSubtargetInfo &STI) const override;42 43  bool mayNeedRelaxation(unsigned Opcode, ArrayRef<MCOperand> Operands,44                         const MCSubtargetInfo &STI) const override;45 46  unsigned getMinimumNopSize() const override;47  bool writeNopData(raw_ostream &OS, uint64_t Count,48                    const MCSubtargetInfo *STI) const override;49 50  std::optional<MCFixupKind> getFixupKind(StringRef Name) const override;51  MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override;52};53 54} //End anonymous namespace55 56void AMDGPUAsmBackend::relaxInstruction(MCInst &Inst,57                                        const MCSubtargetInfo &STI) const {58  MCInst Res;59  unsigned RelaxedOpcode = AMDGPU::getSOPPWithRelaxation(Inst.getOpcode());60  Res.setOpcode(RelaxedOpcode);61  Res.addOperand(Inst.getOperand(0));62  Inst = std::move(Res);63}64 65bool AMDGPUAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,66                                            uint64_t Value) const {67  // if the branch target has an offset of x3f this needs to be relaxed to68  // add a s_nop 0 immediately after branch to effectively increment offset69  // for hardware workaround in gfx101070  return (((int64_t(Value)/4)-1) == 0x3f);71}72 73bool AMDGPUAsmBackend::mayNeedRelaxation(unsigned Opcode,74                                         ArrayRef<MCOperand> Operands,75                                         const MCSubtargetInfo &STI) const {76  if (!STI.hasFeature(AMDGPU::FeatureOffset3fBug))77    return false;78 79  if (AMDGPU::getSOPPWithRelaxation(Opcode) >= 0)80    return true;81 82  return false;83}84 85static unsigned getFixupKindNumBytes(unsigned Kind) {86  switch (Kind) {87  case AMDGPU::fixup_si_sopp_br:88    return 2;89  case FK_SecRel_1:90  case FK_Data_1:91    return 1;92  case FK_SecRel_2:93  case FK_Data_2:94    return 2;95  case FK_SecRel_4:96  case FK_Data_4:97    return 4;98  case FK_SecRel_8:99  case FK_Data_8:100    return 8;101  default:102    llvm_unreachable("Unknown fixup kind!");103  }104}105 106static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,107                                 MCContext *Ctx) {108  int64_t SignedValue = static_cast<int64_t>(Value);109 110  switch (Fixup.getKind()) {111  case AMDGPU::fixup_si_sopp_br: {112    int64_t BrImm = (SignedValue - 4) / 4;113 114    if (Ctx && !isInt<16>(BrImm))115      Ctx->reportError(Fixup.getLoc(), "branch size exceeds simm16");116 117    return BrImm;118  }119  case FK_Data_1:120  case FK_Data_2:121  case FK_Data_4:122  case FK_Data_8:123  case FK_SecRel_4:124    return Value;125  default:126    llvm_unreachable("unhandled fixup kind");127  }128}129 130void AMDGPUAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,131                                  const MCValue &Target, uint8_t *Data,132                                  uint64_t Value, bool IsResolved) {133  if (Target.getSpecifier())134    IsResolved = false;135  maybeAddReloc(F, Fixup, Target, Value, IsResolved);136  if (mc::isRelocation(Fixup.getKind()))137    return;138 139  Value = adjustFixupValue(Fixup, Value, &getContext());140  if (!Value)141    return; // Doesn't change encoding.142 143  MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());144 145  // Shift the value into position.146  Value <<= Info.TargetOffset;147 148  unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());149  assert(Fixup.getOffset() + NumBytes <= F.getSize() &&150         "Invalid fixup offset!");151 152  // For each byte of the fragment that the fixup touches, mask in the bits from153  // the fixup value.154  for (unsigned i = 0; i != NumBytes; ++i)155    Data[i] |= static_cast<uint8_t>((Value >> (i * 8)) & 0xff);156}157 158std::optional<MCFixupKind>159AMDGPUAsmBackend::getFixupKind(StringRef Name) const {160  auto Type = StringSwitch<unsigned>(Name)161#define ELF_RELOC(Name, Value) .Case(#Name, Value)162#include "llvm/BinaryFormat/ELFRelocs/AMDGPU.def"163#undef ELF_RELOC164                  .Case("BFD_RELOC_NONE", ELF::R_AMDGPU_NONE)165                  .Case("BFD_RELOC_32", ELF::R_AMDGPU_ABS32)166                  .Case("BFD_RELOC_64", ELF::R_AMDGPU_ABS64)167                  .Default(-1u);168  if (Type != -1u)169    return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);170  return std::nullopt;171}172 173MCFixupKindInfo AMDGPUAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {174  const static MCFixupKindInfo Infos[AMDGPU::NumTargetFixupKinds] = {175      // name                   offset bits  flags176      {"fixup_si_sopp_br", 0, 16, 0},177  };178 179  if (mc::isRelocation(Kind))180    return {};181 182  if (Kind < FirstTargetFixupKind)183    return MCAsmBackend::getFixupKindInfo(Kind);184 185  assert(unsigned(Kind - FirstTargetFixupKind) < AMDGPU::NumTargetFixupKinds &&186         "Invalid kind!");187  return Infos[Kind - FirstTargetFixupKind];188}189 190unsigned AMDGPUAsmBackend::getMinimumNopSize() const {191  return 4;192}193 194bool AMDGPUAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,195                                    const MCSubtargetInfo *STI) const {196  // If the count is not aligned to the minimum instruction alignment, we must197  // be writing data into the text section (otherwise we have unaligned198  // instructions, and thus have far bigger problems), so just write zeros199  // instead.200  unsigned MinInstAlignment = getContext().getAsmInfo()->getMinInstAlignment();201  OS.write_zeros(Count % MinInstAlignment);202 203  // We are properly aligned, so write NOPs as requested.204  Count /= MinInstAlignment;205 206  // FIXME: R600 support.207  // s_nop 0208  const uint32_t Encoded_S_NOP_0 = 0xbf800000;209 210  assert(MinInstAlignment == sizeof(Encoded_S_NOP_0));211  for (uint64_t I = 0; I != Count; ++I)212    support::endian::write<uint32_t>(OS, Encoded_S_NOP_0, Endian);213 214  return true;215}216 217//===----------------------------------------------------------------------===//218// ELFAMDGPUAsmBackend class219//===----------------------------------------------------------------------===//220 221namespace {222 223class ELFAMDGPUAsmBackend : public AMDGPUAsmBackend {224  bool Is64Bit;225  bool HasRelocationAddend;226  uint8_t OSABI = ELF::ELFOSABI_NONE;227 228public:229  ELFAMDGPUAsmBackend(const Target &T, const Triple &TT)230      : AMDGPUAsmBackend(T), Is64Bit(TT.isAMDGCN()),231        HasRelocationAddend(TT.getOS() == Triple::AMDHSA) {232    switch (TT.getOS()) {233    case Triple::AMDHSA:234      OSABI = ELF::ELFOSABI_AMDGPU_HSA;235      break;236    case Triple::AMDPAL:237      OSABI = ELF::ELFOSABI_AMDGPU_PAL;238      break;239    case Triple::Mesa3D:240      OSABI = ELF::ELFOSABI_AMDGPU_MESA3D;241      break;242    default:243      break;244    }245  }246 247  std::unique_ptr<MCObjectTargetWriter>248  createObjectTargetWriter() const override {249    return createAMDGPUELFObjectWriter(Is64Bit, OSABI, HasRelocationAddend);250  }251};252 253} // end anonymous namespace254 255MCAsmBackend *llvm::createAMDGPUAsmBackend(const Target &T,256                                           const MCSubtargetInfo &STI,257                                           const MCRegisterInfo &MRI,258                                           const MCTargetOptions &Options) {259  return new ELFAMDGPUAsmBackend(T, STI.getTargetTriple());260}261