mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #74919 from gottesmm/pr-d8b24a45ff257893c8172491f11a617fc00d5589
[region-isolation] Implement support for 'inout sending' diagnostics.
This commit is contained in:
@@ -1205,6 +1205,14 @@ struct PartitionOpBuilder {
|
||||
PartitionOp::Require(lookupValueID(value), currentInst));
|
||||
}
|
||||
|
||||
void addRequireInOutSendingAtFunctionExit(SILValue value) {
|
||||
assert(valueHasID(value, /*dumpIfHasNoID=*/true) &&
|
||||
"required value should already have been encountered");
|
||||
currentInstPartitionOps.emplace_back(
|
||||
PartitionOp::RequireInOutSendingAtFunctionExit(lookupValueID(value),
|
||||
currentInst));
|
||||
}
|
||||
|
||||
void addUnknownPatternError(SILValue value) {
|
||||
if (shouldAbortOnUnknownPatternMatchError()) {
|
||||
llvm::report_fatal_error(
|
||||
@@ -1604,9 +1612,9 @@ public:
|
||||
// compiler exits successfully, actor merge errors could not have happened.
|
||||
std::optional<SILDynamicMergedIsolationInfo> mergedInfo;
|
||||
if (resultIsolationInfoOverride) {
|
||||
mergedInfo = resultIsolationInfoOverride;
|
||||
mergedInfo = SILDynamicMergedIsolationInfo(resultIsolationInfoOverride);
|
||||
} else {
|
||||
mergedInfo = SILIsolationInfo::getDisconnected(false);
|
||||
mergedInfo = SILDynamicMergedIsolationInfo::getDisconnected(false);
|
||||
}
|
||||
|
||||
for (SILValue src : sourceValues) {
|
||||
@@ -2321,6 +2329,22 @@ public:
|
||||
#define INST(INST, PARENT) TranslationSemantics visit##INST(INST *inst);
|
||||
#include "swift/SIL/SILNodes.def"
|
||||
|
||||
/// Adds requires for all sending inout parameters to make sure that they are
|
||||
/// properly updated before the end of the function.
|
||||
void addRequiresForInOutParameters(TermInst *inst) {
|
||||
assert(inst->isFunctionExiting() && "Must be function exiting term inst?!");
|
||||
for (auto *arg : inst->getFunction()->getArguments()) {
|
||||
auto *fArg = cast<SILFunctionArgument>(arg);
|
||||
if (fArg->getArgumentConvention().isInoutConvention() &&
|
||||
fArg->getKnownParameterInfo().hasOption(SILParameterInfo::Sending)) {
|
||||
if (auto ns = tryToTrackValue(arg)) {
|
||||
auto rep = ns->getRepresentative().getValue();
|
||||
builder.addRequireInOutSendingAtFunctionExit(rep);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Top level switch that translates SIL instructions.
|
||||
void translateSILInstruction(SILInstruction *inst) {
|
||||
builder.reset(inst);
|
||||
@@ -2710,12 +2734,8 @@ CONSTANT_TRANSLATION(CondFailInst, Ignored)
|
||||
// function_ref/class_method which are considered sendable.
|
||||
CONSTANT_TRANSLATION(SwitchValueInst, Ignored)
|
||||
CONSTANT_TRANSLATION(UnreachableInst, Ignored)
|
||||
CONSTANT_TRANSLATION(UnwindInst, Ignored)
|
||||
// Doesn't take a parameter.
|
||||
CONSTANT_TRANSLATION(ThrowAddrInst, Ignored)
|
||||
|
||||
// Terminators that only need require.
|
||||
CONSTANT_TRANSLATION(ThrowInst, Require)
|
||||
CONSTANT_TRANSLATION(SwitchEnumAddrInst, Require)
|
||||
CONSTANT_TRANSLATION(YieldInst, Require)
|
||||
|
||||
@@ -2725,6 +2745,33 @@ CONSTANT_TRANSLATION(CondBranchInst, TerminatorPhi)
|
||||
CONSTANT_TRANSLATION(CheckedCastBranchInst, TerminatorPhi)
|
||||
CONSTANT_TRANSLATION(DynamicMethodBranchInst, TerminatorPhi)
|
||||
|
||||
// Function exiting terminators.
|
||||
//
|
||||
// We handle these especially since we want to make sure that inout parameters
|
||||
// that are transferred are forced to be reinitialized.
|
||||
//
|
||||
// There is an assert in TermInst::isFunctionExiting that makes sure we do this
|
||||
// correctly.
|
||||
//
|
||||
// NOTE: We purposely do not require reinitialization along paths that end in
|
||||
// unreachable.
|
||||
#ifdef FUNCTION_EXITING_TERMINATOR_TRANSLATION
|
||||
#error "FUNCTION_EXITING_TERMINATOR_TRANSLATION already defined?!"
|
||||
#endif
|
||||
|
||||
#define FUNCTION_EXITING_TERMINATOR_CONSTANT(INST, Kind) \
|
||||
TranslationSemantics PartitionOpTranslator::visit##INST(INST *inst) { \
|
||||
assert(inst->isFunctionExiting() && "Must be function exiting?!"); \
|
||||
addRequiresForInOutParameters(inst); \
|
||||
return TranslationSemantics::Kind; \
|
||||
}
|
||||
|
||||
FUNCTION_EXITING_TERMINATOR_CONSTANT(UnwindInst, Ignored)
|
||||
FUNCTION_EXITING_TERMINATOR_CONSTANT(ThrowAddrInst, Ignored)
|
||||
FUNCTION_EXITING_TERMINATOR_CONSTANT(ThrowInst, Require)
|
||||
|
||||
#undef FUNCTION_EXITING_TERMINATOR_CONSTANT
|
||||
|
||||
// Today, await_async_continuation just takes Sendable values
|
||||
// (UnsafeContinuation and UnsafeThrowingContinuation).
|
||||
CONSTANT_TRANSLATION(AwaitAsyncContinuationInst, AssertingIfNonSendable)
|
||||
@@ -2961,6 +3008,7 @@ PartitionOpTranslator::visitLoadBorrowInst(LoadBorrowInst *lbi) {
|
||||
}
|
||||
|
||||
TranslationSemantics PartitionOpTranslator::visitReturnInst(ReturnInst *ri) {
|
||||
addRequiresForInOutParameters(ri);
|
||||
if (ri->getFunction()->getLoweredFunctionType()->hasSendingResult()) {
|
||||
return TranslationSemantics::TransferringNoResult;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user