diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp index aa3210cdc4f6c..ef04a93528021 100644 --- a/lib/SILGen/SILGenConstructor.cpp +++ b/lib/SILGen/SILGenConstructor.cpp @@ -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. @@ -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); } diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp index 9db9e9ac92a6e..199bf353f3371 100644 --- a/lib/SILGen/SILGenDecl.cpp +++ b/lib/SILGen/SILGenDecl.cpp @@ -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. @@ -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 && @@ -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(); diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp index ca518d5d1edf8..f9828231882cc 100644 --- a/lib/SILGen/SILGenFunction.cpp +++ b/lib/SILGen/SILGenFunction.cpp @@ -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( @@ -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(); diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h index 3b61126807228..c33284cdfcdca 100644 --- a/lib/SILGen/SILGenFunction.h +++ b/lib/SILGen/SILGenFunction.h @@ -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 @@ -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). diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp index 275a27c0fdf56..57a11eb5a135a 100644 --- a/lib/SILGen/SILGenLValue.cpp +++ b/lib/SILGen/SILGenLValue.cpp @@ -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(addr) || isa(addr)) { + auto box = dyn_cast(addr); + if (box || isa(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() + ->getLayout()->isMutable()) { + addr = SGF.B.createMarkMustCheckInst( + loc, addr, + isReadAccess(getAccessKind()) + ? MarkMustCheckInst::CheckKind::NoConsumeOrAssign + : MarkMustCheckInst::CheckKind::AssignableButNotConsumable); + } return ManagedValue::forLValue(addr); } } @@ -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()) && @@ -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) { @@ -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); @@ -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(); } @@ -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; } @@ -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. @@ -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) { diff --git a/lib/SILGen/SILGenPattern.cpp b/lib/SILGen/SILGenPattern.cpp index 85a61e3a24101..db49dcc3cf466 100644 --- a/lib/SILGen/SILGenPattern.cpp +++ b/lib/SILGen/SILGenPattern.cpp @@ -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); } } } @@ -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 @@ -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); @@ -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); } } } @@ -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 diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp index e10791acb7598..5993dde99742b 100644 --- a/lib/SILGen/SILGenProlog.cpp +++ b/lib/SILGen/SILGenProlog.cpp @@ -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; } @@ -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: diff --git a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp index 9d7a6bb88ce97..66f717aa3a121 100644 --- a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp +++ b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp @@ -2337,8 +2337,7 @@ void LifetimeChecker::updateInstructionForInitState(unsigned UseID) { if (auto *mmci = dyn_cast(stripAccessMarkers(AI->getDest()))) { if (mmci->getCheckKind() == - MarkMustCheckInst::CheckKind::AssignableButNotConsumable && - isa(stripAccessMarkers(mmci->getOperand()))) { + MarkMustCheckInst::CheckKind::AssignableButNotConsumable) { mmci->setCheckKind( MarkMustCheckInst::CheckKind::InitableButNotConsumable); } diff --git a/lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp b/lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp index 14403c4d1ee8a..04ea3963c0953 100644 --- a/lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp +++ b/lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp @@ -477,32 +477,14 @@ static bool isInOutDefThatNeedsEndOfFunctionLiveness(MarkMustCheckInst *markedAd } } - // See if we have an assignable_but_not_consumable from a project_box + - // function_argument. In this case, the value must be live at the end of the - // use, similar to an inout parameter. - // - // TODO: Rather than using a terminator, we might be able to use the - // end_access of the access marker instead. That would slightly change the - // model and this is semantically ok today. + // See if we have an assignable_but_not_consumable from a formal access. + // In this case, the value must be live at the end of the + // access, similar to an inout parameter. if (markedAddr->getCheckKind() == MarkMustCheckInst::CheckKind::AssignableButNotConsumable) { - if (auto *pbi = dyn_cast(stripAccessMarkers(operand))) { - if (auto *fArg = dyn_cast(pbi->getOperand())) { - if (!fArg->isClosureCapture()) - return false; - LLVM_DEBUG(llvm::dbgs() << "Found inout arg: " << *fArg); - return true; - } - } - - if (isa(stripAccessMarkers(operand))) - return true; - - if (isa(stripAccessMarkers(operand))) + if (isa(operand)) { return true; - - if (auto *rei = dyn_cast(stripAccessMarkers(operand))) - return true; + } } @@ -1135,12 +1117,25 @@ struct CopiedLoadBorrowEliminationVisitor : public AccessUseVisitor { StackList targets; CopiedLoadBorrowEliminationVisitor(SILFunction *fn) - : AccessUseVisitor(AccessUseType::Overlapping, + : AccessUseVisitor(AccessUseType::Inner, NestedAccessType::IgnoreAccessBegin), fn(fn), targets(fn) {} bool visitUse(Operand *op, AccessUseType useTy) override { - LLVM_DEBUG(llvm::dbgs() << "CopiedLBElim. Visiting: " << *op->getUser()); + LLVM_DEBUG( + llvm::dbgs() << "CopiedLBElim visiting "; + switch (useTy) { + case AccessUseType::Exact: + llvm::dbgs() << "exact "; + break; + case AccessUseType::Inner: + llvm::dbgs() << "inner "; + break; + case AccessUseType::Overlapping: + llvm::dbgs() << "overlapping"; + break; + } + llvm::dbgs() << " use: " << *op->getUser()); auto *lbi = dyn_cast(op->getUser()); if (!lbi) return true; @@ -1278,7 +1273,7 @@ struct GatherUsesVisitor : public AccessUseVisitor { UseState &useState, MarkMustCheckInst *markedValue, DiagnosticEmitter &diagnosticEmitter, SSAPrunedLiveness &gatherUsesLiveness) - : AccessUseVisitor(AccessUseType::Overlapping, + : AccessUseVisitor(AccessUseType::Inner, NestedAccessType::IgnoreAccessBegin), moveChecker(moveChecker), useState(useState), markedValue(markedValue), diagnosticEmitter(diagnosticEmitter), liveness(gatherUsesLiveness) {} @@ -1351,7 +1346,19 @@ bool GatherUsesVisitor::visitUse(Operand *op, AccessUseType useTy) { // For convenience, grab the user of op. auto *user = op->getUser(); - LLVM_DEBUG(llvm::dbgs() << "Visiting user: " << *user); + LLVM_DEBUG( + switch (useTy) { + case AccessUseType::Exact: + llvm::dbgs() << "Visiting exact user: "; + break; + case AccessUseType::Inner: + llvm::dbgs() << "Visiting inner user: "; + break; + case AccessUseType::Overlapping: + llvm::dbgs() << "Visiting overlapping user: "; + break; + } + llvm::dbgs() << *user); // First check if we have init/reinit. These are quick/simple. if (::memInstMustInitialize(op)) { @@ -1408,15 +1415,15 @@ bool GatherUsesVisitor::visitUse(Operand *op, AccessUseType useTy) { return true; if (auto *di = dyn_cast(user)) { - // Make sure that our debug_value is always on our root value. If not, we - // have something we don't understand and should bail. This ensures we can - // always hoist the debug_value to our mark_must_check. This ensures that by - // marking debug_value later as requiring liveness, we do not change our - // liveness calculation since values are always live at the mark_must_check. - if (di->getOperand() != getRootAddress()) - return false; - - useState.debugValue = di; + // Save the debug_value if it is attached directly to this mark_must_check. + // If the underlying storage we're checking is immutable, then the access + // being checked is not confined to an explicit access, but every other + // use of the storage must also be immutable, so it is fine if we see + // debug_values or other uses that aren't directly related to the current + // marked use; they will have to behave compatibly anyway. + if (di->getOperand() == getRootAddress()) { + useState.debugValue = di; + } return true; } @@ -2286,7 +2293,7 @@ bool MoveOnlyAddressCheckerPImpl::performSingleCheck( SWIFT_DEFER { diagnosticEmitter.clearUsesWithDiagnostic(); }; unsigned diagCount = diagnosticEmitter.getDiagnosticCount(); - auto accessPathWithBase = AccessPathWithBase::compute(markedAddress); + auto accessPathWithBase = AccessPathWithBase::computeInScope(markedAddress); auto accessPath = accessPathWithBase.accessPath; if (!accessPath.isValid()) { LLVM_DEBUG(llvm::dbgs() << "Invalid access path: " << *markedAddress); diff --git a/lib/SILOptimizer/Mandatory/MoveOnlyDiagnostics.cpp b/lib/SILOptimizer/Mandatory/MoveOnlyDiagnostics.cpp index 1f9481327db3a..2f5c1db7a5ec4 100644 --- a/lib/SILOptimizer/Mandatory/MoveOnlyDiagnostics.cpp +++ b/lib/SILOptimizer/Mandatory/MoveOnlyDiagnostics.cpp @@ -670,12 +670,7 @@ void DiagnosticEmitter::emitAddressEscapingClosureCaptureLoadedAndConsumed( sil_moveonlychecker_notconsumable_but_assignable_was_consumed_classfield_let); Optional diag; - if (markedValue->getCheckKind() == - MarkMustCheckInst::CheckKind::NoConsumeOrAssign) { - // We only use no consume or assign if we have a promoted let box. - diag = diag:: - sil_moveonlychecker_notconsumable_but_assignable_was_consumed_classfield_let; - } else if (auto *reai = dyn_cast(operand)) { + if (auto *reai = dyn_cast(operand)) { auto *field = reai->getField(); if (field->isLet()) { diag = diag:: diff --git a/test/Interpreter/moveonly_escaping_definite_initialization.swift b/test/Interpreter/moveonly_escaping_definite_initialization.swift new file mode 100644 index 0000000000000..6fb520ae94f42 --- /dev/null +++ b/test/Interpreter/moveonly_escaping_definite_initialization.swift @@ -0,0 +1,71 @@ +// RUN: %target-run-simple-swift | %FileCheck %s +// REQUIRES: executable_test + +@_moveOnly +struct MO { + var value: Int + + func use() {} + + deinit { print("destroying \(value)") } +} + +var closure: () -> () = {} +var counter = 42 + +func foo(goUp: Bool) { + let mo: MO + + if goUp { + counter += 1 + mo = MO(value: counter) + } else { + counter -= 1 + mo = MO(value: counter) + } + + mo.use() + + closure = { print("captured \(mo.value)") } +} + +// CHECK: starting +print("starting") +// CHECK-NEXT: captured 43 +foo(goUp: true) +closure() +// CHECK-NEXT: destroying 43 +// CHECK-NEXT: captured 44 +foo(goUp: true) +closure() +// CHECK-NEXT: destroying 44 +// CHECK-NEXT: captured 43 +foo(goUp: false) +closure() +// CHECK-NEXT: destroying 43 +closure = {} + +// CHECK-NEXT: starting bar +print("starting bar") +func bar() { + var y: MO + + y = MO(value: 17) + // CHECK-NEXT: destroying 17 + y = MO(value: 38) + + closure = { y = MO(value: 679) } + + y.use() +} +bar() +// CHECK-NEXT: destroying 38 +closure() +// CHECK-NEXT: done with bar +print("done with bar") +// CHECK-NEXT: destroying 679 +closure = {} + +// CHECK-NEXT: done +print("done") + diff --git a/test/SILGen/forget.swift b/test/SILGen/forget.swift index c2ef35d8545ac..daecc55f2fcf5 100644 --- a/test/SILGen/forget.swift +++ b/test/SILGen/forget.swift @@ -18,10 +18,9 @@ func invokedDeinit() {} // CHECK-LABEL: sil hidden [ossa] @$s4test9MaybeFileOAASivg // CHECK: [[SELF_BOX:%.*]] = alloc_box ${ let MaybeFile }, let, name "self", argno 1 - // CHECK: project_box - // CHECK: store {{.*}} to [init] // CHECK: [[SELF_REF:%.*]] = project_box [[SELF_BOX]] : ${ let MaybeFile }, 0 - // CHECK: [[SELF_MMC:%.*]] = mark_must_check [assignable_but_not_consumable] [[SELF_REF]] : $*MaybeFile + // CHECK: store {{.*}} to [init] + // CHECK: [[SELF_MMC:%.*]] = mark_must_check [no_consume_or_assign] [[SELF_REF]] : $*MaybeFile // CHECK: [[SELF_VAL:%.*]] = load [copy] [[SELF_MMC]] : $*MaybeFile // CHECK: switch_enum [[SELF_VAL]] : $MaybeFile, case #MaybeFile.some!enumelt: bb1, case #MaybeFile.none!enumelt: bb2 // @@ -46,12 +45,10 @@ func invokedDeinit() {} // CHECK-LABEL: sil hidden [ossa] @$s4test4FileV14takeDescriptorSiyF // CHECK: [[SELF_BOX:%.*]] = alloc_box ${ let File }, let, name "self", argno 1 - // CHECK: project_box + // CHECK: [[SELF_REF:%.*]] = project_box [[SELF_BOX]] : ${ let File }, 0 // CHECK: store {{.*}} to [init] - // CHECK: project_box // CHECK: load_borrow {{.*}} : $*File - // CHECK: [[SELF_REF:%.*]] = project_box [[SELF_BOX]] : ${ let File }, 0 - // CHECK: [[SELF_MMC:%.*]] = mark_must_check [assignable_but_not_consumable] [[SELF_REF]] : $*File + // CHECK: [[SELF_MMC:%.*]] = mark_must_check [no_consume_or_assign] [[SELF_REF]] : $*File // CHECK: [[SELF_VAL:%.*]] = load [copy] [[SELF_MMC]] : $*File // CHECK: end_lifetime [[SELF_VAL]] : $File @@ -83,14 +80,14 @@ func invokedDeinit() {} // CHECK: [[SELF_BOX:%.*]] = alloc_box ${ var PointerTree }, var, name "self" // CHECK: [[MUI:%.*]] = mark_uninitialized [rootself] [[SELF_BOX]] : ${ var PointerTree } // CHECK: [[SELF:%.*]] = begin_borrow [lexical] [[MUI]] : ${ var PointerTree } +// CHECK: [[SELF_PTR:%.*]] = project_box [[SELF]] : ${ var PointerTree }, 0 // .. skip to the conditional test .. // CHECK: [[SHOULD_THROW:%.*]] = struct_extract {{.*}} : $Bool, #Bool._value // CHECK: cond_br [[SHOULD_THROW]], bb1, bb2 // // CHECK: bb1: -// CHECK: [[SELF_PTR:%.*]] = project_box [[SELF]] : ${ var PointerTree }, 0 // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[SELF_PTR]] : $*PointerTree -// CHECK: [[MMC:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS]] : $*PointerTree +// CHECK: [[MMC:%.*]] = mark_must_check [no_consume_or_assign] [[ACCESS]] : $*PointerTree // CHECK: [[COPIED_SELF:%.*]] = load [copy] [[MMC]] : $*PointerTree // CHECK: end_access [[ACCESS]] : $*PointerTree // CHECK: ([[LEFT:%.*]], [[FILE:%.*]], {{%.*}}, [[RIGHT:%.*]]) = destructure_struct [[COPIED_SELF]] : $PointerTree @@ -160,15 +157,15 @@ final class Wallet { } // As of now, we allow reinitialization after forget. Not sure if this is intended. // CHECK-LABEL: sil hidden [ossa] @$s4test6TicketO8inWalletAcA0D0CSg_tcfC + // CHECK: [[SELF_REF:%.*]] = project_box [[SELF_BOX:%.*]] : ${ var Ticket }, 0 // CHECK: switch_enum {{.*}} : $Optional, case #Optional.some!enumelt: bb2, case #Optional.none!enumelt: bb1 - // CHECK: bb2(%22 : @owned $Wallet): + // CHECK: bb2({{%.*}} : @owned $Wallet): // CHECK: br bb3 // >> now we begin the destruction sequence, which involves pattern matching on self to destroy its innards // CHECK: bb3: - // CHECK: [[SELF_REF:%.*]] = project_box [[SELF_BOX:%.*]] : ${ var Ticket }, 0 - // CHECK: [[SELF_ACCESS:%.*]] = begin_access [read] [unknown] %27 : $*Ticket - // CHECK: [[SELF_MMC:%.*]] = mark_must_check [assignable_but_not_consumable] %28 : $*Ticket - // CHECK: [[SELF_COPY:%.*]] = load [copy] %29 : $*Ticket + // CHECK: [[SELF_ACCESS:%.*]] = begin_access [read] [unknown] {{%.*}} : $*Ticket + // CHECK: [[SELF_MMC:%.*]] = mark_must_check [no_consume_or_assign] [[SELF_ACCESS]] + // CHECK: [[SELF_COPY:%.*]] = load [copy] [[SELF_MMC]] : $*Ticket // CHECK: end_access [[SELF_ACCESS:%.*]] : $*Ticket // CHECK: switch_enum [[SELF_COPY]] : $Ticket, case #Ticket.empty!enumelt: bb4, case #Ticket.within!enumelt: bb5 // CHECK: bb4: @@ -178,9 +175,8 @@ final class Wallet { // CHECK: br bb6 // >> from here on we are reinitializing self. // CHECK: bb6: - // CHECK: [[SELF_REF2:%.*]] = project_box [[SELF_BOX]] : ${ var Ticket }, 0 // CHECK: [[NEW_SELF_VAL:%.*]] = enum $Ticket, #Ticket.within!enumelt, {{.*}} : $Wallet - // CHECK: [[SELF_ACCESS2:%.*]] = begin_access [modify] [unknown] [[SELF_REF2]] : $*Ticket + // CHECK: [[SELF_ACCESS2:%.*]] = begin_access [modify] [unknown] [[SELF_REF]] : $*Ticket // CHECK: [[SELF_MMC2:%.*]] = mark_must_check [assignable_but_not_consumable] [[SELF_ACCESS2]] : $*Ticket // CHECK: assign [[NEW_SELF_VAL]] to [[SELF_MMC2]] : $*Ticket // CHECK: end_access [[SELF_ACCESS2]] : $*Ticket diff --git a/test/SILGen/moveonly.swift b/test/SILGen/moveonly.swift index 88a6ea05734df..49c755b2c1662 100644 --- a/test/SILGen/moveonly.swift +++ b/test/SILGen/moveonly.swift @@ -90,8 +90,7 @@ public func useNonTrivialStruct(_ s: __shared NonTrivialStruct) { // CHECK: [[BOX:%.*]] = alloc_box // CHECK: [[PROJECT:%.*]] = project_box [[BOX]] // CHECK: store [[ARG]] to [init] [[PROJECT]] -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] -// CHECK: mark_must_check [assignable_but_not_consumable] [[PROJECT]] +// CHECK: mark_must_check [no_consume_or_assign] [[PROJECT]] // CHECK: } // end sil function '$s8moveonly24useNonTrivialOwnedStructyyAA0cdF0VnF' public func useNonTrivialOwnedStruct(_ s: __owned NonTrivialStruct) { borrowVal(s) @@ -123,8 +122,7 @@ public func useNonTrivialEnum(_ s: __shared NonTrivialEnum) { // CHECK: [[BOX:%.*]] = alloc_box // CHECK: [[PROJECT:%.*]] = project_box [[BOX]] // CHECK: store [[ARG]] to [init] [[PROJECT]] -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] -// CHECK: mark_must_check [assignable_but_not_consumable] [[PROJECT]] +// CHECK: mark_must_check [no_consume_or_assign] [[PROJECT]] // CHECK: } // end sil function '$s8moveonly22useNonTrivialOwnedEnumyyAA0cdF0OnF' public func useNonTrivialOwnedEnum(_ s: __owned NonTrivialEnum) { borrowVal(s) @@ -176,13 +174,12 @@ extension NonTrivialEnum { // CHECK-LABEL: sil hidden [ossa] @$s8moveonly27blackHoleLetInitialization1yyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box // CHECK: [[BORROWED_BOX:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // CHECK: [[FN:%.*]] = function_ref @$s8moveonly2FDVACycfC : // CHECK: [[X:%.*]] = apply [[FN]]( -// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // CHECK: store [[X]] to [init] [[PROJECT]] // -// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] -// CHECK: [[MARKED:%.*]] = mark_must_check [assignable_but_not_consumable] [[PROJECT]] +// CHECK: [[MARKED:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] // CHECK: [[VALUE:%.*]] = load [copy] [[MARKED]] // CHECK: move_value [[VALUE]] // CHECK: } // end sil function '$s8moveonly27blackHoleLetInitialization1yyF' @@ -194,13 +191,12 @@ func blackHoleLetInitialization1() { // CHECK-LABEL: sil hidden [ossa] @$s8moveonly27blackHoleLetInitialization2yyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box // CHECK: [[BORROWED_BOX:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // CHECK: [[FN:%.*]] = function_ref @$s8moveonly2FDVACycfC : // CHECK: [[X:%.*]] = apply [[FN]]( -// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // CHECK: store [[X]] to [init] [[PROJECT]] // -// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] -// CHECK: [[MARKED:%.*]] = mark_must_check [assignable_but_not_consumable] [[PROJECT]] +// CHECK: [[MARKED:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] // CHECK: [[VALUE:%.*]] = load [copy] [[MARKED]] // CHECK: move_value [[VALUE]] // CHECK: } // end sil function '$s8moveonly27blackHoleLetInitialization2yyF' @@ -214,16 +210,14 @@ func blackHoleLetInitialization2() { // CHECK: [[BOX_BORROW:%.*]] = begin_borrow [lexical] [[BOX]] // CHECK: [[PROJECT_BOX:%.*]] = project_box [[BOX_BORROW]] // CHECK: store {{%.*}} to [init] [[PROJECT_BOX]] -// CHECK: [[PROJECT_BOX:%.*]] = project_box [[BOX_BORROW]] // CHECK: [[FN:%.*]] = function_ref @$s8moveonly2FDVACycfC : // CHECK: [[X:%.*]] = apply [[FN]]( // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT_BOX]] // CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS]] // CHECK: assign [[X]] to [[MARKED_ADDR]] // -// CHECK: [[PROJECT_BOX:%.*]] = project_box [[BOX_BORROW]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PROJECT_BOX]] -// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [assignable_but_not_consumable] [[READ]] +// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [no_consume_or_assign] [[READ]] // CHECK: [[LD:%.*]] = load [copy] [[MARKED_ADDR]] // CHECK: [[CONSUME:%.*]] = move_value [[LD]] // CHECK: } // end sil function '$s8moveonly27blackHoleVarInitialization1yyF' @@ -239,16 +233,14 @@ func blackHoleVarInitialization1() { // CHECK: [[PROJECT_BOX:%.*]] = project_box [[BOX_BORROW]] // CHECK: store {{%.*}} to [init] [[PROJECT_BOX]] // -// CHECK: [[PROJECT_BOX:%.*]] = project_box [[BOX_BORROW]] // CHECK: [[FN:%.*]] = function_ref @$s8moveonly2FDVACycfC : // CHECK: [[X:%.*]] = apply [[FN]]( // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT_BOX]] // CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS]] // CHECK: assign [[X]] to [[MARKED_ADDR]] // -// CHECK: [[PROJECT_BOX:%.*]] = project_box [[BOX_BORROW]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PROJECT_BOX]] -// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [assignable_but_not_consumable] [[READ]] +// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [no_consume_or_assign] [[READ]] // CHECK: [[LD:%.*]] = load [copy] [[MARKED_ADDR]] // CHECK: [[CONSUME:%.*]] = move_value [[LD]] // CHECK: } // end sil function '$s8moveonly27blackHoleVarInitialization2yyF' @@ -264,16 +256,14 @@ func blackHoleVarInitialization2() { // CHECK: [[PROJECT_BOX:%.*]] = project_box [[BOX_BORROW]] // CHECK: store {{%.*}} to [init] [[PROJECT_BOX]] // -// CHECK: [[PROJECT_BOX:%.*]] = project_box [[BOX_BORROW]] // CHECK: [[FN:%.*]] = function_ref @$s8moveonly2FDVACycfC : // CHECK: [[X:%.*]] = apply [[FN]]( // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT_BOX]] // CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS]] // CHECK: assign [[X]] to [[MARKED_ADDR]] // -// CHECK: [[PROJECT_BOX:%.*]] = project_box [[BOX_BORROW]] // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PROJECT_BOX]] -// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [assignable_but_not_consumable] [[READ]] +// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [no_consume_or_assign] [[READ]] // CHECK: [[LD:%.*]] = load [copy] [[MARKED_ADDR]] // CHECK: [[CONSUME:%.*]] = move_value [[LD]] // CHECK: } // end sil function '$s8moveonly27blackHoleVarInitialization3yyF' @@ -294,8 +284,7 @@ func blackHoleVarInitialization3() { // CHECK: [[PROJECT:%.*]] = project_box [[BORROW_BOX]] // CHECK: store {{%.*}} to [init] [[PROJECT]] // -// CHECK: [[PROJECT:%.*]] = project_box [[BORROW_BOX]] -// CHECK: [[CLS:%.*]] = mark_must_check [assignable_but_not_consumable] [[PROJECT]] +// CHECK: [[CLS:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] // CHECK: [[BORROW:%.*]] = load_borrow [[CLS]] // CHECK: [[FN:%.*]] = function_ref @$s8moveonly9borrowValyyAA2FDVhF : // CHECK: apply [[FN]]([[BORROW]]) @@ -309,19 +298,15 @@ func borrowObjectFunctionCall() { // CHECK-LABEL: sil hidden [ossa] @$s8moveonly29moveOnlyStructNonConsumingUseyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box // CHECK: [[BORROWED_BOX:%.*]] = begin_borrow [lexical] [[BOX]] -// -// TODO: We should have a begin_access [init] here probably. // CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // CHECK: store {{%.*}} to [init] [[PROJECT]] // -// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT]] // CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [assignable_but_not_consumable] // CHECK: assign {{%.*}} to [[MARKED_ADDR]] // -// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] -// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS]] +// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [no_consume_or_assign] [[ACCESS]] // CHECK: [[BORROW:%.*]] = load_borrow [[MARKED_ADDR]] // CHECK: [[FN:%.*]] = function_ref @$s8moveonly9borrowValyyAA16NonTrivialStructVhF : // CHECK: apply [[FN]]([[BORROW]]) @@ -337,15 +322,13 @@ func moveOnlyStructNonConsumingUse() { // CHECK-LABEL: sil hidden [ossa] @$s8moveonly018moveOnlyStructMovecD15NonConsumingUseyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box // CHECK: [[BORROW_BOX:%.*]] = begin_borrow [lexical] +// CHECK: [[PROJECT:%.*]] = project_box [[BORROW_BOX]] // -// CHECK: project_box // CHECK: store -// CHECK: project_box // CHECK: assign // -// CHECK: [[PROJECT:%.*]] = project_box [[BORROW_BOX]] // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] -// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS]] +// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [no_consume_or_assign] [[ACCESS]] // CHECK: [[GEP:%.*]] = struct_element_addr [[MARKED_ADDR]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialStruct2 // CHECK: [[BORROW:%.*]] = load_borrow [[GEP]] // CHECK: [[FN:%.*]] = function_ref @$s8moveonly9borrowValyyAA17NonTrivialStruct2VhF : $@convention(thin) (@guaranteed NonTrivialStruct2) -> () @@ -362,15 +345,13 @@ func moveOnlyStructMoveOnlyStructNonConsumingUse() { // CHECK-LABEL: sil hidden [ossa] @$s8moveonly018moveOnlyStructMovecD28CopyableKlassNonConsumingUseyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box // CHECK: [[BORROW_BOX:%.*]] = begin_borrow [lexical] -// -// CHECK: project_box +// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] + // CHECK: store -// CHECK: project_box // CHECK: assign // -// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] -// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS]] +// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [no_consume_or_assign] [[ACCESS]] // CHECK: [[GEP1:%.*]] = struct_element_addr [[MARKED_ADDR]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialStruct2 // CHECK: [[GEP2:%.*]] = struct_element_addr [[GEP1]] : $*NonTrivialStruct2, #NonTrivialStruct2.copyableKlass // CHECK: [[COPY:%.*]] = load [copy] [[GEP2]] : $*CopyableKlass @@ -388,17 +369,15 @@ func moveOnlyStructMoveOnlyStructCopyableKlassNonConsumingUse() { // CHECK-LABEL: sil hidden [ossa] @$s8moveonly021moveOnlyStructSetMoveC5FieldyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box ${ var NonTrivialStruct } // CHECK: [[BORROW_BOX:%.*]] = begin_borrow [lexical] [[BOX]] -// CHECK: project_box +// CHECK: [[PROJECT1:%.*]] = project_box [[BORROW_BOX]] // CHECK: store // // CHECK: [[BOX2:%.*]] = alloc_box ${ let NonTrivialStruct2 } // CHECK: [[BORROW_BOX2:%.*]] = begin_borrow [lexical] [[BOX2]] -// CHECK: project_box +// CHECK: [[PROJECT2:%.*]] = project_box [[BORROW_BOX2]] // CHECK: store // -// CHECK: [[PROJECT1:%.*]] = project_box [[BORROW_BOX]] -// CHECK: [[PROJECT2:%.*]] = project_box [[BORROW_BOX2]] -// CHECK: [[MARKED_ADDR2:%.*]] = mark_must_check [assignable_but_not_consumable] [[PROJECT2]] : $*NonTrivialStruct2 +// CHECK: [[MARKED_ADDR2:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT2]] : $*NonTrivialStruct2 // CHECK: [[CONSUMED_LET:%.*]] = load [copy] [[MARKED_ADDR2]] : $*NonTrivialStruct2 // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT1]] // CHECK: [[MARKED_ADDR1:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS]] @@ -415,15 +394,13 @@ func moveOnlyStructSetMoveOnlyField() { // CHECK-LABEL: sil hidden [ossa] @$s8moveonly022moveOnlyStructCopyableD15NonConsumingUseyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box // CHECK: [[BORROW_BOX:%.*]] = begin_borrow [lexical] +// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // -// CHECK: project_box // CHECK: store -// CHECK: project_box // CHECK: assign // -// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] -// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS]] +// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [no_consume_or_assign] [[ACCESS]] // CHECK: [[GEP:%.*]] = struct_element_addr [[MARKED_ADDR]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialCopyableStruct // CHECK: [[COPY:%.*]] = load [copy] [[GEP]] : $*NonTrivialCopyableStruct // CHECK: end_access [[ACCESS]] @@ -440,15 +417,13 @@ func moveOnlyStructCopyableStructNonConsumingUse() { // CHECK-LABEL: sil hidden [ossa] @$s8moveonly022moveOnlyStructCopyabledE20KlassNonConsumingUseyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box // CHECK: [[BORROW_BOX:%.*]] = begin_borrow [lexical] +// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // -// CHECK: project_box // CHECK: store -// CHECK: project_box // CHECK: assign // -// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] -// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS]] +// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [no_consume_or_assign] [[ACCESS]] // CHECK: [[GEP1:%.*]] = struct_element_addr [[MARKED_ADDR]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialCopyableStruct // CHECK: [[GEP2:%.*]] = struct_element_addr [[GEP1]] : $*NonTrivialCopyableStruct, #NonTrivialCopyableStruct.copyableKlass // CHECK: [[COPY:%.*]] = load [copy] [[GEP2]] : $*CopyableKlass @@ -466,15 +441,13 @@ func moveOnlyStructCopyableStructCopyableKlassNonConsumingUse() { // CHECK-LABEL: sil hidden [ossa] @$s8moveonly022moveOnlyStructCopyabledeD15NonConsumingUseyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box // CHECK: [[BORROW_BOX:%.*]] = begin_borrow [lexical] +// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // -// CHECK: project_box // CHECK: store -// CHECK: project_box // CHECK: assign // -// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] -// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS]] +// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [no_consume_or_assign] [[ACCESS]] // CHECK: [[GEP1:%.*]] = struct_element_addr [[MARKED_ADDR]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialCopyableStruct // CHECK: [[GEP2:%.*]] = struct_element_addr [[GEP1]] : $*NonTrivialCopyableStruct, #NonTrivialCopyableStruct.nonTrivialCopyableStruct2 // CHECK: [[COPY:%.*]] = load [copy] [[GEP2]] : $*NonTrivialCopyableStruct2 @@ -492,15 +465,13 @@ func moveOnlyStructCopyableStructCopyableStructNonConsumingUse() { // CHECK-LABEL: sil hidden [ossa] @$s8moveonly022moveOnlyStructCopyablededE20KlassNonConsumingUseyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box // CHECK: [[BORROW_BOX:%.*]] = begin_borrow [lexical] +// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // -// CHECK: project_box // CHECK: store -// CHECK: project_box // CHECK: assign // -// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] -// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS]] +// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [no_consume_or_assign] [[ACCESS]] // CHECK: [[GEP1:%.*]] = struct_element_addr [[MARKED_ADDR]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialCopyableStruct // CHECK: [[GEP2:%.*]] = struct_element_addr [[GEP1]] : $*NonTrivialCopyableStruct, #NonTrivialCopyableStruct.nonTrivialCopyableStruct2 // CHECK: [[GEP3:%.*]] = struct_element_addr [[GEP2]] : $*NonTrivialCopyableStruct2, #NonTrivialCopyableStruct2.copyableKlass @@ -521,15 +492,13 @@ func moveOnlyStructCopyableStructCopyableStructCopyableKlassNonConsumingUse() { // CHECK-LABEL: sil hidden [ossa] @$s8moveonly022moveOnlyStructCopyabledede9KlassMovecF15NonConsumingUseyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box // CHECK: [[BORROW_BOX:%.*]] = begin_borrow [lexical] +// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // -// CHECK: project_box // CHECK: store -// CHECK: project_box // CHECK: assign // -// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] -// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS]] +// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [no_consume_or_assign] [[ACCESS]] // CHECK: [[GEP1:%.*]] = struct_element_addr [[MARKED_ADDR]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialCopyableStruct // CHECK: [[GEP2:%.*]] = struct_element_addr [[GEP1]] : $*NonTrivialCopyableStruct, #NonTrivialCopyableStruct.nonTrivialCopyableStruct2 // CHECK: [[GEP3:%.*]] = struct_element_addr [[GEP2]] : $*NonTrivialCopyableStruct2, #NonTrivialCopyableStruct2.copyableKlass @@ -679,7 +648,7 @@ func enumSwitchTest1(_ e: __shared EnumSwitchTests.E) { // CHECK-LABEL: sil hidden [ossa] @$s8moveonly16testGlobalBorrowyyF : $@convention(thin) () -> () { // CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly9varGlobalAA16NonTrivialStructVvp : // CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[GLOBAL]] -// CHECK: [[MARKED_GLOBAL:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS]] +// CHECK: [[MARKED_GLOBAL:%.*]] = mark_must_check [no_consume_or_assign] [[ACCESS]] // CHECK: [[LOADED_VAL:%.*]] = load_borrow [[MARKED_GLOBAL]] : $*NonTrivialStruct // CHECK: apply {{%.*}}([[LOADED_VAL]]) // CHECK: end_borrow [[LOADED_VAL]] @@ -687,7 +656,7 @@ func enumSwitchTest1(_ e: __shared EnumSwitchTests.E) { // // CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly9varGlobalAA16NonTrivialStructVvp : // CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[GLOBAL]] -// CHECK: [[MARKED_GLOBAL:%.*]] = mark_must_check [assignable_but_not_consumable] [[ACCESS]] +// CHECK: [[MARKED_GLOBAL:%.*]] = mark_must_check [no_consume_or_assign] [[ACCESS]] // CHECK: [[GEP:%.*]] = struct_element_addr [[MARKED_GLOBAL]] // CHECK: [[LOADED_VAL:%.*]] = load_borrow [[GEP]] : $*NonTrivialStruct2 // CHECK: apply {{%.*}}([[LOADED_VAL]]) @@ -695,13 +664,13 @@ func enumSwitchTest1(_ e: __shared EnumSwitchTests.E) { // CHECK: end_access [[ACCESS]] // // CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly9letGlobalAA16NonTrivialStructVvp : -// CHECK: [[MARKED_GLOBAL:%.*]] = mark_must_check [assignable_but_not_consumable] [[GLOBAL]] +// CHECK: [[MARKED_GLOBAL:%.*]] = mark_must_check [no_consume_or_assign] [[GLOBAL]] // CHECK: [[LOADED_VAL:%.*]] = load_borrow [[MARKED_GLOBAL]] : $*NonTrivialStruct // CHECK: apply {{%.*}}([[LOADED_VAL]]) // CHECK: end_borrow [[LOADED_VAL]] // // CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly9letGlobalAA16NonTrivialStructVvp : -// CHECK: [[MARKED_GLOBAL:%.*]] = mark_must_check [assignable_but_not_consumable] [[GLOBAL]] +// CHECK: [[MARKED_GLOBAL:%.*]] = mark_must_check [no_consume_or_assign] [[GLOBAL]] // FIXME: this copy probably shouldn't be here when accessing through the letGlobal, but maybe it's cleaned up? // CHECK: [[LOADED_VAL:%.*]] = load [copy] [[MARKED_GLOBAL]] : $*NonTrivialStruct // CHECK: [[LOADED_BORROWED_VAL:%.*]] = begin_borrow [[LOADED_VAL]] @@ -734,12 +703,12 @@ func testGlobalBorrow() { // CHECK: end_access [[ACCESS]] // // CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly9letGlobalAA16NonTrivialStructVvp : -// CHECK: [[MARKED_GLOBAL:%.*]] = mark_must_check [assignable_but_not_consumable] [[GLOBAL]] +// CHECK: [[MARKED_GLOBAL:%.*]] = mark_must_check [no_consume_or_assign] [[GLOBAL]] // CHECK: [[LOADED_VAL:%.*]] = load [copy] [[MARKED_GLOBAL]] // CHECK: apply {{%.*}}([[LOADED_VAL]]) // // CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly9letGlobalAA16NonTrivialStructVvp : -// CHECK: [[MARKED_GLOBAL:%.*]] = mark_must_check [assignable_but_not_consumable] [[GLOBAL]] +// CHECK: [[MARKED_GLOBAL:%.*]] = mark_must_check [no_consume_or_assign] [[GLOBAL]] // CHECK: [[LOADED_VAL:%.*]] = load [copy] [[MARKED_GLOBAL]] // CHECK: [[LOADED_BORROWED_VAL:%.*]] = begin_borrow [[LOADED_VAL]] // CHECK: [[LOADED_GEP:%.*]] = struct_extract [[LOADED_BORROWED_VAL]] @@ -802,7 +771,6 @@ func testGlobalAssign() { // CHECK: store [[ARG]] to [init] [[PROJECT]] // // CHECK: [[FN:%.*]] = function_ref @$s8moveonly28checkMarkMustCheckOnCaptured1xyAA2FDVn_tFyyXEfU_ : $@convention(thin) @substituted <τ_0_0> (@guaranteed FD) -> @out τ_0_0 for <()> -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] // CHECK: [[MARK:%.*]] = mark_must_check [assignable_but_not_consumable] [[PROJECT]] // CHECK: [[VALUE:%.*]] = load [copy] [[MARK]] // CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FN]]([[VALUE]]) diff --git a/test/SILGen/moveonly_deinits.swift b/test/SILGen/moveonly_deinits.swift index 3030c12549da0..031d991d6bb67 100644 --- a/test/SILGen/moveonly_deinits.swift +++ b/test/SILGen/moveonly_deinits.swift @@ -83,11 +83,11 @@ var value: Bool { false } // SILGEN-LABEL: sil [ossa] @$s16moveonly_deinits24testIntPairWithoutDeinityyF : $@convention(thin) () -> () { // SILGEN: [[BOX:%.*]] = alloc_box +// SILGEN: [[PROJECT:%.*]] = project_box [[BOX]] // SILGEN: cond_br {{%.*}}, bb1, bb2 // // SILGEN: bb1: -// SILGEN: [[PROJECT:%.*]] = project_box [[BOX]] -// SILGEN: [[MARKED:%.*]] = mark_must_check [assignable_but_not_consumable] [[PROJECT]] +// SILGEN: [[MARKED:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] // SILGEN: [[LOAD:%.*]] = load [copy] [[MARKED]] // SILGEN: apply {{%.*}}([[LOAD]]) // SILGEN: br bb3 @@ -132,11 +132,11 @@ public func testIntPairWithoutDeinit() { // SILGEN-LABEL: sil [ossa] @$s16moveonly_deinits21testIntPairWithDeinityyF : $@convention(thin) () -> () { // SILGEN: [[BOX:%.*]] = alloc_box +// SILGEN: [[PROJECT:%.*]] = project_box [[BOX]] // SILGEN: cond_br {{%.*}}, bb1, bb2 // // SILGEN: bb1: -// SILGEN: [[PROJECT:%.*]] = project_box [[BOX]] -// SILGEN: [[MARKED:%.*]] = mark_must_check [assignable_but_not_consumable] [[PROJECT]] +// SILGEN: [[MARKED:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] // SILGEN: [[LOAD:%.*]] = load [copy] [[MARKED]] // SILGEN: apply {{%.*}}([[LOAD]]) // SILGEN: br bb3 @@ -184,11 +184,11 @@ public func testIntPairWithDeinit() { // SILGEN-LABEL: sil [ossa] @$s16moveonly_deinits26testKlassPairWithoutDeinityyF : $@convention(thin) () -> () { // SILGEN: [[BOX:%.*]] = alloc_box // SILGEN: [[BORROWED_BOX:%.*]] = begin_borrow [lexical] [[BOX]] +// SILGEN: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // SILGEN: cond_br {{%.*}}, bb1, bb2 // // SILGEN: bb1: -// SILGEN: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] -// SILGEN: [[MARKED:%.*]] = mark_must_check [assignable_but_not_consumable] [[PROJECT]] +// SILGEN: [[MARKED:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] // SILGEN: [[LOAD:%.*]] = load [copy] [[MARKED]] // SILGEN: apply {{%.*}}([[LOAD]]) // SILGEN: br bb3 @@ -233,11 +233,11 @@ public func testKlassPairWithoutDeinit() { // SILGEN-LABEL: sil [ossa] @$s16moveonly_deinits23testKlassPairWithDeinityyF : $@convention(thin) () -> () { // SILGEN: [[BOX:%.*]] = alloc_box +// SILGEN: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // SILGEN: cond_br {{%.*}}, bb1, bb2 // // SILGEN: bb1: -// SILGEN: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] -// SILGEN: [[MARKED:%.*]] = mark_must_check [assignable_but_not_consumable] [[PROJECT]] +// SILGEN: [[MARKED:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] // SILGEN: [[LOAD:%.*]] = load [copy] [[MARKED]] // SILGEN: apply {{%.*}}([[LOAD]]) // SILGEN: br bb3 @@ -367,11 +367,11 @@ func consumeKlassEnumPairWithDeinit(_ x: __owned KlassEnumPairWithDeinit) { } // SILGEN-LABEL: sil [ossa] @$s16moveonly_deinits28testIntEnumPairWithoutDeinityyF : $@convention(thin) () -> () { // SILGEN: [[BOX:%.*]] = alloc_box +// SILGEN: [[PROJECT:%.*]] = project_box [[BOX]] // SILGEN: cond_br {{%.*}}, bb1, bb2 // // SILGEN: bb1: -// SILGEN: [[PROJECT:%.*]] = project_box [[BOX]] -// SILGEN: [[MARKED:%.*]] = mark_must_check [assignable_but_not_consumable] [[PROJECT]] +// SILGEN: [[MARKED:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] // SILGEN: [[LOAD:%.*]] = load [copy] [[MARKED]] // SILGEN: apply {{%.*}}([[LOAD]]) // SILGEN: br bb3 @@ -415,11 +415,11 @@ public func testIntEnumPairWithoutDeinit() { // SILGEN-LABEL: sil [ossa] @$s16moveonly_deinits25testIntEnumPairWithDeinityyF : $@convention(thin) () -> () { // SILGEN: [[BOX:%.*]] = alloc_box +// SILGEN: [[PROJECT:%.*]] = project_box [[BOX]] // SILGEN: cond_br {{%.*}}, bb1, bb2 // // SILGEN: bb1: -// SILGEN: [[PROJECT:%.*]] = project_box [[BOX]] -// SILGEN: [[MARKED:%.*]] = mark_must_check [assignable_but_not_consumable] [[PROJECT]] +// SILGEN: [[MARKED:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] // SILGEN: [[LOAD:%.*]] = load [copy] [[MARKED]] // SILGEN: apply {{%.*}}([[LOAD]]) // SILGEN: br bb3 @@ -465,11 +465,11 @@ public func testIntEnumPairWithDeinit() { // SILGEN-LABEL: sil [ossa] @$s16moveonly_deinits30testKlassEnumPairWithoutDeinityyF : $@convention(thin) () -> () { // SILGEN: [[BOX:%.*]] = alloc_box +// SILGEN: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // SILGEN: cond_br {{%.*}}, bb1, bb2 // // SILGEN: bb1: -// SILGEN: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] -// SILGEN: [[MARKED:%.*]] = mark_must_check [assignable_but_not_consumable] [[PROJECT]] +// SILGEN: [[MARKED:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] // SILGEN: [[LOAD:%.*]] = load [copy] [[MARKED]] // SILGEN: apply {{%.*}}([[LOAD]]) // SILGEN: br bb3 @@ -513,11 +513,11 @@ public func testKlassEnumPairWithoutDeinit() { // SILGEN-LABEL: sil [ossa] @$s16moveonly_deinits27testKlassEnumPairWithDeinityyF : $@convention(thin) () -> () { // SILGEN: [[BOX:%.*]] = alloc_box +// SILGEN: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] // SILGEN: cond_br {{%.*}}, bb1, bb2 // // SILGEN: bb1: -// SILGEN: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]] -// SILGEN: [[MARKED:%.*]] = mark_must_check [assignable_but_not_consumable] [[PROJECT]] +// SILGEN: [[MARKED:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] // SILGEN: [[LOAD:%.*]] = load [copy] [[MARKED]] // SILGEN: apply {{%.*}}([[LOAD]]) // SILGEN: br bb3 diff --git a/test/SILGen/moveonly_enum_literal.swift b/test/SILGen/moveonly_enum_literal.swift index 80ca7c4ac0e26..321e1eab08463 100644 --- a/test/SILGen/moveonly_enum_literal.swift +++ b/test/SILGen/moveonly_enum_literal.swift @@ -15,12 +15,11 @@ var value: Bool { false } // CHECK-LABEL: sil hidden [ossa] @$s21moveonly_enum_literal4testyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box -// CHECK: [[VALUE:%.*]] = enum $MoveOnlyIntPair, #MoveOnlyIntPair.lhs!enumelt, // CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[VALUE:%.*]] = enum $MoveOnlyIntPair, #MoveOnlyIntPair.lhs!enumelt, // CHECK: store [[VALUE]] to [init] [[PROJECT]] // -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] -// CHECK: [[MARKED_VALUE:%.*]] = mark_must_check [assignable_but_not_consumable] [[PROJECT]] +// CHECK: [[MARKED_VALUE:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] // CHECK: } // end sil function '$s21moveonly_enum_literal4testyyF' func test() { let x = MoveOnlyIntPair.lhs(5) diff --git a/test/SILOptimizer/moveonly_addresschecker.sil b/test/SILOptimizer/moveonly_addresschecker.sil index 8ab4b0a4c6996..8b4b27539b8ac 100644 --- a/test/SILOptimizer/moveonly_addresschecker.sil +++ b/test/SILOptimizer/moveonly_addresschecker.sil @@ -514,7 +514,7 @@ bb0: %10 = apply %9() : $@convention(thin) () -> @owned NonTrivialStruct %0 = global_addr @$s23moveonly_addresschecker9varGlobalAA16NonTrivialStructVvp : $*NonTrivialStruct %1 = begin_access [modify] [dynamic] %0 : $*NonTrivialStruct - %2 = mark_must_check [assignable_but_not_consumable] %0 : $*NonTrivialStruct + %2 = mark_must_check [assignable_but_not_consumable] %1 : $*NonTrivialStruct store %10 to [assign] %2 : $*NonTrivialStruct end_access %1 : $*NonTrivialStruct %8 = tuple () @@ -534,4 +534,4 @@ sil [ossa] @test_in_use : $@convention(thin) () -> () { dealloc_stack %0 : $*NonTrivialStruct %9999 = tuple () return %9999 : $() -} \ No newline at end of file +}