[AMDGPU] New gfx940 mfma instructions
[llvm-project.git] / llvm / lib / Target / AArch64 / AArch64MCInstLower.cpp
blob450c270fcc9b5c7d28f219b5d863f68b1e6f9ac1
1 //==-- AArch64MCInstLower.cpp - Convert AArch64 MachineInstr to an MCInst --==//
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 // This file contains code to lower AArch64 MachineInstrs to their corresponding
10 // MCInst records.
12 //===----------------------------------------------------------------------===//
14 #include "AArch64MCInstLower.h"
15 #include "MCTargetDesc/AArch64MCExpr.h"
16 #include "Utils/AArch64BaseInfo.h"
17 #include "llvm/CodeGen/AsmPrinter.h"
18 #include "llvm/CodeGen/MachineBasicBlock.h"
19 #include "llvm/CodeGen/MachineInstr.h"
20 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
21 #include "llvm/IR/Mangler.h"
22 #include "llvm/MC/MCContext.h"
23 #include "llvm/MC/MCExpr.h"
24 #include "llvm/MC/MCInst.h"
25 #include "llvm/Support/CodeGen.h"
26 #include "llvm/Support/CommandLine.h"
27 #include "llvm/Target/TargetLoweringObjectFile.h"
28 #include "llvm/Target/TargetMachine.h"
29 using namespace llvm;
31 extern cl::opt<bool> EnableAArch64ELFLocalDynamicTLSGeneration;
33 AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer)
34 : Ctx(ctx), Printer(printer) {}
36 MCSymbol *
37 AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
38 const GlobalValue *GV = MO.getGlobal();
39 unsigned TargetFlags = MO.getTargetFlags();
40 const Triple &TheTriple = Printer.TM.getTargetTriple();
41 if (!TheTriple.isOSBinFormatCOFF())
42 return Printer.getSymbolPreferLocal(*GV);
44 assert(TheTriple.isOSWindows() &&
45 "Windows is the only supported COFF target");
47 bool IsIndirect = (TargetFlags & (AArch64II::MO_DLLIMPORT | AArch64II::MO_COFFSTUB));
48 if (!IsIndirect)
49 return Printer.getSymbol(GV);
51 SmallString<128> Name;
52 if (TargetFlags & AArch64II::MO_DLLIMPORT)
53 Name = "__imp_";
54 else if (TargetFlags & AArch64II::MO_COFFSTUB)
55 Name = ".refptr.";
56 Printer.TM.getNameWithPrefix(Name, GV,
57 Printer.getObjFileLowering().getMangler());
59 MCSymbol *MCSym = Ctx.getOrCreateSymbol(Name);
61 if (TargetFlags & AArch64II::MO_COFFSTUB) {
62 MachineModuleInfoCOFF &MMICOFF =
63 Printer.MMI->getObjFileInfo<MachineModuleInfoCOFF>();
64 MachineModuleInfoImpl::StubValueTy &StubSym =
65 MMICOFF.getGVStubEntry(MCSym);
67 if (!StubSym.getPointer())
68 StubSym = MachineModuleInfoImpl::StubValueTy(Printer.getSymbol(GV), true);
71 return MCSym;
74 MCSymbol *
75 AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const {
76 return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
79 MCOperand AArch64MCInstLower::lowerSymbolOperandDarwin(const MachineOperand &MO,
80 MCSymbol *Sym) const {
81 // FIXME: We would like an efficient form for this, so we don't have to do a
82 // lot of extra uniquing.
83 MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
84 if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) {
85 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
86 RefKind = MCSymbolRefExpr::VK_GOTPAGE;
87 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
88 AArch64II::MO_PAGEOFF)
89 RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF;
90 else
91 llvm_unreachable("Unexpected target flags with MO_GOT on GV operand");
92 } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) {
93 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
94 RefKind = MCSymbolRefExpr::VK_TLVPPAGE;
95 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
96 AArch64II::MO_PAGEOFF)
97 RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF;
98 else
99 llvm_unreachable("Unexpected target flags with MO_TLS on GV operand");
100 } else {
101 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
102 RefKind = MCSymbolRefExpr::VK_PAGE;
103 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
104 AArch64II::MO_PAGEOFF)
105 RefKind = MCSymbolRefExpr::VK_PAGEOFF;
107 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
108 if (!MO.isJTI() && MO.getOffset())
109 Expr = MCBinaryExpr::createAdd(
110 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
111 return MCOperand::createExpr(Expr);
114 MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
115 MCSymbol *Sym) const {
116 uint32_t RefFlags = 0;
118 if (MO.getTargetFlags() & AArch64II::MO_GOT)
119 RefFlags |= AArch64MCExpr::VK_GOT;
120 else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
121 TLSModel::Model Model;
122 if (MO.isGlobal()) {
123 const GlobalValue *GV = MO.getGlobal();
124 Model = Printer.TM.getTLSModel(GV);
125 if (!EnableAArch64ELFLocalDynamicTLSGeneration &&
126 Model == TLSModel::LocalDynamic)
127 Model = TLSModel::GeneralDynamic;
129 } else {
130 assert(MO.isSymbol() &&
131 StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" &&
132 "unexpected external TLS symbol");
133 // The general dynamic access sequence is used to get the
134 // address of _TLS_MODULE_BASE_.
135 Model = TLSModel::GeneralDynamic;
137 switch (Model) {
138 case TLSModel::InitialExec:
139 RefFlags |= AArch64MCExpr::VK_GOTTPREL;
140 break;
141 case TLSModel::LocalExec:
142 RefFlags |= AArch64MCExpr::VK_TPREL;
143 break;
144 case TLSModel::LocalDynamic:
145 RefFlags |= AArch64MCExpr::VK_DTPREL;
146 break;
147 case TLSModel::GeneralDynamic:
148 RefFlags |= AArch64MCExpr::VK_TLSDESC;
149 break;
151 } else if (MO.getTargetFlags() & AArch64II::MO_PREL) {
152 RefFlags |= AArch64MCExpr::VK_PREL;
153 } else {
154 // No modifier means this is a generic reference, classified as absolute for
155 // the cases where it matters (:abs_g0: etc).
156 RefFlags |= AArch64MCExpr::VK_ABS;
159 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
160 RefFlags |= AArch64MCExpr::VK_PAGE;
161 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
162 AArch64II::MO_PAGEOFF)
163 RefFlags |= AArch64MCExpr::VK_PAGEOFF;
164 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3)
165 RefFlags |= AArch64MCExpr::VK_G3;
166 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2)
167 RefFlags |= AArch64MCExpr::VK_G2;
168 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1)
169 RefFlags |= AArch64MCExpr::VK_G1;
170 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0)
171 RefFlags |= AArch64MCExpr::VK_G0;
172 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_HI12)
173 RefFlags |= AArch64MCExpr::VK_HI12;
175 if (MO.getTargetFlags() & AArch64II::MO_NC)
176 RefFlags |= AArch64MCExpr::VK_NC;
178 const MCExpr *Expr =
179 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
180 if (!MO.isJTI() && MO.getOffset())
181 Expr = MCBinaryExpr::createAdd(
182 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
184 AArch64MCExpr::VariantKind RefKind;
185 RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
186 Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
188 return MCOperand::createExpr(Expr);
191 MCOperand AArch64MCInstLower::lowerSymbolOperandCOFF(const MachineOperand &MO,
192 MCSymbol *Sym) const {
193 uint32_t RefFlags = 0;
195 if (MO.getTargetFlags() & AArch64II::MO_TLS) {
196 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGEOFF)
197 RefFlags |= AArch64MCExpr::VK_SECREL_LO12;
198 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
199 AArch64II::MO_HI12)
200 RefFlags |= AArch64MCExpr::VK_SECREL_HI12;
202 } else if (MO.getTargetFlags() & AArch64II::MO_S) {
203 RefFlags |= AArch64MCExpr::VK_SABS;
204 } else {
205 RefFlags |= AArch64MCExpr::VK_ABS;
207 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
208 RefFlags |= AArch64MCExpr::VK_PAGE;
209 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
210 AArch64II::MO_PAGEOFF)
211 RefFlags |= AArch64MCExpr::VK_PAGEOFF | AArch64MCExpr::VK_NC;
214 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3)
215 RefFlags |= AArch64MCExpr::VK_G3;
216 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2)
217 RefFlags |= AArch64MCExpr::VK_G2;
218 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1)
219 RefFlags |= AArch64MCExpr::VK_G1;
220 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0)
221 RefFlags |= AArch64MCExpr::VK_G0;
223 // FIXME: Currently we only set VK_NC for MO_G3/MO_G2/MO_G1/MO_G0. This is
224 // because setting VK_NC for others would mean setting their respective
225 // RefFlags correctly. We should do this in a separate patch.
226 if (MO.getTargetFlags() & AArch64II::MO_NC) {
227 auto MOFrag = (MO.getTargetFlags() & AArch64II::MO_FRAGMENT);
228 if (MOFrag == AArch64II::MO_G3 || MOFrag == AArch64II::MO_G2 ||
229 MOFrag == AArch64II::MO_G1 || MOFrag == AArch64II::MO_G0)
230 RefFlags |= AArch64MCExpr::VK_NC;
233 const MCExpr *Expr =
234 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
235 if (!MO.isJTI() && MO.getOffset())
236 Expr = MCBinaryExpr::createAdd(
237 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
239 auto RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
240 assert(RefKind != AArch64MCExpr::VK_INVALID &&
241 "Invalid relocation requested");
242 Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
244 return MCOperand::createExpr(Expr);
247 MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
248 MCSymbol *Sym) const {
249 if (Printer.TM.getTargetTriple().isOSDarwin())
250 return lowerSymbolOperandDarwin(MO, Sym);
251 if (Printer.TM.getTargetTriple().isOSBinFormatCOFF())
252 return lowerSymbolOperandCOFF(MO, Sym);
254 assert(Printer.TM.getTargetTriple().isOSBinFormatELF() && "Invalid target");
255 return lowerSymbolOperandELF(MO, Sym);
258 bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO,
259 MCOperand &MCOp) const {
260 switch (MO.getType()) {
261 default:
262 llvm_unreachable("unknown operand type");
263 case MachineOperand::MO_Register:
264 // Ignore all implicit register operands.
265 if (MO.isImplicit())
266 return false;
267 MCOp = MCOperand::createReg(MO.getReg());
268 break;
269 case MachineOperand::MO_RegisterMask:
270 // Regmasks are like implicit defs.
271 return false;
272 case MachineOperand::MO_Immediate:
273 MCOp = MCOperand::createImm(MO.getImm());
274 break;
275 case MachineOperand::MO_MachineBasicBlock:
276 MCOp = MCOperand::createExpr(
277 MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
278 break;
279 case MachineOperand::MO_GlobalAddress:
280 MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
281 break;
282 case MachineOperand::MO_ExternalSymbol:
283 MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
284 break;
285 case MachineOperand::MO_MCSymbol:
286 MCOp = LowerSymbolOperand(MO, MO.getMCSymbol());
287 break;
288 case MachineOperand::MO_JumpTableIndex:
289 MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
290 break;
291 case MachineOperand::MO_ConstantPoolIndex:
292 MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
293 break;
294 case MachineOperand::MO_BlockAddress:
295 MCOp = LowerSymbolOperand(
296 MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
297 break;
299 return true;
302 void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
303 OutMI.setOpcode(MI->getOpcode());
305 for (const MachineOperand &MO : MI->operands()) {
306 MCOperand MCOp;
307 if (lowerOperand(MO, MCOp))
308 OutMI.addOperand(MCOp);
311 switch (OutMI.getOpcode()) {
312 case AArch64::CATCHRET:
313 OutMI = MCInst();
314 OutMI.setOpcode(AArch64::RET);
315 OutMI.addOperand(MCOperand::createReg(AArch64::LR));
316 break;
317 case AArch64::CLEANUPRET:
318 OutMI = MCInst();
319 OutMI.setOpcode(AArch64::RET);
320 OutMI.addOperand(MCOperand::createReg(AArch64::LR));
321 break;