Change the syntax for parameter attributes:
authorReid Spencer <rspencer@reidspencer.com>
Fri, 5 Jan 2007 17:06:19 +0000 (17:06 +0000)
committerReid Spencer <rspencer@reidspencer.com>
Fri, 5 Jan 2007 17:06:19 +0000 (17:06 +0000)
1. The @ sign is no longer necessary.
2. We now support "function attributes" as parameter attribute 0.
3. Instead of locating the return type attributes after the type of a
   function result, they are now located after the function header's
   closing paranthesis and before any alignment or section options.
4. The way has been prepared for a new "noreturn" function attribute but
   there is no support for recognizing it in the lexer nor doing anything
   with it if it does get set.
5. The FunctionType::getParamAttrsText method now has support for
   returning multiple attributes. This required a change in its interface.

I'm unhappy that this change leads to 6 new shift/reduce conflicts, but
in each case bison's decision to choose the shift is correct so there
shouldn't be any damage from these conflicts.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@32904 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/DerivedTypes.h
lib/AsmParser/llvmAsmParser.y
lib/VMCore/AsmWriter.cpp
lib/VMCore/Type.cpp

index 25c66a638199108de9b577feba197e6d5bd85252..f8d9a1bf9460a231e4cfd0a726e06d20ae2e80b3 100644 (file)
@@ -81,9 +81,10 @@ public:
   /// set of possible attributes.
   /// @brief Function parameter attributes enumeration.
   enum ParameterAttributes {
-    NoAttributeSet = 0, ///< No attribute value has been set on the parameter
-    ZExtAttribute  = 1, ///< The parameter should be zero extended before call
-    SExtAttribute  = 2  ///< The parameter should be sign extended before call
+    NoAttributeSet    = 0,      ///< No attribute value has been set 
+    ZExtAttribute     = 1,      ///< zero extended before/after call
+    SExtAttribute     = 1 << 1, ///< sign extended before/after call
+    NoReturnAttribute = 1 << 2  ///< mark the function as not returning
   };
   typedef std::vector<ParameterAttributes> ParamAttrsList;
 private:
@@ -142,7 +143,7 @@ public:
   }
 
   /// @brief Convert a ParameterAttribute into its assembly text
-  static const char * getParamAttrsText(ParameterAttributes Attr);
+  static std::string getParamAttrsText(ParameterAttributes Attr);
 
   // Implement the AbstractTypeUser interface.
   virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
index bc09675898c38e7aca7eb412db10a55c58ea9e90..133c534c91e46e8c12f3dcd5f78f068788cacdce 100644 (file)
@@ -951,7 +951,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
 %type <ValueList>     IndexList         // For GEP indices
 %type <TypeList>      TypeListI 
 %type <TypeWithAttrsList> ArgTypeList ArgTypeListI
-%type <TypeWithAttrs> ArgType ResultType
+%type <TypeWithAttrs> ArgType
 %type <JumpTable>     JumpTable
 %type <BoolVal>       GlobalType                  // GLOBAL or CONSTANT?
 %type <BoolVal>       OptVolatile                 // 'volatile' or not
@@ -978,7 +978,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
 %token  <FPVal>     FPVAL     // Float or Double constant
 
 // Built in types...
-%type  <TypeVal> Types
+%type  <TypeVal> Types ResultTypes
 %type  <PrimType> IntType FPType PrimType           // Classifications
 %token <PrimType> VOID BOOL INT8 INT16 INT32 INT64
 %token <PrimType> FLOAT DOUBLE LABEL
@@ -999,7 +999,8 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
 %token X86_STDCALLCC_TOK X86_FASTCALLCC_TOK
 %token DATALAYOUT
 %type <UIntVal> OptCallingConv
-%type <ParamAttrs> OptParamAttrs ParamAttrList ParamAttr
+%type <ParamAttrs> OptParamAttrs ParamAttr 
+%type <ParamAttrs> OptFuncAttrs  FuncAttr
 
 // Basic Block Terminating Operators
 %token <TermOpVal> RET BR SWITCH INVOKE UNWIND UNREACHABLE
@@ -1026,6 +1027,8 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
 %token <OtherOpVal> PHI_TOK SELECT SHL LSHR ASHR VAARG
 %token <OtherOpVal> EXTRACTELEMENT INSERTELEMENT SHUFFLEVECTOR
 
+// Function Attributes
+%token NORETURN
 
 %start Module
 %%
