LLVM 22.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;
38 uint64_t Value) const override;
39
40 void relaxInstruction(MCInst &Inst,
41 const MCSubtargetInfo &STI) const override;
42
44 const MCSubtargetInfo &STI) const override;
45
46 unsigned getMinimumNopSize() const override;
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 namespace
55
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 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);
71}
72
73bool AMDGPUAsmBackend::mayNeedRelaxation(unsigned Opcode,
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) {
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
107 MCContext *Ctx) {
108 int64_t SignedValue = static_cast<int64_t>(Value);
109
110 switch (Fixup.getKind()) {
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 from
153 // 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 {
161#define ELF_RELOC(Name, Value) .Case(#Name, Value)
162#include "llvm/BinaryFormat/ELFRelocs/AMDGPU.def"
163#undef ELF_RELOC
164 .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 flags
176 {"fixup_si_sopp_br", 0, 16, 0},
177 };
178
179 if (mc::isRelocation(Kind))
180 return {};
181
182 if (Kind < FirstTargetFixupKind)
184
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 must
197 // be writing data into the text section (otherwise we have unaligned
198 // instructions, and thus have far bigger problems), so just write zeros
199 // 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 0
208 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 class
219//===----------------------------------------------------------------------===//
220
221namespace {
222
223class ELFAMDGPUAsmBackend : public AMDGPUAsmBackend {
224 bool Is64Bit;
225 bool HasRelocationAddend;
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:
235 break;
236 case Triple::AMDPAL:
238 break;
239 case Triple::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 namespace
254
256 const MCSubtargetInfo &STI,
257 const MCRegisterInfo &MRI,
258 const MCTargetOptions &Options) {
259 return new ELFAMDGPUAsmBackend(T, STI.getTargetTriple());
260}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, MCContext *Ctx)
static unsigned getFixupKindNumBytes(unsigned Kind)
Provides AMDGPU specific target descriptions.
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
std::string Name
static LVOptions Options
Definition: LVOptions.cpp:25
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
mir Rename Register Operands
PowerPC TLS Dynamic Call Fixup
raw_pwrite_stream & OS
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
Generic interface to target specific assembler backends.
Definition: MCAsmBackend.h:55
virtual unsigned getMinimumNopSize() const
Returns the minimum size of a nop in bytes on this target.
Definition: MCAsmBackend.h:185
virtual bool writeNopData(raw_ostream &OS, uint64_t Count, const MCSubtargetInfo *STI) const =0
Write an (optimal) nop sequence of Count bytes to the given output.
virtual void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const
Relax the instruction in the given fragment to the next wider instruction.
Definition: MCAsmBackend.h:157
virtual MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
virtual bool mayNeedRelaxation(unsigned Opcode, ArrayRef< MCOperand > Operands, const MCSubtargetInfo &STI) const
Check whether the given instruction (encoded as Opcode+Operands) may need relaxation.
Definition: MCAsmBackend.h:135
virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value) const
Simple predicate for targets where !Resolved implies requiring relaxation.
Definition: MCAsmBackend.h:147
virtual std::optional< MCFixupKind > getFixupKind(StringRef Name) const
Map a relocation name used in .reloc to a fixup kind.
virtual void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target, uint8_t *Data, uint64_t Value, bool IsResolved)=0
Context object for machine code objects.
Definition: MCContext.h:83
LLVM_ABI void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:1115
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
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:43
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:68
R Default(T Value)
Definition: StringSwitch.h:177
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:47
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVM Value Representation.
Definition: Value.h:75
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
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 int getSOPPWithRelaxation(uint16_t Opcode)
@ ELFOSABI_AMDGPU_HSA
Definition: ELF.h:367
@ ELFOSABI_AMDGPU_MESA3D
Definition: ELF.h:369
@ ELFOSABI_NONE
Definition: ELF.h:346
@ ELFOSABI_AMDGPU_PAL
Definition: ELF.h:368
bool isRelocation(MCFixupKind FixupKind)
Definition: MCFixup.h:130
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ 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
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)
endianness
Definition: bit.h:71
Target independent information on a fixup kind.
Definition: MCAsmBackend.h:38