blob: 09e4937b19e586619d25ac7d276434ee7a1b05c4 [file] [log] [blame]
Chris Lattnerb16f72e2009-09-02 17:35:12 +00001//===-- X86MCInstLower.cpp - Convert X86 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 X86 MachineInstrs to their corresponding
11// MCInst records.
12//
13//===----------------------------------------------------------------------===//
14
15
16#include "X86ATTAsmPrinter.h"
17#include "X86MCAsmInfo.h"
18#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
21#include "llvm/MC/MCStreamer.h"
22#include "llvm/Support/FormattedStream.h"
23#include "llvm/Support/Mangler.h"
24#include "llvm/ADT/SmallString.h"
25#include "llvm/ADT/StringExtras.h" // fixme, kill utostr.
26
27using namespace llvm;
28
29MCSymbol *X86ATTAsmPrinter::GetPICBaseSymbol() {
30 // FIXME: the actual label generated doesn't matter here! Just mangle in
31 // something unique (the function number) with Private prefix.
32 std::string Name;
33
34 if (Subtarget->isTargetDarwin()) {
35 Name = "L" + utostr(getFunctionNumber())+"$pb";
36 } else {
37 assert(Subtarget->isTargetELF() && "Don't know how to print PIC label!");
38 Name = ".Lllvm$" + utostr(getFunctionNumber())+".$piclabel";
39 }
40 return OutContext.GetOrCreateSymbol(Name);
41}
42
43
44
45static void lower_lea64_32mem(MCInst *MI, unsigned OpNo) {
46 // Convert registers in the addr mode according to subreg64.
47 for (unsigned i = 0; i != 4; ++i) {
48 if (!MI->getOperand(i).isReg()) continue;
49
50 unsigned Reg = MI->getOperand(i).getReg();
51 if (Reg == 0) continue;
52
53 MI->getOperand(i).setReg(getX86SubSuperRegister(Reg, MVT::i64));
54 }
55}
56
57/// LowerGlobalAddressOperand - Lower an MO_GlobalAddress operand to an
58/// MCOperand.
59MCOperand X86ATTAsmPrinter::LowerGlobalAddressOperand(const MachineOperand &MO){
60 const GlobalValue *GV = MO.getGlobal();
61
62 const char *Suffix = "";
63 if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB)
64 Suffix = "$stub";
65 else if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||
66 MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE ||
67 MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY ||
68 MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE)
69 Suffix = "$non_lazy_ptr";
70
71 std::string Name = Mang->getMangledName(GV, Suffix, Suffix[0] != '\0');
72 if (Subtarget->isTargetCygMing())
73 DecorateCygMingName(Name, GV);
74
75 // Handle dllimport linkage.
76 if (MO.getTargetFlags() == X86II::MO_DLLIMPORT)
77 Name = "__imp_" + Name;
78
79 if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||
80 MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE)
81 GVStubs[Name] = Mang->getMangledName(GV);
82 else if (MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY ||
83 MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE)
84 HiddenGVStubs[Name] = Mang->getMangledName(GV);
85 else if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB)
86 FnStubs[Name] = Mang->getMangledName(GV);
87
88
89 // Handle target operand flags.
90 // FIXME: This should be common between external symbols, constant pool etc.
91 MCSymbol *NegatedSymbol = 0;
92
93 switch (MO.getTargetFlags()) {
94 default:
95 llvm_unreachable("Unknown target flag on GV operand");
96 case X86II::MO_NO_FLAG: // No flag.
97 break;
98 case X86II::MO_DARWIN_NONLAZY:
99 case X86II::MO_DARWIN_HIDDEN_NONLAZY:
100 case X86II::MO_DLLIMPORT:
101 case X86II::MO_DARWIN_STUB:
102 // These affect the name of the symbol, not any suffix.
103 break;
104 case X86II::MO_GOT_ABSOLUTE_ADDRESS:
105 assert(0 && "Reloc mode unimp!");
106 //O << " + [.-";
107 //PrintPICBaseSymbol();
108 //O << ']';
109 break;
110 case X86II::MO_PIC_BASE_OFFSET:
111 case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
112 case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
113 // Subtract the pic base.
114 NegatedSymbol = GetPICBaseSymbol();
115 break;
116
117 // FIXME: These probably should be a modifier on the symbol or something??
118 case X86II::MO_TLSGD: Name += "@TLSGD"; break;
119 case X86II::MO_GOTTPOFF: Name += "@GOTTPOFF"; break;
120 case X86II::MO_INDNTPOFF: Name += "@INDNTPOFF"; break;
121 case X86II::MO_TPOFF: Name += "@TPOFF"; break;
122 case X86II::MO_NTPOFF: Name += "@NTPOFF"; break;
123 case X86II::MO_GOTPCREL: Name += "@GOTPCREL"; break;
124 case X86II::MO_GOT: Name += "@GOT"; break;
125 case X86II::MO_GOTOFF: Name += "@GOTOFF"; break;
126 case X86II::MO_PLT: Name += "@PLT"; break;
127 }
128
129 // Create a symbol for the name.
130 MCSymbol *Sym = OutContext.GetOrCreateSymbol(Name);
131 // FIXME: We would like an efficient form for this, so we don't have to do a
132 // lot of extra uniquing.
133 const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, OutContext);
134 if (NegatedSymbol)
135 Expr = MCBinaryExpr::CreateSub(Expr, MCSymbolRefExpr::Create(NegatedSymbol,
136 OutContext),
137 OutContext);
138 if (MO.getOffset())
139 Expr = MCBinaryExpr::CreateAdd(Expr, MCConstantExpr::Create(MO.getOffset(),
140 OutContext),
141 OutContext);
142 return MCOperand::CreateExpr(Expr);
143}
144
145MCOperand X86ATTAsmPrinter::
146LowerExternalSymbolOperand(const MachineOperand &MO) {
147 std::string Name = Mang->makeNameProper(MO.getSymbolName());
148 if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) {
149 FnStubs[Name+"$stub"] = Name;
150 Name += "$stub";
151 }
152
153 MCSymbol *Sym = OutContext.GetOrCreateSymbol(Name);
154 // FIXME: We would like an efficient form for this, so we don't have to do a
155 // lot of extra uniquing.
156 const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, OutContext);
157 if (MO.getOffset())
158 Expr = MCBinaryExpr::CreateAdd(Expr,
159 MCConstantExpr::Create(MO.getOffset(),
160 OutContext),
161 OutContext);
162 return MCOperand::CreateExpr(Expr);
163}
164
165MCOperand X86ATTAsmPrinter::LowerJumpTableOperand(const MachineOperand &MO) {
166 SmallString<256> Name;
167 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI"
168 << getFunctionNumber() << '_' << MO.getIndex();
169
170 MCSymbol *NegatedSymbol = 0;
171 switch (MO.getTargetFlags()) {
172 default:
173 llvm_unreachable("Unknown target flag on GV operand");
174 case X86II::MO_PIC_BASE_OFFSET:
175 case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
176 case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
177 // Subtract the pic base.
178 NegatedSymbol = GetPICBaseSymbol();
179 break;
180 }
181
182 // Create a symbol for the name.
183 MCSymbol *Sym = OutContext.GetOrCreateSymbol(Name.str());
184 // FIXME: We would like an efficient form for this, so we don't have to do a
185 // lot of extra uniquing.
186 const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, OutContext);
187 if (NegatedSymbol)
188 Expr = MCBinaryExpr::CreateSub(Expr, MCSymbolRefExpr::Create(NegatedSymbol,
189 OutContext),
190 OutContext);
191 return MCOperand::CreateExpr(Expr);
192}
193
194
195void X86ATTAsmPrinter::
196printInstructionThroughMCStreamer(const MachineInstr *MI) {
197
198 MCInst TmpInst;
199
200 switch (MI->getOpcode()) {
201 case TargetInstrInfo::DBG_LABEL:
202 case TargetInstrInfo::EH_LABEL:
203 case TargetInstrInfo::GC_LABEL:
204 printLabel(MI);
205 return;
206 case TargetInstrInfo::INLINEASM:
207 O << '\t';
208 printInlineAsm(MI);
209 return;
210 case TargetInstrInfo::IMPLICIT_DEF:
211 printImplicitDef(MI);
212 return;
213 case X86::MOVPC32r: {
214 // This is a pseudo op for a two instruction sequence with a label, which
215 // looks like:
216 // call "L1$pb"
217 // "L1$pb":
218 // popl %esi
219
220 // Emit the call.
221 MCSymbol *PICBase = GetPICBaseSymbol();
222 TmpInst.setOpcode(X86::CALLpcrel32);
223 // FIXME: We would like an efficient form for this, so we don't have to do a
224 // lot of extra uniquing.
225 TmpInst.addOperand(MCOperand::CreateExpr(MCSymbolRefExpr::Create(PICBase,
226 OutContext)));
227 printInstruction(&TmpInst);
228
229 // Emit the label.
230 OutStreamer.EmitLabel(PICBase);
231
232 // popl $reg
233 TmpInst.setOpcode(X86::POP32r);
234 TmpInst.getOperand(0) = MCOperand::CreateReg(MI->getOperand(0).getReg());
235 printInstruction(&TmpInst);
236 return;
237 }
238 }
239
240 TmpInst.setOpcode(MI->getOpcode());
241
242 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
243 const MachineOperand &MO = MI->getOperand(i);
244
245 MCOperand MCOp;
246 switch (MO.getType()) {
247 default:
248 O.flush();
249 errs() << "Cannot lower operand #" << i << " of :" << *MI;
250 llvm_unreachable("Unimp");
251 case MachineOperand::MO_JumpTableIndex:
252 MCOp = LowerJumpTableOperand(MO);
253 break;
254 case MachineOperand::MO_Register:
255 MCOp = MCOperand::CreateReg(MO.getReg());
256 break;
257 case MachineOperand::MO_Immediate:
258 MCOp = MCOperand::CreateImm(MO.getImm());
259 break;
260 case MachineOperand::MO_MachineBasicBlock:
261 MCOp = MCOperand::CreateMBBLabel(getFunctionNumber(),
262 MO.getMBB()->getNumber());
263 break;
264 case MachineOperand::MO_GlobalAddress:
265 MCOp = LowerGlobalAddressOperand(MO);
266 break;
267 case MachineOperand::MO_ExternalSymbol:
268 MCOp = LowerExternalSymbolOperand(MO);
269 break;
270 }
271
272 TmpInst.addOperand(MCOp);
273 }
274
275 switch (TmpInst.getOpcode()) {
276 case X86::LEA64_32r:
277 // Handle the 'subreg rewriting' for the lea64_32mem operand.
278 lower_lea64_32mem(&TmpInst, 1);
279 break;
280 }
281
282 printInstruction(&TmpInst);
283}