Skip to content

Commit 2f7c210

Browse files
committed
Merge branch 'master' into fix-module-ver
2 parents cb5fd7f + 794ff31 commit 2f7c210

File tree

15 files changed

+111
-30
lines changed

15 files changed

+111
-30
lines changed

include/swift/SIL/Consumption.h

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,41 @@ enum class CastConsumptionKind : uint8_t {
4343
/// The source value is always left in place, and the destination
4444
/// value is copied into on success.
4545
CopyOnSuccess,
46+
47+
/// The source value is never taken, regardless of whether the cast
48+
/// succeeds. Instead, we always borrow the source value and feed it through.
49+
///
50+
/// NOTE: This can only be used with objects. We do not support borrowing of
51+
/// addresses. If an address is needed for a cast operation, a BorrowAlways
52+
/// value must be copied into a temporary and operated upon. If the result of
53+
/// the cast is a loadable type then the value is loaded using a
54+
/// load_borrow. If an address only value is returned, we continue processing
55+
/// the value as an owned TakeAlways value.
56+
BorrowAlways,
4657
};
4758

4859
/// Should the source value be destroyed if the cast fails?
4960
inline bool shouldDestroyOnFailure(CastConsumptionKind kind) {
50-
return (kind == CastConsumptionKind::TakeAlways);
61+
switch (kind) {
62+
case CastConsumptionKind::TakeAlways:
63+
return true;
64+
case CastConsumptionKind::TakeOnSuccess:
65+
case CastConsumptionKind::CopyOnSuccess:
66+
case CastConsumptionKind::BorrowAlways:
67+
return false;
68+
}
5169
}
5270

5371
/// Should the source value be taken if the cast succeeds?
5472
inline IsTake_t shouldTakeOnSuccess(CastConsumptionKind kind) {
55-
return IsTake_t(kind != CastConsumptionKind::CopyOnSuccess);
73+
switch (kind) {
74+
case CastConsumptionKind::TakeAlways:
75+
case CastConsumptionKind::TakeOnSuccess:
76+
return IsTake;
77+
case CastConsumptionKind::CopyOnSuccess:
78+
case CastConsumptionKind::BorrowAlways:
79+
return IsNotTake;
80+
}
5681
}
5782

5883
} // end namespace swift

include/swift/SIL/SILInstruction.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7402,7 +7402,10 @@ class CheckedCastAddrBranchInst
74027402
: InstructionBase(DebugLoc), ConsumptionKind(consumptionKind),
74037403
Operands{this, src, dest}, DestBBs{{this, successBB, Target1Count},
74047404
{this, failureBB, Target2Count}},
7405-
SourceType(srcType), TargetType(targetType) {}
7405+
SourceType(srcType), TargetType(targetType) {
7406+
assert(ConsumptionKind != CastConsumptionKind::BorrowAlways &&
7407+
"BorrowAlways is not supported on addresses");
7408+
}
74067409

74077410
public:
74087411
enum {

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
5757
/// Don't worry about adhering to the 80-column limit for this line.
58-
const uint16_t VERSION_MINOR = 453; // Last change: multiple nominal types for operators
58+
const uint16_t VERSION_MINOR = 454; // Last change: multiple nominal types for operators
5959

6060
using DeclIDField = BCFixed<31>;
6161

lib/ParseSIL/ParseSIL.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3155,6 +3155,8 @@ bool SILParser::parseSILInstruction(SILBuilder &B) {
31553155
"cast consumption kind")) {
31563156
return true;
31573157
}
3158+
// NOTE: BorrowAlways is not a supported cast kind for address types, so we
3159+
// purposely do not parse it here.
31583160
auto kind = llvm::StringSwitch<Optional<CastConsumptionKind>>(
31593161
consumptionKindToken.str())
31603162
.Case("take_always", CastConsumptionKind::TakeAlways)

