Skip to content

Commit 34ec32b

Browse files
committed
[semantic-arc] Handle the rest of the unqualified mem opts in SILGen.
Keep in mind that these are approximations that will not impact correctness since in all cases I ensured that the SIL will be the same after the OwnershipModelEliminator has run. The cases that I was unsure of I commented with SEMANTIC ARC TODO. Once we have the verifier any confusion that may have occurred here will be dealt with. rdar://28685236
1 parent 4ee4703 commit 34ec32b

File tree

105 files changed

+690
-691
lines changed

Some content is hidden

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

105 files changed

+690
-691
lines changed

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/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.

lib/SILGen/SILGenDecl.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ void TupleInitialization::copyOrInitValueInto(SILGenFunction &SGF,
9292
member = SGF.B.createTupleElementAddr(loc, value, i, fieldTy);
9393
if (!fieldTL.isAddressOnly())
9494
member =
95-
SGF.B.createLoad(loc, member, LoadOwnershipQualifier::Unqualified);
95+
fieldTL.emitLoad(SGF.B, loc, member, LoadOwnershipQualifier::Take);
9696
} else {
9797
member = SGF.B.createTupleExtract(loc, value, i, fieldTy);
9898
}
@@ -715,7 +715,7 @@ emitEnumMatch(ManagedValue value, EnumElementDecl *ElementDecl,
715715
// Load a loadable data value.
716716
if (eltTL.isLoadable())
717717
eltValue =
718-
SGF.B.createLoad(loc, eltValue, LoadOwnershipQualifier::Unqualified);
718+
eltTL.emitLoad(SGF.B, loc, eltValue, LoadOwnershipQualifier::Take);
719719
} else {
720720
// Otherwise, we're consuming this as a +1 value.
721721
value.forward(SGF);
@@ -728,9 +728,10 @@ emitEnumMatch(ManagedValue value, EnumElementDecl *ElementDecl,
728728
if (ElementDecl->isIndirect() || ElementDecl->getParentEnum()->isIndirect()) {
729729
SILValue boxedValue = SGF.B.createProjectBox(loc, eltMV.getValue(), 0);
730730
auto &boxedTL = SGF.getTypeLowering(boxedValue->getType());
731+
// SEMANTIC ARC TODO: Revisit this when the verifier is enabled.
731732
if (boxedTL.isLoadable())
732-
boxedValue = SGF.B.createLoad(loc, boxedValue,
733-
LoadOwnershipQualifier::Unqualified);
733+
boxedValue = boxedTL.emitLoad(SGF.B, loc, boxedValue,
734+
LoadOwnershipQualifier::Take);
734735

735736
// We must treat the boxed value as +0 since it may be shared. Copy it if
736737
// nontrivial.

lib/SILGen/SILGenDynamicCast.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ namespace {
140140
//emission.
141141
scalarOperandValue = operand.forward(SGF);
142142
if (scalarOperandValue->getType().isAddress()) {
143-
scalarOperandValue = SGF.B.createLoad(
144-
Loc, scalarOperandValue, LoadOwnershipQualifier::Unqualified);
143+
scalarOperandValue = SGF.B.emitLoadValueOperation(
144+
Loc, scalarOperandValue, LoadOwnershipQualifier::Take);
145145
}
146146
SGF.B.createCheckedCastBranch(Loc, /*exact*/ false, scalarOperandValue,
147147
origTargetTL.getLoweredType(),

lib/SILGen/SILGenExpr.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,21 @@ ManagedValue SILGenFunction::emitManagedRetain(SILLocation loc,
6363
return emitManagedRValueWithCleanup(v, lowering);
6464
}
6565

66+
ManagedValue SILGenFunction::emitManagedLoadCopy(SILLocation loc, SILValue v) {
67+
auto &lowering = getTypeLowering(v->getType().getSwiftRValueType());
68+
return emitManagedLoadCopy(loc, v, lowering);
69+
}
70+
71+
ManagedValue SILGenFunction::emitManagedLoadCopy(SILLocation loc, SILValue v,
72+
const TypeLowering &lowering) {
73+
assert(lowering.getLoweredType().getAddressType() == v->getType());
74+
v = lowering.emitLoadOfCopy(B, loc, v, IsNotTake);
75+
if (lowering.isTrivial())
76+
return ManagedValue::forUnmanaged(v);
77+
assert(!lowering.isAddressOnly() && "cannot retain an unloadable type");
78+
return emitManagedRValueWithCleanup(v, lowering);
79+
}
80+
6681
ManagedValue SILGenFunction::emitManagedRValueWithCleanup(SILValue v) {
6782
auto &lowering = getTypeLowering(v->getType());
6883
return emitManagedRValueWithCleanup(v, lowering);
@@ -3243,8 +3258,8 @@ class AutoreleasingWritebackComponent : public LogicalPathComponent {
32433258
RValue get(SILGenFunction &gen, SILLocation loc,
32443259
ManagedValue base, SGFContext c) && override {
32453260
// Load the value at +0.
3246-
SILValue owned = gen.B.createLoad(loc, base.getUnmanagedValue(),
3247-
LoadOwnershipQualifier::Unqualified);
3261+
SILValue owned = gen.B.createLoadBorrow(loc, base.getUnmanagedValue());
3262+
32483263
// Convert it to unowned.
32493264
auto refType = owned->getType().getSwiftRValueType();
32503265
auto unownedType = SILType::getPrimitiveObjectType(

0 commit comments

Comments
 (0)