Skip to content

Commit bcca7ee

Browse files
committed
SILGen: Combine related addressable buffer bookkeeping types into one place.
There's no need for two separate types here. Fully separate the addressable buffer tracking from VarLocs as well, in order to set up for a fix to addressable references to `if let` and `guard let` bindings.
1 parent 9d7d3a1 commit bcca7ee

File tree

4 files changed

+66
-132
lines changed

4 files changed

+66
-132
lines changed

lib/SILGen/SILGenDecl.cpp

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ namespace {
682682

683683
static void deallocateAddressable(SILGenFunction &SGF,
684684
SILLocation l,
685-
const SILGenFunction::VarLoc::AddressableBuffer::State &state) {
685+
const SILGenFunction::AddressableBuffer::State &state) {
686686
SGF.B.createEndBorrow(l, state.storeBorrow);
687687
SGF.B.createDeallocStack(l, state.allocStack);
688688
if (state.reabstraction
@@ -704,10 +704,6 @@ class DeallocateLocalVariableAddressableBuffer : public Cleanup {
704704
if (!addressableBuffer) {
705705
return;
706706
}
707-
auto found = SGF.VarLocs.find(vd);
708-
if (found == SGF.VarLocs.end()) {
709-
return;
710-
}
711707

712708
if (auto *state = addressableBuffer->getState()) {
713709
// The addressable buffer was forced, so clean it up now.
@@ -2243,7 +2239,7 @@ void SILGenFunction::destroyLocalVariable(SILLocation silLoc, VarDecl *vd) {
22432239
void
22442240
SILGenFunction::enterLocalVariableAddressableBufferScope(VarDecl *decl) {
22452241
auto marker = B.createTuple(decl, {});
2246-
AddressableBuffers[decl] = marker;
2242+
AddressableBuffers[decl].insertPoint = marker;
22472243
Cleanups.pushCleanup<DeallocateLocalVariableAddressableBuffer>(decl);
22482244
}
22492245

@@ -2296,27 +2292,12 @@ SILGenFunction::getLocalVariableAddressableBuffer(VarDecl *decl,
22962292
SILValue reabstraction, allocStack, storeBorrow;
22972293
{
22982294
SavedInsertionPointRAII save(B);
2299-
SILInstruction *insertPoint = nullptr;
2300-
// Look through bindings that might alias the original addressable buffer
2301-
// (such as case block variables, which use an alias variable to represent the
2302-
// incoming value from all of the case label patterns).
2303-
VarDecl *origDecl = decl;
2304-
do {
2305-
auto bufferIter = AddressableBuffers.find(origDecl);
2306-
ASSERT(bufferIter != AddressableBuffers.end()
2307-
&& "local variable didn't have an addressability scope set");
2308-
2309-
insertPoint = bufferIter->second.getInsertPoint();
2310-
if (insertPoint) {
2311-
break;
2312-
}
2295+
auto *addressableBuffer = getAddressableBufferInfo(decl);
23132296

2314-
origDecl = bufferIter->second.getOriginalForAlias();
2315-
ASSERT(origDecl && "no insert point or alias for addressable declaration!");
2316-
} while (true);
2317-
2318-
assert(insertPoint && "didn't find an insertion point for the addressable buffer");
2319-
B.setInsertionPoint(insertPoint);
2297+
assert(addressableBuffer
2298+
&& addressableBuffer->insertPoint
2299+
&& "didn't find an insertion point for the addressable buffer");
2300+
B.setInsertionPoint(addressableBuffer->insertPoint);
23202301
auto allocStackTy = fullyAbstractedTy;
23212302
if (value->getType().isMoveOnlyWrapped()) {
23222303
allocStackTy = allocStackTy.addingMoveOnlyWrapper();
@@ -2366,7 +2347,7 @@ SILGenFunction::getLocalVariableAddressableBuffer(VarDecl *decl,
23662347
// Record the addressable representation.
23672348
auto *addressableBuffer = getAddressableBufferInfo(decl);
23682349
auto *newState
2369-
= new VarLoc::AddressableBuffer::State(reabstraction, allocStack, storeBorrow);
2350+
= new AddressableBuffer::State(reabstraction, allocStack, storeBorrow);
23702351
addressableBuffer->stateOrAlias = newState;
23712352

23722353
// Emit cleanups on any paths where we previously would have cleaned up
@@ -2415,7 +2396,10 @@ void BlackHoleInitialization::copyOrInitValueInto(SILGenFunction &SGF, SILLocati
24152396
SGF.B.createIgnoredUse(loc, value.getValue());
24162397
}
24172398

2418-
SILGenFunction::VarLoc::AddressableBuffer::~AddressableBuffer() {
2399+
SILGenFunction::AddressableBuffer::~AddressableBuffer() {
2400+
if (insertPoint) {
2401+
insertPoint->eraseFromParent();
2402+
}
24192403
for (auto cleanupPoint : cleanupPoints) {
24202404
cleanupPoint->eraseFromParent();
24212405
}

lib/SILGen/SILGenFunction.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2005,19 +2005,16 @@ void SILGenFunction::emitAssignOrInit(SILLocation loc, ManagedValue selfValue,
20052005
AssignOrInitInst::Unknown);
20062006
}
20072007

2008-
SILGenFunction::VarLoc::AddressableBuffer *
2008+
SILGenFunction::AddressableBuffer *
20092009
SILGenFunction::getAddressableBufferInfo(ValueDecl *vd) {
20102010
do {
2011-
auto found = VarLocs.find(vd);
2012-
if (found == VarLocs.end()) {
2013-
return nullptr;
2014-
}
2011+
auto &found = AddressableBuffers[vd];
20152012

2016-
if (auto orig = found->second.addressableBuffer.stateOrAlias
2013+
if (auto orig = found.stateOrAlias
20172014
.dyn_cast<VarDecl*>()) {
20182015
vd = orig;
20192016
continue;
20202017
}
2021-
return &found->second.addressableBuffer;
2018+
return &found;
20222019
} while (true);
20232020
}

lib/SILGen/SILGenFunction.h

Lines changed: 50 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -478,67 +478,6 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
478478
/// or `Unknown` if it's known to be immutable.
479479
SILAccessEnforcement access;
480480

481-
/// A structure used for bookkeeping the on-demand formation and cleanup
482-
/// of an addressable representation for an immutable value binding.
483-
struct AddressableBuffer {
484-
struct State {
485-
// If the value needs to be reabstracted to provide an addressable
486-
// representation, this SILValue owns the reabstracted representation.
487-
SILValue reabstraction = SILValue();
488-
// The stack allocation for the addressable representation.
489-
SILValue allocStack = SILValue();
490-
// The initiation of the in-memory borrow.
491-
SILValue storeBorrow = SILValue();
492-
493-
State(SILValue reabstraction,
494-
SILValue allocStack,
495-
SILValue storeBorrow)
496-
: reabstraction(reabstraction), allocStack(allocStack),
497-
storeBorrow(storeBorrow)
498-
{}
499-
};
500-
501-
llvm::PointerUnion<State *, VarDecl*> stateOrAlias = (State*)nullptr;
502-
503-
// If the variable cleanup is triggered before the addressable
504-
// representation is demanded, but the addressable representation
505-
// gets demanded later, we save the insertion points where the
506-
// representation would be cleaned up so we can backfill them.
507-
llvm::SmallVector<SILInstruction*, 1> cleanupPoints;
508-
509-
AddressableBuffer() = default;
510-
511-
AddressableBuffer(VarDecl *original)
512-
: stateOrAlias(original)
513-
{
514-
}
515-
516-
AddressableBuffer(AddressableBuffer &&other)
517-
: stateOrAlias(other.stateOrAlias)
518-
{
519-
other.stateOrAlias = (State*)nullptr;
520-
cleanupPoints.swap(other.cleanupPoints);
521-
}
522-
523-
AddressableBuffer &operator=(AddressableBuffer &&other) {
524-
if (auto state = stateOrAlias.dyn_cast<State*>()) {
525-
delete state;
526-
}
527-
stateOrAlias = other.stateOrAlias;
528-
cleanupPoints.swap(other.cleanupPoints);
529-
return *this;
530-
}
531-
532-
State *getState() {
533-
ASSERT(!isa<VarDecl *>(stateOrAlias) &&
534-
"must get state from original AddressableBuffer");
535-
return stateOrAlias.dyn_cast<State*>();
536-
}
537-
538-
~AddressableBuffer();
539-
};
540-
AddressableBuffer addressableBuffer;
541-
542481
VarLoc() = default;
543482

544483
VarLoc(SILValue value, SILAccessEnforcement access,
@@ -552,55 +491,71 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
552491
/// a local variable.
553492
llvm::DenseMap<ValueDecl*, VarLoc> VarLocs;
554493

555-
VarLoc::AddressableBuffer *getAddressableBufferInfo(ValueDecl *vd);
556-
557-
// Represents an addressable buffer that has been allocated but not yet used.
558-
struct PreparedAddressableBuffer {
559-
llvm::PointerUnion<SILInstruction *, VarDecl *> insertPointOrAlias
560-
= (SILInstruction*)nullptr;
494+
/// A structure used for bookkeeping the on-demand formation and cleanup
495+
/// of an addressable representation for an immutable value binding.
496+
struct AddressableBuffer {
497+
struct State {
498+
// If the value needs to be reabstracted to provide an addressable
499+
// representation, this SILValue owns the reabstracted representation.
500+
SILValue reabstraction = SILValue();
501+
// The stack allocation for the addressable representation.
502+
SILValue allocStack = SILValue();
503+
// The initiation of the in-memory borrow.
504+
SILValue storeBorrow = SILValue();
505+
506+
State(SILValue reabstraction,
507+
SILValue allocStack,
508+
SILValue storeBorrow)
509+
: reabstraction(reabstraction), allocStack(allocStack),
510+
storeBorrow(storeBorrow)
511+
{}
512+
};
561513

562-
PreparedAddressableBuffer() = default;
514+
llvm::PointerUnion<State *, VarDecl*> stateOrAlias = (State*)nullptr;
515+
516+
// The point at which the buffer will be inserted.
517+
SILInstruction *insertPoint = nullptr;
563518

564-
PreparedAddressableBuffer(SILInstruction *insertPoint)
565-
: insertPointOrAlias(insertPoint)
566-
{
567-
ASSERT(insertPoint && "null insertion point provided");
568-
}
519+
// If the variable cleanup is triggered before the addressable
520+
// representation is demanded, but the addressable representation
521+
// gets demanded later, we save the insertion points where the
522+
// representation would be cleaned up so we can backfill them.
523+
llvm::SmallVector<SILInstruction*, 1> cleanupPoints;
524+
525+
AddressableBuffer() = default;
569526

570-
PreparedAddressableBuffer(VarDecl *alias)
571-
: insertPointOrAlias(alias)
527+
AddressableBuffer(VarDecl *original)
528+
: stateOrAlias(original)
572529
{
573-
ASSERT(alias && "null alias provided");
574530
}
575531

576-
PreparedAddressableBuffer(PreparedAddressableBuffer &&other)
577-
: insertPointOrAlias(other.insertPointOrAlias)
532+
AddressableBuffer(AddressableBuffer &&other)
533+
: stateOrAlias(other.stateOrAlias)
578534
{
579-
other.insertPointOrAlias = (SILInstruction*)nullptr;
535+
other.stateOrAlias = (State*)nullptr;
536+
cleanupPoints.swap(other.cleanupPoints);
580537
}
581538

582-
PreparedAddressableBuffer &operator=(PreparedAddressableBuffer &&other) {
583-
insertPointOrAlias = other.insertPointOrAlias;
584-
other.insertPointOrAlias = nullptr;
539+
AddressableBuffer &operator=(AddressableBuffer &&other) {
540+
if (auto state = stateOrAlias.dyn_cast<State*>()) {
541+
delete state;
542+
}
543+
stateOrAlias = other.stateOrAlias;
544+
cleanupPoints.swap(other.cleanupPoints);
585545
return *this;
586546
}
587547

588-
SILInstruction *getInsertPoint() const {
589-
return insertPointOrAlias.dyn_cast<SILInstruction*>();
548+
State *getState() {
549+
ASSERT(!isa<VarDecl *>(stateOrAlias) &&
550+
"must get state from original AddressableBuffer");
551+
return stateOrAlias.dyn_cast<State*>();
590552
}
591553

592-
VarDecl *getOriginalForAlias() const {
593-
return insertPointOrAlias.dyn_cast<VarDecl*>();
594-
}
595-
596-
~PreparedAddressableBuffer() {
597-
if (auto insertPoint = getInsertPoint()) {
598-
// Remove the insertion point if it went unused.
599-
insertPoint->eraseFromParent();
600-
}
601-
}
554+
~AddressableBuffer();
602555
};
603-
llvm::DenseMap<VarDecl *, PreparedAddressableBuffer> AddressableBuffers;
556+
llvm::DenseMap<ValueDecl *, AddressableBuffer> AddressableBuffers;
557+
558+
AddressableBuffer *getAddressableBufferInfo(ValueDecl *vd);
604559

605560
/// Establish the scope for the addressable buffer that might be allocated
606561
/// for a local variable binding.

lib/SILGen/SILGenPattern.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3173,8 +3173,6 @@ static void switchCaseStmtSuccessCallback(SILGenFunction &SGF,
31733173
expectedLoc = SILGenFunction::VarLoc(vdLoc->second.value,
31743174
vdLoc->second.access,
31753175
vdLoc->second.box);
3176-
expectedLoc.addressableBuffer = vd;
3177-
// Alias the addressable buffer for the two variables.
31783176
SGF.AddressableBuffers[expected] = vd;
31793177

31803178
// Emit a debug description for the variable, nested within a scope

0 commit comments

Comments
 (0)