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/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"
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 AArch64MCExpr::VariantKind RefKind
= AArch64MCExpr::VK_NONE
;
177 if (MO
.getTargetFlags() & AArch64II::MO_TLS
) {
178 if ((MO
.getTargetFlags() & AArch64II::MO_FRAGMENT
) == AArch64II::MO_PAGEOFF
)
179 RefKind
= AArch64MCExpr::VK_SECREL_LO12
;
180 else if ((MO
.getTargetFlags() & AArch64II::MO_FRAGMENT
) ==
182 RefKind
= AArch64MCExpr::VK_SECREL_HI12
;
185 MCSymbolRefExpr::create(Sym
, MCSymbolRefExpr::VK_None
, Ctx
);
186 if (!MO
.isJTI() && MO
.getOffset())
187 Expr
= MCBinaryExpr::createAdd(
188 Expr
, MCConstantExpr::create(MO
.getOffset(), Ctx
), Ctx
);
189 Expr
= AArch64MCExpr::create(Expr
, RefKind
, Ctx
);
190 return MCOperand::createExpr(Expr
);
193 MCOperand
AArch64MCInstLower::LowerSymbolOperand(const MachineOperand
&MO
,
194 MCSymbol
*Sym
) const {
195 if (Printer
.TM
.getTargetTriple().isOSDarwin())
196 return lowerSymbolOperandDarwin(MO
, Sym
);
197 if (Printer
.TM
.getTargetTriple().isOSBinFormatCOFF())
198 return lowerSymbolOperandCOFF(MO
, Sym
);
200 assert(Printer
.TM
.getTargetTriple().isOSBinFormatELF() && "Invalid target");
201 return lowerSymbolOperandELF(MO
, Sym
);
204 bool AArch64MCInstLower::lowerOperand(const MachineOperand
&MO
,
205 MCOperand
&MCOp
) const {
206 switch (MO
.getType()) {
208 llvm_unreachable("unknown operand type");
209 case MachineOperand::MO_Register
:
210 // Ignore all implicit register operands.
213 MCOp
= MCOperand::createReg(MO
.getReg());
215 case MachineOperand::MO_RegisterMask
:
216 // Regmasks are like implicit defs.
218 case MachineOperand::MO_Immediate
:
219 MCOp
= MCOperand::createImm(MO
.getImm());
221 case MachineOperand::MO_MachineBasicBlock
:
222 MCOp
= MCOperand::createExpr(
223 MCSymbolRefExpr::create(MO
.getMBB()->getSymbol(), Ctx
));
225 case MachineOperand::MO_GlobalAddress
:
226 MCOp
= LowerSymbolOperand(MO
, GetGlobalAddressSymbol(MO
));
228 case MachineOperand::MO_ExternalSymbol
:
229 MCOp
= LowerSymbolOperand(MO
, GetExternalSymbolSymbol(MO
));
231 case MachineOperand::MO_MCSymbol
:
232 MCOp
= LowerSymbolOperand(MO
, MO
.getMCSymbol());
234 case MachineOperand::MO_JumpTableIndex
:
235 MCOp
= LowerSymbolOperand(MO
, Printer
.GetJTISymbol(MO
.getIndex()));
237 case MachineOperand::MO_ConstantPoolIndex
:
238 MCOp
= LowerSymbolOperand(MO
, Printer
.GetCPISymbol(MO
.getIndex()));
240 case MachineOperand::MO_BlockAddress
:
241 MCOp
= LowerSymbolOperand(
242 MO
, Printer
.GetBlockAddressSymbol(MO
.getBlockAddress()));
248 void AArch64MCInstLower::Lower(const MachineInstr
*MI
, MCInst
&OutMI
) const {
249 OutMI
.setOpcode(MI
->getOpcode());
251 for (const MachineOperand
&MO
: MI
->operands()) {
253 if (lowerOperand(MO
, MCOp
))
254 OutMI
.addOperand(MCOp
);