Skip to content

Commit f6ba633

Browse files
committed
Allow SIL convention overriding in operand ownership verification
This lets the SILBuilder's verification continue to run during address lowering before the SIL stage has been updated.
1 parent 2cc58fe commit f6ba633

File tree

6 files changed

+48
-27
lines changed

6 files changed

+48
-27
lines changed

include/swift/SIL/SILBuilder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2690,7 +2690,7 @@ class SILBuilder {
26902690
// sync. We don't care if an instruction is used in global_addr.
26912691
if (F)
26922692
TheInst->verifyDebugInfo();
2693-
TheInst->verifyOperandOwnership();
2693+
TheInst->verifyOperandOwnership(&C.silConv);
26942694
#endif
26952695
}
26962696

include/swift/SIL/SILInstruction.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,7 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
773773

774774
/// Verify that all operands of this instruction have compatible ownership
775775
/// with this instruction.
776-
void verifyOperandOwnership() const;
776+
void verifyOperandOwnership(SILModuleConventions *silConv = nullptr) const;
777777

778778
/// Verify that this instruction and its associated debug information follow
779779
/// all SIL debug info invariants.

include/swift/SIL/SILValue.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class ConsumingUseIterator;
4646
class NonConsumingUseIterator;
4747
class NonTypeDependentUseIterator;
4848
class SILValue;
49+
class SILModuleConventions;
4950

5051
/// An enumeration which contains values for all the concrete ValueBase
5152
/// subclasses.
@@ -922,7 +923,8 @@ inline bool canAcceptUnownedValue(OperandOwnership operandOwnership) {
922923
}
923924

924925
/// Return true if all OperandOwnership invariants hold.
925-
bool checkOperandOwnershipInvariants(const Operand *operand);
926+
bool checkOperandOwnershipInvariants(const Operand *operand,
927+
SILModuleConventions *silConv = nullptr);
926928

