PR8369: make __attribute((regparm(0))) work correctly. Original patch by

pageexec@freemail.hu, tweaks by me.

llvm-svn: 129206
This commit is contained in:
Eli Friedman 2011-04-09 08:18:08 +00:00
parent 66a7b04767
commit c5b20b5283
11 changed files with 44 additions and 22 deletions

View 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(); }

View 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());

View 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());

View 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);

View 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) {

View 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();

View 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);
}

View 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);

View 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)

View 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());

View 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)