Add support for casting operators
[oota-llvm.git] / lib / VMCore / AsmWriter.cpp
index 6d32edc31959a0286c8e6186c6780ac649194501..1719bc532f881f252fb811d010fe7aaf00a6a4ae 100644 (file)
 #include "llvm/iOther.h"
 #include "llvm/iMemory.h"
 
+void DebugValue(const Value *V) {
+  cerr << V << endl;
+}
+
+// WriteAsOperand - Write the name of the specified value out to the specified
+// ostream.  This can be useful when you just want to print int %reg126, not the
+// whole instruction that generated it.
+//
+ostream &WriteAsOperand(ostream &Out, const Value *V, bool PrintType, 
+                       bool PrintName, SlotCalculator *Table) {
+  if (PrintType)
+    Out << " " << V->getType();
+  
+  if (V->hasName() && PrintName) {
+    Out << " %" << V->getName();
+  } else {
+    if (const ConstPoolVal *CPV = V->castConstant()) {
+      Out << " " << CPV->getStrValue();
+    } else {
+      int Slot;
+      if (Table) {
+       Slot = Table->getValSlot(V);
+      } else {
+       if (const Type *Ty = V->castType()) {
+         return Out << " " << Ty;
+       } else if (const MethodArgument *MA = V->castMethodArgument()) {
+         Table = new SlotCalculator(MA->getParent(), true);
+       } else if (const Instruction *I = V->castInstruction()) {
+         Table = new SlotCalculator(I->getParent()->getParent(), true);
+       } else if (const BasicBlock *BB = V->castBasicBlock()) {
+         Table = new SlotCalculator(BB->getParent(), true);
+       } else if (const Method *Meth = V->castMethod()) {
+         Table = new SlotCalculator(Meth, true);
+       } else if (const Module *Mod  = V->castModule()) {
+         Table = new SlotCalculator(Mod, true);
+       } else {
+         return Out << "BAD VALUE TYPE!";
+       }
+       Slot = Table->getValSlot(V);
+       delete Table;
+      }
+      if (Slot >= 0)  Out << " %" << Slot;
+      else if (PrintName)
+        Out << "<badref>";     // Not embeded into a location?
+    }
+  }
+  return Out;
+}
+
+
+
 class AssemblyWriter : public ModuleAnalyzer {
   ostream &Out;
   SlotCalculator &Table;
@@ -60,10 +111,12 @@ bool AssemblyWriter::processConstPool(const ConstantPool &CP, bool isMethod) {
 
   ModuleAnalyzer::processConstPool(CP, isMethod);
   
-  if (isMethod)
-    Out << "begin";
-  else
+  if (isMethod) {
+    if (!CP.getParentV()->castMethodAsserting()->isExternal())
+      Out << "begin";
+  } else {
     Out << "implementation\n";
+  }
   return false;
 }
 
@@ -98,11 +151,13 @@ bool AssemblyWriter::processConstant(const ConstPoolVal *CPV) {
 //
 bool AssemblyWriter::processMethod(const Method *M) {
   // Print out the return type and name...
-  Out << "\n" << M->getReturnType() << " \"" << M->getName() << "\"(";
+  Out << "\n" << (M->isExternal() ? "declare " : "") 
+      << M->getReturnType() << " \"" << M->getName() << "\"(";
   Table.incorporateMethod(M);
   ModuleAnalyzer::processMethod(M);
   Table.purgeMethod();
-  Out << "end\n";
+  if (!M->isExternal())
+    Out << "end\n";
   return false;
 }
 
@@ -154,60 +209,62 @@ bool AssemblyWriter::processInstruction(const Instruction *I) {
     Out << "%" << I->getName() << " = ";
 
   // Print out the opcode...
-  Out << I->getOpcode();
+  Out << I->getOpcodeName();
 
   // Print out the type of the operands...
-  const Value *Operand = I->getOperand(0);
+  const Value *Operand = I->getNumOperands() ? I->getOperand(0) : 0;
 
   // Special case conditional branches to swizzle the condition out to the front
-  if (I->getInstType() == Instruction::Br && I->getOperand(1)) {
+  if (I->getOpcode() == Instruction::Br && I->getNumOperands() > 1) {
     writeOperand(I->getOperand(2), true);
     Out << ",";
     writeOperand(Operand, true);
     Out << ",";
     writeOperand(I->getOperand(1), true);
 
-  } else if (I->getInstType() == Instruction::Switch) {
+  } else if (I->getOpcode() == Instruction::Switch) {
     // Special case switch statement to get formatting nice and correct...
     writeOperand(Operand         , true); Out << ",";
     writeOperand(I->getOperand(1), true); Out << " [";
 
-    for (unsigned op = 2; (Operand = I->getOperand(op)); op += 2) {
+    for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; op += 2) {
       Out << "\n\t\t";
-      writeOperand(Operand, true); Out << ",";
+      writeOperand(I->getOperand(op  ), true); Out << ",";
       writeOperand(I->getOperand(op+1), true);
     }
     Out << "\n\t]";
-  } else if (I->getInstType() == Instruction::PHINode) {
+  } else if (I->isPHINode()) {
     Out << " " << Operand->getType();
 
     Out << " [";  writeOperand(Operand, false); Out << ",";
-    writeOperand(I->getOperand(1), false); Out << "]";
-    for (unsigned op = 2; (Operand = I->getOperand(op)); op += 2) {
-      Out << ", [";  writeOperand(Operand, false); Out << ",";
-      writeOperand(I->getOperand(op+1), false); Out << "]";
+    writeOperand(I->getOperand(1), false); Out << " ]";
+    for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; op += 2) {
+      Out << ", [";  
+      writeOperand(I->getOperand(op  ), false); Out << ",";
+      writeOperand(I->getOperand(op+1), false); Out << " ]";
     }
-  } else if (I->getInstType() == Instruction::Ret && !Operand) {
+  } else if (I->getOpcode() == Instruction::Ret && !Operand) {
     Out << " void";
-  } else if (I->getInstType() == Instruction::Call) {
+  } else if (I->getOpcode() == Instruction::Call) {
     writeOperand(Operand, true);
     Out << "(";
-    Operand = I->getOperand(1);
-    if (Operand) writeOperand(Operand, true);
-    for (unsigned op = 2; (Operand = I->getOperand(op)); ++op) {
+    if (I->getNumOperands() > 1) writeOperand(I->getOperand(1), true);
+    for (unsigned op = 2, Eop = I->getNumOperands(); op < Eop; ++op) {
       Out << ",";
-      writeOperand(Operand, true);
+      writeOperand(I->getOperand(op), true);
     }
 
     Out << " )";
-  } else if (I->getInstType() == Instruction::Malloc || 
-            I->getInstType() == Instruction::Alloca) {
-    Out << " " << ((const PointerType*)((ConstPoolType*)Operand)
-                  ->getValue())->getValueType();
-    if ((Operand = I->getOperand(1))) {
-      Out << ","; writeOperand(Operand, true);
+  } else if (I->getOpcode() == Instruction::Malloc || 
+            I->getOpcode() == Instruction::Alloca) {
+    Out << " " << ((const PointerType*)I->getType())->getValueType();
+    if (I->getNumOperands()) {
+      Out << ",";
+      writeOperand(I->getOperand(0), true);
     }
-
+  } else if (I->getOpcode() == Instruction::Cast) {
+    writeOperand(Operand, true);
+    Out << " to " << I->getType();
   } else if (Operand) {   // Print the normal way...
 
     // PrintAllTypes - Instructions who have operands of all the same type 
@@ -215,9 +272,9 @@ bool AssemblyWriter::processInstruction(const Instruction *I) {
     // different type operands (for example br), then they are all printed.
     bool PrintAllTypes = false;
     const Type *TheType = Operand->getType();
-    unsigned i;
 
-    for (i = 1; (Operand = I->getOperand(i)); i++) {
+    for (unsigned i = 1, E = I->getNumOperands(); i != E; ++i) {
+      Operand = I->getOperand(i);
       if (Operand->getType() != TheType) {
        PrintAllTypes = true;       // We have differing types!  Print them all!
        break;
@@ -227,9 +284,9 @@ bool AssemblyWriter::processInstruction(const Instruction *I) {
     if (!PrintAllTypes)
       Out << " " << I->getOperand(0)->getType();
 
-    for (unsigned i = 0; (Operand = I->getOperand(i)); i++) {
+    for (unsigned i = 0, E = I->getNumOperands(); i != E; ++i) {
       if (i) Out << ",";
-      writeOperand(Operand, PrintAllTypes);
+      writeOperand(I->getOperand(i), PrintAllTypes);
     }
   }
 
@@ -254,22 +311,7 @@ bool AssemblyWriter::processInstruction(const Instruction *I) {
 
 void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType, 
                                  bool PrintName) {
-  if (PrintType)
-    Out << " " << Operand->getType();
-  
-  if (Operand->hasName() && PrintName) {
-    Out << " %" << Operand->getName();
-  } else {
-    int Slot = Table.getValSlot(Operand);
-    
-    if (Operand->getValueType() == Value::ConstantVal) {
-      Out << " " << ((ConstPoolVal*)Operand)->getStrValue();
-    } else {
-      if (Slot >= 0)  Out << " %" << Slot;
-      else if (PrintName)
-        Out << "<badref>";     // Not embeded into a location?
-    }
-  }
+  WriteAsOperand(Out, Operand, PrintType, PrintName, &Table);
 }
 
 
@@ -313,12 +355,11 @@ void WriteToAssembly(const ConstPoolVal *CPV, ostream &o) {
   // A Constant pool value may have a parent that is either a method or a 
   // module.  Untangle this now...
   //
-  if (CPV->getParent() == 0 || 
-      CPV->getParent()->getValueType() == Value::MethodVal) {
-    SlotTable = new SlotCalculator((Method*)CPV->getParent(), true);
+  if (const Method *Meth = CPV->getParentV()->castMethod()) {
+    SlotTable = new SlotCalculator(Meth, true);
   } else {
-    assert(CPV->getParent()->getValueType() == Value::ModuleVal);
-    SlotTable = new SlotCalculator((Module*)CPV->getParent(), true);
+    SlotTable =
+      new SlotCalculator(CPV->getParentV()->castModuleAsserting(), true);
   }
 
   AssemblyWriter W(o, *SlotTable);