OSDN Git Service

Merge "Update LLVM for 3.5 rebase (r209712)."
[android-x86/external-llvm.git] / 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/Target/TargetMachine.h"
26 using namespace llvm;
27
28 AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, Mangler &mang,
29                                        AsmPrinter &printer)
30     : Ctx(ctx), Printer(printer), TargetTriple(printer.getTargetTriple()) {}
31
32 MCSymbol *
33 AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
34   return Printer.getSymbol(MO.getGlobal());
35 }
36
37 MCSymbol *
38 AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const {
39   return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
40 }
41
42 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       assert(0 && "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
77 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
144 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
153 bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO,
154                                       MCOperand &MCOp) const {
155   switch (MO.getType()) {
156   default:
157     assert(0 && "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
194 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 }