[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