@@ -472,7 +472,7 @@ class DestroyLocalVariable : public Cleanup {
472472 Var->print (llvm::errs ());
473473 llvm::errs () << " \n " ;
474474 if (isActive ()) {
475- auto loc = SGF.VarLocs [Var];
475+ auto & loc = SGF.VarLocs [Var];
476476 assert ((loc.box || loc.value ) && " One of box or value should be set" );
477477 if (loc.box ) {
478478 llvm::errs () << " Box: " << loc.box << " \n " ;
@@ -664,7 +664,8 @@ class LocalVariableInitialization : public SingleBufferInitialization {
664664 // / decl to.
665665 assert (SGF.VarLocs .count (decl) == 0 && " Already emitted the local?" );
666666
667- SGF.VarLocs [decl] = SILGenFunction::VarLoc::get (Addr, Box);
667+ SGF.VarLocs [decl] = SILGenFunction::VarLoc (Addr,
668+ SILAccessEnforcement::Dynamic, Box);
668669
669670 SingleBufferInitialization::finishInitialization (SGF);
670671 assert (!DidFinish &&
@@ -677,6 +678,54 @@ class LocalVariableInitialization : public SingleBufferInitialization {
677678} // end anonymous namespace
678679
679680namespace {
681+
682+ static void deallocateAddressable (SILGenFunction &SGF,
683+ SILLocation l,
684+ SILGenFunction::VarLoc &loc) {
685+ SGF.B .createEndBorrow (l, loc.addressableBuffer .state ->storeBorrow );
686+ SGF.B .createDeallocStack (l, loc.addressableBuffer .state ->allocStack );
687+ if (loc.addressableBuffer .state ->reabstraction ) {
688+ SGF.B .createDestroyValue (l, loc.addressableBuffer .state ->reabstraction );
689+ }
690+ }
691+
692+ // / Cleanup to deallocate the addressable buffer for a parameter or let
693+ // / binding.
694+ class DeallocateLocalVariableAddressableBuffer : public Cleanup {
695+ ValueDecl *vd;
696+ public:
697+ DeallocateLocalVariableAddressableBuffer (ValueDecl *vd) : vd(vd) {}
698+
699+ void emit (SILGenFunction &SGF, CleanupLocation l,
700+ ForUnwind_t forUnwind) override {
701+ auto found = SGF.VarLocs .find (vd);
702+ if (found == SGF.VarLocs .end ()) {
703+ return ;
704+ }
705+ auto &loc = found->second ;
706+
707+ if (loc.addressableBuffer .state ) {
708+ // The addressable buffer was forced, so clean it up now.
709+ deallocateAddressable (SGF, l, loc);
710+ } else {
711+ // Remember this insert location in case we need to force the addressable
712+ // buffer later.
713+ SILInstruction *marker = SGF.B .createTuple (l, {});
714+ loc.addressableBuffer .cleanupPoints .emplace_back (marker);
715+ }
716+ }
717+
718+ void dump (SILGenFunction &SGF) const override {
719+ #ifndef NDEBUG
720+ llvm::errs () << " DeallocateLocalVariableAddressableBuffer\n "
721+ << " State:" << getState () << " \n "
722+ << " Decl: " ;
723+ vd->print (llvm::errs ());
724+ llvm::errs () << " \n " ;
725+ #endif
726+ }
727+ };
728+
680729// / Initialize a writeback buffer that receives the value of a 'let'
681730// / declaration.
682731class LetValueInitialization : public Initialization {
@@ -755,7 +804,8 @@ class LetValueInitialization : public Initialization {
755804 if (isUninitialized)
756805 address = SGF.B .createMarkUninitializedVar (vd, address);
757806 DestroyCleanup = SGF.enterDormantTemporaryCleanup (address, *lowering);
758- SGF.VarLocs [vd] = SILGenFunction::VarLoc::get (address);
807+ SGF.VarLocs [vd] = SILGenFunction::VarLoc (address,
808+ SILAccessEnforcement::Unknown);
759809 }
760810 // Push a cleanup to destroy the let declaration. This has to be
761811 // inactive until the variable is initialized: if control flow exits the
@@ -766,6 +816,10 @@ class LetValueInitialization : public Initialization {
766816 SGF.Cleanups .pushCleanupInState <DestroyLocalVariable>(
767817 CleanupState::Dormant, vd);
768818 DestroyCleanup = SGF.Cleanups .getTopCleanup ();
819+
820+ // If the binding has an addressable buffer forced, it should be cleaned
821+ // up here.
822+ SGF.enterLocalVariableAddressableBufferScope (vd);
769823 }
770824
771825 ~LetValueInitialization () override {
@@ -883,7 +937,8 @@ class LetValueInitialization : public Initialization {
883937 if (SGF.getASTContext ().SILOpts .supportsLexicalLifetimes (SGF.getModule ()))
884938 value = getValueForLexicalLifetimeBinding (SGF, loc, value, wasPlusOne);
885939
886- SGF.VarLocs [vd] = SILGenFunction::VarLoc::get (value);
940+ SGF.VarLocs [vd] = SILGenFunction::VarLoc (value,
941+ SILAccessEnforcement::Unknown);
887942
888943 // Emit a debug_value[_addr] instruction to record the start of this value's
889944 // lifetime, if permitted to do so.
@@ -1463,7 +1518,7 @@ SILGenFunction::emitInitializationForVarDecl(VarDecl *vd, bool forceImmutable,
14631518 assert (SILDebugClient && " Debugger client doesn't support SIL" );
14641519 SILValue SV = SILDebugClient->emitLValueForVariable (vd, B);
14651520
1466- VarLocs[vd] = SILGenFunction:: VarLoc::get (SV);
1521+ VarLocs[vd] = VarLoc (SV, SILAccessEnforcement::Dynamic );
14671522 return InitializationPtr (new KnownAddressInitialization (SV));
14681523 }
14691524
@@ -1494,7 +1549,7 @@ SILGenFunction::emitInitializationForVarDecl(VarDecl *vd, bool forceImmutable,
14941549 if (isUninitialized)
14951550 addr = B.createMarkUninitializedVar (loc, addr);
14961551
1497- VarLocs[vd] = SILGenFunction:: VarLoc::get (addr);
1552+ VarLocs[vd] = VarLoc (addr, SILAccessEnforcement::Dynamic );
14981553 Result = InitializationPtr (new KnownAddressInitialization (addr));
14991554 } else {
15001555 std::optional<MarkUninitializedInst::Kind> uninitKind;
@@ -2309,7 +2364,7 @@ void SILGenFunction::destroyLocalVariable(SILLocation silLoc, VarDecl *vd) {
23092364 }
23102365 };
23112366
2312- auto loc = VarLocs[vd];
2367+ auto & loc = VarLocs[vd];
23132368
23142369 // For a heap variable, the box is responsible for the value. We just need
23152370 // to give up our retain count on it.
@@ -2406,6 +2461,101 @@ void SILGenFunction::destroyLocalVariable(SILLocation silLoc, VarDecl *vd) {
24062461 llvm_unreachable (" unhandled case" );
24072462}
24082463
2464+ void
2465+ SILGenFunction::enterLocalVariableAddressableBufferScope (VarDecl *decl) {
2466+ Cleanups.pushCleanup <DeallocateLocalVariableAddressableBuffer>(decl);
2467+ }
2468+
2469+ SILValue
2470+ SILGenFunction::getLocalVariableAddressableBuffer (VarDecl *decl,
2471+ SILLocation curLoc,
2472+ ValueOwnership ownership) {
2473+ auto foundVarLoc = VarLocs.find (decl);
2474+ if (foundVarLoc == VarLocs.end ()) {
2475+ return SILValue ();
2476+ }
2477+
2478+ auto &varLoc = foundVarLoc->second ;
2479+ SILType fullyAbstractedTy = getLoweredType (AbstractionPattern::getOpaque (),
2480+ decl->getTypeInContext ()->getRValueType ());
2481+
2482+ // Check whether the bound value is inherently suitable for addressability.
2483+ // It must already be in memory and fully abstracted.
2484+ if (varLoc.value ->getType ().isAddress ()
2485+ && fullyAbstractedTy.getASTType ()==varLoc.value ->getType ().getASTType ()) {
2486+ SILValue address = varLoc.value ;
2487+ // Begin an access if the address is mutable.
2488+ if (varLoc.access != SILAccessEnforcement::Unknown) {
2489+ address = B.emitBeginAccess (curLoc, address,
2490+ ownership == ValueOwnership::InOut ? SILAccessKind::Modify
2491+ : SILAccessKind::Read,
2492+ varLoc.access );
2493+ }
2494+ return address;
2495+ }
2496+
2497+ // We can't retroactively introduce a reabstracted representation for a
2498+ // mutable binding (since we would now have two mutable memory locations
2499+ // representing the same value).
2500+ if (varLoc.access != SILAccessEnforcement::Unknown) {
2501+ return SILValue ();
2502+ }
2503+
2504+ assert (ownership == ValueOwnership::Shared);
2505+
2506+ // Check whether the in-memory representation has already been forced.
2507+ if (auto &state = varLoc.addressableBuffer .state ) {
2508+ return state->storeBorrow ;
2509+ }
2510+
2511+ // Otherwise, force the addressable representation.
2512+ SILValue reabstraction, allocStack, storeBorrow;
2513+ {
2514+ SavedInsertionPointRAII save (B);
2515+ B.setInsertionPoint (varLoc.value ->getNextInstruction ());
2516+ auto declarationLoc = varLoc.value ->getDefiningInsertionPoint ()->getLoc ();
2517+
2518+ // Reabstract if necessary.
2519+ auto value = varLoc.value ;
2520+ reabstraction = SILValue ();
2521+ if (value->getType ().getASTType () != fullyAbstractedTy.getASTType ()){
2522+ auto reabstracted = emitSubstToOrigValue (curLoc,
2523+ ManagedValue::forBorrowedRValue (value),
2524+ AbstractionPattern::getOpaque (),
2525+ decl->getTypeInContext ()->getCanonicalType (),
2526+ SGFContext ());
2527+ reabstraction = reabstracted.forward (*this );
2528+ value = reabstraction;
2529+ }
2530+ // TODO: reabstract
2531+ allocStack = B.createAllocStack (declarationLoc, value->getType (),
2532+ std::nullopt ,
2533+ DoesNotHaveDynamicLifetime,
2534+ IsNotLexical,
2535+ IsNotFromVarDecl,
2536+ DoesNotUseMoveableValueDebugInfo,
2537+ /* skipVarDeclAssert*/ true );
2538+ storeBorrow = B.createStoreBorrow (declarationLoc, value, allocStack);
2539+ }
2540+
2541+ // Record the addressable representation.
2542+ varLoc.addressableBuffer .state
2543+ = std::make_unique<VarLoc::AddressableBuffer::State>(reabstraction,
2544+ allocStack,
2545+ storeBorrow);
2546+
2547+ // Emit cleanups on any paths where we previously would have cleaned up
2548+ // the addressable representation if it had been forced earlier.
2549+ for (SILInstruction *cleanupPoint : varLoc.addressableBuffer .cleanupPoints ) {
2550+ SavedInsertionPointRAII insertCleanup (B, cleanupPoint);
2551+ deallocateAddressable (*this , cleanupPoint->getLoc (), varLoc);
2552+ cleanupPoint->eraseFromParent ();
2553+ }
2554+ varLoc.addressableBuffer .cleanupPoints .clear ();
2555+
2556+ return storeBorrow;
2557+ }
2558+
24092559void BlackHoleInitialization::performPackExpansionInitialization (
24102560 SILGenFunction &SGF,
24112561 SILLocation loc,
@@ -2437,3 +2587,9 @@ void BlackHoleInitialization::copyOrInitValueInto(SILGenFunction &SGF, SILLocati
24372587 value = SGF.B .createMoveValue (loc, value);
24382588 SGF.B .createIgnoredUse (loc, value.getValue ());
24392589}
2590+
2591+ SILGenFunction::VarLoc::AddressableBuffer::~AddressableBuffer () {
2592+ for (auto cleanupPoint : cleanupPoints) {
2593+ cleanupPoint->eraseFromParent ();
2594+ }
2595+ }
0 commit comments