Finally eliminate printMCInst and send instructions through
[oota-llvm.git] / lib / Target / X86 / AsmPrinter / X86MCInstLower.cpp
index 9946506441b27dc0a434bb7a0b85f0bb0ee27aa5..eb60a8c1c1ae707103ee39bcaa862d0004521952 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #include "X86MCInstLower.h"
-#include "X86ATTAsmPrinter.h"
+#include "X86AsmPrinter.h"
 #include "X86MCAsmInfo.h"
+#include "X86COFFMachineModuleInfo.h"
+#include "llvm/Analysis/DebugInfo.h"
+#include "llvm/CodeGen/MachineModuleInfoImpls.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCStreamer.h"
+#include "llvm/Target/Mangler.h"
 #include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/Mangler.h"
 #include "llvm/ADT/SmallString.h"
 using namespace llvm;
 
@@ -29,33 +32,18 @@ const X86Subtarget &X86MCInstLower::getSubtarget() const {
   return AsmPrinter.getSubtarget();
 }
 
-
-MCSymbol *X86MCInstLower::GetPICBaseSymbol() const {
-  // FIXME: the actual label generated doesn't matter here!  Just mangle in
-  // something unique (the function number) with Private prefix.
-  SmallString<60> Name;
-  
-  if (getSubtarget().isTargetDarwin()) {
-    raw_svector_ostream(Name) << 'L' << AsmPrinter.getFunctionNumber() << "$pb";
-  } else {
-    assert(getSubtarget().isTargetELF() && "Don't know how to print PIC label!");
-    raw_svector_ostream(Name) << ".Lllvm$" << AsmPrinter.getFunctionNumber()
-       << ".$piclabel";
-  }
-  return Ctx.GetOrCreateSymbol(Name.str());
+MachineModuleInfoMachO &X86MCInstLower::getMachOMMI() const {
+  assert(getSubtarget().isTargetDarwin() &&"Can only get MachO info on darwin");
+  return AsmPrinter.MMI->getObjFileInfo<MachineModuleInfoMachO>(); 
 }
 
-MCOperand X86MCInstLower::LowerMBBOperand(const MachineOperand &MO) const {
-  SmallString<60> Name;
-  raw_svector_ostream(Name) << AsmPrinter.MAI->getPrivateGlobalPrefix() << "BB"
-      << AsmPrinter.getFunctionNumber() << '_' << MO.getMBB()->getNumber();
 
-  MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
-  return MCOperand::CreateExpr(MCSymbolRefExpr::Create(Sym, Ctx));
+MCSymbol *X86MCInstLower::GetPICBaseSymbol() const {
+  const TargetLowering *TLI = AsmPrinter.TM.getTargetLowering();
+  return static_cast<const X86TargetLowering*>(TLI)->
+    getPICBaseSymbol(AsmPrinter.MF, Ctx);
 }
 
-
-
 /// LowerGlobalAddressOperand - Lower an MO_GlobalAddress operand to an
 /// MCOperand.
 MCSymbol *X86MCInstLower::
@@ -72,13 +60,15 @@ GetGlobalAddressSymbol(const MachineOperand &MO) const {
   SmallString<128> Name;
   Mang->getNameWithPrefix(Name, GV, isImplicitlyPrivate);
   
-  if (getSubtarget().isTargetCygMing())
-    AsmPrinter.DecorateCygMingName(Name, GV);
+  if (getSubtarget().isTargetCygMing()) {
+    X86COFFMachineModuleInfo &COFFMMI = 
+      AsmPrinter.MMI->getObjFileInfo<X86COFFMachineModuleInfo>();
+    COFFMMI.DecorateCygMingName(Name, GV, *AsmPrinter.TM.getTargetData());
+  }
   
   switch (MO.getTargetFlags()) {
   default: llvm_unreachable("Unknown target flag on GV operand");
   case X86II::MO_NO_FLAG:                // No flag.
-  case X86II::MO_GOT_ABSOLUTE_ADDRESS:   // Doesn't modify symbol name.
   case X86II::MO_PIC_BASE_OFFSET:        // Doesn't modify symbol name.
     break;
   case X86II::MO_DLLIMPORT: {
@@ -91,34 +81,26 @@ GetGlobalAddressSymbol(const MachineOperand &MO) const {
   case X86II::MO_DARWIN_NONLAZY_PIC_BASE: {
     Name += "$non_lazy_ptr";
     MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
-    MCSymbol *&StubSym = AsmPrinter.GVStubs[Sym];
-    if (StubSym == 0) {
-      Name.clear();
-      Mang->getNameWithPrefix(Name, GV, false);
-      StubSym = Ctx.GetOrCreateSymbol(Name.str());
-    }
+
+    const MCSymbol *&StubSym = getMachOMMI().getGVStubEntry(Sym);
+    if (StubSym == 0)
+      StubSym = AsmPrinter.GetGlobalValueSymbol(GV);
     return Sym;
   }
   case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: {
     Name += "$non_lazy_ptr";
     MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
-    MCSymbol *&StubSym = AsmPrinter.HiddenGVStubs[Sym];
-    if (StubSym == 0) {
-      Name.clear();
-      Mang->getNameWithPrefix(Name, GV, false);
-      StubSym = Ctx.GetOrCreateSymbol(Name.str());
-    }
+    const MCSymbol *&StubSym = getMachOMMI().getHiddenGVStubEntry(Sym);
+    if (StubSym == 0)
+      StubSym = AsmPrinter.GetGlobalValueSymbol(GV);
     return Sym;
   }
   case X86II::MO_DARWIN_STUB: {
     Name += "$stub";
     MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
-    MCSymbol *&StubSym = AsmPrinter.FnStubs[Sym];
-    if (StubSym == 0) {
-      Name.clear();
-      Mang->getNameWithPrefix(Name, GV, false);
-      StubSym = Ctx.GetOrCreateSymbol(Name.str());
-    }
+    const MCSymbol *&StubSym = getMachOMMI().getFnStubEntry(Sym);
+    if (StubSym == 0)
+      StubSym = AsmPrinter.GetGlobalValueSymbol(GV);
     return Sym;
   }
   // FIXME: These probably should be a modifier on the symbol or something??
@@ -157,7 +139,8 @@ GetExternalSymbolSymbol(const MachineOperand &MO) const {
   case X86II::MO_DARWIN_STUB: {
     Name += "$stub";
     MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
-    MCSymbol *&StubSym = AsmPrinter.FnStubs[Sym];
+    const MCSymbol *&StubSym = getMachOMMI().getFnStubEntry(Sym);
+
     if (StubSym == 0) {
       Name.erase(Name.end()-5, Name.end());
       StubSym = Ctx.GetOrCreateSymbol(Name.str());
@@ -181,6 +164,8 @@ GetExternalSymbolSymbol(const MachineOperand &MO) const {
 
 MCSymbol *X86MCInstLower::GetJumpTableSymbol(const MachineOperand &MO) const {
   SmallString<256> Name;
+  // FIXME: Use AsmPrinter.GetJTISymbol.  @TLSGD shouldn't be part of the symbol
+  // name!
   raw_svector_ostream(Name) << AsmPrinter.MAI->getPrivateGlobalPrefix() << "JTI"
     << AsmPrinter.getFunctionNumber() << '_' << MO.getIndex();
   
@@ -212,6 +197,8 @@ MCSymbol *X86MCInstLower::GetJumpTableSymbol(const MachineOperand &MO) const {
 MCSymbol *X86MCInstLower::
 GetConstantPoolIndexSymbol(const MachineOperand &MO) const {
   SmallString<256> Name;
+  // FIXME: USe AsmPrinter.GetCPISymbol.  @TLSGD shouldn't be part of the symbol
+  // name!
   raw_svector_ostream(Name) << AsmPrinter.MAI->getPrivateGlobalPrefix() << "CPI"
     << AsmPrinter.getFunctionNumber() << '_' << MO.getIndex();
   
@@ -239,6 +226,19 @@ GetConstantPoolIndexSymbol(const MachineOperand &MO) const {
   return Ctx.GetOrCreateSymbol(Name.str());
 }
 
+MCSymbol *X86MCInstLower::
+GetBlockAddressSymbol(const MachineOperand &MO) const {
+  const char *Suffix = "";
+  switch (MO.getTargetFlags()) {
+  default: llvm_unreachable("Unknown target flag on BA operand");
+  case X86II::MO_NO_FLAG:         break; // No flag.
+  case X86II::MO_PIC_BASE_OFFSET: break; // Doesn't modify symbol name.
+  case X86II::MO_GOTOFF: Suffix = "@GOTOFF"; break;
+  }
+
+  return AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress(), Suffix);
+}
+
 MCOperand X86MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
                                              MCSymbol *Sym) const {
   // FIXME: We would like an efficient form for this, so we don't have to do a
@@ -268,29 +268,9 @@ MCOperand X86MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
   case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE:
     // Subtract the pic base.
     Expr = MCBinaryExpr::CreateSub(Expr, 
-                                   MCSymbolRefExpr::Create(GetPICBaseSymbol(),
-                                                           Ctx),
+                               MCSymbolRefExpr::Create(GetPICBaseSymbol(), Ctx),
                                    Ctx);
     break;
-  case X86II::MO_GOT_ABSOLUTE_ADDRESS: {
-    // For this, we want to print something like:
-    //   MYSYMBOL + (. - PICBASE)
-    // However, we can't generate a ".", so just emit a new label here and refer
-    // to it.  We know that this operand flag occurs at most once per function.
-    SmallString<64> Name;
-    raw_svector_ostream(Name) << AsmPrinter.MAI->getPrivateGlobalPrefix()
-      << "picbaseref" << AsmPrinter.getFunctionNumber();
-    MCSymbol *DotSym = Ctx.GetOrCreateSymbol(Name.str());
-// FIXME: This instruction should be lowered before we get here...    
-    AsmPrinter.OutStreamer.EmitLabel(DotSym);
-
-    const MCExpr *DotExpr = MCSymbolRefExpr::Create(DotSym, Ctx);
-    const MCExpr *PICBase = MCSymbolRefExpr::Create(GetPICBaseSymbol(),
-                                                    Ctx);
-    DotExpr = MCBinaryExpr::CreateSub(DotExpr, PICBase, Ctx);
-    Expr = MCBinaryExpr::CreateAdd(Expr, DotExpr, Ctx);
-    break;      
-  }
   }
   
   if (!MO.isJTI() && MO.getOffset())
@@ -335,13 +315,16 @@ void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
       MI->dump();
       llvm_unreachable("unknown operand type");
     case MachineOperand::MO_Register:
+      // Ignore all implicit register operands.
+      if (MO.isImplicit()) continue;
       MCOp = MCOperand::CreateReg(MO.getReg());
       break;
     case MachineOperand::MO_Immediate:
       MCOp = MCOperand::CreateImm(MO.getImm());
       break;
     case MachineOperand::MO_MachineBasicBlock:
-      MCOp = LowerMBBOperand(MO);
+      MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
+                       MO.getMBB()->getSymbol(Ctx), Ctx));
       break;
     case MachineOperand::MO_GlobalAddress:
       MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
@@ -355,6 +338,9 @@ void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
     case MachineOperand::MO_ConstantPoolIndex:
       MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO));
       break;
+    case MachineOperand::MO_BlockAddress:
+      MCOp = LowerSymbolOperand(MO, GetBlockAddressSymbol(MO));
+      break;
     }
     
     OutMI.addOperand(MCOp);
@@ -365,10 +351,6 @@ void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
   case X86::LEA64_32r: // Handle 'subreg rewriting' for the lea64_32mem operand.
     lower_lea64_32mem(&OutMI, 1);
     break;
-  case X86::MOV16r0:
-    OutMI.setOpcode(X86::MOV32r0);
-    lower_subreg32(&OutMI, 0);
-    break;
   case X86::MOVZX16rr8:
     OutMI.setOpcode(X86::MOVZX32rr8);
     lower_subreg32(&OutMI, 0);
@@ -413,27 +395,62 @@ void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
     OutMI.setOpcode(X86::MOVZX32rm16);
     lower_subreg32(&OutMI, 0);
     break;
+  case X86::MOV16r0:
+    OutMI.setOpcode(X86::MOV32r0);
+    lower_subreg32(&OutMI, 0);
+    break;
+  case X86::MOV64r0:
+    OutMI.setOpcode(X86::MOV32r0);
+    lower_subreg32(&OutMI, 0);
+    break;
   }
 }
 
 
 
-void X86ATTAsmPrinter::
-printInstructionThroughMCStreamer(const MachineInstr *MI) {
+void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
   X86MCInstLower MCInstLowering(OutContext, Mang, *this);
   switch (MI->getOpcode()) {
-  case TargetInstrInfo::DBG_LABEL:
-  case TargetInstrInfo::EH_LABEL:
-  case TargetInstrInfo::GC_LABEL:
-    printLabel(MI);
-    return;
-  case TargetInstrInfo::INLINEASM:
-    O << '\t';
-    printInlineAsm(MI);
-    return;
-  case TargetInstrInfo::IMPLICIT_DEF:
-    printImplicitDef(MI);
+  case TargetInstrInfo::DEBUG_VALUE: {
+    // FIXME: if this is implemented for another target before it goes
+    // away completely, the common part should be moved into AsmPrinter.
+    if (!VerboseAsm)
+      return;
+    O << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
+    unsigned NOps = MI->getNumOperands();
+    // cast away const; DIetc do not take const operands for some reason.
+    DIVariable V((MDNode*)(MI->getOperand(NOps-1).getMetadata()));
+    O << V.getName();
+    O << " <- ";
+    if (NOps==3) {
+      // Register or immediate value. Register 0 means undef.
+      assert(MI->getOperand(0).getType()==MachineOperand::MO_Register ||
+             MI->getOperand(0).getType()==MachineOperand::MO_Immediate ||
+             MI->getOperand(0).getType()==MachineOperand::MO_FPImmediate);
+      if (MI->getOperand(0).getType()==MachineOperand::MO_Register &&
+          MI->getOperand(0).getReg()==0) {
+        // Suppress offset in this case, it is not meaningful.
+        O << "undef";
+        return;
+      } else if (MI->getOperand(0).getType()==MachineOperand::MO_FPImmediate) {
+        // This is more naturally done in printOperand, but since the only use
+        // of such an operand is in this comment and that is temporary, we
+        // prefer to keep this localized.
+        O << '$';
+        MI->getOperand(0).print(O, &TM);
+      } else
+        printOperand(MI, 0);
+    } else {
+      // Frame address.  Currently handles register +- offset only.
+      assert(MI->getOperand(0).getType()==MachineOperand::MO_Register);
+      assert(MI->getOperand(3).getType()==MachineOperand::MO_Immediate);
+      O << '['; printOperand(MI, 0); O << '+'; printOperand(MI, 3); O << ']';
+    }
+    O << "+";
+    printOperand(MI, NOps-2);
+    O << '\n';
     return;
+  }
   case X86::MOVPC32r: {
     MCInst TmpInst;
     // This is a pseudo op for a two instruction sequence with a label, which
@@ -449,8 +466,7 @@ printInstructionThroughMCStreamer(const MachineInstr *MI) {
     // lot of extra uniquing.
     TmpInst.addOperand(MCOperand::CreateExpr(MCSymbolRefExpr::Create(PICBase,
                                                                  OutContext)));
-    printInstruction(&TmpInst);
-    O << '\n';
+    OutStreamer.EmitInstruction(TmpInst);
     
     // Emit the label.
     OutStreamer.EmitLabel(PICBase);
@@ -458,14 +474,52 @@ printInstructionThroughMCStreamer(const MachineInstr *MI) {
     // popl $reg
     TmpInst.setOpcode(X86::POP32r);
     TmpInst.getOperand(0) = MCOperand::CreateReg(MI->getOperand(0).getReg());
-    printInstruction(&TmpInst);
+    OutStreamer.EmitInstruction(TmpInst);
     return;
-    }
+  }
+      
+  case X86::ADD32ri: {
+    // Lower the MO_GOT_ABSOLUTE_ADDRESS form of ADD32ri.
+    if (MI->getOperand(2).getTargetFlags() != X86II::MO_GOT_ABSOLUTE_ADDRESS)
+      break;
+    
+    // Okay, we have something like:
+    //  EAX = ADD32ri EAX, MO_GOT_ABSOLUTE_ADDRESS(@MYGLOBAL)
+    
+    // For this, we want to print something like:
+    //   MYGLOBAL + (. - PICBASE)
+    // However, we can't generate a ".", so just emit a new label here and refer
+    // to it.  We know that this operand flag occurs at most once per function.
+    const char *Prefix = MAI->getPrivateGlobalPrefix();
+    MCSymbol *DotSym = OutContext.GetOrCreateSymbol(Twine(Prefix)+"picbaseref"+
+                                                    Twine(getFunctionNumber()));
+    OutStreamer.EmitLabel(DotSym);
+    
+    // Now that we have emitted the label, lower the complex operand expression.
+    MCSymbol *OpSym = MCInstLowering.GetExternalSymbolSymbol(MI->getOperand(2));
+    
+    const MCExpr *DotExpr = MCSymbolRefExpr::Create(DotSym, OutContext);
+    const MCExpr *PICBase =
+      MCSymbolRefExpr::Create(MCInstLowering.GetPICBaseSymbol(), OutContext);
+    DotExpr = MCBinaryExpr::CreateSub(DotExpr, PICBase, OutContext);
+    
+    DotExpr = MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(OpSym,OutContext), 
+                                      DotExpr, OutContext);
+    
+    MCInst TmpInst;
+    TmpInst.setOpcode(X86::ADD32ri);
+    TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
+    TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
+    TmpInst.addOperand(MCOperand::CreateExpr(DotExpr));
+    OutStreamer.EmitInstruction(TmpInst);
+    return;
+  }
   }
   
   MCInst TmpInst;
   MCInstLowering.Lower(MI, TmpInst);
   
   
-  printInstruction(&TmpInst);
+  OutStreamer.EmitInstruction(TmpInst);
 }
+