Skip to content

Commit 5baf2af

Browse files
committed
[sil] Add a new instruction called explicit_copy_addr.
This is exactly like copy_addr except that it is not viewed from the verifiers perspective as an "invalid" copy of a move only value. It is intended to be used in two contexts: 1. When the move checker emits a diagnostic since it could not eliminate a copy, we still need to produce valid SIL without copy_addr on move only types since we will hit canonical SIL eventually even if we don't actually codegen the SIL. The pass can just convert said copy_addr to explicit_copy_addr and everyone is happy. 2. To implement the explicit copy function for address only types.
1 parent 82ae1d1 commit 5baf2af

File tree

19 files changed

+249
-1
lines changed

19 files changed

+249
-1
lines changed

docs/SIL.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4245,6 +4245,25 @@ operations::
42454245
If ``T`` is a trivial type, then ``copy_addr`` is always equivalent to its
42464246
take-initialization form.
42474247

4248+
It is illegal in non-Raw SIL to apply ``copy_addr [init]`` to a value that is
4249+
move only.
4250+
4251+
explicit_copy_addr
4252+
``````````````````
4253+
::
4254+
4255+
sil-instruction ::= 'explicit_copy_addr' '[take]'? sil-value
4256+
'to' '[initialization]'? sil-operand
4257+
4258+
explicit_copy_addr [take] %0 to [initialization] %1 : $*T
4259+
// %0 and %1 must be of the same $*T address type
4260+
4261+
This instruction is exactly the same as `copy_addr`_ except that it has special
4262+
behavior for move only types. Specifically, an `explicit_copy_addr`_ is viewed
4263+
as a copy_addr that is allowed on values that are move only. This is only used
4264+
by a move checker after it has emitted an error diagnostic to preserve the
4265+
general ``copy_addr [init]`` ban in Canonical SIL on move only types.
4266+
42484267
destroy_addr
42494268
````````````
42504269
::

include/swift/SIL/SILBuilder.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,14 @@ class SILBuilder {
10371037
getSILDebugLocation(Loc), srcAddr, destAddr, isTake, isInitialize));
10381038
}
10391039

