49
49
#include " llvm/Support/PointerLikeTypeTraits.h"
50
50
#include " llvm/Support/TrailingObjects.h"
51
51
#include " llvm/Support/type_traits.h"
52
+ #include < bitset>
52
53
#include < cassert>
53
54
#include < cstddef>
54
55
#include < cstdint>
@@ -119,6 +120,8 @@ class EnumDecl;
119
120
class Expr ;
120
121
class ExtQualsTypeCommonBase ;
121
122
class FunctionDecl ;
123
+ class FunctionEffectsRef ;
124
+ class FunctionEffectKindSet ;
122
125
class FunctionEffectSet ;
123
126
class IdentifierInfo ;
124
127
class NamedDecl ;
@@ -4712,12 +4715,13 @@ class FunctionEffect {
4712
4715
public:
4713
4716
// / Identifies the particular effect.
4714
4717
enum class Kind : uint8_t {
4715
- None = 0 ,
4716
- NonBlocking = 1 ,
4717
- NonAllocating = 2 ,
4718
- Blocking = 3 ,
4719
- Allocating = 4
4718
+ NonBlocking ,
4719
+ NonAllocating ,
4720
+ Blocking ,
4721
+ Allocating ,
4722
+ Last = Allocating
4720
4723
};
4724
+ constexpr static size_t KindCount = static_cast <size_t >(Kind::Last) + 1 ;
4721
4725
4722
4726
// / Flags describing some behaviors of the effect.
4723
4727
using Flags = unsigned ;
@@ -4743,8 +4747,6 @@ class FunctionEffect {
4743
4747
// be considered for uniqueness.
4744
4748
4745
4749
public:
4746
- FunctionEffect () : FKind(Kind::None) {}
4747
-
4748
4750
explicit FunctionEffect (Kind K) : FKind(K) {}
4749
4751
4750
4752
// / The kind of the effect.
@@ -4773,35 +4775,43 @@ class FunctionEffect {
4773
4775
case Kind::Blocking:
4774
4776
case Kind::Allocating:
4775
4777
return 0 ;
4776
- case Kind::None:
4777
- break ;
4778
4778
}
4779
4779
llvm_unreachable (" unknown effect kind" );
4780
4780
}
4781
4781
4782
4782
// / The description printed in diagnostics, e.g. 'nonblocking'.
4783
4783
StringRef name () const ;
4784
4784
4785
- // / Return true if the effect is allowed to be inferred on the callee,
4786
- // / which is either a FunctionDecl or BlockDecl.
4785
+ friend raw_ostream &operator <<(raw_ostream &OS,
4786
+ const FunctionEffect &Effect) {
4787
+ OS << Effect.name ();
4788
+ return OS;
4789
+ }
4790
+
4791
+ // / Determine whether the effect is allowed to be inferred on the callee,
4792
+ // / which is either a FunctionDecl or BlockDecl. If the returned optional
4793
+ // / is empty, inference is permitted; otherwise it holds the effect which
4794
+ // / blocked inference.
4787
4795
// / Example: This allows nonblocking(false) to prevent inference for the
4788
4796
// / function.
4789
- bool canInferOnFunction (const Decl &Callee) const ;
4797
+ std::optional<FunctionEffect>
4798
+ effectProhibitingInference (const Decl &Callee,
4799
+ FunctionEffectKindSet CalleeFX) const ;
4790
4800
4791
4801
// Return false for success. When true is returned for a direct call, then the
4792
4802
// FE_InferrableOnCallees flag may trigger inference rather than an immediate
4793
4803
// diagnostic. Caller should be assumed to have the effect (it may not have it
4794
4804
// explicitly when inferring).
4795
4805
bool shouldDiagnoseFunctionCall (bool Direct,
4796
- ArrayRef<FunctionEffect> CalleeFX) const ;
4806
+ FunctionEffectKindSet CalleeFX) const ;
4797
4807
4798
- friend bool operator ==(const FunctionEffect & LHS, const FunctionEffect & RHS) {
4808
+ friend bool operator ==(FunctionEffect LHS, FunctionEffect RHS) {
4799
4809
return LHS.FKind == RHS.FKind ;
4800
4810
}
4801
- friend bool operator !=(const FunctionEffect & LHS, const FunctionEffect & RHS) {
4811
+ friend bool operator !=(FunctionEffect LHS, FunctionEffect RHS) {
4802
4812
return !(LHS == RHS);
4803
4813
}
4804
- friend bool operator <(const FunctionEffect & LHS, const FunctionEffect & RHS) {
4814
+ friend bool operator <(FunctionEffect LHS, FunctionEffect RHS) {
4805
4815
return LHS.FKind < RHS.FKind ;
4806
4816
}
4807
4817
};
@@ -4829,13 +4839,14 @@ struct FunctionEffectWithCondition {
4829
4839
FunctionEffect Effect;
4830
4840
EffectConditionExpr Cond;
4831
4841
4832
- FunctionEffectWithCondition () = default ;
4833
- FunctionEffectWithCondition (const FunctionEffect &E,
4834
- const EffectConditionExpr &C)
4842
+ FunctionEffectWithCondition (FunctionEffect E, const EffectConditionExpr &C)
4835
4843
: Effect(E), Cond(C) {}
4836
4844
4837
4845
// / Return a textual description of the effect, and its condition, if any.
4838
4846
std::string description () const ;
4847
+
4848
+ friend raw_ostream &operator <<(raw_ostream &OS,
4849
+ const FunctionEffectWithCondition &CFE);
4839
4850
};
4840
4851
4841
4852
// / Support iteration in parallel through a pair of FunctionEffect and
@@ -4940,6 +4951,85 @@ class FunctionEffectsRef {
4940
4951
void dump (llvm::raw_ostream &OS) const ;
4941
4952
};
4942
4953
4954
+ // / A mutable set of FunctionEffect::Kind.
4955
+ class FunctionEffectKindSet {
4956
+ // For now this only needs to be a bitmap.
4957
+ constexpr static size_t EndBitPos = FunctionEffect::KindCount;
4958
+ using KindBitsT = std::bitset<EndBitPos>;
4959
+
4960
+ KindBitsT KindBits{};
4961
+
4962
+ explicit FunctionEffectKindSet (KindBitsT KB) : KindBits(KB) {}
4963
+
4964
+ // Functions to translate between an effect kind, starting at 1, and a
4965
+ // position in the bitset.
4966
+
4967
+ constexpr static size_t kindToPos (FunctionEffect::Kind K) {
4968
+ return static_cast <size_t >(K);
4969
+ }
4970
+
4971
+ constexpr static FunctionEffect::Kind posToKind (size_t Pos) {
4972
+ return static_cast <FunctionEffect::Kind>(Pos);
4973
+ }
4974
+
4975
+ // Iterates through the bits which are set.
4976
+ class iterator {
4977
+ const FunctionEffectKindSet *Outer = nullptr ;
4978
+ size_t Idx = 0 ;
4979
+
4980
+ // If Idx does not reference a set bit, advance it until it does,
4981
+ // or until it reaches EndBitPos.
4982
+ void advanceToNextSetBit () {
4983
+ while (Idx < EndBitPos && !Outer->KindBits .test (Idx))
4984
+ ++Idx;
4985
+ }
4986
+
4987
+ public:
4988
+ iterator ();
4989
+ iterator (const FunctionEffectKindSet &O, size_t I) : Outer(&O), Idx(I) {
4990
+ advanceToNextSetBit ();
4991
+ }
4992
+ bool operator ==(const iterator &Other) const { return Idx == Other.Idx ; }
4993
+ bool operator !=(const iterator &Other) const { return Idx != Other.Idx ; }
4994
+
4995
+ iterator operator ++() {
4996
+ ++Idx;
4997
+ advanceToNextSetBit ();
4998
+ return *this ;
4999
+ }
5000
+
5001
+ FunctionEffect operator *() const {
5002
+ assert (Idx < EndBitPos && " Dereference of end iterator" );
5003
+ return FunctionEffect (posToKind (Idx));
5004
+ }
5005
+ };
5006
+
5007
+ public:
5008
+ FunctionEffectKindSet () = default ;
5009
+ explicit FunctionEffectKindSet (FunctionEffectsRef FX) { insert (FX); }
5010
+
5011
+ iterator begin () const { return iterator (*this , 0 ); }
5012
+ iterator end () const { return iterator (*this , EndBitPos); }
5013
+
5014
+ void insert (FunctionEffect Effect) { KindBits.set (kindToPos (Effect.kind ())); }
5015
+ void insert (FunctionEffectsRef FX) {
5016
+ for (FunctionEffect Item : FX.effects ())
5017
+ insert (Item);
5018
+ }
5019
+ void insert (FunctionEffectKindSet Set) { KindBits |= Set.KindBits ; }
5020
+
5021
+ bool empty () const { return KindBits.none (); }
5022
+ bool contains (const FunctionEffect::Kind EK) const {
5023
+ return KindBits.test (kindToPos (EK));
5024
+ }
5025
+ void dump (llvm::raw_ostream &OS) const ;
5026
+
5027
+ static FunctionEffectKindSet difference (FunctionEffectKindSet LHS,
5028
+ FunctionEffectKindSet RHS) {
5029
+ return FunctionEffectKindSet (LHS.KindBits & ~RHS.KindBits );
5030
+ }
5031
+ };
5032
+
4943
5033
// / A mutable set of FunctionEffects and possibly conditions attached to them.
4944
5034
// / Used to compare and merge effects on declarations.
4945
5035
// /
0 commit comments