Partial CBackend support for 128-bit integers. This is needed
[oota-llvm.git] / lib / Target / CBackend / CBackend.cpp
index bdef34d7ebd817be01705e9d95aa70ea12bd9ee8..161c6be0f9e3cd5d63bf32f3969a579caa2a5e3b 100644 (file)
@@ -18,7 +18,6 @@
 #include "llvm/DerivedTypes.h"
 #include "llvm/Module.h"
 #include "llvm/Instructions.h"
-#include "llvm/ParamAttrsList.h"
 #include "llvm/Pass.h"
 #include "llvm/PassManager.h"
 #include "llvm/TypeSymbolTable.h"
@@ -87,11 +86,11 @@ namespace {
     std::map<const Type *, std::string> TypeNames;
     std::map<const ConstantFP *, unsigned> FPConstantMap;
     std::set<Function*> intrinsicPrototypesAlreadyGenerated;
-    std::set<const Value*> ByValParams;
+    std::set<const Argument*> ByValParams;
 
   public:
     static char ID;
-    CWriter(std::ostream &o) 
+    explicit CWriter(std::ostream &o)
       : FunctionPass((intptr_t)&ID), Out(o), IL(0), Mang(0), LI(0), 
         TheModule(0), TAsm(0), TD(0) {}
 
@@ -122,8 +121,8 @@ namespace {
       delete Mang;
       FPConstantMap.clear();
       TypeNames.clear();
-      intrinsicPrototypesAlreadyGenerated.clear();
       ByValParams.clear();
+      intrinsicPrototypesAlreadyGenerated.clear();
       return false;
     }
 
@@ -131,14 +130,28 @@ namespace {
                             bool isSigned = false,
                             const std::string &VariableName = "",
                             bool IgnoreName = false,
-                            const ParamAttrsList *PAL = 0);
+                            const PAListPtr &PAL = PAListPtr());
     std::ostream &printSimpleType(std::ostream &Out, const Type *Ty, 
                                   bool isSigned, 
                                   const std::string &NameSoFar = "");
 
     void printStructReturnPointerFunctionType(std::ostream &Out,
-                                              const ParamAttrsList *PAL,
+                                              const PAListPtr &PAL,
                                               const PointerType *Ty);
+
+    /// writeOperandDeref - Print the result of dereferencing the specified
+    /// operand with '*'.  This is equivalent to printing '*' then using
+    /// writeOperand, but avoids excess syntax in some cases.
+    void writeOperandDeref(Value *Operand) {
+      if (isAddressExposed(Operand)) {
+        // Already something with an address exposed.
+        writeOperandInternal(Operand);
+      } else {
+        Out << "*(";
+        writeOperand(Operand);
+        Out << ")";
+      }
+    }
     
     void writeOperand(Value *Operand);
     void writeOperandRaw(Value *Operand);