1040+
ExplicitCopyAddrInst *
1041+
createExplicitCopyAddr(SILLocation Loc, SILValue srcAddr, SILValue destAddr,
1042+
IsTake_t isTake, IsInitialization_t isInitialize) {
1043+
assert(srcAddr->getType() == destAddr->getType());
1044+
return insert(new (getModule()) ExplicitCopyAddrInst(
1045+
getSILDebugLocation(Loc), srcAddr, destAddr, isTake, isInitialize));
1046+
}
1047+
10401048
BindMemoryInst *createBindMemory(SILLocation Loc, SILValue base,
10411049
SILValue index, SILType boundType) {
10421050
return insert(BindMemoryInst::create(getSILDebugLocation(Loc), base, index,

include/swift/SIL/SILCloner.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,17 @@ SILCloner<ImplClass>::visitCopyAddrInst(CopyAddrInst *Inst) {
13831383
Inst->isInitializationOfDest()));
13841384
}
13851385

1386+
template <typename ImplClass>
1387+
void SILCloner<ImplClass>::visitExplicitCopyAddrInst(
1388+
ExplicitCopyAddrInst *Inst) {
1389+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
1390+
recordClonedInstruction(
1391+
Inst, getBuilder().createExplicitCopyAddr(
1392+
getOpLocation(Inst->getLoc()), getOpValue(Inst->getSrc()),
1393+
getOpValue(Inst->getDest()), Inst->isTakeOfSrc(),
1394+
Inst->isInitializationOfDest()));
1395+
}
1396+
13861397
template <typename ImplClass>
13871398
void SILCloner<ImplClass>::visitMarkUnresolvedMoveAddrInst(
13881399
MarkUnresolvedMoveAddrInst *Inst) {

include/swift/SIL/SILInstruction.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5000,6 +5000,48 @@ class CopyAddrInst
50005000
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
50015001
};
50025002

5003+
/// ExplicitCopyAddrInst - A copy_addr that should not be optimized and should
5004+
/// be viewed
5005+
class ExplicitCopyAddrInst
5006+
: public InstructionBase<SILInstructionKind::ExplicitCopyAddrInst,
5007+
NonValueInstruction>,
5008+
public CopyLikeInstruction {
5009+
friend SILBuilder;
5010+
5011+
private:
5012+
FixedOperandList<2> Operands;
5013+
USE_SHARED_UINT8;
5014+
5015+
ExplicitCopyAddrInst(SILDebugLocation DebugLoc, SILValue Src, SILValue Dest,
5016+
IsTake_t isTakeOfSrc,
5017+
IsInitialization_t isInitializationOfDest);
5018+
5019+
public:
5020+
SILValue getSrc() const { return Operands[Src].get(); }
5021+
SILValue getDest() const { return Operands[Dest].get(); }
5022+
5023+
void setSrc(SILValue V) { Operands[Src].set(V); }
5024+
void setDest(SILValue V) { Operands[Dest].set(V); }
5025+
5026+
IsTake_t isTakeOfSrc() const {
5027+
return IsTake_t(sharedUInt8().ExplicitCopyAddrInst.isTakeOfSrc);
5028+
}
5029+
IsInitialization_t isInitializationOfDest() const {
5030+
return IsInitialization_t(
5031+
sharedUInt8().ExplicitCopyAddrInst.isInitializationOfDest);
5032+
}
5033+
5034+
void setIsTakeOfSrc(IsTake_t T) {
5035+
sharedUInt8().ExplicitCopyAddrInst.isTakeOfSrc = (bool)T;
5036+
}
5037+
void setIsInitializationOfDest(IsInitialization_t I) {
5038+
sharedUInt8().ExplicitCopyAddrInst.isInitializationOfDest = (bool)I;
5039+
}
5040+
5041+
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
5042+
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
5043+
};
5044+
50035045
/// "%token = bind_memory %0 : $Builtin.RawPointer, %1 : $Builtin.Word to $T"
50045046
///
50055047
/// Binds memory at the raw pointer %0 to type $T with enough capacity

include/swift/SIL/SILNode.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,10 @@ class alignas(8) SILNode :
219219
isTakeOfSrc : 1,
220220
isInitializationOfDest : 1);
221221

222+
SHARED_FIELD(ExplicitCopyAddrInst, uint8_t
223+
isTakeOfSrc : 1,
224+
isInitializationOfDest : 1);
225+
222226
SHARED_FIELD(PointerToAddressInst, uint8_t
223227
isStrict : 1,
224228
isInvariant : 1);

