Skip to content

Commit d74299e

Browse files
committed
[move-function] Add a new instruction called mark_unresolved_move_addr.
This instruction is similar to a copy_addr except that it marks a move of an address that has to be checked. In order to keep the memory lifetime verifier happy, the semantics before the checker runs are the mark_unresolved_move_addr is equivalent to copy_addr [init] (not copy_addr [take][init]). The use of this instruction is that Mandatory Inlining converts builtin "move" to a mark_unresolved_move_addr when inlining the function "_move" (the only place said builtin is invoked). This is then run through a special checker (that is later in this PR) that either proves that the mark_unresolved_move_addr can actually be a move in which case it converts it to copy_addr [take][init] or if it can not be a move, emit an error and convert the instruction to a copy_addr [init]. After this is done for all instructions, we loop back through again and emit an error on any mark_unresolved_move_addr that were not processed earlier allowing for us to know that we have completeness. NOTE: The move kills checker for addresses is going to run after Mandatory Inlining, but before predictable memory opts and friends.
1 parent cce3e8a commit d74299e

26 files changed

+238
-16
lines changed

include/swift/SIL/SILBuilder.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,6 +1271,12 @@ class SILBuilder {
12711271
MoveValueInst(getSILDebugLocation(loc), operand));
12721272
}
12731273

1274+
MarkUnresolvedMoveAddrInst *createMarkUnresolvedMoveAddr(SILLocation loc, SILValue srcAddr,
1275+
SILValue takeAddr) {
1276+
return insert(new (getModule()) MarkUnresolvedMoveAddrInst(getSILDebugLocation(loc),
1277+
srcAddr, takeAddr));
1278+
}
1279+
12741280
UnconditionalCheckedCastInst *
12751281
createUnconditionalCheckedCast(SILLocation Loc, SILValue op,
12761282
SILType destLoweredTy,

include/swift/SIL/SILCloner.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,6 +1341,15 @@ SILCloner<ImplClass>::visitCopyAddrInst(CopyAddrInst *Inst) {
13411341
Inst->isInitializationOfDest()));
13421342
}
13431343

1344+
template <typename ImplClass>
1345+
void SILCloner<ImplClass>::visitMarkUnresolvedMoveAddrInst(MarkUnresolvedMoveAddrInst *Inst) {
1346+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
1347+
auto *MVI = getBuilder().createMarkUnresolvedMoveAddr(getOpLocation(Inst->getLoc()),
1348+
getOpValue(Inst->getSrc()),
1349+
getOpValue(Inst->getDest()));
1350+
recordClonedInstruction(Inst, MVI);
1351+
}
1352+
13441353
template<typename ImplClass>
13451354
void
13461355
SILCloner<ImplClass>::visitBindMemoryInst(BindMemoryInst *Inst) {

include/swift/SIL/SILInstruction.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7424,6 +7424,35 @@ class MoveValueInst
74247424
void setAllowsDiagnostics(bool newValue) { allowDiagnostics = newValue; }
74257425
};
74267426

7427+
/// Equivalent to a copy_addr to [init] except that it is used for diagnostics
7428+
/// and should not be pattern matched. During the diagnostic passes, the "move
7429+
/// function" checker for addresses always converts this to a copy_addr [init]
7430+
/// (if we emitted a diagnostic and proved we could not emit a move here) or a
7431+
/// copy_addr [take][init] if we can. So this should never occur in canonical
7432+
/// SIL.
7433+
class MarkUnresolvedMoveAddrInst
7434+
: public InstructionBase<SILInstructionKind::MarkUnresolvedMoveAddrInst,
7435+
NonValueInstruction>,
7436+
public CopyLikeInstruction {
7437+
friend class SILBuilder;
7438+
7439+
FixedOperandList<2> Operands;
7440+
7441+
MarkUnresolvedMoveAddrInst(SILDebugLocation DebugLoc, SILValue srcAddr,
7442+
SILValue takeAddr)
7443+
: InstructionBase(DebugLoc), Operands(this, srcAddr, takeAddr) {}
7444+
7445+
public:
7446+
SILValue getSrc() const { return Operands[Src].get(); }
7447+
SILValue getDest() const { return Operands[Dest].get(); }
7448+
7449+
void setSrc(SILValue V) { Operands[Src].set(V); }
7450+
void setDest(SILValue V) { Operands[Dest].set(V); }
7451+
7452+
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
7453+
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
7454+
};
7455+
74277456
/// Given an object reference, return true iff it is non-nil and refers
74287457
/// to a native swift object with strong reference count of 1.
74297458
class IsUniqueInst

include/swift/SIL/SILNodes.def

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -591,8 +591,15 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
591591
SingleValueInstruction, None, MayRelease)
592592
// A move_value is an OSSA only instruction. Its result does not have any side
593593
// effects relative to other OSSA values like copy_value.
594-
SINGLE_VALUE_INST(MoveValueInst, move_value,
595-
SingleValueInstruction, None, DoesNotRelease)
594+
SINGLE_VALUE_INST(MoveValueInst, move_value, SingleValueInstruction, None,
595+
DoesNotRelease)
596+
597+
// A move_addr is a Raw SIL only instruction that is equivalent to a copy_addr
598+
// [init]. It is lowered during the diagnostic passes to a copy_addr [init] if
599+
// the move checker found uses that prevented us from converting this to a
600+
// move or if we do not find such uses, a copy_addr [init] [take].
601+
NON_VALUE_INST(MarkUnresolvedMoveAddrInst, mark_unresolved_move_addr,
602+
SILInstruction, None, DoesNotRelease)
596603

