blob: 25bcaea943366421ccc24964e0ec6b110968d038 [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//==-- 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"
David Blaikieb3bde2e2017-11-17 01:07:10 +000021#include "llvm/CodeGen/TargetLoweringObjectFile.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000022#include "llvm/IR/Mangler.h"
Martin Storsjo373c8ef2017-10-25 07:25:18 +000023#include "llvm/MC/MCContext.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000024#include "llvm/MC/MCExpr.h"
25#include "llvm/MC/MCInst.h"
26#include "llvm/Support/CodeGen.h"
Kristof Beylsaea84612015-03-04 09:12:08 +000027#include "llvm/Support/CommandLine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000028#include "llvm/Target/TargetMachine.h"
29using namespace llvm;
30
Kristof Beylsaea84612015-03-04 09:12:08 +000031extern cl::opt<bool> EnableAArch64ELFLocalDynamicTLSGeneration;
32
Alexey Samsonov96b02d12014-08-19 21:51:08 +000033AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer)
Eric Christopher98983d02016-10-01 01:50:25 +000034 : Ctx(ctx), Printer(printer) {}
Tim Northover3b0846e2014-05-24 12:50:23 +000035
36MCSymbol *
37AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
Martin Storsjo373c8ef2017-10-25 07:25:18 +000038 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);
43
44 assert(TheTriple.isOSWindows() &&
45 "Windows is the only supported COFF target");
46
47 bool IsIndirect = (TargetFlags & AArch64II::MO_DLLIMPORT);
48 if (!IsIndirect)
49 return Printer.getSymbol(GV);
50
51 SmallString<128> Name;
52 Name = "__imp_";
53 Printer.TM.getNameWithPrefix(Name, GV,
54 Printer.getObjFileLowering().getMangler());
55
56 return Ctx.getOrCreateSymbol(Name);
Tim Northover3b0846e2014-05-24 12:50:23 +000057}
58
59MCSymbol *
60AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const {
61 return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
62}
63
64MCOperand 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
Craig Topper2a30d782014-06-18 05:05:13 +000076 llvm_unreachable("Unexpected target flags with MO_GOT on GV operand");
Tim Northover3b0846e2014-05-24 12:50:23 +000077 } 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;
91 }
Jim Grosbach13760bd2015-05-30 01:25:56 +000092 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +000093 if (!MO.isJTI() && MO.getOffset())
Jim Grosbach13760bd2015-05-30 01:25:56 +000094 Expr = MCBinaryExpr::createAdd(
95 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
Jim Grosbache9119e42015-05-13 18:37:00 +000096 return MCOperand::createExpr(Expr);
Tim Northover3b0846e2014-05-24 12:50:23 +000097}
98
99MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
100 MCSymbol *Sym) const {
101 uint32_t RefFlags = 0;
102
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);
Kristof Beylsaea84612015-03-04 09:12:08 +0000110 if (!EnableAArch64ELFLocalDynamicTLSGeneration &&
111 Model == TLSModel::LocalDynamic)
112 Model = TLSModel::GeneralDynamic;
113
Tim Northover3b0846e2014-05-24 12:50:23 +0000114 } else {
115 assert(MO.isSymbol() &&
116 StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" &&
117 "unexpected external TLS symbol");
Kristof Beylsaea84612015-03-04 09:12:08 +0000118 // The general dynamic access sequence is used to get the
119 // address of _TLS_MODULE_BASE_.
Tim Northover3b0846e2014-05-24 12:50:23 +0000120 Model = TLSModel::GeneralDynamic;
121 }
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;
135 }
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;
140 }
141
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;
Kristof Beylsaea84612015-03-04 09:12:08 +0000155 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_HI12)
156 RefFlags |= AArch64MCExpr::VK_HI12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000157
158 if (MO.getTargetFlags() & AArch64II::MO_NC)
159 RefFlags |= AArch64MCExpr::VK_NC;
160
161 const MCExpr *Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +0000162 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +0000163 if (!MO.isJTI() && MO.getOffset())
Jim Grosbach13760bd2015-05-30 01:25:56 +0000164 Expr = MCBinaryExpr::createAdd(
165 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +0000166
167 AArch64MCExpr::VariantKind RefKind;
168 RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
Jim Grosbach13760bd2015-05-30 01:25:56 +0000169 Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +0000170
Jim Grosbache9119e42015-05-13 18:37:00 +0000171 return MCOperand::createExpr(Expr);
Tim Northover3b0846e2014-05-24 12:50:23 +0000172}
173
Mandeep Singh Grang0c721722017-06-27 23:58:19 +0000174MCOperand AArch64MCInstLower::lowerSymbolOperandCOFF(const MachineOperand &MO,
175 MCSymbol *Sym) const {
Martin Storsjocc240962018-03-10 19:05:21 +0000176 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;
183 }
184 const MCExpr *Expr =
185 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
Mandeep Singh Grang0c721722017-06-27 23:58:19 +0000186 if (!MO.isJTI() && MO.getOffset())
187 Expr = MCBinaryExpr::createAdd(
188 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
Martin Storsjocc240962018-03-10 19:05:21 +0000189 Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
Mandeep Singh Grang0c721722017-06-27 23:58:19 +0000190 return MCOperand::createExpr(Expr);
191}
192
Tim Northover3b0846e2014-05-24 12:50:23 +0000193MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
194 MCSymbol *Sym) const {
Eric Christopher98983d02016-10-01 01:50:25 +0000195 if (Printer.TM.getTargetTriple().isOSDarwin())
Tim Northover3b0846e2014-05-24 12:50:23 +0000196 return lowerSymbolOperandDarwin(MO, Sym);
Mandeep Singh Grang0c721722017-06-27 23:58:19 +0000197 if (Printer.TM.getTargetTriple().isOSBinFormatCOFF())
198 return lowerSymbolOperandCOFF(MO, Sym);
Tim Northover3b0846e2014-05-24 12:50:23 +0000199
Mandeep Singh Grang6f61e232017-06-28 19:37:38 +0000200 assert(Printer.TM.getTargetTriple().isOSBinFormatELF() && "Invalid target");
Tim Northover3b0846e2014-05-24 12:50:23 +0000201 return lowerSymbolOperandELF(MO, Sym);
202}
203
204bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO,
205 MCOperand &MCOp) const {
206 switch (MO.getType()) {
207 default:
Craig Topper2a30d782014-06-18 05:05:13 +0000208 llvm_unreachable("unknown operand type");
Tim Northover3b0846e2014-05-24 12:50:23 +0000209 case MachineOperand::MO_Register:
210 // Ignore all implicit register operands.
211 if (MO.isImplicit())
212 return false;
Jim Grosbache9119e42015-05-13 18:37:00 +0000213 MCOp = MCOperand::createReg(MO.getReg());
Tim Northover3b0846e2014-05-24 12:50:23 +0000214 break;
215 case MachineOperand::MO_RegisterMask:
216 // Regmasks are like implicit defs.
217 return false;
218 case MachineOperand::MO_Immediate:
Jim Grosbache9119e42015-05-13 18:37:00 +0000219 MCOp = MCOperand::createImm(MO.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +0000220 break;
221 case MachineOperand::MO_MachineBasicBlock:
Jim Grosbache9119e42015-05-13 18:37:00 +0000222 MCOp = MCOperand::createExpr(
Jim Grosbach13760bd2015-05-30 01:25:56 +0000223 MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +0000224 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;
Rafael Espindolace4c2bc2015-06-23 12:21:54 +0000231 case MachineOperand::MO_MCSymbol:
232 MCOp = LowerSymbolOperand(MO, MO.getMCSymbol());
233 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000234 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;
244 }
245 return true;
246}
247
248void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
249 OutMI.setOpcode(MI->getOpcode());
250
Pete Cooper7be8f8f2015-08-03 19:04:32 +0000251 for (const MachineOperand &MO : MI->operands()) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000252 MCOperand MCOp;
Pete Cooper7be8f8f2015-08-03 19:04:32 +0000253 if (lowerOperand(MO, MCOp))
Tim Northover3b0846e2014-05-24 12:50:23 +0000254 OutMI.addOperand(MCOp);
255 }
256}