lib/SIL/SILPrinter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ static StringRef getCastConsumptionKindName(CastConsumptionKind kind) {
398398
case CastConsumptionKind::TakeAlways: return "take_always";
399399
case CastConsumptionKind::TakeOnSuccess: return "take_on_success";
400400
case CastConsumptionKind::CopyOnSuccess: return "copy_on_success";
401+
case CastConsumptionKind::BorrowAlways: return "borrow_always";
401402
}
402403
llvm_unreachable("bad cast consumption kind");
403404
}

lib/SIL/SILVerifier.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2860,9 +2860,15 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
28602860
return true;
28612861
}
28622862
case SILInstructionKind::CheckedCastAddrBranchInst:
2863-
if (cast<CheckedCastAddrBranchInst>(inst)->getConsumptionKind() !=
2864-
CastConsumptionKind::CopyOnSuccess)
2863+
switch (cast<CheckedCastAddrBranchInst>(inst)->getConsumptionKind()) {
2864+
case CastConsumptionKind::BorrowAlways:
2865+
llvm_unreachable("checked_cast_addr_br cannot have BorrowAlways");
2866+
case CastConsumptionKind::CopyOnSuccess:
2867+
break;
2868+
case CastConsumptionKind::TakeAlways:
2869+
case CastConsumptionKind::TakeOnSuccess:
28652870
return true;
2871+
}
28662872
break;
28672873
case SILInstructionKind::LoadInst:
28682874
// A 'non-taking' value load is harmless.

lib/SILGen/SILGenDynamicCast.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,11 +229,16 @@ namespace {
229229
return;
230230
}
231231

