1//===-- AMDGPUMCTargetDesc.cpp - AMDGPU Target Descriptions ---------------===//
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//===----------------------------------------------------------------------===//
8//
9/// \file
10/// This file provides AMDGPU specific target descriptions.
11//
12//===----------------------------------------------------------------------===//
13
14#include "AMDGPUMCTargetDesc.h"
15#include "AMDGPUELFStreamer.h"
16#include "AMDGPUInstPrinter.h"
17#include "AMDGPUMCAsmInfo.h"
18#include "AMDGPUTargetStreamer.h"
19#include "R600InstPrinter.h"
20#include "R600MCTargetDesc.h"
21#include "TargetInfo/AMDGPUTargetInfo.h"
22#include "llvm/MC/MCAsmBackend.h"
23#include "llvm/MC/MCCodeEmitter.h"
24#include "llvm/MC/MCContext.h"
25#include "llvm/MC/MCELFStreamer.h"
26#include "llvm/MC/MCInstPrinter.h"
27#include "llvm/MC/MCInstrDesc.h"
28#include "llvm/MC/MCInstrInfo.h"
29#include "llvm/MC/MCObjectWriter.h"
30#include "llvm/MC/MCRegisterInfo.h"
31#include "llvm/MC/MCStreamer.h"
32#include "llvm/MC/MCSubtargetInfo.h"
33#include "llvm/MC/TargetRegistry.h"
34#include "llvm/Support/Compiler.h"
35
36using namespace llvm;
37
38#define GET_INSTRINFO_MC_DESC
39#define ENABLE_INSTR_PREDICATE_VERIFIER
40#include "AMDGPUGenInstrInfo.inc"
41
42#define GET_SUBTARGETINFO_MC_DESC
43#include "AMDGPUGenSubtargetInfo.inc"
44
45#define NoSchedModel NoSchedModelR600
46#define GET_SUBTARGETINFO_MC_DESC
47#include "R600GenSubtargetInfo.inc"
48#undef NoSchedModelR600
49
50#define GET_REGINFO_MC_DESC
51#include "AMDGPUGenRegisterInfo.inc"
52
53#define GET_REGINFO_MC_DESC
54#include "R600GenRegisterInfo.inc"
55
56static MCInstrInfo *createAMDGPUMCInstrInfo() {
57 MCInstrInfo *X = new MCInstrInfo();
58 InitAMDGPUMCInstrInfo(II: X);
59 return X;
60}
61
62static MCRegisterInfo *createAMDGPUMCRegisterInfo(const Triple &TT) {
63 MCRegisterInfo *X = new MCRegisterInfo();
64 if (TT.getArch() == Triple::r600)
65 InitR600MCRegisterInfo(RI: X, RA: 0);
66 else
67 InitAMDGPUMCRegisterInfo(RI: X, RA: AMDGPU::PC_REG);
68 return X;
69}
70
71MCRegisterInfo *llvm::createGCNMCRegisterInfo(AMDGPUDwarfFlavour DwarfFlavour) {
72 MCRegisterInfo *X = new MCRegisterInfo();
73 InitAMDGPUMCRegisterInfo(RI: X, RA: AMDGPU::PC_REG, DwarfFlavour, EHFlavour: DwarfFlavour);
74 return X;
75}
76
77static MCSubtargetInfo *
78createAMDGPUMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
79 if (TT.getArch() == Triple::r600)
80 return createR600MCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS);
81
82 MCSubtargetInfo *STI =
83 createAMDGPUMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS);
84
85 bool IsWave64 = STI->hasFeature(Feature: AMDGPU::FeatureWavefrontSize64);
86 bool IsWave32 = STI->hasFeature(Feature: AMDGPU::FeatureWavefrontSize32);
87
88 // FIXME: We should error for the default target.
89 if (STI->getFeatureBits().none())
90 STI->ToggleFeature(FB: AMDGPU::FeatureSouthernIslands);
91
92 if (!IsWave64 && !IsWave32) {
93 // If there is no default wave size it must be a generation before gfx10,
94 // these have FeatureWavefrontSize64 in their definition already. For gfx10+
95 // set wave32 as a default.
96 STI->ToggleFeature(FB: AMDGPU::isGFX10Plus(STI: *STI)
97 ? AMDGPU::FeatureWavefrontSize32
98 : AMDGPU::FeatureWavefrontSize64);
99 } else if (IsWave64 && IsWave32) {
100 // The wave size is mutually exclusive. If both somehow end up set, wave32
101 // wins if supported.
102 STI->ToggleFeature(FB: AMDGPU::supportsWave32(STI: *STI)
103 ? AMDGPU::FeatureWavefrontSize64
104 : AMDGPU::FeatureWavefrontSize32);
105
106 // If both wavesizes were manually requested, hack in a feature to permit
107 // assembling modules with mixed wavesizes.
108 STI->ToggleFeature(FB: AMDGPU::FeatureAssemblerPermissiveWavesize);
109 }
110
111 assert((STI->hasFeature(AMDGPU::FeatureWavefrontSize64) !=
112 STI->hasFeature(AMDGPU::FeatureWavefrontSize32)) &&
113 "wavesize features are mutually exclusive");
114
115 return STI;
116}
117
118static MCInstPrinter *createAMDGPUMCInstPrinter(const Triple &T,
119 unsigned SyntaxVariant,
120 const MCAsmInfo &MAI,
121 const MCInstrInfo &MII,
122 const MCRegisterInfo &MRI) {
123 if (T.getArch() == Triple::r600)
124 return new R600InstPrinter(MAI, MII, MRI);
125 return new AMDGPUInstPrinter(MAI, MII, MRI);
126}
127
128static MCTargetStreamer *
129createAMDGPUAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS,
130 MCInstPrinter *InstPrint) {
131 return new AMDGPUTargetAsmStreamer(S, OS);
132}
133
134static MCTargetStreamer * createAMDGPUObjectTargetStreamer(
135 MCStreamer &S,
136 const MCSubtargetInfo &STI) {
137 return new AMDGPUTargetELFStreamer(S, STI);
138}
139
140static MCTargetStreamer *createAMDGPUNullTargetStreamer(MCStreamer &S) {
141 return new AMDGPUTargetStreamer(S);
142}
143
144static MCStreamer *createMCStreamer(const Triple &T, MCContext &Context,
145 std::unique_ptr<MCAsmBackend> &&MAB,
146 std::unique_ptr<MCObjectWriter> &&OW,
147 std::unique_ptr<MCCodeEmitter> &&Emitter) {
148 return createAMDGPUELFStreamer(T, Context, MAB: std::move(MAB), OW: std::move(OW),
149 Emitter: std::move(Emitter));
150}
151
152namespace llvm {
153namespace AMDGPU {
154
155bool AMDGPUMCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr,
156 uint64_t Size,
157 uint64_t &Target) const {
158 if (Inst.getNumOperands() == 0 || !Inst.getOperand(i: 0).isImm() ||
159 Info->get(Opcode: Inst.getOpcode()).operands()[0].OperandType !=
160 MCOI::OPERAND_PCREL)
161 return false;
162
163 int64_t Imm = Inst.getOperand(i: 0).getImm();
164 // Our branches take a simm16.
165 Target = SignExtend64<16>(x: Imm) * 4 + Addr + Size;
166 return true;
167}
168
169void AMDGPUMCInstrAnalysis::updateState(const MCInst &Inst, uint64_t Addr) {
170 if (Inst.getOpcode() == AMDGPU::S_SET_VGPR_MSB_gfx12)
171 VgprMSBs = Inst.getOperand(i: 0).getImm() & 0xff;
172 else if (isTerminator(Inst))
173 VgprMSBs = 0;
174}
175
176} // end namespace AMDGPU
177} // end namespace llvm
178
179static MCInstrAnalysis *createAMDGPUMCInstrAnalysis(const MCInstrInfo *Info) {
180 return new AMDGPU::AMDGPUMCInstrAnalysis(Info);
181}
182
183extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
184LLVMInitializeAMDGPUTargetMC() {
185
186 TargetRegistry::RegisterMCInstrInfo(T&: getTheGCNTarget(), Fn: createAMDGPUMCInstrInfo);
187 TargetRegistry::RegisterMCInstrInfo(T&: getTheR600Target(),
188 Fn: createR600MCInstrInfo);
189 for (Target *T : {&getTheR600Target(), &getTheGCNTarget()}) {
190 RegisterMCAsmInfo<AMDGPUMCAsmInfo> X(*T);
191
192 TargetRegistry::RegisterMCRegInfo(T&: *T, Fn: createAMDGPUMCRegisterInfo);
193 TargetRegistry::RegisterMCSubtargetInfo(T&: *T, Fn: createAMDGPUMCSubtargetInfo);
194 TargetRegistry::RegisterMCInstPrinter(T&: *T, Fn: createAMDGPUMCInstPrinter);
195 TargetRegistry::RegisterMCInstrAnalysis(T&: *T, Fn: createAMDGPUMCInstrAnalysis);
196 TargetRegistry::RegisterMCAsmBackend(T&: *T, Fn: createAMDGPUAsmBackend);
197 TargetRegistry::RegisterELFStreamer(T&: *T, Fn: createMCStreamer);
198 }
199
200 // R600 specific registration
201 TargetRegistry::RegisterMCCodeEmitter(T&: getTheR600Target(),
202 Fn: createR600MCCodeEmitter);
203 TargetRegistry::RegisterObjectTargetStreamer(
204 T&: getTheR600Target(), Fn: createAMDGPUObjectTargetStreamer);
205
206 // GCN specific registration
207 TargetRegistry::RegisterMCCodeEmitter(T&: getTheGCNTarget(),
208 Fn: createAMDGPUMCCodeEmitter);
209
210 TargetRegistry::RegisterAsmTargetStreamer(T&: getTheGCNTarget(),
211 Fn: createAMDGPUAsmTargetStreamer);
212 TargetRegistry::RegisterObjectTargetStreamer(
213 T&: getTheGCNTarget(), Fn: createAMDGPUObjectTargetStreamer);
214 TargetRegistry::RegisterNullTargetStreamer(T&: getTheGCNTarget(),
215 Fn: createAMDGPUNullTargetStreamer);
216}
217