Cygwin apparently works with %'s on registers!
[oota-llvm.git] / lib / Target / X86 / Printer.cpp
index 96200a4de00ffe144feafdd97c4afac09a0509ce..db55593ad7a7c731ddc8b7a38902a276cda012f9 100644 (file)
@@ -3,7 +3,7 @@
 // This file contains a printer that converts from our internal
 // representation of machine-dependent LLVM code to Intel-format
 // assembly language. This printer is the output mechanism used
-// by `llc' and `lli -printmachineinstrs' on X86.
+// by `llc' and `lli -print-machineinstrs' on X86.
 //
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Assembly/Writer.h"
 #include "llvm/Support/Mangler.h"
 #include "Support/StringExtras.h"
+#include "Support/CommandLine.h"
 
 namespace {
+  // FIXME: This should be automatically picked up by autoconf from the C
+  // frontend
+  cl::opt<bool> EmitCygwin("enable-cygwin-compatible-output", cl::Hidden,
+         cl::desc("Emit X86 assembly code suitable for consumption by cygwin"));
+
   struct Printer : public MachineFunctionPass {
     /// Output stream on which we're printing assembly code.
     ///
@@ -55,6 +61,7 @@ namespace {
       return "X86 Assembly Printer";
     }
 
+    void checkImplUses (const TargetInstrDescriptor &Desc);
     void printMachineInstruction(const MachineInstr *MI);
     void printOp(const MachineOperand &MO,
                 bool elideOffsetKeyword = false);
@@ -119,16 +126,16 @@ std::string Printer::valToExprString(const Value* V) {
 /// and return this as a string.
 ///
 std::string Printer::ConstantExprToString(const ConstantExpr* CE) {
-  std::string S;
   const TargetData &TD = TM.getTargetData();
   switch(CE->getOpcode()) {
   case Instruction::GetElementPtr:
     { // generate a symbolic expression for the byte address
       const Value* ptrVal = CE->getOperand(0);
       std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
-      S += "(" + valToExprString(ptrVal) + ") + ("
-       + utostr(TD.getIndexedOffset(ptrVal->getType(),idxVec)) + ")";
-      break;
+      if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec))
+        return "(" + valToExprString(ptrVal) + ") + " + utostr(Offset);
+      else
+        return valToExprString(ptrVal);
     }
 
   case Instruction::Cast:
@@ -143,23 +150,19 @@ std::string Printer::ConstantExprToString(const ConstantExpr* CE) {
              || (isa<PointerType>(Ty)
                  && (OpTy == Type::LongTy || OpTy == Type::ULongTy)))
             || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
-                 && (OpTy-> isLosslesslyConvertibleTo(Ty))))
+                 && (OpTy->isLosslesslyConvertibleTo(Ty))))
             && "FIXME: Don't yet support this kind of constant cast expr");
-      S += "(" + valToExprString(Op) + ")";
+      return "(" + valToExprString(Op) + ")";
     }
-    break;
 
   case Instruction::Add:
-    S += "(" + valToExprString(CE->getOperand(0)) + ") + ("
-      + valToExprString(CE->getOperand(1)) + ")";
-    break;
+    return "(" + valToExprString(CE->getOperand(0)) + ") + ("
+               + valToExprString(CE->getOperand(1)) + ")";
 
   default:
     assert(0 && "Unsupported operator in ConstantExprToString()");
-    break;
+    return "";
   }
-
-  return S;
 }
 
 /// printSingleConstantValue - Print a single constant value.
