-
Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathRCStateTransition.h
154 lines (122 loc) · 5.3 KB
/
RCStateTransition.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//===--- RCStateTransition.h ------------------------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SILOPTIMIZER_PASSMANAGER_ARC_RCSTATETRANSITION_H
#define SWIFT_SILOPTIMIZER_PASSMANAGER_ARC_RCSTATETRANSITION_H
#include "swift/Basic/type_traits.h"
#include "swift/Basic/ImmutablePointerSet.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILInstruction.h"
#include "llvm/ADT/SmallPtrSet.h"
#include <cstdint>
namespace swift {
class RCIdentityFunctionInfo;
class ConsumedArgToEpilogueReleaseMatcher;
} // end swift namespace
//===----------------------------------------------------------------------===//
// RCStateTransitionKind
//===----------------------------------------------------------------------===//
namespace swift {
/// The kind of an RCStateTransition.
enum class RCStateTransitionKind : uint8_t {
#define KIND(K) K,
#define ABSTRACT_VALUE(Name, StartKind, EndKind) \
Name ## _Start = StartKind, Name ## _End = EndKind,
#include "RCStateTransition.def"
};
/// \returns the RCStateTransitionKind corresponding to \p N.
RCStateTransitionKind getRCStateTransitionKind(SILNode *N);
/// Define predicates to test for RCStateTransition abstract value kinds.
#define ABSTRACT_VALUE(Name, Start, End) \
bool isRCStateTransition ## Name(RCStateTransitionKind Kind); \
static inline bool isRCStateTransition ## Name(SILNode *N) { \
return isRCStateTransition ## Name(getRCStateTransitionKind(N)); \
}
#define KIND(Name) \
static inline bool isRCStateTransition ## Name(SILNode *N) { \
return RCStateTransitionKind::Name == getRCStateTransitionKind(N); \
}
#include "RCStateTransition.def"
//===----------------------------------------------------------------------===//
// RCStateTransition
//===----------------------------------------------------------------------===//
class RefCountState;
class BottomUpRefCountState;
class TopDownRefCountState;
/// Represents a transition in the RC history of a ref count.
class RCStateTransition {
friend class RefCountState;
friend class BottomUpRefCountState;
friend class TopDownRefCountState;
/// An RCStateTransition can represent either an RC end point (i.e. an initial
/// or terminal RC transition) or a ptr set of Mutators.
SILNode *EndPoint;
ImmutablePointerSet<SILInstruction> *Mutators =
ImmutablePointerSetFactory<SILInstruction>::getEmptySet();
RCStateTransitionKind Kind;
// Should only be constructed be default RefCountState.
RCStateTransition() = default;
public:
~RCStateTransition() = default;
RCStateTransition(const RCStateTransition &R) = default;
RCStateTransition(ImmutablePointerSet<SILInstruction> *I) {
assert(I->size() == 1);
SILInstruction *Inst = *I->begin();
Kind = getRCStateTransitionKind(Inst->asSILNode());
if (isRCStateTransitionEndPoint(Kind)) {
EndPoint = Inst->asSILNode();
return;
}
if (isRCStateTransitionMutator(Kind)) {
Mutators = I;
return;
}
// Unknown kind.
}
RCStateTransition(SILFunctionArgument *A)
: EndPoint(A), Kind(RCStateTransitionKind::StrongEntrance) {
assert(A->hasConvention(SILArgumentConvention::Direct_Owned) &&
"Expected owned argument");
}
RCStateTransitionKind getKind() const { return Kind; }
/// Define test functions for the various abstract categorizations we have.
#define ABSTRACT_VALUE(Name, StartKind, EndKind) bool is ## Name() const;
#include "RCStateTransition.def"
/// Return true if this Transition is a mutator transition that contains I.
bool containsMutator(SILInstruction *I) const {
assert(isMutator() && "This should only be called if we are of mutator "
"kind");
return Mutators->count(I);
}
using mutator_range =
iterator_range<std::remove_pointer<decltype(Mutators)>::type::iterator>;
/// Returns a Range of Mutators. Asserts if this transition is not a mutator
/// transition.
mutator_range getMutators() const {
return {Mutators->begin(), Mutators->end()};
}
/// Return true if Inst is an instruction that causes a transition that can be
/// paired with this transition.
bool matchingInst(SILInstruction *Inst) const;
/// Attempt to merge \p Other into \p this. Returns true if we succeeded,
/// false otherwise.
bool merge(const RCStateTransition &Other);
/// Return true if the kind of this RCStateTransition is not 'Invalid'.
bool isValid() const { return getKind() != RCStateTransitionKind::Invalid; }
};
// These static assert checks are here for performance reasons.
static_assert(IsTriviallyCopyable<RCStateTransition>::value,
"RCStateTransitions must be trivially copyable");
} // end swift namespace
namespace llvm {
raw_ostream &operator<<(raw_ostream &os, swift::RCStateTransitionKind Kind);
} // end llvm namespace
#endif