aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2011-04-09 08:18:08 +0000
committerEli Friedman <eli.friedman@gmail.com>2011-04-09 08:18:08 +0000
commita49218e17bcbb1acde0245773173e2c0c42f4f19 (patch)
tree737b5fa7ae7c8d440c2f71d7c8d891467b2bc14b
parentb6006696358572a668d6de773af8f550e54259bf (diff)
PR8369: make __attribute((regparm(0))) work correctly. Original patch by
pageexec@freemail.hu, tweaks by me. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129206 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Type.h16
-rw-r--r--lib/AST/ASTContext.cpp3
-rw-r--r--lib/AST/DumpXML.cpp2
-rw-r--r--lib/CodeGen/CGCall.cpp13
-rw-r--r--lib/CodeGen/CGCall.h6
-rw-r--r--lib/Sema/SemaDecl.cpp5
-rw-r--r--lib/Sema/SemaExpr.cpp2
-rw-r--r--lib/Sema/SemaType.cpp2
-rw-r--r--lib/Serialization/ASTReader.cpp11
-rw-r--r--lib/Serialization/ASTWriter.cpp1
-rw-r--r--test/CodeGen/regparm-flag.c5
11 files changed, 44 insertions, 22 deletions
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 97d3d0f35b..1b94a1d83f 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -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(); }
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 39229a7b73..420fcd398d 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -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());
diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp
index 9a34722aa5..93ae1e37c9 100644
--- a/lib/AST/DumpXML.cpp
+++ b/lib/AST/DumpXML.cpp
@@ -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());
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 7a1600f166..0ba6789367 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -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);
diff --git a/lib/CodeGen/CGCall.h b/lib/CodeGen/CGCall.h
index fed29a2cf4..f5a84ec99f 100644
--- a/lib/CodeGen/CGCall.h
+++ b/lib/CodeGen/CGCall.h
@@ -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) {
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 32fd9a1204..a2249c787b 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -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();
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index e8488f9ac4..fbf0a986d5 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -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);
}
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 0ec2986ba5..3a19f2f73a 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -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);
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 4cbb81d1ac..0e96770f57 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -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)
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 482ce4bec7..f0f5347a16 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -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());
diff --git a/test/CodeGen/regparm-flag.c b/test/CodeGen/regparm-flag.c
index f37239e473..8ecf539508 100644
--- a/test/CodeGen/regparm-flag.c
+++ b/test/CodeGen/regparm-flag.c
@@ -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)