Skip to content

Commit f4dfbe9

Browse files
committed
[ownership] Require all operands of ref_tail_addr to have guaranteed ownership.
This ensures that the optimizer has a summary of where the ref_tail_addr will no longer be used. This is important when analyzing the lifetime of the base of the ref_tail_addr. I also cleaned up a little the description around the specification for this in OperandOwnership. Now all instructions that are "INTERIOR_POINTER_PROJECTIONS" have their own section/macro as a form of self documenting.
1 parent 746b58e commit f4dfbe9

File tree

3 files changed

+31
-4
lines changed

3 files changed

+31
-4
lines changed

lib/SIL/OperandOwnership.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,18 @@ SHOULD_NEVER_VISIT_INST(StrongRelease)
142142
#include "swift/AST/ReferenceStorage.def"
143143
#undef SHOULD_NEVER_VISIT_INST
144144

145+
/// Instructions that are interior pointers into a guaranteed value.
146+
#define INTERIOR_POINTER_PROJECTION(INST) \
147+
OperandOwnershipKindMap OperandOwnershipKindClassifier::visit##INST##Inst( \
148+
INST##Inst *i) { \
149+
assert(i->getNumOperands() && "Expected to have non-zero operands"); \
150+
return Map::compatibilityMap(ValueOwnershipKind::Guaranteed, \
151+
UseLifetimeConstraint::MustBeLive); \
152+
}
153+
INTERIOR_POINTER_PROJECTION(RefElementAddr)
154+
INTERIOR_POINTER_PROJECTION(RefTailAddr)
155+
#undef INTERIOR_POINTER_PROJECTION
156+
145157
/// Instructions whose arguments are always compatible with one convention.
146158
#define CONSTANT_OWNERSHIP_INST(OWNERSHIP, USE_LIFETIME_CONSTRAINT, INST) \
147159
OperandOwnershipKindMap OperandOwnershipKindClassifier::visit##INST##Inst( \
@@ -151,7 +163,6 @@ SHOULD_NEVER_VISIT_INST(StrongRelease)
151163
ValueOwnershipKind::OWNERSHIP, \
152164
UseLifetimeConstraint::USE_LIFETIME_CONSTRAINT); \
153165
}
154-
CONSTANT_OWNERSHIP_INST(Guaranteed, MustBeLive, RefElementAddr)
155166
CONSTANT_OWNERSHIP_INST(Guaranteed, MustBeLive, OpenExistentialValue)
156167
CONSTANT_OWNERSHIP_INST(Guaranteed, MustBeLive, OpenExistentialBoxValue)
157168
CONSTANT_OWNERSHIP_INST(Owned, MustBeInvalidated, AutoreleaseValue)
@@ -271,7 +282,6 @@ ACCEPTS_ANY_OWNERSHIP_INST(BridgeObjectToWord)
271282
ACCEPTS_ANY_OWNERSHIP_INST(ClassifyBridgeObject)
272283
ACCEPTS_ANY_OWNERSHIP_INST(CopyBlock)
273284
ACCEPTS_ANY_OWNERSHIP_INST(OpenExistentialBox)
274-
ACCEPTS_ANY_OWNERSHIP_INST(RefTailAddr)
275285
ACCEPTS_ANY_OWNERSHIP_INST(RefToRawPointer)
276286
ACCEPTS_ANY_OWNERSHIP_INST(SetDeallocating)
277287
ACCEPTS_ANY_OWNERSHIP_INST(ProjectExistentialBox)

lib/SILGen/SILGenBuiltin.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -976,8 +976,8 @@ static ManagedValue emitBuiltinProjectTailElems(SILGenFunction &SGF,
976976
SILType ElemType = SGF.getLoweredType(subs.getReplacementTypes()[1]->
977977
getCanonicalType()).getObjectType();
978978

979-
SILValue result = SGF.B.createRefTailAddr(loc, args[0].getValue(),
980-
ElemType.getAddressType());
979+
SILValue result = SGF.B.createRefTailAddr(
980+
loc, args[0].borrow(SGF, loc).getValue(), ElemType.getAddressType());
981981
SILType rawPointerType = SILType::getRawPointerType(SGF.F.getASTContext());
982982
result = SGF.B.createAddressToPointer(loc, result, rawPointerType);
983983
return ManagedValue::forUnmanaged(result);

test/SILGen/builtins.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,23 @@ func projectTailElems<T>(h: Header, ty: T.Type) -> Builtin.RawPointer {
360360
}
361361
// CHECK: } // end sil function '$s8builtins16projectTailElems1h2tyBpAA6HeaderC_xmtlF'
362362

363+
// Make sure we borrow if this is owned.
364+
//
365+
// CHECK-LABEL: sil hidden [ossa] @$s8builtins21projectTailElemsOwned{{[_0-9a-zA-Z]*}}F
366+
func projectTailElemsOwned<T>(h: __owned Header, ty: T.Type) -> Builtin.RawPointer {
367+
// CHECK: bb0([[ARG1:%.*]] : @owned $Header
368+
// CHECK: [[BORROWED_ARG1:%.*]] = begin_borrow [[ARG1]]
369+
// CHECK: [[TA:%.*]] = ref_tail_addr [[BORROWED_ARG1]] : $Header
370+
// -- Once we have passed the address through a2p, we no longer provide any guarantees.
371+
// -- We still need to make sure that the a2p itself is in the borrow site though.
372+
// CHECK: [[A2P:%.*]] = address_to_pointer [[TA]]
373+
// CHECK: end_borrow [[BORROWED_ARG1]]
374+
// CHECK: destroy_value [[ARG1]]
375+
// CHECK: return [[A2P]]
376+
return Builtin.projectTailElems(h, ty)
377+
}
378+
// CHECK: } // end sil function '$s8builtins21projectTailElemsOwned{{[_0-9a-zA-Z]*}}F'
379+
363380
// CHECK-LABEL: sil hidden [ossa] @$s8builtins11getTailAddr{{[_0-9a-zA-Z]*}}F
364381
func getTailAddr<T1, T2>(start: Builtin.RawPointer, i: Builtin.Word, ty1: T1.Type, ty2: T2.Type) -> Builtin.RawPointer {
365382
// CHECK: [[P2A:%.*]] = pointer_to_address %0

0 commit comments

Comments
 (0)