Skip to content

Commit f938287

Browse files
committed
[SIL] Added unowned_copy_value.
1 parent 0cb3ce5 commit f938287

21 files changed

+172
-6
lines changed

docs/SIL.rst

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5285,8 +5285,8 @@ positive. Otherwise, traps.
52855285

52865286
This operation must be atomic with respect to the final ``strong_release`` on
52875287
the operand (source) heap object. It need not be atomic with respect to
5288-
``store_unowned`` or ``load_unowned``/``strong_copy_unowned_value`` operations
5289-
on the same address.
5288+
``store_unowned``/``unowned_copy_value`` or
5289+
``load_unowned``/``strong_copy_unowned_value`` operations on the same address.
52905290

52915291
store_unowned
52925292
`````````````
@@ -5306,9 +5306,30 @@ The storage must be initialized iff ``[init]`` is not specified.
53065306

53075307
This operation must be atomic with respect to the final ``strong_release`` on
53085308
the operand (source) heap object. It need not be atomic with respect to
5309-
``store_unowned`` or ``load_unowned``/``strong_copy_unowned_value`` operations
5310-
on the same address.
5309+
``store_unowned``/``unowned_copy_value`` or
5310+
``load_unowned``/``strong_copy_unowned_value`` operations on the same address.
53115311

5312+
unowned_copy_value
5313+
``````````````````
5314+
::
5315+
5316+
sil-instruction ::= 'unowned_copy_value' sil-operand
5317+
5318+
%1 = unowned_copy_value %0 : $T
5319+
// %1 will be an @owned value of type $@sil_unowned T.
5320+
// $T must be a reference type
5321+
// $@sil_unowned T must be address-only
5322+
5323+
Only valid in opaque values mode. Lowered by AddressLowering to store_unowned.
5324+
5325+
Increments the unowned reference count of the object at ``%0``.
5326+
5327+
Wraps the operand in an instance of ``@sil_unowned``.
5328+
5329+
This operation must be atomic with respect to the final ``strong_release`` on
5330+
the operand (source) heap object. It need not be atomic with respect to
5331+
``store_unowned``/``unowned_copy_value`` or
5332+
``load_unowned``/``strong_copy_unowned_value`` operations on the same address.
53125333

53135334
fix_lifetime
53145335
````````````

include/swift/SIL/SILBuilder.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,17 @@ class SILBuilder {
10611061
getSILDebugLocation(Loc), ArgumentsSpecification, getModule()));
10621062
}
10631063

1064+
UnownedCopyValueInst *createUnownedCopyValue(SILLocation Loc,
1065+
SILValue operand) {
1066+
assert(!getFunction().getModule().useLoweredAddresses());
1067+
auto type = operand->getType()
1068+
.getReferenceStorageType(getFunction().getASTContext(),
1069+
ReferenceOwnership::Unowned)
1070+
.getObjectType();
1071+
return insert(new (getModule()) UnownedCopyValueInst(
1072+
getSILDebugLocation(Loc), operand, type));
1073+
}
1074+
10641075
WeakCopyValueInst *createWeakCopyValue(SILLocation Loc, SILValue operand) {
10651076
assert(!getFunction().getModule().useLoweredAddresses());
10661077
auto type = operand->getType()

include/swift/SIL/SILCloner.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,6 +1407,15 @@ SILCloner<ImplClass>::visitDebugStepInst(DebugStepInst *Inst) {
14071407
recordClonedInstruction(Inst, getBuilder().createDebugStep(Inst->getLoc()));
14081408
}
14091409

1410+
template <typename ImplClass>
1411+
void SILCloner<ImplClass>::visitUnownedCopyValueInst(
1412+
UnownedCopyValueInst *Inst) {
1413+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
1414+
recordClonedInstruction(
1415+
Inst, getBuilder().createUnownedCopyValue(
1416+
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand())));
1417+
}
1418+
14101419
template <typename ImplClass>
14111420
void SILCloner<ImplClass>::visitWeakCopyValueInst(WeakCopyValueInst *Inst) {
14121421
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));

include/swift/SIL/SILInstruction.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8109,6 +8109,18 @@ class WeakCopyValueInst
81098109
}
81108110
};
81118111

8112+
class UnownedCopyValueInst
8113+
: public UnaryInstructionBase<SILInstructionKind::UnownedCopyValueInst,
8114+
SingleValueInstruction> {
8115+
friend class SILBuilder;
8116+
UnownedCopyValueInst(SILDebugLocation DebugLoc, SILValue operand,
8117+
SILType type)
8118+
: UnaryInstructionBase(DebugLoc, operand, type) {
8119+
assert(type.getReferenceStorageOwnership() == ReferenceOwnership::Unowned);
8120+
assert(type.getReferenceStorageReferentType() == operand->getType());
8121+
}
8122+
};
8123+
81128124
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
81138125
class StrongCopy##Name##ValueInst \
81148126
: public UnaryInstructionBase< \

include/swift/SIL/SILNodes.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,9 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
453453
// alone by OSSA optimizations.
454454
SINGLE_VALUE_INST(ExplicitCopyValueInst, explicit_copy_value,
455455
SingleValueInstruction, None, DoesNotRelease)
456+
// Produce a @sil_unowned value from the specified value of reference type.
457+
SINGLE_VALUE_INST(UnownedCopyValueInst, unowned_copy_value,
458+
SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
456459
SINGLE_VALUE_INST(WeakCopyValueInst, weak_copy_value,
457460
SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
458461
#define REF_STORAGE(Name, name, ...) \

lib/IRGen/IRGenSIL.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,6 +1504,7 @@ class IRGenSILFunction :
15041504
void visitHasSymbolInst(HasSymbolInst *i);
15051505

15061506
void visitWeakCopyValueInst(swift::WeakCopyValueInst *i);
1507+
void visitUnownedCopyValueInst(swift::UnownedCopyValueInst *i);
15071508
#define LOADABLE_REF_STORAGE_HELPER(Name) \
15081509
void visitRefTo##Name##Inst(RefTo##Name##Inst *i); \
15091510
void visit##Name##ToRefInst(Name##ToRefInst *i);
@@ -5361,6 +5362,12 @@ void IRGenSILFunction::visitWeakCopyValueInst(swift::WeakCopyValueInst *i) {
53615362
llvm::report_fatal_error("weak_copy_value not lowered by AddressLowering!?");
53625363
}
53635364

5365+
void IRGenSILFunction::visitUnownedCopyValueInst(
5366+
swift::UnownedCopyValueInst *i) {
5367+
llvm::report_fatal_error(
5368+
"unowned_copy_value not lowered by AddressLowering!?");
5369+
}
5370+
53645371
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \
53655372
void IRGenSILFunction::visitLoad##Name##Inst(swift::Load##Name##Inst *i) { \
53665373
Address source = getLoweredAddress(i->getOperand()); \

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ OPERAND_OWNERSHIP(InstantaneousUse, ClassMethod)
220220
OPERAND_OWNERSHIP(InstantaneousUse, SuperMethod)
221221
OPERAND_OWNERSHIP(InstantaneousUse, ClassifyBridgeObject)
222222
OPERAND_OWNERSHIP(InstantaneousUse, SetDeallocating)
223+
OPERAND_OWNERSHIP(InstantaneousUse, UnownedCopyValue)
223224
OPERAND_OWNERSHIP(InstantaneousUse, WeakCopyValue)
224225
#define REF_STORAGE(Name, ...) \
225226
OPERAND_OWNERSHIP(InstantaneousUse, StrongCopy##Name##Value)

lib/SIL/IR/SILPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2141,6 +2141,10 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
21412141
*this << getIDAndType(I->getOperand());
21422142
}
21432143

2144+
void visitUnownedCopyValueInst(UnownedCopyValueInst *I) {
2145+
*this << getIDAndType(I->getOperand());
2146+
}
2147+
21442148
void visitWeakCopyValueInst(WeakCopyValueInst *I) {
21452149
*this << getIDAndType(I->getOperand());
21462150
}

lib/SIL/IR/ValueOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class ValueOwnershipKindClassifier
4949
return OwnershipKind::OWNERSHIP; \
5050
}
5151

52+
CONSTANT_OWNERSHIP_INST(Owned, UnownedCopyValue)
5253
CONSTANT_OWNERSHIP_INST(Owned, WeakCopyValue)
5354
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
5455
CONSTANT_OWNERSHIP_INST(Owned, StrongCopy##Name##Value) \

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3646,6 +3646,7 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
36463646
REFCOUNTING_INSTRUCTION(RetainValue)
36473647
REFCOUNTING_INSTRUCTION(ReleaseValueAddr)
36483648
REFCOUNTING_INSTRUCTION(RetainValueAddr)
3649+
UNARY_INSTRUCTION(UnownedCopyValue)
36493650
UNARY_INSTRUCTION(WeakCopyValue)
36503651
#define UNCHECKED_REF_STORAGE(Name, ...) \
36513652
UNARY_INSTRUCTION(StrongCopy##Name##Value)

lib/SIL/Utils/InstructionUtils.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,7 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType)
848848
#include "swift/AST/ReferenceStorage.def"
849849
#undef ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE
850850

851+
case SILInstructionKind::UnownedCopyValueInst:
851852
case SILInstructionKind::WeakCopyValueInst:
852853
return RuntimeEffect::RefCounting;
853854
#define REF_STORAGE(Name, ...) \

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2983,6 +2983,13 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
29832983
"'MoveOnly' types can only be copied in Raw SIL?!");
29842984
}
29852985

2986+
void checkUnownedCopyValueInst(UnownedCopyValueInst *I) {
2987+
require(!F.getModule().useLoweredAddresses(),
2988+
"unowned_copy_value is only valid in opaque values");
2989+
require(I->getType().isAddressOnly(F),
2990+
"unowned_copy_value must produce an address-only value");
2991+
}
2992+
29862993
void checkWeakCopyValueInst(WeakCopyValueInst *I) {
29872994
require(!F.getModule().useLoweredAddresses(),
29882995
"weak_copy_value is only valid in opaque values");

lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ static bool hasOpaqueArchetype(TypeExpansionContext context,
210210
case SILInstructionKind::MarkUnresolvedReferenceBindingInst:
211211
case SILInstructionKind::CopyableToMoveOnlyWrapperValueInst:
212212
case SILInstructionKind::MoveOnlyWrapperToCopyableValueInst:
213+
case SILInstructionKind::UnownedCopyValueInst:
213214
case SILInstructionKind::WeakCopyValueInst:
214215
#define REF_STORAGE(Name, ...) \
215216
case SILInstructionKind::StrongCopy##Name##ValueInst:

lib/SILOptimizer/Utils/SILInliner.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,6 +1122,7 @@ InlineCost swift::instructionInlineCost(SILInstruction &I) {
11221122
case SILInstructionKind::HopToExecutorInst:
11231123
case SILInstructionKind::ExtractExecutorInst:
11241124
case SILInstructionKind::HasSymbolInst:
1125+
case SILInstructionKind::UnownedCopyValueInst:
11251126
case SILInstructionKind::WeakCopyValueInst:
11261127
#define COMMON_ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name) \
11271128
case SILInstructionKind::Name##ToRefInst: \

lib/Serialization/DeserializeSIL.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2082,6 +2082,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn,
20822082
(Atomicity)Attr); \
20832083
break;
20842084

2085+
UNARY_INSTRUCTION(UnownedCopyValue)
20852086
UNARY_INSTRUCTION(WeakCopyValue)
20862087
#define UNCHECKED_REF_STORAGE(Name, ...) \
20872088
UNARY_INSTRUCTION(StrongCopy##Name##Value)

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 799; // added weak_copy_value
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 800; // added unowned_copy_value
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///

lib/Serialization/SerializeSIL.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
14421442
ListOfValues);
14431443
break;
14441444
}
1445+
case SILInstructionKind::UnownedCopyValueInst:
14451446
case SILInstructionKind::WeakCopyValueInst:
14461447
#define UNCHECKED_REF_STORAGE(Name, ...) \
14471448
case SILInstructionKind::StrongCopy##Name##ValueInst:
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-sil-opt -enable-sil-opaque-values -enable-sil-verify-all -emit-sorted-sil %s | %FileCheck %s
2+
3+
// REQUIRES: objc_interop
4+
5+
import Builtin
6+
import Swift
7+
8+
struct UnownedBox<T : AnyObject> {
9+
unowned var value: T
10+
}
11+
12+
// CHECK-LABEL: sil [ossa] @test_unowned_copy_value : {{.*}} {
13+
// CHECK: bb0([[VALUE:%[^,]+]] :
14+
// CHECK: unowned_copy_value [[VALUE]]
15+
// CHECK-LABEL: } // end sil function 'test_unowned_copy_value'
16+
sil [ossa] @test_unowned_copy_value : $@convention(thin) <T where T : AnyObject> (@owned T) -> @out UnownedBox<T> {
17+
bb0(%owned_value : @owned $T):
18+
%unowned_value = unowned_copy_value %owned_value : $T
19+
destroy_value %owned_value : $T
20+
%instance = struct $UnownedBox<T> (%unowned_value : $@sil_unowned T)
21+
return %instance : $UnownedBox<T>
22+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// First parse this and then emit a *.sib. Then read in the *.sib, then recreate
2+
// RUN: %empty-directory(%t)
3+
// FIXME: <rdar://problem/29281364> sil-opt -verify is broken
4+
// RUN: %target-sil-opt %s -enable-sil-opaque-values -emit-sib -o %t/tmp.sib -module-name opaqueval
5+
// RUN: %target-sil-opt %t/tmp.sib -enable-sil-opaque-values -verify -o %t/tmp.2.sib -module-name opaqueval
6+
// RUN: %target-sil-opt %t/tmp.2.sib -enable-sil-opaque-values -emit-sorted-sil -verify -module-name opaqueval | %FileCheck %s
7+
8+
// REQUIRES: objc_interop
9+
10+
sil_stage raw
11+
12+
import Builtin
13+
import Swift
14+
15+
struct UnownedBox<T : AnyObject> {
16+
unowned var value: T
17+
}
18+
19+
// CHECK-LABEL: sil [ossa] @test_unowned_copy_value : {{.*}} {
20+
// CHECK: bb0([[VALUE:%[^,]+]] :
21+
// CHECK: unowned_copy_value [[VALUE]]
22+
// CHECK-LABEL: } // end sil function 'test_unowned_copy_value'
23+
sil [ossa] @test_unowned_copy_value : $@convention(thin) <T where T : AnyObject> (@owned T) -> @out UnownedBox<T> {
24+
bb0(%owned_value : @owned $T):
25+
%unowned_value = unowned_copy_value %owned_value : $T
26+
destroy_value %owned_value : $T
27+
%instance = struct $UnownedBox<T> (%unowned_value : $@sil_unowned T)
28+
return %instance : $UnownedBox<T>
29+
}
30+

test/SIL/cloning_opaque_values.sil

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ struct WeakBox<T : AnyObject> {
88
weak var t: T?
99
}
1010

11-
1211
// CHECK-LABEL: sil [ossa] @strong_copy_weak_value_caller : {{.*}} {
1312
// CHECK: bb0([[INSTANCE:%[^,]+]] :
1413
// CHECK: [[WEAK_OPTIONAL:%[^,]+]] = struct_extract [[INSTANCE]]
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all -enable-sil-opaque-values -inline %s | %FileCheck %s
2+
3+
// Check cloning of instructions that are only legal in opaque values mode.
4+
5+
// REQUIRES: objc_interop
6+
7+
import Swift
8+
9+
struct UnownedBox<T : AnyObject> {
10+
unowned var value: T
11+
}
12+
13+
// CHECK-LABEL: sil [ossa] @unowned_copy_value_caller : {{.*}} {
14+
// CHECK: bb0([[STRONG:%[^,]+]] :
15+
// CHECK: [[UNOWNED:%[^,]+]] = unowned_copy_value [[STRONG]]
16+
// CHECK: destroy_value [[STRONG]]
17+
// CHECK: [[RETVAL:%[^,]+]] = struct $UnownedBox<T> ([[UNOWNED]] :
18+
// CHECK: return [[RETVAL]]
19+
// CHECK-LABEL: } // end sil function 'unowned_copy_value_caller'
20+
sil [ossa] @unowned_copy_value_caller : $@convention(thin) <T where T : AnyObject> (@owned T) -> @out UnownedBox<T> {
21+
bb0(%value : @owned $T):
22+
%callee = function_ref @unowned_copy_value : $@convention(thin) <T where T : AnyObject> (@owned T) -> @out UnownedBox<T>
23+
%retval = apply %callee<T>(%value) : $@convention(thin) <T where T : AnyObject> (@owned T) -> @out UnownedBox<T>
24+
return %retval : $UnownedBox<T>
25+
}
26+
27+
sil [always_inline] [ossa] @unowned_copy_value : $@convention(thin) <T where T : AnyObject> (@owned T) -> @out UnownedBox<T> {
28+
bb0(%owned_value : @owned $T):
29+
%unowned_value = unowned_copy_value %owned_value : $T
30+
destroy_value %owned_value : $T
31+
%instance = struct $UnownedBox<T> (%unowned_value : $@sil_unowned T)
32+
return %instance : $UnownedBox<T>
33+
}

0 commit comments

Comments
 (0)