Revert r354244 "[DAGCombiner] Eliminate dead stores to stack."
[llvm-complete.git] / lib / Target / AArch64 / AArch64MCInstLower.cpp
blobe7d4a2789a28fdf8db75a4c06252ae160c070402
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 {
152 // No modifier means this is a generic reference, classified as absolute for
153 // the cases where it matters (:abs_g0: etc).
154 RefFlags |= AArch64MCExpr::VK_ABS;
157 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
158 RefFlags |= AArch64MCExpr::VK_PAGE;
159 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
160 AArch64II::MO_PAGEOFF)
161 RefFlags |= AArch64MCExpr::VK_PAGEOFF;
162 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3)
163 RefFlags |= AArch64MCExpr::VK_G3;
164 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2)
165 RefFlags |= AArch64MCExpr::VK_G2;
166 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1)
167 RefFlags |= AArch64MCExpr::VK_G1;
168 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0)
169 RefFlags |= AArch64MCExpr::VK_G0;
170 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_HI12)
171 RefFlags |= AArch64MCExpr::VK_HI12;
173 if (MO.getTargetFlags() & AArch64II::MO_NC)
174 RefFlags |= AArch64MCExpr::VK_NC;
176 const MCExpr *Expr =
177 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
178 if (!MO.isJTI() && MO.getOffset())
179 Expr = MCBinaryExpr::createAdd(
180 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
182 AArch64MCExpr::VariantKind RefKind;
183 RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
184 Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
186 return MCOperand::createExpr(Expr);
189 MCOperand AArch64MCInstLower::lowerSymbolOperandCOFF(const MachineOperand &MO,
190 MCSymbol *Sym) const {
191 uint32_t RefFlags = 0;
193 if (MO.getTargetFlags() & AArch64II::MO_TLS) {
194 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGEOFF)
195 RefFlags |= AArch64MCExpr::VK_SECREL_LO12;
196 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
197 AArch64II::MO_HI12)
198 RefFlags |= AArch64MCExpr::VK_SECREL_HI12;
200 } else if (MO.getTargetFlags() & AArch64II::MO_S) {
201 RefFlags |= AArch64MCExpr::VK_SABS;
202 } else {
203 RefFlags |= AArch64MCExpr::VK_ABS;
206 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3)
207 RefFlags |= AArch64MCExpr::VK_G3;
208 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2)
209 RefFlags |= AArch64MCExpr::VK_G2;
210 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1)
211 RefFlags |= AArch64MCExpr::VK_G1;
212 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0)
213 RefFlags |= AArch64MCExpr::VK_G0;
215 // FIXME: Currently we only set VK_NC for MO_G3/MO_G2/MO_G1/MO_G0. This is
216 // because setting VK_NC for others would mean setting their respective
217 // RefFlags correctly. We should do this in a separate patch.
218 if (MO.getTargetFlags() & AArch64II::MO_NC) {
219 auto MOFrag = (MO.getTargetFlags() & AArch64II::MO_FRAGMENT);
220 if (MOFrag == AArch64II::MO_G3 || MOFrag == AArch64II::MO_G2 ||
221 MOFrag == AArch64II::MO_G1 || MOFrag == AArch64II::MO_G0)
222 RefFlags |= AArch64MCExpr::VK_NC;
225 const MCExpr *Expr =
226 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
227 if (!MO.isJTI() && MO.getOffset())
228 Expr = MCBinaryExpr::createAdd(
229 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
231 auto RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
232 assert(RefKind != AArch64MCExpr::VK_INVALID &&
233 "Invalid relocation requested");
234 Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
236 return MCOperand::createExpr(Expr);
239 MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
240 MCSymbol *Sym) const {
241 if (Printer.TM.getTargetTriple().isOSDarwin())
242 return lowerSymbolOperandDarwin(MO, Sym);
243 if (Printer.TM.getTargetTriple().isOSBinFormatCOFF())
244 return lowerSymbolOperandCOFF(MO, Sym);
246 assert(Printer.TM.getTargetTriple().isOSBinFormatELF() && "Invalid target");
247 return lowerSymbolOperandELF(MO, Sym);
250 bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO,
251 MCOperand &MCOp) const {
252 switch (MO.getType()) {
253 default:
254 llvm_unreachable("unknown operand type");
255 case MachineOperand::MO_Register:
256 // Ignore all implicit register operands.
257 if (MO.isImplicit())
258 return false;
259 MCOp = MCOperand::createReg(MO.getReg());
260 break;
261 case MachineOperand::MO_RegisterMask:
262 // Regmasks are like implicit defs.
263 return false;
264 case MachineOperand::MO_Immediate:
265 MCOp = MCOperand::createImm(MO.getImm());
266 break;
267 case MachineOperand::MO_MachineBasicBlock:
268 MCOp = MCOperand::createExpr(
269 MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
270 break;
271 case MachineOperand::MO_GlobalAddress:
272 MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
273 break;
274 case MachineOperand::MO_ExternalSymbol:
275 MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
276 break;
277 case MachineOperand::MO_MCSymbol:
278 MCOp = LowerSymbolOperand(MO, MO.getMCSymbol());
279 break;
280 case MachineOperand::MO_JumpTableIndex:
281 MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
282 break;
283 case MachineOperand::MO_ConstantPoolIndex:
284 MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
285 break;
286 case MachineOperand::MO_BlockAddress:
287 MCOp = LowerSymbolOperand(
288 MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
289 break;
291 return true;
294 void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
295 OutMI.setOpcode(MI->getOpcode());
297 for (const MachineOperand &MO : MI->operands()) {
298 MCOperand MCOp;
299 if (lowerOperand(MO, MCOp))
300 OutMI.addOperand(MCOp);
303 switch (OutMI.getOpcode()) {
304 case AArch64::CATCHRET:
305 OutMI = MCInst();
306 OutMI.setOpcode(AArch64::RET);
307 OutMI.addOperand(MCOperand::createReg(AArch64::LR));
308 break;
309 case AArch64::CLEANUPRET:
310 OutMI = MCInst();
311 OutMI.setOpcode(AArch64::RET);
312 OutMI.addOperand(MCOperand::createReg(AArch64::LR));
313 break;