Skip to content

Commit 5ced1d1

Browse files
authored
Merge pull request #41085 from gottesmm/pr-f777a3678aa7c0fcd9369e7ad04c5d94a067024a
[no-implicit-copy] Add a new instruction called MarkMustCheckInst and use it in the move checker.
2 parents 82410c6 + 68d37e1 commit 5ced1d1

21 files changed

+284
-27
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,10 @@ ERROR(sil_keypath_no_use_of_operand_in_pattern,none,
653653
(unsigned))
654654
ERROR(sil_movevalue_invalid_optional_attribute,none,
655655
"Optional attribute '[%0]' can not be applied to move_value", (StringRef))
656+
ERROR(sil_markmustcheck_invalid_attribute,none,
657+
"Attribute '[%0]' can not be applied to mark_value_as_moveonly", (StringRef))
658+
ERROR(sil_markmustcheck_requires_attribute,none,
659+
"mark_must_check requires an attribute like 'noImplicitCopy'", ())
656660

657661
// SIL Basic Blocks
658662
ERROR(expected_sil_block_name,none,

include/swift/SIL/SILBuilder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,13 @@ class SILBuilder {
12791279
getSILDebugLocation(loc), srcAddr, takeAddr));
12801280
}
12811281

1282+
MarkMustCheckInst *
1283+
createMarkMustCheckInst(SILLocation loc, SILValue src,
1284+
MarkMustCheckInst::CheckKind kind) {
1285+
return insert(new (getModule())
1286+
MarkMustCheckInst(getSILDebugLocation(loc), src, kind));
1287+
}
1288+
12821289
UnconditionalCheckedCastInst *
12831290
createUnconditionalCheckedCast(SILLocation Loc, SILValue op,
12841291
SILType destLoweredTy,

include/swift/SIL/SILCloner.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1790,6 +1790,15 @@ void SILCloner<ImplClass>::visitMoveValueInst(MoveValueInst *Inst) {
17901790
recordClonedInstruction(Inst, MVI);
17911791
}
17921792

1793+
template <typename ImplClass>
1794+
void SILCloner<ImplClass>::visitMarkMustCheckInst(MarkMustCheckInst *Inst) {
1795+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
1796+
auto *MVI = getBuilder().createMarkMustCheckInst(
1797+
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
1798+
Inst->getCheckKind());
1799+
recordClonedInstruction(Inst, MVI);
1800+
}
1801+
17931802
template <typename ImplClass>
17941803
void SILCloner<ImplClass>::visitReleaseValueInst(ReleaseValueInst *Inst) {
17951804
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));

include/swift/SIL/SILInstruction.h

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7501,6 +7501,38 @@ class MarkUnresolvedMoveAddrInst
75017501
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
75027502
};
75037503

7504+
/// This is a marker instruction that has no effect that is consumed by a
7505+
/// diagnostic based semantic checker. Example: no implicit copy. Only legal in
7506+
/// Raw SIL so that we can guarantee canonical SIL has had all SSA based
7507+
/// checking by the checkers that rely upon this instruction.
7508+
class MarkMustCheckInst
7509+
: public UnaryInstructionBase<SILInstructionKind::MarkMustCheckInst,
7510+
SingleValueInstruction>,
7511+
public OwnershipForwardingMixin {
7512+
friend class SILBuilder;
7513+
7514+
public:
7515+
enum class CheckKind : unsigned {
7516+
Invalid = 0,
7517+
NoImplicitCopy,
7518+
};
7519+
7520+
private:
7521+
CheckKind kind;
7522+
7523+
MarkMustCheckInst(SILDebugLocation DebugLoc, SILValue operand,
7524+
CheckKind checkKind)
7525+
: UnaryInstructionBase(DebugLoc, operand, operand->getType()),
7526+
OwnershipForwardingMixin(SILInstructionKind::MarkMustCheckInst,
7527+
operand->getOwnershipKind()),
7528+
kind(checkKind) {}
7529+
7530+
public:
7531+
CheckKind getCheckKind() const { return kind; }
7532+
7533+
bool isNoImplicitCopy() const { return kind == CheckKind::NoImplicitCopy; }
7534+
};
7535+
75047536
/// Given an object reference, return true iff it is non-nil and refers
75057537
/// to a native swift object with strong reference count of 1.
75067538
class IsUniqueInst
@@ -9683,7 +9715,8 @@ inline bool OwnershipForwardingMixin::isa(SILInstructionKind kind) {
96839715
OwnershipForwardingTermInst::classof(kind) ||
96849716
OwnershipForwardingConversionInst::classof(kind) ||
96859717
OwnershipForwardingSelectEnumInstBase::classof(kind) ||
9686-
OwnershipForwardingMultipleValueInstruction::classof(kind);
9718+
OwnershipForwardingMultipleValueInstruction::classof(kind) ||
9719+
kind == SILInstructionKind::MarkMustCheckInst;
96879720
}
96889721

96899722
inline OwnershipForwardingMixin *
@@ -9705,6 +9738,8 @@ OwnershipForwardingMixin::get(SILInstruction *inst) {
97059738
if (auto *result =
97069739
dyn_cast<OwnershipForwardingMultipleValueInstruction>(inst))
97079740
return result;
9741+
if (auto *result = dyn_cast<MarkMustCheckInst>(inst))
9742+
return result;
97089743
return nullptr;
97099744
}
97109745

