Skip to content

Commit 0b27fe9

Browse files
authored
Merge pull request #5692 from gottesmm/change_silgen_emit_qualified_loadstrong
[semantic-arc] Handle the rest of the unqualified mem opts in SILGen.
2 parents 64d6307 + dd03a9b commit 0b27fe9

File tree

109 files changed

+758
-715
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

109 files changed

+758
-715
lines changed

include/swift/SIL/SILBuilder.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,12 @@ class SILBuilder {
459459

460460
LoadInst *createLoad(SILLocation Loc, SILValue LV,
461461
LoadOwnershipQualifier Qualifier) {
462+
assert((Qualifier != LoadOwnershipQualifier::Unqualified) ||
463+
F.hasUnqualifiedOwnership() &&
464+
"Unqualified inst in qualified function");
465+
assert((Qualifier == LoadOwnershipQualifier::Unqualified) ||
466+
F.hasQualifiedOwnership() &&
467+
"Qualified inst in unqualified function");
462468
assert(LV->getType().isLoadable(F.getModule()));
463469
return insert(new (F.getModule())
464470
LoadInst(getSILDebugLocation(Loc), LV, Qualifier));
@@ -481,6 +487,12 @@ class SILBuilder {
481487

482488
StoreInst *createStore(SILLocation Loc, SILValue Src, SILValue DestAddr,
483489
StoreOwnershipQualifier Qualifier) {
490+
assert((Qualifier != StoreOwnershipQualifier::Unqualified) ||
491+
F.hasUnqualifiedOwnership() &&
492+
"Unqualified inst in qualified function");
493+
assert((Qualifier == StoreOwnershipQualifier::Unqualified) ||
494+
F.hasQualifiedOwnership() &&
495+
"Qualified inst in unqualified function");
484496
return insert(new (F.getModule()) StoreInst(getSILDebugLocation(Loc), Src,
485497
DestAddr, Qualifier));
486498
}

include/swift/SIL/SILValue.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,9 +301,11 @@ class OperandValueArrayRef {
301301
: Operands(operands) {}
302302

303303
/// A simple iterator adapter.
304-
class iterator {
304+
class iterator : public std::iterator<std::forward_iterator_tag,
305+
SILValue, ptrdiff_t> {
305306
const Operand *Ptr;
306307
public:
308+
iterator() = default;
307309
iterator(const Operand *ptr) : Ptr(ptr) {}
308310
SILValue operator*() const { assert(Ptr); return Ptr->get(); }
309311
SILValue operator->() const { return operator*(); }

lib/Parse/ParseSIL.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3996,16 +3996,18 @@ bool SILParser::parseSILBasicBlock(SILBuilder &B) {
39963996

39973997
bool AssumeUnqualifiedOwnershipWhenParsing =
39983998
F->getModule().getOptions().AssumeUnqualifiedOwnershipWhenParsing;
3999+
if (AssumeUnqualifiedOwnershipWhenParsing) {
4000+
F->setUnqualifiedOwnership();
4001+
}
39994002
do {
40004003
if (parseSILInstruction(BB, B))
40014004
return true;
40024005
// Evaluate how the just parsed instruction effects this functions Ownership
40034006
// Qualification. For more details, see the comment on the
40044007
// FunctionOwnershipEvaluator class.
40054008
SILInstruction *ParsedInst = &*BB->rbegin();
4006-
if (AssumeUnqualifiedOwnershipWhenParsing) {
4007-
F->setUnqualifiedOwnership();
4008-
} else if (!OwnershipEvaluator.evaluate(ParsedInst)) {
4009+
if (!AssumeUnqualifiedOwnershipWhenParsing &&
4010+
!OwnershipEvaluator.evaluate(ParsedInst)) {
40094011
P.diagnose(ParsedInst->getLoc().getSourceLoc(),
40104012
diag::found_unqualified_instruction_in_qualified_function,
40114013
F->getName());

lib/SIL/SILVerifier.cpp

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,33 +1123,30 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
11231123
case LoadOwnershipQualifier::Unqualified:
11241124
// We should not see loads with unqualified ownership when SILOwnership is
11251125
// enabled.
1126-
requireTrueAndSILOwnership(
1127-
this, F.hasUnqualifiedOwnership(),
1128-
"Load with unqualified ownership in a qualified function");
1126+
require(F.hasUnqualifiedOwnership(),
1127+
"Load with unqualified ownership in a qualified function");
11291128
break;
11301129
case LoadOwnershipQualifier::Copy:
11311130
case LoadOwnershipQualifier::Take:
1132-
requireTrueAndSILOwnership(
1133-
this, F.hasQualifiedOwnership(),
1134-
"Load with qualified ownership in an unqualified function");
1131+
require(F.hasQualifiedOwnership(),
1132+
"Load with qualified ownership in an unqualified function");
11351133
// TODO: Could probably make this a bit stricter.
11361134
require(!LI->getType().isTrivial(LI->getModule()),
11371135
"load [copy] or load [take] can only be applied to non-trivial "
11381136
"types");
11391137
break;
11401138
case LoadOwnershipQualifier::Trivial:
1141-
requireTrueAndSILOwnership(
1142-
this, F.hasQualifiedOwnership(),
1143-
"Load with qualified ownership in an unqualified function");
1139+
require(F.hasQualifiedOwnership(),
1140+
"Load with qualified ownership in an unqualified function");
11441141
require(LI->getType().isTrivial(LI->getModule()),
11451142
"A load with trivial ownership must load a trivial type");
11461143
break;
11471144
}
11481145
}
11491146

11501147
void checkLoadBorrowInst(LoadBorrowInst *LBI) {
1151-
requireTrueAndSILOwnership(
1152-
this, F.hasQualifiedOwnership(),
1148+
require(
1149+
F.hasQualifiedOwnership(),
11531150
"Inst with qualified ownership in a function that is not qualified");
11541151
require(LBI->getType().isObject(), "Result of load must be an object");
11551152
require(LBI->getType().isLoadable(LBI->getModule()),
@@ -1161,8 +1158,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
11611158
}
11621159

11631160
void checkEndBorrowInst(EndBorrowInst *EBI) {
1164-
requireTrueAndSILOwnership(
1165-
this, F.hasQualifiedOwnership(),
1161+
require(
1162+
F.hasQualifiedOwnership(),
11661163
"Inst with qualified ownership in a function that is not qualified");
11671164
// We allow for end_borrow to express relationships in between addresses and
11681165
// values, but we require that the types are the same ignoring value
@@ -1188,22 +1185,22 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
11881185
case StoreOwnershipQualifier::Unqualified:
11891186
// We should not see loads with unqualified ownership when SILOwnership is
11901187
// enabled.
1191-
requireTrueAndSILOwnership(this, F.hasUnqualifiedOwnership(),
1192-
"Invalid load with unqualified ownership");
1188+
require(F.hasUnqualifiedOwnership(),
1189+
"Qualified store in function with unqualified ownership?!");
11931190
break;
11941191
case StoreOwnershipQualifier::Init:
11951192
case StoreOwnershipQualifier::Assign:
1196-
requireTrueAndSILOwnership(
1197-
this, F.hasQualifiedOwnership(),
1193+
require(
1194+
F.hasQualifiedOwnership(),
11981195
"Inst with qualified ownership in a function that is not qualified");
11991196
// TODO: Could probably make this a bit stricter.
12001197
require(!SI->getSrc()->getType().isTrivial(SI->getModule()),
12011198
"store [init] or store [assign] can only be applied to "
12021199
"non-trivial types");
12031200
break;
12041201
case StoreOwnershipQualifier::Trivial:
1205-
requireTrueAndSILOwnership(
1206-
this, F.hasQualifiedOwnership(),
1202+
require(
1203+
F.hasQualifiedOwnership(),
12071204
"Inst with qualified ownership in a function that is not qualified");
12081205
require(SI->getSrc()->getType().isTrivial(SI->getModule()),
12091206
"A store with trivial ownership must store a trivial type");

lib/SIL/TypeLowering.cpp

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -494,8 +494,7 @@ namespace {
494494
public:
495495
void emitDestroyAddress(SILBuilder &B, SILLocation loc,
496496
SILValue addr) const override {
497-
SILValue value =
498-
B.createLoad(loc, addr, LoadOwnershipQualifier::Unqualified);
497+
SILValue value = emitLoad(B, loc, addr, LoadOwnershipQualifier::Take);
499498
emitDestroyValue(B, loc, value);
500499
}
501500

@@ -520,23 +519,29 @@ namespace {
520519

521520
SILValue emitLoadOfCopy(SILBuilder &B, SILLocation loc, SILValue addr,
522521
IsTake_t isTake) const override {
523-
return B.createLoad(loc, addr, LoadOwnershipQualifier::Unqualified);
522+
return emitLoad(B, loc, addr, LoadOwnershipQualifier::Trivial);
524523
}
525524

526525
void emitStoreOfCopy(SILBuilder &B, SILLocation loc,
527526
SILValue value, SILValue addr,
528527
IsInitialization_t isInit) const override {
529-
B.createStore(loc, value, addr, StoreOwnershipQualifier::Unqualified);
528+
emitStore(B, loc, value, addr, StoreOwnershipQualifier::Trivial);
530529
}
531530

532531
void emitStore(SILBuilder &B, SILLocation loc, SILValue value,
533532
SILValue addr, StoreOwnershipQualifier qual) const override {
534-
B.createStore(loc, value, addr, StoreOwnershipQualifier::Trivial);
533+
if (B.getFunction().hasQualifiedOwnership()) {
534+
B.createStore(loc, value, addr, StoreOwnershipQualifier::Trivial);
535+
return;
536+
}
537+
B.createStore(loc, value, addr, StoreOwnershipQualifier::Unqualified);
535538
}
536539

537540
SILValue emitLoad(SILBuilder &B, SILLocation loc, SILValue addr,
538541
LoadOwnershipQualifier qual) const override {
539-
return B.createLoad(loc, addr, LoadOwnershipQualifier::Trivial);
542+
if (B.getFunction().hasQualifiedOwnership())
543+
return B.createLoad(loc, addr, LoadOwnershipQualifier::Trivial);
544+
return B.createLoad(loc, addr, LoadOwnershipQualifier::Unqualified);
540545
}
541546

542547
void emitDestroyAddress(SILBuilder &B, SILLocation loc,
@@ -576,32 +581,57 @@ namespace {
576581

577582
SILValue emitLoadOfCopy(SILBuilder &B, SILLocation loc,
578583
SILValue addr, IsTake_t isTake) const override {
579-
SILValue value =
580-
B.createLoad(loc, addr, LoadOwnershipQualifier::Unqualified);
581-
if (!isTake)
582-
emitCopyValue(B, loc, value);
583-
return value;
584+
auto qual =
585+
isTake ? LoadOwnershipQualifier::Take : LoadOwnershipQualifier::Copy;
586+
return emitLoad(B, loc, addr, qual);
584587
}
585588

586589
void emitStoreOfCopy(SILBuilder &B, SILLocation loc,
587590
SILValue newValue, SILValue addr,
588591
IsInitialization_t isInit) const override {
589-
SILValue oldValue;
590-
if (!isInit)
591-
oldValue = B.createLoad(loc, addr, LoadOwnershipQualifier::Unqualified);
592-
B.createStore(loc, newValue, addr, StoreOwnershipQualifier::Unqualified);
593-
if (!isInit)
594-
emitDestroyValue(B, loc, oldValue);
592+
auto qual = isInit ? StoreOwnershipQualifier::Init
593+
: StoreOwnershipQualifier::Assign;
594+
emitStore(B, loc, newValue, addr, qual);
595595
}
596596

597597
void emitStore(SILBuilder &B, SILLocation loc, SILValue value,
598598
SILValue addr, StoreOwnershipQualifier qual) const override {
599-
B.createStore(loc, value, addr, qual);
599+
if (B.getFunction().hasQualifiedOwnership()) {
600+
B.createStore(loc, value, addr, qual);
601+
return;
602+
}
603+
604+
if (qual != StoreOwnershipQualifier::Assign) {
605+
B.createStore(loc, value, addr, StoreOwnershipQualifier::Unqualified);
606+
return;
607+
}
608+
609+
// If the ownership qualifier is [assign], then we need to eliminate the
610+
// old value.
611+
//
612+
// 1. Load old value.
613+
// 2. Store new value.
614+
// 3. Release old value.
615+
SILValue old =
616+
B.createLoad(loc, addr, LoadOwnershipQualifier::Unqualified);
617+
B.createStore(loc, value, addr, StoreOwnershipQualifier::Unqualified);
618+
B.emitDestroyValueOperation(loc, old);
600619
}
601620

602621
SILValue emitLoad(SILBuilder &B, SILLocation loc, SILValue addr,
603622
LoadOwnershipQualifier qual) const override {
604-
return B.createLoad(loc, addr, qual);
623+
if (B.getFunction().hasQualifiedOwnership())
624+
return B.createLoad(loc, addr, qual);
625+
626+
SILValue loadValue =
627+
B.createLoad(loc, addr, LoadOwnershipQualifier::Unqualified);
628+
629+
// If we do not have a copy, just return the value...
630+
if (qual != LoadOwnershipQualifier::Copy)
631+
return loadValue;
632+
633+
// Otherwise, emit the copy value operation.
634+
return B.emitCopyValueOperation(loc, loadValue);
605635
}
606636
};
607637

lib/SILGen/RValue.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ class ExplodeTupleValue
105105
// loaded. Except it's not really an invariant, because
106106
// argument emission likes to lie sometimes.
107107
if (eltTI.isLoadable()) {
108-
elt = gen.B.createLoad(loc, elt, LoadOwnershipQualifier::Unqualified);
108+
elt = eltTI.emitLoad(gen.B, loc, elt, LoadOwnershipQualifier::Take);
109109
}
110110
}
111111

lib/SILGen/SILGenApply.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,8 +1999,8 @@ namespace {
19991999

20002000
// If the value isn't address-only, go ahead and load.
20012001
if (!substTL.isAddressOnly()) {
2002-
auto load = gen.B.createLoad(loc, value.forward(gen),
2003-
LoadOwnershipQualifier::Unqualified);
2002+
auto load = substTL.emitLoad(gen.B, loc, value.forward(gen),
2003+
LoadOwnershipQualifier::Take);
20042004
value = gen.emitManagedRValueWithCleanup(load);
20052005
}
20062006

@@ -3908,14 +3908,14 @@ ManagedValue SILGenFunction::emitInjectEnum(SILLocation loc,
39083908
if (payloadMV) {
39093909
// If the payload was indirect, we already evaluated it and
39103910
// have a single value. Store it into the result.
3911-
B.createStore(loc, payloadMV.forward(*this), resultData,
3912-
StoreOwnershipQualifier::Unqualified);
3911+
B.emitStoreValueOperation(loc, payloadMV.forward(*this), resultData,
3912+
StoreOwnershipQualifier::Init);
39133913
} else if (payloadTL.isLoadable()) {
39143914
// The payload of this specific enum case might be loadable
39153915
// even if the overall enum is address-only.
39163916
payloadMV = std::move(payload).getAsSingleValue(*this, origFormalType);
3917-
B.createStore(loc, payloadMV.forward(*this), resultData,
3918-
StoreOwnershipQualifier::Unqualified);
3917+
B.emitStoreValueOperation(loc, payloadMV.forward(*this), resultData,
3918+
StoreOwnershipQualifier::Init);
39193919
} else {
39203920
// The payload is address-only. Evaluate it directly into
39213921
// the enum.
@@ -5573,7 +5573,7 @@ RValue SILGenFunction::emitDynamicMemberRefExpr(DynamicMemberRefExpr *e,
55735573
// Package up the result.
55745574
auto optResult = optTemp;
55755575
if (optTL.isLoadable())
5576-
optResult = B.createLoad(e, optResult, LoadOwnershipQualifier::Unqualified);
5576+
optResult = optTL.emitLoad(B, e, optResult, LoadOwnershipQualifier::Take);
55775577
return RValue(*this, e, emitManagedRValueWithCleanup(optResult, optTL));
55785578
}
55795579

@@ -5666,6 +5666,6 @@ RValue SILGenFunction::emitDynamicSubscriptExpr(DynamicSubscriptExpr *e,
56665666
// Package up the result.
56675667
auto optResult = optTemp;
56685668
if (optTL.isLoadable())
5669-
optResult = B.createLoad(e, optResult, LoadOwnershipQualifier::Unqualified);
5669+
optResult = optTL.emitLoad(B, e, optResult, LoadOwnershipQualifier::Take);
56705670
return RValue(*this, e, emitManagedRValueWithCleanup(optResult, optTL));
56715671
}

lib/SILGen/SILGenBuiltin.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -607,8 +607,7 @@ emitBuiltinCastReference(SILGenFunction &gen,
607607
return gen.emitManagedBufferWithCleanup(toAddr);
608608

609609
// Load the destination value.
610-
auto result =
611-
gen.B.createLoad(loc, toAddr, LoadOwnershipQualifier::Unqualified);
610+
auto result = toTL.emitLoad(gen.B, loc, toAddr, LoadOwnershipQualifier::Take);
612611
return gen.emitManagedRValueWithCleanup(result);
613612
}
614613

@@ -643,9 +642,7 @@ static ManagedValue emitBuiltinReinterpretCast(SILGenFunction &gen,
643642
// Load and retain the destination value if it's loadable. Leave the cleanup
644643
// on the original value since we don't know anything about it's type.
645644
if (toTL.isLoadable()) {
646-
SILValue val =
647-
gen.B.createLoad(loc, toAddr, LoadOwnershipQualifier::Unqualified);
648-
return gen.emitManagedRetain(loc, val, toTL);
645+
return gen.emitManagedLoadCopy(loc, toAddr, toTL);
649646
}
650647
// Leave the cleanup on the original value.
651648
if (toTL.isTrivial())

lib/SILGen/SILGenConstructor.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -275,11 +275,8 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
275275

276276
if (!lowering.isAddressOnly()) {
277277
// Otherwise, load and return the final 'self' value.
278-
selfValue =
279-
B.createLoad(cleanupLoc, selfLV, LoadOwnershipQualifier::Unqualified);
280-
281-
// Emit a retain of the loaded value, since we return it +1.
282-
selfValue = lowering.emitCopyValue(B, cleanupLoc, selfValue);
278+
selfValue = lowering.emitLoad(B, cleanupLoc, selfLV,
279+
LoadOwnershipQualifier::Copy);
283280

284281
// Inject the self value into an optional if the constructor is failable.
285282
if (ctor->getFailability() != OTK_None) {
@@ -582,8 +579,9 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
582579
if (NeedsBoxForSelf) {
583580
SILLocation prologueLoc = RegularLocation(ctor);
584581
prologueLoc.markAsPrologue();
585-
B.createStore(prologueLoc, selfArg, VarLocs[selfDecl].value,
586-
StoreOwnershipQualifier::Unqualified);
582+
// SEMANTIC ARC TODO: When the verifier is complete, review this.
583+
B.emitStoreValueOperation(prologueLoc, selfArg, VarLocs[selfDecl].value,
584+
StoreOwnershipQualifier::Init);
587585
} else {
588586
selfArg = B.createMarkUninitialized(selfDecl, selfArg, MUKind);
589587
VarLocs[selfDecl] = VarLoc::get(selfArg);
@@ -670,12 +668,19 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
670668
if (Expr *SI = ctor->getSuperInitCall())
671669
emitRValue(SI);
672670

673-
selfArg = B.createLoad(cleanupLoc, VarLocs[selfDecl].value,
674-
LoadOwnershipQualifier::Unqualified);
671+
selfArg = B.emitLoadValueOperation(cleanupLoc, VarLocs[selfDecl].value,
672+
LoadOwnershipQualifier::Copy);
673+
} else {
674+
// We have to do a retain because we are returning the pointer +1.
675+
//
676+
// SEMANTIC ARC TODO: When the verifier is complete, we will need to
677+
// change this to selfArg = B.emitCopyValueOperation(...). Currently due
678+
// to the way that SILGen performs folding of copy_value, destroy_value,
679+
// the returned selfArg may be deleted causing us to have a
680+
// dead-pointer. Instead just use the old self value since we have a
681+
// class.
682+
selfArg = B.emitCopyValueOperation(cleanupLoc, selfArg);
675683
}
676-
677-
// We have to do a retain because we are returning the pointer +1.
678-
selfArg = B.emitCopyValueOperation(cleanupLoc, selfArg);
679684

680685
// Inject the self value into an optional if the constructor is failable.
681686
if (ctor->getFailability() != OTK_None) {

lib/SILGen/SILGenConvert.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ ManagedValue SILGenFunction::emitUncheckedGetOptionalValueFrom(SILLocation loc,
250250

251251
if (optTL.isLoadable())
252252
payloadVal =
253-
B.createLoad(loc, payloadVal, LoadOwnershipQualifier::Unqualified);
253+
optTL.emitLoad(B, loc, payloadVal, LoadOwnershipQualifier::Take);
254254
}
255255

256256
// Produce a correctly managed value.

0 commit comments

Comments
 (0)