Skip to content

[5.9] MoveOnlyAddressChecker: Confine analysis to current formal access. #64864

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 1 commit into from
Apr 3, 2023
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
6 changes: 0 additions & 6 deletions lib/SILGen/SILGenConstructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,8 +558,6 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {

ManagedValue selfLV =
maybeEmitValueOfLocalVarDecl(selfDecl, AccessKind::ReadWrite);
if (!selfLV)
selfLV = maybeEmitAddressForBoxOfLocalVarDecl(selfDecl, selfDecl);
assert(selfLV);

// Emit the prolog.
Expand Down Expand Up @@ -1223,10 +1221,6 @@ static ManagedValue emitSelfForMemberInit(SILGenFunction &SGF, SILLocation loc,
SGFContext::AllowImmediatePlusZero)
.getAsSingleValue(SGF, loc);
} else {
// First see if we have a variable that is boxed without a value.
if (auto value = SGF.maybeEmitAddressForBoxOfLocalVarDecl(loc, selfDecl))
return value;
// Otherwise, emit the address directly.
return SGF.emitAddressOfLocalVarDecl(loc, selfDecl, selfFormalType,
SGFAccessKind::Write);
}
Expand Down
11 changes: 3 additions & 8 deletions lib/SILGen/SILGenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,8 +533,7 @@ class LocalVariableInitialization : public SingleBufferInitialization {
}
}

if (!Box->getType().isBoxedNonCopyableType(Box->getFunction()))
Addr = SGF.B.createProjectBox(decl, Box, 0);
Addr = SGF.B.createProjectBox(decl, Box, 0);