597604
// IsUnique does not actually write to memory but should be modeled
598605
// as such. Its operand is a pointer to an object reference. The

lib/IRGen/IRGenSIL.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,6 +1262,9 @@ class IRGenSILFunction :
12621262
void visitDeallocPartialRefInst(DeallocPartialRefInst *i);
12631263

12641264
void visitCopyAddrInst(CopyAddrInst *i);
1265+
void visitMarkUnresolvedMoveAddrInst(MarkUnresolvedMoveAddrInst *mai) {
1266+
llvm_unreachable("Valid only when ownership is enabled");
1267+
}
12651268
void visitDestroyAddrInst(DestroyAddrInst *i);
12661269

12671270
void visitBindMemoryInst(BindMemoryInst *i);

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ OPERAND_OWNERSHIP(TrivialUse, CheckedCastAddrBranch)
143143
OPERAND_OWNERSHIP(TrivialUse, CondBranch)
144144
OPERAND_OWNERSHIP(TrivialUse, CondFail)
145145
OPERAND_OWNERSHIP(TrivialUse, CopyAddr)
146+
OPERAND_OWNERSHIP(TrivialUse, MarkUnresolvedMoveAddr)
146147
OPERAND_OWNERSHIP(TrivialUse, DeallocStack)
147148
OPERAND_OWNERSHIP(TrivialUse, DeinitExistentialAddr)
148149
OPERAND_OWNERSHIP(TrivialUse, DestroyAddr)

lib/SIL/IR/SILInstruction.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,10 @@ bool SILInstruction::mayRelease() const {
11671167
return CopyAddr->isInitializationOfDest() ==
11681168
IsInitialization_t::IsNotInitialization;
11691169
}
1170+
// mark_unresolved_move_addr is equivalent to a copy_addr [init], so a release does not
1171+
// occur.
1172+
case SILInstructionKind::MarkUnresolvedMoveAddrInst:
1173+
return false;
11701174

11711175
case SILInstructionKind::BuiltinInst: {
11721176
auto *BI = cast<BuiltinInst>(this);

lib/SIL/IR/SILPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1703,6 +1703,11 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
17031703
*this << getIDAndType(CI->getDest());
17041704
}
17051705

1706+
void visitMarkUnresolvedMoveAddrInst(MarkUnresolvedMoveAddrInst *CI) {
1707+
*this << Ctx.getID(CI->getSrc()) << " to ";
1708+
*this << getIDAndType(CI->getDest());
1709+
}
1710+
17061711
void visitBindMemoryInst(BindMemoryInst *BI) {
17071712
*this << getIDAndType(BI->getBase()) << ", ";
17081713
*this << getIDAndType(BI->getIndex()) << " to ";

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4771,6 +4771,34 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
47714771
IsInitialization_t(IsInit));
47724772
break;
47734773
}
4774+
case SILInstructionKind::MarkUnresolvedMoveAddrInst: {
4775+
UnresolvedValueName SrcLName;
4776+
SILValue DestLVal;
4777+
SourceLoc ToLoc, DestLoc;
4778+
Identifier ToToken;
4779+
if (parseValueName(SrcLName) ||
4780+
parseSILIdentifier(ToToken, ToLoc, diag::expected_tok_in_sil_instr,
4781+
"to") ||
4782+
parseTypedValueRef(DestLVal, DestLoc, B) ||
4783+
parseSILDebugLocation(InstLoc, B))
4784+
return true;
4785+
4786+
if (ToToken.str() != "to") {
4787+
P.diagnose(ToLoc, diag::expected_tok_in_sil_instr, "to");
4788+
return true;
4789+
}
4790+
4791+
if (!DestLVal->getType().isAddress()) {
4792+
P.diagnose(DestLoc, diag::sil_invalid_instr_operands);
4793+
return true;
4794+
}
4795+
4796+
SILValue SrcLVal =
4797+
getLocalValue(SrcLName, DestLVal->getType(), InstLoc, B);
4798+
ResultVal = B.createMarkUnresolvedMoveAddr(InstLoc, SrcLVal, DestLVal);
4799+
break;
4800+
}
4801+
47744802
case SILInstructionKind::BindMemoryInst: {
47754803
SILValue IndexVal;
47764804
SILType EltTy;

lib/SIL/Utils/InstructionUtils.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,11 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType)
631631
return RuntimeEffect::MetaData | RuntimeEffect::RefCounting;
632632
return RuntimeEffect::MetaData;
633633
}
634+
// Equialent to a copy_addr [init]
635+
case SILInstructionKind::MarkUnresolvedMoveAddrInst: {
636+
return RuntimeEffect::MetaData | RuntimeEffect::RefCounting;
637+
}
638+
634639
case SILInstructionKind::StoreInst:
635640
switch (cast<StoreInst>(inst)->getOwnershipQualifier()) {
636641
case StoreOwnershipQualifier::Unqualified:

0 commit comments

Comments
 (0)