1 //==-- AArch64MCInstLower.cpp - Convert AArch64 MachineInstr to an MCInst --==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains code to lower AArch64 MachineInstrs to their corresponding
13 //===----------------------------------------------------------------------===//
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/TargetLoweringObjectFile.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/TargetMachine.h"
31 extern cl::opt<bool> EnableAArch64ELFLocalDynamicTLSGeneration;
33 AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer)
34 : Ctx(ctx), Printer(printer) {}
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);
49 return Printer.getSymbol(GV);
51 SmallString<128> Name;
53 Printer.TM.getNameWithPrefix(Name, GV,
54 Printer.getObjFileLowering().getMangler());
56 return Ctx.getOrCreateSymbol(Name);
60 AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const {
61 return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
64 MCOperand AArch64MCInstLower::lowerSymbolOperandDarwin(const MachineOperand &MO,
65 MCSymbol *Sym) const {
66 // FIXME: We would like an efficient form for this, so we don't have to do a
67 // lot of extra uniquing.
68 MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
69 if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) {
70 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
71 RefKind = MCSymbolRefExpr::VK_GOTPAGE;
72 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
73 AArch64II::MO_PAGEOFF)
74 RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF;
76 llvm_unreachable("Unexpected target flags with MO_GOT on GV operand");
77 } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) {
78 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
79 RefKind = MCSymbolRefExpr::VK_TLVPPAGE;
80 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
81 AArch64II::MO_PAGEOFF)
82 RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF;
84 llvm_unreachable("Unexpected target flags with MO_TLS on GV operand");
86 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
87 RefKind = MCSymbolRefExpr::VK_PAGE;
88 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
89 AArch64II::MO_PAGEOFF)
90 RefKind = MCSymbolRefExpr::VK_PAGEOFF;
92 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
93 if (!MO.isJTI() && MO.getOffset())
94 Expr = MCBinaryExpr::createAdd(
95 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
96 return MCOperand::createExpr(Expr);
99 MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
100 MCSymbol *Sym) const {
101 uint32_t RefFlags = 0;
103 if (MO.getTargetFlags() & AArch64II::MO_GOT)
104 RefFlags |= AArch64MCExpr::VK_GOT;
105 else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
106 TLSModel::Model Model;
108 const GlobalValue *GV = MO.getGlobal();
109 Model = Printer.TM.getTLSModel(GV);
110 if (!EnableAArch64ELFLocalDynamicTLSGeneration &&
111 Model == TLSModel::LocalDynamic)
112 Model = TLSModel::GeneralDynamic;
115 assert(MO.isSymbol() &&
116 StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" &&
117 "unexpected external TLS symbol");
118 // The general dynamic access sequence is used to get the
119 // address of _TLS_MODULE_BASE_.
120 Model = TLSModel::GeneralDynamic;
123 case TLSModel::InitialExec:
124 RefFlags |= AArch64MCExpr::VK_GOTTPREL;
126 case TLSModel::LocalExec:
127 RefFlags |= AArch64MCExpr::VK_TPREL;
129 case TLSModel::LocalDynamic:
130 RefFlags |= AArch64MCExpr::VK_DTPREL;
132 case TLSModel::GeneralDynamic:
133 RefFlags |= AArch64MCExpr::VK_TLSDESC;
137 // No modifier means this is a generic reference, classified as absolute for
138 // the cases where it matters (:abs_g0: etc).
139 RefFlags |= AArch64MCExpr::VK_ABS;
142 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
143 RefFlags |= AArch64MCExpr::VK_PAGE;
144 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
145 AArch64II::MO_PAGEOFF)
146 RefFlags |= AArch64MCExpr::VK_PAGEOFF;
147 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3)
148 RefFlags |= AArch64MCExpr::VK_G3;
149 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2)
150 RefFlags |= AArch64MCExpr::VK_G2;
151 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1)
152 RefFlags |= AArch64MCExpr::VK_G1;
153 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0)
154 RefFlags |= AArch64MCExpr::VK_G0;
155 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_HI12)
156 RefFlags |= AArch64MCExpr::VK_HI12;
158 if (MO.getTargetFlags() & AArch64II::MO_NC)
159 RefFlags |= AArch64MCExpr::VK_NC;
162 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
163 if (!MO.isJTI() && MO.getOffset())
164 Expr = MCBinaryExpr::createAdd(
165 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
167 AArch64MCExpr::VariantKind RefKind;
168 RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
169 Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
171 return MCOperand::createExpr(Expr);
174 MCOperand AArch64MCInstLower::lowerSymbolOperandCOFF(const MachineOperand &MO,
175 MCSymbol *Sym) const {
176 MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
177 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
178 if (!MO.isJTI() && MO.getOffset())
179 Expr = MCBinaryExpr::createAdd(
180 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
181 return MCOperand::createExpr(Expr);
184 MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
185 MCSymbol *Sym) const {
186 if (Printer.TM.getTargetTriple().isOSDarwin())
187 return lowerSymbolOperandDarwin(MO, Sym);
188 if (Printer.TM.getTargetTriple().isOSBinFormatCOFF())
189 return lowerSymbolOperandCOFF(MO, Sym);
191 assert(Printer.TM.getTargetTriple().isOSBinFormatELF() && "Invalid target");
192 return lowerSymbolOperandELF(MO, Sym);
195 bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO,
196 MCOperand &MCOp) const {
197 switch (MO.getType()) {
199 llvm_unreachable("unknown operand type");
200 case MachineOperand::MO_Register:
201 // Ignore all implicit register operands.
204 MCOp = MCOperand::createReg(MO.getReg());
206 case MachineOperand::MO_RegisterMask:
207 // Regmasks are like implicit defs.
209 case MachineOperand::MO_Immediate:
210 MCOp = MCOperand::createImm(MO.getImm());
212 case MachineOperand::MO_MachineBasicBlock:
213 MCOp = MCOperand::createExpr(
214 MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
216 case MachineOperand::MO_GlobalAddress:
217 MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
219 case MachineOperand::MO_ExternalSymbol:
220 MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
222 case MachineOperand::MO_MCSymbol:
223 MCOp = LowerSymbolOperand(MO, MO.getMCSymbol());
225 case MachineOperand::MO_JumpTableIndex:
226 MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
228 case MachineOperand::MO_ConstantPoolIndex:
229 MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
231 case MachineOperand::MO_BlockAddress:
232 MCOp = LowerSymbolOperand(
233 MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
239 void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
240 OutMI.setOpcode(MI->getOpcode());
242 for (const MachineOperand &MO : MI->operands()) {
244 if (lowerOperand(MO, MCOp))
245 OutMI.addOperand(MCOp);