aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CodeGenFunction.h
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-02-16 20:13:02 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-02-16 20:13:02 +0000
commitb60736ec1405bb0a8dd40989f67ef4c93da068ab (patch)
tree5c43fbb7c9fc45f0f87e0e6795a86267dbd12f9d /clang/lib/CodeGen/CodeGenFunction.h
parentcfca06d7963fa0909f90483b42a6d7d194d01e08 (diff)
Diffstat (limited to 'clang/lib/CodeGen/CodeGenFunction.h')
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h257
1 files changed, 164 insertions, 93 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index d794f4f0fa81..8eb7adbc8fcb 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -502,6 +502,26 @@ public:
/// True if the current statement has nomerge attribute.
bool InNoMergeAttributedStmt = false;
+ /// True if the current function should be marked mustprogress.
+ bool FnIsMustProgress = false;
+
+ /// True if the C++ Standard Requires Progress.
+ bool CPlusPlusWithProgress() {
+ return getLangOpts().CPlusPlus11 || getLangOpts().CPlusPlus14 ||
+ getLangOpts().CPlusPlus17 || getLangOpts().CPlusPlus20;
+ }
+
+ /// True if the C Standard Requires Progress.
+ bool CWithProgress() {
+ return getLangOpts().C11 || getLangOpts().C17 || getLangOpts().C2x;
+ }
+
+ /// True if the language standard requires progress in functions or
+ /// in infinite loops with non-constant conditionals.
+ bool LanguageRequiresProgress() {
+ return CWithProgress() || CPlusPlusWithProgress();
+ }
+
const CodeGen::CGBlockInfo *BlockInfo = nullptr;
llvm::Value *BlockPointer = nullptr;
@@ -608,11 +628,15 @@ public:
class CGFPOptionsRAII {
public:
CGFPOptionsRAII(CodeGenFunction &CGF, FPOptions FPFeatures);
+ CGFPOptionsRAII(CodeGenFunction &CGF, const Expr *E);
~CGFPOptionsRAII();
private:
+ void ConstructorHelper(FPOptions FPFeatures);
CodeGenFunction &CGF;
FPOptions OldFPFeatures;
+ llvm::fp::ExceptionBehavior OldExcept;
+ llvm::RoundingMode OldRounding;
Optional<CGBuilderTy::FastMathFlagGuard> FMFGuard;
};
FPOptions CurFPFeatures;
@@ -672,12 +696,13 @@ public:
initFullExprCleanup();
}
- /// Queue a cleanup to be pushed after finishing the current
- /// full-expression.
+ /// Queue a cleanup to be pushed after finishing the current full-expression,
+ /// potentially with an active flag.
template <class T, class... As>
void pushCleanupAfterFullExpr(CleanupKind Kind, As... A) {
if (!isInConditionalBranch())
- return pushCleanupAfterFullExprImpl<T>(Kind, Address::invalid(), A...);
+ return pushCleanupAfterFullExprWithActiveFlag<T>(Kind, Address::invalid(),
+ A...);
Address ActiveFlag = createCleanupActiveFlag();
assert(!DominatingValue<Address>::needsSaving(ActiveFlag) &&
@@ -687,12 +712,12 @@ public:
SavedTuple Saved{saveValueInCond(A)...};
typedef EHScopeStack::ConditionalCleanup<T, As...> CleanupType;
- pushCleanupAfterFullExprImpl<CleanupType>(Kind, ActiveFlag, Saved);
+ pushCleanupAfterFullExprWithActiveFlag<CleanupType>(Kind, ActiveFlag, Saved);
}
template <class T, class... As>
- void pushCleanupAfterFullExprImpl(CleanupKind Kind, Address ActiveFlag,
- As... A) {
+ void pushCleanupAfterFullExprWithActiveFlag(CleanupKind Kind,
+ Address ActiveFlag, As... A) {
LifetimeExtendedCleanupHeader Header = {sizeof(T), Kind,
ActiveFlag.isValid()};
@@ -1394,19 +1419,31 @@ private:
};
OpenMPCancelExitStack OMPCancelStack;
+ /// Calculate branch weights for the likelihood attribute
+ llvm::MDNode *createBranchWeights(Stmt::Likelihood LH) const;
+
CodeGenPGO PGO;
/// Calculate branch weights appropriate for PGO data
- llvm::MDNode *createProfileWeights(uint64_t TrueCount, uint64_t FalseCount);
- llvm::MDNode *createProfileWeights(ArrayRef<uint64_t> Weights);
+ llvm::MDNode *createProfileWeights(uint64_t TrueCount,
+ uint64_t FalseCount) const;
+ llvm::MDNode *createProfileWeights(ArrayRef<uint64_t> Weights) const;
llvm::MDNode *createProfileWeightsForLoop(const Stmt *Cond,
- uint64_t LoopCount);
+ uint64_t LoopCount) const;
+
+ /// Calculate the branch weight for PGO data or the likelihood attribute.
+ /// The function tries to get the weight of \ref createProfileWeightsForLoop.
+ /// If that fails it gets the weight of \ref createBranchWeights.
+ llvm::MDNode *createProfileOrBranchWeightsForLoop(const Stmt *Cond,
+ uint64_t LoopCount,
+ const Stmt *Body) const;
public:
/// Increment the profiler's counter for the given statement by \p StepV.
/// If \p StepV is null, the default increment is 1.
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV = nullptr) {
- if (CGM.getCodeGenOpts().hasProfileClangInstr())
+ if (CGM.getCodeGenOpts().hasProfileClangInstr() &&
+ !CurFn->hasFnAttribute(llvm::Attribute::NoProfile))
PGO.emitCounterIncrement(Builder, S, StepV);
PGO.setCurrentStmt(S);
}
@@ -1438,6 +1475,9 @@ private:
/// The branch weights of SwitchInsn when doing instrumentation based PGO.
SmallVector<uint64_t, 16> *SwitchWeights = nullptr;
+ /// The likelihood attributes of the SwitchCase.
+ SmallVector<Stmt::Likelihood, 16> *SwitchLikelihood = nullptr;
+
/// CaseRangeBlock - This block holds if condition check for last case
/// statement range in current switch instruction.
llvm::BasicBlock *CaseRangeBlock = nullptr;
@@ -1817,7 +1857,7 @@ private:
llvm::BasicBlock *TerminateLandingPad = nullptr;
llvm::BasicBlock *TerminateHandler = nullptr;
- llvm::BasicBlock *TrapBB = nullptr;
+ llvm::SmallVector<llvm::BasicBlock *, 2> TrapBBs;
/// Terminate funclets keyed by parent funclet pad.
llvm::MapVector<llvm::Value *, llvm::BasicBlock *> TerminateFunclets;
@@ -3074,7 +3114,7 @@ public:
/// statements.
///
/// \return True if the statement was handled.
- bool EmitSimpleStmt(const Stmt *S);
+ bool EmitSimpleStmt(const Stmt *S, ArrayRef<const Attr *> Attrs);
Address EmitCompoundStmt(const CompoundStmt &S, bool GetLast = false,
AggValueSlot AVS = AggValueSlot::ignored());
@@ -3103,9 +3143,9 @@ public:
void EmitBreakStmt(const BreakStmt &S);
void EmitContinueStmt(const ContinueStmt &S);
void EmitSwitchStmt(const SwitchStmt &S);
- void EmitDefaultStmt(const DefaultStmt &S);
- void EmitCaseStmt(const CaseStmt &S);
- void EmitCaseStmtRange(const CaseStmt &S);
+ void EmitDefaultStmt(const DefaultStmt &S, ArrayRef<const Attr *> Attrs);
+ void EmitCaseStmt(const CaseStmt &S, ArrayRef<const Attr *> Attrs);
+ void EmitCaseStmtRange(const CaseStmt &S, ArrayRef<const Attr *> Attrs);
void EmitAsmStmt(const AsmStmt &S);
void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S);
@@ -3334,12 +3374,15 @@ public:
Address BasePointersArray = Address::invalid();
Address PointersArray = Address::invalid();
Address SizesArray = Address::invalid();
+ Address MappersArray = Address::invalid();
unsigned NumberOfTargetItems = 0;
explicit OMPTargetDataInfo() = default;
OMPTargetDataInfo(Address BasePointersArray, Address PointersArray,
- Address SizesArray, unsigned NumberOfTargetItems)
+ Address SizesArray, Address MappersArray,
+ unsigned NumberOfTargetItems)
: BasePointersArray(BasePointersArray), PointersArray(PointersArray),
- SizesArray(SizesArray), NumberOfTargetItems(NumberOfTargetItems) {}
+ SizesArray(SizesArray), MappersArray(MappersArray),
+ NumberOfTargetItems(NumberOfTargetItems) {}
};
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S,
const RegionCodeGenTy &BodyGen,
@@ -3562,6 +3605,9 @@ public:
// LValue Expression Emission
//===--------------------------------------------------------------------===//
+ /// Create a check that a scalar RValue is non-null.
+ llvm::Value *EmitNonNullRValueCheck(RValue RV, QualType T);
+
/// GetUndefRValue - Get an appropriate 'undef' rvalue for the given type.
RValue GetUndefRValue(QualType Ty);
@@ -4075,13 +4121,10 @@ public:
llvm::AtomicOrdering &AO,
llvm::SyncScope::ID &SSID);
-private:
enum class MSVCIntrin;
-
-public:
llvm::Value *EmitMSVCBuiltinExpr(MSVCIntrin BuiltinID, const CallExpr *E);
- llvm::Value *EmitBuiltinAvailable(ArrayRef<llvm::Value *> Args);
+ llvm::Value *EmitBuiltinAvailable(const VersionTuple &Version);
llvm::Value *EmitObjCProtocolExpr(const ObjCProtocolExpr *E);
llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E);
@@ -4259,7 +4302,7 @@ public:
void registerGlobalDtorWithAtExit(llvm::Constant *dtorStub);
/// Call unatexit() with function dtorStub.
- llvm::Value *unregisterGlobalDtorWithUnAtExit(llvm::Function *dtorStub);
+ llvm::Value *unregisterGlobalDtorWithUnAtExit(llvm::Constant *dtorStub);
/// Emit code in this function to perform a guarded variable
/// initialization. Guarded initializations are used when it's not
@@ -4312,7 +4355,8 @@ public:
llvm::Value *EmitAnnotationCall(llvm::Function *AnnotationFn,
llvm::Value *AnnotatedVal,
StringRef AnnotationStr,
- SourceLocation Location);
+ SourceLocation Location,
+ const AnnotateAttr *Attr);
/// Emit local annotations for the local variable V, declared by D.
void EmitVarAnnotations(const VarDecl *D, llvm::Value *V);
@@ -4351,13 +4395,29 @@ public:
bool ConstantFoldsToSimpleInteger(const Expr *Cond, llvm::APSInt &Result,
bool AllowLabels = false);
+ /// isInstrumentedCondition - Determine whether the given condition is an
+ /// instrumentable condition (i.e. no "&&" or "||").
+ static bool isInstrumentedCondition(const Expr *C);
+
+ /// EmitBranchToCounterBlock - Emit a conditional branch to a new block that
+ /// increments a profile counter based on the semantics of the given logical
+ /// operator opcode. This is used to instrument branch condition coverage
+ /// for logical operators.
+ void EmitBranchToCounterBlock(const Expr *Cond, BinaryOperator::Opcode LOp,
+ llvm::BasicBlock *TrueBlock,
+ llvm::BasicBlock *FalseBlock,
+ uint64_t TrueCount = 0,
+ Stmt::Likelihood LH = Stmt::LH_None,
+ const Expr *CntrIdx = nullptr);
+
/// EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g. for an
/// if statement) to the specified blocks. Based on the condition, this might
/// try to simplify the codegen of the conditional based on the branch.
/// TrueCount should be the number of times we expect the condition to
/// evaluate to true based on PGO data.
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock,
- llvm::BasicBlock *FalseBlock, uint64_t TrueCount);
+ llvm::BasicBlock *FalseBlock, uint64_t TrueCount,
+ Stmt::Likelihood LH = Stmt::LH_None);
/// Given an assignment `*LHS = RHS`, emit a test that checks if \p RHS is
/// nonnull, if \p LHS is marked _Nonnull.
@@ -4421,7 +4481,7 @@ public:
/// Create a basic block that will call the trap intrinsic, and emit a
/// conditional branch to it, for the -ftrapv checks.
- void EmitTrapCheck(llvm::Value *Checked);
+ void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID);
/// Emit a call to trap or debugtrap and attach function attribute
/// "trap-func-name" if specified.
@@ -4516,26 +4576,6 @@ private:
Address Loc);
public:
-#ifndef NDEBUG
- // Determine whether the given argument is an Objective-C method
- // that may have type parameters in its signature.
- static bool isObjCMethodWithTypeParams(const ObjCMethodDecl *method) {
- const DeclContext *dc = method->getDeclContext();
- if (const ObjCInterfaceDecl *classDecl= dyn_cast<ObjCInterfaceDecl>(dc)) {
- return classDecl->getTypeParamListAsWritten();
- }
-
- if (const ObjCCategoryDecl *catDecl = dyn_cast<ObjCCategoryDecl>(dc)) {
- return catDecl->getTypeParamList();
- }
-
- return false;
- }
-
- template<typename T>
- static bool isObjCMethodWithTypeParams(const T *) { return false; }
-#endif
-
enum class EvaluationOrder {
///! No language constraints on evaluation order.
Default,
@@ -4545,56 +4585,16 @@ public:
ForceRightToLeft
};
- /// EmitCallArgs - Emit call arguments for a function.
- template <typename T>
- void EmitCallArgs(CallArgList &Args, const T *CallArgTypeInfo,
- llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange,
- AbstractCallee AC = AbstractCallee(),
- unsigned ParamsToSkip = 0,
- EvaluationOrder Order = EvaluationOrder::Default) {
- SmallVector<QualType, 16> ArgTypes;
- CallExpr::const_arg_iterator Arg = ArgRange.begin();
-
- assert((ParamsToSkip == 0 || CallArgTypeInfo) &&
- "Can't skip parameters if type info is not provided");
- if (CallArgTypeInfo) {
-#ifndef NDEBUG
- bool isGenericMethod = isObjCMethodWithTypeParams(CallArgTypeInfo);
-#endif
-
- // First, use the argument types that the type info knows about
- for (auto I = CallArgTypeInfo->param_type_begin() + ParamsToSkip,
- E = CallArgTypeInfo->param_type_end();
- I != E; ++I, ++Arg) {
- assert(Arg != ArgRange.end() && "Running over edge of argument list!");
- assert((isGenericMethod ||
- ((*I)->isVariablyModifiedType() ||
- (*I).getNonReferenceType()->isObjCRetainableType() ||
- getContext()
- .getCanonicalType((*I).getNonReferenceType())
- .getTypePtr() ==
- getContext()
- .getCanonicalType((*Arg)->getType())
- .getTypePtr())) &&
- "type mismatch in call argument!");
- ArgTypes.push_back(*I);
- }
- }
-
- // Either we've emitted all the call args, or we have a call to variadic
- // function.
- assert((Arg == ArgRange.end() || !CallArgTypeInfo ||
- CallArgTypeInfo->isVariadic()) &&
- "Extra arguments in non-variadic function!");
-
- // If we still have any arguments, emit them using the type of the argument.
- for (auto *A : llvm::make_range(Arg, ArgRange.end()))
- ArgTypes.push_back(CallArgTypeInfo ? getVarArgType(A) : A->getType());
+ // Wrapper for function prototype sources. Wraps either a FunctionProtoType or
+ // an ObjCMethodDecl.
+ struct PrototypeWrapper {
+ llvm::PointerUnion<const FunctionProtoType *, const ObjCMethodDecl *> P;
- EmitCallArgs(Args, ArgTypes, ArgRange, AC, ParamsToSkip, Order);
- }
+ PrototypeWrapper(const FunctionProtoType *FT) : P(FT) {}
+ PrototypeWrapper(const ObjCMethodDecl *MD) : P(MD) {}
+ };
- void EmitCallArgs(CallArgList &Args, ArrayRef<QualType> ArgTypes,
+ void EmitCallArgs(CallArgList &Args, PrototypeWrapper Prototype,
llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange,
AbstractCallee AC = AbstractCallee(),
unsigned ParamsToSkip = 0,
@@ -4672,6 +4672,77 @@ private:
llvm::Value *FormResolverCondition(const MultiVersionResolverOption &RO);
};
+/// TargetFeatures - This class is used to check whether the builtin function
+/// has the required tagert specific features. It is able to support the
+/// combination of ','(and), '|'(or), and '()'. By default, the priority of
+/// ',' is higher than that of '|' .
+/// E.g:
+/// A,B|C means the builtin function requires both A and B, or C.
+/// If we want the builtin function requires both A and B, or both A and C,
+/// there are two ways: A,B|A,C or A,(B|C).
+/// The FeaturesList should not contain spaces, and brackets must appear in
+/// pairs.
+class TargetFeatures {
+ struct FeatureListStatus {
+ bool HasFeatures;
+ StringRef CurFeaturesList;
+ };
+
+ const llvm::StringMap<bool> &CallerFeatureMap;
+
+ FeatureListStatus getAndFeatures(StringRef FeatureList) {
+ int InParentheses = 0;
+ bool HasFeatures = true;
+ size_t SubexpressionStart = 0;
+ for (size_t i = 0, e = FeatureList.size(); i < e; ++i) {
+ char CurrentToken = FeatureList[i];
+ switch (CurrentToken) {
+ default:
+ break;
+ case '(':
+ if (InParentheses == 0)
+ SubexpressionStart = i + 1;
+ ++InParentheses;
+ break;
+ case ')':
+ --InParentheses;
+ assert(InParentheses >= 0 && "Parentheses are not in pair");
+ LLVM_FALLTHROUGH;
+ case '|':
+ case ',':
+ if (InParentheses == 0) {
+ if (HasFeatures && i != SubexpressionStart) {
+ StringRef F = FeatureList.slice(SubexpressionStart, i);
+ HasFeatures = CurrentToken == ')' ? hasRequiredFeatures(F)
+ : CallerFeatureMap.lookup(F);
+ }
+ SubexpressionStart = i + 1;
+ if (CurrentToken == '|') {
+ return {HasFeatures, FeatureList.substr(SubexpressionStart)};
+ }
+ }
+ break;
+ }
+ }
+ assert(InParentheses == 0 && "Parentheses are not in pair");
+ if (HasFeatures && SubexpressionStart != FeatureList.size())
+ HasFeatures =
+ CallerFeatureMap.lookup(FeatureList.substr(SubexpressionStart));
+ return {HasFeatures, StringRef()};
+ }
+
+public:
+ bool hasRequiredFeatures(StringRef FeatureList) {
+ FeatureListStatus FS = {false, FeatureList};
+ while (!FS.HasFeatures && !FS.CurFeaturesList.empty())
+ FS = getAndFeatures(FS.CurFeaturesList);
+ return FS.HasFeatures;
+ }
+
+ TargetFeatures(const llvm::StringMap<bool> &CallerFeatureMap)
+ : CallerFeatureMap(CallerFeatureMap) {}
+};
+
inline DominatingLLVMValue::saved_type
DominatingLLVMValue::save(CodeGenFunction &CGF, llvm::Value *value) {
if (!needsSaving(value)) return saved_type(value, false);