@@ -1129,15 +1132,20 @@ ParamAttr     : ZEXT { $$ = FunctionType::ZExtAttribute; }
               | SEXT { $$ = FunctionType::SExtAttribute; }
               ;
 
-ParamAttrList : ParamAttr    { $$ = $1; }
-              | ParamAttrList ',' ParamAttr {
-                $$ = FunctionType::ParameterAttributes($1 | $3);
+OptParamAttrs : /* empty */  { $$ = FunctionType::NoAttributeSet; }
+              | OptParamAttrs ParamAttr {
+                $$ = FunctionType::ParameterAttributes($1 | $2);
               }
               ;
 
-OptParamAttrs : /* empty */  { $$ = FunctionType::NoAttributeSet; }
-              | '@' ParamAttr { $$ = $2; }
-              | '@' '(' ParamAttrList ')' { $$ = $3; }
+FuncAttr      : NORETURN { $$ = FunctionType::NoReturnAttribute; }
+              | ParamAttr
+              ;
+
+OptFuncAttrs  : /* empty */ { $$ = FunctionType::NoAttributeSet; }
+              | OptFuncAttrs FuncAttr {
+                $$ = FunctionType::ParameterAttributes($1 | $2);
+              }
               ;
 
 // OptAlign/OptCAlign - An optional alignment, and an optional alignment with
@@ -1223,11 +1231,11 @@ Types
     UR_OUT("New Upreference!\n");
     CHECK_FOR_ERROR
   }
