[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / lib / Target / AArch64 / AArch64MCInstLower.cpp
blobafd5ae6bcbf2cc5dce8c6110c8a1a7e9cbb0aa04
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.getSymbol(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;
208 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3)
209 RefFlags |= AArch64MCExpr::VK_G3;
210 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2)
211 RefFlags |= AArch64MCExpr::VK_G2;
212 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1)
213 RefFlags |= AArch64MCExpr::VK_G1;
214 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0)
215 RefFlags |= AArch64MCExpr::VK_G0;
217 // FIXME: Currently we only set VK_NC for MO_G3/MO_G2/MO_G1/MO_G0. This is
218 // because setting VK_NC for others would mean setting their respective
219 // RefFlags correctly. We should do this in a separate patch.
220 if (MO.getTargetFlags() & AArch64II::MO_NC) {
221 auto MOFrag = (MO.getTargetFlags() & AArch64II::MO_FRAGMENT);
222 if (MOFrag == AArch64II::MO_G3 || MOFrag == AArch64II::MO_G2 ||
223 MOFrag == AArch64II::MO_G1 || MOFrag == AArch64II::MO_G0)
224 RefFlags |= AArch64MCExpr::VK_NC;
227 const MCExpr *Expr =
228 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
229 if (!MO.isJTI() && MO.getOffset())
230 Expr = MCBinaryExpr::createAdd(
231 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
233 auto RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
234 assert(RefKind != AArch64MCExpr::VK_INVALID &&
235 "Invalid relocation requested");
236 Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
238 return MCOperand::createExpr(Expr);
241 MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
242 MCSymbol *Sym) const {
243 if (Printer.TM.getTargetTriple().isOSDarwin())
244 return lowerSymbolOperandDarwin(MO, Sym);
245 if (Printer.TM.getTargetTriple().isOSBinFormatCOFF())
246 return lowerSymbolOperandCOFF(MO, Sym);
248 assert(Printer.TM.getTargetTriple().isOSBinFormatELF() && "Invalid target");
249 return lowerSymbolOperandELF(MO, Sym);
252 bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO,
253 MCOperand &MCOp) const {
254 switch (MO.getType()) {
255 default:
256 llvm_unreachable("unknown operand type");
257 case MachineOperand::MO_Register:
258 // Ignore all implicit register operands.
259 if (MO.isImplicit())
260 return false;
261 MCOp = MCOperand::createReg(MO.getReg());
262 break;
263 case MachineOperand::MO_RegisterMask:
264 // Regmasks are like implicit defs.
265 return false;
266 case MachineOperand::MO_Immediate:
267 MCOp = MCOperand::createImm(MO.getImm());
268 break;
269 case MachineOperand::MO_MachineBasicBlock:
270 MCOp = MCOperand::createExpr(
271 MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
272 break;
273 case MachineOperand::MO_GlobalAddress:
274 MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
275 break;
276 case MachineOperand::MO_ExternalSymbol:
277 MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
278 break;
279 case MachineOperand::MO_MCSymbol:
280 MCOp = LowerSymbolOperand(MO, MO.getMCSymbol());
281 break;
282 case MachineOperand::MO_JumpTableIndex:
283 MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
284 break;
285 case MachineOperand::MO_ConstantPoolIndex:
286 MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
287 break;
288 case MachineOperand::MO_BlockAddress:
289 MCOp = LowerSymbolOperand(
290 MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
291 break;
293 return true;
296 void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
297 OutMI.setOpcode(MI->getOpcode());
299 for (const MachineOperand &MO : MI->operands()) {
300 MCOperand MCOp;
301 if (lowerOperand(MO, MCOp))
302 OutMI.addOperand(MCOp);
305 switch (OutMI.getOpcode()) {
306 case AArch64::CATCHRET:
307 OutMI = MCInst();
308 OutMI.setOpcode(AArch64::RET);
309 OutMI.addOperand(MCOperand::createReg(AArch64::LR));
310 break;
311 case AArch64::CLEANUPRET:
312 OutMI = MCInst();
313 OutMI.setOpcode(AArch64::RET);
314 OutMI.addOperand(MCOperand::createReg(AArch64::LR));
315 break;