]> granicus.if.org Git - clang/commitdiff
PR8369: make __attribute((regparm(0))) work correctly. Original patch by
authorEli Friedman <eli.friedman@gmail.com>
Sat, 9 Apr 2011 08:18:08 +0000 (08:18 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Sat, 9 Apr 2011 08:18:08 +0000 (08:18 +0000)
pageexec@freemail.hu, tweaks by me.

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

include/clang/AST/Type.h
lib/AST/ASTContext.cpp
lib/AST/DumpXML.cpp
lib/CodeGen/CGCall.cpp
lib/CodeGen/CGCall.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaType.cpp
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp
test/CodeGen/regparm-flag.c

index 97d3d0f35b610fc8d36d6df6262ef7cc207bd067..1b94a1d83fe06361c3efc12d49b63a51c1e16c88 100644 (file)
@@ -2271,12 +2271,13 @@ class FunctionType : public Type {
     // you'll need to adjust both the Bits field below and
     // Type::FunctionTypeBitfields.
 
-    //   |  CC  |noreturn|regparm
-    //   |0 .. 2|   3    |4 ..  6
+    //   |  CC  |noreturn|hasregparm|regparm
+    //   |0 .. 2|   3    |    4     |5 ..  7
     enum { CallConvMask = 0x7 };
     enum { NoReturnMask = 0x8 };
+    enum { HasRegParmMask = 0x10 };
     enum { RegParmMask = ~(CallConvMask | NoReturnMask),
-           RegParmOffset = 4 };
+           RegParmOffset = 5 };
 
     unsigned char Bits;
 
@@ -2287,9 +2288,10 @@ class FunctionType : public Type {
    public:
     // Constructor with no defaults. Use this when you know that you
     // have all the elements (when reading an AST file for example).
-    ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) {
+    ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc) {
       Bits = ((unsigned) cc) |
              (noReturn ? NoReturnMask : 0) |
+             (hasRegParm ? HasRegParmMask : 0) |
              (regParm << RegParmOffset);
     }
 
@@ -2298,6 +2300,7 @@ class FunctionType : public Type {
     ExtInfo() : Bits(0) {}
 
     bool getNoReturn() const { return Bits & NoReturnMask; }
+    bool getHasRegParm() const { return Bits & HasRegParmMask; }
     unsigned getRegParm() const { return Bits >> RegParmOffset; }
     CallingConv getCC() const { return CallingConv(Bits & CallConvMask); }
 
@@ -2319,7 +2322,7 @@ class FunctionType : public Type {
     }
 
     ExtInfo withRegParm(unsigned RegParm) const {
-      return ExtInfo((Bits & ~RegParmMask) | (RegParm << RegParmOffset));
+      return ExtInfo(HasRegParmMask | (Bits & ~RegParmMask) | (RegParm << RegParmOffset));
     }
 
     ExtInfo withCallingConv(CallingConv cc) const {
@@ -2355,7 +2358,8 @@ protected:
 public:
 
   QualType getResultType() const { return ResultType; }
-  
+
+  bool getHasRegParm() const { return getExtInfo().getHasRegParm(); }
   unsigned getRegParmType() const { return getExtInfo().getRegParm(); }
   bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); }
   CallingConv getCallConv() const { return getExtInfo().getCC(); }
index 39229a7b731e4b2bb31a493e2c83e013f68aa689..420fcd398d2d1ab9ac54b1b9cef63821c2ecf832 100644 (file)
@@ -5175,6 +5175,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
     return QualType();
 
   // Regparm is part of the calling convention.
+  if (lbaseInfo.getHasRegParm() != rbaseInfo.getHasRegParm())
+    return QualType();
   if (lbaseInfo.getRegParm() != rbaseInfo.getRegParm())
     return QualType();
 
@@ -5187,6 +5189,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
     allRTypes = false;
 
   FunctionType::ExtInfo einfo(NoReturn,
+                              lbaseInfo.getHasRegParm(),
                               lbaseInfo.getRegParm(),
                               lbaseInfo.getCC());
 
index 9a34722aa5da3d2e415a28426a9becc99dcbeca5..93ae1e37c9ced4b0a926f5ba29994cdd86886b2d 100644 (file)
@@ -955,7 +955,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
   void visitFunctionTypeAttrs(FunctionType *T) {
     setFlag("noreturn", T->getNoReturnAttr());
     setCallingConv(T->getCallConv());
-    if (T->getRegParmType()) setInteger("regparm", T->getRegParmType());
+    if (T->getHasRegParm()) setInteger("regparm", T->getRegParmType());
   }
   void visitFunctionTypeChildren(FunctionType *T) {
     dispatch(T->getResultType());
index 7a1600f166c57d4ae56b1f8e8d611efa0944a5ae..0ba6789367f49e746ccdc86998db8453e0fa644a 100644 (file)
@@ -188,6 +188,7 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const ObjCMethodDecl *MD) {
                          ArgTys,
                          FunctionType::ExtInfo(
                              /*NoReturn*/ false,
+                             /*HasRegParm*/ false,
                              /*RegParm*/ 0,
                              getCallingConventionForDecl(MD)));
 }
