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.
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"
25 #include "llvm/Target/TargetMachine.h"
26 using namespace llvm;
27
AArch64MCInstLower(MCContext & ctx,Mangler & mang,AsmPrinter & printer)28 AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, Mangler &mang,
29 AsmPrinter &printer)
30 : Ctx(ctx), Printer(printer), TargetTriple(printer.getTargetTriple()) {}
31
32 MCSymbol *
GetGlobalAddressSymbol(const MachineOperand & MO) const33 AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
34 return Printer.getSymbol(MO.getGlobal());
35 }
36
37 MCSymbol *
GetExternalSymbolSymbol(const MachineOperand & MO) const38 AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const {
39 return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
40 }
41
lowerSymbolOperandDarwin(const MachineOperand & MO,MCSymbol * Sym) const42 MCOperand AArch64MCInstLower::lowerSymbolOperandDarwin(const MachineOperand &MO,
43 MCSymbol *Sym) const {
44 // FIXME: We would like an efficient form for this, so we don't have to do a
45 // lot of extra uniquing.
46 MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
47 if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) {
48 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
49 RefKind = MCSymbolRefExpr::VK_GOTPAGE;
50 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
51 AArch64II::MO_PAGEOFF)
52 RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF;
53 else
54 llvm_unreachable("Unexpected target flags with MO_GOT on GV operand");
55 } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) {
56 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
57 RefKind = MCSymbolRefExpr::VK_TLVPPAGE;
58 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
59 AArch64II::MO_PAGEOFF)
60 RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF;
61 else
62 llvm_unreachable("Unexpected target flags with MO_TLS on GV operand");
63 } else {
64 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
65 RefKind = MCSymbolRefExpr::VK_PAGE;
66 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
67 AArch64II::MO_PAGEOFF)
68 RefKind = MCSymbolRefExpr::VK_PAGEOFF;
69 }
70 const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, RefKind, Ctx);
71 if (!MO.isJTI() && MO.getOffset())
72 Expr = MCBinaryExpr::CreateAdd(
73 Expr, MCConstantExpr::Create(MO.getOffset(), Ctx), Ctx);
74 return MCOperand::CreateExpr(Expr);
75 }
76
lowerSymbolOperandELF(const MachineOperand & MO,MCSymbol * Sym) const77 MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
78 MCSymbol *Sym) const {
79 uint32_t RefFlags = 0;
80
81 if (MO.getTargetFlags() & AArch64II::MO_GOT)
82 RefFlags |= AArch64MCExpr::VK_GOT;
83 else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
84 TLSModel::Model Model;
85 if (MO.isGlobal()) {
86 const GlobalValue *GV = MO.getGlobal();
87 Model = Printer.TM.getTLSModel(GV);
88 } else {
89 assert(MO.isSymbol() &&
90 StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" &&
91 "unexpected external TLS symbol");
92 Model = TLSModel::GeneralDynamic;
93 }
94 switch (Model) {
95 case TLSModel::InitialExec:
96 RefFlags |= AArch64MCExpr::VK_GOTTPREL;
97 break;
98 case TLSModel::LocalExec:
99 RefFlags |= AArch64MCExpr::VK_TPREL;
100 break;
101 case TLSModel::LocalDynamic:
102 RefFlags |= AArch64MCExpr::VK_DTPREL;
103 break;
104 case TLSModel::GeneralDynamic:
105 RefFlags |= AArch64MCExpr::VK_TLSDESC;
106 break;
107 }
108 } else {
109 // No modifier means this is a generic reference, classified as absolute for
110 // the cases where it matters (:abs_g0: etc).
111 RefFlags |= AArch64MCExpr::VK_ABS;
112 }
113
114 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
115 RefFlags |= AArch64MCExpr::VK_PAGE;
116 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
117 AArch64II::MO_PAGEOFF)
118 RefFlags |= AArch64MCExpr::VK_PAGEOFF;
119 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3)
120 RefFlags |= AArch64MCExpr::VK_G3;
121 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2)
122 RefFlags |= AArch64MCExpr::VK_G2;
123 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1)
124 RefFlags |= AArch64MCExpr::VK_G1;
125 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0)
126 RefFlags |= AArch64MCExpr::VK_G0;
127
128 if (MO.getTargetFlags() & AArch64II::MO_NC)
129 RefFlags |= AArch64MCExpr::VK_NC;
130
131 const MCExpr *Expr =
132 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, Ctx);
133 if (!MO.isJTI() && MO.getOffset())
134 Expr = MCBinaryExpr::CreateAdd(
135 Expr, MCConstantExpr::Create(MO.getOffset(), Ctx), Ctx);
136
137 AArch64MCExpr::VariantKind RefKind;
138 RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
139 Expr = AArch64MCExpr::Create(Expr, RefKind, Ctx);
140
141 return MCOperand::CreateExpr(Expr);
142 }
143
LowerSymbolOperand(const MachineOperand & MO,MCSymbol * Sym) const144 MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
145 MCSymbol *Sym) const {
146 if (TargetTriple.isOSDarwin())
147 return lowerSymbolOperandDarwin(MO, Sym);
148
149 assert(TargetTriple.isOSBinFormatELF() && "Expect Darwin or ELF target");
150 return lowerSymbolOperandELF(MO, Sym);
151 }
152
lowerOperand(const MachineOperand & MO,MCOperand & MCOp) const153 bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO,
154 MCOperand &MCOp) const {
155 switch (MO.getType()) {
156 default:
157 llvm_unreachable("unknown operand type");
158 case MachineOperand::MO_Register:
159 // Ignore all implicit register operands.
160 if (MO.isImplicit())
161 return false;
162 MCOp = MCOperand::CreateReg(MO.getReg());
163 break;
164 case MachineOperand::MO_RegisterMask:
165 // Regmasks are like implicit defs.
166 return false;
167 case MachineOperand::MO_Immediate:
168 MCOp = MCOperand::CreateImm(MO.getImm());
169 break;
170 case MachineOperand::MO_MachineBasicBlock:
171 MCOp = MCOperand::CreateExpr(
172 MCSymbolRefExpr::Create(MO.getMBB()->getSymbol(), Ctx));
173 break;
174 case MachineOperand::MO_GlobalAddress:
175 MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
176 break;
177 case MachineOperand::MO_ExternalSymbol:
178 MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
179 break;
180 case MachineOperand::MO_JumpTableIndex:
181 MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
182 break;
183 case MachineOperand::MO_ConstantPoolIndex:
184 MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
185 break;
186 case MachineOperand::MO_BlockAddress:
187 MCOp = LowerSymbolOperand(
188 MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
189 break;
190 }
191 return true;
192 }
193
Lower(const MachineInstr * MI,MCInst & OutMI) const194 void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
195 OutMI.setOpcode(MI->getOpcode());
196
197 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
198 MCOperand MCOp;
199 if (lowerOperand(MI->getOperand(i), MCOp))
200 OutMI.addOperand(MCOp);
201 }
202 }
203