Skip to content

Commit 59eea14

Browse files
committed
Add OwnershipForwardingMixin::hasSameRepresentation and verify
Also add OwnershipForwardingMixin::isAddressOnly.
1 parent 1c8f142 commit 59eea14

File tree

3 files changed

+55
-6
lines changed

3 files changed

+55
-6
lines changed

include/swift/SIL/SILInstruction.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,6 +1176,18 @@ class OwnershipForwardingMixin {
11761176
return isa(i);
11771177
return false;
11781178
}
1179+
1180+
/// Return true if the forwarded value has the same representation. If true,
1181+
/// then the result can be mapped to the same storage without a move or copy.
1182+
///
1183+
/// \p inst is an OwnershipForwardingMixin
1184+
static bool hasSameRepresentation(SILInstruction *inst);
1185+
1186+
/// Return true if the forwarded value is address-only either before or after
1187+
/// forwarding.
1188+
///
1189+
/// \p inst is an OwnershipForwardingMixin
1190+
static bool isAddressOnly(SILInstruction *inst);
11791191
};
11801192

11811193
/// A single value inst that forwards a static ownership from its first operand.

lib/SIL/IR/SILInstructions.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2904,6 +2904,42 @@ ReturnInst::ReturnInst(SILFunction &func, SILDebugLocation debugLoc,
29042904
"result info?!");
29052905
}
29062906

2907+
bool OwnershipForwardingMixin::hasSameRepresentation(SILInstruction *inst) {
2908+
switch (inst->getKind()) {
2909+
default:
2910+
// Conservatively assume that a conversion changes representation.
2911+
// Operations can be added as needed to participate in SIL opaque values.
2912+
assert(OwnershipForwardingMixin::isa(inst));
2913+
return false;
2914+
2915+
case SILInstructionKind::ConvertFunctionInst:
2916+
case SILInstructionKind::DestructureTupleInst:
2917+
case SILInstructionKind::DestructureStructInst:
2918+
case SILInstructionKind::InitExistentialRefInst:
2919+
case SILInstructionKind::ObjectInst:
2920+
case SILInstructionKind::OpenExistentialBoxValueInst:
2921+
case SILInstructionKind::OpenExistentialRefInst:
2922+
case SILInstructionKind::OpenExistentialValueInst:
2923+
case SILInstructionKind::MarkMustCheckInst:
2924+
case SILInstructionKind::MarkUninitializedInst:
2925+
case SILInstructionKind::SelectEnumInst:
2926+
case SILInstructionKind::StructExtractInst:
2927+
case SILInstructionKind::TupleExtractInst:
2928+
return true;
2929+
}
2930+
}
2931+
2932+
bool OwnershipForwardingMixin::isAddressOnly(SILInstruction *inst) {
2933+
if (auto *aggregate =
2934+
dyn_cast<AllArgOwnershipForwardingSingleValueInst>(inst)) {
2935+
// If any of the operands are address-only, then the aggregate must be.
2936+
return aggregate->getType().isAddressOnly(*inst->getFunction());
2937+
}
2938+
// All other forwarding instructions must forward their first operand.
2939+
assert(OwnershipForwardingMixin::isa(inst));
2940+
return inst->getOperand(0)->getType().isAddressOnly(*inst->getFunction());
2941+
}
2942+
29072943
// This may be called in an invalid SIL state. SILCombine creates new
29082944
// terminators in non-terminator position and defers deleting the original
29092945
// terminator until after all modification.

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,21 +1245,22 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
12451245
}
12461246
}
12471247

1248-
/// We are given an instruction \p fInst that forwards ownership from \p
1249-
/// operand to one of \p fInst's results, make sure that if we have a
1250-
/// forwarding instruction that can only accept owned or guaranteed ownership
1251-
/// that we are following that invariant.
1248+
/// For an instruction \p i that forwards ownership from an operand to one
1249+
/// of its results, check forwarding invariants.
12521250
void checkOwnershipForwardingInst(SILInstruction *i) {
1251+
ValueOwnershipKind ownership =
1252+
OwnershipForwardingMixin::get(i)->getForwardingOwnershipKind();
1253+
12531254
if (auto *o = dyn_cast<OwnedFirstArgForwardingSingleValueInst>(i)) {
12541255
ValueOwnershipKind kind = OwnershipKind::Owned;
1255-
require(kind.isCompatibleWith(o->getForwardingOwnershipKind()),
1256+
require(kind.isCompatibleWith(ownership),
12561257
"OwnedFirstArgForwardingSingleValueInst's ownership kind must be "
12571258
"compatible with owned");
12581259
}
12591260

12601261
if (auto *o = dyn_cast<GuaranteedFirstArgForwardingSingleValueInst>(i)) {
12611262
ValueOwnershipKind kind = OwnershipKind::Guaranteed;
1262-
require(kind.isCompatibleWith(o->getForwardingOwnershipKind()),
1263+
require(kind.isCompatibleWith(ownership),
12631264
"GuaranteedFirstArgForwardingSingleValueInst's ownership kind "
12641265
"must be compatible with guaranteed");
12651266
}

0 commit comments

Comments
 (0)