1*9880d681SAndroid Build Coastguard Worker //==-- AArch64MCInstLower.cpp - Convert AArch64 MachineInstr to an MCInst --==//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file contains code to lower AArch64 MachineInstrs to their corresponding
11*9880d681SAndroid Build Coastguard Worker // MCInst records.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Worker #include "AArch64MCInstLower.h"
16*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/AArch64MCExpr.h"
17*9880d681SAndroid Build Coastguard Worker #include "Utils/AArch64BaseInfo.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/AsmPrinter.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineBasicBlock.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstr.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Mangler.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCExpr.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInst.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CodeGen.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetMachine.h"
27*9880d681SAndroid Build Coastguard Worker using namespace llvm;
28*9880d681SAndroid Build Coastguard Worker
29*9880d681SAndroid Build Coastguard Worker extern cl::opt<bool> EnableAArch64ELFLocalDynamicTLSGeneration;
30*9880d681SAndroid Build Coastguard Worker
AArch64MCInstLower(MCContext & ctx,AsmPrinter & printer)31*9880d681SAndroid Build Coastguard Worker AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer)
32*9880d681SAndroid Build Coastguard Worker : Ctx(ctx), Printer(printer), TargetTriple(printer.getTargetTriple()) {}
33*9880d681SAndroid Build Coastguard Worker
34*9880d681SAndroid Build Coastguard Worker MCSymbol *
GetGlobalAddressSymbol(const MachineOperand & MO) const35*9880d681SAndroid Build Coastguard Worker AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
36*9880d681SAndroid Build Coastguard Worker return Printer.getSymbol(MO.getGlobal());
37*9880d681SAndroid Build Coastguard Worker }
38*9880d681SAndroid Build Coastguard Worker
39*9880d681SAndroid Build Coastguard Worker MCSymbol *
GetExternalSymbolSymbol(const MachineOperand & MO) const40*9880d681SAndroid Build Coastguard Worker AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const {
41*9880d681SAndroid Build Coastguard Worker return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
42*9880d681SAndroid Build Coastguard Worker }
43*9880d681SAndroid Build Coastguard Worker
lowerSymbolOperandDarwin(const MachineOperand & MO,MCSymbol * Sym) const44*9880d681SAndroid Build Coastguard Worker MCOperand AArch64MCInstLower::lowerSymbolOperandDarwin(const MachineOperand &MO,
45*9880d681SAndroid Build Coastguard Worker MCSymbol *Sym) const {
46*9880d681SAndroid Build Coastguard Worker // FIXME: We would like an efficient form for this, so we don't have to do a
47*9880d681SAndroid Build Coastguard Worker // lot of extra uniquing.
48*9880d681SAndroid Build Coastguard Worker MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
49*9880d681SAndroid Build Coastguard Worker if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) {
50*9880d681SAndroid Build Coastguard Worker if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
51*9880d681SAndroid Build Coastguard Worker RefKind = MCSymbolRefExpr::VK_GOTPAGE;
52*9880d681SAndroid Build Coastguard Worker else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
53*9880d681SAndroid Build Coastguard Worker AArch64II::MO_PAGEOFF)
54*9880d681SAndroid Build Coastguard Worker RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF;
55*9880d681SAndroid Build Coastguard Worker else
56*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unexpected target flags with MO_GOT on GV operand");
57*9880d681SAndroid Build Coastguard Worker } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) {
58*9880d681SAndroid Build Coastguard Worker if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
59*9880d681SAndroid Build Coastguard Worker RefKind = MCSymbolRefExpr::VK_TLVPPAGE;
60*9880d681SAndroid Build Coastguard Worker else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
61*9880d681SAndroid Build Coastguard Worker AArch64II::MO_PAGEOFF)
62*9880d681SAndroid Build Coastguard Worker RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF;
63*9880d681SAndroid Build Coastguard Worker else
64*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unexpected target flags with MO_TLS on GV operand");
65*9880d681SAndroid Build Coastguard Worker } else {
66*9880d681SAndroid Build Coastguard Worker if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
67*9880d681SAndroid Build Coastguard Worker RefKind = MCSymbolRefExpr::VK_PAGE;
68*9880d681SAndroid Build Coastguard Worker else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
69*9880d681SAndroid Build Coastguard Worker AArch64II::MO_PAGEOFF)
70*9880d681SAndroid Build Coastguard Worker RefKind = MCSymbolRefExpr::VK_PAGEOFF;
71*9880d681SAndroid Build Coastguard Worker }
72*9880d681SAndroid Build Coastguard Worker const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
73*9880d681SAndroid Build Coastguard Worker if (!MO.isJTI() && MO.getOffset())
74*9880d681SAndroid Build Coastguard Worker Expr = MCBinaryExpr::createAdd(
75*9880d681SAndroid Build Coastguard Worker Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
76*9880d681SAndroid Build Coastguard Worker return MCOperand::createExpr(Expr);
77*9880d681SAndroid Build Coastguard Worker }
78*9880d681SAndroid Build Coastguard Worker
lowerSymbolOperandELF(const MachineOperand & MO,MCSymbol * Sym) const79*9880d681SAndroid Build Coastguard Worker MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
80*9880d681SAndroid Build Coastguard Worker MCSymbol *Sym) const {
81*9880d681SAndroid Build Coastguard Worker uint32_t RefFlags = 0;
82*9880d681SAndroid Build Coastguard Worker
83*9880d681SAndroid Build Coastguard Worker if (MO.getTargetFlags() & AArch64II::MO_GOT)
84*9880d681SAndroid Build Coastguard Worker RefFlags |= AArch64MCExpr::VK_GOT;
85*9880d681SAndroid Build Coastguard Worker else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
86*9880d681SAndroid Build Coastguard Worker TLSModel::Model Model;
87*9880d681SAndroid Build Coastguard Worker if (MO.isGlobal()) {
88*9880d681SAndroid Build Coastguard Worker const GlobalValue *GV = MO.getGlobal();
89*9880d681SAndroid Build Coastguard Worker Model = Printer.TM.getTLSModel(GV);
90*9880d681SAndroid Build Coastguard Worker if (!EnableAArch64ELFLocalDynamicTLSGeneration &&
91*9880d681SAndroid Build Coastguard Worker Model == TLSModel::LocalDynamic)
92*9880d681SAndroid Build Coastguard Worker Model = TLSModel::GeneralDynamic;
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Worker } else {
95*9880d681SAndroid Build Coastguard Worker assert(MO.isSymbol() &&
96*9880d681SAndroid Build Coastguard Worker StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" &&
97*9880d681SAndroid Build Coastguard Worker "unexpected external TLS symbol");
98*9880d681SAndroid Build Coastguard Worker // The general dynamic access sequence is used to get the
99*9880d681SAndroid Build Coastguard Worker // address of _TLS_MODULE_BASE_.
100*9880d681SAndroid Build Coastguard Worker Model = TLSModel::GeneralDynamic;
101*9880d681SAndroid Build Coastguard Worker }
102*9880d681SAndroid Build Coastguard Worker switch (Model) {
103*9880d681SAndroid Build Coastguard Worker case TLSModel::InitialExec:
104*9880d681SAndroid Build Coastguard Worker RefFlags |= AArch64MCExpr::VK_GOTTPREL;
105*9880d681SAndroid Build Coastguard Worker break;
106*9880d681SAndroid Build Coastguard Worker case TLSModel::LocalExec:
107*9880d681SAndroid Build Coastguard Worker RefFlags |= AArch64MCExpr::VK_TPREL;
108*9880d681SAndroid Build Coastguard Worker break;
109*9880d681SAndroid Build Coastguard Worker case TLSModel::LocalDynamic:
110*9880d681SAndroid Build Coastguard Worker RefFlags |= AArch64MCExpr::VK_DTPREL;
111*9880d681SAndroid Build Coastguard Worker break;
112*9880d681SAndroid Build Coastguard Worker case TLSModel::GeneralDynamic:
113*9880d681SAndroid Build Coastguard Worker RefFlags |= AArch64MCExpr::VK_TLSDESC;
114*9880d681SAndroid Build Coastguard Worker break;
115*9880d681SAndroid Build Coastguard Worker }
116*9880d681SAndroid Build Coastguard Worker } else {
117*9880d681SAndroid Build Coastguard Worker // No modifier means this is a generic reference, classified as absolute for
118*9880d681SAndroid Build Coastguard Worker // the cases where it matters (:abs_g0: etc).
119*9880d681SAndroid Build Coastguard Worker RefFlags |= AArch64MCExpr::VK_ABS;
120*9880d681SAndroid Build Coastguard Worker }
121*9880d681SAndroid Build Coastguard Worker
122*9880d681SAndroid Build Coastguard Worker if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
123*9880d681SAndroid Build Coastguard Worker RefFlags |= AArch64MCExpr::VK_PAGE;
124*9880d681SAndroid Build Coastguard Worker else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
125*9880d681SAndroid Build Coastguard Worker AArch64II::MO_PAGEOFF)
126*9880d681SAndroid Build Coastguard Worker RefFlags |= AArch64MCExpr::VK_PAGEOFF;
127*9880d681SAndroid Build Coastguard Worker else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3)
128*9880d681SAndroid Build Coastguard Worker RefFlags |= AArch64MCExpr::VK_G3;
129*9880d681SAndroid Build Coastguard Worker else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2)
130*9880d681SAndroid Build Coastguard Worker RefFlags |= AArch64MCExpr::VK_G2;
131*9880d681SAndroid Build Coastguard Worker else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1)
132*9880d681SAndroid Build Coastguard Worker RefFlags |= AArch64MCExpr::VK_G1;
133*9880d681SAndroid Build Coastguard Worker else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0)
134*9880d681SAndroid Build Coastguard Worker RefFlags |= AArch64MCExpr::VK_G0;
135*9880d681SAndroid Build Coastguard Worker else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_HI12)
136*9880d681SAndroid Build Coastguard Worker RefFlags |= AArch64MCExpr::VK_HI12;
137*9880d681SAndroid Build Coastguard Worker
138*9880d681SAndroid Build Coastguard Worker if (MO.getTargetFlags() & AArch64II::MO_NC)
139*9880d681SAndroid Build Coastguard Worker RefFlags |= AArch64MCExpr::VK_NC;
140*9880d681SAndroid Build Coastguard Worker
141*9880d681SAndroid Build Coastguard Worker const MCExpr *Expr =
142*9880d681SAndroid Build Coastguard Worker MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
143*9880d681SAndroid Build Coastguard Worker if (!MO.isJTI() && MO.getOffset())
144*9880d681SAndroid Build Coastguard Worker Expr = MCBinaryExpr::createAdd(
145*9880d681SAndroid Build Coastguard Worker Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
146*9880d681SAndroid Build Coastguard Worker
147*9880d681SAndroid Build Coastguard Worker AArch64MCExpr::VariantKind RefKind;
148*9880d681SAndroid Build Coastguard Worker RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
149*9880d681SAndroid Build Coastguard Worker Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
150*9880d681SAndroid Build Coastguard Worker
151*9880d681SAndroid Build Coastguard Worker return MCOperand::createExpr(Expr);
152*9880d681SAndroid Build Coastguard Worker }
153*9880d681SAndroid Build Coastguard Worker
LowerSymbolOperand(const MachineOperand & MO,MCSymbol * Sym) const154*9880d681SAndroid Build Coastguard Worker MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
155*9880d681SAndroid Build Coastguard Worker MCSymbol *Sym) const {
156*9880d681SAndroid Build Coastguard Worker if (TargetTriple.isOSDarwin())
157*9880d681SAndroid Build Coastguard Worker return lowerSymbolOperandDarwin(MO, Sym);
158*9880d681SAndroid Build Coastguard Worker
159*9880d681SAndroid Build Coastguard Worker assert(TargetTriple.isOSBinFormatELF() && "Expect Darwin or ELF target");
160*9880d681SAndroid Build Coastguard Worker return lowerSymbolOperandELF(MO, Sym);
161*9880d681SAndroid Build Coastguard Worker }
162*9880d681SAndroid Build Coastguard Worker
lowerOperand(const MachineOperand & MO,MCOperand & MCOp) const163*9880d681SAndroid Build Coastguard Worker bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO,
164*9880d681SAndroid Build Coastguard Worker MCOperand &MCOp) const {
165*9880d681SAndroid Build Coastguard Worker switch (MO.getType()) {
166*9880d681SAndroid Build Coastguard Worker default:
167*9880d681SAndroid Build Coastguard Worker llvm_unreachable("unknown operand type");
168*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_Register:
169*9880d681SAndroid Build Coastguard Worker // Ignore all implicit register operands.
170*9880d681SAndroid Build Coastguard Worker if (MO.isImplicit())
171*9880d681SAndroid Build Coastguard Worker return false;
172*9880d681SAndroid Build Coastguard Worker MCOp = MCOperand::createReg(MO.getReg());
173*9880d681SAndroid Build Coastguard Worker break;
174*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_RegisterMask:
175*9880d681SAndroid Build Coastguard Worker // Regmasks are like implicit defs.
176*9880d681SAndroid Build Coastguard Worker return false;
177*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_Immediate:
178*9880d681SAndroid Build Coastguard Worker MCOp = MCOperand::createImm(MO.getImm());
179*9880d681SAndroid Build Coastguard Worker break;
180*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_MachineBasicBlock:
181*9880d681SAndroid Build Coastguard Worker MCOp = MCOperand::createExpr(
182*9880d681SAndroid Build Coastguard Worker MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
183*9880d681SAndroid Build Coastguard Worker break;
184*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_GlobalAddress:
185*9880d681SAndroid Build Coastguard Worker MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
186*9880d681SAndroid Build Coastguard Worker break;
187*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_ExternalSymbol:
188*9880d681SAndroid Build Coastguard Worker MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
189*9880d681SAndroid Build Coastguard Worker break;
190*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_MCSymbol:
191*9880d681SAndroid Build Coastguard Worker MCOp = LowerSymbolOperand(MO, MO.getMCSymbol());
192*9880d681SAndroid Build Coastguard Worker break;
193*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_JumpTableIndex:
194*9880d681SAndroid Build Coastguard Worker MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
195*9880d681SAndroid Build Coastguard Worker break;
196*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_ConstantPoolIndex:
197*9880d681SAndroid Build Coastguard Worker MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
198*9880d681SAndroid Build Coastguard Worker break;
199*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_BlockAddress:
200*9880d681SAndroid Build Coastguard Worker MCOp = LowerSymbolOperand(
201*9880d681SAndroid Build Coastguard Worker MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
202*9880d681SAndroid Build Coastguard Worker break;
203*9880d681SAndroid Build Coastguard Worker }
204*9880d681SAndroid Build Coastguard Worker return true;
205*9880d681SAndroid Build Coastguard Worker }
206*9880d681SAndroid Build Coastguard Worker
Lower(const MachineInstr * MI,MCInst & OutMI) const207*9880d681SAndroid Build Coastguard Worker void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
208*9880d681SAndroid Build Coastguard Worker OutMI.setOpcode(MI->getOpcode());
209*9880d681SAndroid Build Coastguard Worker
210*9880d681SAndroid Build Coastguard Worker for (const MachineOperand &MO : MI->operands()) {
211*9880d681SAndroid Build Coastguard Worker MCOperand MCOp;
212*9880d681SAndroid Build Coastguard Worker if (lowerOperand(MO, MCOp))
213*9880d681SAndroid Build Coastguard Worker OutMI.addOperand(MCOp);
214*9880d681SAndroid Build Coastguard Worker }
215*9880d681SAndroid Build Coastguard Worker }
216