forked from OSchip/llvm-project
PR8369: make __attribute((regparm(0))) work correctly. Original patch by
pageexec@freemail.hu, tweaks by me. llvm-svn: 129206
This commit is contained in:
parent
66a7b04767
commit
c5b20b5283
|
@ -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(); }
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue