assert(0) -> LLVM_UNREACHABLE.
[oota-llvm.git] / lib / Target / X86 / AsmPrinter / X86ATTInstPrinter.cpp
index 0267c4e58071619361f38e3c5c150f6af2cb7d08..6b9167f40930c4dc6b9856173e91ea5243d4f16d 100644 (file)
@@ -15,6 +15,8 @@
 #define DEBUG_TYPE "asm-printer"
 #include "llvm/MC/MCInst.h"
 #include "X86ATTAsmPrinter.h"
+#include "llvm/Target/TargetAsmInfo.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace llvm;
 
@@ -25,9 +27,8 @@ using namespace llvm;
 #undef MachineInstr
 
 void X86ATTAsmPrinter::printSSECC(const MCInst *MI, unsigned Op) {
-  unsigned char value = MI->getOperand(Op).getImm();
-  assert(value <= 7 && "Invalid ssecc argument!");
-  switch (value) {
+  switch (MI->getOperand(Op).getImm()) {
+  default: LLVM_UNREACHABLE( "Invalid ssecc argument!");
   case 0: O << "eq"; break;
   case 1: O << "lt"; break;
   case 2: O << "le"; break;
@@ -41,14 +42,32 @@ void X86ATTAsmPrinter::printSSECC(const MCInst *MI, unsigned Op) {
 
 
 void X86ATTAsmPrinter::printPICLabel(const MCInst *MI, unsigned Op) {
-  assert(0 &&
+  LLVM_UNREACHABLE(
          "This is only used for MOVPC32r, should lower before asm printing!");
 }
 
 
+/// print_pcrel_imm - This is used to print an immediate value that ends up
+/// being encoded as a pc-relative value.  These print slightly differently, for
+/// example, a $ is not emitted.
+void X86ATTAsmPrinter::print_pcrel_imm(const MCInst *MI, unsigned OpNo) {
+  const MCOperand &Op = MI->getOperand(OpNo);
+  
+  if (Op.isImm())
+    O << Op.getImm();
+  else if (Op.isMBBLabel())
+    // FIXME: Keep in sync with printBasicBlockLabel.  printBasicBlockLabel
+    // should eventually call into this code, not the other way around.
+    O << TAI->getPrivateGlobalPrefix() << "BB" << Op.getMBBLabelFunction()
+      << '_' << Op.getMBBLabelBlock();
+  else
+    LLVM_UNREACHABLE( "Unknown pcrel immediate operand");
+}
+
+
 void X86ATTAsmPrinter::printOperand(const MCInst *MI, unsigned OpNo,
-                                    const char *Modifier, bool NotRIPRel) {
-  //assert(Modifier == 0 && "Modifiers should not be used");
+                                    const char *Modifier) {
+  assert(Modifier == 0 && "Modifiers should not be used");
   
   const MCOperand &Op = MI->getOperand(OpNo);
   if (Op.isReg()) {
@@ -65,320 +84,47 @@ void X86ATTAsmPrinter::printOperand(const MCInst *MI, unsigned OpNo,
     O << TRI->getAsmName(Reg);
     return;
   } else if (Op.isImm()) {
-    //if (!Modifier || (strcmp(Modifier, "debug") && strcmp(Modifier, "mem") &&
-    // strcmp(Modifier, "call")))
+    //if (!Modifier || (strcmp(Modifier, "debug") && strcmp(Modifier, "mem")))
     O << '$';
     O << Op.getImm();
     return;
   }
   
   O << "<<UNKNOWN OPERAND KIND>>";
-  
-  
-#if 0
-  const MachineOperand &MO = MI->getOperand(OpNo);
-  switch (MO.getType()) {
-    case MachineOperand::MO_Register: {
-      assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
-             "Virtual registers should not make it this far!");
-      O << '%';
-      unsigned Reg = MO.getReg();
-      if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) {
-        MVT VT = (strcmp(Modifier+6,"64") == 0) ?
-        MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 :
-                    ((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8));
-        Reg = getX86SubSuperRegister(Reg, VT);
-      }
-      O << TRI->getAsmName(Reg);
-      return;
-    }
-      
-    case MachineOperand::MO_Immediate:
-      if (!Modifier || (strcmp(Modifier, "debug") &&
-                        strcmp(Modifier, "mem") &&
-                        strcmp(Modifier, "call")))
-        O << '$';
-      O << MO.getImm();
-      return;
-    case MachineOperand::MO_MachineBasicBlock:
-      printBasicBlockLabel(MO.getMBB(), false, false, VerboseAsm);
-      return;
-    case MachineOperand::MO_JumpTableIndex: {
-      bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
-      if (!isMemOp) O << '$';
-      O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
-      << MO.getIndex();
-      
-      if (TM.getRelocationModel() == Reloc::PIC_) {
-        if (Subtarget->isPICStyleStub())
-          O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
-          << "$pb\"";
-        else if (Subtarget->isPICStyleGOT())
-          O << "@GOTOFF";
-      }
-      
-      if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel)
-        O << "(%rip)";
-      return;
-    }
-    case MachineOperand::MO_ConstantPoolIndex: {
-      bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
-      if (!isMemOp) O << '$';
-      O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
-      << MO.getIndex();
-      
-      if (TM.getRelocationModel() == Reloc::PIC_) {
-        if (Subtarget->isPICStyleStub())
-          O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
-          << "$pb\"";
-        else if (Subtarget->isPICStyleGOT())
-          O << "@GOTOFF";
-      }
-      
-      printOffset(MO.getOffset());
-      
-      if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel)
-        O << "(%rip)";
-      return;
-    }
-    case MachineOperand::MO_GlobalAddress: {
-      bool isCallOp = Modifier && !strcmp(Modifier, "call");
-      bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
-      bool needCloseParen = false;
-      
-      const GlobalValue *GV = MO.getGlobal();
-      const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
-      if (!GVar) {
-        // If GV is an alias then use the aliasee for determining
-        // thread-localness.
-        if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
-          GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal(false));
-      }
-      
-      bool isThreadLocal = GVar && GVar->isThreadLocal();
-      
-      std::string Name = Mang->getValueName(GV);
-      decorateName(Name, GV);
-      
-      if (!isMemOp && !isCallOp)
-        O << '$';
-      else if (Name[0] == '$') {
-        // The name begins with a dollar-sign. In order to avoid having it look
-        // like an integer immediate to the assembler, enclose it in parens.
-        O << '(';
-        needCloseParen = true;
-      }
-      
-      if (shouldPrintStub(TM, Subtarget)) {
-        // Link-once, declaration, or Weakly-linked global variables need
-        // non-lazily-resolved stubs
-        if (GV->isDeclaration() || GV->isWeakForLinker()) {
-          // Dynamically-resolved functions need a stub for the function.
-          if (isCallOp && isa<Function>(GV)) {
-            // Function stubs are no longer needed for Mac OS X 10.5 and up.
-            if (Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9) {
-              O << Name;
-            } else {
-              FnStubs.insert(Name);
-              printSuffixedName(Name, "$stub");
-            }
-          } else if (GV->hasHiddenVisibility()) {
-            if (!GV->isDeclaration() && !GV->hasCommonLinkage())
-              // Definition is not definitely in the current translation unit.
-              O << Name;
-            else {
-              HiddenGVStubs.insert(Name);
-              printSuffixedName(Name, "$non_lazy_ptr");
-            }
-          } else {
-            GVStubs.insert(Name);
-            printSuffixedName(Name, "$non_lazy_ptr");
-          }
-        } else {
-          if (GV->hasDLLImportLinkage())
-            O << "__imp_";
-          O << Name;
-        }
-        
-        if (!isCallOp && TM.getRelocationModel() == Reloc::PIC_)
-          O << '-' << getPICLabelString(getFunctionNumber(), TAI, Subtarget);
-      } else {
-        if (GV->hasDLLImportLinkage()) {
-          O << "__imp_";
-        }
-        O << Name;
-        
-        if (isCallOp) {
-          if (shouldPrintPLT(TM, Subtarget)) {
-            // Assemble call via PLT for externally visible symbols
-            if (!GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
-                !GV->hasLocalLinkage())
-              O << "@PLT";
-          }
-          if (Subtarget->isTargetCygMing() && GV->isDeclaration())
-            // Save function name for later type emission
-            FnStubs.insert(Name);
-        }
-      }
-      
-      if (GV->hasExternalWeakLinkage())
-        ExtWeakSymbols.insert(GV);
-      
-      printOffset(MO.getOffset());
-      
-      if (isThreadLocal) {
-        TLSModel::Model model = getTLSModel(GVar, TM.getRelocationModel());
-        switch (model) {
-          case TLSModel::GeneralDynamic:
-            O << "@TLSGD";
-            break;
-          case TLSModel::LocalDynamic:
-            // O << "@TLSLD"; // local dynamic not implemented
-            O << "@TLSGD";
-            break;
-          case TLSModel::InitialExec:
-            if (Subtarget->is64Bit()) {
-              assert (!NotRIPRel);
-              O << "@GOTTPOFF(%rip)";
-            } else {
-              O << "@INDNTPOFF";
-            }
-            break;
-          case TLSModel::LocalExec:
-            if (Subtarget->is64Bit())
-              O << "@TPOFF";
-            else
-              O << "@NTPOFF";
-            break;
-          default:
-            assert (0 && "Unknown TLS model");
-        }
-      } else if (isMemOp) {
-        if (shouldPrintGOT(TM, Subtarget)) {
-          if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
-            O << "@GOT";
-          else
-            O << "@GOTOFF";
-        } else if (Subtarget->isPICStyleRIPRel() && !NotRIPRel) {
-          if (TM.getRelocationModel() != Reloc::Static) {
-            if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
-              O << "@GOTPCREL";
-            
-            if (needCloseParen) {
-              needCloseParen = false;
-              O << ')';
-            }
-          }
-          
-          // Use rip when possible to reduce code size, except when
-          // index or base register are also part of the address. e.g.
-          // foo(%rip)(%rcx,%rax,4) is not legal
-          O << "(%rip)";
-        }
-      }
-      
-      if (needCloseParen)
-        O << ')';
-      
-      return;
-    }
-    case MachineOperand::MO_ExternalSymbol: {
-      bool isCallOp = Modifier && !strcmp(Modifier, "call");
-      bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
-      bool needCloseParen = false;
-      std::string Name(TAI->getGlobalPrefix());
-      Name += MO.getSymbolName();
-      // Print function stub suffix unless it's Mac OS X 10.5 and up.
-      if (isCallOp && shouldPrintStub(TM, Subtarget) && 
-          !(Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9)) {
-        FnStubs.insert(Name);
-        printSuffixedName(Name, "$stub");
-        return;
-      }
-      if (!isMemOp && !isCallOp)
-        O << '$';
-      else if (Name[0] == '$') {
-        // The name begins with a dollar-sign. In order to avoid having it look
-        // like an integer immediate to the assembler, enclose it in parens.
-        O << '(';
-        needCloseParen = true;
-      }
-      
-      O << Name;
-      
-      if (shouldPrintPLT(TM, Subtarget)) {
-        std::string GOTName(TAI->getGlobalPrefix());
-        GOTName+="_GLOBAL_OFFSET_TABLE_";
-        if (Name == GOTName)
-          // HACK! Emit extra offset to PC during printing GOT offset to
-          // compensate for the size of popl instruction. The resulting code
-          // should look like:
-          //   call .piclabel
-          // piclabel:
-          //   popl %some_register
-          //   addl $_GLOBAL_ADDRESS_TABLE_ + [.-piclabel], %some_register
-          O << " + [.-"
-          << getPICLabelString(getFunctionNumber(), TAI, Subtarget) << ']';
-        
-        if (isCallOp)
-          O << "@PLT";
-      }
-      
-      if (needCloseParen)
-        O << ')';
-      
-      if (!isCallOp && Subtarget->isPICStyleRIPRel())
-        O << "(%rip)";
-      
-      return;
-    }
-    default:
-      O << "<unknown operand type>"; return;
-  }
-#endif
 }
 
-void X86ATTAsmPrinter::printLeaMemReference(const MCInst *MI, unsigned Op,
-                                            const char *Modifier,
-                                            bool NotRIPRel) {
+void X86ATTAsmPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) {
+
   const MCOperand &BaseReg  = MI->getOperand(Op);
   const MCOperand &IndexReg = MI->getOperand(Op+2);
   const MCOperand &DispSpec = MI->getOperand(Op+3);
   
-  NotRIPRel |= IndexReg.getReg() || BaseReg.getReg();
   if (DispSpec.isImm()) {
     int64_t DispVal = DispSpec.getImm();
     if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg()))
       O << DispVal;
   } else {
-    abort();
+    LLVM_UNREACHABLE("non-immediate displacement for LEA?");
     //assert(DispSpec.isGlobal() || DispSpec.isCPI() ||
     //       DispSpec.isJTI() || DispSpec.isSymbol());
-    //printOperand(MI, Op+3, "mem", NotRIPRel);
+    //printOperand(MI, Op+3, "mem");
   }
   
   if (IndexReg.getReg() || BaseReg.getReg()) {
-    unsigned ScaleVal = MI->getOperand(Op+1).getImm();
-    unsigned BaseRegOperand = 0, IndexRegOperand = 2;
-    
     // There are cases where we can end up with ESP/RSP in the indexreg slot.
     // If this happens, swap the base/index register to support assemblers that
     // don't work when the index is *SP.
     // FIXME: REMOVE THIS.
-    if (IndexReg.getReg() == X86::ESP || IndexReg.getReg() == X86::RSP) {
-      assert(ScaleVal == 1 && "Scale not supported for stack pointer!");
-      abort();
-      //std::swap(BaseReg, IndexReg);
-      //std::swap(BaseRegOperand, IndexRegOperand);
-    }
+    assert(IndexReg.getReg() != X86::ESP && IndexReg.getReg() != X86::RSP);
     
     O << '(';
     if (BaseReg.getReg())
-      printOperand(MI, Op+BaseRegOperand, Modifier);
+      printOperand(MI, Op);
     
     if (IndexReg.getReg()) {
       O << ',';
-      printOperand(MI, Op+IndexRegOperand, Modifier);
+      printOperand(MI, Op+2);
+      unsigned ScaleVal = MI->getOperand(Op+1).getImm();
       if (ScaleVal != 1)
         O << ',' << ScaleVal;
     }
@@ -386,13 +132,11 @@ void X86ATTAsmPrinter::printLeaMemReference(const MCInst *MI, unsigned Op,
   }
 }
 
-void X86ATTAsmPrinter::printMemReference(const MCInst *MI, unsigned Op,
-                                         const char *Modifier, bool NotRIPRel){
-  //assert(isMem(MI, Op) && "Invalid memory reference!");
+void X86ATTAsmPrinter::printMemReference(const MCInst *MI, unsigned Op) {
   const MCOperand &Segment = MI->getOperand(Op+4);
   if (Segment.getReg()) {
-    printOperand(MI, Op+4, Modifier);
+    printOperand(MI, Op+4);
     O << ':';
   }
-  printLeaMemReference(MI, Op, Modifier, NotRIPRel);
+  printLeaMemReference(MI, Op);
 }