From 98a49337be3fdf2c4bfa6cccc50fbb5d2aa7e3be Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Fri, 22 Sep 2017 00:41:05 +0000 Subject: Add support for attribute 'noescape'. The attribute informs the compiler that the annotated pointer parameter of a function cannot escape and enables IRGen to attach attribute 'nocapture' to parameters that are annotated with the attribute. That is the only optimization that currently takes advantage of 'noescape', but there are other optimizations that will be added later that improves IRGen for ObjC blocks. This recommits r313722, which was reverted in r313725 because clang couldn't build compiler-rt. It failed to build because there were function declarations that were missing 'noescape'. That has been fixed in r313929. rdar://problem/19886775 Differential Revision: https://reviews.llvm.org/D32210 llvm-svn: 313945 --- clang/lib/AST/ASTContext.cpp | 64 +++++++++++++++++++++++++++++++---------- clang/lib/AST/ItaniumMangle.cpp | 3 ++ clang/lib/AST/TypePrinter.cpp | 2 ++ 3 files changed, 54 insertions(+), 15 deletions(-) (limited to 'clang/lib/AST') diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 4d26748b077..82e74528d19 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -7968,9 +7968,17 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (lproto->getTypeQuals() != rproto->getTypeQuals()) return QualType(); - if (!doFunctionTypesMatchOnExtParameterInfos(rproto, lproto)) + SmallVector newParamInfos; + bool canUseLeft, canUseRight; + if (!mergeExtParameterInfo(lproto, rproto, canUseLeft, canUseRight, + newParamInfos)) return QualType(); + if (!canUseLeft) + allLTypes = false; + if (!canUseRight) + allRTypes = false; + // Check parameter type compatibility SmallVector types; for (unsigned i = 0, n = lproto->getNumParams(); i < n; i++) { @@ -8001,6 +8009,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, FunctionProtoType::ExtProtoInfo EPI = lproto->getExtProtoInfo(); EPI.ExtInfo = einfo; + EPI.ExtParameterInfos = + newParamInfos.empty() ? nullptr : newParamInfos.data(); return getFunctionType(retType, types, EPI); } @@ -8360,26 +8370,50 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, llvm_unreachable("Invalid Type::Class!"); } -bool ASTContext::doFunctionTypesMatchOnExtParameterInfos( - const FunctionProtoType *firstFnType, - const FunctionProtoType *secondFnType) { +bool ASTContext::mergeExtParameterInfo( + const FunctionProtoType *FirstFnType, const FunctionProtoType *SecondFnType, + bool &CanUseFirst, bool &CanUseSecond, + SmallVectorImpl &NewParamInfos) { + assert(NewParamInfos.empty() && "param info list not empty"); + CanUseFirst = CanUseSecond = true; + bool FirstHasInfo = FirstFnType->hasExtParameterInfos(); + bool SecondHasInfo = SecondFnType->hasExtParameterInfos(); + // Fast path: if the first type doesn't have ext parameter infos, - // we match if and only if they second type also doesn't have them. - if (!firstFnType->hasExtParameterInfos()) - return !secondFnType->hasExtParameterInfos(); + // we match if and only if the second type also doesn't have them. + if (!FirstHasInfo && !SecondHasInfo) + return true; - // Otherwise, we can only match if the second type has them. - if (!secondFnType->hasExtParameterInfos()) - return false; + bool NeedParamInfo = false; + size_t E = FirstHasInfo ? FirstFnType->getExtParameterInfos().size() + : SecondFnType->getExtParameterInfos().size(); - auto firstEPI = firstFnType->getExtParameterInfos(); - auto secondEPI = secondFnType->getExtParameterInfos(); - assert(firstEPI.size() == secondEPI.size()); + for (size_t I = 0; I < E; ++I) { + FunctionProtoType::ExtParameterInfo FirstParam, SecondParam; + if (FirstHasInfo) + FirstParam = FirstFnType->getExtParameterInfo(I); + if (SecondHasInfo) + SecondParam = SecondFnType->getExtParameterInfo(I); - for (size_t i = 0, n = firstEPI.size(); i != n; ++i) { - if (firstEPI[i] != secondEPI[i]) + // Cannot merge unless everything except the noescape flag matches. + if (FirstParam.withIsNoEscape(false) != SecondParam.withIsNoEscape(false)) return false; + + bool FirstNoEscape = FirstParam.isNoEscape(); + bool SecondNoEscape = SecondParam.isNoEscape(); + bool IsNoEscape = FirstNoEscape && SecondNoEscape; + NewParamInfos.push_back(FirstParam.withIsNoEscape(IsNoEscape)); + if (NewParamInfos.back().getOpaqueValue()) + NeedParamInfo = true; + if (FirstNoEscape != IsNoEscape) + CanUseFirst = false; + if (SecondNoEscape != IsNoEscape) + CanUseSecond = false; } + + if (!NeedParamInfo) + NewParamInfos.clear(); + return true; } diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index dbda7a5dbd4..a9c5ab2cc1d 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -2643,6 +2643,9 @@ CXXNameMangler::mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo PI) { if (PI.isConsumed()) mangleVendorQualifier("ns_consumed"); + + if (PI.isNoEscape()) + mangleVendorQualifier("noescape"); } // ::= diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 15c63bf4ed9..1f5b4834896 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -665,6 +665,8 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T, auto EPI = T->getExtParameterInfo(i); if (EPI.isConsumed()) OS << "__attribute__((ns_consumed)) "; + if (EPI.isNoEscape()) + OS << "__attribute__((noescape)) "; auto ABI = EPI.getABI(); if (ABI != ParameterABI::Ordinary) OS << "__attribute__((" << getParameterABISpelling(ABI) << ")) "; -- cgit v1.2.3