927929
/// Return the OperandOwnership for a forwarded operand when the forwarding
928930
/// operation has this "forwarding ownership" (as returned by
@@ -1039,22 +1041,25 @@ class Operand {
10391041
/// Return the use ownership of this operand.
10401042
///
10411043
/// NOTE: This is implemented in OperandOwnership.cpp.
1042-
OperandOwnership getOperandOwnership() const;
1044+
OperandOwnership
1045+
getOperandOwnership(SILModuleConventions *silConv = nullptr) const;
10431046

10441047
/// Return the ownership constraint that restricts what types of values this
10451048
/// Operand can contain.
1046-
OwnershipConstraint getOwnershipConstraint() const {
1047-
return getOperandOwnership().getOwnershipConstraint();
1049+
OwnershipConstraint
1050+
getOwnershipConstraint(SILModuleConventions *silConv = nullptr) const {
1051+
return getOperandOwnership(silConv).getOwnershipConstraint();
10481052
}
10491053

10501054
/// Returns true if changing the operand to use a value with the given
10511055
/// ownership kind, without rewriting the instruction, would not cause the
10521056
/// operand to violate the operand's ownership constraints.
1053-
bool canAcceptKind(ValueOwnershipKind kind) const;
1057+
bool canAcceptKind(ValueOwnershipKind kind,
1058+
SILModuleConventions *silConv = nullptr) const;
10541059

10551060
/// Returns true if this operand and its value satisfy the operand's
10561061
/// operand constraint.
1057-
bool satisfiesConstraints() const;
1062+
bool satisfiesConstraints(SILModuleConventions *silConv = nullptr) const;
10581063

10591064
/// Returns true if this operand acts as a use that ends the lifetime its
10601065
/// associated value, either by consuming the owned value or ending the

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@
2020
using namespace swift;
2121

2222
/// Return true if all OperandOwnership invariants hold.
23-
bool swift::checkOperandOwnershipInvariants(const Operand *operand) {
24-
OperandOwnership opOwnership = operand->getOperandOwnership();
23+
bool swift::checkOperandOwnershipInvariants(const Operand *operand,
24+
SILModuleConventions *silConv) {
25+
OperandOwnership opOwnership = operand->getOperandOwnership(silConv);
2526
if (opOwnership == OperandOwnership::Borrow) {
2627
// Must be a valid BorrowingOperand.
2728
return bool(BorrowingOperand(const_cast<Operand *>(operand)));
@@ -38,6 +39,9 @@ namespace {
3839
class OperandOwnershipClassifier
3940
: public SILInstructionVisitor<OperandOwnershipClassifier, OperandOwnership> {
4041
LLVM_ATTRIBUTE_UNUSED SILModule &mod;
42+
// Allow module conventions to be overriden while lowering between canonical
43+
// and lowered SIL stages.
44+
SILModuleConventions silConv;
4145

4246
const Operand &op;
4347

@@ -49,8 +53,8 @@ class OperandOwnershipClassifier
4953
/// should be the subobject and Value should be the parent object. An example
5054
/// of where one would want to do this is in the case of value projections
5155
/// like struct_extract.
52-
OperandOwnershipClassifier(SILModule &mod, const Operand &op)
53-
: mod(mod), op(op) {}
56+
OperandOwnershipClassifier(SILModuleConventions silConv, const Operand &op)
57+
: mod(silConv.getModule()), silConv(silConv), op(op) {}
5458

5559
SILValue getValue() const { return op.get(); }
5660

@@ -474,9 +478,17 @@ OperandOwnershipClassifier::visitFullApply(FullApplySite apply) {
474478
if (getValue()->getType().isAddress()) {
475479
return OperandOwnership::TrivialUse;
476480
}
477-
SILArgumentConvention argConv = apply.isCalleeOperand(op)
478-
? SILArgumentConvention(apply.getSubstCalleeType()->getCalleeConvention())
479-
: apply.getArgumentConvention(op);
481+
auto calleeTy = apply.getSubstCalleeType();
482+
SILArgumentConvention argConv = [&]() {
483+
if (apply.isCalleeOperand(op)) {
484+
return SILArgumentConvention(calleeTy->getCalleeConvention());
485+
} else {
486+
unsigned calleeArgIdx = apply.getCalleeArgIndexOfFirstAppliedArg()
487+
+ apply.getAppliedArgIndex(op);
488+
return silConv.getFunctionConventions(calleeTy).getSILArgumentConvention(
489+
calleeArgIdx);
490+
}
491+
}();
480492

481493
auto argOwnership = getFunctionArgOwnership(
482494
argConv, /*hasScopeInCaller*/ apply.beginsCoroutineEvaluation());
@@ -904,8 +916,9 @@ OperandOwnership OperandOwnershipClassifier::visitBuiltinInst(BuiltinInst *bi) {
904916
// Top Level Entrypoint
905917
//===----------------------------------------------------------------------===//
906918

907-
OperandOwnership Operand::getOperandOwnership() const {
908-
// A type-dependent operant is a NonUse (as opposed to say an
919+
OperandOwnership
920+
Operand::getOperandOwnership(SILModuleConventions *silConv) const {
921+
// A type-dependent operand is a NonUse (as opposed to say an
909922
// InstantaneousUse) because it does not require liveness.
910923
if (isTypeDependent())
911924
return OperandOwnership::NonUse;
@@ -925,7 +938,8 @@ OperandOwnership Operand::getOperandOwnership() const {
925938
return OperandOwnership(OperandOwnership::InstantaneousUse);
926939
}
927940
}
928-
929-
OperandOwnershipClassifier classifier(getUser()->getModule(), *this);
941+
SILModuleConventions overrideConv =
942+
silConv ? *silConv : SILModuleConventions(getUser()->getModule());
943+
OperandOwnershipClassifier classifier(overrideConv, *this);
930944
return classifier.visit(const_cast<SILInstruction *>(getUser()));
931945
}

lib/SIL/IR/SILValue.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,9 @@ SILFunction *Operand::getParentFunction() const {
318318
return self->getUser()->getFunction();
319319
}
320320

321-
bool Operand::canAcceptKind(ValueOwnershipKind kind) const {
322-
auto operandOwnership = getOperandOwnership();
321+
bool Operand::canAcceptKind(ValueOwnershipKind kind,
322+
SILModuleConventions *silConv) const {
323+
auto operandOwnership = getOperandOwnership(silConv);
323324
auto constraint = operandOwnership.getOwnershipConstraint();
324325
if (constraint.satisfiesConstraint(kind)) {
325326
// Constraints aren't precise enough to enforce Unowned value uses.
@@ -332,8 +333,8 @@ bool Operand::canAcceptKind(ValueOwnershipKind kind) const {
332333
return false;
333334
}
334335

335-
bool Operand::satisfiesConstraints() const {
336-
return canAcceptKind(get().getOwnershipKind());
336+
bool Operand::satisfiesConstraints(SILModuleConventions *silConv) const {
337+
return canAcceptKind(get().getOwnershipKind(), silConv);
337338
}
338339

339340
bool Operand::isLifetimeEnding() const {

lib/SIL/Verifier/SILOwnershipVerifier.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,8 @@ bool SILValueOwnershipChecker::checkUses() {
687687
// Top Level Entrypoints
688688
//===----------------------------------------------------------------------===//
689689

690-
void SILInstruction::verifyOperandOwnership() const {
690+
void SILInstruction::verifyOperandOwnership(
691+
SILModuleConventions *silConv) const {
691692
if (DisableOwnershipVerification)
692693
return;
693694

@@ -736,7 +737,7 @@ void SILInstruction::verifyOperandOwnership() const {
736737
if (isTypeDependentOperand(op))
737738
continue;
738739

739-
if (!checkOperandOwnershipInvariants(&op)) {
740+
if (!checkOperandOwnershipInvariants(&op, silConv)) {
740741
errorBuilder->handleMalformedSIL([&] {
741742
llvm::errs() << "Found an operand with invalid invariants.\n";
742743
llvm::errs() << "Value: " << op.get();
@@ -747,8 +748,8 @@ void SILInstruction::verifyOperandOwnership() const {
747748
});
748749
}
749750

750-
if (!op.satisfiesConstraints()) {
751-
auto constraint = op.getOwnershipConstraint();
751+
if (!op.satisfiesConstraints(silConv)) {
752+
auto constraint = op.getOwnershipConstraint(silConv);
752753
SILValue opValue = op.get();
753754
auto valueOwnershipKind = opValue.getOwnershipKind();
754755
errorBuilder->handleMalformedSIL([&] {

0 commit comments

Comments
 (0)