include/swift/SIL/SILNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,8 @@ BRIDGED_NON_VALUE_INST(DebugValueInst, debug_value,
781781
#include "swift/AST/ReferenceStorage.def"
782782
BRIDGED_NON_VALUE_INST(CopyAddrInst, copy_addr,
783783
SILInstruction, MayHaveSideEffects, MayRelease)
784+
BRIDGED_NON_VALUE_INST(ExplicitCopyAddrInst, explicit_copy_addr,
785+
SILInstruction, MayHaveSideEffects, MayRelease)
784786
BRIDGED_NON_VALUE_INST(DestroyAddrInst, destroy_addr,
785787
SILInstruction, MayHaveSideEffects, MayRelease)
786788
NON_VALUE_INST(EndLifetimeInst, end_lifetime,

lib/IRGen/IRGenSIL.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,6 +1310,7 @@ class IRGenSILFunction :
13101310
void visitDeallocPartialRefInst(DeallocPartialRefInst *i);
13111311

13121312
void visitCopyAddrInst(CopyAddrInst *i);
1313+
void visitExplicitCopyAddrInst(ExplicitCopyAddrInst *i);
13131314
void visitMarkUnresolvedMoveAddrInst(MarkUnresolvedMoveAddrInst *mai) {
13141315
llvm_unreachable("Valid only when ownership is enabled");
13151316
}
@@ -6884,6 +6885,30 @@ void IRGenSILFunction::visitCopyAddrInst(swift::CopyAddrInst *i) {
68846885
}
68856886
}
68866887

6888+
void IRGenSILFunction::visitExplicitCopyAddrInst(
6889+
swift::ExplicitCopyAddrInst *i) {
6890+
SILType addrTy = i->getSrc()->getType();
6891+
const TypeInfo &addrTI = getTypeInfo(addrTy);
6892+
Address src = getLoweredAddress(i->getSrc());
6893+
// See whether we have a deferred fixed-size buffer initialization.
6894+
auto &loweredDest = getLoweredValue(i->getDest());
6895+
assert(!loweredDest.isUnallocatedAddressInBuffer());
6896+
Address dest = loweredDest.getAnyAddress();
6897+
if (i->isInitializationOfDest()) {
6898+
if (i->isTakeOfSrc()) {
6899+
addrTI.initializeWithTake(*this, dest, src, addrTy, false);
6900+
} else {
6901+
addrTI.initializeWithCopy(*this, dest, src, addrTy, false);
6902+
}
6903+
} else {
6904+
if (i->isTakeOfSrc()) {
6905+
addrTI.assignWithTake(*this, dest, src, addrTy, false);
6906+
} else {
6907+
addrTI.assignWithCopy(*this, dest, src, addrTy, false);
6908+
}
6909+
}
6910+
}
6911+
68876912
// bind_memory and rebind_memory are no-ops because Swift TBAA info is not
68886913
// lowered to LLVM IR TBAA, and the output token is ignored except for
68896914
// verification.

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ OPERAND_OWNERSHIP(TrivialUse, CheckedCastAddrBranch)
147147
OPERAND_OWNERSHIP(TrivialUse, CondBranch)
148148
OPERAND_OWNERSHIP(TrivialUse, CondFail)
149149
OPERAND_OWNERSHIP(TrivialUse, CopyAddr)
150+
OPERAND_OWNERSHIP(TrivialUse, ExplicitCopyAddr)
150151
OPERAND_OWNERSHIP(TrivialUse, MarkUnresolvedMoveAddr)
151152
OPERAND_OWNERSHIP(TrivialUse, DeallocStack)
152153
OPERAND_OWNERSHIP(TrivialUse, DeinitExistentialAddr)

lib/SIL/IR/SILInstructions.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,6 +1172,15 @@ CopyAddrInst::CopyAddrInst(SILDebugLocation Loc, SILValue SrcLValue,
11721172
bool(isInitializationOfDest);
11731173
}
11741174

1175+
ExplicitCopyAddrInst::ExplicitCopyAddrInst(
1176+
SILDebugLocation Loc, SILValue SrcLValue, SILValue DestLValue,
1177+
IsTake_t isTakeOfSrc, IsInitialization_t isInitializationOfDest)
1178+
: InstructionBase(Loc), Operands(this, SrcLValue, DestLValue) {
1179+
sharedUInt8().ExplicitCopyAddrInst.isTakeOfSrc = bool(isTakeOfSrc);
1180+
sharedUInt8().ExplicitCopyAddrInst.isInitializationOfDest =
1181+
bool(isInitializationOfDest);
1182+
}
1183+
11751184
BindMemoryInst *
11761185
BindMemoryInst::create(SILDebugLocation Loc, SILValue Base, SILValue Index,
11771186
SILType BoundType, SILFunction &F) {

lib/SIL/IR/SILPrinter.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1749,6 +1749,15 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
17491749
*this << getIDAndType(CI->getDest());
17501750
}
17511751

1752+
void visitExplicitCopyAddrInst(ExplicitCopyAddrInst *CI) {
1753+
if (CI->isTakeOfSrc())
1754+
*this << "[take] ";
1755+
*this << Ctx.getID(CI->getSrc()) << " to ";
1756+
if (CI->isInitializationOfDest())
1757+
*this << "[initialization] ";
1758+
*this << getIDAndType(CI->getDest());
1759+
}
1760+
17521761
void visitMarkUnresolvedMoveAddrInst(MarkUnresolvedMoveAddrInst *CI) {
17531762
*this << Ctx.getID(CI->getSrc()) << " to ";
17541763
*this << getIDAndType(CI->getDest());

0 commit comments

Comments
 (0)