@@ -402,7 +405,8 @@ bool Printer::runOnMachineFunction(MachineFunction &MF) {
   O << "\t.text\n";
   O << "\t.align 16\n";
   O << "\t.globl\t" << CurrentFnName << "\n";
-  O << "\t.type\t" << CurrentFnName << ", @function\n";
+  if (!EmitCygwin)
+    O << "\t.type\t" << CurrentFnName << ", @function\n";
   O << CurrentFnName << ":\n";
 
   // Number each basic block so that we can consistently refer to them
@@ -445,6 +449,8 @@ static bool isMem(const MachineInstr *MI, unsigned Op) {
     MI->getOperand(Op+2).isRegister() &&MI->getOperand(Op+3).isImmediate();
 }
 
+
+
 void Printer::printOp(const MachineOperand &MO,
                      bool elideOffsetKeyword /* = false */) {
   const MRegisterInfo &RI = *TM.getRegisterInfo();
@@ -456,9 +462,10 @@ void Printer::printOp(const MachineOperand &MO,
     }
     // FALLTHROUGH
   case MachineOperand::MO_MachineRegister:
-    if (MO.getReg() < MRegisterInfo::FirstVirtualRegister)
+    if (MO.getReg() < MRegisterInfo::FirstVirtualRegister) {
+      // Bug Workaround: See note in Printer::doInitialization about %.
       O << RI.get(MO.getReg()).Name;
-    else
+    else
       O << "%reg" << MO.getReg();
     return;
 
@@ -501,7 +508,6 @@ static const std::string sizePtr(const TargetInstrDescriptor &Desc) {
 }
 
 void Printer::printMemReference(const MachineInstr *MI, unsigned Op) {
-  const MRegisterInfo &RI = *TM.getRegisterInfo();
   assert(isMem(MI, Op) && "Invalid memory reference!");
 
   if (MI->getOperand(Op).isFrameIndex()) {
@@ -552,6 +558,19 @@ void Printer::printMemReference(const MachineInstr *MI, unsigned Op) {
   O << "]";
 }
 
+/// checkImplUses - Emit the implicit-use registers for the
+/// instruction described by DESC, if its PrintImplUses flag is set.
+///
+void Printer::checkImplUses (const TargetInstrDescriptor &Desc) {
+  const MRegisterInfo &RI = *TM.getRegisterInfo();
+  if (Desc.TSFlags & X86II::PrintImplUses) {
+    for (const unsigned *p = Desc.ImplicitUses; *p; ++p) {
+      // Bug Workaround: See note in Printer::doInitialization about %.
+      O << ", %" << RI.get(*p).Name;
+    }
+  }
+}
+
 /// printMachineInstruction -- Print out a single X86 LLVM instruction
 /// MI in Intel syntax to the current output stream.
 ///
@@ -559,7 +578,6 @@ void Printer::printMachineInstruction(const MachineInstr *MI) {
   unsigned Opcode = MI->getOpcode();
   const TargetInstrInfo &TII = TM.getInstrInfo();
   const TargetInstrDescriptor &Desc = TII.get(Opcode);
-  const MRegisterInfo &RI = *TM.getRegisterInfo();
 
   switch (Desc.TSFlags & X86II::FormMask) {
   case X86II::Pseudo:
@@ -651,11 +669,7 @@ void Printer::printMachineInstruction(const MachineInstr *MI) {
       O << ", ";
       printOp(MI->getOperand(1));
     }
-    if (Desc.TSFlags & X86II::PrintImplUses) {
-      for (const unsigned *p = Desc.ImplicitUses; *p; ++p) {
-       O << ", " << RI.get(*p).Name;
-      }
-    }
+    checkImplUses(Desc);
     O << "\n";
     return;
   }
@@ -786,11 +800,7 @@ void Printer::printMachineInstruction(const MachineInstr *MI) {
       O << ", ";
       printOp(MI->getOperand(MI->getNumOperands()-1));
     }
-    if (Desc.TSFlags & X86II::PrintImplUses) {
-      for (const unsigned *p = Desc.ImplicitUses; *p; ++p) {
-       O << ", " << RI.get(*p).Name;
-      }
-    }
+    checkImplUses(Desc);
     O << "\n";
 
     return;
@@ -900,12 +910,20 @@ void Printer::printMachineInstruction(const MachineInstr *MI) {
   }
 }
 
-bool Printer::doInitialization(Module &M)
-{
-  // Tell gas we are outputting Intel syntax (not AT&T syntax) assembly,
-  // with no % decorations on register names.
-  O << "\t.intel_syntax noprefix\n";
-  Mang = new Mangler(M);
+bool Printer::doInitialization(Module &M) {
+  // Tell gas we are outputting Intel syntax (not AT&T syntax) assembly.
+  //
+  // Bug: gas in `intel_syntax noprefix' mode interprets the symbol `Sp' in an
+  // instruction as a reference to the register named sp, and if you try to
+  // reference a symbol `Sp' (e.g. `mov ECX, OFFSET Sp') then it gets lowercased
+  // before being looked up in the symbol table. This creates spurious
+  // `undefined symbol' errors when linking. Workaround: Do not use `noprefix'
+  // mode, and decorate all register names with percent signs.
+  //
+  // Cygwin presumably doesn't have this problem, so drop the %'s.
+  //
+  O << "\t.intel_syntax\n";
+  Mang = new Mangler(M, EmitCygwin);
   return false; // success
 }