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