Line data Source code
1 : //==-- AArch64MCInstLower.cpp - Convert AArch64 MachineInstr to an MCInst --==//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This file contains code to lower AArch64 MachineInstrs to their corresponding
11 : // MCInst records.
12 : //
13 : //===----------------------------------------------------------------------===//
14 :
15 : #include "AArch64MCInstLower.h"
16 : #include "MCTargetDesc/AArch64MCExpr.h"
17 : #include "Utils/AArch64BaseInfo.h"
18 : #include "llvm/CodeGen/AsmPrinter.h"
19 : #include "llvm/CodeGen/MachineBasicBlock.h"
20 : #include "llvm/CodeGen/MachineInstr.h"
21 : #include "llvm/CodeGen/MachineModuleInfoImpls.h"
22 : #include "llvm/IR/Mangler.h"
23 : #include "llvm/MC/MCContext.h"
24 : #include "llvm/MC/MCExpr.h"
25 : #include "llvm/MC/MCInst.h"
26 : #include "llvm/Support/CodeGen.h"
27 : #include "llvm/Support/CommandLine.h"
28 : #include "llvm/Target/TargetLoweringObjectFile.h"
29 : #include "llvm/Target/TargetMachine.h"
30 : using namespace llvm;
31 :
32 : extern cl::opt<bool> EnableAArch64ELFLocalDynamicTLSGeneration;
33 :
34 1193 : AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer)
35 2386 : : Ctx(ctx), Printer(printer) {}
36 :
37 : MCSymbol *
38 8465 : AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
39 8465 : const GlobalValue *GV = MO.getGlobal();
40 : unsigned TargetFlags = MO.getTargetFlags();
41 8465 : const Triple &TheTriple = Printer.TM.getTargetTriple();
42 8465 : if (!TheTriple.isOSBinFormatCOFF())
43 8390 : return Printer.getSymbol(GV);
44 :
45 : assert(TheTriple.isOSWindows() &&
46 : "Windows is the only supported COFF target");
47 :
48 75 : bool IsIndirect = (TargetFlags & (AArch64II::MO_DLLIMPORT | AArch64II::MO_COFFSTUB));
49 75 : if (!IsIndirect)
50 47 : return Printer.getSymbol(GV);
51 :
52 : SmallString<128> Name;
53 28 : if (TargetFlags & AArch64II::MO_DLLIMPORT)
54 : Name = "__imp_";
55 8 : else if (TargetFlags & AArch64II::MO_COFFSTUB)
56 : Name = ".refptr.";
57 28 : Printer.TM.getNameWithPrefix(Name, GV,
58 28 : Printer.getObjFileLowering().getMangler());
59 :
60 56 : MCSymbol *MCSym = Ctx.getOrCreateSymbol(Name);
61 :
62 28 : if (TargetFlags & AArch64II::MO_COFFSTUB) {
63 : MachineModuleInfoCOFF &MMICOFF =
64 8 : Printer.MMI->getObjFileInfo<MachineModuleInfoCOFF>();
65 : MachineModuleInfoImpl::StubValueTy &StubSym =
66 8 : MMICOFF.getGVStubEntry(MCSym);
67 :
68 16 : if (!StubSym.getPointer())
69 3 : StubSym = MachineModuleInfoImpl::StubValueTy(Printer.getSymbol(GV), true);
70 : }
71 :
72 : return MCSym;
73 : }
74 :
75 : MCSymbol *
76 631 : AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const {
77 1262 : return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
78 : }
79 :
80 1355 : MCOperand AArch64MCInstLower::lowerSymbolOperandDarwin(const MachineOperand &MO,
81 : MCSymbol *Sym) const {
82 : // FIXME: We would like an efficient form for this, so we don't have to do a
83 : // lot of extra uniquing.
84 : MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
85 1355 : if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) {
86 364 : if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
87 : RefKind = MCSymbolRefExpr::VK_GOTPAGE;
88 182 : else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
89 : AArch64II::MO_PAGEOFF)
90 : RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF;
91 : else
92 0 : llvm_unreachable("Unexpected target flags with MO_GOT on GV operand");
93 991 : } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) {
94 50 : if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
95 : RefKind = MCSymbolRefExpr::VK_TLVPPAGE;
96 25 : else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
97 : AArch64II::MO_PAGEOFF)
98 : RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF;
99 : else
100 0 : llvm_unreachable("Unexpected target flags with MO_TLS on GV operand");
101 : } else {
102 941 : if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
103 : RefKind = MCSymbolRefExpr::VK_PAGE;
104 725 : else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
105 : AArch64II::MO_PAGEOFF)
106 : RefKind = MCSymbolRefExpr::VK_PAGEOFF;
107 : }
108 1355 : const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
109 1355 : if (!MO.isJTI() && MO.getOffset())
110 10 : Expr = MCBinaryExpr::createAdd(
111 10 : Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
112 1355 : return MCOperand::createExpr(Expr);
113 : }
114 :
115 8069 : MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
116 : MCSymbol *Sym) const {
117 : uint32_t RefFlags = 0;
118 :
119 8069 : if (MO.getTargetFlags() & AArch64II::MO_GOT)
120 : RefFlags |= AArch64MCExpr::VK_GOT;
121 7909 : else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
122 : TLSModel::Model Model;
123 141 : if (MO.isGlobal()) {
124 114 : const GlobalValue *GV = MO.getGlobal();
125 114 : Model = Printer.TM.getTLSModel(GV);
126 114 : if (!EnableAArch64ELFLocalDynamicTLSGeneration &&
127 : Model == TLSModel::LocalDynamic)
128 : Model = TLSModel::GeneralDynamic;
129 :
130 : } else {
131 : assert(MO.isSymbol() &&
132 : StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" &&
133 : "unexpected external TLS symbol");
134 : // The general dynamic access sequence is used to get the
135 : // address of _TLS_MODULE_BASE_.
136 : Model = TLSModel::GeneralDynamic;
137 : }
138 : switch (Model) {
139 : case TLSModel::InitialExec:
140 : RefFlags |= AArch64MCExpr::VK_GOTTPREL;
141 : break;
142 : case TLSModel::LocalExec:
143 : RefFlags |= AArch64MCExpr::VK_TPREL;
144 : break;
145 : case TLSModel::LocalDynamic:
146 : RefFlags |= AArch64MCExpr::VK_DTPREL;
147 : break;
148 : case TLSModel::GeneralDynamic:
149 : RefFlags |= AArch64MCExpr::VK_TLSDESC;
150 : break;
151 : }
152 : } else {
153 : // No modifier means this is a generic reference, classified as absolute for
154 : // the cases where it matters (:abs_g0: etc).
155 : RefFlags |= AArch64MCExpr::VK_ABS;
156 : }
157 :
158 8069 : if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
159 2887 : RefFlags |= AArch64MCExpr::VK_PAGE;
160 5182 : else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
161 : AArch64II::MO_PAGEOFF)
162 3293 : RefFlags |= AArch64MCExpr::VK_PAGEOFF;
163 1889 : else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3)
164 31 : RefFlags |= AArch64MCExpr::VK_G3;
165 1858 : else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2)
166 31 : RefFlags |= AArch64MCExpr::VK_G2;
167 1827 : else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1)
168 31 : RefFlags |= AArch64MCExpr::VK_G1;
169 1796 : else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0)
170 31 : RefFlags |= AArch64MCExpr::VK_G0;
171 1765 : else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_HI12)
172 21 : RefFlags |= AArch64MCExpr::VK_HI12;
173 :
174 8069 : if (MO.getTargetFlags() & AArch64II::MO_NC)
175 3357 : RefFlags |= AArch64MCExpr::VK_NC;
176 :
177 : const MCExpr *Expr =
178 8069 : MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
179 8069 : if (!MO.isJTI() && MO.getOffset())
180 50 : Expr = MCBinaryExpr::createAdd(
181 50 : Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
182 :
183 : AArch64MCExpr::VariantKind RefKind;
184 : RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
185 8069 : Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
186 :
187 8069 : return MCOperand::createExpr(Expr);
188 : }
189 :
190 99 : MCOperand AArch64MCInstLower::lowerSymbolOperandCOFF(const MachineOperand &MO,
191 : MCSymbol *Sym) const {
192 : AArch64MCExpr::VariantKind RefKind = AArch64MCExpr::VK_NONE;
193 99 : if (MO.getTargetFlags() & AArch64II::MO_TLS) {
194 10 : if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGEOFF)
195 : RefKind = AArch64MCExpr::VK_SECREL_LO12;
196 5 : else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
197 : AArch64II::MO_HI12)
198 : RefKind = AArch64MCExpr::VK_SECREL_HI12;
199 : }
200 : const MCExpr *Expr =
201 99 : MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
202 99 : if (!MO.isJTI() && MO.getOffset())
203 0 : Expr = MCBinaryExpr::createAdd(
204 0 : Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
205 99 : Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
206 99 : return MCOperand::createExpr(Expr);
207 : }
208 :
209 9523 : MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
210 : MCSymbol *Sym) const {
211 9523 : if (Printer.TM.getTargetTriple().isOSDarwin())
212 1355 : return lowerSymbolOperandDarwin(MO, Sym);
213 8168 : if (Printer.TM.getTargetTriple().isOSBinFormatCOFF())
214 99 : return lowerSymbolOperandCOFF(MO, Sym);
215 :
216 : assert(Printer.TM.getTargetTriple().isOSBinFormatELF() && "Invalid target");
217 8069 : return lowerSymbolOperandELF(MO, Sym);
218 : }
219 :
220 244732 : bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO,
221 : MCOperand &MCOp) const {
222 244732 : switch (MO.getType()) {
223 0 : default:
224 0 : llvm_unreachable("unknown operand type");
225 : case MachineOperand::MO_Register:
226 : // Ignore all implicit register operands.
227 186419 : if (MO.isImplicit())
228 : return false;
229 156872 : MCOp = MCOperand::createReg(MO.getReg());
230 156872 : break;
231 : case MachineOperand::MO_RegisterMask:
232 : // Regmasks are like implicit defs.
233 : return false;
234 45708 : case MachineOperand::MO_Immediate:
235 45708 : MCOp = MCOperand::createImm(MO.getImm());
236 45708 : break;
237 1342 : case MachineOperand::MO_MachineBasicBlock:
238 : MCOp = MCOperand::createExpr(
239 1342 : MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
240 1342 : break;
241 8465 : case MachineOperand::MO_GlobalAddress:
242 8465 : MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
243 8465 : break;
244 631 : case MachineOperand::MO_ExternalSymbol:
245 631 : MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
246 631 : break;
247 32 : case MachineOperand::MO_MCSymbol:
248 32 : MCOp = LowerSymbolOperand(MO, MO.getMCSymbol());
249 32 : break;
250 57 : case MachineOperand::MO_JumpTableIndex:
251 57 : MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
252 57 : break;
253 321 : case MachineOperand::MO_ConstantPoolIndex:
254 321 : MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
255 321 : break;
256 17 : case MachineOperand::MO_BlockAddress:
257 : MCOp = LowerSymbolOperand(
258 17 : MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
259 17 : break;
260 : }
261 : return true;
262 : }
263 :
264 77726 : void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
265 77726 : OutMI.setOpcode(MI->getOpcode());
266 :
267 322131 : for (const MachineOperand &MO : MI->operands()) {
268 : MCOperand MCOp;
269 244405 : if (lowerOperand(MO, MCOp))
270 : OutMI.addOperand(MCOp);
271 : }
272 77726 : }
|