fix another GCC bootstrap problem, which manifested as things
[oota-llvm.git] / lib / Target / X86 / AsmPrinter / X86MCInstLower.cpp
1 //===-- 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 using namespace llvm;
26
27 MCSymbol *X86ATTAsmPrinter::GetPICBaseSymbol() {
28   // FIXME: the actual label generated doesn't matter here!  Just mangle in
29   // something unique (the function number) with Private prefix.
30   SmallString<60> Name;
31   
32   if (Subtarget->isTargetDarwin()) {
33     raw_svector_ostream(Name) << 'L' << getFunctionNumber() << "$pb";
34   } else {
35     assert(Subtarget->isTargetELF() && "Don't know how to print PIC label!");
36     raw_svector_ostream(Name) << ".Lllvm$" << getFunctionNumber()<<".$piclabel";
37   }
38   return OutContext.GetOrCreateSymbol(Name.str());
39 }
40
41
42 /// LowerGlobalAddressOperand - Lower an MO_GlobalAddress operand to an
43 /// MCOperand.
44 MCSymbol *X86ATTAsmPrinter::GetGlobalAddressSymbol(const MachineOperand &MO) {
45   const GlobalValue *GV = MO.getGlobal();
46   
47   bool isImplicitlyPrivate = false;
48   if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB ||
49       MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||
50       MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE ||
51       MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE)
52     isImplicitlyPrivate = true;
53   
54   SmallString<128> Name;
55   Mang->getNameWithPrefix(Name, GV, isImplicitlyPrivate);
56   
57   if (Subtarget->isTargetCygMing())
58     DecorateCygMingName(Name, GV);
59   
60   switch (MO.getTargetFlags()) {
61   default: llvm_unreachable("Unknown target flag on GV operand");
62   case X86II::MO_NO_FLAG:                // No flag.
63   case X86II::MO_GOT_ABSOLUTE_ADDRESS:   // Doesn't modify symbol name.
64   case X86II::MO_PIC_BASE_OFFSET:        // Doesn't modify symbol name.
65     break;
66   case X86II::MO_DLLIMPORT: {
67     // Handle dllimport linkage.
68     const char *Prefix = "__imp_";
69     Name.insert(Name.begin(), Prefix, Prefix+strlen(Prefix));
70     break;
71   }
72   case X86II::MO_DARWIN_NONLAZY:
73   case X86II::MO_DARWIN_NONLAZY_PIC_BASE: {
74     Name += "$non_lazy_ptr";
75     MCSymbol *Sym = OutContext.GetOrCreateSymbol(Name.str());
76     MCSymbol *&StubSym = GVStubs[Sym];
77     if (StubSym == 0) {
78       Name.clear();
79       Mang->getNameWithPrefix(Name, GV, false);
80       StubSym = OutContext.GetOrCreateSymbol(Name.str());
81     }
82     return Sym;
83     
84   }
85   case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: {
86     Name += "$non_lazy_ptr";
87     MCSymbol *Sym = OutContext.GetOrCreateSymbol(Name.str());
88     MCSymbol *&StubSym = HiddenGVStubs[Sym];
89     if (StubSym == 0) {
90       Name.clear();
91       Mang->getNameWithPrefix(Name, GV, false);
92       StubSym = OutContext.GetOrCreateSymbol(Name.str());
93     }
94     return Sym;
95   }
96   case X86II::MO_DARWIN_STUB: {
97     Name += "$stub";
98     MCSymbol *Sym = OutContext.GetOrCreateSymbol(Name.str());
99     MCSymbol *&StubSym = FnStubs[Sym];
100     if (StubSym == 0) {
101       Name.clear();
102       Mang->getNameWithPrefix(Name, GV, false);
103       StubSym = OutContext.GetOrCreateSymbol(Name.str());
104     }
105     return Sym;
106   }
107   // FIXME: These probably should be a modifier on the symbol or something??
108   case X86II::MO_TLSGD:     Name += "@TLSGD";     break;
109   case X86II::MO_GOTTPOFF:  Name += "@GOTTPOFF";  break;
110   case X86II::MO_INDNTPOFF: Name += "@INDNTPOFF"; break;
111   case X86II::MO_TPOFF:     Name += "@TPOFF";     break;
112   case X86II::MO_NTPOFF:    Name += "@NTPOFF";    break;
113   case X86II::MO_GOTPCREL:  Name += "@GOTPCREL";  break;
114   case X86II::MO_GOT:       Name += "@GOT";       break;
115   case X86II::MO_GOTOFF:    Name += "@GOTOFF";    break;
116   case X86II::MO_PLT:       Name += "@PLT";       break;
117   }
118   
119   return OutContext.GetOrCreateSymbol(Name.str());
120 }
121
122 MCSymbol *X86ATTAsmPrinter::GetExternalSymbolSymbol(const MachineOperand &MO) {
123   SmallString<128> Name;
124   Name += MAI->getGlobalPrefix();
125   Name += MO.getSymbolName();
126   
127   switch (MO.getTargetFlags()) {
128   default: llvm_unreachable("Unknown target flag on GV operand");
129   case X86II::MO_NO_FLAG:                // No flag.
130   case X86II::MO_GOT_ABSOLUTE_ADDRESS:   // Doesn't modify symbol name.
131   case X86II::MO_PIC_BASE_OFFSET:        // Doesn't modify symbol name.
132     break;
133   case X86II::MO_DLLIMPORT: {
134     // Handle dllimport linkage.
135     const char *Prefix = "__imp_";
136     Name.insert(Name.begin(), Prefix, Prefix+strlen(Prefix));
137     break;
138   }
139   case X86II::MO_DARWIN_STUB: {
140     Name += "$stub";
141     MCSymbol *Sym = OutContext.GetOrCreateSymbol(Name.str());
142     MCSymbol *&StubSym = FnStubs[Sym];
143     if (StubSym == 0) {
144       Name.erase(Name.end()-5, Name.end());
145       StubSym = OutContext.GetOrCreateSymbol(Name.str());
146     }
147     return Sym;
148   }
149   // FIXME: These probably should be a modifier on the symbol or something??
150   case X86II::MO_TLSGD:     Name += "@TLSGD";     break;
151   case X86II::MO_GOTTPOFF:  Name += "@GOTTPOFF";  break;
152   case X86II::MO_INDNTPOFF: Name += "@INDNTPOFF"; break;
153   case X86II::MO_TPOFF:     Name += "@TPOFF";     break;
154   case X86II::MO_NTPOFF:    Name += "@NTPOFF";    break;
155   case X86II::MO_GOTPCREL:  Name += "@GOTPCREL";  break;
156   case X86II::MO_GOT:       Name += "@GOT";       break;
157   case X86II::MO_GOTOFF:    Name += "@GOTOFF";    break;
158   case X86II::MO_PLT:       Name += "@PLT";       break;
159   }
160   
161   return OutContext.GetOrCreateSymbol(Name.str());
162 }
163
164 MCSymbol *X86ATTAsmPrinter::GetJumpTableSymbol(const MachineOperand &MO) {
165   SmallString<256> Name;
166   raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI"
167     << getFunctionNumber() << '_' << MO.getIndex();
168   
169   switch (MO.getTargetFlags()) {
170   default:
171     llvm_unreachable("Unknown target flag on GV operand");
172   case X86II::MO_NO_FLAG:    // No flag.
173   case X86II::MO_PIC_BASE_OFFSET:
174   case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
175   case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
176     break;
177     // FIXME: These probably should be a modifier on the symbol or something??
178   case X86II::MO_TLSGD:     Name += "@TLSGD";     break;
179   case X86II::MO_GOTTPOFF:  Name += "@GOTTPOFF";  break;
180   case X86II::MO_INDNTPOFF: Name += "@INDNTPOFF"; break;
181   case X86II::MO_TPOFF:     Name += "@TPOFF";     break;
182   case X86II::MO_NTPOFF:    Name += "@NTPOFF";    break;
183   case X86II::MO_GOTPCREL:  Name += "@GOTPCREL";  break;
184   case X86II::MO_GOT:       Name += "@GOT";       break;
185   case X86II::MO_GOTOFF:    Name += "@GOTOFF";    break;
186   case X86II::MO_PLT:       Name += "@PLT";       break;
187   }
188   
189   // Create a symbol for the name.
190   return OutContext.GetOrCreateSymbol(Name.str());
191 }
192
193
194 MCSymbol *X86ATTAsmPrinter::
195 GetConstantPoolIndexSymbol(const MachineOperand &MO) {
196   SmallString<256> Name;
197   raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "CPI"
198   << getFunctionNumber() << '_' << MO.getIndex();
199   
200   switch (MO.getTargetFlags()) {
201   default:
202     llvm_unreachable("Unknown target flag on GV operand");
203   case X86II::MO_NO_FLAG:    // No flag.
204   case X86II::MO_PIC_BASE_OFFSET:
205   case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
206   case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
207     break;
208     // FIXME: These probably should be a modifier on the symbol or something??
209   case X86II::MO_TLSGD:     Name += "@TLSGD";     break;
210   case X86II::MO_GOTTPOFF:  Name += "@GOTTPOFF";  break;
211   case X86II::MO_INDNTPOFF: Name += "@INDNTPOFF"; break;
212   case X86II::MO_TPOFF:     Name += "@TPOFF";     break;
213   case X86II::MO_NTPOFF:    Name += "@NTPOFF";    break;
214   case X86II::MO_GOTPCREL:  Name += "@GOTPCREL";  break;
215   case X86II::MO_GOT:       Name += "@GOT";       break;
216   case X86II::MO_GOTOFF:    Name += "@GOTOFF";    break;
217   case X86II::MO_PLT:       Name += "@PLT";       break;
218   }
219   
220   // Create a symbol for the name.
221   return OutContext.GetOrCreateSymbol(Name.str());
222 }
223
224 MCOperand X86ATTAsmPrinter::LowerSymbolOperand(const MachineOperand &MO,
225                                                MCSymbol *Sym) {
226   // FIXME: We would like an efficient form for this, so we don't have to do a
227   // lot of extra uniquing.
228   const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, OutContext);
229   
230   switch (MO.getTargetFlags()) {
231   default: llvm_unreachable("Unknown target flag on GV operand");
232   case X86II::MO_NO_FLAG:    // No flag.
233       
234   // These affect the name of the symbol, not any suffix.
235   case X86II::MO_DARWIN_NONLAZY:
236   case X86II::MO_DLLIMPORT:
237   case X86II::MO_DARWIN_STUB:
238   case X86II::MO_TLSGD:
239   case X86II::MO_GOTTPOFF:
240   case X86II::MO_INDNTPOFF:
241   case X86II::MO_TPOFF:
242   case X86II::MO_NTPOFF:
243   case X86II::MO_GOTPCREL:
244   case X86II::MO_GOT:
245   case X86II::MO_GOTOFF:
246   case X86II::MO_PLT:
247     break;
248   case X86II::MO_PIC_BASE_OFFSET:
249   case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
250   case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
251     // Subtract the pic base.
252     Expr = MCBinaryExpr::CreateSub(Expr, 
253                                    MCSymbolRefExpr::Create(GetPICBaseSymbol(),
254                                                            OutContext),
255                                    OutContext);
256     break;
257   case X86II::MO_GOT_ABSOLUTE_ADDRESS: {
258     // For this, we want to print something like:
259     //   MYSYMBOL + (. - PICBASE)
260     // However, we can't generate a ".", so just emit a new label here and refer
261     // to it.  We know that this operand flag occurs at most once per function.
262     SmallString<64> Name;
263     raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "picbaseref"
264       << getFunctionNumber();
265     MCSymbol *DotSym = OutContext.GetOrCreateSymbol(Name.str());
266     OutStreamer.EmitLabel(DotSym);
267
268     const MCExpr *DotExpr = MCSymbolRefExpr::Create(DotSym, OutContext);
269     const MCExpr *PICBase = MCSymbolRefExpr::Create(GetPICBaseSymbol(),
270                                                     OutContext);
271     DotExpr = MCBinaryExpr::CreateSub(DotExpr, PICBase, OutContext);
272     Expr = MCBinaryExpr::CreateAdd(Expr, DotExpr, OutContext);
273     break;      
274   }
275   }
276   
277   if (!MO.isJTI() && MO.getOffset())
278     Expr = MCBinaryExpr::CreateAdd(Expr, MCConstantExpr::Create(MO.getOffset(),
279                                                                 OutContext),
280                                    OutContext);
281   return MCOperand::CreateExpr(Expr);
282 }
283
284
285
286 static void lower_subreg32(MCInst *MI, unsigned OpNo) {
287   // Convert registers in the addr mode according to subreg32.
288   unsigned Reg = MI->getOperand(OpNo).getReg();
289   if (Reg != 0)
290     MI->getOperand(OpNo).setReg(getX86SubSuperRegister(Reg, MVT::i32));
291 }
292
293 static void lower_lea64_32mem(MCInst *MI, unsigned OpNo) {
294   // Convert registers in the addr mode according to subreg64.
295   for (unsigned i = 0; i != 4; ++i) {
296     if (!MI->getOperand(OpNo+i).isReg()) continue;
297     
298     unsigned Reg = MI->getOperand(OpNo+i).getReg();
299     if (Reg == 0) continue;
300     
301     MI->getOperand(OpNo+i).setReg(getX86SubSuperRegister(Reg, MVT::i64));
302   }
303 }
304
305
306 void X86ATTAsmPrinter::
307 printInstructionThroughMCStreamer(const MachineInstr *MI) {
308   MCInst TmpInst;
309   switch (MI->getOpcode()) {
310   case TargetInstrInfo::DBG_LABEL:
311   case TargetInstrInfo::EH_LABEL:
312   case TargetInstrInfo::GC_LABEL:
313     printLabel(MI);
314     return;
315   case TargetInstrInfo::INLINEASM:
316     O << '\t';
317     printInlineAsm(MI);
318     return;
319   case TargetInstrInfo::IMPLICIT_DEF:
320     printImplicitDef(MI);
321     return;
322   case X86::MOVPC32r: {
323     // This is a pseudo op for a two instruction sequence with a label, which
324     // looks like:
325     //     call "L1$pb"
326     // "L1$pb":
327     //     popl %esi
328     
329     // Emit the call.
330     MCSymbol *PICBase = GetPICBaseSymbol();
331     TmpInst.setOpcode(X86::CALLpcrel32);
332     // FIXME: We would like an efficient form for this, so we don't have to do a
333     // lot of extra uniquing.
334     TmpInst.addOperand(MCOperand::CreateExpr(MCSymbolRefExpr::Create(PICBase,
335                                                                  OutContext)));
336     printInstruction(&TmpInst);
337     O << '\n';
338     
339     // Emit the label.
340     OutStreamer.EmitLabel(PICBase);
341     
342     // popl $reg
343     TmpInst.setOpcode(X86::POP32r);
344     TmpInst.getOperand(0) = MCOperand::CreateReg(MI->getOperand(0).getReg());
345     printInstruction(&TmpInst);
346     return;
347     }
348   }
349   
350   TmpInst.setOpcode(MI->getOpcode());
351   
352   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
353     const MachineOperand &MO = MI->getOperand(i);
354     
355     MCOperand MCOp;
356     switch (MO.getType()) {
357     default:
358       O.flush();
359       errs() << "Cannot lower operand #" << i << " of :" << *MI;
360       llvm_unreachable("Unimp");
361     case MachineOperand::MO_Register:
362       MCOp = MCOperand::CreateReg(MO.getReg());
363       break;
364     case MachineOperand::MO_Immediate:
365       MCOp = MCOperand::CreateImm(MO.getImm());
366       break;
367     case MachineOperand::MO_MachineBasicBlock:
368       MCOp = MCOperand::CreateMBBLabel(getFunctionNumber(), 
369                                        MO.getMBB()->getNumber());
370       break;
371     case MachineOperand::MO_GlobalAddress:
372       MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
373       break;
374     case MachineOperand::MO_ExternalSymbol:
375       MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
376       break;
377     case MachineOperand::MO_JumpTableIndex:
378       MCOp = LowerSymbolOperand(MO, GetJumpTableSymbol(MO));
379       break;
380     case MachineOperand::MO_ConstantPoolIndex:
381       MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO));
382       break;
383     }
384     
385     TmpInst.addOperand(MCOp);
386   }
387   
388   // Handle a few special cases to eliminate operand modifiers.
389   switch (TmpInst.getOpcode()) {
390   case X86::LEA64_32r: // Handle 'subreg rewriting' for the lea64_32mem operand.
391     lower_lea64_32mem(&TmpInst, 1);
392     break;
393   case X86::MOV16r0:
394     TmpInst.setOpcode(X86::MOV32r0);
395     lower_subreg32(&TmpInst, 0);
396     break;
397   case X86::MOVZX16rr8:
398     TmpInst.setOpcode(X86::MOVZX32rr8);
399     lower_subreg32(&TmpInst, 0);
400     break;
401   case X86::MOVZX16rm8:
402     TmpInst.setOpcode(X86::MOVZX32rm8);
403     lower_subreg32(&TmpInst, 0);
404     break;
405   case X86::MOVSX16rr8:
406     TmpInst.setOpcode(X86::MOVSX32rr8);
407     lower_subreg32(&TmpInst, 0);
408     break;
409   case X86::MOVSX16rm8:
410     TmpInst.setOpcode(X86::MOVSX32rm8);
411     lower_subreg32(&TmpInst, 0);
412     break;
413   case X86::MOVZX64rr32:
414     TmpInst.setOpcode(X86::MOV32rr);
415     lower_subreg32(&TmpInst, 0);
416     break;
417   case X86::MOVZX64rm32:
418     TmpInst.setOpcode(X86::MOV32rm);
419     lower_subreg32(&TmpInst, 0);
420     break;
421   case X86::MOV64ri64i32:
422     TmpInst.setOpcode(X86::MOV32ri);
423     lower_subreg32(&TmpInst, 0);
424     break;
425   case X86::MOVZX64rr8:
426     TmpInst.setOpcode(X86::MOVZX32rr8);
427     lower_subreg32(&TmpInst, 0);
428     break;
429   case X86::MOVZX64rm8:
430     TmpInst.setOpcode(X86::MOVZX32rm8);
431     lower_subreg32(&TmpInst, 0);
432     break;
433   case X86::MOVZX64rr16:
434     TmpInst.setOpcode(X86::MOVZX32rr16);
435     lower_subreg32(&TmpInst, 0);
436     break;
437   case X86::MOVZX64rm16:
438     TmpInst.setOpcode(X86::MOVZX32rm16);
439     lower_subreg32(&TmpInst, 0);
440     break;
441   }
442   
443   printInstruction(&TmpInst);
444 }