]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r306956, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / AArch64 / AArch64MCInstLower.cpp
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/Support/CommandLine.h"
26 #include "llvm/Target/TargetMachine.h"
27 using namespace llvm;
28
29 extern cl::opt<bool> EnableAArch64ELFLocalDynamicTLSGeneration;
30
31 AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer)
32     : Ctx(ctx), Printer(printer) {}
33
34 MCSymbol *
35 AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
36   return Printer.getSymbol(MO.getGlobal());
37 }
38
39 MCSymbol *
40 AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const {
41   return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
42 }
43
44 MCOperand 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
56       llvm_unreachable("Unexpected target flags with MO_GOT on GV operand");
57   } 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   }
72   const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
73   if (!MO.isJTI() && MO.getOffset())
74     Expr = MCBinaryExpr::createAdd(
75         Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
76   return MCOperand::createExpr(Expr);
77 }
78
79 MCOperand 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);
90       if (!EnableAArch64ELFLocalDynamicTLSGeneration &&
91           Model == TLSModel::LocalDynamic)
92         Model = TLSModel::GeneralDynamic;
93
94     } else {
95       assert(MO.isSymbol() &&
96              StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" &&
97              "unexpected external TLS symbol");
98       // The general dynamic access sequence is used to get the
99       // address of _TLS_MODULE_BASE_.
100       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;
135   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_HI12)
136     RefFlags |= AArch64MCExpr::VK_HI12;
137
138   if (MO.getTargetFlags() & AArch64II::MO_NC)
139     RefFlags |= AArch64MCExpr::VK_NC;
140
141   const MCExpr *Expr =
142       MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
143   if (!MO.isJTI() && MO.getOffset())
144     Expr = MCBinaryExpr::createAdd(
145         Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
146
147   AArch64MCExpr::VariantKind RefKind;
148   RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
149   Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
150
151   return MCOperand::createExpr(Expr);
152 }
153
154 MCOperand AArch64MCInstLower::lowerSymbolOperandCOFF(const MachineOperand &MO,
155                                                      MCSymbol *Sym) const {
156   MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
157   const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
158   if (!MO.isJTI() && MO.getOffset())
159     Expr = MCBinaryExpr::createAdd(
160         Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
161   return MCOperand::createExpr(Expr);
162 }
163
164 MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
165                                                  MCSymbol *Sym) const {
166   if (Printer.TM.getTargetTriple().isOSDarwin())
167     return lowerSymbolOperandDarwin(MO, Sym);
168   if (Printer.TM.getTargetTriple().isOSBinFormatCOFF())
169     return lowerSymbolOperandCOFF(MO, Sym);
170
171   assert(Printer.TM.getTargetTriple().isOSBinFormatELF() && "Invalid target");
172   return lowerSymbolOperandELF(MO, Sym);
173 }
174
175 bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO,
176                                       MCOperand &MCOp) const {
177   switch (MO.getType()) {
178   default:
179     llvm_unreachable("unknown operand type");
180   case MachineOperand::MO_Register:
181     // Ignore all implicit register operands.
182     if (MO.isImplicit())
183       return false;
184     MCOp = MCOperand::createReg(MO.getReg());
185     break;
186   case MachineOperand::MO_RegisterMask:
187     // Regmasks are like implicit defs.
188     return false;
189   case MachineOperand::MO_Immediate:
190     MCOp = MCOperand::createImm(MO.getImm());
191     break;
192   case MachineOperand::MO_MachineBasicBlock:
193     MCOp = MCOperand::createExpr(
194         MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
195     break;
196   case MachineOperand::MO_GlobalAddress:
197     MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
198     break;
199   case MachineOperand::MO_ExternalSymbol:
200     MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
201     break;
202   case MachineOperand::MO_MCSymbol:
203     MCOp = LowerSymbolOperand(MO, MO.getMCSymbol());
204     break;
205   case MachineOperand::MO_JumpTableIndex:
206     MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
207     break;
208   case MachineOperand::MO_ConstantPoolIndex:
209     MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
210     break;
211   case MachineOperand::MO_BlockAddress:
212     MCOp = LowerSymbolOperand(
213         MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
214     break;
215   }
216   return true;
217 }
218
219 void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
220   OutMI.setOpcode(MI->getOpcode());
221
222   for (const MachineOperand &MO : MI->operands()) {
223     MCOperand MCOp;
224     if (lowerOperand(MO, MCOp))
225       OutMI.addOperand(MCOp);
226   }
227 }