232-
if (consumption == CastConsumptionKind::CopyOnSuccess) {
232+
switch (consumption) {
233+
case CastConsumptionKind::BorrowAlways:
234+
case CastConsumptionKind::CopyOnSuccess:
233235
SGF.B.createGuaranteedPhiArgument(operandValue.getType());
234236
handleFalse(None);
235-
} else {
237+
break;
238+
case CastConsumptionKind::TakeAlways:
239+
case CastConsumptionKind::TakeOnSuccess:
236240
handleFalse(SGF.B.createOwnedPhiArgument(operandValue.getType()));
241+
break;
237242
}
238243

239244
assert(!SGF.B.hasValidInsertionPoint() && "handler did not end block");

lib/SILGen/SILGenPattern.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,6 +1165,7 @@ static bool shouldTake(ConsumableManagedValue value, bool isIrrefutable) {
11651165
case CastConsumptionKind::TakeAlways: return true;
11661166
case CastConsumptionKind::TakeOnSuccess: return isIrrefutable;
11671167
case CastConsumptionKind::CopyOnSuccess: return false;
1168+
case CastConsumptionKind::BorrowAlways: return false;
11681169
}
11691170
llvm_unreachable("bad consumption kind");
11701171
}
@@ -1349,14 +1350,17 @@ static ConsumableManagedValue
13491350
getManagedSubobject(SILGenFunction &SGF, SILValue value,
13501351
const TypeLowering &valueTL,
13511352
CastConsumptionKind consumption) {
1352-
if (consumption == CastConsumptionKind::CopyOnSuccess) {
1353+
switch (consumption) {
1354+
case CastConsumptionKind::BorrowAlways:
1355+
case CastConsumptionKind::CopyOnSuccess:
13531356
return {ManagedValue::forUnmanaged(value), consumption};
1357+
case CastConsumptionKind::TakeAlways:
1358+
case CastConsumptionKind::TakeOnSuccess:
1359+
assert((!SGF.F.getModule().getOptions().EnableSILOwnership ||
1360+
consumption != CastConsumptionKind::TakeOnSuccess) &&
1361+
"TakeOnSuccess should never be used when sil ownership is enabled");
1362+
return {SGF.emitManagedRValueWithCleanup(value, valueTL), consumption};
13541363
}
1355-
1356-
assert((!SGF.F.getModule().getOptions().EnableSILOwnership ||
1357-
consumption != CastConsumptionKind::TakeOnSuccess) &&
1358-
"TakeOnSuccess should never be used when sil ownership is enabled");
1359-
return {SGF.emitManagedRValueWithCleanup(value, valueTL), consumption};
13601364
}
13611365

13621366
static ConsumableManagedValue
@@ -1873,6 +1877,7 @@ void PatternMatchEmission::emitEnumElementDispatch(
18731877
switch (src.getFinalConsumption()) {
18741878
case CastConsumptionKind::TakeAlways:
18751879
case CastConsumptionKind::CopyOnSuccess:
1880+
case CastConsumptionKind::BorrowAlways:
18761881
// No change to src necessary.
18771882
break;
18781883

@@ -1977,7 +1982,13 @@ void PatternMatchEmission::emitEnumElementDispatch(
19771982
eltValue = SGF.B.createUncheckedTakeEnumDataAddr(loc, srcValue,
19781983
elt, eltTy);
19791984
break;
1980-
1985+
case CastConsumptionKind::BorrowAlways:
1986+
// If we reach this point, we know that we have a loadable
1987+
// element type from an enum with mixed address
1988+
// only/loadable cases. Since we had an address only type,
1989+
// we assume that we will not have BorrowAlways since
1990+
// address only types do not support BorrowAlways.
1991+
llvm_unreachable("not allowed");
19811992
case CastConsumptionKind::CopyOnSuccess: {
19821993
auto copy = SGF.emitTemporaryAllocation(loc, srcValue->getType());
19831994
SGF.B.createCopyAddr(loc, srcValue, copy,

lib/SILOptimizer/Utils/CastOptimizer.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,13 +242,19 @@ SILInstruction *CastOptimizer::optimizeBridgedObjCToSwiftCast(
242242
}
243243

244244
if (auto *CCABI = dyn_cast<CheckedCastAddrBranchInst>(Inst)) {
245-
if (CCABI->getConsumptionKind() == CastConsumptionKind::TakeAlways) {
245+
switch (CCABI->getConsumptionKind()) {
246+
case CastConsumptionKind::TakeAlways:
246247
Builder.createReleaseValue(Loc, SrcOp, Builder.getDefaultAtomicity());
247-
} else if (CCABI->getConsumptionKind() ==
248-
CastConsumptionKind::TakeOnSuccess) {
248+
break;
249+
case CastConsumptionKind::TakeOnSuccess:
249250
// Insert a release in the success BB.
250251
Builder.setInsertionPoint(SuccessBB->begin());
251252
Builder.createReleaseValue(Loc, SrcOp, Builder.getDefaultAtomicity());
253+
break;
254+
case CastConsumptionKind::BorrowAlways:
255+
llvm_unreachable("checked_cast_addr_br never has BorrowAlways");
256+
case CastConsumptionKind::CopyOnSuccess:
257+
break;
252258
}
253259
}
254260

@@ -442,6 +448,7 @@ SILInstruction *CastOptimizer::optimizeBridgedSwiftToObjCCast(
442448
case CastConsumptionKind::TakeOnSuccess:
443449
needReleaseInSuccess = true;
444450
break;
451+
case CastConsumptionKind::BorrowAlways:
445452
case CastConsumptionKind::CopyOnSuccess:
446453
// Conservatively insert a retain/release pair around the conversion
447454
// function because the conversion function could decrement the
@@ -771,12 +778,21 @@ SILInstruction *CastOptimizer::simplifyCheckedCastAddrBranchInst(
771778
if (!Src->getType().isAddress() || !Dest->getType().isAddress()) {
772779
return nullptr;
773780
}
781+
774782
// For CopyOnSuccess casts, we could insert an explicit copy here, but this
775783
// case does not happen in practice.
784+
//
776785
// Both TakeOnSuccess and TakeAlways can be reduced to an
777786
// UnconditionalCheckedCast, since the failure path is irrelevant.
778-
if (Inst->getConsumptionKind() == CastConsumptionKind::CopyOnSuccess)
787+
switch (Inst->getConsumptionKind()) {
788+
case CastConsumptionKind::BorrowAlways:
789+
llvm_unreachable("checked_cast_addr_br never has BorrowAlways");
790+
case CastConsumptionKind::CopyOnSuccess:
779791
return nullptr;
792+
case CastConsumptionKind::TakeAlways:
793+
case CastConsumptionKind::TakeOnSuccess:
794+
break;
795+
}
780796

781797
if (!emitSuccessfulIndirectUnconditionalCast(Builder, Mod.getSwiftModule(),
782798
Loc, Src, SourceType, Dest,

lib/Serialization/DeserializeSIL.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,8 @@ static CastConsumptionKind getCastConsumptionKind(unsigned attr) {
789789
return CastConsumptionKind::TakeOnSuccess;
790790
case SIL_CAST_CONSUMPTION_COPY_ON_SUCCESS:
791791
return CastConsumptionKind::CopyOnSuccess;
792+
case SIL_CAST_CONSUMPTION_BORROW_ALWAYS:
793+
return CastConsumptionKind::BorrowAlways;
792794
default:
793795
llvm_unreachable("not a valid CastConsumptionKind for SIL");
794796
}

lib/Serialization/SILFormat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ enum CastConsumptionKindEncoding : uint8_t {
7676
SIL_CAST_CONSUMPTION_TAKE_ALWAYS,
7777
SIL_CAST_CONSUMPTION_TAKE_ON_SUCCESS,
7878
SIL_CAST_CONSUMPTION_COPY_ON_SUCCESS,
79+
SIL_CAST_CONSUMPTION_BORROW_ALWAYS,
7980
};
8081

8182
enum class KeyPathComponentKindEncoding : uint8_t {

lib/Serialization/SerializeSIL.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ static unsigned toStableCastConsumptionKind(CastConsumptionKind kind) {
8585
return SIL_CAST_CONSUMPTION_TAKE_ON_SUCCESS;
8686
case CastConsumptionKind::CopyOnSuccess:
8787
return SIL_CAST_CONSUMPTION_COPY_ON_SUCCESS;
88+
case CastConsumptionKind::BorrowAlways:
89+
return SIL_CAST_CONSUMPTION_BORROW_ALWAYS;
8890
}
8991
llvm_unreachable("bad cast consumption kind");
9092
}

stdlib/public/SwiftShims/RefCount.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -788,7 +788,6 @@ class RefCounts {
788788
if (bits.hasSideTable())
789789
return bits.getSideTable()->getCount();
790790

791-
assert(!bits.getIsDeiniting()); // FIXME: can we assert this?
792791
return bits.getStrongExtraRefCount() + 1;
793792
}
794793

stdlib/public/runtime/HeapObject.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,9 @@ void swift::swift_nonatomic_release_n(HeapObject *object, uint32_t n) {
365365
}
366366

367367
size_t swift::swift_retainCount(HeapObject *object) {
368-
return object->refCounts.getCount();
368+
if (isValidPointerForNativeRetain(object))
369+
return object->refCounts.getCount();
370+
return 0;
369371
}
370372

371373
size_t swift::swift_unownedRetainCount(HeapObject *object) {

stdlib/public/runtime/SwiftObject.mm

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -580,10 +580,16 @@ static bool isNonNative_unTagged_bridgeObject(void *object) {
580580
static_assert((heap_object_abi::SwiftSpareBitsMask & objectPointerIsObjCBit) ==
581581
objectPointerIsObjCBit,
582582
"isObjC bit not within spare bits");
583-
return (uintptr_t(object) & objectPointerIsObjCBit) != 0 && (uintptr_t(object) & heap_object_abi::BridgeObjectTagBitsMask) == 0;
583+
return (uintptr_t(object) & objectPointerIsObjCBit) != 0
584+
&& (uintptr_t(object) & heap_object_abi::BridgeObjectTagBitsMask) == 0;
584585
}
585586
#endif
586587

588+
/// Return true iff the given BridgeObject is a tagged value.
589+
static bool isBridgeObjectTaggedPointer(void *object) {
590+
return (uintptr_t(object) & heap_object_abi::BridgeObjectTagBitsMask) != 0;
591+
}
592+
587593
// Mask out the spare bits in a bridgeObject, returning the object it
588594
// encodes.
589595
///
@@ -594,7 +600,7 @@ static bool isNonNative_unTagged_bridgeObject(void *object) {
594600

595601
void *swift::swift_bridgeObjectRetain(void *object) {
596602
#if SWIFT_OBJC_INTEROP
597-
if (isObjCTaggedPointer(object))
603+
if (isObjCTaggedPointer(object) || isBridgeObjectTaggedPointer(object))
598604
return object;
599605
#endif
600606

@@ -616,7 +622,7 @@ static bool isNonNative_unTagged_bridgeObject(void *object) {
616622
SWIFT_RUNTIME_EXPORT
617623
void *swift::swift_nonatomic_bridgeObjectRetain(void *object) {
618624
#if SWIFT_OBJC_INTEROP
619-
if (isObjCTaggedPointer(object))
625+
if (isObjCTaggedPointer(object) || isBridgeObjectTaggedPointer(object))
620626
return object;
621627
#endif
622628

@@ -638,7 +644,7 @@ static bool isNonNative_unTagged_bridgeObject(void *object) {
638644
SWIFT_RUNTIME_EXPORT
639645
void swift::swift_bridgeObjectRelease(void *object) {
640646
#if SWIFT_OBJC_INTEROP
641-
if (isObjCTaggedPointer(object))
647+
if (isObjCTaggedPointer(object) || isBridgeObjectTaggedPointer(object))
642648
return;
643649
#endif
644650

@@ -655,7 +661,7 @@ static bool isNonNative_unTagged_bridgeObject(void *object) {
655661

656662
void swift::swift_nonatomic_bridgeObjectRelease(void *object) {
657663
#if SWIFT_OBJC_INTEROP
658-
if (isObjCTaggedPointer(object))
664+
if (isObjCTaggedPointer(object) || isBridgeObjectTaggedPointer(object))
659665
return;
660666
#endif
661667

@@ -672,7 +678,7 @@ static bool isNonNative_unTagged_bridgeObject(void *object) {
672678

673679
void *swift::swift_bridgeObjectRetain_n(void *object, int n) {
674680
#if SWIFT_OBJC_INTEROP
675-
if (isObjCTaggedPointer(object))
681+
if (isObjCTaggedPointer(object) || isBridgeObjectTaggedPointer(object))
676682
return object;
677683
#endif
678684

@@ -695,7 +701,7 @@ static bool isNonNative_unTagged_bridgeObject(void *object) {
695701

696702
void swift::swift_bridgeObjectRelease_n(void *object, int n) {
697703
#if SWIFT_OBJC_INTEROP
698-
if (isObjCTaggedPointer(object))
704+
if (isObjCTaggedPointer(object) || isBridgeObjectTaggedPointer(object))
699705
return;
700706
#endif
701707

@@ -713,7 +719,7 @@ static bool isNonNative_unTagged_bridgeObject(void *object) {
713719

714720
void *swift::swift_nonatomic_bridgeObjectRetain_n(void *object, int n) {
715721
#if SWIFT_OBJC_INTEROP
716-
if (isObjCTaggedPointer(object))
722+
if (isObjCTaggedPointer(object) || isBridgeObjectTaggedPointer(object))
717723
return object;
718724
#endif
719725

@@ -736,7 +742,7 @@ static bool isNonNative_unTagged_bridgeObject(void *object) {
736742

737743
void swift::swift_nonatomic_bridgeObjectRelease_n(void *object, int n) {
738744
#if SWIFT_OBJC_INTEROP
739-
if (isObjCTaggedPointer(object))
745+
if (isObjCTaggedPointer(object) || isBridgeObjectTaggedPointer(object))
740746
return;
741747
#endif
742748

0 commit comments

Comments
 (0)