blob: 45083df7ab4573752903a9308c0bcedb1f608eed [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"
21#include "llvm/IR/Mangler.h"
22#include "llvm/MC/MCExpr.h"
23#include "llvm/MC/MCInst.h"
24#include "llvm/Support/CodeGen.h"
Kristof Beylsaea84612015-03-04 09:12:08 +000025#include "llvm/Support/CommandLine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000026#include "llvm/Target/TargetMachine.h"
27using namespace llvm;
28
Kristof Beylsaea84612015-03-04 09:12:08 +000029extern cl::opt<bool> EnableAArch64ELFLocalDynamicTLSGeneration;
30
Alexey Samsonov96b02d12014-08-19 21:51:08 +000031AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer)
Eric Christopher98983d02016-10-01 01:50:25 +000032 : Ctx(ctx), Printer(printer) {}
Tim Northover3b0846e2014-05-24 12:50:23 +000033
34MCSymbol *
35AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
36 return Printer.getSymbol(MO.getGlobal());
37}
38
39MCSymbol *
40AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const {
41 return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
42}
43
44MCOperand AArch64MCInstLower::lowerSymbolOperandDarwin(const MachineOperand &MO,
45 MCSymbol *Sym) const {
46 // FIXME: We would like an efficient form for this, so we don't have to do a
47 // lot of extra uniquing.
48 MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
49 if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) {
50 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
51 RefKind = MCSymbolRefExpr::VK_GOTPAGE;
52 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
53 AArch64II::MO_PAGEOFF)
54 RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF;
55 else
Craig Topper2a30d782014-06-18 05:05:13 +000056 llvm_unreachable("Unexpected target flags with MO_GOT on GV operand");
Tim Northover3b0846e2014-05-24 12:50:23 +000057 } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) {
58 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
59 RefKind = MCSymbolRefExpr::VK_TLVPPAGE;
60 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
61 AArch64II::MO_PAGEOFF)
62 RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF;
63 else
64 llvm_unreachable("Unexpected target flags with MO_TLS on GV operand");
65 } else {
66 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
67 RefKind = MCSymbolRefExpr::VK_PAGE;
68 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
69 AArch64II::MO_PAGEOFF)
70 RefKind = MCSymbolRefExpr::VK_PAGEOFF;
71 }
Jim Grosbach13760bd2015-05-30 01:25:56 +000072 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +000073 if (!MO.isJTI() && MO.getOffset())
Jim Grosbach13760bd2015-05-30 01:25:56 +000074 Expr = MCBinaryExpr::createAdd(
75 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
Jim Grosbache9119e42015-05-13 18:37:00 +000076 return MCOperand::createExpr(Expr);
Tim Northover3b0846e2014-05-24 12:50:23 +000077}
78
79MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
80 MCSymbol *Sym) const {
81 uint32_t RefFlags = 0;
82
83 if (MO.getTargetFlags() & AArch64II::MO_GOT)
84 RefFlags |= AArch64MCExpr::VK_GOT;
85 else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
86 TLSModel::Model Model;
87 if (MO.isGlobal()) {
88 const GlobalValue *GV = MO.getGlobal();
89 Model = Printer.TM.getTLSModel(GV);
Kristof Beylsaea84612015-03-04 09:12:08 +000090 if (!EnableAArch64ELFLocalDynamicTLSGeneration &&
91 Model == TLSModel::LocalDynamic)
92 Model = TLSModel::GeneralDynamic;
93
Tim Northover3b0846e2014-05-24 12:50:23 +000094 } else {
95 assert(MO.isSymbol() &&
96 StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" &&
97 "unexpected external TLS symbol");
Kristof Beylsaea84612015-03-04 09:12:08 +000098 // The general dynamic access sequence is used to get the
99 // address of _TLS_MODULE_BASE_.
Tim Northover3b0846e2014-05-24 12:50:23 +0000100 Model = TLSModel::GeneralDynamic;
101 }
102 switch (Model) {
103 case TLSModel::InitialExec:
104 RefFlags |= AArch64MCExpr::VK_GOTTPREL;
105 break;
106 case TLSModel::LocalExec:
107 RefFlags |= AArch64MCExpr::VK_TPREL;
108 break;
109 case TLSModel::LocalDynamic:
110 RefFlags |= AArch64MCExpr::VK_DTPREL;
111 break;
112 case TLSModel::GeneralDynamic:
113 RefFlags |= AArch64MCExpr::VK_TLSDESC;
114 break;
115 }
116 } else {
117 // No modifier means this is a generic reference, classified as absolute for
118 // the cases where it matters (:abs_g0: etc).
119 RefFlags |= AArch64MCExpr::VK_ABS;
120 }
121
122 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
123 RefFlags |= AArch64MCExpr::VK_PAGE;
124 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
125 AArch64II::MO_PAGEOFF)
126 RefFlags |= AArch64MCExpr::VK_PAGEOFF;
127 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3)
128 RefFlags |= AArch64MCExpr::VK_G3;
129 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2)
130 RefFlags |= AArch64MCExpr::VK_G2;
131 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1)
132 RefFlags |= AArch64MCExpr::VK_G1;
133 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0)
134 RefFlags |= AArch64MCExpr::VK_G0;
Kristof Beylsaea84612015-03-04 09:12:08 +0000135 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_HI12)
136 RefFlags |= AArch64MCExpr::VK_HI12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000137
138 if (MO.getTargetFlags() & AArch64II::MO_NC)
139 RefFlags |= AArch64MCExpr::VK_NC;
140
141 const MCExpr *Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +0000142 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +0000143 if (!MO.isJTI() && MO.getOffset())
Jim Grosbach13760bd2015-05-30 01:25:56 +0000144 Expr = MCBinaryExpr::createAdd(
145 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +0000146
147 AArch64MCExpr::VariantKind RefKind;
148 RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
Jim Grosbach13760bd2015-05-30 01:25:56 +0000149 Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +0000150
Jim Grosbache9119e42015-05-13 18:37:00 +0000151 return MCOperand::createExpr(Expr);
Tim Northover3b0846e2014-05-24 12:50:23 +0000152}
153
154MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
155 MCSymbol *Sym) const {
Eric Christopher98983d02016-10-01 01:50:25 +0000156 if (Printer.TM.getTargetTriple().isOSDarwin())
Tim Northover3b0846e2014-05-24 12:50:23 +0000157 return lowerSymbolOperandDarwin(MO, Sym);
158
Eric Christopher98983d02016-10-01 01:50:25 +0000159 assert(Printer.TM.getTargetTriple().isOSBinFormatELF() &&
160 "Expect Darwin or ELF target");
Tim Northover3b0846e2014-05-24 12:50:23 +0000161 return lowerSymbolOperandELF(MO, Sym);
162}
163
164bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO,
165 MCOperand &MCOp) const {
166 switch (MO.getType()) {
167 default:
Craig Topper2a30d782014-06-18 05:05:13 +0000168 llvm_unreachable("unknown operand type");
Tim Northover3b0846e2014-05-24 12:50:23 +0000169 case MachineOperand::MO_Register:
170 // Ignore all implicit register operands.
171 if (MO.isImplicit())
172 return false;
Jim Grosbache9119e42015-05-13 18:37:00 +0000173 MCOp = MCOperand::createReg(MO.getReg());
Tim Northover3b0846e2014-05-24 12:50:23 +0000174 break;
175 case MachineOperand::MO_RegisterMask:
176 // Regmasks are like implicit defs.
177 return false;
178 case MachineOperand::MO_Immediate:
Jim Grosbache9119e42015-05-13 18:37:00 +0000179 MCOp = MCOperand::createImm(MO.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +0000180 break;
181 case MachineOperand::MO_MachineBasicBlock:
Jim Grosbache9119e42015-05-13 18:37:00 +0000182 MCOp = MCOperand::createExpr(
Jim Grosbach13760bd2015-05-30 01:25:56 +0000183 MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +0000184 break;
185 case MachineOperand::MO_GlobalAddress:
186 MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
187 break;
188 case MachineOperand::MO_ExternalSymbol:
189 MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
190 break;
Rafael Espindolace4c2bc2015-06-23 12:21:54 +0000191 case MachineOperand::MO_MCSymbol:
192 MCOp = LowerSymbolOperand(MO, MO.getMCSymbol());
193 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000194 case MachineOperand::MO_JumpTableIndex:
195 MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
196 break;
197 case MachineOperand::MO_ConstantPoolIndex:
198 MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
199 break;
200 case MachineOperand::MO_BlockAddress:
201 MCOp = LowerSymbolOperand(
202 MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
203 break;
204 }
205 return true;
206}
207
208void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
209 OutMI.setOpcode(MI->getOpcode());
210
Pete Cooper7be8f8f2015-08-03 19:04:32 +0000211 for (const MachineOperand &MO : MI->operands()) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000212 MCOperand MCOp;
Pete Cooper7be8f8f2015-08-03 19:04:32 +0000213 if (lowerOperand(MO, MCOp))
Tim Northover3b0846e2014-05-24 12:50:23 +0000214 OutMI.addOperand(MCOp);
215 }
216}