@@ -255,7 +256,7 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy,
     return *FI;
 
   // Construct the function info.
-  FI = new CGFunctionInfo(CC, Info.getNoReturn(), Info.getRegParm(), ResTy,
+  FI = new CGFunctionInfo(CC, Info.getNoReturn(), Info.getHasRegParm(), Info.getRegParm(), ResTy,
                           ArgTys.data(), ArgTys.size());
   FunctionInfos.InsertNode(FI, InsertPos);
 
@@ -284,13 +285,13 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy,
 }
 
 CGFunctionInfo::CGFunctionInfo(unsigned _CallingConvention,
-                               bool _NoReturn, unsigned _RegParm,
+                               bool _NoReturn, bool _HasRegParm, unsigned _RegParm,
                                CanQualType ResTy,
                                const CanQualType *ArgTys,
                                unsigned NumArgTys)
   : CallingConvention(_CallingConvention),
     EffectiveCallingConvention(_CallingConvention),
-    NoReturn(_NoReturn), RegParm(_RegParm)
+    NoReturn(_NoReturn), HasRegParm(_HasRegParm), RegParm(_RegParm)
 {
   NumArgs = NumArgTys;
 
@@ -762,8 +763,10 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
     PAL.push_back(llvm::AttributeWithIndex::get(0, RetAttrs));
 
   // FIXME: RegParm should be reduced in case of global register variable.
-  signed RegParm = FI.getRegParm();
-  if (!RegParm)
+  signed RegParm;
+  if (FI.getHasRegParm())
+    RegParm = FI.getRegParm();
+  else
     RegParm = CodeGenOpts.NumRegisterParameters;
 
   unsigned PointerWidth = getContext().Target.getPointerWidth(0);
index fed29a2cf44f8fffacfc90ae40c417a7b33a7ad8..f5a84ec99f4be56ce518710c928fba02e510190e 100644 (file)
@@ -83,6 +83,7 @@ namespace CodeGen {
     ArgInfo *Args;
 
     /// How many arguments to pass inreg.
+    bool HasRegParm;
     unsigned RegParm;
 
   public:
@@ -90,7 +91,7 @@ namespace CodeGen {
     typedef ArgInfo *arg_iterator;
 
     CGFunctionInfo(unsigned CallingConvention, bool NoReturn,
-                   unsigned RegParm, CanQualType ResTy,
+                   bool HasRegParm, unsigned RegParm, CanQualType ResTy,
                    const CanQualType *ArgTys, unsigned NumArgTys);
     ~CGFunctionInfo() { delete[] Args; }
 
@@ -116,6 +117,7 @@ namespace CodeGen {
       EffectiveCallingConvention = Value;
     }
 
+    bool getHasRegParm() const { return HasRegParm; }
     unsigned getRegParm() const { return RegParm; }
 
     CanQualType getReturnType() const { return Args[0].type; }
@@ -126,6 +128,7 @@ namespace CodeGen {
     void Profile(llvm::FoldingSetNodeID &ID) {
       ID.AddInteger(getCallingConvention());
       ID.AddBoolean(NoReturn);
+      ID.AddBoolean(HasRegParm);
       ID.AddInteger(RegParm);
       getReturnType().Profile(ID);
       for (arg_iterator it = arg_begin(), ie = arg_end(); it != ie; ++it)
@@ -139,6 +142,7 @@ namespace CodeGen {
                         Iterator end) {
       ID.AddInteger(Info.getCC());
       ID.AddBoolean(Info.getNoReturn());
+      ID.AddBoolean(Info.getHasRegParm());
       ID.AddInteger(Info.getRegParm());
       ResTy.Profile(ID);
       for (; begin != end; ++begin) {
index 32fd9a120460a720f56a307a21f28c91897d2dda..a2249c787b542d09d0c8ee45ccd8dfb7e735cec4 100644 (file)
@@ -1270,8 +1270,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
   }
 
   // Merge regparm attribute.
-  if (OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) {
-    if (NewTypeInfo.getRegParm()) {
+  if (OldTypeInfo.getHasRegParm() != NewTypeInfo.getHasRegParm() ||
+      OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) {
+    if (NewTypeInfo.getHasRegParm()) {
       Diag(New->getLocation(), diag::err_regparm_mismatch)
         << NewType->getRegParmType()
         << OldType->getRegParmType();
index e8488f9ac48c3f21ef8d1cc70fc70d90b75c0d5a..fbf0a986d5f95db73a9a9014969250ff1b5ad463 100644 (file)
@@ -9367,7 +9367,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
   // If we don't have a function type, just build one from nothing.
   } else {
     FunctionProtoType::ExtProtoInfo EPI;
-    EPI.ExtInfo = FunctionType::ExtInfo(NoReturn, 0, CC_Default);
+    EPI.ExtInfo = FunctionType::ExtInfo(NoReturn, false, 0, CC_Default);
     BlockTy = Context.getFunctionType(RetTy, 0, 0, EPI);
   }
 
index 0ec2986ba56639256683f9cabcdeafaf58d9e9b2..3a19f2f73a2b63f84c6225614f62503c5db4551d 100644 (file)
@@ -2976,7 +2976,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
     }
 
     // Also diagnose fastcall with regparm.
-    if (fn->getRegParmType()) {
+    if (fn->getHasRegParm()) {
       S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
         << "regparm"
         << FunctionType::getNameForCallConv(CC);
index 4cbb81d1ac41253670546ef661ec3e6e2ec7079c..0e96770f5789e6f1522118ddb640599d9d675e46 100644 (file)
@@ -3092,12 +3092,12 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) {
   }
 
   case TYPE_FUNCTION_NO_PROTO: {
-    if (Record.size() != 4) {
+    if (Record.size() != 5) {
       Error("incorrect encoding of no-proto function type");
       return QualType();
     }
     QualType ResultType = GetType(Record[0]);
-    FunctionType::ExtInfo Info(Record[1], Record[2], (CallingConv)Record[3]);
+    FunctionType::ExtInfo Info(Record[1], Record[2], Record[3], (CallingConv)Record[4]);
     return Context->getFunctionNoProtoType(ResultType, Info);
   }
 
@@ -3106,10 +3106,11 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) {
 
     FunctionProtoType::ExtProtoInfo EPI;
     EPI.ExtInfo = FunctionType::ExtInfo(/*noreturn*/ Record[1],
-                                        /*regparm*/ Record[2],
-                                        static_cast<CallingConv>(Record[3]));
+                                        /*hasregparm*/ Record[2],
+                                        /*regparm*/ Record[3],
+                                        static_cast<CallingConv>(Record[4]));
 
-    unsigned Idx = 4;
+    unsigned Idx = 5;
     unsigned NumParams = Record[Idx++];
     llvm::SmallVector<QualType, 16> ParamTypes;
     for (unsigned I = 0; I != NumParams; ++I)
index 482ce4bec7c763a0c3dbf1dd18c63ebad84148de..f0f5347a16d8a4094a80b6ac4c11b15230ad4e3d 100644 (file)
@@ -161,6 +161,7 @@ void ASTTypeWriter::VisitFunctionType(const FunctionType *T) {
   Writer.AddTypeRef(T->getResultType(), Record);
   FunctionType::ExtInfo C = T->getExtInfo();
   Record.push_back(C.getNoReturn());
+  Record.push_back(C.getHasRegParm());
   Record.push_back(C.getRegParm());
   // FIXME: need to stabilize encoding of calling convention...
   Record.push_back(C.getCC());
index f37239e473cd3aa742e1a2494b3149af778896b5..8ecf53950805347a3e07b219eda0ae6c5cf7d693 100644 (file)
@@ -4,12 +4,17 @@
 void f1(int a, int b, int c, int d,
         int e, int f, int g, int h);
 
+void f2(int a, int b) __attribute((regparm(0)));
+
 void f0() {
 // CHECK: call void @f1(i32 inreg 1, i32 inreg 2, i32 inreg 3, i32 inreg 4,
 // CHECK: i32 5, i32 6, i32 7, i32 8)
   f1(1, 2, 3, 4, 5, 6, 7, 8);
+// CHECK: call void @f2(i32 1, i32 2)
+  f2(1, 2);
 }
 
 // CHECK: declare void @f1(i32 inreg, i32 inreg, i32 inreg, i32 inreg,
 // CHECK: i32, i32, i32, i32)
+// CHECK: declare void @f2(i32, i32)