Skip to content

Commit 4c754ae

Browse files
authored
Merge pull request #70171 from gottesmm/pr-b349a91e3e11b734533ef6be6960d755ed783b71
[region-isolation] Ensure that if a var is captured by reference in a closure that we do not allow for later accesses to sendableFields
2 parents 8d22e48 + 59cc595 commit 4c754ae

16 files changed

+1208
-231
lines changed

include/swift/Basic/ImmutablePointerSet.h

Lines changed: 62 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -58,19 +58,22 @@
5858

5959
namespace swift {
6060

61-
template <typename PtrTy> class ImmutablePointerSetFactory;
61+
template <typename T>
62+
class ImmutablePointerSetFactory;
6263

6364
/// An immutable set of pointers. It is backed by a tail allocated sorted array
6465
/// ref.
65-
template <typename T> class ImmutablePointerSet : public llvm::FoldingSetNode {
66-
using PtrTy = typename std::add_pointer<T>::type;
66+
template <typename T>
67+
class ImmutablePointerSet : public llvm::FoldingSetNode {
6768
friend class ImmutablePointerSetFactory<T>;
6869

70+
using PtrTraits = llvm::PointerLikeTypeTraits<T>;
71+
6972
NullablePtr<ImmutablePointerSetFactory<T>> ParentFactory;
70-
llvm::ArrayRef<PtrTy> Data;
73+
llvm::ArrayRef<T> Data;
7174

7275
ImmutablePointerSet(ImmutablePointerSetFactory<T> *ParentFactory,
73-
llvm::ArrayRef<PtrTy> NewData)
76+
llvm::ArrayRef<T> NewData)
7477
: ParentFactory(ParentFactory), Data(NewData) {}
7578

7679
public:
@@ -100,7 +103,7 @@ template <typename T> class ImmutablePointerSet : public llvm::FoldingSetNode {
100103
return !(*this == P);
101104
}
102105

103-
unsigned count(PtrTy Ptr) const {
106+
unsigned count(T Ptr) const {
104107
// This returns the first element >= Ptr. Since we know that our array is
105108
// sorted and uniqued, Ptr must be that element.
106109
auto LowerBound = std::lower_bound(begin(), end(), Ptr);
@@ -113,17 +116,19 @@ template <typename T> class ImmutablePointerSet : public llvm::FoldingSetNode {
113116
return *LowerBound == Ptr;
114117
}
115118

116-
using iterator = typename llvm::ArrayRef<PtrTy>::iterator;
119+
using iterator = typename llvm::ArrayRef<T>::iterator;
117120
iterator begin() const { return Data.begin(); }
118121
iterator end() const { return Data.end(); }
122+
llvm::iterator_range<iterator> range() const { return {begin(), end()}; }
123+
llvm::ArrayRef<T> data() const { return Data; }
119124

120125
unsigned size() const { return Data.size(); }
121126
bool empty() const { return Data.empty(); }
122127

123128
void Profile(llvm::FoldingSetNodeID &ID) const {
124129
assert(!Data.empty() && "Should not profile empty ImmutablePointerSet");
125-
for (PtrTy P : Data) {
126-
ID.AddPointer(P);
130+
for (T P : Data) {
131+
ID.AddPointer(PtrTraits::getAsVoidPointer(P));
127132
}
128133
}
129134

@@ -177,10 +182,11 @@ template <typename T> class ImmutablePointerSet : public llvm::FoldingSetNode {
177182
}
178183
};
179184

180-
template <typename T> class ImmutablePointerSetFactory {
181-
using PtrTy = typename std::add_pointer<T>::type;
182-
185+
template <typename T>
186+
class ImmutablePointerSetFactory {
183187
using PtrSet = ImmutablePointerSet<T>;
188+
using PtrTraits = typename PtrSet::PtrTraits;
189+
184190
// This is computed out-of-line so that ImmutablePointerSetFactory is
185191
// treated as a complete type.
186192
static const unsigned AllocAlignment;
@@ -205,7 +211,7 @@ template <typename T> class ImmutablePointerSetFactory {
205211

206212
/// Given a sorted and uniqued list \p Array, return the ImmutablePointerSet
207213
/// containing Array. Asserts if \p Array is not sorted and uniqued.
208-
PtrSet *get(llvm::ArrayRef<PtrTy> Array) {
214+
PtrSet *get(llvm::ArrayRef<T> Array) {
209215
if (Array.empty())
210216
return ImmutablePointerSetFactory::getEmptySet();
211217

@@ -215,8 +221,8 @@ template <typename T> class ImmutablePointerSetFactory {
215221
assert(is_sorted_and_uniqued(Array));
216222

217223
llvm::FoldingSetNodeID ID;
218-
for (PtrTy Ptr : Array) {
219-
ID.AddPointer(Ptr);
224+
for (T Ptr : Array) {
225+
ID.AddPointer(PtrTraits::getAsVoidPointer(Ptr));
220226
}
221227

222228
void *InsertPt;
@@ -225,7 +231,7 @@ template <typename T> class ImmutablePointerSetFactory {
225231
}
226232

227233
size_t NumElts = Array.size();
228-
size_t MemSize = sizeof(PtrSet) + sizeof(PtrTy) * NumElts;
234+
size_t MemSize = sizeof(PtrSet) + sizeof(T) * NumElts;
229235

230236
// Allocate the memory.
231237
auto *Mem =
@@ -234,8 +240,8 @@ template <typename T> class ImmutablePointerSetFactory {
234240
// Copy in the pointers into the tail allocated memory. We do not need to do
235241
// any sorting/uniquing ourselves since we assume that our users perform
236242
// this task for us.
237-
llvm::MutableArrayRef<PtrTy> DataMem(reinterpret_cast<PtrTy *>(&Mem[1]),
238-
NumElts);
243+
llvm::MutableArrayRef<T> DataMem(reinterpret_cast<T *>(&Mem[1]),
244+
NumElts);
239245
std::copy(Array.begin(), Array.end(), DataMem.begin());
240246

241247
// Allocate the new node and insert it into the Set.
@@ -244,7 +250,35 @@ template <typename T> class ImmutablePointerSetFactory {
244250
return NewNode;
245251
}
246252

247-
PtrSet *merge(PtrSet *S1, llvm::ArrayRef<PtrTy> S2) {
253+
PtrSet *get(T value) {
254+
llvm::FoldingSetNodeID ID;
255+
ID.AddPointer(PtrTraits::getAsVoidPointer(value));
256+
257+
void *InsertPt;
258+
if (auto *PSet = Set.FindNodeOrInsertPos(ID, InsertPt)) {
259+
return PSet;
260+
}
261+
262+
size_t NumElts = 1;
263+
size_t MemSize = sizeof(PtrSet) + sizeof(T) * NumElts;
264+
265+
// Allocate the memory.
266+
auto *Mem =
267+
reinterpret_cast<PtrSet *>(Allocator.Allocate(MemSize, AllocAlignment));
268+
269+
// Copy in the pointers into the tail allocated memory. We do not need to do
270+
// any sorting/uniquing ourselves since we assume that our users perform
271+
// this task for us.
272+
llvm::MutableArrayRef<T> DataMem(reinterpret_cast<T *>(&Mem[1]), NumElts);
273+
DataMem[0] = value;
274+
275+
// Allocate the new node and insert it into the Set.
276+
auto *NewNode = new (Mem) PtrSet(this, DataMem);
277+
Set.InsertNode(NewNode, InsertPt);
278+
return NewNode;
279+
}
280+
281+
PtrSet *merge(PtrSet *S1, llvm::ArrayRef<T> S2) {
248282
if (S1->empty())
249283
return get(S2);
250284

@@ -266,7 +300,7 @@ template <typename T> class ImmutablePointerSetFactory {
266300
// perform a sorted set merging algorithm to create the ID. We also count
267301
// the number of unique elements for allocation purposes.
268302
unsigned NumElts = 0;
269-
set_union_for_each(*S1, S2, [&ID, &NumElts](const PtrTy Ptr) -> void {
303+
set_union_for_each(*S1, S2, [&ID, &NumElts](const T Ptr) -> void {
270304
ID.AddPointer(Ptr);
271305
NumElts++;
272306
});
@@ -277,7 +311,7 @@ template <typename T> class ImmutablePointerSetFactory {
277311
return PSet;
278312
}
279313

280-
unsigned MemSize = sizeof(PtrSet) + sizeof(PtrTy) * NumElts;
314+
unsigned MemSize = sizeof(PtrSet) + sizeof(T) * NumElts;
281315

282316
// Allocate the memory.
283317
auto *Mem =
@@ -286,8 +320,7 @@ template <typename T> class ImmutablePointerSetFactory {
286320
// Copy in the union of the two pointer sets into the tail allocated
287321
// memory. Since we know that our sorted arrays are uniqued, we can use
288322
// set_union to get the uniqued sorted array that we want.
289-
llvm::MutableArrayRef<PtrTy> DataMem(reinterpret_cast<PtrTy *>(&Mem[1]),
290-
NumElts);
323+
llvm::MutableArrayRef<T> DataMem(reinterpret_cast<T *>(&Mem[1]), NumElts);
291324
std::set_union(S1->begin(), S1->end(), S2.begin(), S2.end(),
292325
DataMem.begin());
293326

@@ -316,8 +349,8 @@ template <typename T> class ImmutablePointerSetFactory {
316349
// perform a sorted set merging algorithm to create the ID. We also count
317350
// the number of unique elements for allocation purposes.
318351
unsigned NumElts = 0;
319-
set_union_for_each(*S1, *S2, [&ID, &NumElts](const PtrTy Ptr) -> void {
320-
ID.AddPointer(Ptr);
352+
set_union_for_each(*S1, *S2, [&ID, &NumElts](const T Ptr) -> void {
353+
ID.AddPointer(PtrTraits::getAsVoidPointer(Ptr));
321354
NumElts++;
322355
});
323356

@@ -327,7 +360,7 @@ template <typename T> class ImmutablePointerSetFactory {
327360
return PSet;
328361
}
329362

330-
unsigned MemSize = sizeof(PtrSet) + sizeof(PtrTy) * NumElts;
363+
unsigned MemSize = sizeof(PtrSet) + sizeof(T) * NumElts;
331364

332365
// Allocate the memory.
333366
auto *Mem =
@@ -336,8 +369,7 @@ template <typename T> class ImmutablePointerSetFactory {
336369
// Copy in the union of the two pointer sets into the tail allocated
337370
// memory. Since we know that our sorted arrays are uniqued, we can use
338371
// set_union to get the uniqued sorted array that we want.
339-
llvm::MutableArrayRef<PtrTy> DataMem(reinterpret_cast<PtrTy *>(&Mem[1]),
340-
NumElts);
372+
llvm::MutableArrayRef<T> DataMem(reinterpret_cast<T *>(&Mem[1]), NumElts);
341373
std::set_union(S1->begin(), S1->end(), S2->begin(), S2->end(),
342374
DataMem.begin());
343375

@@ -356,8 +388,8 @@ template <typename T>
356388
#if !defined(_MSC_VER) || defined(__clang__)
357389
constexpr
358390
#endif
359-
const unsigned ImmutablePointerSetFactory<T>::AllocAlignment =
360-
(alignof(PtrSet) > alignof(PtrTy)) ? alignof(PtrSet) : alignof(PtrTy);
391+
const unsigned ImmutablePointerSetFactory<T>::AllocAlignment =
392+
(alignof(PtrSet) > alignof(T)) ? alignof(PtrSet) : alignof(T);
361393

362394
} // end swift namespace
363395

include/swift/SIL/SILBasicBlock.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,52 @@ public SwiftObjectHeader {
231231
const_reverse_iterator rbegin() const { return InstList.rbegin(); }
232232
const_reverse_iterator rend() const { return InstList.rend(); }
233233

234+
llvm::iterator_range<iterator> getRangeStartingAtInst(SILInstruction *inst) {
235+
assert(inst->getParent() == this);
236+
return {inst->getIterator(), end()};
237+
}
238+
239+
llvm::iterator_range<iterator> getRangeEndingAtInst(SILInstruction *inst) {
240+
assert(inst->getParent() == this);
241+
return {begin(), inst->getIterator()};
242+
}
243+
244+
llvm::iterator_range<reverse_iterator>
245+
getReverseRangeStartingAtInst(SILInstruction *inst) {
246+
assert(inst->getParent() == this);
247+
return {inst->getReverseIterator(), rend()};
248+
}
249+
250+
llvm::iterator_range<reverse_iterator>
251+
getReverseRangeEndingAtInst(SILInstruction *inst) {
252+
assert(inst->getParent() == this);
253+
return {rbegin(), inst->getReverseIterator()};
254+
}
255+
256+
llvm::iterator_range<const_iterator>
257+
getRangeStartingAtInst(SILInstruction *inst) const {
258+
assert(inst->getParent() == this);
259+
return {inst->getIterator(), end()};
260+
}
261+
262+
llvm::iterator_range<const_iterator>
263+
getRangeEndingAtInst(SILInstruction *inst) const {
264+
assert(inst->getParent() == this);
265+
return {begin(), inst->getIterator()};
266+
}
267+
268+
llvm::iterator_range<const_reverse_iterator>
269+
getReverseRangeStartingAtInst(SILInstruction *inst) const {
270+
assert(inst->getParent() == this);
271+
return {inst->getReverseIterator(), rend()};
272+
}
273+
274+
llvm::iterator_range<const_reverse_iterator>
275+
getReverseRangeEndingAtInst(SILInstruction *inst) const {
276+
assert(inst->getParent() == this);
277+
return {rbegin(), inst->getReverseIterator()};
278+
}
279+
234280
/// Allows deleting instructions while iterating over all instructions of the
235281
/// block.
236282
///

0 commit comments

Comments
 (0)