48
48
#include " llvm/Support/PointerLikeTypeTraits.h"
49
49
#include " llvm/Support/TrailingObjects.h"
50
50
#include " llvm/Support/type_traits.h"
51
+ #include < bitset>
51
52
#include < cassert>
52
53
#include < cstddef>
53
54
#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 ;
@@ -4695,12 +4698,13 @@ class FunctionEffect {
4695
4698
public:
4696
4699
// / Identifies the particular effect.
4697
4700
enum class Kind : uint8_t {
4698
- None = 0 ,
4699
- NonBlocking = 1 ,
4700
- NonAllocating = 2 ,
4701
- Blocking = 3 ,
4702
- Allocating = 4
4701
+ NonBlocking ,
4702
+ NonAllocating ,
4703
+ Blocking ,
4704
+ Allocating ,
4705
+ Last = Allocating
4703
4706
};
4707
+ constexpr static size_t KindCount = static_cast <size_t >(Kind::Last) + 1 ;
4704
4708
4705
4709
// / Flags describing some behaviors of the effect.
4706
4710
using Flags = unsigned ;
@@ -4726,8 +4730,6 @@ class FunctionEffect {
4726
4730
// be considered for uniqueness.
4727
4731
4728
4732
public:
4729
- FunctionEffect () : FKind(Kind::None) {}
4730
-
4731
4733
explicit FunctionEffect (Kind K) : FKind(K) {}
4732
4734
4733
4735
// / The kind of the effect.
@@ -4756,35 +4758,43 @@ class FunctionEffect {
4756
4758
case Kind::Blocking:
4757
4759
case Kind::Allocating:
4758
4760
return 0 ;
4759
- case Kind::None:
4760
- break ;
4761
4761
}
4762
4762
llvm_unreachable (" unknown effect kind" );
4763
4763
}
4764
4764
4765
4765
// / The description printed in diagnostics, e.g. 'nonblocking'.
4766
4766
StringRef name () const ;
4767
4767
4768
- // / Return true if the effect is allowed to be inferred on the callee,
4769
- // / which is either a FunctionDecl or BlockDecl.
4768
+ friend raw_ostream &operator <<(raw_ostream &OS,
4769
+ const FunctionEffect &Effect) {
4770
+ OS << Effect.name ();
4771
+ return OS;
4772
+ }
4773
+
4774
+ // / Determine whether the effect is allowed to be inferred on the callee,
4775
+ // / which is either a FunctionDecl or BlockDecl. If the returned optional
4776
+ // / is empty, inference is permitted; otherwise it holds the effect which
4777
+ // / blocked inference.
4770
4778
// / Example: This allows nonblocking(false) to prevent inference for the
4771
4779
// / function.
4772
- bool canInferOnFunction (const Decl &Callee) const ;
4780
+ std::optional<FunctionEffect>
4781
+ effectProhibitingInference (const Decl &Callee,
4782
+ FunctionEffectKindSet CalleeFX) const ;
4773
4783
4774
4784
// Return false for success. When true is returned for a direct call, then the
4775
4785
// FE_InferrableOnCallees flag may trigger inference rather than an immediate
4776
4786
// diagnostic. Caller should be assumed to have the effect (it may not have it
4777
4787
// explicitly when inferring).
4778
4788
bool shouldDiagnoseFunctionCall (bool Direct,
4779
- ArrayRef<FunctionEffect> CalleeFX) const ;
4789
+ FunctionEffectKindSet CalleeFX) const ;
4780
4790
4781
- friend bool operator ==(const FunctionEffect & LHS, const FunctionEffect & RHS) {
4791
+ friend bool operator ==(FunctionEffect LHS, FunctionEffect RHS) {
4782
4792
return LHS.FKind == RHS.FKind ;
4783
4793
}
4784
- friend bool operator !=(const FunctionEffect & LHS, const FunctionEffect & RHS) {
4794
+ friend bool operator !=(FunctionEffect LHS, FunctionEffect RHS) {
4785
4795
return !(LHS == RHS);
4786
4796
}
4787
- friend bool operator <(const FunctionEffect & LHS, const FunctionEffect & RHS) {
4797
+ friend bool operator <(FunctionEffect LHS, FunctionEffect RHS) {
4788
4798
return LHS.FKind < RHS.FKind ;
4789
4799
}
4790
4800
};
@@ -4812,13 +4822,14 @@ struct FunctionEffectWithCondition {
4812
4822
FunctionEffect Effect;
4813
4823
EffectConditionExpr Cond;
4814
4824
4815
- FunctionEffectWithCondition () = default ;
4816
- FunctionEffectWithCondition (const FunctionEffect &E,
4817
- const EffectConditionExpr &C)
4825
+ FunctionEffectWithCondition (FunctionEffect E, const EffectConditionExpr &C)
4818
4826
: Effect(E), Cond(C) {}
4819
4827
4820
4828
// / Return a textual description of the effect, and its condition, if any.
4821
4829
std::string description () const ;
4830
+
4831
+ friend raw_ostream &operator <<(raw_ostream &OS,
4832
+ const FunctionEffectWithCondition &CFE);
4822
4833
};
4823
4834
4824
4835
// / Support iteration in parallel through a pair of FunctionEffect and
@@ -4923,6 +4934,85 @@ class FunctionEffectsRef {
4923
4934
void dump (llvm::raw_ostream &OS) const ;
4924
4935
};
4925
4936
4937
+ // / A mutable set of FunctionEffect::Kind.
4938
+ class FunctionEffectKindSet {
4939
+ // For now this only needs to be a bitmap.
4940
+ constexpr static size_t EndBitPos = FunctionEffect::KindCount;
4941
+ using KindBitsT = std::bitset<EndBitPos>;
4942
+
4943
+ KindBitsT KindBits{};
4944
+
4945
+ explicit FunctionEffectKindSet (KindBitsT KB) : KindBits(KB) {}
4946
+
4947
+ // Functions to translate between an effect kind, starting at 1, and a
4948
+ // position in the bitset.
4949
+
4950
+ constexpr static size_t kindToPos (FunctionEffect::Kind K) {
4951
+ return static_cast <size_t >(K);
4952
+ }
4953
+
4954
+ constexpr static FunctionEffect::Kind posToKind (size_t Pos) {
4955
+ return static_cast <FunctionEffect::Kind>(Pos);
4956
+ }
4957
+
4958
+ // Iterates through the bits which are set.
4959
+ class iterator {
4960
+ const FunctionEffectKindSet *Outer = nullptr ;
4961
+ size_t Idx = 0 ;
4962
+
4963
+ // If Idx does not reference a set bit, advance it until it does,
4964
+ // or until it reaches EndBitPos.
4965
+ void advanceToNextSetBit () {
4966
+ while (Idx < EndBitPos && !Outer->KindBits .test (Idx))
4967
+ ++Idx;
4968
+ }
4969
+
4970
+ public:
4971
+ iterator ();
4972
+ iterator (const FunctionEffectKindSet &O, size_t I) : Outer(&O), Idx(I) {
4973
+ advanceToNextSetBit ();
4974
+ }
4975
+ bool operator ==(const iterator &Other) const { return Idx == Other.Idx ; }
4976
+ bool operator !=(const iterator &Other) const { return Idx != Other.Idx ; }
4977
+
4978
+ iterator operator ++() {
4979
+ ++Idx;
4980
+ advanceToNextSetBit ();
4981
+ return *this ;
4982
+ }
4983
+
4984
+ FunctionEffect operator *() const {
4985
+ assert (Idx < EndBitPos && " Dereference of end iterator" );
4986
+ return FunctionEffect (posToKind (Idx));
4987
+ }
4988
+ };
4989
+
4990
+ public:
4991
+ FunctionEffectKindSet () = default ;
4992
+ explicit FunctionEffectKindSet (FunctionEffectsRef FX) { insert (FX); }
4993
+
4994
+ iterator begin () const { return iterator (*this , 0 ); }
4995
+ iterator end () const { return iterator (*this , EndBitPos); }
4996
+
4997
+ void insert (FunctionEffect Effect) { KindBits.set (kindToPos (Effect.kind ())); }
4998
+ void insert (FunctionEffectsRef FX) {
4999
+ for (FunctionEffect Item : FX.effects ())
5000
+ insert (Item);
5001
+ }
5002
+ void insert (FunctionEffectKindSet Set) { KindBits |= Set.KindBits ; }
5003
+
5004
+ bool empty () const { return KindBits.none (); }
5005
+ bool contains (const FunctionEffect::Kind EK) const {
5006
+ return KindBits.test (kindToPos (EK));
5007
+ }
5008
+ void dump (llvm::raw_ostream &OS) const ;
5009
+
5010
+ static FunctionEffectKindSet difference (FunctionEffectKindSet LHS,
5011
+ FunctionEffectKindSet RHS) {
5012
+ return FunctionEffectKindSet (LHS.KindBits & ~RHS.KindBits );
5013
+ }
5014
+ };
5015
+
4926
5016
// / A mutable set of FunctionEffects and possibly conditions attached to them.
4927
5017
// / Used to compare and merge effects on declarations.
4928
5018
// /
0 commit comments