[cfe-commits] r99940 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/Type.h lib/AST/ASTContext.cpp lib/AST/Type.cpp lib/AST/TypePrinter.cpp lib/CodeGen/CGCall.cpp lib/CodeGen/CGCall.h lib/Frontend/PCHReader.cpp lib/Frontend/PCHWriter.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaType.cpp test/CodeGen/regparm.c

Rafael Espindola rafael.espindola at gmail.com
Tue Mar 30 15:15:11 PDT 2010


Author: rafael
Date: Tue Mar 30 17:15:11 2010
New Revision: 99940

URL: http://llvm.org/viewvc/llvm-project?rev=99940&view=rev
Log:
Remember the regparm attribute in FunctionType::ExtInfo.
Fixes PR3782.


Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/AST/TypePrinter.cpp
    cfe/trunk/lib/CodeGen/CGCall.cpp
    cfe/trunk/lib/CodeGen/CGCall.h
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/test/CodeGen/regparm.c

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=99940&r1=99939&r2=99940&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Tue Mar 30 17:15:11 2010
@@ -447,6 +447,11 @@
   /// allowable type.
   QualType getCallConvType(QualType T, CallingConv CallConv);
 
+  /// getRegParmType - Sets the specified regparm attribute to
+  /// the given type, which must be a FunctionType or a pointer to an
+  /// allowable type.
+  QualType getRegParmType(QualType T, unsigned RegParm);
+
   /// getComplexType - Return the uniqued reference to the type for a complex
   /// number with the specified element type.
   QualType getComplexType(QualType T);

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=99940&r1=99939&r2=99940&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Tue Mar 30 17:15:11 2010
@@ -1740,6 +1740,9 @@
   /// NoReturn - Indicates if the function type is attribute noreturn.
   unsigned NoReturn : 1;
 
+  /// RegParm - How many arguments to pass inreg.
+  unsigned RegParm : 3;
+
   /// CallConv - The calling convention used by the function.
   unsigned CallConv : 2;
 
@@ -1750,22 +1753,38 @@
   // This class is used for passing arround the information needed to
   // construct a call. It is not actually used for storage, just for
   // factoring together common arguments.
+  // If you add a field (say Foo), other than the obvious places (both, constructors,
+  // compile failures), what you need to update is
+  // * Operetor==
+  // * getFoo
+  // * withFoo
+  // * functionType. Add Foo, getFoo.
+  // * ASTContext::getFooType
+  // * ASTContext::mergeFunctionTypes
+  // * FunctionNoProtoType::Profile
+  // * FunctionProtoType::Profile
+  // * TypePrinter::PrintFunctionProto
+  // * PCH read and write
+  // * Codegen
+
   class ExtInfo {
    public:
     // Constructor with no defaults. Use this when you know that you
     // have all the elements (when reading a PCH file for example).
-    ExtInfo(bool noReturn, CallingConv cc) :
-        NoReturn(noReturn), CC(cc) {}
+    ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) :
+        NoReturn(noReturn), RegParm(regParm), CC(cc) {}
 
     // Constructor with all defaults. Use when for example creating a
     // function know to use defaults.
-    ExtInfo() : NoReturn(false), CC(CC_Default) {}
+    ExtInfo() : NoReturn(false), RegParm(0), CC(CC_Default) {}
 
     bool getNoReturn() const { return NoReturn; }
