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/LaneBitmask.h" |
23 | #include "llvm/MC/MCAsmBackend.h" |
24 | #include "llvm/MC/MCCodeEmitter.h" |
25 | #include "llvm/MC/MCELFStreamer.h" |
26 | #include "llvm/MC/MCInstPrinter.h" |
27 | #include "llvm/MC/MCInstrAnalysis.h" |
28 | #include "llvm/MC/MCInstrDesc.h" |
29 | #include "llvm/MC/MCInstrInfo.h" |
30 | #include "llvm/MC/MCObjectWriter.h" |
31 | #include "llvm/MC/MCRegisterInfo.h" |
32 | #include "llvm/MC/MCStreamer.h" |
33 | #include "llvm/MC/MCSubtargetInfo.h" |
34 | #include "llvm/MC/TargetRegistry.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 | return createAMDGPUMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS); |
82 | } |
83 | |
84 | static MCInstPrinter *createAMDGPUMCInstPrinter(const Triple &T, |
85 | unsigned SyntaxVariant, |
86 | const MCAsmInfo &MAI, |
87 | const MCInstrInfo &MII, |
88 | const MCRegisterInfo &MRI) { |
89 | if (T.getArch() == Triple::r600) |
90 | return new R600InstPrinter(MAI, MII, MRI); |
91 | return new AMDGPUInstPrinter(MAI, MII, MRI); |
92 | } |
93 | |
94 | static MCTargetStreamer * |
95 | createAMDGPUAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS, |
96 | MCInstPrinter *InstPrint) { |
97 | return new AMDGPUTargetAsmStreamer(S, OS); |
98 | } |
99 | |
100 | static MCTargetStreamer * createAMDGPUObjectTargetStreamer( |
101 | MCStreamer &S, |
102 | const MCSubtargetInfo &STI) { |
103 | return new AMDGPUTargetELFStreamer(S, STI); |
104 | } |
105 | |
106 | static MCTargetStreamer *createAMDGPUNullTargetStreamer(MCStreamer &S) { |
107 | return new AMDGPUTargetStreamer(S); |
108 | } |
109 | |
110 | static MCStreamer *createMCStreamer(const Triple &T, MCContext &Context, |
111 | std::unique_ptr<MCAsmBackend> &&MAB, |
112 | std::unique_ptr<MCObjectWriter> &&OW, |
113 | std::unique_ptr<MCCodeEmitter> &&Emitter) { |
114 | return createAMDGPUELFStreamer(T, Context, MAB: std::move(MAB), OW: std::move(OW), |
115 | Emitter: std::move(Emitter)); |
116 | } |
117 | |
118 | namespace { |
119 | |
120 | class AMDGPUMCInstrAnalysis : public MCInstrAnalysis { |
121 | public: |
122 | explicit AMDGPUMCInstrAnalysis(const MCInstrInfo *Info) |
123 | : MCInstrAnalysis(Info) {} |
124 | |
125 | bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, |
126 | uint64_t &Target) const override { |
127 | if (Inst.getNumOperands() == 0 || !Inst.getOperand(i: 0).isImm() || |
128 | Info->get(Opcode: Inst.getOpcode()).operands()[0].OperandType != |
129 | MCOI::OPERAND_PCREL) |
130 | return false; |
131 | |
132 | int64_t Imm = Inst.getOperand(i: 0).getImm(); |
133 | // Our branches take a simm16, but we need two extra bits to account for |
134 | // the factor of 4. |
135 | APInt SignedOffset(18, Imm * 4, true); |
136 | Target = (SignedOffset.sext(width: 64) + Addr + Size).getZExtValue(); |
137 | return true; |
138 | } |
139 | }; |
140 | |
141 | } // end anonymous namespace |
142 | |
143 | static MCInstrAnalysis *createAMDGPUMCInstrAnalysis(const MCInstrInfo *Info) { |
144 | return new AMDGPUMCInstrAnalysis(Info); |
145 | } |
146 | |
147 | extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAMDGPUTargetMC() { |
148 | |
149 | TargetRegistry::RegisterMCInstrInfo(T&: getTheGCNTarget(), Fn: createAMDGPUMCInstrInfo); |
150 | TargetRegistry::RegisterMCInstrInfo(T&: getTheR600Target(), |
151 | Fn: createR600MCInstrInfo); |
152 | for (Target *T : {&getTheR600Target(), &getTheGCNTarget()}) { |
153 | RegisterMCAsmInfo<AMDGPUMCAsmInfo> X(*T); |
154 | |
155 | TargetRegistry::RegisterMCRegInfo(T&: *T, Fn: createAMDGPUMCRegisterInfo); |
156 | TargetRegistry::RegisterMCSubtargetInfo(T&: *T, Fn: createAMDGPUMCSubtargetInfo); |
157 | TargetRegistry::RegisterMCInstPrinter(T&: *T, Fn: createAMDGPUMCInstPrinter); |
158 | TargetRegistry::RegisterMCInstrAnalysis(T&: *T, Fn: createAMDGPUMCInstrAnalysis); |
159 | TargetRegistry::RegisterMCAsmBackend(T&: *T, Fn: createAMDGPUAsmBackend); |
160 | TargetRegistry::RegisterELFStreamer(T&: *T, Fn: createMCStreamer); |
161 | } |
162 | |
163 | // R600 specific registration |
164 | TargetRegistry::RegisterMCCodeEmitter(T&: getTheR600Target(), |
165 | Fn: createR600MCCodeEmitter); |
166 | TargetRegistry::RegisterObjectTargetStreamer( |
167 | T&: getTheR600Target(), Fn: createAMDGPUObjectTargetStreamer); |
168 | |
169 | // GCN specific registration |
170 | TargetRegistry::RegisterMCCodeEmitter(T&: getTheGCNTarget(), |
171 | Fn: createAMDGPUMCCodeEmitter); |
172 | |
173 | TargetRegistry::RegisterAsmTargetStreamer(T&: getTheGCNTarget(), |
174 | Fn: createAMDGPUAsmTargetStreamer); |
175 | TargetRegistry::RegisterObjectTargetStreamer( |
176 | T&: getTheGCNTarget(), Fn: createAMDGPUObjectTargetStreamer); |
177 | TargetRegistry::RegisterNullTargetStreamer(T&: getTheGCNTarget(), |
178 | Fn: createAMDGPUNullTargetStreamer); |
179 | } |
180 | |