include/swift/SIL/SILNodes.def

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,12 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
475475
// effects relative to other OSSA values like copy_value.
476476
SINGLE_VALUE_INST(MoveValueInst, move_value, SingleValueInstruction, None,
477477
DoesNotRelease)
478-
478+
// A canary value inserted by a SIL generating frontend to signal to the move
479+
// checker to check a specific value. Valid only in Raw SIL. The relevant
480+
// checkers should remove the mark_must_check instruction after successfully
481+
// running the relevant diagnostic.
482+
SINGLE_VALUE_INST(MarkMustCheckInst, mark_must_check,
483+
SingleValueInstruction, None, DoesNotRelease)
479484
// A move_addr is a Raw SIL only instruction that is equivalent to a copy_addr
480485
// [init]. It is lowered during the diagnostic passes to a copy_addr [init] if
481486
// the move checker found uses that prevented us from converting this to a

lib/IRGen/IRGenSIL.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,9 @@ class IRGenSILFunction :
11541154
auto e = getLoweredExplosion(i->getOperand());
11551155
setLoweredExplosion(i, e);
11561156
}
1157+
void visitMarkMustCheckInst(MarkMustCheckInst *i) {
1158+
llvm_unreachable("Invalid in Lowered SIL");
1159+
}
11571160
void visitReleaseValueInst(ReleaseValueInst *i);
11581161
void visitReleaseValueAddrInst(ReleaseValueAddrInst *i);
11591162
void visitDestroyValueInst(DestroyValueInst *i);

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ FORWARDING_OWNERSHIP(UnconditionalCheckedCast)
327327
FORWARDING_OWNERSHIP(InitExistentialRef)
328328
FORWARDING_OWNERSHIP(DifferentiableFunction)
329329
FORWARDING_OWNERSHIP(LinearFunction)
330+
FORWARDING_OWNERSHIP(MarkMustCheck)
330331
#undef FORWARDING_OWNERSHIP
331332

332333
// Arbitrary value casts are forwarding instructions that are also allowed to

lib/SIL/IR/SILPrinter.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1901,6 +1901,18 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
19011901
*this << getIDAndType(I->getOperand());
19021902
}
19031903

1904+
void visitMarkMustCheckInst(MarkMustCheckInst *I) {
1905+
using CheckKind = MarkMustCheckInst::CheckKind;
1906+
switch (I->getCheckKind()) {
1907+
case CheckKind::Invalid:
1908+
llvm_unreachable("Invalid?!");
1909+
case CheckKind::NoImplicitCopy:
1910+
*this << "[no_implicit_copy] ";
1911+
break;
1912+
}
1913+
*this << getIDAndType(I->getOperand());
1914+
}
1915+
19041916
#define UNCHECKED_REF_STORAGE(Name, ...) \
19051917
void visitStrongCopy##Name##ValueInst(StrongCopy##Name##ValueInst *I) { \
19061918
*this << getIDAndType(I->getOperand()); \

lib/SIL/IR/ValueOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ FORWARDING_OWNERSHIP_INST(MarkDependence)
277277
FORWARDING_OWNERSHIP_INST(InitExistentialRef)
278278
FORWARDING_OWNERSHIP_INST(DifferentiableFunction)
279279
FORWARDING_OWNERSHIP_INST(LinearFunction)
280+
FORWARDING_OWNERSHIP_INST(MarkMustCheck)
280281
#undef FORWARDING_OWNERSHIP_INST
281282

282283
ValueOwnershipKind

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "SILParserFunctionBuilder.h"
1414
#include "SILParserState.h"
1515
#include "swift/AST/ASTWalker.h"
16+
#include "swift/AST/DiagnosticsParse.h"
1617
#include "swift/AST/ExistentialLayout.h"
1718
#include "swift/AST/GenericEnvironment.h"
1819
#include "swift/AST/NameLookup.h"
@@ -3322,6 +3323,34 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
33223323
break;
33233324
}
33243325

3326+
case SILInstructionKind::MarkMustCheckInst: {
3327+
if (parseTypedValueRef(Val, B))
3328+
return true;
3329+
if (parseSILDebugLocation(InstLoc, B))
3330+
return true;
3331+
3332+
StringRef AttrName;
3333+
if (!parseSILOptional(AttrName, *this)) {
3334+
auto diag = diag::sil_markmustcheck_requires_attribute;
3335+
P.diagnose(InstLoc.getSourceLoc(), diag);
3336+
return true;
3337+
}
3338+
3339+
using CheckKind = MarkMustCheckInst::CheckKind;
3340+
CheckKind CKind = llvm::StringSwitch<CheckKind>(AttrName)
3341+
.Case("no_implicit_copy", CheckKind::NoImplicitCopy)
3342+
.Default(CheckKind::Invalid);
3343+
3344+
if (CKind == CheckKind::Invalid) {
3345+
auto diag = diag::sil_markmustcheck_invalid_attribute;
3346+
P.diagnose(InstLoc.getSourceLoc(), diag, AttrName);
3347+
return true;
3348+
}
3349+
auto *MVI = B.createMarkMustCheckInst(InstLoc, Val, CKind);
3350+
ResultVal = MVI;
3351+
break;
3352+
}
3353+
33253354
case SILInstructionKind::LoadInst: {
33263355
Optional<LoadOwnershipQualifier> Qualifier;
33273356
SourceLoc AddrLoc;

0 commit comments

Comments
 (0)