@@ -170,8 +183,17 @@ namespace {
     void printConstantWithCast(Constant *CPV, unsigned Opcode);
     bool printConstExprCast(const ConstantExpr *CE);
     void printConstantArray(ConstantArray *CPA);
-    void printConstantVector(ConstantVector *CP);
+    void printConstantVector(ConstantVector *CV);
 
+    /// isAddressExposed - Return true if the specified value's name needs to
+    /// have its address taken in order to get a C value of the correct type.
+    /// This happens for global variables, byval parameters, and direct allocas.
+    bool isAddressExposed(const Value *V) const {
+      if (const Argument *A = dyn_cast<Argument>(V))
+        return ByValParams.count(A);
+      return isa<GlobalVariable>(V) || isDirectAlloca(V);
+    }
+    
     // isInlinableInst - Attempt to inline instructions into their uses to build
     // trees as much as possible.  To do this, we have to consistently decide
     // what is acceptable to inline, so that variable declarations don't get
@@ -191,8 +213,13 @@ 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;
+      // Must not be used in inline asm, extractelement, or shufflevector.
+      if (I.hasOneUse()) {
+        const Instruction &User = cast<Instruction>(*I.use_back());
+        if (isInlineAsm(User) || isa<ExtractElementInst>(User) ||
+            isa<ShuffleVectorInst>(User))
+          return false;
+      }
 
       // Only inline instruction it if it's use is in the same BB as the inst.
       return I.getParent() == cast<Instruction>(I.use_back())->getParent();
@@ -243,6 +270,7 @@ namespace {
     void visitSelectInst(SelectInst &I);
     void visitCallInst (CallInst &I);
     void visitInlineAsm(CallInst &I);
+    bool visitBuiltinCall(CallInst &I, Intrinsic::ID ID, bool &WroteCallee);
 
     void visitMallocInst(MallocInst &I);
     void visitAllocaInst(AllocaInst &I);
@@ -253,6 +281,8 @@ namespace {
     void visitVAArgInst (VAArgInst &I);
     
     void visitInsertElementInst(InsertElementInst &I);
+    void visitExtractElementInst(ExtractElementInst &I);
+    void visitShuffleVectorInst(ShuffleVectorInst &SVI);
 
     void visitInstruction(Instruction &I) {
       cerr << "C Writer does not know about " << I;
@@ -268,8 +298,8 @@ namespace {
                                     BasicBlock *Successor, unsigned Indent);
     void printBranchToBlock(BasicBlock *CurBlock, BasicBlock *SuccBlock,
                             unsigned Indent);
-    void printIndexingExpression(Value *Ptr, gep_type_iterator I,
-                                 gep_type_iterator E);
+    void printGEPExpression(Value *Ptr, gep_type_iterator I,
+                            gep_type_iterator E);
 
     std::string GetValueName(const Value *Operand);
   };
@@ -364,7 +394,7 @@ bool CBackendNameAllUsedStructsAndMergeFunctions::runOnModule(Module &M) {
 /// return type, except, instead of printing the type as void (*)(Struct*, ...)
 /// print it as "Struct (*)(...)", for struct return functions.
 void CWriter::printStructReturnPointerFunctionType(std::ostream &Out,
-                                                   const ParamAttrsList *PAL,
+                                                   const PAListPtr &PAL,
                                                    const PointerType *TheTy) {
   const FunctionType *FTy = cast<FunctionType>(TheTy->getElementType());
   std::stringstream FunctionInnards;
@@ -378,12 +408,12 @@ void CWriter::printStructReturnPointerFunctionType(std::ostream &Out,
     if (PrintedType)
       FunctionInnards << ", ";
     const Type *ArgTy = *I;
-    if (PAL && PAL->paramHasAttr(Idx, ParamAttr::ByVal)) {
+    if (PAL.paramHasAttr(Idx, ParamAttr::ByVal)) {
       assert(isa<PointerType>(ArgTy));
       ArgTy = cast<PointerType>(ArgTy)->getElementType();
     }
     printType(FunctionInnards, ArgTy,
-        /*isSigned=*/PAL && PAL->paramHasAttr(Idx, ParamAttr::SExt), "");
+        /*isSigned=*/PAL.paramHasAttr(Idx, ParamAttr::SExt), "");
     PrintedType = true;
   }
   if (FTy->isVarArg()) {
@@ -395,7 +425,7 @@ void CWriter::printStructReturnPointerFunctionType(std::ostream &Out,
   FunctionInnards << ')';
   std::string tstr = FunctionInnards.str();
   printType(Out, RetTy, 
-      /*isSigned=*/PAL && PAL->paramHasAttr(0, ParamAttr::SExt), tstr);
+      /*isSigned=*/PAL.paramHasAttr(0, ParamAttr::SExt), tstr);
 }
 
 std::ostream &
@@ -415,9 +445,11 @@ CWriter::printSimpleType(std::ostream &Out, const Type *Ty, bool isSigned,
       return Out << (isSigned?"signed":"unsigned") << " short " << NameSoFar;
     else if (NumBits <= 32)
       return Out << (isSigned?"signed":"unsigned") << " int " << NameSoFar;
-    else { 
-      assert(NumBits <= 64 && "Bit widths > 64 not implemented yet");
+    else if (NumBits <= 64)
       return Out << (isSigned?"signed":"unsigned") << " long long "<< NameSoFar;
+    else { 
+      assert(NumBits <= 128 && "Bit widths > 128 not implemented yet");
+      return Out << (isSigned?"llvmInt128":"llvmUInt128") << " " << NameSoFar;
     }
   }
   case Type::FloatTyID:  return Out << "float "   << NameSoFar;
@@ -446,7 +478,7 @@ CWriter::printSimpleType(std::ostream &Out, const Type *Ty, bool isSigned,
 //
 std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty,
                                  bool isSigned, const std::string &NameSoFar,
-                                 bool IgnoreName, const ParamAttrsList* PAL) {
+                                 bool IgnoreName, const PAListPtr &PAL) {
   if (Ty->isPrimitiveType() || Ty->isInteger() || isa<VectorType>(Ty)) {
     printSimpleType(Out, Ty, isSigned, NameSoFar);
     return Out;
@@ -467,14 +499,14 @@ std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty,
     for (FunctionType::param_iterator I = FTy->param_begin(),
            E = FTy->param_end(); I != E; ++I) {
       const Type *ArgTy = *I;
-      if (PAL && PAL->paramHasAttr(Idx, ParamAttr::ByVal)) {
+      if (PAL.paramHasAttr(Idx, ParamAttr::ByVal)) {
         assert(isa<PointerType>(ArgTy));
         ArgTy = cast<PointerType>(ArgTy)->getElementType();
       }
       if (I != FTy->param_begin())
         FunctionInnards << ", ";
       printType(FunctionInnards, ArgTy,
-        /*isSigned=*/PAL && PAL->paramHasAttr(Idx, ParamAttr::SExt), "");
+        /*isSigned=*/PAL.paramHasAttr(Idx, ParamAttr::SExt), "");
       ++Idx;
     }
     if (FTy->isVarArg()) {
@@ -486,7 +518,7 @@ std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty,
     FunctionInnards << ')';
     std::string tstr = FunctionInnards.str();
     printType(Out, FTy->getReturnType(), 
-      /*isSigned=*/PAL && PAL->paramHasAttr(0, ParamAttr::SExt), tstr);
+      /*isSigned=*/PAL.paramHasAttr(0, ParamAttr::SExt), tstr);
     return Out;
   }
   case Type::StructTyID: {
@@ -513,7 +545,7 @@ std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty,
         isa<VectorType>(PTy->getElementType()))
       ptrName = "(" + ptrName + ")";
 
-    if (PAL)
+    if (!PAL.isEmpty())
       // Must be a function ptr cast!
       return printType(Out, PTy->getElementType(), false, ptrName, true, PAL);
     return printType(Out, PTy->getElementType(), false, ptrName);
@@ -765,10 +797,10 @@ void CWriter::printConstant(Constant *CPV) {
       return;
 
     case Instruction::GetElementPtr:
-      Out << "(&(";
-      printIndexingExpression(CE->getOperand(0), gep_type_begin(CPV),
-                              gep_type_end(CPV));
-      Out << "))";
+      Out << "(";
+      printGEPExpression(CE->getOperand(0), gep_type_begin(CPV),
+                         gep_type_end(CPV));
+      Out << ")";
       return;
     case Instruction::Select:
       Out << '(';
@@ -883,7 +915,12 @@ void CWriter::printConstant(Constant *CPV) {
   } else if (isa<UndefValue>(CPV) && CPV->getType()->isFirstClassType()) {
     Out << "((";
     printType(Out, CPV->getType()); // sign doesn't matter
-    Out << ")/*UNDEF*/0)";
+    Out << ")/*UNDEF*/";
+    if (!isa<VectorType>(CPV->getType())) {
+      Out << "0)";
+    } else {
+      Out << "{})";
+    }
     return;
   }
 
@@ -974,7 +1011,7 @@ void CWriter::printConstant(Constant *CPV) {
   }
 
   case Type::ArrayTyID:
-    if (ConstantArray *CA = cast<ConstantArray>(CPV)) {
+    if (ConstantArray *CA = dyn_cast<ConstantArray>(CPV)) {
       printConstantArray(CA);
     } else {
       assert(isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV));
@@ -998,7 +1035,7 @@ void CWriter::printConstant(Constant *CPV) {
     Out << "(";
     printType(Out, CPV->getType());
     Out << ")";
-    if (ConstantVector *CV = cast<ConstantVector>(CPV)) {
+    if (ConstantVector *CV = dyn_cast<ConstantVector>(CPV)) {
       printConstantVector(CV);
     } else {
       assert(isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV));
@@ -1207,12 +1244,13 @@ void CWriter::writeOperandRaw(Value *Operand) {
 }
 
 void CWriter::writeOperand(Value *Operand) {
-  if (isa<GlobalVariable>(Operand) || isDirectAlloca(Operand))
+  bool isAddressImplicit = isAddressExposed(Operand);
+  if (isAddressImplicit)
     Out << "(&";  // Global variables are referenced as their addresses by llvm
 
   writeOperandInternal(Operand);
 
-  if (isa<GlobalVariable>(Operand) || isDirectAlloca(Operand))
+  if (isAddressImplicit)
     Out << ')';
 }
 
@@ -1442,6 +1480,11 @@ static void generateCompilerSpecificCode(std::ostream& Out) {
       << "#define __builtin_stack_restore(X) /* noop */\n"
       << "#endif\n\n";
 
+  Out << "#ifdef __GNUC__ /* 128-bit integer types */\n"
+      << "typedef int __attribute__((mode(TI))) llvmInt128;\n"
+      << "typedef unsigned __attribute__((mode(TI))) llvmUInt128;\n"
+      << "#endif\n\n";
+
   // Output target-specific code that should be inserted into main.
   Out << "#define CODE_FOR_MAIN() /* Any target-specific code for main()*/\n";
 }
@@ -1867,7 +1910,7 @@ void CWriter::printContainedStructs(const Type *Ty,
 
 void CWriter::printFunctionSignature(const Function *F, bool Prototype) {
   /// isStructReturn - Should this function actually return a struct by-value?
-  bool isStructReturn = F->isStructReturn();
+  bool isStructReturn = F->hasStructRetAttr();
   
   if (F->hasInternalLinkage()) Out << "static ";
   if (F->hasDLLImportLinkage()) Out << "__declspec(dllimport) ";
@@ -1883,7 +1926,7 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) {
   
   // Loop over the arguments, printing them...
   const FunctionType *FT = cast<FunctionType>(F->getFunctionType());
-  const ParamAttrsList *PAL = F->getParamAttrs();
+  const PAListPtr &PAL = F->getParamAttrs();
 
   std::stringstream FunctionInnards;
 
@@ -1912,14 +1955,12 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) {
         else
           ArgName = "";
         const Type *ArgTy = I->getType();
-        if (PAL && PAL->paramHasAttr(Idx, ParamAttr::ByVal)) {
-          assert(isa<PointerType>(ArgTy));
+        if (PAL.paramHasAttr(Idx, ParamAttr::ByVal)) {
           ArgTy = cast<PointerType>(ArgTy)->getElementType();
-          const Value *Arg = &(*I);
-          ByValParams.insert(Arg);
+          ByValParams.insert(I);
         }
         printType(FunctionInnards, ArgTy,
-            /*isSigned=*/PAL && PAL->paramHasAttr(Idx, ParamAttr::SExt),
+            /*isSigned=*/PAL.paramHasAttr(Idx, ParamAttr::SExt),
             ArgName);
         PrintedArg = true;
         ++Idx;
@@ -1941,12 +1982,12 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) {
     for (; I != E; ++I) {
       if (PrintedArg) FunctionInnards << ", ";
       const Type *ArgTy = *I;
-      if (PAL && PAL->paramHasAttr(Idx, ParamAttr::ByVal)) {
+      if (PAL.paramHasAttr(Idx, ParamAttr::ByVal)) {
         assert(isa<PointerType>(ArgTy));
         ArgTy = cast<PointerType>(ArgTy)->getElementType();
       }
       printType(FunctionInnards, ArgTy,
-             /*isSigned=*/PAL && PAL->paramHasAttr(Idx, ParamAttr::SExt));
+             /*isSigned=*/PAL.paramHasAttr(Idx, ParamAttr::SExt));
       PrintedArg = true;
       ++Idx;
     }
@@ -1974,7 +2015,7 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) {
     
   // Print out the return type and the signature built above.
   printType(Out, RetTy, 
-            /*isSigned=*/ PAL && PAL->paramHasAttr(0, ParamAttr::SExt),
+            /*isSigned=*/PAL.paramHasAttr(0, ParamAttr::SExt),
             FunctionInnards.str());
 }
 
@@ -1989,7 +2030,7 @@ static inline bool isFPIntBitCast(const Instruction &I) {
 
 void CWriter::printFunction(Function &F) {
   /// isStructReturn - Should this function actually return a struct by-value?
-  bool isStructReturn = F.isStructReturn();
+  bool isStructReturn = F.hasStructRetAttr();
 
   printFunctionSignature(&F, false);
   Out << " {\n";
@@ -2113,7 +2154,7 @@ void CWriter::printBasicBlock(BasicBlock *BB) {
 //
 void CWriter::visitReturnInst(ReturnInst &I) {
   // If this is a struct return function, return the temporary struct.
-  bool isStructReturn = I.getParent()->getParent()->isStructReturn();
+  bool isStructReturn = I.getParent()->getParent()->hasStructRetAttr();
 
   if (isStructReturn) {
     Out << "  return StructReturn;\n";
@@ -2423,13 +2464,6 @@ void CWriter::visitCastInst(CastInst &I) {
       // Make sure we really get a sext from bool by subtracing the bool from 0
       Out << "0-";
     }
-    // If it's a byval parameter being casted, then takes its address.
-    bool isByVal = ByValParams.count(I.getOperand(0));
-    if (isByVal) {
-      assert(I.getOpcode() == Instruction::BitCast &&
-             "ByVal aggregate parameter must ptr type");
-      Out << '&';
-    }
     writeOperand(I.getOperand(0));
     if (DstTy == Type::Int1Ty && 
         (I.getOpcode() == Instruction::Trunc ||
@@ -2479,7 +2513,12 @@ void CWriter::lowerIntrinsics(Function &F) {
           case Intrinsic::prefetch:
           case Intrinsic::dbg_stoppoint:
           case Intrinsic::powi:
-            // We directly implement these intrinsics
+          case Intrinsic::x86_sse_cmp_ss:
+          case Intrinsic::x86_sse_cmp_ps:
+          case Intrinsic::x86_sse2_cmp_sd:
+          case Intrinsic::x86_sse2_cmp_pd:
+          case Intrinsic::ppc_altivec_lvsl:
+              // We directly implement these intrinsics
             break;
           default:
             // If this is an intrinsic that directly corresponds to a GCC
@@ -2527,7 +2566,6 @@ void CWriter::lowerIntrinsics(Function &F) {
   }
 }
 
-
 void CWriter::visitCallInst(CallInst &I) {
   //check if we have inline asm
   if (isInlineAsm(I)) {
@@ -2539,114 +2577,9 @@ void CWriter::visitCallInst(CallInst &I) {
 
   // Handle intrinsic function calls first...
   if (Function *F = I.getCalledFunction())
-    if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) {
-      switch (ID) {
-      default: {
-        // If this is an intrinsic that directly corresponds to a GCC
-        // builtin, we emit it here.
-        const char *BuiltinName = "";
-#define GET_GCC_BUILTIN_NAME
-#include "llvm/Intrinsics.gen"
-#undef GET_GCC_BUILTIN_NAME
-        assert(BuiltinName[0] && "Unknown LLVM intrinsic!");
-
-        Out << BuiltinName;
-        WroteCallee = true;
-        break;
-      }
-      case Intrinsic::memory_barrier:
-        Out << "0; __sync_syncronize()";
-        return;
-      case Intrinsic::vastart:
-        Out << "0; ";
-
-        Out << "va_start(*(va_list*)";
-        writeOperand(I.getOperand(1));
-        Out << ", ";
-        // Output the last argument to the enclosing function...
-        if (I.getParent()->getParent()->arg_empty()) {
-          cerr << "The C backend does not currently support zero "
-               << "argument varargs functions, such as '"
-               << I.getParent()->getParent()->getName() << "'!\n";
-          abort();
-        }
-        writeOperand(--I.getParent()->getParent()->arg_end());
-        Out << ')';
-        return;
-      case Intrinsic::vaend:
-        if (!isa<ConstantPointerNull>(I.getOperand(1))) {
-          Out << "0; va_end(*(va_list*)";
-          writeOperand(I.getOperand(1));
-          Out << ')';
-        } else {
-          Out << "va_end(*(va_list*)0)";
-        }
-        return;
-      case Intrinsic::vacopy:
-        Out << "0; ";
-        Out << "va_copy(*(va_list*)";
-        writeOperand(I.getOperand(1));
-        Out << ", *(va_list*)";
-        writeOperand(I.getOperand(2));
-        Out << ')';
-        return;
-      case Intrinsic::returnaddress:
-        Out << "__builtin_return_address(";
-        writeOperand(I.getOperand(1));
-        Out << ')';
-        return;
-      case Intrinsic::frameaddress:
-        Out << "__builtin_frame_address(";
-        writeOperand(I.getOperand(1));
-        Out << ')';
-        return;
-      case Intrinsic::powi:
-        Out << "__builtin_powi(";
-        writeOperand(I.getOperand(1));
-        Out << ", ";
-        writeOperand(I.getOperand(2));
-        Out << ')';
-        return;
-      case Intrinsic::setjmp:
-        Out << "setjmp(*(jmp_buf*)";
-        writeOperand(I.getOperand(1));
-        Out << ')';
-        return;
-      case Intrinsic::longjmp:
-        Out << "longjmp(*(jmp_buf*)";
-        writeOperand(I.getOperand(1));
-        Out << ", ";
-        writeOperand(I.getOperand(2));
-        Out << ')';
-        return;
-      case Intrinsic::prefetch:
-        Out << "LLVM_PREFETCH((const void *)";
-        writeOperand(I.getOperand(1));
-        Out << ", ";
-        writeOperand(I.getOperand(2));
-        Out << ", ";
-        writeOperand(I.getOperand(3));
-        Out << ")";
+    if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
+      if (visitBuiltinCall(I, ID, WroteCallee))
         return;
-      case Intrinsic::stacksave:
-        // Emit this as: Val = 0; *((void**)&Val) = __builtin_stack_save()
-        // to work around GCC bugs (see PR1809).
-        Out << "0; *((void**)&" << GetValueName(&I)
-            << ") = __builtin_stack_save()";
-        return;
-      case Intrinsic::dbg_stoppoint: {
-        // If we use writeOperand directly we get a "u" suffix which is rejected
-        // by gcc.
-        DbgStopPointInst &SPI = cast<DbgStopPointInst>(I);
-
-        Out << "\n#line "
-            << SPI.getLine()
-            << " \"" << SPI.getDirectory()
-            << SPI.getFileName() << "\"\n";
-        return;
-      }
-      }
-    }
 
   Value *Callee = I.getCalledValue();
 
@@ -2655,14 +2588,11 @@ void CWriter::visitCallInst(CallInst &I) {
 
   // If this is a call to a struct-return function, assign to the first
   // parameter instead of passing it to the call.
-  const ParamAttrsList *PAL = I.getParamAttrs();
+  const PAListPtr &PAL = I.getParamAttrs();
   bool hasByVal = I.hasByValArgument();
-  bool isStructRet = I.isStructReturn();
+  bool isStructRet = I.hasStructRetAttr();
   if (isStructRet) {
-    bool isByVal = ByValParams.count(I.getOperand(1));
-    if (!isByVal) Out << "*(";
-    writeOperand(I.getOperand(1));
-    if (!isByVal) Out << ")";
+    writeOperandDeref(I.getOperand(1));
     Out << " = ";
   }
   
@@ -2726,25 +2656,173 @@ void CWriter::visitCallInst(CallInst &I) {
         (*AI)->getType() != FTy->getParamType(ArgNo)) {
       Out << '(';
       printType(Out, FTy->getParamType(ArgNo), 
-            /*isSigned=*/PAL && PAL->paramHasAttr(ArgNo+1, ParamAttr::SExt));
+            /*isSigned=*/PAL.paramHasAttr(ArgNo+1, ParamAttr::SExt));
       Out << ')';
     }
     // Check if the argument is expected to be passed by value.
-    bool isOutByVal = PAL && PAL->paramHasAttr(ArgNo+1, ParamAttr::ByVal);
-    // Check if this argument itself is passed in by reference. 
-    bool isInByVal = ByValParams.count(*AI);
-    if (isOutByVal && !isInByVal)
-      Out << "*(";
-    else if (!isOutByVal && isInByVal)
-      Out << "&(";
-    writeOperand(*AI);
-    if (isOutByVal ^ isInByVal)
-      Out << ")";
+    if (I.paramHasAttr(ArgNo+1, ParamAttr::ByVal))
+      writeOperandDeref(*AI);
+    else
+      writeOperand(*AI);
     PrintedArg = true;
   }
   Out << ')';
 }
 
+/// visitBuiltinCall - Handle the call to the specified builtin.  Returns true
+/// if the entire call is handled, return false it it wasn't handled, and
+/// optionally set 'WroteCallee' if the callee has already been printed out.
+bool CWriter::visitBuiltinCall(CallInst &I, Intrinsic::ID ID,
+                               bool &WroteCallee) {
+  switch (ID) {
+  default: {
+    // If this is an intrinsic that directly corresponds to a GCC
+    // builtin, we emit it here.
+    const char *BuiltinName = "";
+    Function *F = I.getCalledFunction();
+#define GET_GCC_BUILTIN_NAME
+#include "llvm/Intrinsics.gen"
+#undef GET_GCC_BUILTIN_NAME
+    assert(BuiltinName[0] && "Unknown LLVM intrinsic!");
+    
+    Out << BuiltinName;
+    WroteCallee = true;
+    return false;
+  }
+  case Intrinsic::memory_barrier:
+    Out << "__sync_synchronize()";
+    return true;
+  case Intrinsic::vastart:
+    Out << "0; ";
+      
+    Out << "va_start(*(va_list*)";
+    writeOperand(I.getOperand(1));
+    Out << ", ";
+    // Output the last argument to the enclosing function.
+    if (I.getParent()->getParent()->arg_empty()) {
+      cerr << "The C backend does not currently support zero "
+           << "argument varargs functions, such as '"
+           << I.getParent()->getParent()->getName() << "'!\n";
+      abort();
+    }
+    writeOperand(--I.getParent()->getParent()->arg_end());
+    Out << ')';
+    return true;
+  case Intrinsic::vaend:
+    if (!isa<ConstantPointerNull>(I.getOperand(1))) {
+      Out << "0; va_end(*(va_list*)";
+      writeOperand(I.getOperand(1));
+      Out << ')';
+    } else {
+      Out << "va_end(*(va_list*)0)";
+    }
+    return true;
+  case Intrinsic::vacopy:
+    Out << "0; ";
+    Out << "va_copy(*(va_list*)";
+    writeOperand(I.getOperand(1));
+    Out << ", *(va_list*)";
+    writeOperand(I.getOperand(2));
+    Out << ')';
+    return true;
+  case Intrinsic::returnaddress:
+    Out << "__builtin_return_address(";
+    writeOperand(I.getOperand(1));
+    Out << ')';
+    return true;
+  case Intrinsic::frameaddress:
+    Out << "__builtin_frame_address(";
+    writeOperand(I.getOperand(1));
+    Out << ')';
+    return true;
+  case Intrinsic::powi:
+    Out << "__builtin_powi(";
+    writeOperand(I.getOperand(1));
+    Out << ", ";
+    writeOperand(I.getOperand(2));
+    Out << ')';
+    return true;
+  case Intrinsic::setjmp:
+    Out << "setjmp(*(jmp_buf*)";
+    writeOperand(I.getOperand(1));
+    Out << ')';
+    return true;
+  case Intrinsic::longjmp:
+    Out << "longjmp(*(jmp_buf*)";
+    writeOperand(I.getOperand(1));
+    Out << ", ";
+    writeOperand(I.getOperand(2));
+    Out << ')';
+    return true;
+  case Intrinsic::prefetch:
+    Out << "LLVM_PREFETCH((const void *)";
+    writeOperand(I.getOperand(1));
+    Out << ", ";
+    writeOperand(I.getOperand(2));
+    Out << ", ";
+    writeOperand(I.getOperand(3));
+    Out << ")";
+    return true;
+  case Intrinsic::stacksave:
+    // Emit this as: Val = 0; *((void**)&Val) = __builtin_stack_save()
+    // to work around GCC bugs (see PR1809).
+    Out << "0; *((void**)&" << GetValueName(&I)
+        << ") = __builtin_stack_save()";
+    return true;
+  case Intrinsic::dbg_stoppoint: {
+    // If we use writeOperand directly we get a "u" suffix which is rejected
+    // by gcc.
+    DbgStopPointInst &SPI = cast<DbgStopPointInst>(I);
+    Out << "\n#line "
+        << SPI.getLine()
+        << " \"" << SPI.getDirectory()
+        << SPI.getFileName() << "\"\n";
+    return true;
+  }
+  case Intrinsic::x86_sse_cmp_ss:
+  case Intrinsic::x86_sse_cmp_ps:
+  case Intrinsic::x86_sse2_cmp_sd:
+  case Intrinsic::x86_sse2_cmp_pd:
+    Out << '(';
+    printType(Out, I.getType());
+    Out << ')';  
+    // Multiple GCC builtins multiplex onto this intrinsic.
+    switch (cast<ConstantInt>(I.getOperand(3))->getZExtValue()) {
+    default: assert(0 && "Invalid llvm.x86.sse.cmp!");
+    case 0: Out << "__builtin_ia32_cmpeq"; break;
+    case 1: Out << "__builtin_ia32_cmplt"; break;
+    case 2: Out << "__builtin_ia32_cmple"; break;
+    case 3: Out << "__builtin_ia32_cmpunord"; break;
+    case 4: Out << "__builtin_ia32_cmpneq"; break;
+    case 5: Out << "__builtin_ia32_cmpnlt"; break;
+    case 6: Out << "__builtin_ia32_cmpnle"; break;
+    case 7: Out << "__builtin_ia32_cmpord"; break;
+    }
+    if (ID == Intrinsic::x86_sse_cmp_ps || ID == Intrinsic::x86_sse2_cmp_pd)
+      Out << 'p';
+    else
+      Out << 's';
+    if (ID == Intrinsic::x86_sse_cmp_ss || ID == Intrinsic::x86_sse_cmp_ps)
+      Out << 's';
+    else
+      Out << 'd';
+      
+    Out << "(";
+    writeOperand(I.getOperand(1));
+    Out << ", ";
+    writeOperand(I.getOperand(2));
+    Out << ")";
+    return true;
+  case Intrinsic::ppc_altivec_lvsl:
+    Out << '(';
+    printType(Out, I.getType());
+    Out << ')';  
+    Out << "__builtin_altivec_lvsl(0, (void*)";
+    writeOperand(I.getOperand(1));
+    Out << ")";
+    return true;
+  }
+}
 
 //This converts the llvm constraint string to something gcc is expecting.
 //TODO: work out platform independent constraints and factor those out
@@ -2754,7 +2832,7 @@ std::string CWriter::InterpretASMConstraint(InlineAsm::ConstraintInfo& c) {
 
   assert(c.Codes.size() == 1 && "Too many asm constraint codes to handle");
 
-  const char** table = 0;
+  const char *const *table = 0;
   
   //Grab the translation table from TargetAsmInfo if it exists
   if (!TAsm) {
@@ -2851,7 +2929,7 @@ void CWriter::visitInlineAsm(CallInst &CI) {
   
   Out << "__asm__ volatile (\"" << asmstr << "\"\n";
   Out << "        :";
-  for (std::vector<std::pair<std::string, Value*> >::iterator I = Output.begin(),
+  for (std::vector<std::pair<std::string, Value*> >::iterator I =Output.begin(),
          E = Output.end(); I != E; ++I) {
     Out << "\"" << I->first << "\"(";
     writeOperandRaw(I->second);
@@ -2894,61 +2972,85 @@ void CWriter::visitFreeInst(FreeInst &I) {
   assert(0 && "lowerallocations pass didn't work!");
 }
 
-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 (isa<GlobalValue>(Ptr)) {
-    HasImplicitAddress = true;
-  } else if (isDirectAlloca(Ptr)) {
-    HasImplicitAddress = true;
-  }
-
+void CWriter::printGEPExpression(Value *Ptr, gep_type_iterator I,
+                                 gep_type_iterator E) {
+  
+  // If there are no indices, just print out the pointer.
   if (I == E) {
-    if (!HasImplicitAddress)
-      Out << '*';  // Implicit zero first argument: '*x' is equivalent to 'x[0]'
-
-    writeOperandInternal(Ptr);
+    writeOperand(Ptr);
     return;
   }
-
-  const Constant *CI = dyn_cast<Constant>(I.getOperand());
-  if (HasImplicitAddress && (!CI || !CI->isNullValue()))
-    Out << "(&";
-
-  writeOperandInternal(Ptr);
-
-  if (HasImplicitAddress && (!CI || !CI->isNullValue())) {
-    Out << ')';
-    HasImplicitAddress = false;  // HIA is only true if we haven't addressed yet
+    
+  // Find out if the last index is into a vector.  If so, we have to print this
+  // specially.  Since vectors can't have elements of indexable type, only the
+  // last index could possibly be of a vector element.
+  const VectorType *LastIndexIsVector = 0;
+  {
+    for (gep_type_iterator TmpI = I; TmpI != E; ++TmpI)
+      LastIndexIsVector = dyn_cast<VectorType>(*TmpI);
   }
+  
+  Out << "(";
+  
+  // If the last index is into a vector, we can't print it as &a[i][j] because
+  // we can't index into a vector with j in GCC.  Instead, emit this as
+  // (((float*)&a[i])+j)
+  if (LastIndexIsVector) {
+    Out << "((";
+    printType(Out, PointerType::getUnqual(LastIndexIsVector->getElementType()));
+    Out << ")(";
+  }
+  
+  Out << '&';
 
-  assert((!HasImplicitAddress || (CI && CI->isNullValue())) &&
-         "Can only have implicit address with direct accessing");
-
-  if (HasImplicitAddress) {
-    ++I;
-  } else if (CI && CI->isNullValue()) {
-    gep_type_iterator TmpI = I; ++TmpI;
-
-    // Print out the -> operator if possible...
-    if (TmpI != E && isa<StructType>(*TmpI)) {
-      // Check if it's actually an aggregate parameter passed by value.
-      bool isByVal = ByValParams.count(Ptr);
-      Out << ((HasImplicitAddress || isByVal) ? "." : "->");
-      Out << "field" << cast<ConstantInt>(TmpI.getOperand())->getZExtValue();
-      I = ++TmpI;
+  // If the first index is 0 (very typical) we can do a number of
+  // simplifications to clean up the code.
+  Value *FirstOp = I.getOperand();
+  if (!isa<Constant>(FirstOp) || !cast<Constant>(FirstOp)->isNullValue()) {
+    // First index isn't simple, print it the hard way.
+    writeOperand(Ptr);
+  } else {
+    ++I;  // Skip the zero index.
+
+    // Okay, emit the first operand. If Ptr is something that is already address
+    // exposed, like a global, avoid emitting (&foo)[0], just emit foo instead.
+    if (isAddressExposed(Ptr)) {
+      writeOperandInternal(Ptr);
+    } else if (I != E && isa<StructType>(*I)) {
+      // If we didn't already emit the first operand, see if we can print it as
+      // P->f instead of "P[0].f"
+      writeOperand(Ptr);
+      Out << "->field" << cast<ConstantInt>(I.getOperand())->getZExtValue();
+      ++I;  // eat the struct index as well.
+    } else {
+      // Instead of emitting P[0][1], emit (*P)[1], which is more idiomatic.
+      Out << "(*";
+      writeOperand(Ptr);
+      Out << ")";
     }
   }
 
-  for (; I != E; ++I)
+  for (; I != E; ++I) {
     if (isa<StructType>(*I)) {
       Out << ".field" << cast<ConstantInt>(I.getOperand())->getZExtValue();
-    } else {
+    } else if (!isa<VectorType>(*I)) {
       Out << '[';
       writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr);
       Out << ']';
+    } else {
+      // If the last index is into a vector, then print it out as "+j)".  This
+      // works with the 'LastIndexIsVector' code above.
+      if (isa<Constant>(I.getOperand()) &&
+          cast<Constant>(I.getOperand())->isNullValue()) {
+        Out << "))";  // avoid "+0".
+      } else {
+        Out << ")+(";
+        writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr);
+        Out << "))";
+      }
     }
+  }
+  Out << ")";
 }
 
 void CWriter::writeMemoryAccess(Value *Operand, const Type *OperandType,
@@ -2982,14 +3084,12 @@ void CWriter::writeMemoryAccess(Value *Operand, const Type *OperandType,
 }
 
 void CWriter::visitLoadInst(LoadInst &I) {
-
   writeMemoryAccess(I.getOperand(0), I.getType(), I.isVolatile(),
                     I.getAlignment());
 
 }
 
 void CWriter::visitStoreInst(StoreInst &I) {
-
   writeMemoryAccess(I.getPointerOperand(), I.getOperand(0)->getType(),
                     I.isVolatile(), I.getAlignment());
   Out << " = ";
@@ -3011,9 +3111,8 @@ void CWriter::visitStoreInst(StoreInst &I) {
 }
 
 void CWriter::visitGetElementPtrInst(GetElementPtrInst &I) {
-  Out << '&';
-  printIndexingExpression(I.getPointerOperand(), gep_type_begin(I),
-                          gep_type_end(I));
+  printGEPExpression(I.getPointerOperand(), gep_type_begin(I),
+                     gep_type_end(I));
 }
 
 void CWriter::visitVAArgInst(VAArgInst &I) {
@@ -3031,12 +3130,54 @@ void CWriter::visitInsertElementInst(InsertElementInst &I) {
   Out << "((";
   printType(Out, PointerType::getUnqual(EltTy));
   Out << ")(&" << GetValueName(&I) << "))[";
-  writeOperand(I.getOperand(1));
-  Out << "] = (";
   writeOperand(I.getOperand(2));
+  Out << "] = (";
+  writeOperand(I.getOperand(1));
   Out << ")";
 }
 
+void CWriter::visitExtractElementInst(ExtractElementInst &I) {
+  // We know that our operand is not inlined.
+  Out << "((";
+  const Type *EltTy = 
+    cast<VectorType>(I.getOperand(0)->getType())->getElementType();
+  printType(Out, PointerType::getUnqual(EltTy));
+  Out << ")(&" << GetValueName(I.getOperand(0)) << "))[";
+  writeOperand(I.getOperand(1));
+  Out << "]";
+}
+
+void CWriter::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
+  Out << "(";
+  printType(Out, SVI.getType());
+  Out << "){ ";
+  const VectorType *VT = SVI.getType();
+  unsigned NumElts = VT->getNumElements();
+  const Type *EltTy = VT->getElementType();
+
+  for (unsigned i = 0; i != NumElts; ++i) {
+    if (i) Out << ", ";
+    int SrcVal = SVI.getMaskValue(i);
+    if ((unsigned)SrcVal >= NumElts*2) {
+      Out << " 0/*undef*/ ";
+    } else {
+      Value *Op = SVI.getOperand((unsigned)SrcVal >= NumElts);
+      if (isa<Instruction>(Op)) {
+        // Do an extractelement of this value from the appropriate input.
+        Out << "((";
+        printType(Out, PointerType::getUnqual(EltTy));
+        Out << ")(&" << GetValueName(Op)
+            << "))[" << (SrcVal & NumElts-1) << "]";
+      } else if (isa<ConstantAggregateZero>(Op) || isa<UndefValue>(Op)) {
+        Out << "0";
+      } else {
+        printConstant(cast<ConstantVector>(Op)->getOperand(SrcVal & NumElts-1));
+      }
+    }
+  }
+  Out << "}";
+}
+
 
 //===----------------------------------------------------------------------===//
 //                       External Interface declaration