[cfe-commits] [PATCH] Encoding calling conventions in FunctionTypes

Charles Davis cdavis at mymail.mines.edu
Mon Dec 21 19:01:48 PST 2009


Douglas Gregor wrote:
> On Dec 16, 2009, at 1:12 PM, Charles Davis wrote:
> 
>> Hi,
>>
>> This patch encodes calling conventions into FunctionType objects. Right
>> now, only cdecl, stdcall, and fastcall are supported. No real users yet,
>> but I went through and fixed all the users of
>> ASTContext::getFunctionType() and friends to respect the calling
>> convention.
>>
>> Next up: applying calling convention attributes to the function types.
> 
> Comments below.
How's the attached patch? (Responses to particular comments below.)
> 
>> Index: include/clang/AST/ASTContext.h
>> ===================================================================
>> --- include/clang/AST/ASTContext.h    (revision 91549)
>> +++ include/clang/AST/ASTContext.h    (working copy)
>> @@ -399,6 +399,11 @@
>>   /// BlockPointer.
>>   QualType getNoReturnType(QualType T, bool AddNoReturn = true);
>>
>> +  /// getCallConvType - Adds the specified calling convention
>> attribute to
>> +  /// the given type, which must be a FunctionType or a pointer to an
>> +  /// allowable type.
>> +  QualType getCallConvType(QualType T, unsigned CallConv);
>> +
> 
> The calling convention needs to be an enumeration (defined in Type.h)
> rather than just an "unsigned". We're only likely to support a few
> calling conventions, and adding new ones will be a non-trivial undertaking.
Done.
> 
>>   /// getComplexType - Return the uniqued reference to the type for a
>> complex
>>   /// number with the specified element type.
>>   QualType getComplexType(QualType T);
>> @@ -515,7 +520,8 @@
>>
>>   /// getFunctionNoProtoType - Return a K&R style C function type like
>> 'int()'.
>>   ///
>> -  QualType getFunctionNoProtoType(QualType ResultTy, bool NoReturn =
>> false);
>> +  QualType getFunctionNoProtoType(QualType ResultTy, bool NoReturn =
>> false,
>> +                                  unsigned CallConv = 0);
>>
>>   /// getFunctionType - Return a normal function type with a typed
>> argument
>>   /// list.  isVariadic indicates whether the argument list includes
>> '...'.
>> @@ -524,7 +530,7 @@
>>                            unsigned TypeQuals, bool hasExceptionSpec =
>> false,
>>                            bool hasAnyExceptionSpec = false,
>>                            unsigned NumExs = 0, const QualType
>> *ExArray = 0,
>> -                           bool NoReturn = false);
>> +                           bool NoReturn = false, unsigned CallConv =
>> 0);
>>
>>   /// getTypeDeclType - Return the unique reference to the type for
>>   /// the specified type declaration.
>> Index: include/clang/AST/Type.h
>> ===================================================================
>> --- include/clang/AST/Type.h    (revision 91549)
>> +++ include/clang/AST/Type.h    (working copy)
>> @@ -1708,21 +1708,26 @@
>>   /// NoReturn - Indicates if the function type is attribute noreturn.
>>   unsigned NoReturn : 1;
>>
>> +  /// CallConv - The calling convention used by the function. Is 0
>> +  /// for default, 1 for C, 2 for stdcall, and 3 for fastcall.
>> +  unsigned CallConv : 2;
>> +
>>   // The type returned by the function.
>>   QualType ResultType;
>> protected:
>>   FunctionType(TypeClass tc, QualType res, bool SubclassInfo,
>>                unsigned typeQuals, QualType Canonical, bool Dependent,
>> -               bool noReturn = false)
>> +               bool noReturn = false, unsigned callConv = 0)
>>     : Type(tc, Canonical, Dependent),
>>       SubClassData(SubclassInfo), TypeQuals(typeQuals),
>> NoReturn(noReturn),
>> -      ResultType(res) {}
>> +      CallConv(callConv), ResultType(res) {}
>>   bool getSubClassData() const { return SubClassData; }
>>   unsigned getTypeQuals() const { return TypeQuals; }
>> public:
>>
>>   QualType getResultType() const { return ResultType; }
>>   bool getNoReturnAttr() const { return NoReturn; }
>> +  unsigned getCallConv() const { return CallConv; }
> 
> Any change to one of the ASTs requires a (de-)serialization code for
> Clang's precompiled headers. PCHWriter.cpp and PCHReader.cpp will need
> to be updated to include the calling convention.
Are you sure? I looked at PCHWriter.cpp, and I didn't see any special
handling for the noreturn attribute, even when it's stored as part of
the type. It looks like PCHWriter just stores the noreturn attribute
itself into the PCH.
> 
> Also, when you get to applying calling convention attributes to function
> types, please make sure to update the type printer as well.
Will do.
> 
>>   static bool classof(const Type *T) {
>>     return T->getTypeClass() == FunctionNoProto ||
>> @@ -1735,9 +1740,9 @@
>> /// no information available about its arguments.
>> class FunctionNoProtoType : public FunctionType, public
>> llvm::FoldingSetNode {
>>   FunctionNoProtoType(QualType Result, QualType Canonical,
>> -                      bool NoReturn = false)
>> +                      bool NoReturn = false, unsigned CallConv = 0)
>>     : FunctionType(FunctionNoProto, Result, false, 0, Canonical,
>> -                   /*Dependent=*/false, NoReturn) {}
>> +                   /*Dependent=*/false, NoReturn, CallConv) {}
>>   friend class ASTContext;  // ASTContext creates these.
>> public:
>>   // No additional state past what FunctionType provides.
>> @@ -1779,10 +1784,12 @@
>>   FunctionProtoType(QualType Result, const QualType *ArgArray,
>> unsigned numArgs,
>>                     bool isVariadic, unsigned typeQuals, bool hasExs,
>>                     bool hasAnyExs, const QualType *ExArray,
>> -                    unsigned numExs, QualType Canonical, bool NoReturn)
>> +                    unsigned numExs, QualType Canonical, bool NoReturn,
>> +                    unsigned CallConv = 0)
>>     : FunctionType(FunctionProto, Result, isVariadic, typeQuals,
>> Canonical,
>>                    (Result->isDependentType() ||
>> -                    hasAnyDependentType(ArgArray, numArgs)), NoReturn),
>> +                    hasAnyDependentType(ArgArray, numArgs)), NoReturn,
>> +                   CallConv),
>>       NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs),
>>       AnyExceptionSpec(hasAnyExs) {
>>     // Fill in the trailing argument array.
>> Index: lib/Sema/SemaTemplateInstantiateDecl.cpp
>> ===================================================================
>> --- lib/Sema/SemaTemplateInstantiateDecl.cpp    (revision 91549)
>> +++ lib/Sema/SemaTemplateInstantiateDecl.cpp    (working copy)
>> @@ -1523,7 +1523,8 @@
>>                                                 
>> Proto->hasAnyExceptionSpec(),
>>                                                  Exceptions.size(),
>>                                                  Exceptions.data(),
>> -                                                
>> Proto->getNoReturnAttr()));
>> +                                                
>> Proto->getNoReturnAttr(),
>> +                                                 Proto->getCallConv()));
>>   }
>>
>>   return false;
>> Index: lib/AST/ASTContext.cpp
>> ===================================================================
>> --- lib/AST/ASTContext.cpp    (revision 91549)
>> +++ lib/AST/ASTContext.cpp    (working copy)
>> @@ -1222,7 +1222,8 @@
>>       return T;
>>
>>     if (const FunctionNoProtoType *FNPT =
>> dyn_cast<FunctionNoProtoType>(F)) {
>> -      ResultType = getFunctionNoProtoType(FNPT->getResultType(),
>> AddNoReturn);
>> +      ResultType = getFunctionNoProtoType(FNPT->getResultType(),
>> AddNoReturn,
>> +                                          FNPT->getCallConv());
>>     } else {
>>       const FunctionProtoType *FPT = cast<FunctionProtoType>(F);
>>       ResultType
>> @@ -1231,7 +1232,7 @@
>>                           FPT->getTypeQuals(),
>>                           FPT->hasExceptionSpec(),
>> FPT->hasAnyExceptionSpec(),
>>                           FPT->getNumExceptions(),
>> FPT->exception_begin(),
>> -                          AddNoReturn);
>> +                          AddNoReturn, FPT->getCallConv());
>>     }
>>   } else
>>     return T;
>> @@ -1239,6 +1240,38 @@
>>   return getQualifiedType(ResultType, T.getLocalQualifiers());
>> }
>>
>> +QualType ASTContext::getCallConvType(QualType T, unsigned CallConv) {
>> +  QualType ResultType;
>> +  if (const PointerType *Pointer = T->getAs<PointerType>()) {
>> +    QualType Pointee = Pointer->getPointeeType();
>> +    ResultType = getCallConvType(Pointee, CallConv);
>> +    if (ResultType == Pointee)
>> +      return T;
>> +
>> +    ResultType = getPointerType(ResultType);
>> +  } else if (const FunctionType *F = T->getAs<FunctionType>()) {
>> +    if (F->getCallConv() == CallConv)
>> +      return T;
>> +
>> +    if (const FunctionNoProtoType *FNPT =
>> dyn_cast<FunctionNoProtoType>(F)) {
>> +      ResultType = getFunctionNoProtoType(FNPT->getResultType(),
>> +                                          FNPT->getNoReturn(),
>> CallConv);
>> +    } else {
>> +      const FunctionProtoType *FPT = cast<FunctionProtoType>(F);
>> +      ResultType
>> +        = getFunctionType(FPT->getResultType(), FPT->arg_type_begin(),
>> +                          FPT->getNumArgs(), FPT->isVariadic(),
>> +                          FPT->getTypeQuals(),
>> +                          FPT->hasExceptionSpec(),
>> FPT->hasAnyExceptionSpec(),
>> +                          FPT->getNumExceptions(),
>> FPT->exception_begin(),
>> +                          FPT->getNoReturn(), CallConv);
>> +    }
>> +  } else
>> +    return T;
>> +
>> +  return getQualifiedType(ResultType, T.getLocalQualifiers());
>> +}
> 
> It's really unfortunate that this code is nearly a copy of
> getNoReturnType. Is there a way to consolidate the two?
Took me a while, but I found one. The problem was that, when I called
the common function from getNoReturnType() (or its brother
getCallConvType()), I needed a default value for the attribute I wasn't
setting. The obvious place to get it from would be from the type itself,
but then there's the case where the get*Type() methods get called on
something that isn't a function type. So I added a method to QualType
that does the check and grabs the calling convention from the FunctionType.
> 
>> /// getComplexType - Return the uniqued reference to the type for a
>> complex
>> /// number with the specified element type.
>> QualType ASTContext::getComplexType(QualType T) {
>> @@ -1690,7 +1723,8 @@
>>
>> /// getFunctionNoProtoType - Return a K&R style C function type like
>> 'int()'.
>> ///
>> -QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool
>> NoReturn) {
>> +QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool
>> NoReturn,
>> +                                            unsigned CallConv) {
>>   // Unique functions, to guarantee there is only one function of a
>> particular
>>   // structure.
>>   llvm::FoldingSetNodeID ID;
>> @@ -1703,7 +1737,8 @@
>>
>>   QualType Canonical;
>>   if (!ResultTy.isCanonical()) {
>> -    Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy),
>> NoReturn);
>> +    Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy),
>> NoReturn,
>> +                                       CallConv);
>>
>>     // Get the new insert position for the node we care about.
>>     FunctionNoProtoType *NewIP =
>> @@ -1724,7 +1759,8 @@
>>                                      unsigned NumArgs, bool isVariadic,
>>                                      unsigned TypeQuals, bool
>> hasExceptionSpec,
>>                                      bool hasAnyExceptionSpec,
>> unsigned NumExs,
>> -                                     const QualType *ExArray, bool
>> NoReturn) {
>> +                                     const QualType *ExArray, bool
>> NoReturn,
>> +                                     unsigned CallConv) {
>>   // Unique functions, to guarantee there is only one function of a
>> particular
>>   // structure.
>>   llvm::FoldingSetNodeID ID;
>> @@ -1755,7 +1791,7 @@
>>     Canonical = getFunctionType(getCanonicalType(ResultTy),
>>                                 CanonicalArgs.data(), NumArgs,
>>                                 isVariadic, TypeQuals, false,
>> -                                false, 0, 0, NoReturn);
>> +                                false, 0, 0, NoReturn, CallConv);
>>
>>     // Get the new insert position for the node we care about.
>>     FunctionProtoType *NewIP =
>> @@ -1772,7 +1808,7 @@
>>                                  NumExs*sizeof(QualType), TypeAlignment);
>>   new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, isVariadic,
>>                               TypeQuals, hasExceptionSpec,
>> hasAnyExceptionSpec,
>> -                              ExArray, NumExs, Canonical, NoReturn);
>> +                              ExArray, NumExs, Canonical, NoReturn,
>> CallConv);
>>   Types.push_back(FTP);
>>   FunctionProtoTypes.InsertNode(FTP, InsertPos);
>>   return QualType(FTP, 0);
>> @@ -4213,6 +4249,11 @@
>>     allLTypes = false;
>>   if (NoReturn != rbase->getNoReturnAttr())
>>     allRTypes = false;
>> +  unsigned lcc = lbase->getCallConv();
>> +  unsigned rcc = rbase->getCallConv();
>> +  // Compatible functions must have the same calling convention
>> +  if((lcc == 0 || rcc != 0) && lcc != rcc)
>> +    return QualType();
>>
>>   if (lproto && rproto) { // two C99 style function prototypes
>>     assert(!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec() &&
>> @@ -4248,7 +4289,7 @@
>>     if (allRTypes) return rhs;
>>     return getFunctionType(retType, types.begin(), types.size(),
>>                            lproto->isVariadic(), lproto->getTypeQuals(),
>> -                           NoReturn);
>> +                           NoReturn, lcc);
>>   }
>>
>>   if (lproto) allRTypes = false;
>> @@ -4275,12 +4316,12 @@
>>     if (allRTypes) return rhs;
>>     return getFunctionType(retType, proto->arg_type_begin(),
>>                            proto->getNumArgs(), proto->isVariadic(),
>> -                           proto->getTypeQuals(), NoReturn);
>> +                           proto->getTypeQuals(), NoReturn, lcc);
>>   }
>>
>>   if (allLTypes) return lhs;
>>   if (allRTypes) return rhs;
>> -  return getFunctionNoProtoType(retType, NoReturn);
>> +  return getFunctionNoProtoType(retType, NoReturn, lcc);
>> }
>>
>> QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
> 

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: callconv-in-types.patch
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20091221/d2f32683/attachment.ksh>


More information about the cfe-commits mailing list