-  | Types OptParamAttrs '(' ArgTypeListI ')' {
+  | Types '(' ArgTypeListI ')' OptFuncAttrs {
     std::vector<const Type*> Params;
     std::vector<FunctionType::ParameterAttributes> Attrs;
-    Attrs.push_back($2);
-    for (TypeWithAttrsList::iterator I=$4->begin(), E=$4->end(); I != E; ++I) {
+    Attrs.push_back($5);
+    for (TypeWithAttrsList::iterator I=$3->begin(), E=$3->end(); I != E; ++I) {
       Params.push_back(I->Ty->get());
       if (I->Ty->get() != Type::VoidTy)
         Attrs.push_back(I->Attrs);
@@ -1236,16 +1244,16 @@ Types
     if (isVarArg) Params.pop_back();
 
     FunctionType *FT = FunctionType::get(*$1, Params, isVarArg, Attrs);
-    delete $4;      // Delete the argument list
+    delete $3;      // Delete the argument list
     delete $1;   // Delete the return type handle
     $$ = new PATypeHolder(HandleUpRefs(FT)); 
     CHECK_FOR_ERROR
   }
-  | VOID OptParamAttrs '(' ArgTypeListI ')' {
+  | VOID '(' ArgTypeListI ')' OptFuncAttrs {
     std::vector<const Type*> Params;
     std::vector<FunctionType::ParameterAttributes> Attrs;
-    Attrs.push_back($2);
-    for (TypeWithAttrsList::iterator I=$4->begin(), E=$4->end(); I != E; ++I) {
+    Attrs.push_back($5);
+    for (TypeWithAttrsList::iterator I=$3->begin(), E=$3->end(); I != E; ++I) {
       Params.push_back(I->Ty->get());
       if (I->Ty->get() != Type::VoidTy)
         Attrs.push_back(I->Attrs);
@@ -1254,7 +1262,7 @@ Types
     if (isVarArg) Params.pop_back();
 
     FunctionType *FT = FunctionType::get($1, Params, isVarArg, Attrs);
-    delete $4;      // Delete the argument list
+    delete $3;      // Delete the argument list
     $$ = new PATypeHolder(HandleUpRefs(FT)); 
     CHECK_FOR_ERROR
   }
@@ -1313,18 +1321,16 @@ ArgType
   }
   ;
 
-ResultType 
-  : Types OptParamAttrs { 
+ResultTypes
+  : Types {
     if (!UpRefs.empty())
       GEN_ERROR("Invalid upreference in type: " + (*$1)->getDescription());
     if (!(*$1)->isFirstClassType())
       GEN_ERROR("LLVM functions cannot return aggregate types!");
-    $$.Ty = $1;
-    $$.Attrs = $2;
+    $$ = $1;
   }
-  | VOID OptParamAttrs {
-    $$.Ty = new PATypeHolder(Type::VoidTy);
-    $$.Attrs = $2;
+  | VOID {
+    $$ = new PATypeHolder(Type::VoidTy);
   }
   ;
 
@@ -1990,20 +1996,20 @@ ArgList : ArgListH {
     CHECK_FOR_ERROR
   };
 
-FunctionHeaderH : OptCallingConv ResultType Name '(' ArgList ')' 
-                  OptSection OptAlign {
+FunctionHeaderH : OptCallingConv ResultTypes Name '(' ArgList ')' 
+                  OptFuncAttrs OptSection OptAlign {
   UnEscapeLexed($3);
   std::string FunctionName($3);
   free($3);  // Free strdup'd memory!
   
   // Check the function result for abstractness if this is a define. We should
   // have no abstract types at this point
-  if (!CurFun.isDeclare && CurModule.TypeIsUnresolved($2.Ty))
-    GEN_ERROR("Reference to abstract result: "+ $2.Ty->get()->getDescription());
+  if (!CurFun.isDeclare && CurModule.TypeIsUnresolved($2))
+    GEN_ERROR("Reference to abstract result: "+ $2->get()->getDescription());
 
   std::vector<const Type*> ParamTypeList;
   std::vector<FunctionType::ParameterAttributes> ParamAttrs;
-  ParamAttrs.push_back($2.Attrs);
+  ParamAttrs.push_back($7);
   if ($5) {   // If there are arguments...
     for (ArgListType::iterator I = $5->begin(); I != $5->end(); ++I) {
       const Type* Ty = I->Ty->get();
@@ -2018,10 +2024,10 @@ FunctionHeaderH : OptCallingConv ResultType Name '(' ArgList ')'
   bool isVarArg = ParamTypeList.size() && ParamTypeList.back() == Type::VoidTy;
   if (isVarArg) ParamTypeList.pop_back();
 
-  FunctionType *FT = FunctionType::get(*$2.Ty, ParamTypeList, isVarArg,
+  FunctionType *FT = FunctionType::get(*$2, ParamTypeList, isVarArg,
                                        ParamAttrs);
   const PointerType *PFT = PointerType::get(FT);
-  delete $2.Ty;
+  delete $2;
 
   ValID ID;
   if (!FunctionName.empty()) {
@@ -2066,10 +2072,10 @@ FunctionHeaderH : OptCallingConv ResultType Name '(' ArgList ')'
     Fn->setLinkage(CurFun.Linkage);
   }
   Fn->setCallingConv($1);
-  Fn->setAlignment($8);
-  if ($7) {
-    Fn->setSection($7);
-    free($7);
+  Fn->setAlignment($9);
+  if ($8) {
+    Fn->setSection($8);
+    free($8);
   }
 
   // Add all of the arguments we parsed to the function...
@@ -2340,18 +2346,18 @@ BBTerminatorInst : RET ResolvedVal {              // Return with a result...
     $$ = S;
     CHECK_FOR_ERROR
   }
-  | INVOKE OptCallingConv ResultType ValueRef '(' ValueRefList ')' 
+  | INVOKE OptCallingConv ResultTypes ValueRef '(' ValueRefList ')' OptFuncAttrs
     TO LABEL ValueRef UNWIND LABEL ValueRef {
 
     // Handle the short syntax
     const PointerType *PFTy = 0;
     const FunctionType *Ty = 0;
-    if (!(PFTy = dyn_cast<PointerType>($3.Ty->get())) ||
+    if (!(PFTy = dyn_cast<PointerType>($3->get())) ||
         !(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) {
       // Pull out the types of all of the arguments...
       std::vector<const Type*> ParamTypes;
       FunctionType::ParamAttrsList ParamAttrs;
-      ParamAttrs.push_back($3.Attrs);
+      ParamAttrs.push_back($8);
       for (ValueRefList::iterator I = $6->begin(), E = $6->end(); I != E; ++I) {
         const Type *Ty = I->Val->getType();
         if (Ty == Type::VoidTy)
@@ -2360,15 +2366,15 @@ BBTerminatorInst : RET ResolvedVal {              // Return with a result...
         ParamAttrs.push_back(I->Attrs);
       }
 
-      Ty = FunctionType::get($3.Ty->get(), ParamTypes, false, ParamAttrs);
+      Ty = FunctionType::get($3->get(), ParamTypes, false, ParamAttrs);
       PFTy = PointerType::get(Ty);
     }
 
     Value *V = getVal(PFTy, $4);   // Get the function we're calling...
     CHECK_FOR_ERROR
-    BasicBlock *Normal = getBBVal($10);
+    BasicBlock *Normal = getBBVal($11);
     CHECK_FOR_ERROR
-    BasicBlock *Except = getBBVal($13);
+    BasicBlock *Except = getBBVal($14);
     CHECK_FOR_ERROR
 
     // Check the arguments
@@ -2655,17 +2661,18 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
     delete $2;  // Free the list...
     CHECK_FOR_ERROR
   }
-  | OptTailCall OptCallingConv ResultType ValueRef '(' ValueRefList ')' {
+  | OptTailCall OptCallingConv ResultTypes ValueRef '(' ValueRefList ')' 
+    OptFuncAttrs {
 
     // Handle the short syntax
     const PointerType *PFTy = 0;
     const FunctionType *Ty = 0;
-    if (!(PFTy = dyn_cast<PointerType>($3.Ty->get())) ||
+    if (!(PFTy = dyn_cast<PointerType>($3->get())) ||
         !(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) {
       // Pull out the types of all of the arguments...
       std::vector<const Type*> ParamTypes;
       FunctionType::ParamAttrsList ParamAttrs;
-      ParamAttrs.push_back($3.Attrs);
+      ParamAttrs.push_back($8);
       for (ValueRefList::iterator I = $6->begin(), E = $6->end(); I != E; ++I) {
         const Type *Ty = I->Val->getType();
         if (Ty == Type::VoidTy)
@@ -2674,7 +2681,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
         ParamAttrs.push_back(I->Attrs);
       }
 
-      Ty = FunctionType::get($3.Ty->get(), ParamTypes, false, ParamAttrs);
+      Ty = FunctionType::get($3->get(), ParamTypes, false, ParamAttrs);
       PFTy = PointerType::get(Ty);
     }
 
index a46adabd1e1f674ecbd269cef5b462a8f9eb35e9..f5b24844295ae6419c07bd3eb1da4d7b6f85dfda 100644 (file)
@@ -271,10 +271,6 @@ static void calcTypeName(const Type *Ty,
   case Type::FunctionTyID: {
     const FunctionType *FTy = cast<FunctionType>(Ty);
     calcTypeName(FTy->getReturnType(), TypeStack, TypeNames, Result);
-    if (FTy->getParamAttrs(0)) {
-      Result += " ";
-      Result += FunctionType::getParamAttrsText(FTy->getParamAttrs(0));
-    }
     Result += " (";
     unsigned Idx = 1;
     for (FunctionType::param_iterator I = FTy->param_begin(),
@@ -293,6 +289,10 @@ static void calcTypeName(const Type *Ty,
       Result += "...";
     }
     Result += ")";
+    if (FTy->getParamAttrs(0)) {
+      Result += " ";
+      Result += FunctionType::getParamAttrsText(FTy->getParamAttrs(0));
+    }
     break;
   }
   case Type::StructTyID: {
@@ -698,8 +698,6 @@ private:
 std::ostream &AssemblyWriter::printTypeAtLeastOneLevel(const Type *Ty) {
   if (const FunctionType *FTy = dyn_cast<FunctionType>(Ty)) {
     printType(FTy->getReturnType());
-    if (FTy->getParamAttrs(0))
-      Out << ' ' << FunctionType::getParamAttrsText(FTy->getParamAttrs(0));
     Out << " (";
     unsigned Idx = 1;
     for (FunctionType::param_iterator I = FTy->param_begin(),
@@ -717,6 +715,8 @@ std::ostream &AssemblyWriter::printTypeAtLeastOneLevel(const Type *Ty) {
       Out << "...";
     }
     Out << ')';
+    if (FTy->getParamAttrs(0))
+      Out << ' ' << FunctionType::getParamAttrsText(FTy->getParamAttrs(0));
   } else if (const StructType *STy = dyn_cast<StructType>(Ty)) {
     if (STy->isPacked())
       Out << '<';
@@ -969,8 +969,6 @@ void AssemblyWriter::printFunction(const Function *F) {
 
   const FunctionType *FT = F->getFunctionType();
   printType(F->getReturnType()) << ' ';
-  if (FT->getParamAttrs(0))
-    Out << FunctionType::getParamAttrsText(FT->getParamAttrs(0)) << ' ';
   if (!F->getName().empty())
     Out << getLLVMName(F->getName());
   else
@@ -995,7 +993,8 @@ void AssemblyWriter::printFunction(const Function *F) {
     Out << "...";  // Output varargs portion of signature!
   }
   Out << ')';
-
+  if (FT->getParamAttrs(0))
+    Out << ' ' << FunctionType::getParamAttrsText(FT->getParamAttrs(0));
   if (F->hasSection())
     Out << " section \"" << F->getSection() << '"';
   if (F->getAlignment())
@@ -1186,8 +1185,6 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
         (!isa<PointerType>(RetTy) ||
          !isa<FunctionType>(cast<PointerType>(RetTy)->getElementType()))) {
       Out << ' '; printType(RetTy);
-      if (FTy->getParamAttrs(0) != FunctionType::NoAttributeSet)
-        Out << " " << FTy->getParamAttrsText(FTy->getParamAttrs(0));
       writeOperand(Operand, false);
     } else {
       writeOperand(Operand, true);
@@ -1201,6 +1198,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
         Out << " " << FTy->getParamAttrsText(FTy->getParamAttrs(op));
     }
     Out << " )";
+    if (FTy->getParamAttrs(0) != FunctionType::NoAttributeSet)
+      Out << ' ' << FTy->getParamAttrsText(FTy->getParamAttrs(0));
   } else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
     const PointerType  *PTy = cast<PointerType>(Operand->getType());
     const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
@@ -1225,8 +1224,6 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
         (!isa<PointerType>(RetTy) ||
          !isa<FunctionType>(cast<PointerType>(RetTy)->getElementType()))) {
       Out << ' '; printType(RetTy);
-      if (FTy->getParamAttrs(0) != FunctionType::NoAttributeSet)
-        Out << " " << FTy->getParamAttrsText(FTy->getParamAttrs(0));
       writeOperand(Operand, false);
     } else {
       writeOperand(Operand, true);
@@ -1241,7 +1238,10 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
         Out << " " << FTy->getParamAttrsText(FTy->getParamAttrs(op-2));
     }
 
-    Out << " )\n\t\t\tto";
+    Out << " )";
+    if (FTy->getParamAttrs(0) != FunctionType::NoAttributeSet)
+      Out << " " << FTy->getParamAttrsText(FTy->getParamAttrs(0));
+    Out << "\n\t\t\tto";
     writeOperand(II->getNormalDest(), true);
     Out << " unwind";
     writeOperand(II->getUnwindDest(), true);
index e328369d90c748ac9783403359cd0656f963c8e9..25da1e3a8517ec3205f4035e729324a8637ddae0 100644 (file)
@@ -245,7 +245,6 @@ static std::string getTypeDescription(const Type *Ty,
   switch (Ty->getTypeID()) {
   case Type::FunctionTyID: {
     const FunctionType *FTy = cast<FunctionType>(Ty);
-    Result = FunctionType::getParamAttrsText(FTy->getParamAttrs(0));
     if (!Result.empty())
       Result += " ";
     Result += getTypeDescription(FTy->getReturnType(), TypeStack) + " (";
@@ -254,11 +253,7 @@ static std::string getTypeDescription(const Type *Ty,
            E = FTy->param_end(); I != E; ++I) {
       if (I != FTy->param_begin())
         Result += ", ";
-      const char *PA = FunctionType::getParamAttrsText(FTy->getParamAttrs(Idx));
-      if (PA[0] != 0) {
-        Result += PA;
-        Result += " ";
-      }
+      Result +=  FunctionType::getParamAttrsText(FTy->getParamAttrs(Idx));
       Idx++;
       Result += getTypeDescription(*I, TypeStack);
     }
@@ -267,6 +262,9 @@ static std::string getTypeDescription(const Type *Ty,
       Result += "...";
     }
     Result += ")";
+    if (FTy->getParamAttrs(0)) {
+      Result += " " + FunctionType::getParamAttrsText(FTy->getParamAttrs(0));
+    }
     break;
   }
   case Type::StructTyID: {
@@ -1021,13 +1019,15 @@ FunctionType::getParamAttrs(unsigned Idx) const {
   return (*ParamAttrs)[Idx];
 }
 
-const char *FunctionType::getParamAttrsText(ParameterAttributes Attr) {
-  switch (Attr) {
-    default: assert(0 && "Invalid ParameterAttribute value");
-    case 0: return "";
-    case ZExtAttribute: return "@zext";
-    case SExtAttribute: return "@sext";
-  }
+std::string FunctionType::getParamAttrsText(ParameterAttributes Attr) {
+  std::string Result;
+  if (Attr & ZExtAttribute)
+    Result += "zext ";
+  if (Attr & SExtAttribute)
+    Result += "sext ";
+  if (Attr & NoReturnAttribute)
+    Result += "noreturn ";
+  return Result;
 }
 
 //===----------------------------------------------------------------------===//