Skip to content

Commit 3ea9e9e

Browse files
authored
Merge pull request swiftlang#39984 from gottesmm/pr-135d6a4f34ad56ff7b7f978fdb5599412fd608c0
[moveOnly] Add a semi-generic _copy function similar to the semi-generic _move
2 parents 06fbca6 + 3a5049f commit 3ea9e9e

31 files changed

+366
-4
lines changed

docs/SIL.rst

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5205,6 +5205,36 @@ independent of the operand. In terms of specific types:
52055205
In ownership qualified functions, a ``copy_value`` produces a +1 value that must
52065206
be consumed at most once along any path through the program.
52075207

5208+
explicit_copy_value
5209+
```````````````````
5210+
5211+
::
5212+
5213+
sil-instruction ::= 'explicit_copy_value' sil-operand
5214+
5215+
%1 = explicit_copy_value %0 : $A
5216+
5217+
Performs a copy of a loadable value as if by the value's type lowering and
5218+
returns the copy. The returned copy semantically is a value that is completely
5219+
independent of the operand. In terms of specific types:
5220+
5221+
1. For trivial types, this is equivalent to just propagating through the trivial
5222+
value.
5223+
2. For reference types, this is equivalent to performing a ``strong_retain``
5224+
operation and returning the reference.
5225+
3. For ``@unowned`` types, this is equivalent to performing an
5226+
``unowned_retain`` and returning the operand.
5227+
4. For aggregate types, this is equivalent to recursively performing a
5228+
``copy_value`` on its components, forming a new aggregate from the copied
5229+
components, and then returning the new aggregate.
5230+
5231+
In ownership qualified functions, a ``explicit_copy_value`` produces a +1 value
5232+
that must be consumed at most once along any path through the program.
5233+
5234+
When move only variable checking is performed, ``explicit_copy_value`` is
5235+
treated as an explicit copy asked for by the user that should not be rewritten
5236+
and should be treated as a non-consuming use.
5237+
52085238
move_value
52095239
``````````
52105240

include/swift/AST/Builtins.def

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,24 @@ BUILTIN_MISC_OPERATION(DestroyTaskGroup,
790790
/// the SILVerifier.
791791
BUILTIN_MISC_OPERATION(Move, "move", "", Special)
792792

793+
/// A builtin that can only be called from a transparent generic function. Takes
794+
/// two operands, the first operand the result address, the second operand the
795+
/// input address. Transforms into
796+
///
797+
/// %input = load [take] %inputAddr
798+
/// %result = explicit_copy_value %input
799+
/// store %result to [init] %resultAddr
800+
/// store %input to [init] %inputAddr
801+
///
802+
/// transparently inlined into a caller that has the generic of the callee
803+
/// specialized into a loadable type. If the transparent inlining does not
804+
/// specialize the type (due to being inlined into a non-generic context, the
805+
/// SILVerifier will abort).
806+
///
807+
/// Illegal to call except for in Swift._copy in the stdlib. This is enforced by
808+
/// the SILVerifier.
809+
BUILTIN_MISC_OPERATION(Copy, "copy", "", Special)
810+
793811
// BUILTIN_MISC_OPERATION_WITH_SILGEN - Miscellaneous operations that are
794812
// specially emitted during SIL generation.
795813
//

include/swift/AST/DiagnosticsSIL.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,10 @@ NOTE(capturepromotion_variable_defined_here,none,
718718
ERROR(move_operator_used_on_generic_or_existential_value, none,
719719
"move() used on a generic or existential value", ())
720720

721+
// copy operator used on generic or evalue
722+
ERROR(copy_operator_used_on_generic_or_existential_value, none,
723+
"copy() used on a generic or existential value", ())
724+
721725
// noimplicitcopy on generic or existential binding
722726
ERROR(noimplicitcopy_used_on_generic_or_existential, none,
723727
"@_noImplicitCopy can not be used on a generic or existential typed "

include/swift/AST/SemanticAttrs.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ SEMANTICS_ATTR(FORCE_EMIT_OPT_REMARK_PREFIX, "optremark")
114114
SEMANTICS_ATTR(OBJC_FORBID_ASSOCIATED_OBJECTS, "objc.forbidAssociatedObjects")
115115

116116
SEMANTICS_ATTR(LIFETIMEMANAGEMENT_MOVE, "lifetimemanagement.move")
117+
SEMANTICS_ATTR(LIFETIMEMANAGEMENT_COPY, "lifetimemanagement.copy")
117118

118119
SEMANTICS_ATTR(NO_PERFORMANCE_ANALYSIS, "no_performance_analysis")
119120

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,6 @@ LANGUAGE_FEATURE(BuiltinBuildExecutor, 0, "Executor-building builtins", true)
5555
LANGUAGE_FEATURE(BuiltinBuildMainExecutor, 0, "MainActor executor building builtin", true)
5656
LANGUAGE_FEATURE(BuiltinCreateAsyncTaskInGroup, 0, "MainActor executor building builtin", true)
5757
LANGUAGE_FEATURE(BuiltinMove, 0, "Builtin.move()", true)
58+
LANGUAGE_FEATURE(BuiltinCopy, 0, "Builtin.copy()", true)
5859

5960
#undef LANGUAGE_FEATURE

include/swift/SIL/SILBuilder.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,15 @@ class SILBuilder {
12371237
CopyValueInst(getSILDebugLocation(Loc), operand));
12381238
}
12391239

1240+
ExplicitCopyValueInst *createExplicitCopyValue(SILLocation Loc,
1241+
SILValue operand) {
1242+
assert(!operand->getType().isTrivial(getFunction()) &&
1243+
"Should not be passing trivial values to this api. Use instead "
1244+
"emitCopyValueOperation");
1245+
return insert(new (getModule())
1246+
ExplicitCopyValueInst(getSILDebugLocation(Loc), operand));
1247+
}
1248+
12401249
DestroyValueInst *createDestroyValue(SILLocation Loc, SILValue operand,
12411250
bool poisonRefs = false) {
12421251
assert(isLoadableOrOpaque(operand->getType()));

include/swift/SIL/SILCloner.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1713,6 +1713,21 @@ void SILCloner<ImplClass>::visitCopyValueInst(CopyValueInst *Inst) {
17131713
getOpValue(Inst->getOperand())));
17141714
}
17151715

1716+
template <typename ImplClass>
1717+
void SILCloner<ImplClass>::visitExplicitCopyValueInst(
1718+
ExplicitCopyValueInst *Inst) {
1719+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
1720+
if (!getBuilder().hasOwnership()) {
1721+
SILValue newValue = getBuilder().emitCopyValueOperation(
1722+
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()));
1723+
return recordFoldedValue(Inst, newValue);
1724+
}
1725+
1726+
recordClonedInstruction(
1727+
Inst, getBuilder().createExplicitCopyValue(
1728+
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand())));
1729+
}
1730+
17161731
template <typename ImplClass>
17171732
void SILCloner<ImplClass>::visitMoveValueInst(MoveValueInst *Inst) {
17181733
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));

include/swift/SIL/SILInstruction.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7267,6 +7267,15 @@ class CopyValueInst
72677267
: UnaryInstructionBase(DebugLoc, operand, operand->getType()) {}
72687268
};
72697269

7270+
class ExplicitCopyValueInst
7271+
: public UnaryInstructionBase<SILInstructionKind::ExplicitCopyValueInst,
7272+
SingleValueInstruction> {
7273+
friend class SILBuilder;
7274+
7275+
ExplicitCopyValueInst(SILDebugLocation DebugLoc, SILValue operand)
7276+
: UnaryInstructionBase(DebugLoc, operand, operand->getType()) {}
7277+
};
7278+
72707279
#define UNCHECKED_REF_STORAGE(Name, ...) \
72717280
class StrongCopy##Name##ValueInst \
72727281
: public UnaryInstructionBase< \

include/swift/SIL/SILNodes.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,10 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
575575
// A copy_value's retain semantics are fully encapsulated in OSSA
576576
// invariants. It has no side effects relative to other OSSA values.
577577
BRIDGED_SINGLE_VALUE_INST(CopyValueInst, copy_value,
578+
SingleValueInstruction, None, DoesNotRelease)
579+
// A copy_value instruction that was explicitly asked for by the user. Left
580+
// alone by OSSA optimizations.
581+
SINGLE_VALUE_INST(ExplicitCopyValueInst, explicit_copy_value,
578582
SingleValueInstruction, None, DoesNotRelease)
579583
#define UNCHECKED_REF_STORAGE(Name, name, ...) \
580584
SINGLE_VALUE_INST(StrongCopy##Name##ValueInst, strong_copy_##name##_value, \

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2816,6 +2816,8 @@ static bool usesFeatureBuiltinMove(Decl *decl) {
28162816
return false;
28172817
}
28182818

2819+
static bool usesFeatureBuiltinCopy(Decl *decl) { return false; }
2820+
28192821
static bool usesFeatureInheritActorContext(Decl *decl) {
28202822
if (auto func = dyn_cast<AbstractFunctionDecl>(decl)) {
28212823
for (auto param : *func->getParameters()) {

0 commit comments

Comments
 (0)