1919
2020#include " swift/Basic/DiverseStack.h"
2121#include " swift/SIL/SILLocation.h"
22+ #include " swift/SIL/SILValue.h"
2223#include " llvm/ADT/SmallVector.h"
2324
2425namespace swift {
@@ -75,10 +76,23 @@ llvm::raw_ostream &operator<<(raw_ostream &os, CleanupState state);
7576
7677class LLVM_LIBRARY_VISIBILITY Cleanup {
7778 friend class CleanupManager ;
79+ friend class CleanupCloner ;
7880
79- unsigned allocatedSize;
81+ protected:
82+ // A set of flags that categorize the type of cleanup such that it can be
83+ // recreated via SILGenFunction methods based on the type of argument input.
84+ //
85+ // Example: Distinguishing in between @owned cleanups with a writeback buffer
86+ // (ExclusiveBorrowCleanup) or ones that involve formal access cleanups.
87+ enum class Flags : uint8_t {
88+ None = 0 ,
89+ ExclusiveBorrowCleanup = 1 ,
90+ };
8091
92+ private:
8193 CleanupState state;
94+ unsigned allocatedSize : 24 ;
95+ Flags flags : 8 ;
8296
8397protected:
8498 Cleanup () {}
@@ -99,6 +113,16 @@ class LLVM_LIBRARY_VISIBILITY Cleanup {
99113 virtual void emit (SILGenFunction &SGF, CleanupLocation loc,
100114 ForUnwind_t forUnwind) = 0;
101115 virtual void dump (SILGenFunction &SGF) const = 0;
116+
117+ protected:
118+ Flags getFlags () const { return flags; }
119+
120+ // / Call func passing in the SILValue address that this cleanup will write
121+ // / back to if supported and any flags associated with the cleanup. Returns
122+ // / false otherwise.
123+ virtual bool getWritebackBuffer (function_ref<void (SILValue)> func) {
124+ return false ;
125+ }
102126};
103127
104128// / A cleanup depth is generally used to denote the set of cleanups
@@ -117,6 +141,7 @@ typedef DiverseStackImpl<Cleanup>::stable_iterator CleanupHandle;
117141
118142class LLVM_LIBRARY_VISIBILITY CleanupManager {
119143 friend class Scope ;
144+ friend class CleanupCloner ;
120145
121146 SILGenFunction &SGF;
122147
@@ -229,7 +254,7 @@ class LLVM_LIBRARY_VISIBILITY CleanupManager {
229254 // / Set the state of the cleanup at the given depth.
230255 // / The transition must be non-trivial and legal.
231256 void setCleanupState (CleanupHandle depth, CleanupState state);
232-
257+
233258 // / True if there are any active cleanups in the scope between the two
234259 // / cleanup handles.
235260 bool hasAnyActiveCleanups (CleanupsDepth from, CleanupsDepth to);
@@ -246,6 +271,12 @@ class LLVM_LIBRARY_VISIBILITY CleanupManager {
246271
247272 // / Verify that the given cleanup handle is valid.
248273 void checkIterator (CleanupHandle handle) const ;
274+
275+ private:
276+ // Look up the flags and optionally the writeback address associated with the
277+ // cleanup at \p depth. If
278+ std::tuple<Cleanup::Flags, Optional<SILValue>>
279+ getFlagsAndWritebackBuffer (CleanupHandle depth);
249280};
250281
251282// / An RAII object that allows the state of a cleanup to be
@@ -274,10 +305,14 @@ class CleanupStateRestorationScope {
274305 void popImpl ();
275306};
276307
308+ // / Extract enough information from a managed value to reliably clone its
309+ // / cleanup (if it has any) on a newly computed type. This includes modeling
310+ // / writeback buffers.
277311class CleanupCloner {
278312 SILGenFunction &SGF;
279313 bool hasCleanup;
280314 bool isLValue;
315+ Optional<SILValue> writebackBuffer;
281316
282317public:
283318 CleanupCloner (SILGenFunction &SGF, const ManagedValue &mv);
0 commit comments