LLVM 23.0.0git
AMDGPUAsmBackend.cpp
Go to the documentation of this file.
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//===----------------------------------------------------------------------===//
9
16#include "llvm/MC/MCAsmInfo.h"
17#include "llvm/MC/MCAssembler.h"
18#include "llvm/MC/MCContext.h"
21#include "llvm/MC/MCValue.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 fixupNeedsRelaxationAdvanced(const MCFragment &, const MCFixup &,
38 const MCValue &, uint64_t,
39 bool) const override;
40
41 void relaxInstruction(MCInst &Inst,
42 const MCSubtargetInfo &STI) const override;
43
44 bool mayNeedRelaxation(unsigned Opcode, ArrayRef<MCOperand> Operands,
45 const MCSubtargetInfo &STI) const override;
46
47 unsigned getMinimumNopSize() const override;
48 bool writeNopData(raw_ostream &OS, uint64_t Count,
49 const MCSubtargetInfo *STI) const override;
50
51 std::optional<MCFixupKind> getFixupKind(StringRef Name) const override;
52 MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override;
53};
54
55} //End anonymous namespace
56
57void AMDGPUAsmBackend::relaxInstruction(MCInst &Inst,
58 const MCSubtargetInfo &STI) const {
59 MCInst Res;
60 unsigned RelaxedOpcode = AMDGPU::getSOPPWithRelaxation(Inst.getOpcode());
61 Res.setOpcode(RelaxedOpcode);
62 Res.addOperand(Inst.getOperand(0));
63 Inst = std::move(Res);
64}
65
66bool AMDGPUAsmBackend::fixupNeedsRelaxationAdvanced(const MCFragment &,
67 const MCFixup &Fixup,
68 const MCValue &,
69 uint64_t Value,
70 bool Resolved) const {
71 if (!Resolved)
72 return true;
73 // if the branch target has an offset of x3f this needs to be relaxed to
74 // add a s_nop 0 immediately after branch to effectively increment offset
75 // for hardware workaround in gfx1010
76 return (((int64_t(Value)/4)-1) == 0x3f);
77}
78
79bool AMDGPUAsmBackend::mayNeedRelaxation(unsigned Opcode,
80 ArrayRef<MCOperand> Operands,
81 const MCSubtargetInfo &STI) const {
82 if (!STI.hasFeature(AMDGPU::FeatureOffset3fBug))
83 return false;
84
85 if (AMDGPU::getSOPPWithRelaxation(Opcode) >= 0)
86 return true;
87
88 return false;
89}
90
91static unsigned getFixupKindNumBytes(unsigned Kind) {
92 switch (Kind) {
94 return 2;
95 case FK_SecRel_1:
96 case FK_Data_1:
97 return 1;
98 case FK_SecRel_2:
99 case FK_Data_2:
100 return 2;
101 case FK_SecRel_4:
102 case FK_Data_4:
103 return 4;
104 case FK_SecRel_8:
105 case FK_Data_8:
106 return 8;
107 default:
108 llvm_unreachable("Unknown fixup kind!");
109 }
110}
111
113 MCContext *Ctx) {
114 int64_t SignedValue = static_cast<int64_t>(Value);
115
116 switch (Fixup.getKind()) {
118 int64_t BrImm = (SignedValue - 4) / 4;
119
120 if (Ctx && !isInt<16>(BrImm))
121 Ctx->reportError(Fixup.getLoc(), "branch size exceeds simm16");
122
123 return BrImm;
124 }
125 case FK_Data_1:
126 case FK_Data_2:
127 case FK_Data_4:
128 case FK_Data_8:
129 case FK_SecRel_4:
130 return Value;
131 default:
132 llvm_unreachable("unhandled fixup kind");
133 }
134}
135
136void AMDGPUAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
137 const MCValue &Target, uint8_t *Data,
138 uint64_t Value, bool IsResolved) {
139 if (Target.getSpecifier())
140 IsResolved = false;
141 maybeAddReloc(F, Fixup, Target, Value, IsResolved);
142 if (mc::isRelocation(Fixup.getKind()))
143 return;
144
146 if (!Value)
147 return; // Doesn't change encoding.
148
149 MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
150
151 // Shift the value into position.
152 Value <<= Info.TargetOffset;
153
154 unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
155 assert(Fixup.getOffset() + NumBytes <= F.getSize() &&
156 "Invalid fixup offset!");
157
158 // For each byte of the fragment that the fixup touches, mask in the bits from
159 // the fixup value.
160 for (unsigned i = 0; i != NumBytes; ++i)
161 Data[i] |= static_cast<uint8_t>((Value >> (i * 8)) & 0xff);
162}
163
164std::optional<MCFixupKind>
165AMDGPUAsmBackend::getFixupKind(StringRef Name) const {
166 auto Type = StringSwitch<unsigned>(Name)
167#define ELF_RELOC(Name, Value) .Case(#Name, Value)
168#include "llvm/BinaryFormat/ELFRelocs/AMDGPU.def"
169#undef ELF_RELOC
170 .Case("BFD_RELOC_NONE", ELF::R_AMDGPU_NONE)
171 .Case("BFD_RELOC_32", ELF::R_AMDGPU_ABS32)
172 .Case("BFD_RELOC_64", ELF::R_AMDGPU_ABS64)
173 .Default(-1u);
174 if (Type != -1u)
175 return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);
176 return std::nullopt;
177}
178
179MCFixupKindInfo AMDGPUAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
180 const static MCFixupKindInfo Infos[AMDGPU::NumTargetFixupKinds] = {
181 // name offset bits flags
182 {"fixup_si_sopp_br", 0, 16, 0},
183 };
184
185 if (mc::isRelocation(Kind))
186 return {};
187
188 if (Kind < FirstTargetFixupKind)
190
192 "Invalid kind!");
193 return Infos[Kind - FirstTargetFixupKind];
194}
195
196unsigned AMDGPUAsmBackend::getMinimumNopSize() const {
197 return 4;
198}
199
200bool AMDGPUAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
201 const MCSubtargetInfo *STI) const {
202 // If the count is not aligned to the minimum instruction alignment, we must
203 // be writing data into the text section (otherwise we have unaligned
204 // instructions, and thus have far bigger problems), so just write zeros
205 // instead.
206 unsigned MinInstAlignment = getContext().getAsmInfo()->getMinInstAlignment();
207 OS.write_zeros(Count % MinInstAlignment);
208
209 // We are properly aligned, so write NOPs as requested.
210 Count /= MinInstAlignment;
211
212 // FIXME: R600 support.
213 // s_nop 0
214 const uint32_t Encoded_S_NOP_0 = 0xbf800000;
215
216 assert(MinInstAlignment == sizeof(Encoded_S_NOP_0));
217 for (uint64_t I = 0; I != Count; ++I)
218 support::endian::write<uint32_t>(OS, Encoded_S_NOP_0, Endian);
219
220 return true;
221}
222
223//===----------------------------------------------------------------------===//
224// ELFAMDGPUAsmBackend class
225//===----------------------------------------------------------------------===//
226
227namespace {
228
229class ELFAMDGPUAsmBackend : public AMDGPUAsmBackend {
230 bool Is64Bit;
231 bool HasRelocationAddend;
232 uint8_t OSABI = ELF::ELFOSABI_NONE;
233
234public:
235 ELFAMDGPUAsmBackend(const Target &T, const Triple &TT)
236 : AMDGPUAsmBackend(T), Is64Bit(TT.isAMDGCN()),
237 HasRelocationAddend(TT.getOS() == Triple::AMDHSA) {
238 switch (TT.getOS()) {
239 case Triple::AMDHSA:
240 OSABI = ELF::ELFOSABI_AMDGPU_HSA;
241 break;
242 case Triple::AMDPAL:
243 OSABI = ELF::ELFOSABI_AMDGPU_PAL;
244 break;
245 case Triple::Mesa3D:
246 OSABI = ELF::ELFOSABI_AMDGPU_MESA3D;
247 break;
248 default:
249 break;
250 }
251 }
252
253 std::unique_ptr<MCObjectTargetWriter>
254 createObjectTargetWriter() const override {
255 return createAMDGPUELFObjectWriter(Is64Bit, OSABI, HasRelocationAddend);
256 }
257};
258
259} // end anonymous namespace
260
262 const MCSubtargetInfo &STI,
263 const MCRegisterInfo &MRI,
264 const MCTargetOptions &Options) {
265 return new ELFAMDGPUAsmBackend(T, STI.getTargetTriple());
266}
static unsigned getFixupKindNumBytes(unsigned Kind)
The number of bytes the fixup may change.
static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target, uint64_t Value, MCContext &Ctx, const Triple &TheTriple, bool IsResolved)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Provides AMDGPU specific target descriptions.
static LVOptions Options
Definition LVOptions.cpp:25
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
PowerPC TLS Dynamic Call Fixup
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
Generic interface to target specific assembler backends.
virtual MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
Context object for machine code objects.
Definition MCContext.h:83
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition MCFixup.h:61
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
unsigned getOpcode() const
Definition MCInst.h:202
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
const MCOperand & getOperand(unsigned i) const
Definition MCInst.h:210
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
const Triple & getTargetTriple() const
Target - Wrapper for Target specific information.
LLVM Value Representation.
Definition Value.h:75
raw_ostream & write_zeros(unsigned NumZeros)
write_zeros - Insert 'NumZeros' nulls.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ fixup_si_sopp_br
16-bit PC relative fixup for SOPP branch instructions.
LLVM_READONLY int32_t getSOPPWithRelaxation(uint32_t Opcode)
@ ELFOSABI_NONE
Definition ELF.h:346
VE::Fixups getFixupKind(uint8_t S)
bool isRelocation(MCFixupKind FixupKind)
Definition MCFixup.h:130
Context & getContext() const
Definition BasicBlock.h:99
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
Definition Endian.h:96
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:165
MCAsmBackend * createAMDGPUAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
std::unique_ptr< MCObjectTargetWriter > createAMDGPUELFObjectWriter(bool Is64Bit, uint8_t OSABI, bool HasRelocationAddend)
uint16_t MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition MCFixup.h:22
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
@ FirstTargetFixupKind
Definition MCFixup.h:44
@ FK_SecRel_2
A two-byte section relative fixup.
Definition MCFixup.h:40
@ FirstLiteralRelocationKind
Definition MCFixup.h:29
@ FK_Data_8
A eight-byte fixup.
Definition MCFixup.h:37
@ FK_Data_1
A one-byte fixup.
Definition MCFixup.h:34
@ FK_Data_4
A four-byte fixup.
Definition MCFixup.h:36
@ FK_SecRel_8
A eight-byte section relative fixup.
Definition MCFixup.h:42
@ FK_SecRel_4
A four-byte section relative fixup.
Definition MCFixup.h:41
@ FK_SecRel_1
A one-byte section relative fixup.
Definition MCFixup.h:39
@ FK_Data_2
A two-byte fixup.
Definition MCFixup.h:35
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
ArrayRef(const T &OneElt) -> ArrayRef< T >
endianness
Definition bit.h:71