Skip to content

Implement verification of CopyValueInst and DestroyValueInst. #5418

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/swift/SIL/InstructionUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class FunctionOwnershipEvaluator {
F = NewF;
HasOwnershipQualifiedInstruction = false;
}
bool evaluate(const SILInstruction &I);
bool evaluate(SILInstruction *I);
};

} // end namespace swift
Expand Down
2 changes: 1 addition & 1 deletion lib/Parse/ParseSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3985,7 +3985,7 @@ bool SILParser::parseSILBasicBlock(SILBuilder &B) {
// Evaluate how the just parsed instruction effects this functions Ownership
// Qualification. For more details, see the comment on the
// FunctionOwnershipEvaluator class.
if (!OwnershipEvaluator.evaluate(*BB->rbegin()))
if (!OwnershipEvaluator.evaluate(&*BB->rbegin()))
return true;
} while (isStartOfSILInstruction());

Expand Down
55 changes: 32 additions & 23 deletions lib/SIL/InstructionUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "swift/SIL/Projection.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILBasicBlock.h"
#include "swift/SIL/SILVisitor.h"

using namespace swift;

Expand Down Expand Up @@ -231,41 +232,49 @@ enum class OwnershipQualifiedKind {
Unqualified,
};

} // end anonymous namespace
struct OwnershipQualifiedKindVisitor : SILInstructionVisitor<OwnershipQualifiedKindVisitor, OwnershipQualifiedKind> {

OwnershipQualifiedKind visitValueBase(ValueBase *V) {
return OwnershipQualifiedKind::NotApplicable;
}

static OwnershipQualifiedKind
getOwnershipQualifiedKind(const SILInstruction &I) {
switch (I.getKind()) {
case ValueKind::LoadInst:
if (cast<LoadInst>(I).getOwnershipQualifier() ==
LoadOwnershipQualifier::Unqualified)
#define QUALIFIED_INST(CLASS) \
OwnershipQualifiedKind visit ## CLASS(CLASS *I) { \
return OwnershipQualifiedKind::Qualified; \
}
QUALIFIED_INST(EndBorrowInst)
QUALIFIED_INST(LoadBorrowInst)
QUALIFIED_INST(CopyValueInst)
QUALIFIED_INST(DestroyValueInst)
#undef QUALIFIED_INST

OwnershipQualifiedKind visitLoadInst(LoadInst *LI) {
if (LI->getOwnershipQualifier() == LoadOwnershipQualifier::Unqualified)
return OwnershipQualifiedKind::Unqualified;
return OwnershipQualifiedKind::Qualified;
case ValueKind::StoreInst:
if (cast<StoreInst>(I).getOwnershipQualifier() ==
StoreOwnershipQualifier::Unqualified)
}

OwnershipQualifiedKind visitStoreInst(StoreInst *SI) {
if (SI->getOwnershipQualifier() == StoreOwnershipQualifier::Unqualified)
return OwnershipQualifiedKind::Unqualified;
return OwnershipQualifiedKind::Qualified;
case ValueKind::LoadBorrowInst:
case ValueKind::EndBorrowInst:
return OwnershipQualifiedKind::Qualified;
default:
return OwnershipQualifiedKind::NotApplicable;
}
}
};

} // end anonymous namespace

bool FunctionOwnershipEvaluator::evaluate(const SILInstruction &I) {
assert(I.getFunction() == F.get() && "Can not evaluate function ownership "
"implications of an instruction that "
"does not belong to the instruction "
"that we are evaluating");
bool FunctionOwnershipEvaluator::evaluate(SILInstruction *I) {
assert(I->getFunction() == F.get() && "Can not evaluate function ownership "
"implications of an instruction that "
"does not belong to the instruction "
"that we are evaluating");

// If SIL ownership is not enabled in this module, just return true. There is
// no further work to do here.
if (!I.getModule().getOptions().EnableSILOwnership)
if (!I->getModule().getOptions().EnableSILOwnership)
return true;

switch (getOwnershipQualifiedKind(I)) {
switch (OwnershipQualifiedKindVisitor().visit(I)) {
case OwnershipQualifiedKind::Unqualified: {
// If we already know that the function has unqualified ownership, just
// return early.
Expand Down
16 changes: 16 additions & 0 deletions lib/SIL/SILVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1349,6 +1349,22 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
"Source value should be an object value");
}

void checkCopyValueInst(CopyValueInst *I) {
require(I->getOperand()->getType().isObject(),
"Source value should be an object value");
requireTrueOrNone(F.hasQualifiedOwnership(),
"copy_value is only valid in functions with qualified "
"ownership");
}

void checkDestroyValueInst(DestroyValueInst *I) {
require(I->getOperand()->getType().isObject(),
"Source value should be an object value");
requireTrueOrNone(F.hasQualifiedOwnership(),
"destroy_value is only valid in functions with qualified "
"ownership");
}

void checkReleaseValueInst(ReleaseValueInst *I) {
require(I->getOperand()->getType().isObject(),
"Source value should be an object value");
Expand Down
2 changes: 1 addition & 1 deletion lib/Serialization/DeserializeSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1892,7 +1892,7 @@ bool SILDeserializer::readSILInstruction(

// Evaluate ResultVal's ownership. If we find that as a result of ResultVal,
// we are mixing qualified and unqualified ownership instructions, bail.
if (!OwnershipEvaluator.evaluate(*ResultVal))
if (!OwnershipEvaluator.evaluate(ResultVal))
return true;

if (ResultVal->hasValue()) {
Expand Down