@@ -305,8 +305,7 @@ class SILInlineCloner
305
305
void cloneInline (ArrayRef<SILValue> AppliedArgs);
306
306
307
307
protected:
308
- SILValue borrowFunctionArgument (SILValue callArg, FullApplySite AI,
309
- unsigned index);
308
+ SILValue borrowFunctionArgument (SILValue callArg, unsigned index);
310
309
311
310
void visitDebugValueInst (DebugValueInst *Inst);
312
311
void visitHopToExecutorInst (HopToExecutorInst *Inst);
@@ -486,7 +485,7 @@ void SILInlineCloner::cloneInline(ArrayRef<SILValue> AppliedArgs) {
486
485
} else {
487
486
// Insert begin/end borrow for guaranteed arguments.
488
487
if (paramInfo.isGuaranteed ()) {
489
- if (SILValue newValue = borrowFunctionArgument (callArg, Apply, idx)) {
488
+ if (SILValue newValue = borrowFunctionArgument (callArg, idx)) {
490
489
callArg = newValue;
491
490
borrowedArgs[idx] = true ;
492
491
}
@@ -631,34 +630,77 @@ void SILInlineCloner::postFixUp(SILFunction *calleeFunction) {
631
630
deleter.forceDelete (Apply.getInstruction ());
632
631
}
633
632
634
- SILValue SILInlineCloner::borrowFunctionArgument (SILValue callArg,
635
- FullApplySite AI,
636
- unsigned index) {
637
- auto &mod = Apply.getFunction ()->getModule ();
633
+ namespace {
634
+
635
+ enum class Scope : uint8_t {
636
+ None,
637
+ Bare,
638
+ Lexical,
639
+ };
640
+ Scope scopeForArgument (Scope nonlexicalScope, SILValue callArg, unsigned index,
641
+ SILFunction *caller, SILFunction *callee) {
642
+ if (!caller->hasOwnership ()) {
643
+ // The function isn't in OSSA. Borrows/moves are not meaningful.
644
+ return Scope::None;
645
+ }
646
+
647
+ auto &mod = caller->getModule ();
638
648
auto enableLexicalLifetimes =
639
649
mod.getASTContext ().SILOpts .supportsLexicalLifetimes (mod);
640
- auto argOwnershipRequiresBorrow = [&]() {
641
- auto kind = callArg->getOwnershipKind ();
642
- if (enableLexicalLifetimes) {
643
- // At this point, we know that the function argument is @guaranteed.
644
- // If the value passed as that parameter has ownership, always add a
645
- // lexical borrow scope to ensure that the value stays alive for the
646
- // duration of the inlined callee.
647
- return kind != OwnershipKind::None;
648
- }
649
- return kind == OwnershipKind::Owned;
650
- };
651
- if (!AI.getFunction ()->hasOwnership () || !argOwnershipRequiresBorrow ()) {
652
- return SILValue ();
650
+ SILFunctionArgument *argument =
651
+ cast<SILFunctionArgument>(callee->getEntryBlock ()->getArgument (index));
652
+ if (!enableLexicalLifetimes) {
653
+ // Lexical lifetimes are disabled. Use the non-lexical scope:
654
+ // - for borrows, do an ownership conversion.
655
+ return nonlexicalScope;
653
656
}
657
+ if (!argument->getLifetime ().isLexical ()) {
658
+ // The same applies if lexical lifetimes are enabled but the function
659
+ // argument is not lexical. There is no lexical lifetime to maintain. Use
660
+ // the non-lexical scope.
661
+ return nonlexicalScope;
662
+ }
663
+ // Lexical lifetimes are enabled and the function argument is lexical.
664
+ // During inlining, we need to ensure that the lifetime is maintained.
665
+ if (callArg->isLexical ()) {
666
+ // The caller's value is already lexical. It will maintain the lifetime of
667
+ // the argument. Just do an ownership conversion if needed.
668
+ return nonlexicalScope;
669
+ }
670
+ // Lexical lifetimes are enabled, the function argument's lifetime is
671
+ // lexical, but the caller's value is not lexical. Extra care is required to
672
+ // maintain the function argument's lifetime. We need to add a lexical
673
+ // scope.
674
+ return Scope::Lexical;
675
+ }
654
676
655
- SILFunctionArgument *argument = cast<SILFunctionArgument>(
656
- getCalleeFunction ()->getEntryBlock ()->getArgument (index));
677
+ } // anonymous namespace
657
678
658
- SILBuilderWithScope beginBuilder (AI.getInstruction (), getBuilder ());
659
- auto isLexical =
660
- enableLexicalLifetimes && argument->getLifetime ().isLexical ();
661
- return beginBuilder.createBeginBorrow (AI.getLoc (), callArg, isLexical);
679
+ SILValue SILInlineCloner::borrowFunctionArgument (SILValue callArg,
680
+ unsigned index) {
681
+ // The "minimal" borrow scope: Guaranteed values are valid operands to some
682
+ // instructions that owned values are not. If the caller's value is owned,
683
+ // it must be converted (via a "bare" begin_borrow) to a guaranteed value so
684
+ // that it can be used in place of the original guaranteed value in the
685
+ // instructions that are being inlined.
686
+ auto scopeForOwnership = callArg->getOwnershipKind () == OwnershipKind::Owned
687
+ ? Scope::Bare
688
+ : Scope::None;
689
+ auto scope = scopeForArgument (scopeForOwnership, callArg, index,
690
+ Apply.getFunction (), getCalleeFunction ());
691
+ bool isLexical;
692
+ switch (scope) {
693
+ case Scope::None:
694
+ return SILValue ();
695
+ case Scope::Bare:
696
+ isLexical = false ;
697
+ break ;
698
+ case Scope::Lexical:
699
+ isLexical = true ;
700
+ break ;
701
+ }
702
+ SILBuilderWithScope beginBuilder (Apply.getInstruction (), getBuilder ());
703
+ return beginBuilder.createBeginBorrow (Apply.getLoc (), callArg, isLexical);
662
704
}
663
705
664
706
void SILInlineCloner::visitDebugValueInst (DebugValueInst *Inst) {
0 commit comments