Skip to content

[region-isolation] Ensure that if a var is captured by reference in a closure that we do not allow for later accesses to sendableFields #70171

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 62 additions & 30 deletions include/swift/Basic/ImmutablePointerSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,22 @@

namespace swift {

template <typename PtrTy> class ImmutablePointerSetFactory;
template <typename T>
class ImmutablePointerSetFactory;

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

using PtrTraits = llvm::PointerLikeTypeTraits<T>;

NullablePtr<ImmutablePointerSetFactory<T>> ParentFactory;
llvm::ArrayRef<PtrTy> Data;
llvm::ArrayRef<T> Data;

ImmutablePointerSet(ImmutablePointerSetFactory<T> *ParentFactory,
llvm::ArrayRef<PtrTy> NewData)
llvm::ArrayRef<T> NewData)
: ParentFactory(ParentFactory), Data(NewData) {}

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

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

using iterator = typename llvm::ArrayRef<PtrTy>::iterator;
using iterator = typename llvm::ArrayRef<T>::iterator;
iterator begin() const { return Data.begin(); }
iterator end() const { return Data.end(); }
llvm::iterator_range<iterator> range() const { return {begin(), end()}; }
llvm::ArrayRef<T> data() const { return Data; }

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

void Profile(llvm::FoldingSetNodeID &ID) const {
assert(!Data.empty() && "Should not profile empty ImmutablePointerSet");
for (PtrTy P : Data) {
ID.AddPointer(P);
for (T P : Data) {
ID.AddPointer(PtrTraits::getAsVoidPointer(P));
}
}

Expand Down Expand Up @@ -177,10 +182,11 @@ template <typename T> class ImmutablePointerSet : public llvm::FoldingSetNode {
}
};

template <typename T> class ImmutablePointerSetFactory {
using PtrTy = typename std::add_pointer<T>::type;

template <typename T>
class ImmutablePointerSetFactory {
using PtrSet = ImmutablePointerSet<T>;
using PtrTraits = typename PtrSet::PtrTraits;

// This is computed out-of-line so that ImmutablePointerSetFactory is
// treated as a complete type.
static const unsigned AllocAlignment;
Expand All @@ -205,7 +211,7 @@ template <typename T> class ImmutablePointerSetFactory {

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

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

llvm::FoldingSetNodeID ID;
for (PtrTy Ptr : Array) {
ID.AddPointer(Ptr);
for (T Ptr : Array) {
ID.AddPointer(PtrTraits::getAsVoidPointer(Ptr));
}

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

size_t NumElts = Array.size();
size_t MemSize = sizeof(PtrSet) + sizeof(PtrTy) * NumElts;
size_t MemSize = sizeof(PtrSet) + sizeof(T) * NumElts;

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

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

PtrSet *merge(PtrSet *S1, llvm::ArrayRef<PtrTy> S2) {
PtrSet *get(T value) {
llvm::FoldingSetNodeID ID;
ID.AddPointer(PtrTraits::getAsVoidPointer(value));

void *InsertPt;
if (auto *PSet = Set.FindNodeOrInsertPos(ID, InsertPt)) {
return PSet;
}

size_t NumElts = 1;
size_t MemSize = sizeof(PtrSet) + sizeof(T) * NumElts;

// Allocate the memory.
auto *Mem =
reinterpret_cast<PtrSet *>(Allocator.Allocate(MemSize, AllocAlignment));

// Copy in the pointers into the tail allocated memory. We do not need to do
// any sorting/uniquing ourselves since we assume that our users perform
// this task for us.
llvm::MutableArrayRef<T> DataMem(reinterpret_cast<T *>(&Mem[1]), NumElts);
DataMem[0] = value;

// Allocate the new node and insert it into the Set.
auto *NewNode = new (Mem) PtrSet(this, DataMem);
Set.InsertNode(NewNode, InsertPt);
return NewNode;
}

PtrSet *merge(PtrSet *S1, llvm::ArrayRef<T> S2) {
if (S1->empty())
return get(S2);

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

unsigned MemSize = sizeof(PtrSet) + sizeof(PtrTy) * NumElts;
unsigned MemSize = sizeof(PtrSet) + sizeof(T) * NumElts;

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

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

Expand All @@ -327,7 +360,7 @@ template <typename T> class ImmutablePointerSetFactory {
return PSet;
}

unsigned MemSize = sizeof(PtrSet) + sizeof(PtrTy) * NumElts;
unsigned MemSize = sizeof(PtrSet) + sizeof(T) * NumElts;

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

Expand All @@ -356,8 +388,8 @@ template <typename T>
#if !defined(_MSC_VER) || defined(__clang__)
constexpr
#endif
const unsigned ImmutablePointerSetFactory<T>::AllocAlignment =
(alignof(PtrSet) > alignof(PtrTy)) ? alignof(PtrSet) : alignof(PtrTy);
const unsigned ImmutablePointerSetFactory<T>::AllocAlignment =
(alignof(PtrSet) > alignof(T)) ? alignof(PtrSet) : alignof(T);

} // end swift namespace

Expand Down
46 changes: 46 additions & 0 deletions include/swift/SIL/SILBasicBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,52 @@ public SwiftObjectHeader {
const_reverse_iterator rbegin() const { return InstList.rbegin(); }
const_reverse_iterator rend() const { return InstList.rend(); }

llvm::iterator_range<iterator> getRangeStartingAtInst(SILInstruction *inst) {
assert(inst->getParent() == this);
return {inst->getIterator(), end()};
}

llvm::iterator_range<iterator> getRangeEndingAtInst(SILInstruction *inst) {
assert(inst->getParent() == this);
return {begin(), inst->getIterator()};
}

llvm::iterator_range<reverse_iterator>
getReverseRangeStartingAtInst(SILInstruction *inst) {
assert(inst->getParent() == this);
return {inst->getReverseIterator(), rend()};
}

llvm::iterator_range<reverse_iterator>
getReverseRangeEndingAtInst(SILInstruction *inst) {
assert(inst->getParent() == this);
return {rbegin(), inst->getReverseIterator()};
}

llvm::iterator_range<const_iterator>
getRangeStartingAtInst(SILInstruction *inst) const {
assert(inst->getParent() == this);
return {inst->getIterator(), end()};
}

llvm::iterator_range<const_iterator>
getRangeEndingAtInst(SILInstruction *inst) const {
assert(inst->getParent() == this);
return {begin(), inst->getIterator()};
}

llvm::iterator_range<const_reverse_iterator>
getReverseRangeStartingAtInst(SILInstruction *inst) const {
assert(inst->getParent() == this);
return {inst->getReverseIterator(), rend()};
}

llvm::iterator_range<const_reverse_iterator>
getReverseRangeEndingAtInst(SILInstruction *inst) const {
assert(inst->getParent() == this);
return {rbegin(), inst->getReverseIterator()};
}

/// Allows deleting instructions while iterating over all instructions of the
/// block.
///
Expand Down
Loading