xref: /openbsd-src/gnu/llvm/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===-- AMDGPUAsmBackend.cpp - AMDGPU Assembler Backend -------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick /// \file
809467b48Spatrick //===----------------------------------------------------------------------===//
909467b48Spatrick 
1009467b48Spatrick #include "MCTargetDesc/AMDGPUFixupKinds.h"
1109467b48Spatrick #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
1273471bf0Spatrick #include "Utils/AMDGPUBaseInfo.h"
13*d415bd75Srobert #include "llvm/BinaryFormat/ELF.h"
1409467b48Spatrick #include "llvm/MC/MCAsmBackend.h"
1509467b48Spatrick #include "llvm/MC/MCAssembler.h"
1609467b48Spatrick #include "llvm/MC/MCContext.h"
1709467b48Spatrick #include "llvm/MC/MCFixupKindInfo.h"
1809467b48Spatrick #include "llvm/MC/MCObjectWriter.h"
19*d415bd75Srobert #include "llvm/MC/MCSubtargetInfo.h"
20*d415bd75Srobert #include "llvm/MC/TargetRegistry.h"
21097a140dSpatrick #include "llvm/Support/EndianStream.h"
22*d415bd75Srobert #include "llvm/Support/TargetParser.h"
2309467b48Spatrick 
2409467b48Spatrick using namespace llvm;
2509467b48Spatrick using namespace llvm::AMDGPU;
2609467b48Spatrick 
2709467b48Spatrick namespace {
2809467b48Spatrick 
2909467b48Spatrick class AMDGPUAsmBackend : public MCAsmBackend {
3009467b48Spatrick public:
AMDGPUAsmBackend(const Target & T)3109467b48Spatrick   AMDGPUAsmBackend(const Target &T) : MCAsmBackend(support::little) {}
3209467b48Spatrick 
getNumFixupKinds() const3309467b48Spatrick   unsigned getNumFixupKinds() const override { return AMDGPU::NumTargetFixupKinds; };
3409467b48Spatrick 
3509467b48Spatrick   void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
3609467b48Spatrick                   const MCValue &Target, MutableArrayRef<char> Data,
3709467b48Spatrick                   uint64_t Value, bool IsResolved,
3809467b48Spatrick                   const MCSubtargetInfo *STI) const override;
3909467b48Spatrick   bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
4009467b48Spatrick                             const MCRelaxableFragment *DF,
4109467b48Spatrick                             const MCAsmLayout &Layout) const override;
4209467b48Spatrick 
43097a140dSpatrick   void relaxInstruction(MCInst &Inst,
44097a140dSpatrick                         const MCSubtargetInfo &STI) const override;
4509467b48Spatrick 
4609467b48Spatrick   bool mayNeedRelaxation(const MCInst &Inst,
4709467b48Spatrick                          const MCSubtargetInfo &STI) const override;
4809467b48Spatrick 
4909467b48Spatrick   unsigned getMinimumNopSize() const override;
50*d415bd75Srobert   bool writeNopData(raw_ostream &OS, uint64_t Count,
51*d415bd75Srobert                     const MCSubtargetInfo *STI) const override;
5209467b48Spatrick 
53*d415bd75Srobert   std::optional<MCFixupKind> getFixupKind(StringRef Name) const override;
5409467b48Spatrick   const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
55*d415bd75Srobert   bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
56*d415bd75Srobert                              const MCValue &Target) override;
5709467b48Spatrick };
5809467b48Spatrick 
5909467b48Spatrick } //End anonymous namespace
6009467b48Spatrick 
relaxInstruction(MCInst & Inst,const MCSubtargetInfo & STI) const61097a140dSpatrick void AMDGPUAsmBackend::relaxInstruction(MCInst &Inst,
62097a140dSpatrick                                         const MCSubtargetInfo &STI) const {
63097a140dSpatrick   MCInst Res;
6409467b48Spatrick   unsigned RelaxedOpcode = AMDGPU::getSOPPWithRelaxation(Inst.getOpcode());
6509467b48Spatrick   Res.setOpcode(RelaxedOpcode);
6609467b48Spatrick   Res.addOperand(Inst.getOperand(0));
67097a140dSpatrick   Inst = std::move(Res);
6809467b48Spatrick }
6909467b48Spatrick 
fixupNeedsRelaxation(const MCFixup & Fixup,uint64_t Value,const MCRelaxableFragment * DF,const MCAsmLayout & Layout) const7009467b48Spatrick bool AMDGPUAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
7109467b48Spatrick                                             uint64_t Value,
7209467b48Spatrick                                             const MCRelaxableFragment *DF,
7309467b48Spatrick                                             const MCAsmLayout &Layout) const {
7409467b48Spatrick   // if the branch target has an offset of x3f this needs to be relaxed to
7509467b48Spatrick   // add a s_nop 0 immediately after branch to effectively increment offset
7609467b48Spatrick   // for hardware workaround in gfx1010
7709467b48Spatrick   return (((int64_t(Value)/4)-1) == 0x3f);
7809467b48Spatrick }
7909467b48Spatrick 
mayNeedRelaxation(const MCInst & Inst,const MCSubtargetInfo & STI) const8009467b48Spatrick bool AMDGPUAsmBackend::mayNeedRelaxation(const MCInst &Inst,
8109467b48Spatrick                        const MCSubtargetInfo &STI) const {
8209467b48Spatrick   if (!STI.getFeatureBits()[AMDGPU::FeatureOffset3fBug])
8309467b48Spatrick     return false;
8409467b48Spatrick 
8509467b48Spatrick   if (AMDGPU::getSOPPWithRelaxation(Inst.getOpcode()) >= 0)
8609467b48Spatrick     return true;
8709467b48Spatrick 
8809467b48Spatrick   return false;
8909467b48Spatrick }
9009467b48Spatrick 
getFixupKindNumBytes(unsigned Kind)9109467b48Spatrick static unsigned getFixupKindNumBytes(unsigned Kind) {
9209467b48Spatrick   switch (Kind) {
9309467b48Spatrick   case AMDGPU::fixup_si_sopp_br:
9409467b48Spatrick     return 2;
9509467b48Spatrick   case FK_SecRel_1:
9609467b48Spatrick   case FK_Data_1:
9709467b48Spatrick     return 1;
9809467b48Spatrick   case FK_SecRel_2:
9909467b48Spatrick   case FK_Data_2:
10009467b48Spatrick     return 2;
10109467b48Spatrick   case FK_SecRel_4:
10209467b48Spatrick   case FK_Data_4:
10309467b48Spatrick   case FK_PCRel_4:
10409467b48Spatrick     return 4;
10509467b48Spatrick   case FK_SecRel_8:
10609467b48Spatrick   case FK_Data_8:
10709467b48Spatrick     return 8;
10809467b48Spatrick   default:
10909467b48Spatrick     llvm_unreachable("Unknown fixup kind!");
11009467b48Spatrick   }
11109467b48Spatrick }
11209467b48Spatrick 
adjustFixupValue(const MCFixup & Fixup,uint64_t Value,MCContext * Ctx)11309467b48Spatrick static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
11409467b48Spatrick                                  MCContext *Ctx) {
11509467b48Spatrick   int64_t SignedValue = static_cast<int64_t>(Value);
11609467b48Spatrick 
11709467b48Spatrick   switch (Fixup.getTargetKind()) {
11809467b48Spatrick   case AMDGPU::fixup_si_sopp_br: {
11909467b48Spatrick     int64_t BrImm = (SignedValue - 4) / 4;
12009467b48Spatrick 
12109467b48Spatrick     if (Ctx && !isInt<16>(BrImm))
12209467b48Spatrick       Ctx->reportError(Fixup.getLoc(), "branch size exceeds simm16");
12309467b48Spatrick 
12409467b48Spatrick     return BrImm;
12509467b48Spatrick   }
12609467b48Spatrick   case FK_Data_1:
12709467b48Spatrick   case FK_Data_2:
12809467b48Spatrick   case FK_Data_4:
12909467b48Spatrick   case FK_Data_8:
13009467b48Spatrick   case FK_PCRel_4:
13109467b48Spatrick   case FK_SecRel_4:
13209467b48Spatrick     return Value;
13309467b48Spatrick   default:
13409467b48Spatrick     llvm_unreachable("unhandled fixup kind");
13509467b48Spatrick   }
13609467b48Spatrick }
13709467b48Spatrick 
applyFixup(const MCAssembler & Asm,const MCFixup & Fixup,const MCValue & Target,MutableArrayRef<char> Data,uint64_t Value,bool IsResolved,const MCSubtargetInfo * STI) const13809467b48Spatrick void AMDGPUAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
13909467b48Spatrick                                   const MCValue &Target,
14009467b48Spatrick                                   MutableArrayRef<char> Data, uint64_t Value,
14109467b48Spatrick                                   bool IsResolved,
14209467b48Spatrick                                   const MCSubtargetInfo *STI) const {
143*d415bd75Srobert   if (Fixup.getKind() >= FirstLiteralRelocationKind)
144*d415bd75Srobert     return;
145*d415bd75Srobert 
14609467b48Spatrick   Value = adjustFixupValue(Fixup, Value, &Asm.getContext());
14709467b48Spatrick   if (!Value)
14809467b48Spatrick     return; // Doesn't change encoding.
14909467b48Spatrick 
15009467b48Spatrick   MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
15109467b48Spatrick 
15209467b48Spatrick   // Shift the value into position.
15309467b48Spatrick   Value <<= Info.TargetOffset;
15409467b48Spatrick 
15509467b48Spatrick   unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
15609467b48Spatrick   uint32_t Offset = Fixup.getOffset();
15709467b48Spatrick   assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
15809467b48Spatrick 
15909467b48Spatrick   // For each byte of the fragment that the fixup touches, mask in the bits from
16009467b48Spatrick   // the fixup value.
16109467b48Spatrick   for (unsigned i = 0; i != NumBytes; ++i)
16209467b48Spatrick     Data[Offset + i] |= static_cast<uint8_t>((Value >> (i * 8)) & 0xff);
16309467b48Spatrick }
16409467b48Spatrick 
165*d415bd75Srobert std::optional<MCFixupKind>
getFixupKind(StringRef Name) const166*d415bd75Srobert AMDGPUAsmBackend::getFixupKind(StringRef Name) const {
167*d415bd75Srobert   return StringSwitch<std::optional<MCFixupKind>>(Name)
168*d415bd75Srobert #define ELF_RELOC(Name, Value)                                                 \
169*d415bd75Srobert   .Case(#Name, MCFixupKind(FirstLiteralRelocationKind + Value))
170*d415bd75Srobert #include "llvm/BinaryFormat/ELFRelocs/AMDGPU.def"
171*d415bd75Srobert #undef ELF_RELOC
172*d415bd75Srobert       .Default(std::nullopt);
173*d415bd75Srobert }
174*d415bd75Srobert 
getFixupKindInfo(MCFixupKind Kind) const17509467b48Spatrick const MCFixupKindInfo &AMDGPUAsmBackend::getFixupKindInfo(
17609467b48Spatrick                                                        MCFixupKind Kind) const {
17709467b48Spatrick   const static MCFixupKindInfo Infos[AMDGPU::NumTargetFixupKinds] = {
17809467b48Spatrick     // name                   offset bits  flags
17909467b48Spatrick     { "fixup_si_sopp_br",     0,     16,   MCFixupKindInfo::FKF_IsPCRel },
18009467b48Spatrick   };
18109467b48Spatrick 
182*d415bd75Srobert   if (Kind >= FirstLiteralRelocationKind)
183*d415bd75Srobert     return MCAsmBackend::getFixupKindInfo(FK_NONE);
184*d415bd75Srobert 
18509467b48Spatrick   if (Kind < FirstTargetFixupKind)
18609467b48Spatrick     return MCAsmBackend::getFixupKindInfo(Kind);
18709467b48Spatrick 
18809467b48Spatrick   return Infos[Kind - FirstTargetFixupKind];
18909467b48Spatrick }
19009467b48Spatrick 
shouldForceRelocation(const MCAssembler &,const MCFixup & Fixup,const MCValue &)191*d415bd75Srobert bool AMDGPUAsmBackend::shouldForceRelocation(const MCAssembler &,
192*d415bd75Srobert                                              const MCFixup &Fixup,
193*d415bd75Srobert                                              const MCValue &) {
194*d415bd75Srobert   return Fixup.getKind() >= FirstLiteralRelocationKind;
195*d415bd75Srobert }
196*d415bd75Srobert 
getMinimumNopSize() const19709467b48Spatrick unsigned AMDGPUAsmBackend::getMinimumNopSize() const {
19809467b48Spatrick   return 4;
19909467b48Spatrick }
20009467b48Spatrick 
writeNopData(raw_ostream & OS,uint64_t Count,const MCSubtargetInfo * STI) const201*d415bd75Srobert bool AMDGPUAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
202*d415bd75Srobert                                     const MCSubtargetInfo *STI) const {
20309467b48Spatrick   // If the count is not 4-byte aligned, we must be writing data into the text
20409467b48Spatrick   // section (otherwise we have unaligned instructions, and thus have far
20509467b48Spatrick   // bigger problems), so just write zeros instead.
20609467b48Spatrick   OS.write_zeros(Count % 4);
20709467b48Spatrick 
20809467b48Spatrick   // We are properly aligned, so write NOPs as requested.
20909467b48Spatrick   Count /= 4;
21009467b48Spatrick 
21109467b48Spatrick   // FIXME: R600 support.
21209467b48Spatrick   // s_nop 0
21309467b48Spatrick   const uint32_t Encoded_S_NOP_0 = 0xbf800000;
21409467b48Spatrick 
21509467b48Spatrick   for (uint64_t I = 0; I != Count; ++I)
21609467b48Spatrick     support::endian::write<uint32_t>(OS, Encoded_S_NOP_0, Endian);
21709467b48Spatrick 
21809467b48Spatrick   return true;
21909467b48Spatrick }
22009467b48Spatrick 
22109467b48Spatrick //===----------------------------------------------------------------------===//
22209467b48Spatrick // ELFAMDGPUAsmBackend class
22309467b48Spatrick //===----------------------------------------------------------------------===//
22409467b48Spatrick 
22509467b48Spatrick namespace {
22609467b48Spatrick 
22709467b48Spatrick class ELFAMDGPUAsmBackend : public AMDGPUAsmBackend {
22809467b48Spatrick   bool Is64Bit;
22909467b48Spatrick   bool HasRelocationAddend;
23009467b48Spatrick   uint8_t OSABI = ELF::ELFOSABI_NONE;
23109467b48Spatrick   uint8_t ABIVersion = 0;
23209467b48Spatrick 
23309467b48Spatrick public:
ELFAMDGPUAsmBackend(const Target & T,const Triple & TT,uint8_t ABIVersion)23409467b48Spatrick   ELFAMDGPUAsmBackend(const Target &T, const Triple &TT, uint8_t ABIVersion) :
23509467b48Spatrick       AMDGPUAsmBackend(T), Is64Bit(TT.getArch() == Triple::amdgcn),
23609467b48Spatrick       HasRelocationAddend(TT.getOS() == Triple::AMDHSA),
23709467b48Spatrick       ABIVersion(ABIVersion) {
23809467b48Spatrick     switch (TT.getOS()) {
23909467b48Spatrick     case Triple::AMDHSA:
24009467b48Spatrick       OSABI = ELF::ELFOSABI_AMDGPU_HSA;
24109467b48Spatrick       break;
24209467b48Spatrick     case Triple::AMDPAL:
24309467b48Spatrick       OSABI = ELF::ELFOSABI_AMDGPU_PAL;
24409467b48Spatrick       break;
24509467b48Spatrick     case Triple::Mesa3D:
24609467b48Spatrick       OSABI = ELF::ELFOSABI_AMDGPU_MESA3D;
24709467b48Spatrick       break;
24809467b48Spatrick     default:
24909467b48Spatrick       break;
25009467b48Spatrick     }
25109467b48Spatrick   }
25209467b48Spatrick 
25309467b48Spatrick   std::unique_ptr<MCObjectTargetWriter>
createObjectTargetWriter() const25409467b48Spatrick   createObjectTargetWriter() const override {
25509467b48Spatrick     return createAMDGPUELFObjectWriter(Is64Bit, OSABI, HasRelocationAddend,
25609467b48Spatrick                                        ABIVersion);
25709467b48Spatrick   }
25809467b48Spatrick };
25909467b48Spatrick 
26009467b48Spatrick } // end anonymous namespace
26109467b48Spatrick 
createAMDGPUAsmBackend(const Target & T,const MCSubtargetInfo & STI,const MCRegisterInfo & MRI,const MCTargetOptions & Options)26209467b48Spatrick MCAsmBackend *llvm::createAMDGPUAsmBackend(const Target &T,
26309467b48Spatrick                                            const MCSubtargetInfo &STI,
26409467b48Spatrick                                            const MCRegisterInfo &MRI,
26509467b48Spatrick                                            const MCTargetOptions &Options) {
26609467b48Spatrick   return new ELFAMDGPUAsmBackend(T, STI.getTargetTriple(),
267*d415bd75Srobert                                  getHsaAbiVersion(&STI).value_or(0));
26809467b48Spatrick }
269