// Push a cleanup to destroy the local variable. This has to be
// inactive until the variable is initialized.
Expand Down Expand Up @@ -583,10 +582,7 @@ class LocalVariableInitialization : public SingleBufferInitialization {
/// decl to.
assert(SGF.VarLocs.count(decl) == 0 && "Already emitted the local?");

if (Addr)
SGF.VarLocs[decl] = SILGenFunction::VarLoc::get(Addr, Box);
else
SGF.VarLocs[decl] = SILGenFunction::VarLoc::getForBox(Box);
SGF.VarLocs[decl] = SILGenFunction::VarLoc::get(Addr, Box);

SingleBufferInitialization::finishInitialization(SGF);
assert(!DidFinish &&
Expand Down Expand Up @@ -651,8 +647,7 @@ class LetValueInitialization : public Initialization {
// If this is a let with an initializer or bound value, we only need a
// buffer if the type is address only or is noncopyable.
//
// For noncopyable types, we always need to box them and eagerly
// reproject.
// For noncopyable types, we always need to box them.
needsTemporaryBuffer =
(lowering->isAddressOnly() && SGF.silConv.useLoweredAddresses()) ||
lowering->getLoweredType().isPureMoveOnly();
Expand Down
4 changes: 2 additions & 2 deletions lib/SILGen/SILGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ void SILGenFunction::emitCaptures(SILLocation loc,
// Get an address value for a SILValue if it is address only in an type
// expansion context without opaque archetype substitution.
auto getAddressValue = [&](VarLoc entryVarLoc) -> SILValue {
SILValue entryValue = entryVarLoc.getValueOrBoxedValue(*this, vd);
SILValue entryValue = entryVarLoc.value;
if (SGM.M.useLoweredAddresses()
&& SGM.Types
.getTypeLowering(
Expand All @@ -383,7 +383,7 @@ void SILGenFunction::emitCaptures(SILLocation loc,
case CaptureKind::Constant: {
// let declarations.
auto &tl = getTypeLowering(valueType);
SILValue Val = Entry.getValueOrBoxedValue(*this);
SILValue Val = Entry.value;
bool eliminateMoveOnlyWrapper =
Val->getType().isMoveOnlyWrapped() &&
!vd->getInterfaceType()->is<SILMoveOnlyWrappedType>();
Expand Down
22 changes: 0 additions & 22 deletions lib/SILGen/SILGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -436,25 +436,6 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
Result.box = box;
return Result;
}

static VarLoc getForBox(SILValue box) {
VarLoc Result;
Result.value = SILValue();
Result.box = box;
return Result;
}

/// Return either the value if we have one or if we only have a box, project
/// our a new box address and return that.
SILValue getValueOrBoxedValue(SILGenFunction &SGF,
SILLocation loc = SILLocation::invalid()) {
if (value)
return value;
assert(box);
if (loc.isNull())
loc = SGF.CurrentSILLoc;
return SGF.B.createProjectBox(loc, box, 0);
}
};

/// VarLocs - Entries in this map are generated when a PatternBindingDecl is
Expand Down Expand Up @@ -1541,9 +1522,6 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
ManagedValue maybeEmitValueOfLocalVarDecl(
VarDecl *var, AccessKind accessKind);

ManagedValue maybeEmitAddressForBoxOfLocalVarDecl(SILLocation loc,
VarDecl *var);

/// Produce an RValue for a reference to the specified declaration,
/// with the given type and in response to the specified expression. Try to
/// emit into the specified SGFContext to avoid copies (when provided).
Expand Down
70 changes: 22 additions & 48 deletions lib/SILGen/SILGenLValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1090,18 +1090,27 @@ namespace {
ManagedValue base) && override {
assert(!base && "value component must be root of lvalue path");

// See if we have a noncopyable address from a project_box or global, we
// always eagerly reproject out.
// See if we have a noncopyable address from a project_box or global.
if (Value.getType().isAddress() && Value.getType().isMoveOnly()) {
SILValue addr = Value.getValue();
if (isa<ProjectBoxInst>(addr) || isa<GlobalAddrInst>(addr)) {
auto box = dyn_cast<ProjectBoxInst>(addr);
if (box || isa<GlobalAddrInst>(addr)) {
if (Enforcement)
addr = enterAccessScope(SGF, loc, base, addr, getTypeData(),
getAccessKind(), *Enforcement,
takeActorIsolation());
addr = SGF.B.createMarkMustCheckInst(
loc, addr,
MarkMustCheckInst::CheckKind::AssignableButNotConsumable);
// LValue accesses to a `let` box are only ever going to make through
// definite initialization if they are initializations, which don't
// require checking since there's no former value to potentially
// misuse yet.
if (!box || box->getOperand()->getType().castTo<SILBoxType>()
->getLayout()->isMutable()) {
addr = SGF.B.createMarkMustCheckInst(
loc, addr,
isReadAccess(getAccessKind())
? MarkMustCheckInst::CheckKind::NoConsumeOrAssign
: MarkMustCheckInst::CheckKind::AssignableButNotConsumable);
}
return ManagedValue::forLValue(addr);
}
}
Expand Down Expand Up @@ -3009,11 +3018,8 @@ void LValue::addNonMemberVarComponent(SILGenFunction &SGF, SILLocation loc,
auto astAccessKind = mapAccessKind(this->AccessKind);
auto address = SGF.maybeEmitValueOfLocalVarDecl(Storage, astAccessKind);

// The only other case that should get here is a global variable or a
// noncopyable value in a box.
// The only other case that should get here is a global variable.
if (!address) {
address = SGF.maybeEmitAddressForBoxOfLocalVarDecl(Loc, Storage);
if (!address)
address = SGF.emitGlobalVariableRef(Loc, Storage, ActorIso);
} else {
assert((!ActorIso || Storage->isTopLevelGlobal()) &&
Expand Down Expand Up @@ -3056,26 +3062,6 @@ void LValue::addNonMemberVarComponent(SILGenFunction &SGF, SILLocation loc,
emitter.emitUsingStrategy(strategy);
}

ManagedValue
SILGenFunction::maybeEmitAddressForBoxOfLocalVarDecl(SILLocation loc,
VarDecl *var) {
auto It = VarLocs.find(var);

// Wasn't a box.
if (It == VarLocs.end())
return ManagedValue();

SILValue value = It->second.value;
SILValue box = It->second.box;

// We only want to do this if we only have a box without a value.
if (!box || value)
return ManagedValue();

SILValue addr = B.createProjectBox(loc, box, 0);
return ManagedValue::forLValue(addr);
}

ManagedValue
SILGenFunction::maybeEmitValueOfLocalVarDecl(
VarDecl *var, AccessKind accessKind) {
Expand All @@ -3084,13 +3070,7 @@ SILGenFunction::maybeEmitValueOfLocalVarDecl(
if (It != VarLocs.end()) {
SILValue ptr = It->second.value;

// If we do not have an actual value stored, then we must have a box.
if (!ptr) {
assert(It->second.box);
return ManagedValue();
}

// If this has an address, return it. By-value let's have no address.
// If this has an address, return it. By-value let bindings have no address.
if (ptr->getType().isAddress())
return ManagedValue::forLValue(ptr);

Expand All @@ -3101,7 +3081,7 @@ SILGenFunction::maybeEmitValueOfLocalVarDecl(
return ManagedValue::forUnmanaged(ptr);
}

// Otherwise, it's non-local, not stored, or a box.
// Otherwise, it's non-local or not stored.
return ManagedValue();
}

Expand All @@ -3116,9 +3096,6 @@ SILGenFunction::emitAddressOfLocalVarDecl(SILLocation loc, VarDecl *var,
assert(!var->isAsyncLet() && "async let does not have an address");

auto address = maybeEmitValueOfLocalVarDecl(var, astAccessKind);
if (!address)
address = maybeEmitAddressForBoxOfLocalVarDecl(loc, var);
assert(address);
assert(address.isLValue());
return address;
}
Expand All @@ -3141,12 +3118,7 @@ RValue SILGenFunction::emitRValueForNonMemberVarDecl(SILLocation loc,

// If our localValue is a closure captured box of a noncopyable type, project
// it out eagerly and insert a no_consume_or_assign constraint.
ManagedValue localValue;
if (auto localAddr = maybeEmitAddressForBoxOfLocalVarDecl(loc, var)) {
localValue = localAddr;
} else {
localValue = maybeEmitValueOfLocalVarDecl(var, AccessKind::Read);
}
ManagedValue localValue = maybeEmitValueOfLocalVarDecl(var, AccessKind::Read);

// If this VarDecl is represented as an address, emit it as an lvalue, then
// perform a load to get the rvalue.
Expand All @@ -3169,9 +3141,11 @@ RValue SILGenFunction::emitRValueForNonMemberVarDecl(SILLocation loc,
SILAccessKind::Read);

if (accessAddr->getType().isMoveOnly()) {
// When loading an rvalue, we should never need to modify the place
// we're loading from.
accessAddr = B.createMarkMustCheckInst(
loc, accessAddr,
MarkMustCheckInst::CheckKind::AssignableButNotConsumable);
MarkMustCheckInst::CheckKind::NoConsumeOrAssign);
}

auto propagateRValuePastAccess = [&](RValue &&rvalue) {
Expand Down
10 changes: 5 additions & 5 deletions lib/SILGen/SILGenPattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2708,7 +2708,7 @@ static void switchCaseStmtSuccessCallback(SILGenFunction &SGF,
// Emit a debug description for the variable, nested within a scope
// for the pattern match.
SILDebugVariable dbgVar(vd->isLet(), /*ArgNo=*/0);
SGF.B.emitDebugDescription(vd, v.getValueOrBoxedValue(SGF), dbgVar);
SGF.B.emitDebugDescription(vd, v.value, dbgVar);
}
}
}
Expand Down Expand Up @@ -2748,7 +2748,7 @@ static void switchCaseStmtSuccessCallback(SILGenFunction &SGF,
if (!var->hasName() || var->getName() != expected->getName())
continue;

SILValue value = SGF.VarLocs[var].getValueOrBoxedValue(SGF);
SILValue value = SGF.VarLocs[var].value;
SILType type = value->getType();

// If we have an address-only type, initialize the temporary
Expand Down Expand Up @@ -3008,7 +3008,7 @@ void SILGenFunction::emitSwitchFallthrough(FallthroughStmt *S) {
}

auto varLoc = VarLocs[var];
SILValue value = varLoc.getValueOrBoxedValue(*this);
SILValue value = varLoc.value;

if (value->getType().isAddressOnly(F)) {
context->Emission.emitAddressOnlyInitialization(expected, value);
Expand Down Expand Up @@ -3074,7 +3074,7 @@ void SILGenFunction::emitCatchDispatch(DoCatchStmt *S, ManagedValue exn,
// Emit a debug description of the incoming arg, nested within the scope
// for the pattern match.
SILDebugVariable dbgVar(vd->isLet(), /*ArgNo=*/0);
B.emitDebugDescription(vd, v.getValueOrBoxedValue(*this), dbgVar);
B.emitDebugDescription(vd, v.value, dbgVar);
}
}
}
Expand Down Expand Up @@ -3121,7 +3121,7 @@ void SILGenFunction::emitCatchDispatch(DoCatchStmt *S, ManagedValue exn,
if (!var->hasName() || var->getName() != expected->getName())
continue;

SILValue value = VarLocs[var].getValueOrBoxedValue(*this);
SILValue value = VarLocs[var].value;
SILType type = value->getType();

// If we have an address-only type, initialize the temporary
Expand Down
17 changes: 6 additions & 11 deletions lib/SILGen/SILGenProlog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -674,10 +674,9 @@ class ArgumentInitHelper {
SGF.emitManagedRValueWithCleanup(box);

// We manually set calledCompletedUpdate to true since we want to use
// VarLoc::getForBox and use the debug info from the box rather than
// insert a custom debug_value.
// the debug info from the box rather than insert a custom debug_value.
calledCompletedUpdate = true;
SGF.VarLocs[pd] = SILGenFunction::VarLoc::getForBox(box);
SGF.VarLocs[pd] = SILGenFunction::VarLoc::get(destAddr, box);
return;
}

Expand Down Expand Up @@ -947,14 +946,10 @@ static void emitCaptureArguments(SILGenFunction &SGF,
auto *box = SGF.F.begin()->createFunctionArgument(
SILType::getPrimitiveObjectType(boxTy), VD);
box->setClosureCapture(true);
if (box->getType().getSILBoxFieldType(&SGF.F, 0).isMoveOnly()) {
SGF.VarLocs[VD] = SILGenFunction::VarLoc::getForBox(box);
} else {
SILValue addr = SGF.B.createProjectBox(VD, box, 0);
SGF.VarLocs[VD] = SILGenFunction::VarLoc::get(addr, box);
SILDebugVariable DbgVar(VD->isLet(), ArgNo);
SGF.B.createDebugValueAddr(Loc, addr, DbgVar);
}
SILValue addr = SGF.B.createProjectBox(VD, box, 0);
SGF.VarLocs[VD] = SILGenFunction::VarLoc::get(addr, box);
SILDebugVariable DbgVar(VD->isLet(), ArgNo);
SGF.B.createDebugValueAddr(Loc, addr, DbgVar);
break;
}
case CaptureKind::Immutable:
Expand Down
3 changes: 1 addition & 2 deletions lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2337,8 +2337,7 @@ void LifetimeChecker::updateInstructionForInitState(unsigned UseID) {
if (auto *mmci =
dyn_cast<MarkMustCheckInst>(stripAccessMarkers(AI->getDest()))) {
if (mmci->getCheckKind() ==
MarkMustCheckInst::CheckKind::AssignableButNotConsumable &&
isa<RefElementAddrInst>(stripAccessMarkers(mmci->getOperand()))) {
MarkMustCheckInst::CheckKind::AssignableButNotConsumable) {
mmci->setCheckKind(
MarkMustCheckInst::CheckKind::InitableButNotConsumable);
}
Expand Down
Loading