+    unsigned getRegParm() const { return RegParm; }
     CallingConv getCC() const { return CC; }
 
     bool operator==(const ExtInfo &Other) const {
       return getNoReturn() == Other.getNoReturn() &&
+          getRegParm() == Other.getRegParm() &&
           getCC() == Other.getCC();
     }
     bool operator!=(const ExtInfo &Other) const {
@@ -1776,16 +1795,22 @@
     // the following with methods instead of mutating these objects.
 
     ExtInfo withNoReturn(bool noReturn) const {
-      return ExtInfo(noReturn, getCC());
+      return ExtInfo(noReturn, getRegParm(), getCC());
+    }
+
+    ExtInfo withRegParm(unsigned RegParm) const {
+      return ExtInfo(getNoReturn(), RegParm, getCC());
     }
 
     ExtInfo withCallingConv(CallingConv cc) const {
-      return ExtInfo(getNoReturn(), cc);
+      return ExtInfo(getNoReturn(), getRegParm(), cc);
     }
 
    private:
     // True if we have __attribute__((noreturn))
     bool NoReturn;
+    // The value passed to __attribute__((regparm(x)))
+    unsigned RegParm;
     // The calling convention as specified via
     // __attribute__((cdecl|stdcall||fastcall))
     CallingConv CC;
@@ -1798,16 +1823,17 @@
     : Type(tc, Canonical, Dependent),
       SubClassData(SubclassInfo), TypeQuals(typeQuals),
       NoReturn(Info.getNoReturn()),
-      CallConv(Info.getCC()), ResultType(res) {}
+      RegParm(Info.getRegParm()), CallConv(Info.getCC()), ResultType(res) {}
   bool getSubClassData() const { return SubClassData; }
   unsigned getTypeQuals() const { return TypeQuals; }
 public:
 
   QualType getResultType() const { return ResultType; }
+  unsigned getRegParmType() const { return RegParm; }
   bool getNoReturnAttr() const { return NoReturn; }
   CallingConv getCallConv() const { return (CallingConv)CallConv; }
   ExtInfo getExtInfo() const {
-    return ExtInfo(NoReturn, (CallingConv)CallConv);
+    return ExtInfo(NoReturn, RegParm, (CallingConv)CallConv);
   }
 
   static llvm::StringRef getNameForCallConv(CallingConv CC);
@@ -1839,6 +1865,7 @@
   static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType,
                       const ExtInfo &Info) {
     ID.AddInteger(Info.getCC());
+    ID.AddInteger(Info.getRegParm());
     ID.AddInteger(Info.getNoReturn());
     ID.AddPointer(ResultType.getAsOpaquePtr());
   }

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=99940&r1=99939&r2=99940&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Mar 30 17:15:11 2010
@@ -1141,17 +1141,23 @@
 }
 
 QualType ASTContext::getNoReturnType(QualType T, bool AddNoReturn) {
-  FunctionType::ExtInfo Info = getFunctionExtInfo(*T);
+  FunctionType::ExtInfo Info = getFunctionExtInfo(T);
   return getExtFunctionType(*this, T,
                                  Info.withNoReturn(AddNoReturn));
 }
 
 QualType ASTContext::getCallConvType(QualType T, CallingConv CallConv) {
-  FunctionType::ExtInfo Info = getFunctionExtInfo(*T);
+  FunctionType::ExtInfo Info = getFunctionExtInfo(T);
   return getExtFunctionType(*this, T,
                             Info.withCallingConv(CallConv));
 }
 
+QualType ASTContext::getRegParmType(QualType T, unsigned RegParm) {
+  FunctionType::ExtInfo Info = getFunctionExtInfo(T);
+  return getExtFunctionType(*this, T,
+                                 Info.withRegParm(RegParm));
+}
+
 /// getComplexType - Return the uniqued reference to the type for a complex
 /// number with the specified element type.
 QualType ASTContext::getComplexType(QualType T) {
@@ -4308,12 +4314,19 @@
   if (getCanonicalType(retType) != getCanonicalType(rbase->getResultType()))
     allRTypes = false;
   // FIXME: double check this
+  // FIXME: should we error if lbase->getRegParmAttr() != 0 &&
+  //                           rbase->getRegParmAttr() != 0 &&
+  //                           lbase->getRegParmAttr() != rbase->getRegParmAttr()?
   FunctionType::ExtInfo lbaseInfo = lbase->getExtInfo();
   FunctionType::ExtInfo rbaseInfo = rbase->getExtInfo();
+  unsigned RegParm = lbaseInfo.getRegParm() == 0 ? rbaseInfo.getRegParm() :
+      lbaseInfo.getRegParm();
   bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn();
-  if (NoReturn != lbaseInfo.getNoReturn())
+  if (NoReturn != lbaseInfo.getNoReturn() ||
+      RegParm != lbaseInfo.getRegParm())
     allLTypes = false;
-  if (NoReturn != rbaseInfo.getNoReturn())
+  if (NoReturn != rbaseInfo.getNoReturn() ||
+      RegParm != rbaseInfo.getRegParm())
     allRTypes = false;
   CallingConv lcc = lbaseInfo.getCC();
   CallingConv rcc = rbaseInfo.getCC();
@@ -4356,7 +4369,7 @@
     return getFunctionType(retType, types.begin(), types.size(),
                            lproto->isVariadic(), lproto->getTypeQuals(),
                            false, false, 0, 0,
-                           FunctionType::ExtInfo(NoReturn, lcc));
+                           FunctionType::ExtInfo(NoReturn, RegParm, lcc));
   }
 
   if (lproto) allRTypes = false;
