[PowerPC] Materialize more constants with CR-field set in late peephole
[llvm-core.git] / lib / Target / AArch64 / AArch64MCInstLower.cpp
blob6c02635859332ec6426165d12bcc68e9786bfe6d
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.
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"
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);
48 if (!IsIndirect)
49 return Printer.getSymbol(GV);
51 SmallString<128> Name;
52 Name = "__imp_";
53 Printer.TM.getNameWithPrefix(Name, GV,
54 Printer.getObjFileLowering().getMangler());
56 return Ctx.getOrCreateSymbol(Name);
59 MCSymbol *
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;
75 else
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;
83 else
84 llvm_unreachable("Unexpected target flags with MO_TLS on GV operand");
85 } else {
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;
107 if (MO.isGlobal()) {
108 const GlobalValue *GV = MO.getGlobal();
109 Model = Printer.TM.getTLSModel(GV);
110 if (!EnableAArch64ELFLocalDynamicTLSGeneration &&
111 Model == TLSModel::LocalDynamic)
112 Model = TLSModel::GeneralDynamic;
114 } else {
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;
122 switch (Model) {
123 case TLSModel::InitialExec:
124 RefFlags |= AArch64MCExpr::VK_GOTTPREL;
125 break;
126 case TLSModel::LocalExec:
127 RefFlags |= AArch64MCExpr::VK_TPREL;
128 break;
129 case TLSModel::LocalDynamic:
130 RefFlags |= AArch64MCExpr::VK_DTPREL;
131 break;
132 case TLSModel::GeneralDynamic:
133 RefFlags |= AArch64MCExpr::VK_TLSDESC;
134 break;
136 } else {
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;
161 const MCExpr *Expr =
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) ==
181 AArch64II::MO_HI12)
182 RefKind = AArch64MCExpr::VK_SECREL_HI12;
184 const MCExpr *Expr =
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()) {
207 default:
208 llvm_unreachable("unknown operand type");
209 case MachineOperand::MO_Register:
210 // Ignore all implicit register operands.
211 if (MO.isImplicit())
212 return false;
213 MCOp = MCOperand::createReg(MO.getReg());
214 break;
215 case MachineOperand::MO_RegisterMask:
216 // Regmasks are like implicit defs.
217 return false;
218 case MachineOperand::MO_Immediate:
219 MCOp = MCOperand::createImm(MO.getImm());
220 break;
221 case MachineOperand::MO_MachineBasicBlock:
222 MCOp = MCOperand::createExpr(
223 MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
224 break;
225 case MachineOperand::MO_GlobalAddress:
226 MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
227 break;
228 case MachineOperand::MO_ExternalSymbol:
229 MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
230 break;
231 case MachineOperand::MO_MCSymbol:
232 MCOp = LowerSymbolOperand(MO, MO.getMCSymbol());
233 break;
234 case MachineOperand::MO_JumpTableIndex:
235 MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
236 break;
237 case MachineOperand::MO_ConstantPoolIndex:
238 MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
239 break;
240 case MachineOperand::MO_BlockAddress:
241 MCOp = LowerSymbolOperand(
242 MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
243 break;
245 return true;
248 void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
249 OutMI.setOpcode(MI->getOpcode());
251 for (const MachineOperand &MO : MI->operands()) {
252 MCOperand MCOp;
253 if (lowerOperand(MO, MCOp))
254 OutMI.addOperand(MCOp);