update comments
[oota-llvm.git] / lib / Target / CBackend / Writer.cpp
index bc2f7bd5f1f86707e5d077e470e240f893947388..18c4d064e33afda0f8106d0a480c114fb391b190 100644 (file)
 #include "llvm/SymbolTable.h"
 #include "llvm/Intrinsics.h"
 #include "llvm/IntrinsicInst.h"
+#include "llvm/InlineAsm.h"
 #include "llvm/Analysis/ConstantsScanner.h"
 #include "llvm/Analysis/FindUsedTypes.h"
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/CodeGen/IntrinsicLowering.h"
 #include "llvm/Transforms/Scalar.h"
 #include "llvm/Target/TargetMachineRegistry.h"
+#include "llvm/Target/TargetAsmInfo.h"
 #include "llvm/Support/CallSite.h"
 #include "llvm/Support/CFG.h"
 #include "llvm/Support/GetElementPtrTypeIterator.h"
@@ -69,15 +71,16 @@ namespace {
   /// module to a C translation unit.
   class CWriter : public FunctionPass, public InstVisitor<CWriter> {
     std::ostream &Out;
-    DefaultIntrinsicLowering IL;
+    IntrinsicLowering IL;
     Mangler *Mang;
     LoopInfo *LI;
     const Module *TheModule;
+    const TargetAsmInfo* TAsm;
     std::map<const Type *, std::string> TypeNames;
 
     std::map<const ConstantFP *, unsigned> FPConstantMap;
   public:
-    CWriter(std::ostream &o) : Out(o) {}
+    CWriter(std::ostream &o) : Out(o), TAsm(0) {}
 
     virtual const char *getPassName() const { return "C backend"; }
 
@@ -120,9 +123,14 @@ namespace {
                                               const PointerType *Ty);
     
     void writeOperand(Value *Operand);
+    void writeOperandRaw(Value *Operand);
     void writeOperandInternal(Value *Operand);
+    void writeOperandWithCast(Value* Operand, unsigned Opcode);
+    bool writeInstructionCast(const Instruction &I);
 
   private :
+    std::string InterpretASMConstraint(InlineAsm::ConstraintInfo& c);
+
     void lowerIntrinsics(Function &F);
 
     void printModule(Module *M);
@@ -135,7 +143,10 @@ namespace {
     void printBasicBlock(BasicBlock *BB);
     void printLoop(Loop *L);
 
+    void printCast(unsigned opcode, const Type *SrcTy, const Type *DstTy);
     void printConstant(Constant *CPV);
+    void printConstantWithCast(Constant *CPV, unsigned Opcode);
+    bool printConstExprCast(const ConstantExpr *CE);
     void printConstantArray(ConstantArray *CPA);
     void printConstantPacked(ConstantPacked *CP);
 
@@ -157,6 +168,9 @@ namespace {
         // Don't inline a load across a store or other bad things!
         return false;
 
+      // Must not be used in inline asm
+      if (I.hasOneUse() && isInlineAsm(*I.use_back())) return false;
+
       // Only inline instruction it it's use is in the same BB as the inst.
       return I.getParent() == cast<Instruction>(I.use_back())->getParent();
     }
@@ -174,7 +188,14 @@ namespace {
         return 0;
       return AI;
     }
-
+    
+    // isInlineAsm - Check if the instruction is a call to an inline asm chunk
+    static bool isInlineAsm(const Instruction& I) {
+      if (isa<CallInst>(&I) && isa<InlineAsm>(I.getOperand(0)))
+        return true;
+      return false;
+    }
+    
     // Instruction visitation functions
     friend class InstVisitor<CWriter>;
 
@@ -196,6 +217,7 @@ namespace {
     void visitCastInst (CastInst &I);
     void visitSelectInst(SelectInst &I);
     void visitCallInst (CallInst &I);
+    void visitInlineAsm(CallInst &I);
     void visitShiftInst(ShiftInst &I) { visitBinaryOperator(I); }
 
     void visitMallocInst(MallocInst &I);
@@ -530,7 +552,7 @@ void CWriter::printConstantPacked(ConstantPacked *CP) {
 // only deal in IEEE FP).
 //
 static bool isFPCSafeToPrint(const ConstantFP *CFP) {
-#if HAVE_PRINTF_A
+#if HAVE_PRINTF_A && ENABLE_CBE_PRINTF_A
   char Buffer[100];
   sprintf(Buffer, "%a", CFP->getValue());
 
@@ -556,15 +578,79 @@ static bool isFPCSafeToPrint(const ConstantFP *CFP) {
 #endif
 }
 
+/// Print out the casting for a cast operation. This does the double casting
+/// necessary for conversion to the destination type, if necessary. 
+/// @returns true if a closing paren is necessary
+/// @brief Print a cast
+void CWriter::printCast(unsigned opc, const Type *SrcTy, const Type *DstTy) {
+  Out << '(';
+  printType(Out, DstTy);
+  Out << ')';
+  switch (opc) {
+    case Instruction::UIToFP:
+    case Instruction::ZExt:
+      if (SrcTy->isSigned()) {
+        Out << '(';
+        printType(Out, SrcTy->getUnsignedVersion());
+        Out << ')';
+      }
+      break;
+    case Instruction::SIToFP:
+    case Instruction::SExt:
+      if (SrcTy->isUnsigned()) {
+        Out << '(';
+        printType(Out, SrcTy->getSignedVersion());
+        Out << ')';
+      }
+      break;
+    case Instruction::IntToPtr:
+    case Instruction::PtrToInt:
+        // Avoid "cast to pointer from integer of different size" warnings
+        Out << "(unsigned long)";
+        break;
+    case Instruction::Trunc:
+    case Instruction::BitCast:
+    case Instruction::FPExt:
+    case Instruction::FPTrunc:
+    case Instruction::FPToSI:
+    case Instruction::FPToUI:
+    default:
+      break;
+  }
+}
+
 // printConstant - The LLVM Constant to C Constant converter.
 void CWriter::printConstant(Constant *CPV) {
   if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CPV)) {
     switch (CE->getOpcode()) {
-    case Instruction::Cast:
-      Out << "((";
-      printType(Out, CPV->getType());
-      Out << ')';
+    case Instruction::Trunc:
+    case Instruction::ZExt:
+    case Instruction::SExt:
+    case Instruction::FPTrunc:
+    case Instruction::FPExt:
+    case Instruction::UIToFP:
+    case Instruction::SIToFP:
+    case Instruction::FPToUI:
+    case Instruction::FPToSI:
+    case Instruction::PtrToInt:
+    case Instruction::IntToPtr:
+    case Instruction::BitCast:
+      Out << "(";
+      printCast(CE->getOpcode(), CE->getOperand(0)->getType(), CE->getType());
+      if (CE->getOpcode() == Instruction::SExt &&
+          CE->getOperand(0)->getType() == Type::BoolTy) {
+        // Make sure we really sext from bool here by subtracting from 0
+        Out << "0-";
+      }
       printConstant(CE->getOperand(0));
+      if (CE->getType() == Type::BoolTy &&
+          (CE->getOpcode() == Instruction::Trunc ||
+           CE->getOpcode() == Instruction::FPToUI ||
+           CE->getOpcode() == Instruction::FPToSI ||
+           CE->getOpcode() == Instruction::PtrToInt)) {
+        // Make sure we really truncate to bool here by anding with 1
+        Out << "&1u";
+      }
       Out << ')';
       return;
 
@@ -586,8 +672,12 @@ void CWriter::printConstant(Constant *CPV) {
     case Instruction::Add:
     case Instruction::Sub:
     case Instruction::Mul:
-    case Instruction::Div:
-    case Instruction::Rem:
+    case Instruction::SDiv:
+    case Instruction::UDiv:
+    case Instruction::FDiv:
+    case Instruction::URem:
+    case Instruction::SRem:
+    case Instruction::FRem:
     case Instruction::And:
     case Instruction::Or:
     case Instruction::Xor:
@@ -598,15 +688,22 @@ void CWriter::printConstant(Constant *CPV) {
     case Instruction::SetGT:
     case Instruction::SetGE:
     case Instruction::Shl:
-    case Instruction::Shr:
+    case Instruction::LShr:
+    case Instruction::AShr:
+    {
       Out << '(';
-      printConstant(CE->getOperand(0));
+      bool NeedsClosingParens = printConstExprCast(CE); 
+      printConstantWithCast(CE->getOperand(0), CE->getOpcode());
       switch (CE->getOpcode()) {
       case Instruction::Add: Out << " + "; break;
       case Instruction::Sub: Out << " - "; break;
       case Instruction::Mul: Out << " * "; break;
-      case Instruction::Div: Out << " / "; break;
-      case Instruction::Rem: Out << " % "; break;
+      case Instruction::URem:
+      case Instruction::SRem: 
+      case Instruction::FRem: Out << " % "; break;
+      case Instruction::UDiv: 
+      case Instruction::SDiv: 
+      case Instruction::FDiv: Out << " / "; break;
       case Instruction::And: Out << " & "; break;
       case Instruction::Or:  Out << " | "; break;
       case Instruction::Xor: Out << " ^ "; break;
@@ -617,12 +714,16 @@ void CWriter::printConstant(Constant *CPV) {
       case Instruction::SetGT: Out << " > "; break;
       case Instruction::SetGE: Out << " >= "; break;
       case Instruction::Shl: Out << " << "; break;
-      case Instruction::Shr: Out << " >> "; break;
+      case Instruction::LShr:
+      case Instruction::AShr: Out << " >> "; break;
       default: assert(0 && "Illegal opcode here!");
       }
-      printConstant(CE->getOperand(1));
+      printConstantWithCast(CE->getOperand(1), CE->getOpcode());
+      if (NeedsClosingParens)
+        Out << "))";
       Out << ')';
       return;
+    }
 
     default:
       std::cerr << "CWriter Error: Unhandled constant expression: "
@@ -685,7 +786,7 @@ void CWriter::printConstant(Constant *CPV) {
         // The prefix for a quiet NaN is 0x7FF8. For a signalling NaN,
         // it's 0x7ff4.
         const unsigned long QuietNaN = 0x7ff8UL;
-        const unsigned long SignalNaN = 0x7ff4UL;
+        //const unsigned long SignalNaN = 0x7ff4UL;
 
         // We need to grab the first part of the FP #
         char Buffer[100];
@@ -709,7 +810,7 @@ void CWriter::printConstant(Constant *CPV) {
             << " /*inf*/ ";
       } else {
         std::string Num;
-#if HAVE_PRINTF_A
+#if HAVE_PRINTF_A && ENABLE_CBE_PRINTF_A
         // Print out the constant as a floating point number.
         char Buffer[100];
         sprintf(Buffer, "%a", FPC->getValue());
@@ -805,6 +906,98 @@ void CWriter::printConstant(Constant *CPV) {
   }
 }
 
+// Some constant expressions need to be casted back to the original types
+// because their operands were casted to the expected type. This function takes
+// care of detecting that case and printing the cast for the ConstantExpr.
+bool CWriter::printConstExprCast(const ConstantExpr* CE) {
+  bool NeedsExplicitCast = false;
+  const Type *Ty = CE->getOperand(0)->getType();
+  switch (CE->getOpcode()) {
+  case Instruction::LShr:
+  case Instruction::URem: 
+  case Instruction::UDiv: 
+    NeedsExplicitCast = Ty->isSigned(); break;
+  case Instruction::AShr:
+  case Instruction::SRem: 
+  case Instruction::SDiv: 
+    NeedsExplicitCast = Ty->isUnsigned(); break;
+  case Instruction::ZExt:
+  case Instruction::SExt:
+  case Instruction::Trunc:
+  case Instruction::FPTrunc:
+  case Instruction::FPExt:
+  case Instruction::UIToFP:
+  case Instruction::SIToFP:
+  case Instruction::FPToUI:
+  case Instruction::FPToSI:
+  case Instruction::PtrToInt:
+  case Instruction::IntToPtr:
+  case Instruction::BitCast:
+    Ty = CE->getType();
+    NeedsExplicitCast = true;
+    break;
+  default: break;
+  }
+  if (NeedsExplicitCast) {
+    Out << "((";
+    printType(Out, Ty);
+    Out << ")(";
+  }
+  return NeedsExplicitCast;
+}
+
+//  Print a constant assuming that it is the operand for a given Opcode. The
+//  opcodes that care about sign need to cast their operands to the expected
+//  type before the operation proceeds. This function does the casting.
+void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
+
+  // Extract the operand's type, we'll need it.
+  const Type* OpTy = CPV->getType();
+
+  // Indicate whether to do the cast or not.
+  bool shouldCast = false;
+
+  // Based on the Opcode for which this Constant is being written, determine
+  // the new type to which the operand should be casted by setting the value
+  // of OpTy. If we change OpTy, also set shouldCast to true so it gets
+  // casted below.
+  switch (Opcode) {
+    default:
+      // for most instructions, it doesn't matter
+      break; 
+    case Instruction::LShr:
+    case Instruction::UDiv:
+    case Instruction::URem:
+      // For UDiv/URem get correct type
+      if (OpTy->isSigned()) {
+        OpTy = OpTy->getUnsignedVersion();
+        shouldCast = true;
+      }
+      break;
+    case Instruction::AShr:
+    case Instruction::SDiv:
+    case Instruction::SRem:
+      // For SDiv/SRem get correct type
+      if (OpTy->isUnsigned()) {
+        OpTy = OpTy->getSignedVersion();
+        shouldCast = true;
+      }
+      break;
+  }
+
+  // Write out the casted constant if we should, otherwise just write the
+  // operand.
+  if (shouldCast) {
+    Out << "((";
+    printType(Out, OpTy);
+    Out << ")";
+    printConstant(CPV);
+    Out << ")";
+  } else 
+    writeOperand(CPV);
+
+}
+
 void CWriter::writeOperandInternal(Value *Operand) {
   if (Instruction *I = dyn_cast<Instruction>(Operand))
     if (isInlinableInst(*I) && !isDirectAlloca(I)) {
@@ -823,9 +1016,18 @@ void CWriter::writeOperandInternal(Value *Operand) {
   }
 }
 
+void CWriter::writeOperandRaw(Value *Operand) {
+  Constant* CPV = dyn_cast<Constant>(Operand);
+  if (CPV && !isa<GlobalValue>(CPV)) {
+    printConstant(CPV);
+  } else {
+    Out << Mang->getValueName(Operand);
+  }
+}
+
 void CWriter::writeOperand(Value *Operand) {
   if (isa<GlobalVariable>(Operand) || isDirectAlloca(Operand))
-    Out << "(&";  // Global variables are references as their addresses by llvm
+    Out << "(&";  // Global variables are referenced as their addresses by llvm
 
   writeOperandInternal(Operand);
 
@@ -833,6 +1035,97 @@ void CWriter::writeOperand(Value *Operand) {
     Out << ')';
 }
 
+// Some instructions need to have their result value casted back to the 
+// original types because their operands were casted to the expected type. 
+// This function takes care of detecting that case and printing the cast 
+// for the Instruction.
+bool CWriter::writeInstructionCast(const Instruction &I) {
+  bool NeedsExplicitCast = false;
+  const Type *Ty = I.getOperand(0)->getType();
+  switch (I.getOpcode()) {
+  case Instruction::LShr:
+  case Instruction::URem: 
+  case Instruction::UDiv: 
+    NeedsExplicitCast = Ty->isSigned(); break;
+  case Instruction::AShr:
+  case Instruction::SRem: 
+  case Instruction::SDiv: 
+    NeedsExplicitCast = Ty->isUnsigned(); break;
+  case Instruction::ZExt:
+  case Instruction::SExt:
+  case Instruction::Trunc:
+  case Instruction::FPTrunc:
+  case Instruction::FPExt:
+  case Instruction::UIToFP:
+  case Instruction::SIToFP:
+  case Instruction::FPToUI:
+  case Instruction::FPToSI:
+  case Instruction::PtrToInt:
+  case Instruction::IntToPtr:
+  case Instruction::BitCast:
+    Ty = I.getType();
+    NeedsExplicitCast = true;
+    break;
+  default: break;
+  }
+  if (NeedsExplicitCast) {
+    Out << "((";
+    printType(Out, Ty);
+    Out << ")(";
+  }
+  return NeedsExplicitCast;
+}
+
+// Write the operand with a cast to another type based on the Opcode being used.
+// This will be used in cases where an instruction has specific type
+// requirements (usually signedness) for its operands. 
+void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
+
+  // Extract the operand's type, we'll need it.
+  const Type* OpTy = Operand->getType();
+
+  // Indicate whether to do the cast or not.
+  bool shouldCast = false;
+
+  // Based on the Opcode for which this Operand is being written, determine
+  // the new type to which the operand should be casted by setting the value
+  // of OpTy. If we change OpTy, also set shouldCast to true.
+  switch (Opcode) {
+    default:
+      // for most instructions, it doesn't matter
+      break; 
+    case Instruction::LShr:
+    case Instruction::UDiv:
+    case Instruction::URem:
+      // For UDiv to have unsigned operands
+      if (OpTy->isSigned()) {
+        OpTy = OpTy->getUnsignedVersion();
+        shouldCast = true;
+      }
+      break;
+    case Instruction::AShr:
+    case Instruction::SDiv:
+    case Instruction::SRem:
+      if (OpTy->isUnsigned()) {
+        OpTy = OpTy->getSignedVersion();
+        shouldCast = true;
+      }
+      break;
+  }
+
+  // Write out the casted operand if we should, otherwise just write the
+  // operand.
+  if (shouldCast) {
+    Out << "((";
+    printType(Out, OpTy);
+    Out << ")";
+    writeOperand(Operand);
+    Out << ")";
+  } else 
+    writeOperand(Operand);
+
+}
+
 // generateCompilerSpecificCode - This is where we add conditional compilation
 // directives to cater to specific compilers as need be.
 //
@@ -969,7 +1262,7 @@ static void FindStaticTors(GlobalVariable *GV, std::set<Function*> &StaticTors){
         return;  // Found a null terminator, exit printing.
       Constant *FP = CS->getOperand(1);
       if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
-        if (CE->getOpcode() == Instruction::Cast)
+        if (CE->isCast())
           FP = CE->getOperand(0);
       if (Function *F = dyn_cast<Function>(FP))
         StaticTors.insert(F);
@@ -1460,7 +1753,7 @@ void CWriter::printBasicBlock(BasicBlock *BB) {
   for (BasicBlock::iterator II = BB->begin(), E = --BB->end(); II != E;
        ++II) {
     if (!isInlinableInst(*II) && !isDirectAlloca(II)) {
-      if (II->getType() != Type::VoidTy)
+      if (II->getType() != Type::VoidTy && !isInlineAsm(*II))
         outputLValue(II);
       else
         Out << "  ";
@@ -1630,8 +1923,7 @@ void CWriter::visitBinaryOperator(Instruction &I) {
     Out << "-(";
     writeOperand(BinaryOperator::getNegArgument(cast<BinaryOperator>(&I)));
     Out << ")";
-  } else if (I.getOpcode() == Instruction::Rem && 
-             I.getType()->isFloatingPoint()) {
+  } else if (I.getOpcode() == Instruction::FRem) {
     // Output a call to fmod/fmodf instead of emitting a%b
     if (I.getType() == Type::FloatTy)
       Out << "fmodf(";
@@ -1642,14 +1934,26 @@ void CWriter::visitBinaryOperator(Instruction &I) {
     writeOperand(I.getOperand(1));
     Out << ")";
   } else {
-    writeOperand(I.getOperand(0));
+
+    // Write out the cast of the instruction's value back to the proper type
+    // if necessary.
+    bool NeedsClosingParens = writeInstructionCast(I);
+
+    // Certain instructions require the operand to be forced to a specific type
+    // so we use writeOperandWithCast here instead of writeOperand. Similarly
+    // below for operand 1
+    writeOperandWithCast(I.getOperand(0), I.getOpcode());
 
     switch (I.getOpcode()) {
     case Instruction::Add: Out << " + "; break;
     case Instruction::Sub: Out << " - "; break;
     case Instruction::Mul: Out << '*'; break;
-    case Instruction::Div: Out << '/'; break;
-    case Instruction::Rem: Out << '%'; break;
+    case Instruction::URem:
+    case Instruction::SRem:
+    case Instruction::FRem: Out << '%'; break;
+    case Instruction::UDiv:
+    case Instruction::SDiv: 
+    case Instruction::FDiv: Out << '/'; break;
     case Instruction::And: Out << " & "; break;
     case Instruction::Or: Out << " | "; break;
     case Instruction::Xor: Out << " ^ "; break;
@@ -1660,11 +1964,14 @@ void CWriter::visitBinaryOperator(Instruction &I) {
     case Instruction::SetLT: Out << " < "; break;
     case Instruction::SetGT: Out << " > "; break;
     case Instruction::Shl : Out << " << "; break;
-    case Instruction::Shr : Out << " >> "; break;
+    case Instruction::LShr:
+    case Instruction::AShr: Out << " >> "; break;
     default: std::cerr << "Invalid operator type!" << I; abort();
     }
 
-    writeOperand(I.getOperand(1));
+    writeOperandWithCast(I.getOperand(1), I.getOpcode());
+    if (NeedsClosingParens)
+      Out << "))";
   }
 
   if (needsCast) {
@@ -1673,22 +1980,24 @@ void CWriter::visitBinaryOperator(Instruction &I) {
 }
 
 void CWriter::visitCastInst(CastInst &I) {
-  if (I.getType() == Type::BoolTy) {
-    Out << '(';
-    writeOperand(I.getOperand(0));
-    Out << " != 0)";
-    return;
-  }
+  const Type *DstTy = I.getType();
+  const Type *SrcTy = I.getOperand(0)->getType();
   Out << '(';
-  printType(Out, I.getType());
-  Out << ')';
-  if (isa<PointerType>(I.getType())&&I.getOperand(0)->getType()->isIntegral() ||
-      isa<PointerType>(I.getOperand(0)->getType())&&I.getType()->isIntegral()) {
-    // Avoid "cast to pointer from integer of different size" warnings
-    Out << "(long)";
+  printCast(I.getOpcode(), SrcTy, DstTy);
+  if (I.getOpcode() == Instruction::SExt && SrcTy == Type::BoolTy) {
+    // Make sure we really get a sext from bool by subtracing the bool from 0
+    Out << "0-";
   }
-
   writeOperand(I.getOperand(0));
+  if (DstTy == Type::BoolTy && 
+      (I.getOpcode() == Instruction::Trunc ||
+       I.getOpcode() == Instruction::FPToUI ||
+       I.getOpcode() == Instruction::FPToSI ||
+       I.getOpcode() == Instruction::PtrToInt)) {
+    // Make sure we really get a trunc to bool by anding the operand with 1 
+    Out << "&1u";
+  }
+  Out << ')';
 }
 
 void CWriter::visitSelectInst(SelectInst &I) {
@@ -1750,6 +2059,12 @@ void CWriter::lowerIntrinsics(Function &F) {
 
 
 void CWriter::visitCallInst(CallInst &I) {
+  //check if we have inline asm
+  if (isInlineAsm(I)) {
+    visitInlineAsm(I);
+    return;
+  }
+
   bool WroteCallee = false;
 
   // Handle intrinsic function calls first...
@@ -1895,7 +2210,7 @@ void CWriter::visitCallInst(CallInst &I) {
     // match exactly.
     //
     if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Callee))
-      if (CE->getOpcode() == Instruction::Cast)
+      if (CE->isCast())
         if (Function *RF = dyn_cast<Function>(CE->getOperand(0))) {
           NeedsCast = true;
           Callee = RF;
@@ -1941,6 +2256,136 @@ void CWriter::visitCallInst(CallInst &I) {
   Out << ')';
 }
 
+
+//This converts the llvm constraint string to something gcc is expecting.
+//TODO: work out platform independent constraints and factor those out
+//      of the per target tables
+//      handle multiple constraint codes
+std::string CWriter::InterpretASMConstraint(InlineAsm::ConstraintInfo& c) {
+
+  assert(c.Codes.size() == 1 && "Too many asm constraint codes to handle");
+
+  //catch numeric constraints
+  if (c.Codes[0].find_first_not_of("0123456789") >= c.Codes[0].size())
+    return c.Codes[0];
+
+  const char** table = 0;
+  
+  //Grab the translation table from TargetAsmInfo if it exists
+  if (!TAsm) {
+    std::string E;
+    const TargetMachineRegistry::Entry* Match = 
+      TargetMachineRegistry::getClosestStaticTargetForModule(*TheModule, E);
+    if (Match) {
+      //Per platform Target Machines don't exist, so create it
+      // this must be done only once
+      const TargetMachine* TM = Match->CtorFn(*TheModule, "");
+      TAsm = TM->getTargetAsmInfo();
+    }
+  }
+  if (TAsm)
+    table = TAsm->getAsmCBE();
+
+  //Search the translation table if it exists
+  for (int i = 0; table && table[i]; i += 2)
+    if (c.Codes[0] == table[i])
+      return table[i+1];
+
+  assert(0 && "Unknown Asm Constraint");
+  return "";
+}
+
+//TODO: import logic from AsmPrinter.cpp
+static std::string gccifyAsm(std::string asmstr) {
+  for (std::string::size_type i = 0; i != asmstr.size(); ++i)
+    if (asmstr[i] == '\n')
+      asmstr.replace(i, 1, "\\n");
+    else if (asmstr[i] == '\t')
+      asmstr.replace(i, 1, "\\t");
+    else if (asmstr[i] == '$') {
+      if (asmstr[i + 1] == '{') {
+        std::string::size_type a = asmstr.find_first_of(':', i + 1);
+        std::string::size_type b = asmstr.find_first_of('}', i + 1);
+        std::string n = "%" + 
+          asmstr.substr(a + 1, b - a - 1) +
+          asmstr.substr(i + 2, a - i - 2);
+        asmstr.replace(i, b - i + 1, n);
+        i += n.size() - 1;
+      } else
+        asmstr.replace(i, 1, "%");
+    }
+    else if (asmstr[i] == '%')//grr
+      { asmstr.replace(i, 1, "%%"); ++i;}
+  
+  return asmstr;
+}
+
+//TODO: assumptions about what consume arguments from the call are likely wrong
+//      handle communitivity
+void CWriter::visitInlineAsm(CallInst &CI) {
+  InlineAsm* as = cast<InlineAsm>(CI.getOperand(0));
+  std::vector<InlineAsm::ConstraintInfo> Constraints = as->ParseConstraints();
+  std::vector<std::pair<std::string, Value*> > Input;
+  std::vector<std::pair<std::string, Value*> > Output;
+  std::string Clobber;
+  int count = CI.getType() == Type::VoidTy ? 1 : 0;
+  for (std::vector<InlineAsm::ConstraintInfo>::iterator I = Constraints.begin(),
+         E = Constraints.end(); I != E; ++I) {
+    assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle");
+    std::string c = 
+      InterpretASMConstraint(*I);
+    switch(I->Type) {
+    default:
+      assert(0 && "Unknown asm constraint");
+      break;
+    case InlineAsm::isInput: {
+      if (c.size()) {
+        Input.push_back(std::make_pair(c, count ? CI.getOperand(count) : &CI));
+        ++count; //consume arg
+      }
+      break;
+    }
+    case InlineAsm::isOutput: {
+      if (c.size()) {
+        Output.push_back(std::make_pair("="+((I->isEarlyClobber ? "&" : "")+c),
+                                        count ? CI.getOperand(count) : &CI));
+        ++count; //consume arg
+      }
+      break;
+    }
+    case InlineAsm::isClobber: {
+      if (c.size()) 
+        Clobber += ",\"" + c + "\"";
+      break;
+    }
+    }
+  }
+  
+  //fix up the asm string for gcc
+  std::string asmstr = gccifyAsm(as->getAsmString());
+  
+  Out << "__asm__ volatile (\"" << asmstr << "\"\n";
+  Out << "        :";
+  for (std::vector<std::pair<std::string, Value*> >::iterator I = Output.begin(),
+         E = Output.end(); I != E; ++I) {
+    Out << "\"" << I->first << "\"(";
+    writeOperandRaw(I->second);
+    Out << ")";
+    if (I + 1 != E)
+      Out << ",";
+  }
+  Out << "\n        :";
+  for (std::vector<std::pair<std::string, Value*> >::iterator I = Input.begin(),
+         E = Input.end(); I != E; ++I) {
+    Out << "\"" << I->first << "\"(";
+    writeOperandRaw(I->second);
+    Out << ")";
+    if (I + 1 != E)
+      Out << ",";
+  }
+  Out << "\n        :" << Clobber.substr(1) << ")\n";
+}
+
 void CWriter::visitMallocInst(MallocInst &I) {
   assert(0 && "lowerallocations pass didn't work!");
 }
@@ -1966,7 +2411,7 @@ void CWriter::printIndexingExpression(Value *Ptr, gep_type_iterator I,
                                       gep_type_iterator E) {
   bool HasImplicitAddress = false;
   // If accessing a global value with no indexing, avoid *(&GV) syndrome
-  if (GlobalValue *V = dyn_cast<GlobalValue>(Ptr)) {
+  if (isa<GlobalValue>(Ptr)) {
     HasImplicitAddress = true;
   } else if (isDirectAlloca(Ptr)) {
     HasImplicitAddress = true;