@@ -4391,12 +4404,12 @@
                            proto->getNumArgs(), proto->isVariadic(),
                            proto->getTypeQuals(),
                            false, false, 0, 0,
-                           FunctionType::ExtInfo(NoReturn, lcc));
+                           FunctionType::ExtInfo(NoReturn, RegParm, lcc));
   }
 
   if (allLTypes) return lhs;
   if (allRTypes) return rhs;
-  FunctionType::ExtInfo Info(NoReturn, lcc);
+  FunctionType::ExtInfo Info(NoReturn, RegParm, lcc);
   return getFunctionNoProtoType(retType, Info);
 }
 

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=99940&r1=99939&r2=99940&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Tue Mar 30 17:15:11 2010
@@ -841,6 +841,7 @@
       ID.AddPointer(Exs[i].getAsOpaquePtr());
   }
   ID.AddInteger(Info.getNoReturn());
+  ID.AddInteger(Info.getRegParm());
   ID.AddInteger(Info.getCC());
 }
 

Modified: cfe/trunk/lib/AST/TypePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=99940&r1=99939&r2=99940&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypePrinter.cpp (original)
+++ cfe/trunk/lib/AST/TypePrinter.cpp Tue Mar 30 17:15:11 2010
@@ -298,7 +298,9 @@
   }
   if (Info.getNoReturn())
     S += " __attribute__((noreturn))";
-
+  if (Info.getRegParm())
+    S += " __attribute__((regparm (" +
+        llvm::utostr_32(Info.getRegParm()) + ")))";
   
   if (T->hasExceptionSpec()) {
     S += " throw(";

Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=99940&r1=99939&r2=99940&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Tue Mar 30 17:15:11 2010
@@ -175,6 +175,7 @@
                          ArgTys,
                          FunctionType::ExtInfo(
                              /*NoReturn*/ false,
+                             /*RegParm*/ 0,
                              getCallingConventionForDecl(MD)));
 }
 
