diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 27 | ||||
-rw-r--r-- | clang/lib/AST/Type.cpp | 1 | ||||
-rw-r--r-- | clang/lib/AST/TypePrinter.cpp | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 17 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.h | 8 | ||||
-rw-r--r-- | clang/lib/Frontend/PCHReader.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Frontend/PCHWriter.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 25 |
9 files changed, 73 insertions, 26 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 00a7987a2b2..2b88a6cd9f2 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1141,17 +1141,23 @@ static QualType getExtFunctionType(ASTContext& Context, QualType T, } 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 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, 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 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, 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 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, 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); } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index b3675203d7f..4e24de19227 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -841,6 +841,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, ID.AddPointer(Exs[i].getAsOpaquePtr()); } ID.AddInteger(Info.getNoReturn()); + ID.AddInteger(Info.getRegParm()); ID.AddInteger(Info.getCC()); } diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index d1893cc6111..85e23d60baa 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -298,7 +298,9 @@ void TypePrinter::PrintFunctionProto(const FunctionProtoType *T, } if (Info.getNoReturn()) S += " __attribute__((noreturn))"; - + if (Info.getRegParm()) + S += " __attribute__((regparm (" + + llvm::utostr_32(Info.getRegParm()) + ")))"; if (T->hasExceptionSpec()) { S += " throw("; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index d861348ce84..cb1ecc1aa61 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -175,6 +175,7 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const ObjCMethodDecl *MD) { ArgTys, FunctionType::ExtInfo( /*NoReturn*/ false, + /*RegParm*/ 0, getCallingConventionForDecl(MD))); } @@ -216,16 +217,13 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy, 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 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy, 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 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy, 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 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, // 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(), diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h index 235ff9c6745..31c8aac3f24 100644 --- a/clang/lib/CodeGen/CGCall.h +++ b/clang/lib/CodeGen/CGCall.h @@ -76,12 +76,16 @@ namespace CodeGen { 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 @@ namespace CodeGen { EffectiveCallingConvention = Value; } + unsigned getRegParm() const { return RegParm; } + CanQualType getReturnType() const { return Args[0].type; } ABIArgInfo &getReturnInfo() { return Args[0].info; } @@ -116,6 +122,7 @@ namespace CodeGen { 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 @@ namespace CodeGen { 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 diff --git a/clang/lib/Frontend/PCHReader.cpp b/clang/lib/Frontend/PCHReader.cpp index ceb7a6bf57b..579f827e16b 100644 --- a/clang/lib/Frontend/PCHReader.cpp +++ b/clang/lib/Frontend/PCHReader.cpp @@ -2075,20 +2075,21 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { } 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 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { isVariadic, Quals, hasExceptionSpec, hasAnyExceptionSpec, NumExceptions, Exceptions.data(), - FunctionType::ExtInfo(NoReturn, CallConv)); + FunctionType::ExtInfo(NoReturn, RegParm, + CallConv)); } case pch::TYPE_UNRESOLVED_USING: diff --git a/clang/lib/Frontend/PCHWriter.cpp b/clang/lib/Frontend/PCHWriter.cpp index b4fbd17bd67..5086b488f6d 100644 --- a/clang/lib/Frontend/PCHWriter.cpp +++ b/clang/lib/Frontend/PCHWriter.cpp @@ -143,6 +143,7 @@ void PCHTypeWriter::VisitFunctionType(const FunctionType *T) { 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()); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 406b8201a3f..e232230db77 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7037,11 +7037,11 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, 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()); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index ce410a7605c..2c6cc7fc9d1 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1739,6 +1739,30 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) { 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 @@ void ProcessTypeAttributeList(Sema &S, QualType &Result, 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)) |