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/MCELFStreamer.h" |
25 | #include "llvm/MC/MCInstPrinter.h" |
26 | #include "llvm/MC/MCInstrAnalysis.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 | |
36 | using 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 | |
56 | static MCInstrInfo *createAMDGPUMCInstrInfo() { |
57 | MCInstrInfo *X = new MCInstrInfo(); |
58 | InitAMDGPUMCInstrInfo(II: X); |
59 | return X; |
60 | } |
61 | |
62 | static 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 | |
71 | MCRegisterInfo *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 | |
77 | static MCSubtargetInfo * |
78 | createAMDGPUMCSubtargetInfo(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 | // FIXME: We should error for the default target. |
86 | if (!STI->hasFeature(Feature: AMDGPU::FeatureWavefrontSize64) && |
87 | !STI->hasFeature(Feature: AMDGPU::FeatureWavefrontSize32)) { |
88 | // If there is no default wave size it must be a generation before gfx10, |
89 | // these have FeatureWavefrontSize64 in their definition already. For gfx10+ |
90 | // set wave32 as a default. |
91 | STI->ToggleFeature(FB: AMDGPU::isGFX10Plus(STI: *STI) |
92 | ? AMDGPU::FeatureWavefrontSize32 |
93 | : AMDGPU::FeatureWavefrontSize64); |
94 | } |
95 | |
96 | return STI; |
97 | } |
98 | |
99 | static MCInstPrinter *createAMDGPUMCInstPrinter(const Triple &T, |
100 | unsigned SyntaxVariant, |
101 | const MCAsmInfo &MAI, |
102 | const MCInstrInfo &MII, |
103 | const MCRegisterInfo &MRI) { |
104 | if (T.getArch() == Triple::r600) |
105 | return new R600InstPrinter(MAI, MII, MRI); |
106 | return new AMDGPUInstPrinter(MAI, MII, MRI); |
107 | } |
108 | |
109 | static MCTargetStreamer * |
110 | createAMDGPUAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS, |
111 | MCInstPrinter *InstPrint) { |
112 | return new AMDGPUTargetAsmStreamer(S, OS); |
113 | } |
114 | |
115 | static MCTargetStreamer * createAMDGPUObjectTargetStreamer( |
116 | MCStreamer &S, |
117 | const MCSubtargetInfo &STI) { |
118 | return new AMDGPUTargetELFStreamer(S, STI); |
119 | } |
120 | |
121 | static MCTargetStreamer *createAMDGPUNullTargetStreamer(MCStreamer &S) { |
122 | return new AMDGPUTargetStreamer(S); |
123 | } |
124 | |
125 | static MCStreamer *createMCStreamer(const Triple &T, MCContext &Context, |
126 | std::unique_ptr<MCAsmBackend> &&MAB, |
127 | std::unique_ptr<MCObjectWriter> &&OW, |
128 | std::unique_ptr<MCCodeEmitter> &&Emitter) { |
129 | return createAMDGPUELFStreamer(T, Context, MAB: std::move(MAB), OW: std::move(OW), |
130 | Emitter: std::move(Emitter)); |
131 | } |
132 | |
133 | namespace { |
134 | |
135 | class AMDGPUMCInstrAnalysis : public MCInstrAnalysis { |
136 | public: |
137 | explicit AMDGPUMCInstrAnalysis(const MCInstrInfo *Info) |
138 | : MCInstrAnalysis(Info) {} |
139 | |
140 | bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, |
141 | uint64_t &Target) const override { |
142 | if (Inst.getNumOperands() == 0 || !Inst.getOperand(i: 0).isImm() || |
143 | Info->get(Opcode: Inst.getOpcode()).operands()[0].OperandType != |
144 | MCOI::OPERAND_PCREL) |
145 | return false; |
146 | |
147 | int64_t Imm = Inst.getOperand(i: 0).getImm(); |
148 | // Our branches take a simm16. |
149 | Target = SignExtend64<16>(x: Imm) * 4 + Addr + Size; |
150 | return true; |
151 | } |
152 | }; |
153 | |
154 | } // end anonymous namespace |
155 | |
156 | static MCInstrAnalysis *createAMDGPUMCInstrAnalysis(const MCInstrInfo *Info) { |
157 | return new AMDGPUMCInstrAnalysis(Info); |
158 | } |
159 | |
160 | extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void |
161 | LLVMInitializeAMDGPUTargetMC() { |
162 | |
163 | TargetRegistry::RegisterMCInstrInfo(T&: getTheGCNTarget(), Fn: createAMDGPUMCInstrInfo); |
164 | TargetRegistry::RegisterMCInstrInfo(T&: getTheR600Target(), |
165 | Fn: createR600MCInstrInfo); |
166 | for (Target *T : {&getTheR600Target(), &getTheGCNTarget()}) { |
167 | RegisterMCAsmInfo<AMDGPUMCAsmInfo> X(*T); |
168 | |
169 | TargetRegistry::RegisterMCRegInfo(T&: *T, Fn: createAMDGPUMCRegisterInfo); |
170 | TargetRegistry::RegisterMCSubtargetInfo(T&: *T, Fn: createAMDGPUMCSubtargetInfo); |
171 | TargetRegistry::RegisterMCInstPrinter(T&: *T, Fn: createAMDGPUMCInstPrinter); |
172 | TargetRegistry::RegisterMCInstrAnalysis(T&: *T, Fn: createAMDGPUMCInstrAnalysis); |
173 | TargetRegistry::RegisterMCAsmBackend(T&: *T, Fn: createAMDGPUAsmBackend); |
174 | TargetRegistry::RegisterELFStreamer(T&: *T, Fn: createMCStreamer); |
175 | } |
176 | |
177 | // R600 specific registration |
178 | TargetRegistry::RegisterMCCodeEmitter(T&: getTheR600Target(), |
179 | Fn: createR600MCCodeEmitter); |
180 | TargetRegistry::RegisterObjectTargetStreamer( |
181 | T&: getTheR600Target(), Fn: createAMDGPUObjectTargetStreamer); |
182 | |
183 | // GCN specific registration |
184 | TargetRegistry::RegisterMCCodeEmitter(T&: getTheGCNTarget(), |
185 | Fn: createAMDGPUMCCodeEmitter); |
186 | |
187 | TargetRegistry::RegisterAsmTargetStreamer(T&: getTheGCNTarget(), |
188 | Fn: createAMDGPUAsmTargetStreamer); |
189 | TargetRegistry::RegisterObjectTargetStreamer( |
190 | T&: getTheGCNTarget(), Fn: createAMDGPUObjectTargetStreamer); |
191 | TargetRegistry::RegisterNullTargetStreamer(T&: getTheGCNTarget(), |
192 | Fn: createAMDGPUNullTargetStreamer); |
193 | } |
194 | |