Skip to content

Commit c007bae

Browse files
committed
[SIL] Added weak_copy_value.
The new instruction wraps a value in a `@sil_weak` box and produces an owned value. It is only legal in opaque values mode and is transformed by `AddressLowering` to `store_weak`.
1 parent e135c5c commit c007bae

21 files changed

+140
-7
lines changed

docs/SIL.rst

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5191,8 +5191,9 @@ case, the strong reference count will be incremented before any changes to the
51915191
weak reference count.
51925192

51935193
This operation must be atomic with respect to the final ``strong_release`` on
5194-
the operand heap object. It need not be atomic with respect to ``store_weak``
5195-
or ``load_weak``/``strong_copy_weak_value`` operations on the same address.
5194+
the operand heap object. It need not be atomic with respect to
5195+
``store_weak``/``weak_copy_value`` or ``load_weak``/``strong_copy_weak_value``
5196+
operations on the same address.
51965197

51975198
strong_copy_weak_value
51985199
``````````````````````
@@ -5212,8 +5213,9 @@ its strong reference count and produces the value ``Optional.some`` holding the
52125213
object. Otherwise, produces the value ``Optional.none``.
52135214

52145215
This operation must be atomic with respect to the final ``strong_release`` on
5215-
the operand heap object. It need not be atomic with respect to ``store_weak``
5216-
or ``load_weak``/``strong_copy_weak_value`` operations on the same address.
5216+
the operand heap object. It need not be atomic with respect to
5217+
``store_weak``/``weak_copy_value`` or ``load_weak``/``strong_copy_weak_value``
5218+
operations on the same address.
52175219

52185220
store_weak
52195221
``````````
@@ -5239,8 +5241,30 @@ currently be initialized. After the evaluation:
52395241

