Change the PointerType api for creating pointer types. The old functionality of Point...
[oota-llvm.git] / lib / AsmParser / llvmAsmParser.y
index 599300d30f5688248e7067a057ab21137ac261d2..855034cd92d16f18f6b20c76b62dec421f24062a 100644 (file)
@@ -491,7 +491,8 @@ static Value *getVal(const Type *Ty, const ValID &ID) {
    if (const FunctionType *FTy = dyn_cast<FunctionType>(ElTy))
      V = new Function(FTy, GlobalValue::ExternalLinkage);
    else
-     V = new GlobalVariable(ElTy, false, GlobalValue::ExternalLinkage);
+     V = new GlobalVariable(ElTy, false, GlobalValue::ExternalLinkage, 0, "",
+                            (Module*)0, false, PTy->getAddressSpace());
    break;
   }
   default:
@@ -722,13 +723,14 @@ ParseGlobalVariable(std::string *NameStr,
                     GlobalValue::LinkageTypes Linkage,
                     GlobalValue::VisibilityTypes Visibility,
                     bool isConstantGlobal, const Type *Ty,
-                    Constant *Initializer, bool IsThreadLocal) {
+                    Constant *Initializer, bool IsThreadLocal,
+                    unsigned AddressSpace = 0) {
   if (isa<FunctionType>(Ty)) {
     GenerateError("Cannot declare global vars of function type");
     return 0;
   }
 
-  const PointerType *PTy = PointerType::get(Ty);
+  const PointerType *PTy = PointerType::get(Ty, AddressSpace);
 
   std::string Name;
   if (NameStr) {
@@ -780,7 +782,7 @@ ParseGlobalVariable(std::string *NameStr,
   // Otherwise there is no existing GV to use, create one now.
   GlobalVariable *GV =
     new GlobalVariable(Ty, isConstantGlobal, Linkage, Initializer, Name,
-                       CurModule.CurrentModule, IsThreadLocal);
+                       CurModule.CurrentModule, IsThreadLocal, AddressSpace);
   GV->setVisibility(Visibility);
   InsertValue(GV, CurModule.Values);
   return GV;
@@ -1046,15 +1048,15 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
 %token<StrVal> STRINGCONSTANT ATSTRINGCONSTANT PCTSTRINGCONSTANT
 %type <StrVal> LocalName OptLocalName OptLocalAssign
 %type <StrVal> GlobalName OptGlobalAssign GlobalAssign
-%type <StrVal> OptSection SectionString
+%type <StrVal> OptSection SectionString OptGC
 
-%type <UIntVal> OptAlign OptCAlign
+%type <UIntVal> OptAlign OptCAlign OptAddrSpace
 
 %token ZEROINITIALIZER TRUETOK FALSETOK BEGINTOK ENDTOK
 %token DECLARE DEFINE GLOBAL CONSTANT SECTION ALIAS VOLATILE THREAD_LOCAL
 %token TO DOTDOTDOT NULL_TOK UNDEF INTERNAL LINKONCE WEAK APPENDING
 %token DLLIMPORT DLLEXPORT EXTERN_WEAK
-%token OPAQUE EXTERNAL TARGET TRIPLE ALIGN
+%token OPAQUE EXTERNAL TARGET TRIPLE ALIGN ADDRSPACE
 %token DEPLIBS CALL TAIL ASM_TOK MODULE SIDEEFFECT
 %token CC_TOK CCC_TOK FASTCC_TOK COLDCC_TOK X86_STDCALLCC_TOK X86_FASTCALLCC_TOK
 %token DATALAYOUT
@@ -1090,7 +1092,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
 
 // Function Attributes
 %token SIGNEXT ZEROEXT NORETURN INREG SRET NOUNWIND NOALIAS BYVAL NEST
-%token CONST PURE
+%token READNONE READONLY GC
 
 // Visibility Styles
 %token DEFAULT HIDDEN PROTECTED
@@ -1135,6 +1137,9 @@ FPType   : FLOAT | DOUBLE | PPC_FP128 | FP128 | X86_FP80;
 LocalName : LOCALVAR | STRINGCONSTANT | PCTSTRINGCONSTANT ;
 OptLocalName : LocalName | /*empty*/ { $$ = 0; };
 
+OptAddrSpace : ADDRSPACE '(' EUINT64VAL ')' { $$=$3; }
+             | /*empty*/                    { $$=0; };
+
 /// OptLocalAssign - Value producing statements have an optional assignment
 /// component.
 OptLocalAssign : LocalName '=' {
@@ -1234,8 +1239,8 @@ FuncAttr      : NORETURN { $$ = ParamAttr::NoReturn; }
               | NOUNWIND { $$ = ParamAttr::NoUnwind; }
               | ZEROEXT  { $$ = ParamAttr::ZExt;     }
               | SIGNEXT  { $$ = ParamAttr::SExt;     }
-              | PURE     { $$ = ParamAttr::Pure;     }
-              | CONST    { $$ = ParamAttr::Const;    }
+              | READNONE { $$ = ParamAttr::ReadNone; }
+              | READONLY { $$ = ParamAttr::ReadOnly; }
               ;
 
 OptFuncAttrs  : /* empty */ { $$ = ParamAttr::None; }
@@ -1244,6 +1249,12 @@ OptFuncAttrs  : /* empty */ { $$ = ParamAttr::None; }
               }
               ;
 
+OptGC         : /* empty */ { $$ = 0; }
+              | GC STRINGCONSTANT {
+                $$ = $2;
+              }
+              ;
+
 // OptAlign/OptCAlign - An optional alignment, and an optional alignment with
 // a comma before it.
 OptAlign : /*empty*/        { $$ = 0; } |
@@ -1262,6 +1273,7 @@ OptCAlign : /*empty*/            { $$ = 0; } |
 };
 
 
+
 SectionString : SECTION STRINGCONSTANT {
   for (unsigned i = 0, e = $2->length(); i != e; ++i)
     if ((*$2)[i] == '"' || (*$2)[i] == '\\')
@@ -1307,10 +1319,10 @@ Types
     $$ = new PATypeHolder($1);
     CHECK_FOR_ERROR
   }
-  | Types '*' {                             // Pointer type?
+  | Types OptAddrSpace '*' {                             // Pointer type?
     if (*$1 == Type::LabelTy)
       GEN_ERROR("Cannot form a pointer to a basic block");
-    $$ = new PATypeHolder(HandleUpRefs(PointerType::get(*$1)));
+    $$ = new PATypeHolder(HandleUpRefs(PointerType::get(*$1, $2)));
     delete $1;
     CHECK_FOR_ERROR
   }
@@ -1328,61 +1340,55 @@ Types
     CHECK_FOR_ERROR
   }
   | Types '(' ArgTypeListI ')' OptFuncAttrs {
+    // Allow but ignore attributes on function types; this permits auto-upgrade.
+    // FIXME: remove in LLVM 3.0.
+    const Type* RetTy = *$1;
+    if (!(RetTy->isFirstClassType() || RetTy == Type::VoidTy ||
+          isa<OpaqueType>(RetTy)))
+      GEN_ERROR("LLVM Functions cannot return aggregates");
+
     std::vector<const Type*> Params;
-    ParamAttrsVector Attrs;
-    if ($5 != ParamAttr::None) {
-      ParamAttrsWithIndex X; X.index = 0; X.attrs = $5;
-      Attrs.push_back(X);
-    }
-    unsigned index = 1;
     TypeWithAttrsList::iterator I = $3->begin(), E = $3->end();
-    for (; I != E; ++I, ++index) {
+    for (; I != E; ++I ) {
       const Type *Ty = I->Ty->get();
       Params.push_back(Ty);
-      if (Ty != Type::VoidTy)
-        if (I->Attrs != ParamAttr::None) {
-          ParamAttrsWithIndex X; X.index = index; X.attrs = I->Attrs;
-          Attrs.push_back(X);
-        }
     }
+
     bool isVarArg = Params.size() && Params.back() == Type::VoidTy;
     if (isVarArg) Params.pop_back();
 
-    ParamAttrsList *ActualAttrs = 0;
-    if (!Attrs.empty())
-      ActualAttrs = ParamAttrsList::get(Attrs);
-    FunctionType *FT = FunctionType::get(*$1, Params, isVarArg, ActualAttrs);
+    for (unsigned i = 0; i != Params.size(); ++i)
+      if (!(Params[i]->isFirstClassType() || isa<OpaqueType>(Params[i])))
+        GEN_ERROR("Function arguments must be value types!");
+
+    CHECK_FOR_ERROR
+
+    FunctionType *FT = FunctionType::get(RetTy, Params, isVarArg);
     delete $3;   // Delete the argument list
     delete $1;   // Delete the return type handle
     $$ = new PATypeHolder(HandleUpRefs(FT)); 
     CHECK_FOR_ERROR
   }
   | VOID '(' ArgTypeListI ')' OptFuncAttrs {
+    // Allow but ignore attributes on function types; this permits auto-upgrade.
+    // FIXME: remove in LLVM 3.0.
     std::vector<const Type*> Params;
-    ParamAttrsVector Attrs;
-    if ($5 != ParamAttr::None) {
-      ParamAttrsWithIndex X; X.index = 0; X.attrs = $5;
-      Attrs.push_back(X);
-    }
     TypeWithAttrsList::iterator I = $3->begin(), E = $3->end();
-    unsigned index = 1;
-    for ( ; I != E; ++I, ++index) {
+    for ( ; I != E; ++I ) {
       const Type* Ty = I->Ty->get();
       Params.push_back(Ty);
-      if (Ty != Type::VoidTy)
-        if (I->Attrs != ParamAttr::None) {
-          ParamAttrsWithIndex X; X.index = index; X.attrs = I->Attrs;
-          Attrs.push_back(X);
-        }
     }
+
     bool isVarArg = Params.size() && Params.back() == Type::VoidTy;
     if (isVarArg) Params.pop_back();
 
-    ParamAttrsList *ActualAttrs = 0;
-    if (!Attrs.empty())
-      ActualAttrs = ParamAttrsList::get(Attrs);
+    for (unsigned i = 0; i != Params.size(); ++i)
+      if (!(Params[i]->isFirstClassType() || isa<OpaqueType>(Params[i])))
+        GEN_ERROR("Function arguments must be value types!");
+
+    CHECK_FOR_ERROR
 
-    FunctionType *FT = FunctionType::get($1, Params, isVarArg, ActualAttrs);
+    FunctionType *FT = FunctionType::get($1, Params, isVarArg);
     delete $3;      // Delete the argument list
     $$ = new PATypeHolder(HandleUpRefs(FT)); 
     CHECK_FOR_ERROR
@@ -1434,9 +1440,11 @@ Types
   ;
 
 ArgType 
-  : Types OptParamAttrs { 
+  : Types OptParamAttrs {
+    // Allow but ignore attributes on function types; this permits auto-upgrade.
+    // FIXME: remove in LLVM 3.0.
     $$.Ty = $1; 
-    $$.Attrs = $2; 
+    $$.Attrs = ParamAttr::None;
   }
   ;
 
@@ -2061,30 +2069,31 @@ Definition
     }
     CHECK_FOR_ERROR
   }
-  | OptGlobalAssign GVVisibilityStyle ThreadLocal GlobalType ConstVal { 
+  | OptGlobalAssign GVVisibilityStyle ThreadLocal GlobalType ConstVal 
+    OptAddrSpace { 
     /* "Externally Visible" Linkage */
     if ($5 == 0) 
       GEN_ERROR("Global value initializer is not a constant");
     CurGV = ParseGlobalVariable($1, GlobalValue::ExternalLinkage,
-                                $2, $4, $5->getType(), $5, $3);
+                                $2, $4, $5->getType(), $5, $3, $6);
     CHECK_FOR_ERROR
   } GlobalVarAttributes {
     CurGV = 0;
   }
   | OptGlobalAssign GVInternalLinkage GVVisibilityStyle ThreadLocal GlobalType
-    ConstVal {
+    ConstVal OptAddrSpace {
     if ($6 == 0) 
       GEN_ERROR("Global value initializer is not a constant");
-    CurGV = ParseGlobalVariable($1, $2, $3, $5, $6->getType(), $6, $4);
+    CurGV = ParseGlobalVariable($1, $2, $3, $5, $6->getType(), $6, $4, $7);
     CHECK_FOR_ERROR
   } GlobalVarAttributes {
     CurGV = 0;
   }
   | OptGlobalAssign GVExternalLinkage GVVisibilityStyle ThreadLocal GlobalType
-    Types {
+    Types OptAddrSpace {
     if (!UpRefs.empty())
       GEN_ERROR("Invalid upreference in type: " + (*$6)->getDescription());
-    CurGV = ParseGlobalVariable($1, $2, $3, $5, *$6, 0, $4);
+    CurGV = ParseGlobalVariable($1, $2, $3, $5, *$6, 0, $4, $7);
     CHECK_FOR_ERROR
     delete $6;
   } GlobalVarAttributes {
@@ -2229,7 +2238,7 @@ ArgList : ArgListH {
   };
 
 FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')' 
-                  OptFuncAttrs OptSection OptAlign {
+                  OptFuncAttrs OptSection OptAlign OptGC {
   std::string FunctionName(*$3);
   delete $3;  // Free strdup'd memory!
   
@@ -2241,7 +2250,9 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
   std::vector<const Type*> ParamTypeList;
   ParamAttrsVector Attrs;
   if ($7 != ParamAttr::None) {
-    ParamAttrsWithIndex PAWI; PAWI.index = 0; PAWI.attrs = $7;
+    ParamAttrsWithIndex PAWI;
+    PAWI.index = 0;
+    PAWI.attrs = $7;
     Attrs.push_back(PAWI);
   }
   if ($5) {   // If there are arguments...
@@ -2253,7 +2264,9 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
       ParamTypeList.push_back(Ty);
       if (Ty != Type::VoidTy)
         if (I->Attrs != ParamAttr::None) {
-          ParamAttrsWithIndex PAWI; PAWI.index = index; PAWI.attrs = I->Attrs;
+          ParamAttrsWithIndex PAWI;
+          PAWI.index = index;
+          PAWI.attrs = I->Attrs;
           Attrs.push_back(PAWI);
         }
     }
@@ -2262,12 +2275,12 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
   bool isVarArg = ParamTypeList.size() && ParamTypeList.back() == Type::VoidTy;
   if (isVarArg) ParamTypeList.pop_back();
 
-  ParamAttrsList *PAL = 0;
+  const ParamAttrsList *PAL = 0;
   if (!Attrs.empty())
     PAL = ParamAttrsList::get(Attrs);
 
-  FunctionType *FT = FunctionType::get(*$2, ParamTypeList, isVarArg, PAL);
-  const PointerType *PFT = PointerType::get(FT);
+  FunctionType *FT = FunctionType::get(*$2, ParamTypeList, isVarArg);
+  const PointerType *PFT = PointerType::getUnqual(FT);
   delete $2;
 
   ValID ID;
@@ -2283,19 +2296,24 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
     // Move the function to the end of the list, from whereever it was 
     // previously inserted.
     Fn = cast<Function>(FWRef);
+    assert(!Fn->getParamAttrs() && "Forward reference has parameter attributes!");
     CurModule.CurrentModule->getFunctionList().remove(Fn);
     CurModule.CurrentModule->getFunctionList().push_back(Fn);
   } else if (!FunctionName.empty() &&     // Merge with an earlier prototype?
              (Fn = CurModule.CurrentModule->getFunction(FunctionName))) {
-    if (Fn->getFunctionType() != FT) {
+    if (Fn->getFunctionType() != FT ) {
       // The existing function doesn't have the same type. This is an overload
       // error.
       GEN_ERROR("Overload of function '" + FunctionName + "' not permitted.");
+    } else if (Fn->getParamAttrs() != PAL) {
+      // The existing function doesn't have the same parameter attributes.
+      // This is an overload error.
+      GEN_ERROR("Overload of function '" + FunctionName + "' not permitted.");
     } else if (!CurFun.isDeclare && !Fn->isDeclaration()) {
       // Neither the existing or the current function is a declaration and they
       // have the same name and same type. Clearly this is a redefinition.
       GEN_ERROR("Redefinition of function '" + FunctionName + "'");
-    } if (Fn->isDeclaration()) {
+    } else if (Fn->isDeclaration()) {
       // Make sure to strip off any argument names so we can't get conflicts.
       for (Function::arg_iterator AI = Fn->arg_begin(), AE = Fn->arg_end();
            AI != AE; ++AI)
@@ -2304,7 +2322,6 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
   } else  {  // Not already defined?
     Fn = new Function(FT, GlobalValue::ExternalWeakLinkage, FunctionName,
                       CurModule.CurrentModule);
-
     InsertValue(Fn, CurModule.Values);
   }
 
@@ -2318,11 +2335,16 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
     Fn->setVisibility(CurFun.Visibility);
   }
   Fn->setCallingConv($1);
+  Fn->setParamAttrs(PAL);
   Fn->setAlignment($9);
   if ($8) {
     Fn->setSection(*$8);
     delete $8;
   }
+  if ($10) {
+    Fn->setCollector($10->c_str());
+    delete $10;
+  }
 
   // Add all of the arguments we parsed to the function...
   if ($5) {                     // Is null if empty...
@@ -2597,29 +2619,15 @@ BBTerminatorInst : RET ResolvedVal {              // Return with a result...
         !(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) {
       // Pull out the types of all of the arguments...
       std::vector<const Type*> ParamTypes;
-      ParamAttrsVector Attrs;
-      if ($8 != ParamAttr::None) {
-        ParamAttrsWithIndex PAWI; PAWI.index = 0; PAWI.attrs = $8;
-        Attrs.push_back(PAWI);
-      }
       ParamList::iterator I = $6->begin(), E = $6->end();
-      unsigned index = 1;
-      for (; I != E; ++I, ++index) {
+      for (; I != E; ++I) {
         const Type *Ty = I->Val->getType();
         if (Ty == Type::VoidTy)
           GEN_ERROR("Short call syntax cannot be used with varargs");
         ParamTypes.push_back(Ty);
-        if (I->Attrs != ParamAttr::None) {
-          ParamAttrsWithIndex PAWI; PAWI.index = index; PAWI.attrs = I->Attrs;
-          Attrs.push_back(PAWI);
-        }
       }
-
-      ParamAttrsList *PAL = 0;
-      if (!Attrs.empty())
-        PAL = ParamAttrsList::get(Attrs);
-      Ty = FunctionType::get($3->get(), ParamTypes, false, PAL);
-      PFTy = PointerType::get(Ty);
+      Ty = FunctionType::get($3->get(), ParamTypes, false);
+      PFTy = PointerType::getUnqual(Ty);
     }
 
     delete $3;
@@ -2631,6 +2639,12 @@ BBTerminatorInst : RET ResolvedVal {              // Return with a result...
     BasicBlock *Except = getBBVal($14);
     CHECK_FOR_ERROR
 
+    ParamAttrsVector Attrs;
+    if ($8 != ParamAttr::None) {
+      ParamAttrsWithIndex PAWI; PAWI.index = 0; PAWI.attrs = $8;
+      Attrs.push_back(PAWI);
+    }
+
     // Check the arguments
     ValueList Args;
     if ($6->empty()) {                                   // Has no arguments?
@@ -2644,12 +2658,19 @@ BBTerminatorInst : RET ResolvedVal {              // Return with a result...
       FunctionType::param_iterator I = Ty->param_begin();
       FunctionType::param_iterator E = Ty->param_end();
       ParamList::iterator ArgI = $6->begin(), ArgE = $6->end();
+      unsigned index = 1;
 
-      for (; ArgI != ArgE && I != E; ++ArgI, ++I) {
+      for (; ArgI != ArgE && I != E; ++ArgI, ++I, ++index) {
         if (ArgI->Val->getType() != *I)
           GEN_ERROR("Parameter " + ArgI->Val->getName()+ " is not of type '" +
                          (*I)->getDescription() + "'");
         Args.push_back(ArgI->Val);
+        if (ArgI->Attrs != ParamAttr::None) {
+          ParamAttrsWithIndex PAWI;
+          PAWI.index = index;
+          PAWI.attrs = ArgI->Attrs;
+          Attrs.push_back(PAWI);
+        }
       }
 
       if (Ty->isVarArg()) {
@@ -2660,9 +2681,14 @@ BBTerminatorInst : RET ResolvedVal {              // Return with a result...
         GEN_ERROR("Invalid number of parameters detected");
     }
 
+    const ParamAttrsList *PAL = 0;
+    if (!Attrs.empty())
+      PAL = ParamAttrsList::get(Attrs);
+
     // Create the InvokeInst
     InvokeInst *II = new InvokeInst(V, Normal, Except, Args.begin(), Args.end());
     II->setCallingConv($2);
+    II->setParamAttrs(PAL);
     $$ = II;
     delete $6;
     CHECK_FOR_ERROR
@@ -2733,33 +2759,39 @@ PHIList : Types '[' ValueRef ',' ValueRef ']' {    // Used for PHI nodes
   };
 
 
-ParamList : Types ValueRef OptParamAttrs {    
+ParamList : Types OptParamAttrs ValueRef OptParamAttrs {
+    // FIXME: Remove trailing OptParamAttrs in LLVM 3.0, it was a mistake in 2.0
     if (!UpRefs.empty())
       GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription());
     // Used for call and invoke instructions
     $$ = new ParamList();
-    ParamListEntry E; E.Attrs = $3; E.Val = getVal($1->get(), $2);
+    ParamListEntry E; E.Attrs = $2 | $4; E.Val = getVal($1->get(), $3);
     $$->push_back(E);
     delete $1;
+    CHECK_FOR_ERROR
   }
-  | LABEL ValueRef OptParamAttrs {
+  | LABEL OptParamAttrs ValueRef OptParamAttrs {
+    // FIXME: Remove trailing OptParamAttrs in LLVM 3.0, it was a mistake in 2.0
     // Labels are only valid in ASMs
     $$ = new ParamList();
-    ParamListEntry E; E.Attrs = $3; E.Val = getBBVal($2);
+    ParamListEntry E; E.Attrs = $2 | $4; E.Val = getBBVal($3);
     $$->push_back(E);
+    CHECK_FOR_ERROR
   }
-  | ParamList ',' Types ValueRef OptParamAttrs {
+  | ParamList ',' Types OptParamAttrs ValueRef OptParamAttrs {
+    // FIXME: Remove trailing OptParamAttrs in LLVM 3.0, it was a mistake in 2.0
     if (!UpRefs.empty())
       GEN_ERROR("Invalid upreference in type: " + (*$3)->getDescription());
     $$ = $1;
-    ParamListEntry E; E.Attrs = $5; E.Val = getVal($3->get(), $4);
+    ParamListEntry E; E.Attrs = $4 | $6; E.Val = getVal($3->get(), $5);
     $$->push_back(E);
     delete $3;
     CHECK_FOR_ERROR
   }
-  | ParamList ',' LABEL ValueRef OptParamAttrs {
+  | ParamList ',' LABEL OptParamAttrs ValueRef OptParamAttrs {
+    // FIXME: Remove trailing OptParamAttrs in LLVM 3.0, it was a mistake in 2.0
     $$ = $1;
-    ParamListEntry E; E.Attrs = $5; E.Val = getBBVal($4);
+    ParamListEntry E; E.Attrs = $4 | $6; E.Val = getBBVal($5);
     $$->push_back(E);
     CHECK_FOR_ERROR
   }
@@ -2914,30 +2946,15 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
         !(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) {
       // Pull out the types of all of the arguments...
       std::vector<const Type*> ParamTypes;
-      ParamAttrsVector Attrs;
-      if ($8 != ParamAttr::None) {
-        ParamAttrsWithIndex PAWI; PAWI.index = 0; PAWI.attrs = $8;
-        Attrs.push_back(PAWI);
-      }
-      unsigned index = 1;
       ParamList::iterator I = $6->begin(), E = $6->end();
-      for (; I != E; ++I, ++index) {
+      for (; I != E; ++I) {
         const Type *Ty = I->Val->getType();
         if (Ty == Type::VoidTy)
           GEN_ERROR("Short call syntax cannot be used with varargs");
         ParamTypes.push_back(Ty);
-        if (I->Attrs != ParamAttr::None) {
-          ParamAttrsWithIndex PAWI; PAWI.index = index; PAWI.attrs = I->Attrs;
-          Attrs.push_back(PAWI);
-        }
       }
-
-      ParamAttrsList *PAL = 0;
-      if (!Attrs.empty())
-        PAL = ParamAttrsList::get(Attrs);
-
-      Ty = FunctionType::get($3->get(), ParamTypes, false, PAL);
-      PFTy = PointerType::get(Ty);
+      Ty = FunctionType::get($3->get(), ParamTypes, false);
+      PFTy = PointerType::getUnqual(Ty);
     }
 
     Value *V = getVal(PFTy, $4);   // Get the function we're calling...
@@ -2952,6 +2969,14 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
                   theF->getName() + "'");
     }
 
+    // Set up the ParamAttrs for the function
+    ParamAttrsVector Attrs;
+    if ($8 != ParamAttr::None) {
+      ParamAttrsWithIndex PAWI;
+      PAWI.index = 0;
+      PAWI.attrs = $8;
+      Attrs.push_back(PAWI);
+    }
     // Check the arguments 
     ValueList Args;
     if ($6->empty()) {                                   // Has no arguments?
@@ -2961,17 +2986,23 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
                        "expects arguments");
     } else {                                     // Has arguments?
       // Loop through FunctionType's arguments and ensure they are specified
-      // correctly!
-      //
+      // correctly.  Also, gather any parameter attributes.
       FunctionType::param_iterator I = Ty->param_begin();
       FunctionType::param_iterator E = Ty->param_end();
       ParamList::iterator ArgI = $6->begin(), ArgE = $6->end();
+      unsigned index = 1;
 
-      for (; ArgI != ArgE && I != E; ++ArgI, ++I) {
+      for (; ArgI != ArgE && I != E; ++ArgI, ++I, ++index) {
         if (ArgI->Val->getType() != *I)
           GEN_ERROR("Parameter " + ArgI->Val->getName()+ " is not of type '" +
                          (*I)->getDescription() + "'");
         Args.push_back(ArgI->Val);
+        if (ArgI->Attrs != ParamAttr::None) {
+          ParamAttrsWithIndex PAWI;
+          PAWI.index = index;
+          PAWI.attrs = ArgI->Attrs;
+          Attrs.push_back(PAWI);
+        }
       }
       if (Ty->isVarArg()) {
         if (I == E)
@@ -2980,10 +3011,17 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
       } else if (I != E || ArgI != ArgE)
         GEN_ERROR("Invalid number of parameters detected");
     }
+
+    // Finish off the ParamAttrs and check them
+    const ParamAttrsList *PAL = 0;
+    if (!Attrs.empty())
+      PAL = ParamAttrsList::get(Attrs);
+
     // Create the call node
     CallInst *CI = new CallInst(V, Args.begin(), Args.end());
     CI->setTailCall($1);
     CI->setCallingConv($2);
+    CI->setParamAttrs(PAL);
     $$ = CI;
     delete $6;
     delete $3;