Skip to content

Commit 756d440

Browse files
authored
Merge pull request #66196 from gottesmm/release-5.9-more-stuff-2
[5.9] More batched changes
2 parents 7203d52 + 20a9b1b commit 756d440

35 files changed

+3373
-84
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -758,11 +758,10 @@ ERROR(sil_movechecking_value_used_after_consume, none,
758758
"'%0' used after consume", (StringRef))
759759
ERROR(sil_movechecking_guaranteed_value_consumed, none,
760760
"'%0' is borrowed and cannot be consumed", (StringRef))
761-
762-
// FIXME: this diagnostic shouldn't ever be emitted now. rdar://109742587 (closures may still try to consume captures, e.g., borrowed parameters)
763-
ERROR(sil_movechecking_guaranteed_value_captured_by_closure, none,
764-
"'%0' is borrowed and cannot be consumed by closure capture", (StringRef))
765-
761+
ERROR(sil_movechecking_borrowed_parameter_captured_by_closure, none,
762+
"'%0' cannot be captured by an escaping closure since it is a borrowed "
763+
"parameter",
764+
(StringRef))
766765
ERROR(sil_movechecking_capture_consumed, none,
767766
"noncopyable '%0' cannot be consumed when captured by a closure", (StringRef))
768767
ERROR(sil_movechecking_inout_not_reinitialized_before_end_of_function, none,

include/swift/SIL/SILFunctionConventions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,11 @@ class SILFunctionConventions {
371371
return getNumIndirectSILResults();
372372
}
373373

374+
/// Returns the index of self.
375+
unsigned getSILArgIndexOfSelf() const {
376+
return getSILArgIndexOfFirstParam() + getNumParameters() - 1;
377+
}
378+
374379
/// Get the index into formal indirect results corresponding to the given SIL
375380
/// indirect result argument index.
376381
unsigned getIndirectFormalResultIndexForSILArg(unsigned argIdx) const {

include/swift/SIL/SILMoveOnlyDeinit.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,12 @@ class SILMoveOnlyDeinit final : public SILAllocated<SILMoveOnlyDeinit> {
6363

6464
SILFunction *getImplementation() const { return funcImpl; }
6565

66-
bool isSerialized() const { return serialized; }
66+
IsSerialized_t isSerialized() const {
67+
return serialized ? IsSerialized : IsNotSerialized;
68+
}
69+
void setSerialized(IsSerialized_t inputSerialized) {
70+
serialized = inputSerialized ? 1 : 0;
71+
}
6772

6873
void print(llvm::raw_ostream &os, bool verbose) const;
6974
void dump() const;

include/swift/SILOptimizer/Utils/CanonicalizeOSSALifetime.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,10 +319,9 @@ class CanonicalizeOSSALifetime final {
319319
liveness->initializeDef(getCurrentDef());
320320
}
321321

322-
void invalidateLiveness() {
322+
void clear() {
323323
consumingBlocks.clear();
324324
debugValues.clear();
325-
liveness->invalidate();
326325
discoveredBlocks.clear();
327326
}
328327

lib/IRGen/GenType.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2887,19 +2887,26 @@ static bool tryEmitDeinitCall(IRGenFunction &IGF,
28872887
llvm::function_ref<void ()> indirectCleanup) {
28882888
auto ty = T.getASTType();
28892889
auto nominal = ty->getAnyNominal();
2890+
28902891
// We are only concerned with move-only type deinits here.
28912892
if (!nominal || !nominal->getValueTypeDestructor()) {
28922893
return false;
28932894
}
2894-
2895-
auto deinit = IGF.getSILModule().lookUpMoveOnlyDeinit(nominal);
2896-
assert(deinit && "type has a deinit declared in AST but SIL deinit record is not present!");
2897-
2895+
2896+
auto deinitTable = IGF.getSILModule().lookUpMoveOnlyDeinit(nominal);
2897+
2898+
// If we do not have a deinit table, call the value witness instead.
2899+
if (!deinitTable) {
2900+
irgen::emitDestroyCall(IGF, T, indirect());
2901+
indirectCleanup();
2902+
return true;
2903+
}
2904+
28982905
// The deinit should take a single value parameter of the nominal type, either
28992906
// by @owned or indirect @in convention.
2900-
auto deinitFn = IGF.IGM.getAddrOfSILFunction(deinit->getImplementation(),
2907+
auto deinitFn = IGF.IGM.getAddrOfSILFunction(deinitTable->getImplementation(),
29012908
NotForDefinition);
2902-
auto deinitTy = deinit->getImplementation()->getLoweredFunctionType();
2909+
auto deinitTy = deinitTable->getImplementation()->getLoweredFunctionType();
29032910
auto deinitFP = FunctionPointer::forDirect(IGF.IGM, deinitFn,
29042911
nullptr, deinitTy);
29052912
assert(deinitTy->getNumParameters() == 1

lib/SILGen/ArgumentSource.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ class ArgumentSource {
280280

281281
ArgumentSource copyForDiagnostics() const;
282282

283-
void dump() const;
283+
LLVM_DUMP_METHOD void dump() const;
284284
void dump(raw_ostream &os, unsigned indent = 0) const;
285285

286286
private:

lib/SILGen/SILGen.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,11 +1079,6 @@ void SILGenModule::emitFunctionDefinition(SILDeclRef constant, SILFunction *f) {
10791079
preEmitFunction(constant, f, loc);
10801080
PrettyStackTraceSILFunction X("silgen emitDeallocatingDestructor", f);
10811081
SILGenFunction(*this, *f, dd).emitDeallocatingDestructor(dd);
1082-
1083-
// If we have a move only type, create the table for this type.
1084-
if (nom->isMoveOnly())
1085-
SILMoveOnlyDeinit::create(f->getModule(), nom, IsNotSerialized, f);
1086-
10871082
postEmitFunction(constant, f);
10881083
return;
10891084
}

lib/SILGen/SILGen.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,9 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
459459
SILFunction *jvp, SILFunction *vjp,
460460
const DeclAttribute *diffAttr);
461461

462+
/// Emit a deinit table for a noncopyable type.
463+
void emitNonCopyableTypeDeinitTable(NominalTypeDecl *decl);
464+
462465
/// Known functions for bridging.
463466
SILDeclRef getStringToNSStringFn();
464467
SILDeclRef getNSStringToStringFn();

lib/SILGen/SILGenApply.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3029,7 +3029,8 @@ static StorageRefResult findStorageReferenceExprForBorrow(Expr *e) {
30293029
return result.withTransitiveRoot(te);
30303030

30313031
} else if (auto ioe = dyn_cast<InOutExpr>(e)) {
3032-
return ioe;
3032+
if (auto result = findStorageReferenceExprForBorrow(ioe->getSubExpr()))
3033+
return result.withTransitiveRoot(ioe);
30333034
}
30343035

30353036
return StorageRefResult();
@@ -3049,6 +3050,24 @@ Expr *ArgumentSource::findStorageReferenceExprForMoveOnly(
30493050
sawLoad = true;
30503051
}
30513052

3053+
// If we have a subscript, strip it off and make sure that our base is
3054+
// something that we can process. If we do and we succeed below, we return the
3055+
// subscript instead.
3056+
SubscriptExpr *subscriptExpr = nullptr;
3057+
if ((subscriptExpr = dyn_cast<SubscriptExpr>(argExpr))) {
3058+
auto *decl = cast<SubscriptDecl>(subscriptExpr->getDecl().getDecl());
3059+
if (decl->getReadImpl() != ReadImplKind::Read) {
3060+
subscriptExpr = nullptr;
3061+
} else {
3062+
argExpr = subscriptExpr->getBase();
3063+
}
3064+
3065+
// If there's a load on the base of the subscript expr, look past it.
3066+
if (auto *li = dyn_cast<LoadExpr>(argExpr)) {
3067+
argExpr = li->getSubExpr();
3068+
}
3069+
}
3070+
30523071
// If we're consuming instead, then the load _must_ have been there.
30533072
if (kind == StorageReferenceOperationKind::Consume && !sawLoad)
30543073
return nullptr;
@@ -3097,6 +3116,12 @@ Expr *ArgumentSource::findStorageReferenceExprForMoveOnly(
30973116
// has a move only base.
30983117
(void)std::move(*this).asKnownExpr();
30993118

3119+
// If we saw a subscript expr and the base of the subscript expr passed our
3120+
// tests above, we can emit the call to the subscript directly as a borrowed
3121+
// lvalue. Return the subscript expr here so that we emit it appropriately.
3122+
if (subscriptExpr)
3123+
return subscriptExpr;
3124+
31003125
return result.getTransitiveRoot();
31013126
}
31023127

lib/SILGen/SILGenDecl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1958,13 +1958,19 @@ InitializationPtr SILGenFunction::emitLocalVariableWithCleanup(
19581958
std::unique_ptr<TemporaryInitialization>
19591959
SILGenFunction::emitTemporary(SILLocation loc, const TypeLowering &tempTL) {
19601960
SILValue addr = emitTemporaryAllocation(loc, tempTL.getLoweredType());
1961+
if (addr->getType().isMoveOnly())
1962+
addr = B.createMarkMustCheckInst(
1963+
loc, addr, MarkMustCheckInst::CheckKind::ConsumableAndAssignable);
19611964
return useBufferAsTemporary(addr, tempTL);
19621965
}
19631966

19641967
std::unique_ptr<TemporaryInitialization>
19651968
SILGenFunction::emitFormalAccessTemporary(SILLocation loc,
19661969
const TypeLowering &tempTL) {
19671970
SILValue addr = emitTemporaryAllocation(loc, tempTL.getLoweredType());
1971+
if (addr->getType().isMoveOnly())
1972+
addr = B.createMarkMustCheckInst(
1973+
loc, addr, MarkMustCheckInst::CheckKind::ConsumableAndAssignable);
19681974
CleanupHandle cleanup =
19691975
enterDormantFormalAccessTemporaryCleanup(addr, loc, tempTL);
19701976
return std::unique_ptr<TemporaryInitialization>(

lib/SILGen/SILGenLValue.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ LogicalPathComponent::projectForRead(SILGenFunction &SGF, SILLocation loc,
366366
}
367367

368368
TemporaryInitializationPtr tempInit;
369+
ManagedValue result;
369370
RValue rvalue;
370371

371372
// If the RValue type has an openedExistential, then the RValue must be
@@ -377,9 +378,11 @@ LogicalPathComponent::projectForRead(SILGenFunction &SGF, SILLocation loc,
377378

378379
// Create a temporary, whose type may depend on the 'get'.
379380
tempInit = SGF.emitFormalAccessTemporary(loc, RValueTL);
381+
result = tempInit->getManagedAddress();
380382
} else {
381383
// Create a temporary for a static (non-dependent) RValue type.
382384
tempInit = SGF.emitFormalAccessTemporary(loc, RValueTL);
385+
result = tempInit->getManagedAddress();
383386

384387
// Emit a 'get' directly into the temporary.
385388
rvalue = std::move(*this).get(SGF, loc, base, SGFContext(tempInit.get()));
@@ -390,7 +393,8 @@ LogicalPathComponent::projectForRead(SILGenFunction &SGF, SILLocation loc,
390393
if (!rvalue.isInContext())
391394
std::move(rvalue).forwardInto(SGF, loc, tempInit.get());
392395

393-
return tempInit->getManagedAddress();
396+
assert(result);
397+
return result;
394398
}
395399

396400
ManagedValue LogicalPathComponent::project(SILGenFunction &SGF,

lib/SILGen/SILGenType.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,21 @@ void SILGenModule::emitDefaultWitnessTable(ProtocolDecl *protocol) {
10691069
defaultWitnesses->convertToDefinition(builder.DefaultWitnesses);
10701070
}
10711071

1072+
void SILGenModule::emitNonCopyableTypeDeinitTable(NominalTypeDecl *nom) {
1073+
auto *dd = nom->getValueTypeDestructor();
1074+
if (!dd)
1075+
return;
1076+
1077+
SILDeclRef constant(dd, SILDeclRef::Kind::Deallocator);
1078+
SILFunction *f = getFunction(constant, NotForDefinition);
1079+
auto serialized = IsSerialized_t::IsNotSerialized;
1080+
bool nomIsPublic = nom->getEffectiveAccess() >= AccessLevel::Public;
1081+
// We only serialize the deinit if the type is public and not resilient.
1082+
if (nomIsPublic && !nom->isResilient())
1083+
serialized = IsSerialized;
1084+
SILMoveOnlyDeinit::create(f->getModule(), nom, serialized, f);
1085+
}
1086+
10721087
namespace {
10731088

10741089
/// An ASTVisitor for generating SIL from method declarations
@@ -1100,6 +1115,13 @@ class SILGenType : public TypeMemberVisitor<SILGenType> {
11001115
genVTable.emitVTable();
11011116
}
11021117

1118+
// If this is a nominal type that is move only, emit a deinit table for it.
1119+
if (auto *nom = dyn_cast<NominalTypeDecl>(theType)) {
1120+
if (nom->isMoveOnly()) {
1121+
SGM.emitNonCopyableTypeDeinitTable(nom);
1122+
}
1123+
}
1124+
11031125
// Build a default witness table if this is a protocol that needs one.
11041126
if (auto protocol = dyn_cast<ProtocolDecl>(theType)) {
11051127
if (!protocol->isObjC() && protocol->isResilient()) {

lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2523,29 +2523,27 @@ void MoveOnlyAddressCheckerPImpl::rewriteUses(
25232523
// scope, we would have emitted the scope expansion error during diagnostics.
25242524
for (auto pair : addressUseState.borrows) {
25252525
if (auto *li = dyn_cast<LoadInst>(pair.first)) {
2526-
if (li->getOwnershipQualifier() == LoadOwnershipQualifier::Copy) {
2527-
// If we had a load [copy], borrow then we know that all of its destroys
2528-
// must have been destroy_value. So we can just gather up those
2529-
// destroy_value and use then to create a new load_borrow scope.
2530-
SILBuilderWithScope builder(li);
2531-
auto *lbi = builder.createLoadBorrow(li->getLoc(), li->getOperand());
2532-
// We use this auxillary list to avoid iterator invalidation of
2533-
// li->getConsumingUse();
2534-
StackList<DestroyValueInst *> toDelete(lbi->getFunction());
2535-
for (auto *consumeUse : li->getConsumingUses()) {
2536-
auto *dvi = cast<DestroyValueInst>(consumeUse->getUser());
2537-
SILBuilderWithScope destroyBuilder(dvi);
2538-
destroyBuilder.createEndBorrow(dvi->getLoc(), lbi);
2539-
toDelete.push_back(dvi);
2540-
changed = true;
2541-
}
2542-
while (!toDelete.empty())
2543-
toDelete.pop_back_val()->eraseFromParent();
2544-
2545-
li->replaceAllUsesWith(lbi);
2546-
li->eraseFromParent();
2547-
continue;
2526+
// If we had a load -> load_borrow then we know that all of its destroys
2527+
// must have been destroy_value. So we can just gather up those
2528+
// destroy_value and use then to create a new load_borrow scope.
2529+
SILBuilderWithScope builder(li);
2530+
auto *lbi = builder.createLoadBorrow(li->getLoc(), li->getOperand());
2531+
// We use this auxillary list to avoid iterator invalidation of
2532+
// li->getConsumingUse();
2533+
StackList<DestroyValueInst *> toDelete(lbi->getFunction());
2534+
for (auto *consumeUse : li->getConsumingUses()) {
2535+
auto *dvi = cast<DestroyValueInst>(consumeUse->getUser());
2536+
SILBuilderWithScope destroyBuilder(dvi);
2537+
destroyBuilder.createEndBorrow(dvi->getLoc(), lbi);
2538+
toDelete.push_back(dvi);
2539+
changed = true;
25482540
}
2541+
while (!toDelete.empty())
2542+
toDelete.pop_back_val()->eraseFromParent();
2543+
2544+
li->replaceAllUsesWith(lbi);
2545+
li->eraseFromParent();
2546+
continue;
25492547
}
25502548

25512549
llvm::dbgs() << "Borrow: " << *pair.first;

lib/SILOptimizer/Mandatory/MoveOnlyDeinitInsertion.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,21 @@ static bool performTransform(SILFunction &fn) {
7777
auto subMap =
7878
astType->getContextSubstitutionMap(nom->getModuleContext(), nom);
7979
SILBuilderWithScope builder(dvi);
80+
81+
SILValue value = dvi->getOperand();
82+
auto conv = deinitFunc->getConventionsInContext();
83+
if (conv.getSILArgumentConvention(conv.getSILArgIndexOfSelf())
84+
.isIndirectConvention()) {
85+
auto *asi =
86+
builder.createAllocStack(dvi->getLoc(), value->getType());
87+
builder.emitStoreValueOperation(dvi->getLoc(), value, asi,
88+
StoreOwnershipQualifier::Init);
89+
value = asi;
90+
}
8091
auto *funcRef = builder.createFunctionRef(dvi->getLoc(), deinitFunc);
81-
builder.createApply(dvi->getLoc(), funcRef, subMap,
82-
dvi->getOperand());
92+
builder.createApply(dvi->getLoc(), funcRef, subMap, value);
93+
if (isa<AllocStackInst>(value))
94+
builder.createDeallocStack(dvi->getLoc(), value);
8395
dvi->eraseFromParent();
8496
changed = true;
8597
continue;
@@ -103,9 +115,15 @@ static bool performTransform(SILFunction &fn) {
103115
auto *funcRef = builder.createFunctionRef(dai->getLoc(), deinitFunc);
104116
auto subMap = destroyType.getASTType()->getContextSubstitutionMap(
105117
nom->getModuleContext(), nom);
106-
auto loadedValue = builder.emitLoadValueOperation(
107-
dai->getLoc(), dai->getOperand(), LoadOwnershipQualifier::Take);
108-
builder.createApply(dai->getLoc(), funcRef, subMap, loadedValue);
118+
119+
auto conv = deinitFunc->getConventionsInContext();
120+
auto argConv =
121+
conv.getSILArgumentConvention(conv.getSILArgIndexOfSelf());
122+
SILValue value = dai->getOperand();
123+
if (!argConv.isIndirectConvention())
124+
value = builder.emitLoadValueOperation(
125+
dai->getLoc(), dai->getOperand(), LoadOwnershipQualifier::Take);
126+
builder.createApply(dai->getLoc(), funcRef, subMap, value);
109127
dai->eraseFromParent();
110128
changed = true;
111129
continue;

lib/SILOptimizer/Mandatory/MoveOnlyDiagnostics.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ void DiagnosticEmitter::emitObjectGuaranteedDiagnostic(
203203
// See if we have any closure capture uses and emit a better diagnostic.
204204
if (getCanonicalizer().hasPartialApplyConsumingUse()) {
205205
diagnose(astContext, markedValue,
206-
diag::sil_movechecking_guaranteed_value_captured_by_closure,
206+
diag::sil_movechecking_borrowed_parameter_captured_by_closure,
207207
varName);
208208
emitObjectDiagnosticsForPartialApplyUses(varName);
209209
registerDiagnosticEmitted(markedValue);

lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,10 @@ class SerializeSILPass : public SILModuleTransform {
472472
for (auto &VT : M.getVTables()) {
473473
VT->setSerialized(IsNotSerialized);
474474
}
475+
476+
for (auto &Deinit : M.getMoveOnlyDeinits()) {
477+
Deinit->setSerialized(IsNotSerialized);
478+
}
475479
}
476480

477481
public:

lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,7 +1042,7 @@ bool CanonicalizeOSSALifetime::computeLiveness() {
10421042
// Step 1: compute liveness
10431043
if (!computeCanonicalLiveness()) {
10441044
LLVM_DEBUG(llvm::errs() << "Failed to compute canonical liveness?!\n");
1045-
invalidateLiveness();
1045+
clear();
10461046
return false;
10471047
}
10481048
if (accessBlockAnalysis) {
@@ -1076,7 +1076,7 @@ void CanonicalizeOSSALifetime::rewriteLifetimes() {
10761076
// Step 6: rewrite copies and delete extra destroys
10771077
rewriteCopies();
10781078

1079-
invalidateLiveness();
1079+
clear();
10801080
consumes.clear();
10811081
}
10821082

0 commit comments

Comments
 (0)