52405242
This operation must be atomic with respect to the final ``strong_release`` on
52415243
the operand (source) heap object. It need not be atomic with respect to
5242-
``store_weak`` or ``load_weak``/``strong_copy_weak_value`` operations on the
5243-
same address.
5244+
``store_weak``/``weak_copy_value`` or ``load_weak``/``strong_copy_weak_value``
5245+
operations on the same address.
5246+
5247+
weak_copy_value
5248+
```````````````
5249+
::
5250+
5251+
sil-instruction ::= 'weak_copy_value' sil-operand
5252+
5253+
%1 = weak_copy_value %0 : $Optional<T>
5254+
// %1 will be an @owned value of type $@sil_weak Optional<T>.
5255+
// $T must be a reference type
5256+
// $@sil_weak Optional<T> must be address-only
5257+
5258+
Only valid in opaque values mode. Lowered by AddressLowering to store_weak.
5259+
5260+
If ``%0`` is non-nil, produces the value ``@sil_weak Optional.some`` holding the
5261+
object and increments the weak reference count by 1. Otherwise, produces the
5262+
value ``Optional.none`` wrapped in a ``@sil_weak`` box.
5263+
5264+
This operation must be atomic with respect to the final ``strong_release`` on
5265+
the operand (source) heap object. It need not be atomic with respect to
5266+
``store_weak``/``weak_copy_value`` or ``load_weak``/``strong_copy_weak_value``
5267+
operations on the same address.
52445268

52455269
load_unowned
52465270
````````````

include/swift/SIL/SILBuilder.h

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

1064+
WeakCopyValueInst *createWeakCopyValue(SILLocation Loc, SILValue operand) {
1065+
assert(!getFunction().getModule().useLoweredAddresses());
1066+
auto type = operand->getType()
1067+
.getReferenceStorageType(getFunction().getASTContext(),
1068+
ReferenceOwnership::Weak)
1069+
.getObjectType();
1070+
return insert(new (getModule()) WeakCopyValueInst(getSILDebugLocation(Loc),
1071+
operand, type));
1072+
}
1073+
10641074
#define COPYABLE_STORAGE_HELPER(Name) \
10651075
StrongCopy##Name##ValueInst *createStrongCopy##Name##Value( \
10661076
SILLocation Loc, SILValue operand) { \

include/swift/SIL/SILCloner.h

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

1410+
template <typename ImplClass>
1411+
void SILCloner<ImplClass>::visitWeakCopyValueInst(WeakCopyValueInst *Inst) {
1412+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
1413+
recordClonedInstruction(
1414+
Inst, getBuilder().createWeakCopyValue(getOpLocation(Inst->getLoc()),
1415+
getOpValue(Inst->getOperand())));
1416+
}
1417+
14101418
#define COPYABLE_STORAGE_HELPER(Name, name) \
14111419
template <typename ImplClass> \
14121420
void SILCloner<ImplClass>::visitStrongCopy##Name##ValueInst( \

include/swift/SIL/SILInstruction.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8098,6 +8098,17 @@ class ExplicitCopyValueInst
80988098
: UnaryInstructionBase(DebugLoc, operand, operand->getType()) {}
80998099
};
81008100

8101+
class WeakCopyValueInst
8102+
: public UnaryInstructionBase<SILInstructionKind::WeakCopyValueInst,
8103+
SingleValueInstruction> {
8104+
friend class SILBuilder;
8105+
WeakCopyValueInst(SILDebugLocation DebugLoc, SILValue operand, SILType type)
8106+
: UnaryInstructionBase(DebugLoc, operand, type) {
8107+
assert(type.getReferenceStorageOwnership() == ReferenceOwnership::Weak);
8108+
assert(type.getReferenceStorageReferentType() == operand->getType());
8109+
}
8110+
};
8111+
81018112
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
81028113
class StrongCopy##Name##ValueInst \
81038114
: public UnaryInstructionBase< \

include/swift/SIL/SILNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,8 @@ 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+
SINGLE_VALUE_INST(WeakCopyValueInst, weak_copy_value,
457+
SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
456458
#define REF_STORAGE(Name, name, ...) \
457459
SINGLE_VALUE_INST(StrongCopy##Name##ValueInst, strong_copy_##name##_value, \
458460
SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)

lib/IRGen/IRGenSIL.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1503,6 +1503,7 @@ class IRGenSILFunction :
15031503

15041504
void visitHasSymbolInst(HasSymbolInst *i);
15051505

1506+
void visitWeakCopyValueInst(swift::WeakCopyValueInst *i);
15061507
#define LOADABLE_REF_STORAGE_HELPER(Name) \
15071508
void visitRefTo##Name##Inst(RefTo##Name##Inst *i); \
15081509
void visit##Name##ToRefInst(Name##ToRefInst *i);
@@ -5356,6 +5357,10 @@ void IRGenSILFunction::visitStrongCopyWeakValueInst(
53565357
"strong_copy_weak_value not lowered by AddressLowering!?");
53575358
}
53585359

5360+
void IRGenSILFunction::visitWeakCopyValueInst(swift::WeakCopyValueInst *i) {
5361+
llvm::report_fatal_error("weak_copy_value not lowered by AddressLowering!?");
5362+
}
5363+
53595364
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \
53605365
void IRGenSILFunction::visitLoad##Name##Inst(swift::Load##Name##Inst *i) { \
53615366
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, WeakCopyValue)
223224
#define REF_STORAGE(Name, ...) \
224225
OPERAND_OWNERSHIP(InstantaneousUse, StrongCopy##Name##Value)
225226
#include "swift/AST/ReferenceStorage.def"

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 visitWeakCopyValueInst(WeakCopyValueInst *I) {
2145+
*this << getIDAndType(I->getOperand());
2146+
}
2147+
21442148
#define REF_STORAGE(Name, ...) \
21452149
void visitStrongCopy##Name##ValueInst(StrongCopy##Name##ValueInst *I) { \
21462150
*this << getIDAndType(I->getOperand()); \

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, WeakCopyValue)
5253
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
5354
CONSTANT_OWNERSHIP_INST(Owned, StrongCopy##Name##Value) \
5455
CONSTANT_OWNERSHIP_INST(Owned, Load##Name)

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(WeakCopyValue)
36493650
#define UNCHECKED_REF_STORAGE(Name, ...) \
36503651
UNARY_INSTRUCTION(StrongCopy##Name##Value)
36513652
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \

lib/SIL/Utils/InstructionUtils.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,8 @@ 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::WeakCopyValueInst:
852+
return RuntimeEffect::RefCounting;
851853
#define REF_STORAGE(Name, ...) \
852854
case SILInstructionKind::StrongCopy##Name##ValueInst: \
853855
return RuntimeEffect::RefCounting;

lib/SIL/Verifier/SILVerifier.cpp

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

2978+
void checkWeakCopyValueInst(WeakCopyValueInst *I) {
2979+
require(!F.getModule().useLoweredAddresses(),
2980+
"weak_copy_value is only valid in opaque values");
2981+
require(I->getType().isAddressOnly(F),
2982+
"weak_copy_value must produce an address-only value");
2983+
}
2984+
29782985
void checkStrongCopyWeakValueInst(StrongCopyWeakValueInst *I) {
29792986
require(!F.getModule().useLoweredAddresses(),
29802987
"strong_copy_weak_value is only valid in opaque values");

lib/SILGen/SILGenBuilder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ class SILGenBuilder : public SILBuilder {
132132
/// values.
133133
ManagedValue createExplicitCopyValue(SILLocation Loc, ManagedValue operand);
134134

135+
using SILBuilder::createWeakCopyValue;
136+
137+
ManagedValue createWeakCopyValue(SILLocation loc, ManagedValue originalValue);
138+
135139
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
136140
using SILBuilder::createStrongCopy##Name##Value; \
137141
ManagedValue createStrongCopy##Name##Value(SILLocation loc, \

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::WeakCopyValueInst:
213214
#define REF_STORAGE(Name, ...) \
214215
case SILInstructionKind::StrongCopy##Name##ValueInst:
215216
#include "swift/AST/ReferenceStorage.def"

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::WeakCopyValueInst:
11251126
#define COMMON_ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name) \
11261127
case SILInstructionKind::Name##ToRefInst: \
11271128
case SILInstructionKind::RefTo##Name##Inst: \

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(WeakCopyValue)
20852086
#define UNCHECKED_REF_STORAGE(Name, ...) \
20862087
UNARY_INSTRUCTION(StrongCopy##Name##Value)
20872088
#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \

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 = 798; // added strong_copy_weak_value
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 799; // added weak_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::WeakCopyValueInst:
14451446
#define UNCHECKED_REF_STORAGE(Name, ...) \
14461447
case SILInstructionKind::StrongCopy##Name##ValueInst:
14471448
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \

test/SIL/Parser/opaque_values_parse.sil

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,17 @@ bb0(%instance : @guaranteed $WeakBox<T>):
114114
%strong_optional = strong_copy_weak_value %weak_optional : $@sil_weak Optional<T>
115115
return %strong_optional : $Optional<T>
116116
}
117+
118+
// Test weak_copy_value parsing.
119+
120+
// CHECK-LABEL: sil [ossa] @test_weak_copy_value_1 : {{.*}} {
121+
// CHECK: bb0([[VALUE:%[^,]+]] :
122+
// CHECK: weak_copy_value [[VALUE]]
123+
// CHECK-LABEL: } // end sil function 'test_weak_copy_value_1'
124+
sil [ossa] @test_weak_copy_value_1 : $@convention(thin) <T where T : AnyObject> (@owned Optional<T>) -> @out WeakBox<T> {
125+
bb0(%value : @owned $Optional<T>):
126+
%weak_value = weak_copy_value %value : $Optional<T>
127+
destroy_value %value : $Optional<T>
128+
%retval = struct $WeakBox<T> (%weak_value : $@sil_weak Optional<T>)
129+
return %retval : $WeakBox<T>
130+
}

test/SIL/Serialization/opaque_values_serialize.sil

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,15 @@ bb0(%instance : @guaranteed $WeakBox<T>):
9898
%strong_optional = strong_copy_weak_value %weak_optional : $@sil_weak Optional<T>
9999
return %strong_optional : $Optional<T>
100100
}
101+
102+
// CHECK-LABEL: sil [ossa] @test_weak_copy_value_1 : {{.*}} {
103+
// CHECK: bb0([[VALUE:%[^,]+]] :
104+
// CHECK: weak_copy_value [[VALUE]]
105+
// CHECK-LABEL: } // end sil function 'test_weak_copy_value_1'
106+
sil [ossa] @test_weak_copy_value_1 : $@convention(thin) <T where T : AnyObject> (@owned Optional<T>) -> @out WeakBox<T> {
107+
bb0(%value : @owned $Optional<T>):
108+
%weak_value = weak_copy_value %value : $Optional<T>
109+
destroy_value %value : $Optional<T>
110+
%retval = struct $WeakBox<T> (%weak_value : $@sil_weak Optional<T>)
111+
return %retval : $WeakBox<T>
112+
}

test/SIL/cloning_opaque_values.sil

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,26 @@ bb0(%instance : @guaranteed $WeakBox<T>):
2828
%strong_optional = strong_copy_weak_value %weak_optional : $@sil_weak Optional<T>
2929
return %strong_optional : $Optional<T>
3030
}
31+
32+
// CHECK-LABEL: sil [ossa] @weak_copy_value_caller : {{.*}} {
33+
// CHECK: bb0([[STRONG_OPTIONAL:%[^,]+]] :
34+
// CHECK: [[WEAK_OPTIONAL:%[^,]+]] = weak_copy_value [[STRONG_OPTIONAL]]
35+
// CHECK: destroy_value [[STRONG_OPTIONAL]]
36+
// CHECK: [[RETVAL:%[^,]+]] = struct $WeakBox<T> ([[WEAK_OPTIONAL]] :
37+
// CHECK: return [[RETVAL]]
38+
// CHECK-LABEL: } // end sil function 'weak_copy_value_caller'
39+
sil [ossa] @weak_copy_value_caller : $@convention(thin) <T where T : AnyObject> (@owned Optional<T>) -> @out WeakBox<T> {
40+
bb0(%value : @owned $Optional<T>):
41+
%callee = function_ref @weak_copy_value : $@convention(thin) <T where T : AnyObject> (@owned Optional<T>) -> @out WeakBox<T>
42+
%retval = apply %callee<T>(%value) : $@convention(thin) <T where T : AnyObject> (@owned Optional<T>) -> @out WeakBox<T>
43+
return %retval : $WeakBox<T>
44+
}
45+
46+
sil [always_inline] [ossa] @weak_copy_value : $@convention(thin) <T where T : AnyObject> (@owned Optional<T>) -> @out WeakBox<T> {
47+
bb0(%value : @owned $Optional<T>):
48+
%weak_value = weak_copy_value %value : $Optional<T>
49+
destroy_value %value : $Optional<T>
50+
%retval = struct $WeakBox<T> (%weak_value : $@sil_weak Optional<T>)
51+
return %retval : $WeakBox<T>
52+
}
53+

0 commit comments

Comments
 (0)