@@ -216,16 +217,13 @@
 const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy,
                            const llvm::SmallVectorImpl<CanQualType> &ArgTys,
                                             const FunctionType::ExtInfo &Info) {
-  const CallingConv CallConv = Info.getCC();
-  const bool NoReturn = Info.getNoReturn();
-
 #ifndef NDEBUG
   for (llvm::SmallVectorImpl<CanQualType>::const_iterator
          I = ArgTys.begin(), E = ArgTys.end(); I != E; ++I)
     assert(I->isCanonicalAsParam());
 #endif
 
-  unsigned CC = ClangCallConvToLLVMCallConv(CallConv);
+  unsigned CC = ClangCallConvToLLVMCallConv(Info.getCC());
 
   // Lookup or create unique function info.
   llvm::FoldingSetNodeID ID;
@@ -238,7 +236,7 @@
     return *FI;
 
   // Construct the function info.
-  FI = new CGFunctionInfo(CC, NoReturn, ResTy, ArgTys);
+  FI = new CGFunctionInfo(CC, Info.getNoReturn(), Info.getRegParm(), ResTy, ArgTys);
   FunctionInfos.InsertNode(FI, InsertPos);
 
   // Compute ABI information.
@@ -249,11 +247,12 @@
 
 CGFunctionInfo::CGFunctionInfo(unsigned _CallingConvention,
                                bool _NoReturn,
+                               unsigned _RegParm,
                                CanQualType ResTy,
                                const llvm::SmallVectorImpl<CanQualType> &ArgTys)
   : CallingConvention(_CallingConvention),
     EffectiveCallingConvention(_CallingConvention),
-    NoReturn(_NoReturn)
+    NoReturn(_NoReturn), RegParm(_RegParm)
 {
   NumArgs = ArgTys.size();
   Args = new ArgInfo[1 + NumArgs];
@@ -609,11 +608,7 @@
   // FIXME: we need to honour command line settings also...
   // FIXME: RegParm should be reduced in case of nested functions and/or global
   // register variable.
-  signed RegParm = 0;
-  if (TargetDecl)
-    if (const RegparmAttr *RegParmAttr
-          = TargetDecl->getAttr<RegparmAttr>())
-      RegParm = RegParmAttr->getNumParams();
+  signed RegParm = FI.getRegParm();
 
   unsigned PointerWidth = getContext().Target.getPointerWidth(0);
   for (CGFunctionInfo::const_arg_iterator it = FI.arg_begin(),

Modified: cfe/trunk/lib/CodeGen/CGCall.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.h?rev=99940&r1=99939&r2=99940&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.h (original)
+++ cfe/trunk/lib/CodeGen/CGCall.h Tue Mar 30 17:15:11 2010
@@ -76,12 +76,16 @@
     unsigned NumArgs;
     ArgInfo *Args;
 
+    /// How many arguments to pass inreg.
+    unsigned RegParm;
+
   public:
     typedef const ArgInfo *const_arg_iterator;
     typedef ArgInfo *arg_iterator;
 
     CGFunctionInfo(unsigned CallingConvention,
                    bool NoReturn,
+                   unsigned RegParm,
                    CanQualType ResTy,
                    const llvm::SmallVectorImpl<CanQualType> &ArgTys);
     ~CGFunctionInfo() { delete[] Args; }
@@ -108,6 +112,8 @@
       EffectiveCallingConvention = Value;
     }
 
+    unsigned getRegParm() const { return RegParm; }
+
     CanQualType getReturnType() const { return Args[0].type; }
 
     ABIArgInfo &getReturnInfo() { return Args[0].info; }
@@ -116,6 +122,7 @@
     void Profile(llvm::FoldingSetNodeID &ID) {
       ID.AddInteger(getCallingConvention());
       ID.AddBoolean(NoReturn);
+      ID.AddInteger(RegParm);
       getReturnType().Profile(ID);
       for (arg_iterator it = arg_begin(), ie = arg_end(); it != ie; ++it)
         it->type.Profile(ID);
@@ -128,6 +135,7 @@
                         Iterator end) {
       ID.AddInteger(Info.getCC());
       ID.AddBoolean(Info.getNoReturn());
+      ID.AddInteger(Info.getRegParm());
       ResTy.Profile(ID);
       for (; begin != end; ++begin) {
         CanQualType T = *begin; // force iterator to be over canonical types

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=99940&r1=99939&r2=99940&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Tue Mar 30 17:15:11 2010
@@ -2075,20 +2075,21 @@
   }
 
   case pch::TYPE_FUNCTION_NO_PROTO: {
-    if (Record.size() != 3) {
+    if (Record.size() != 4) {
       Error("incorrect encoding of no-proto function type");
       return QualType();
     }
     QualType ResultType = GetType(Record[0]);
-    FunctionType::ExtInfo Info(Record[1], (CallingConv)Record[2]);
+    FunctionType::ExtInfo Info(Record[1], Record[2], (CallingConv)Record[3]);
     return Context->getFunctionNoProtoType(ResultType, Info);
   }
 
   case pch::TYPE_FUNCTION_PROTO: {
     QualType ResultType = GetType(Record[0]);
     bool NoReturn = Record[1];
-    CallingConv CallConv = (CallingConv)Record[2];
-    unsigned Idx = 3;
+    unsigned RegParm = Record[2];
+    CallingConv CallConv = (CallingConv)Record[3];
+    unsigned Idx = 4;
     unsigned NumParams = Record[Idx++];
     llvm::SmallVector<QualType, 16> ParamTypes;
     for (unsigned I = 0; I != NumParams; ++I)
@@ -2105,7 +2106,8 @@
                                     isVariadic, Quals, hasExceptionSpec,
                                     hasAnyExceptionSpec, NumExceptions,
                                     Exceptions.data(),
-                                    FunctionType::ExtInfo(NoReturn, CallConv));
+                                    FunctionType::ExtInfo(NoReturn, RegParm,
+                                                          CallConv));
   }
 
   case pch::TYPE_UNRESOLVED_USING:

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=99940&r1=99939&r2=99940&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Tue Mar 30 17:15:11 2010
@@ -143,6 +143,7 @@
   Writer.AddTypeRef(T->getResultType(), Record);
   FunctionType::ExtInfo C = T->getExtInfo();
   Record.push_back(C.getNoReturn());
+  Record.push_back(C.getRegParm());
   // FIXME: need to stabilize encoding of calling convention...
   Record.push_back(C.getCC());
 }

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=99940&r1=99939&r2=99940&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Mar 30 17:15:11 2010
@@ -7037,11 +7037,11 @@
   QualType BlockTy;
   if (!BSI->hasPrototype)
     BlockTy = Context.getFunctionType(RetTy, 0, 0, false, 0, false, false, 0, 0,
-                                  FunctionType::ExtInfo(NoReturn, CC_Default));
+                                FunctionType::ExtInfo(NoReturn, 0, CC_Default));
   else
     BlockTy = Context.getFunctionType(RetTy, ArgTypes.data(), ArgTypes.size(),
                                       BSI->isVariadic, 0, false, false, 0, 0,
-                                   FunctionType::ExtInfo(NoReturn, CC_Default));
+                                FunctionType::ExtInfo(NoReturn, 0, CC_Default));
 
   // FIXME: Check that return/parameter types are complete/non-abstract
   DiagnoseUnusedParameters(BSI->Params.begin(), BSI->Params.end());

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=99940&r1=99939&r2=99940&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Tue Mar 30 17:15:11 2010
@@ -1739,6 +1739,30 @@
     return false;
   }
 
