Skip to content

Commit cc0e75c

Browse files
authored
Merge pull request #85040 from meg-gupta/returnborrowpr
Introduce return_borrow and unchecked_ownership instructions for use with borrow accessors
2 parents dc759fd + 7c25466 commit cc0e75c

Some content is hidden

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

47 files changed

+525
-66
lines changed

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,6 +1447,8 @@ final public class CopyableToMoveOnlyWrapperAddrInst
14471447
final public class MoveOnlyWrapperToCopyableAddrInst
14481448
: SingleValueInstruction, UnaryInstruction {}
14491449

1450+
final public class UncheckedOwnershipInst: SingleValueInstruction, UnaryInstruction {}
1451+
14501452
final public class ObjectInst : SingleValueInstruction {
14511453
public var baseOperands: OperandArray {
14521454
operands[0..<bridged.ObjectInst_getNumBaseElements()]
@@ -1857,6 +1859,18 @@ final public class ReturnInst : TermInst, UnaryInstruction {
18571859
public override var isFunctionExiting: Bool { true }
18581860
}
18591861

1862+
final public class ReturnBorrowInst : TermInst {
1863+
public var returnValue: Value { operands[0].value }
1864+
public var enclosingOperands: OperandArray {
1865+
let ops = operands
1866+
return ops[1..<ops.count]
1867+
}
1868+
public var enclosingValues: LazyMapSequence<LazySequence<OperandArray>.Elements, Value> {
1869+
enclosingOperands.values
1870+
}
1871+
public override var isFunctionExiting: Bool { true }
1872+
}
1873+
18601874
final public class ThrowInst : TermInst, UnaryInstruction {
18611875
public var thrownValue: Value { operand.value }
18621876
public override var isFunctionExiting: Bool { true }

SwiftCompilerSources/Sources/SIL/Registration.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ private func registerSILClasses() {
120120
register(MoveOnlyWrapperToCopyableBoxInst.self)
121121
register(CopyableToMoveOnlyWrapperAddrInst.self)
122122
register(MoveOnlyWrapperToCopyableAddrInst.self)
123+
register(UncheckedOwnershipInst.self)
123124
register(ObjectInst.self)
124125
register(VectorInst.self)
125126
register(VectorBaseAddrInst.self)
@@ -247,6 +248,7 @@ private func registerSILClasses() {
247248

248249
register(UnreachableInst.self)
249250
register(ReturnInst.self)
251+
register(ReturnBorrowInst.self)
250252
register(ThrowInst.self)
251253
register(ThrowAddrInst.self)
252254
register(YieldInst.self)

docs/SIL/Instructions.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,6 +1199,17 @@ the `set` case is passed `self`.
11991199

12001200
This is only valid in Raw SIL.
12011201

1202+
### unchecked_ownership
1203+
1204+
```
1205+
sil-instruction ::= 'unchecked_ownership' sil-operand
1206+
1207+
unchecked_ownership %1 : $T
1208+
```
1209+
1210+
unchecked_ownership disables the ownership verification of it's operand. This used in cases
1211+
we cannot resolve ownership until a mandatory pass runs. This is only valid in Raw SIL.
1212+
12021213
### copy_addr
12031214

12041215
```
@@ -5003,6 +5014,20 @@ does not apply in the `raw` SIL stage.
50035014

50045015
A function must not contain more than one `return` instruction.
50055016

5017+
### return_borrow
5018+
5019+
```
5020+
sil-terminator ::= 'return_borrow' sil-operand 'from_scopes' '(' (sil-operand (',' sil-operand)*)? ')'
5021+
5022+
return_borrow %0 : $T from_scopes (%1, %2 ...)
5023+
// %0 must be a @guaranteed value
5024+
// %1, %2, ... must be borrow introducers for %0, like `load_borrow`
5025+
// $T must be the return type of the current function
5026+
```
5027+
5028+
return_borrow instruction is valid only for functions @guaranteed results.
5029+
It is used to a return a @guaranteed value that maybe produced within borrow scopes local to the function.
5030+
50065031
### throw
50075032

50085033
```

include/swift/SIL/AddressWalker.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ TransitiveAddressWalker<Impl>::walk(SILValue projectedAddress) {
185185
llvm_unreachable("Never takes an address");
186186
// Point uses.
187187
case TermKind::ReturnInst:
188+
case TermKind::ReturnBorrowInst:
188189
case TermKind::ThrowInst:
189190
case TermKind::YieldInst:
190191
case TermKind::TryApplyInst:

include/swift/SIL/SILBuilder.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,6 +1555,12 @@ class SILBuilder {
15551555
MoveOnlyWrapperToCopyableValueInst::Guaranteed));
15561556
}
15571557

1558+
UncheckedOwnershipInst *createUncheckedOwnership(SILLocation Loc,
1559+
SILValue Operand) {
1560+
return insert(new (getModule()) UncheckedOwnershipInst(
1561+
getSILDebugLocation(Loc), Operand, Operand->getOwnershipKind()));
1562+
}
1563+
15581564
UnconditionalCheckedCastInst *
15591565
createUnconditionalCheckedCast(SILLocation Loc,
15601566
CheckedCastInstOptions options,
@@ -2658,6 +2664,12 @@ class SILBuilder {
26582664
getFunction(), getSILDebugLocation(Loc), ReturnValue));
26592665
}
26602666

2667+
ReturnBorrowInst *createReturnBorrow(SILLocation Loc, SILValue returnValue,
2668+
ArrayRef<SILValue> enclosingValues) {
2669+
return insertTerminator(ReturnBorrowInst::create(
2670+
getSILDebugLocation(Loc), returnValue, enclosingValues, getModule()));
2671+
}
2672+
26612673
ThrowInst *createThrow(SILLocation Loc, SILValue errorValue) {
26622674
return insertTerminator(
26632675
new (getModule()) ThrowInst(getSILDebugLocation(Loc), errorValue));

include/swift/SIL/SILCloner.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2247,6 +2247,19 @@ void SILCloner<ImplClass>::visitCopyableToMoveOnlyWrapperValueInst(
22472247
recordClonedInstruction(inst, cvt);
22482248
}
22492249

2250+
template <typename ImplClass>
2251+
void SILCloner<ImplClass>::visitUncheckedOwnershipInst(
2252+
UncheckedOwnershipInst *uoi) {
2253+
getBuilder().setCurrentDebugScope(getOpScope(uoi->getDebugScope()));
2254+
if (!getBuilder().hasOwnership()) {
2255+
return recordFoldedValue(uoi, getOpValue(uoi->getOperand()));
2256+
}
2257+
2258+
recordClonedInstruction(
2259+
uoi, getBuilder().createUncheckedOwnership(
2260+
getOpLocation(uoi->getLoc()), getOpValue(uoi->getOperand())));
2261+
}
2262+
22502263
template <typename ImplClass>
22512264
void SILCloner<ImplClass>::visitReleaseValueInst(ReleaseValueInst *Inst) {
22522265
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
@@ -3417,6 +3430,22 @@ SILCloner<ImplClass>::visitReturnInst(ReturnInst *Inst) {
34173430
getOpValue(Inst->getOperand())));
34183431
}
34193432

3433+
template <typename ImplClass>
3434+
void SILCloner<ImplClass>::visitReturnBorrowInst(ReturnBorrowInst *rbi) {
3435+
getBuilder().setCurrentDebugScope(getOpScope(rbi->getDebugScope()));
3436+
if (!getBuilder().hasOwnership()) {
3437+
return recordClonedInstruction(
3438+
rbi, getBuilder().createReturn(getOpLocation(rbi->getLoc()),
3439+
getOpValue(rbi->getReturnValue())));
3440+
}
3441+
3442+
auto enclosingValues = getOpValueArray<8>(rbi->getEnclosingValues());
3443+
recordClonedInstruction(
3444+
rbi, getBuilder().createReturnBorrow(getOpLocation(rbi->getLoc()),
3445+
getOpValue(rbi->getReturnValue()),
3446+
enclosingValues));
3447+
}
3448+
34203449
template<typename ImplClass>
34213450
void
34223451
SILCloner<ImplClass>::visitThrowInst(ThrowInst *Inst) {

include/swift/SIL/SILInstruction.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9553,6 +9553,17 @@ class MoveOnlyWrapperToCopyableAddrInst
95539553
}
95549554
};
95559555

9556+
class UncheckedOwnershipInst final
9557+
: public UnaryInstructionBase<SILInstructionKind::UncheckedOwnershipInst,
9558+
OwnershipForwardingSingleValueInstruction> {
9559+
friend class SILBuilder;
9560+
9561+
UncheckedOwnershipInst(SILDebugLocation DebugLoc, SILValue operand,
9562+
ValueOwnershipKind forwardingOwnershipKind)
9563+
: UnaryInstructionBase(DebugLoc, operand, operand->getType(),
9564+
forwardingOwnershipKind) {}
9565+
};
9566+
95569567
/// Given an object reference, return true iff it is non-nil and refers
95579568
/// to a native swift object with strong reference count of 1.
95589569
class IsUniqueInst
@@ -10123,6 +10134,7 @@ class TermInst : public NonValueInstruction {
1012310134
case TermKind::UnwindInst:
1012410135
case TermKind::UnreachableInst:
1012510136
case TermKind::ReturnInst:
10137+
case TermKind::ReturnBorrowInst:
1012610138
case TermKind::ThrowInst:
1012710139
case TermKind::ThrowAddrInst:
1012810140
case TermKind::YieldInst:
@@ -10252,6 +10264,34 @@ class ReturnInst
1025210264
}
1025310265
};
1025410266

10267+
class ReturnBorrowInst final
10268+
: public InstructionBaseWithTrailingOperands<
10269+
SILInstructionKind::ReturnBorrowInst, ReturnBorrowInst, TermInst> {
10270+
friend SILBuilder;
10271+
10272+
ReturnBorrowInst(SILDebugLocation DebugLoc, ArrayRef<SILValue> operands);
10273+
10274+
static ReturnBorrowInst *create(SILDebugLocation DebugLoc, SILValue value,
10275+
ArrayRef<SILValue> enclosingValues,
10276+
SILModule &M);
10277+
10278+
public:
10279+
SILValue getReturnValue() const { return getAllOperands()[0].get(); }
10280+
10281+
ArrayRef<Operand> getEnclosingValueOperands() const {
10282+
return getAllOperands().drop_front();
10283+
}
10284+
10285+
OperandValueArrayRef getEnclosingValues() const {
10286+
return OperandValueArrayRef(getEnclosingValueOperands());
10287+
}
10288+
10289+
SuccessorListTy getSuccessors() {
10290+
// No Successors.
10291+
return SuccessorListTy();
10292+
}
10293+
};
10294+
1025510295
/// ThrowInst - Throw a typed error, returning it via the direct error result.
1025610296
class ThrowInst
1025710297
: public UnaryInstructionBase<SILInstructionKind::ThrowInst, TermInst>
@@ -11667,6 +11707,7 @@ OwnershipForwardingSingleValueInstruction::classof(SILInstructionKind kind) {
1166711707
case SILInstructionKind::DropDeinitInst:
1166811708
case SILInstructionKind::BorrowedFromInst:
1166911709
case SILInstructionKind::ImplicitActorToOpaqueIsolationCastInst:
11710+
case SILInstructionKind::UncheckedOwnershipInst:
1167011711
return true;
1167111712
default:
1167211713
return false;

include/swift/SIL/SILNodes.def

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,8 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
469469
SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
470470
#include "swift/AST/ReferenceStorage.def"
471471
SINGLE_VALUE_INST(UncheckedOwnershipConversionInst, unchecked_ownership_conversion,
472-
SingleValueInstruction, None, MayRelease)
472+
SingleValueInstruction, None, DoesNotRelease)
473+
473474
// A move_value is an OSSA only instruction. Its result does not have any side
474475
// effects relative to other OSSA values like copy_value.
475476
SINGLE_VALUE_INST(MoveValueInst, move_value, SingleValueInstruction, None,
@@ -520,6 +521,8 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
520521
SINGLE_VALUE_INST(CopyableToMoveOnlyWrapperAddrInst,
521522
copyable_to_moveonlywrapper_addr, SingleValueInstruction,
522523
None, DoesNotRelease)
524+
SINGLE_VALUE_INST(UncheckedOwnershipInst, unchecked_ownership,
525+
SingleValueInstruction, None, DoesNotRelease)
523526

524527
// IsUnique does not actually write to memory but should be modeled
525528
// as such. Its operand is a pointer to an object reference. The
@@ -731,6 +734,8 @@ ABSTRACT_INST(TermInst, SILInstruction)
731734
TermInst, None, DoesNotRelease)
732735
TERMINATOR(ReturnInst, return,
733736
TermInst, None, DoesNotRelease)
737+
TERMINATOR(ReturnBorrowInst, return_borrow,
738+
TermInst, None, DoesNotRelease)
734739
TERMINATOR(ThrowInst, throw,
735740
TermInst, None, DoesNotRelease)
736741
TERMINATOR(ThrowAddrInst, throw_addr,

include/swift/SILOptimizer/Utils/SCCVisitor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ class SCCVisitor {
130130

131131
case TermKind::UnreachableInst:
132132
case TermKind::ReturnInst:
133+
case TermKind::ReturnBorrowInst:
133134
case TermKind::SwitchValueInst:
134135
case TermKind::ThrowInst:
135136
case TermKind::ThrowAddrInst:

lib/IRGen/IRGenSIL.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1302,7 +1302,9 @@ class IRGenSILFunction :
13021302
auto e = getLoweredExplosion(i->getOperand());
13031303
setLoweredExplosion(i, e);
13041304
}
1305-
1305+
void visitUncheckedOwnershipInst(UncheckedOwnershipInst *i) {
1306+
llvm_unreachable("unimplemented");
1307+
}
13061308
void visitMergeIsolationRegionInst(MergeIsolationRegionInst *i) {
13071309
llvm_unreachable("Valid only when ownership is enabled");
13081310
}
@@ -1504,6 +1506,9 @@ class IRGenSILFunction :
15041506
void visitBranchInst(BranchInst *i);
15051507
void visitCondBranchInst(CondBranchInst *i);
15061508
void visitReturnInst(ReturnInst *i);
1509+
void visitReturnBorrowInst(ReturnBorrowInst *i) {
1510+
llvm_unreachable("unimplemented");
1511+
}
15071512
void visitThrowInst(ThrowInst *i);
15081513
void visitThrowAddrInst(ThrowAddrInst *i);
15091514
void visitUnwindInst(UnwindInst *i);

0 commit comments

Comments
 (0)