[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / Target / AMDGPU / MCTargetDesc / AMDGPUAsmBackend.cpp
blobdd0db6c7b6550d3f25e4bbd1cf716d8673d0d2c9
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-exception
6 //
7 /// \file
8 //===----------------------------------------------------------------------===//
10 #include "MCTargetDesc/AMDGPUFixupKinds.h"
11 #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
12 #include "Utils/AMDGPUBaseInfo.h"
13 #include "llvm/MC/MCAsmBackend.h"
14 #include "llvm/MC/MCAssembler.h"
15 #include "llvm/MC/MCContext.h"
16 #include "llvm/MC/MCFixupKindInfo.h"
17 #include "llvm/MC/MCObjectWriter.h"
18 #include "llvm/Support/EndianStream.h"
19 #include "llvm/Support/TargetRegistry.h"
21 using namespace llvm;
22 using namespace llvm::AMDGPU;
24 namespace {
26 class AMDGPUAsmBackend : public MCAsmBackend {
27 public:
28 AMDGPUAsmBackend(const Target &T) : MCAsmBackend(support::little) {}
30 unsigned getNumFixupKinds() const override { return AMDGPU::NumTargetFixupKinds; };
32 void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
33 const MCValue &Target, MutableArrayRef<char> Data,
34 uint64_t Value, bool IsResolved,
35 const MCSubtargetInfo *STI) const override;
36 bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
37 const MCRelaxableFragment *DF,
38 const MCAsmLayout &Layout) const override;
40 void relaxInstruction(MCInst &Inst,
41 const MCSubtargetInfo &STI) const override;
43 bool mayNeedRelaxation(const MCInst &Inst,
44 const MCSubtargetInfo &STI) const override;
46 unsigned getMinimumNopSize() const override;
47 bool writeNopData(raw_ostream &OS, uint64_t Count) const override;
49 const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
52 } //End anonymous namespace
54 void AMDGPUAsmBackend::relaxInstruction(MCInst &Inst,
55 const MCSubtargetInfo &STI) const {
56 MCInst Res;
57 unsigned RelaxedOpcode = AMDGPU::getSOPPWithRelaxation(Inst.getOpcode());
58 Res.setOpcode(RelaxedOpcode);
59 Res.addOperand(Inst.getOperand(0));
60 Inst = std::move(Res);
63 bool AMDGPUAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
64 uint64_t Value,
65 const MCRelaxableFragment *DF,
66 const MCAsmLayout &Layout) const {
67 // if the branch target has an offset of x3f this needs to be relaxed to
68 // add a s_nop 0 immediately after branch to effectively increment offset
69 // for hardware workaround in gfx1010
70 return (((int64_t(Value)/4)-1) == 0x3f);
73 bool AMDGPUAsmBackend::mayNeedRelaxation(const MCInst &Inst,
74 const MCSubtargetInfo &STI) const {
75 if (!STI.getFeatureBits()[AMDGPU::FeatureOffset3fBug])
76 return false;
78 if (AMDGPU::getSOPPWithRelaxation(Inst.getOpcode()) >= 0)
79 return true;
81 return false;
84 static unsigned getFixupKindNumBytes(unsigned Kind) {
85 switch (Kind) {
86 case AMDGPU::fixup_si_sopp_br:
87 return 2;
88 case FK_SecRel_1:
89 case FK_Data_1:
90 return 1;
91 case FK_SecRel_2:
92 case FK_Data_2:
93 return 2;
94 case FK_SecRel_4:
95 case FK_Data_4:
96 case FK_PCRel_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!");
106 static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
107 MCContext *Ctx) {
108 int64_t SignedValue = static_cast<int64_t>(Value);
110 switch (Fixup.getTargetKind()) {
111 case AMDGPU::fixup_si_sopp_br: {
112 int64_t BrImm = (SignedValue - 4) / 4;
114 if (Ctx && !isInt<16>(BrImm))
115 Ctx->reportError(Fixup.getLoc(), "branch size exceeds simm16");
117 return BrImm;
119 case FK_Data_1:
120 case FK_Data_2:
121 case FK_Data_4:
122 case FK_Data_8:
123 case FK_PCRel_4:
124 case FK_SecRel_4:
125 return Value;
126 default:
127 llvm_unreachable("unhandled fixup kind");
131 void AMDGPUAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
132 const MCValue &Target,
133 MutableArrayRef<char> Data, uint64_t Value,
134 bool IsResolved,
135 const MCSubtargetInfo *STI) const {
136 Value = adjustFixupValue(Fixup, Value, &Asm.getContext());
137 if (!Value)
138 return; // Doesn't change encoding.
140 MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
142 // Shift the value into position.
143 Value <<= Info.TargetOffset;
145 unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
146 uint32_t Offset = Fixup.getOffset();
147 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
149 // For each byte of the fragment that the fixup touches, mask in the bits from
150 // the fixup value.
151 for (unsigned i = 0; i != NumBytes; ++i)
152 Data[Offset + i] |= static_cast<uint8_t>((Value >> (i * 8)) & 0xff);
155 const MCFixupKindInfo &AMDGPUAsmBackend::getFixupKindInfo(
156 MCFixupKind Kind) const {
157 const static MCFixupKindInfo Infos[AMDGPU::NumTargetFixupKinds] = {
158 // name offset bits flags
159 { "fixup_si_sopp_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
162 if (Kind < FirstTargetFixupKind)
163 return MCAsmBackend::getFixupKindInfo(Kind);
165 return Infos[Kind - FirstTargetFixupKind];
168 unsigned AMDGPUAsmBackend::getMinimumNopSize() const {
169 return 4;
172 bool AMDGPUAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const {
173 // If the count is not 4-byte aligned, we must be writing data into the text
174 // section (otherwise we have unaligned instructions, and thus have far
175 // bigger problems), so just write zeros instead.
176 OS.write_zeros(Count % 4);
178 // We are properly aligned, so write NOPs as requested.
179 Count /= 4;
181 // FIXME: R600 support.
182 // s_nop 0
183 const uint32_t Encoded_S_NOP_0 = 0xbf800000;
185 for (uint64_t I = 0; I != Count; ++I)
186 support::endian::write<uint32_t>(OS, Encoded_S_NOP_0, Endian);
188 return true;
191 //===----------------------------------------------------------------------===//
192 // ELFAMDGPUAsmBackend class
193 //===----------------------------------------------------------------------===//
195 namespace {
197 class ELFAMDGPUAsmBackend : public AMDGPUAsmBackend {
198 bool Is64Bit;
199 bool HasRelocationAddend;
200 uint8_t OSABI = ELF::ELFOSABI_NONE;
201 uint8_t ABIVersion = 0;
203 public:
204 ELFAMDGPUAsmBackend(const Target &T, const Triple &TT, uint8_t ABIVersion) :
205 AMDGPUAsmBackend(T), Is64Bit(TT.getArch() == Triple::amdgcn),
206 HasRelocationAddend(TT.getOS() == Triple::AMDHSA),
207 ABIVersion(ABIVersion) {
208 switch (TT.getOS()) {
209 case Triple::AMDHSA:
210 OSABI = ELF::ELFOSABI_AMDGPU_HSA;
211 break;
212 case Triple::AMDPAL:
213 OSABI = ELF::ELFOSABI_AMDGPU_PAL;
214 break;
215 case Triple::Mesa3D:
216 OSABI = ELF::ELFOSABI_AMDGPU_MESA3D;
217 break;
218 default:
219 break;
223 std::unique_ptr<MCObjectTargetWriter>
224 createObjectTargetWriter() const override {
225 return createAMDGPUELFObjectWriter(Is64Bit, OSABI, HasRelocationAddend,
226 ABIVersion);
230 } // end anonymous namespace
232 MCAsmBackend *llvm::createAMDGPUAsmBackend(const Target &T,
233 const MCSubtargetInfo &STI,
234 const MCRegisterInfo &MRI,
235 const MCTargetOptions &Options) {
236 return new ELFAMDGPUAsmBackend(T, STI.getTargetTriple(),
237 getHsaAbiVersion(&STI).getValueOr(0));