switch ELF @GOTOFF references to use X86MCTargetExpr.
[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 #include "X86MCInstLower.h"
16 #include "X86AsmPrinter.h"
17 #include "X86COFFMachineModuleInfo.h"
18 #include "X86MCAsmInfo.h"
19 #include "X86MCTargetExpr.h"
20 #include "llvm/Analysis/DebugInfo.h"
21 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
22 #include "llvm/MC/MCContext.h"
23 #include "llvm/MC/MCExpr.h"
24 #include "llvm/MC/MCInst.h"
25 #include "llvm/MC/MCStreamer.h"
26 #include "llvm/Target/Mangler.h"
27 #include "llvm/Support/FormattedStream.h"
28 #include "llvm/ADT/SmallString.h"
29 #include "llvm/Type.h"
30 using namespace llvm;
31
32
33 const X86Subtarget &X86MCInstLower::getSubtarget() const {
34   return AsmPrinter.getSubtarget();
35 }
36
37 MachineModuleInfoMachO &X86MCInstLower::getMachOMMI() const {
38   assert(getSubtarget().isTargetDarwin() &&"Can only get MachO info on darwin");
39   return AsmPrinter.MMI->getObjFileInfo<MachineModuleInfoMachO>(); 
40 }
41
42
43 MCSymbol *X86MCInstLower::GetPICBaseSymbol() const {
44   const TargetLowering *TLI = AsmPrinter.TM.getTargetLowering();
45   return static_cast<const X86TargetLowering*>(TLI)->
46     getPICBaseSymbol(AsmPrinter.MF, Ctx);
47 }
48
49 /// LowerGlobalAddressOperand - Lower an MO_GlobalAddress operand to an
50 /// MCOperand.
51 MCSymbol *X86MCInstLower::
52 GetGlobalAddressSymbol(const MachineOperand &MO) const {
53   const GlobalValue *GV = MO.getGlobal();
54   
55   bool isImplicitlyPrivate = false;
56   if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB ||
57       MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY ||
58       MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE ||
59       MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE)
60     isImplicitlyPrivate = true;
61   
62   SmallString<128> Name;
63   Mang->getNameWithPrefix(Name, GV, isImplicitlyPrivate);
64   
65   if (getSubtarget().isTargetCygMing()) {
66     X86COFFMachineModuleInfo &COFFMMI = 
67       AsmPrinter.MMI->getObjFileInfo<X86COFFMachineModuleInfo>();
68     COFFMMI.DecorateCygMingName(Name, GV, *AsmPrinter.TM.getTargetData());
69   }
70   
71   //X86MCTargetExpr::VariantKind Kind = X86MCTargetExpr::Invalid;
72   
73   switch (MO.getTargetFlags()) {
74   default: llvm_unreachable("Unknown target flag on GV operand");
75   case X86II::MO_NO_FLAG:                // No flag.
76   case X86II::MO_PIC_BASE_OFFSET:        // Doesn't modify symbol name.
77     break;
78   case X86II::MO_DLLIMPORT: {
79     // Handle dllimport linkage.
80     const char *Prefix = "__imp_";
81     Name.insert(Name.begin(), Prefix, Prefix+strlen(Prefix));
82     break;
83   }
84   case X86II::MO_DARWIN_NONLAZY:
85   case X86II::MO_DARWIN_NONLAZY_PIC_BASE: {
86     Name += "$non_lazy_ptr";
87     MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
88
89     MCSymbol *&StubSym = getMachOMMI().getGVStubEntry(Sym);
90     if (StubSym == 0)
91       StubSym = AsmPrinter.GetGlobalValueSymbol(GV);
92     return Sym;
93   }
94   case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: {
95     Name += "$non_lazy_ptr";
96     MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
97     MCSymbol *&StubSym = getMachOMMI().getHiddenGVStubEntry(Sym);
98     if (StubSym == 0)
99       StubSym = AsmPrinter.GetGlobalValueSymbol(GV);
100     return Sym;
101   }
102   case X86II::MO_DARWIN_STUB: {
103     Name += "$stub";
104     MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
105     MCSymbol *&StubSym = getMachOMMI().getFnStubEntry(Sym);
106     if (StubSym == 0)
107       StubSym = AsmPrinter.GetGlobalValueSymbol(GV);
108     return Sym;
109   }
110   // FIXME: These probably should be a modifier on the symbol or something??
111   case X86II::MO_TLSGD:     Name += "@TLSGD";     break;
112   case X86II::MO_GOTTPOFF:  Name += "@GOTTPOFF";  break;
113   case X86II::MO_INDNTPOFF: Name += "@INDNTPOFF"; break;
114   case X86II::MO_TPOFF:     Name += "@TPOFF";     break;
115   case X86II::MO_NTPOFF:    Name += "@NTPOFF";    break;
116   case X86II::MO_GOTPCREL:  Name += "@GOTPCREL";  break;
117   case X86II::MO_GOT:       Name += "@GOT";       break;
118   case X86II::MO_GOTOFF:    Name += "@GOTOFF";    break;
119   case X86II::MO_PLT:       Name += "@PLT";       break;
120   }
121
122   return Ctx.GetOrCreateSymbol(Name.str());
123 }
124
125 MCSymbol *X86MCInstLower::
126 GetExternalSymbolSymbol(const MachineOperand &MO) const {
127   SmallString<128> Name;
128   Name += AsmPrinter.MAI->getGlobalPrefix();
129   Name += MO.getSymbolName();
130   
131   switch (MO.getTargetFlags()) {
132   default: llvm_unreachable("Unknown target flag on GV operand");
133   case X86II::MO_NO_FLAG:                // No flag.
134   case X86II::MO_GOT_ABSOLUTE_ADDRESS:   // Doesn't modify symbol name.
135   case X86II::MO_PIC_BASE_OFFSET:        // Doesn't modify symbol name.
136     break;
137   case X86II::MO_DLLIMPORT: {
138     // Handle dllimport linkage.
139     const char *Prefix = "__imp_";
140     Name.insert(Name.begin(), Prefix, Prefix+strlen(Prefix));
141     break;
142   }
143   case X86II::MO_DARWIN_STUB: {
144     Name += "$stub";
145     MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
146     MCSymbol *&StubSym = getMachOMMI().getFnStubEntry(Sym);
147
148     if (StubSym == 0) {
149       Name.erase(Name.end()-5, Name.end());
150       StubSym = Ctx.GetOrCreateSymbol(Name.str());
151     }
152     return Sym;
153   }
154   // FIXME: These probably should be a modifier on the symbol or something??
155   case X86II::MO_TLSGD:     Name += "@TLSGD";     break;
156   case X86II::MO_GOTTPOFF:  Name += "@GOTTPOFF";  break;
157   case X86II::MO_INDNTPOFF: Name += "@INDNTPOFF"; break;
158   case X86II::MO_TPOFF:     Name += "@TPOFF";     break;
159   case X86II::MO_NTPOFF:    Name += "@NTPOFF";    break;
160   case X86II::MO_GOTPCREL:  Name += "@GOTPCREL";  break;
161   case X86II::MO_GOT:       Name += "@GOT";       break;
162   case X86II::MO_GOTOFF:    Name += "@GOTOFF";    break;
163   case X86II::MO_PLT:       Name += "@PLT";       break;
164   }
165   
166   return Ctx.GetOrCreateSymbol(Name.str());
167 }
168
169 MCSymbol *X86MCInstLower::GetJumpTableSymbol(const MachineOperand &MO) const {
170   SmallString<256> Name;
171   // FIXME: Use AsmPrinter.GetJTISymbol.  @TLSGD shouldn't be part of the symbol
172   // name!
173   raw_svector_ostream(Name) << AsmPrinter.MAI->getPrivateGlobalPrefix() << "JTI"
174     << AsmPrinter.getFunctionNumber() << '_' << MO.getIndex();
175   
176   switch (MO.getTargetFlags()) {
177   default:
178     llvm_unreachable("Unknown target flag on GV operand");
179   case X86II::MO_NO_FLAG:    // No flag.
180   case X86II::MO_PIC_BASE_OFFSET:
181   case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
182   case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
183     break;
184     // FIXME: These probably should be a modifier on the symbol or something??
185   case X86II::MO_TLSGD:     Name += "@TLSGD";     break;
186   case X86II::MO_GOTTPOFF:  Name += "@GOTTPOFF";  break;
187   case X86II::MO_INDNTPOFF: Name += "@INDNTPOFF"; break;
188   case X86II::MO_TPOFF:     Name += "@TPOFF";     break;
189   case X86II::MO_NTPOFF:    Name += "@NTPOFF";    break;
190   case X86II::MO_GOTPCREL:  Name += "@GOTPCREL";  break;
191   case X86II::MO_GOT:       Name += "@GOT";       break;
192   case X86II::MO_GOTOFF:    Name += "@GOTOFF";    break;
193   case X86II::MO_PLT:       Name += "@PLT";       break;
194   }
195   
196   // Create a symbol for the name.
197   return Ctx.GetOrCreateSymbol(Name.str());
198 }
199
200
201 MCSymbol *X86MCInstLower::
202 GetConstantPoolIndexSymbol(const MachineOperand &MO) const {
203   SmallString<256> Name;
204   // FIXME: USe AsmPrinter.GetCPISymbol.  @TLSGD shouldn't be part of the symbol
205   // name!
206   raw_svector_ostream(Name) << AsmPrinter.MAI->getPrivateGlobalPrefix() << "CPI"
207     << AsmPrinter.getFunctionNumber() << '_' << MO.getIndex();
208   
209   switch (MO.getTargetFlags()) {
210   default:
211     llvm_unreachable("Unknown target flag on GV operand");
212   case X86II::MO_NO_FLAG:    // No flag.
213   case X86II::MO_PIC_BASE_OFFSET:
214   case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
215   case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
216     break;
217     // FIXME: These probably should be a modifier on the symbol or something??
218   case X86II::MO_TLSGD:     Name += "@TLSGD";     break;
219   case X86II::MO_GOTTPOFF:  Name += "@GOTTPOFF";  break;
220   case X86II::MO_INDNTPOFF: Name += "@INDNTPOFF"; break;
221   case X86II::MO_TPOFF:     Name += "@TPOFF";     break;
222   case X86II::MO_NTPOFF:    Name += "@NTPOFF";    break;
223   case X86II::MO_GOTPCREL:  Name += "@GOTPCREL";  break;
224   case X86II::MO_GOT:       Name += "@GOT";       break;
225   case X86II::MO_GOTOFF:    Name += "@GOTOFF";    break;
226   case X86II::MO_PLT:       Name += "@PLT";       break;
227   }
228   
229   // Create a symbol for the name.
230   return Ctx.GetOrCreateSymbol(Name.str());
231 }
232
233 MCSymbol *X86MCInstLower::
234 GetBlockAddressSymbol(const MachineOperand &MO) const {
235   const char *Suffix = "";
236   switch (MO.getTargetFlags()) {
237   default: llvm_unreachable("Unknown target flag on BA operand");
238   case X86II::MO_NO_FLAG:         break; // No flag.
239   case X86II::MO_PIC_BASE_OFFSET: break; // Doesn't modify symbol name.
240   case X86II::MO_GOTOFF: Suffix = "@GOTOFF"; break;
241   }
242
243   return AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress(), Suffix);
244 }
245
246 MCOperand X86MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
247                                              MCSymbol *Sym) const {
248   // FIXME: We would like an efficient form for this, so we don't have to do a
249   // lot of extra uniquing.
250   const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx);
251   
252   switch (MO.getTargetFlags()) {
253   default: llvm_unreachable("Unknown target flag on GV operand");
254   case X86II::MO_NO_FLAG:    // No flag.
255       
256   // These affect the name of the symbol, not any suffix.
257   case X86II::MO_DARWIN_NONLAZY:
258   case X86II::MO_DLLIMPORT:
259   case X86II::MO_DARWIN_STUB:
260   case X86II::MO_TLSGD:
261   case X86II::MO_GOTTPOFF:
262   case X86II::MO_INDNTPOFF:
263   case X86II::MO_TPOFF:
264   case X86II::MO_NTPOFF:
265   case X86II::MO_GOTPCREL:
266   case X86II::MO_GOT:
267   case X86II::MO_GOTOFF:
268   case X86II::MO_PLT:
269     break;
270   case X86II::MO_PIC_BASE_OFFSET:
271   case X86II::MO_DARWIN_NONLAZY_PIC_BASE:
272   case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
273     // Subtract the pic base.
274     Expr = MCBinaryExpr::CreateSub(Expr, 
275                                MCSymbolRefExpr::Create(GetPICBaseSymbol(), Ctx),
276                                    Ctx);
277     break;
278   }
279   
280   if (!MO.isJTI() && MO.getOffset())
281     Expr = MCBinaryExpr::CreateAdd(Expr,
282                                    MCConstantExpr::Create(MO.getOffset(), Ctx),
283                                    Ctx);
284   return MCOperand::CreateExpr(Expr);
285 }
286
287
288
289 static void lower_subreg32(MCInst *MI, unsigned OpNo) {
290   // Convert registers in the addr mode according to subreg32.
291   unsigned Reg = MI->getOperand(OpNo).getReg();
292   if (Reg != 0)
293     MI->getOperand(OpNo).setReg(getX86SubSuperRegister(Reg, MVT::i32));
294 }
295
296 static void lower_lea64_32mem(MCInst *MI, unsigned OpNo) {
297   // Convert registers in the addr mode according to subreg64.
298   for (unsigned i = 0; i != 4; ++i) {
299     if (!MI->getOperand(OpNo+i).isReg()) continue;
300     
301     unsigned Reg = MI->getOperand(OpNo+i).getReg();
302     if (Reg == 0) continue;
303     
304     MI->getOperand(OpNo+i).setReg(getX86SubSuperRegister(Reg, MVT::i64));
305   }
306 }
307
308 /// LowerSubReg32_Op0 - Things like MOVZX16rr8 -> MOVZX32rr8.
309 static void LowerSubReg32_Op0(MCInst &OutMI, unsigned NewOpc) {
310   OutMI.setOpcode(NewOpc);
311   lower_subreg32(&OutMI, 0);
312 }
313 /// LowerUnaryToTwoAddr - R = setb   -> R = sbb R, R
314 static void LowerUnaryToTwoAddr(MCInst &OutMI, unsigned NewOpc) {
315   OutMI.setOpcode(NewOpc);
316   OutMI.addOperand(OutMI.getOperand(0));
317   OutMI.addOperand(OutMI.getOperand(0));
318 }
319
320
321 void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
322   OutMI.setOpcode(MI->getOpcode());
323   
324   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
325     const MachineOperand &MO = MI->getOperand(i);
326     
327     MCOperand MCOp;
328     switch (MO.getType()) {
329     default:
330       MI->dump();
331       llvm_unreachable("unknown operand type");
332     case MachineOperand::MO_Register:
333       // Ignore all implicit register operands.
334       if (MO.isImplicit()) continue;
335       MCOp = MCOperand::CreateReg(MO.getReg());
336       break;
337     case MachineOperand::MO_Immediate:
338       MCOp = MCOperand::CreateImm(MO.getImm());
339       break;
340     case MachineOperand::MO_MachineBasicBlock:
341       MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
342                        MO.getMBB()->getSymbol(Ctx), Ctx));
343       break;
344     case MachineOperand::MO_GlobalAddress:
345       MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
346       break;
347     case MachineOperand::MO_ExternalSymbol:
348       MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
349       break;
350     case MachineOperand::MO_JumpTableIndex:
351       MCOp = LowerSymbolOperand(MO, GetJumpTableSymbol(MO));
352       break;
353     case MachineOperand::MO_ConstantPoolIndex:
354       MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO));
355       break;
356     case MachineOperand::MO_BlockAddress:
357       MCOp = LowerSymbolOperand(MO, GetBlockAddressSymbol(MO));
358       break;
359     }
360     
361     OutMI.addOperand(MCOp);
362   }
363   
364   // Handle a few special cases to eliminate operand modifiers.
365   switch (OutMI.getOpcode()) {
366   case X86::LEA64_32r: // Handle 'subreg rewriting' for the lea64_32mem operand.
367     lower_lea64_32mem(&OutMI, 1);
368     break;
369   case X86::MOVZX16rr8:   LowerSubReg32_Op0(OutMI, X86::MOVZX32rr8); break;
370   case X86::MOVZX16rm8:   LowerSubReg32_Op0(OutMI, X86::MOVZX32rm8); break;
371   case X86::MOVSX16rr8:   LowerSubReg32_Op0(OutMI, X86::MOVSX32rr8); break;
372   case X86::MOVSX16rm8:   LowerSubReg32_Op0(OutMI, X86::MOVSX32rm8); break;
373   case X86::MOVZX64rr32:  LowerSubReg32_Op0(OutMI, X86::MOV32rr); break;
374   case X86::MOVZX64rm32:  LowerSubReg32_Op0(OutMI, X86::MOV32rm); break;
375   case X86::MOV64ri64i32: LowerSubReg32_Op0(OutMI, X86::MOV32ri); break;
376   case X86::MOVZX64rr8:   LowerSubReg32_Op0(OutMI, X86::MOVZX32rr8); break;
377   case X86::MOVZX64rm8:   LowerSubReg32_Op0(OutMI, X86::MOVZX32rm8); break;
378   case X86::MOVZX64rr16:  LowerSubReg32_Op0(OutMI, X86::MOVZX32rr16); break;
379   case X86::MOVZX64rm16:  LowerSubReg32_Op0(OutMI, X86::MOVZX32rm16); break;
380   case X86::SETB_C8r:     LowerUnaryToTwoAddr(OutMI, X86::SBB8rr); break;
381   case X86::SETB_C16r:    LowerUnaryToTwoAddr(OutMI, X86::SBB16rr); break;
382   case X86::SETB_C32r:    LowerUnaryToTwoAddr(OutMI, X86::SBB32rr); break;
383   case X86::SETB_C64r:    LowerUnaryToTwoAddr(OutMI, X86::SBB64rr); break;
384   case X86::MOV8r0:       LowerUnaryToTwoAddr(OutMI, X86::XOR8rr); break;
385   case X86::MOV32r0:      LowerUnaryToTwoAddr(OutMI, X86::XOR32rr); break;
386   case X86::MMX_V_SET0:   LowerUnaryToTwoAddr(OutMI, X86::MMX_PXORrr); break;
387   case X86::MMX_V_SETALLONES:
388     LowerUnaryToTwoAddr(OutMI, X86::MMX_PCMPEQDrr); break;
389   case X86::FsFLD0SS:     LowerUnaryToTwoAddr(OutMI, X86::PXORrr); break;
390   case X86::FsFLD0SD:     LowerUnaryToTwoAddr(OutMI, X86::PXORrr); break;
391   case X86::V_SET0:       LowerUnaryToTwoAddr(OutMI, X86::XORPSrr); break;
392   case X86::V_SETALLONES: LowerUnaryToTwoAddr(OutMI, X86::PCMPEQDrr); break;
393
394   case X86::MOV16r0:
395     LowerSubReg32_Op0(OutMI, X86::MOV32r0);   // MOV16r0 -> MOV32r0
396     LowerUnaryToTwoAddr(OutMI, X86::XOR32rr); // MOV32r0 -> XOR32rr
397     break;
398   case X86::MOV64r0:
399     LowerSubReg32_Op0(OutMI, X86::MOV32r0);   // MOV64r0 -> MOV32r0
400     LowerUnaryToTwoAddr(OutMI, X86::XOR32rr); // MOV32r0 -> XOR32rr
401     break;
402   }
403 }
404
405
406
407 void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
408   X86MCInstLower MCInstLowering(OutContext, Mang, *this);
409   switch (MI->getOpcode()) {
410   case TargetInstrInfo::DEBUG_VALUE: {
411     // FIXME: if this is implemented for another target before it goes
412     // away completely, the common part should be moved into AsmPrinter.
413     if (!VerboseAsm)
414       return;
415     O << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
416     unsigned NOps = MI->getNumOperands();
417     // cast away const; DIetc do not take const operands for some reason.
418     DIVariable V((MDNode*)(MI->getOperand(NOps-1).getMetadata()));
419     O << V.getName();
420     O << " <- ";
421     if (NOps==3) {
422       // Register or immediate value. Register 0 means undef.
423       assert(MI->getOperand(0).getType()==MachineOperand::MO_Register ||
424              MI->getOperand(0).getType()==MachineOperand::MO_Immediate ||
425              MI->getOperand(0).getType()==MachineOperand::MO_FPImmediate);
426       if (MI->getOperand(0).getType()==MachineOperand::MO_Register &&
427           MI->getOperand(0).getReg()==0) {
428         // Suppress offset in this case, it is not meaningful.
429         O << "undef\n";
430         return;
431       } else if (MI->getOperand(0).getType()==MachineOperand::MO_FPImmediate) {
432         // This is more naturally done in printOperand, but since the only use
433         // of such an operand is in this comment and that is temporary (and it's
434         // ugly), we prefer to keep this localized.
435         // The include of Type.h may be removable when this code is.
436         if (MI->getOperand(0).getFPImm()->getType()->isFloatTy() ||
437             MI->getOperand(0).getFPImm()->getType()->isDoubleTy())
438           MI->getOperand(0).print(O, &TM);
439         else {
440           // There is no good way to print long double.  Convert a copy to
441           // double.  Ah well, it's only a comment.
442           bool ignored;
443           APFloat APF = APFloat(MI->getOperand(0).getFPImm()->getValueAPF());
444           APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven,
445                       &ignored);
446           O << "(long double) " << APF.convertToDouble();
447         }
448       } else
449         printOperand(MI, 0);
450     } else {
451       // Frame address.  Currently handles register +- offset only.
452       assert(MI->getOperand(0).getType()==MachineOperand::MO_Register);
453       assert(MI->getOperand(3).getType()==MachineOperand::MO_Immediate);
454       O << '['; printOperand(MI, 0); O << '+'; printOperand(MI, 3); O << ']';
455     }
456     O << "+";
457     printOperand(MI, NOps-2);
458     O << '\n';
459     return;
460   }
461   case X86::MOVPC32r: {
462     MCInst TmpInst;
463     // This is a pseudo op for a two instruction sequence with a label, which
464     // looks like:
465     //     call "L1$pb"
466     // "L1$pb":
467     //     popl %esi
468     
469     // Emit the call.
470     MCSymbol *PICBase = MCInstLowering.GetPICBaseSymbol();
471     TmpInst.setOpcode(X86::CALLpcrel32);
472     // FIXME: We would like an efficient form for this, so we don't have to do a
473     // lot of extra uniquing.
474     TmpInst.addOperand(MCOperand::CreateExpr(MCSymbolRefExpr::Create(PICBase,
475                                                                  OutContext)));
476     OutStreamer.EmitInstruction(TmpInst);
477     
478     // Emit the label.
479     OutStreamer.EmitLabel(PICBase);
480     
481     // popl $reg
482     TmpInst.setOpcode(X86::POP32r);
483     TmpInst.getOperand(0) = MCOperand::CreateReg(MI->getOperand(0).getReg());
484     OutStreamer.EmitInstruction(TmpInst);
485     return;
486   }
487       
488   case X86::ADD32ri: {
489     // Lower the MO_GOT_ABSOLUTE_ADDRESS form of ADD32ri.
490     if (MI->getOperand(2).getTargetFlags() != X86II::MO_GOT_ABSOLUTE_ADDRESS)
491       break;
492     
493     // Okay, we have something like:
494     //  EAX = ADD32ri EAX, MO_GOT_ABSOLUTE_ADDRESS(@MYGLOBAL)
495     
496     // For this, we want to print something like:
497     //   MYGLOBAL + (. - PICBASE)
498     // However, we can't generate a ".", so just emit a new label here and refer
499     // to it.  We know that this operand flag occurs at most once per function.
500     const char *Prefix = MAI->getPrivateGlobalPrefix();
501     MCSymbol *DotSym = OutContext.GetOrCreateSymbol(Twine(Prefix)+"picbaseref"+
502                                                     Twine(getFunctionNumber()));
503     OutStreamer.EmitLabel(DotSym);
504     
505     // Now that we have emitted the label, lower the complex operand expression.
506     MCSymbol *OpSym = MCInstLowering.GetExternalSymbolSymbol(MI->getOperand(2));
507     
508     const MCExpr *DotExpr = MCSymbolRefExpr::Create(DotSym, OutContext);
509     const MCExpr *PICBase =
510       MCSymbolRefExpr::Create(MCInstLowering.GetPICBaseSymbol(), OutContext);
511     DotExpr = MCBinaryExpr::CreateSub(DotExpr, PICBase, OutContext);
512     
513     DotExpr = MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(OpSym,OutContext), 
514                                       DotExpr, OutContext);
515     
516     MCInst TmpInst;
517     TmpInst.setOpcode(X86::ADD32ri);
518     TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
519     TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
520     TmpInst.addOperand(MCOperand::CreateExpr(DotExpr));
521     OutStreamer.EmitInstruction(TmpInst);
522     return;
523   }
524   }
525   
526   MCInst TmpInst;
527   MCInstLowering.Lower(MI, TmpInst);
528   
529   
530   OutStreamer.EmitInstruction(TmpInst);
531 }
532