+  if (Attr.getKind() == AttributeList::AT_regparm) {
+    // The warning is emitted elsewhere
+    if (Attr.getNumArgs() != 1) {
+      return false;
+    }
+
+    // Delay if this is not a function or pointer to block.
+    if (!Type->isFunctionPointerType()
+        && !Type->isBlockPointerType()
+        && !Type->isFunctionType())
+      return true;
+
+    // Otherwise we can process right away.
+    Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0));
+    llvm::APSInt NumParams(32);
+
+    // The warning is emitted elsewhere
+    if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context))
+      return false;
+
+    Type = S.Context.getRegParmType(Type, NumParams.getZExtValue());
+    return false;
+  }
+
   // Otherwise, a calling convention.
   if (Attr.getNumArgs() != 0) {
     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
@@ -1868,6 +1892,7 @@
     case AttributeList::AT_cdecl:
     case AttributeList::AT_fastcall:
     case AttributeList::AT_stdcall:
+    case AttributeList::AT_regparm:
       // Don't process these on the DeclSpec.
       if (IsDeclSpec ||
           ProcessFnAttr(S, Result, *AL))

Modified: cfe/trunk/test/CodeGen/regparm.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/regparm.c?rev=99940&r1=99939&r2=99940&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/regparm.c (original)
+++ cfe/trunk/test/CodeGen/regparm.c Tue Mar 30 17:15:11 2010
@@ -8,12 +8,16 @@
   int ccc[200];
 } foo;
 
+typedef void (*FType)(int, int)      __attribute ((regparm (3), stdcall));
+FType bar;
+
 static void FASTCALL
-reduced(char b, double c, foo* d, double e, int f) {
-}
+reduced(char b, double c, foo* d, double e, int f);
 
 int
 main(void) {
   // CHECK: call void @reduced(i8 signext inreg 0, {{.*}} %struct.anon* inreg null
   reduced(0, 0.0, 0, 0.0, 0);
+  // CHECK: call x86_stdcallcc void %tmp(i32 inreg 1, i32 inreg 2)
+  bar(1,2);
 }





More information about the cfe-commits mailing list