Skip to content

Commit c6e24a7

Browse files
authored
Merge pull request swiftlang#72264 from gottesmm/eliminate-rest-of-task-or-actor-isolated
[region-isolation] Eliminate most of the rest of the "task or actor" isolated error
2 parents ee3875b + f2b5b86 commit c6e24a7

File tree

8 files changed

+454
-55
lines changed

8 files changed

+454
-55
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -968,34 +968,21 @@ NOTE(regionbasedisolation_isolated_since_in_same_region_basename, none,
968968
ERROR(regionbasedisolation_named_transfer_yields_race, none,
969969
"transferring %0 may cause a race",
970970
(Identifier))
971-
ERROR(regionbasedisolation_stronglytransfer_assignment_yields_race_name, none,
972-
"assigning %0 to transferring parameter %1 may cause a race",
973-
(Identifier, Identifier))
974-
NOTE(regionbasedisolation_named_transfer_into_transferring_param, none,
975-
"%0 %1 is passed as a transferring parameter; Uses in callee may race with later %0 uses",
976-
(StringRef, Identifier))
977971

978972
NOTE(regionbasedisolation_named_info_transfer_yields_race, none,
979973
"%0 is transferred from %1 caller to %2 callee. Later uses in caller could race with potential uses in callee",
980974
(Identifier, ActorIsolation, ActorIsolation))
981-
NOTE(regionbasedisolation_transfer_non_transferrable_named_note, none,
975+
NOTE(regionbasedisolation_named_transfer_non_transferrable, none,
982976
"transferring %1 %0 to %2 callee could cause races between %2 and %1 uses",
983977
(Identifier, ActorIsolation, ActorIsolation))
984-
NOTE(regionbasedisolation_named_info_isolated_capture, none,
985-
"%1 value %0 is captured by %2 closure. Later local uses could race",
986-
(Identifier, ActorIsolation, ActorIsolation))
987-
NOTE(regionbasedisolation_named_arg_info, none,
988-
"Transferring task-isolated function argument %0 could yield races with caller uses",
989-
(Identifier))
990-
NOTE(regionbasedisolation_named_stronglytransferred_binding, none,
991-
"Cannot access a transferring parameter after the parameter has been transferred", ())
992-
NOTE(regionbasedisolation_note_arg_passed_to_strongly_transferred_param, none,
993-
"%0 value of type %1 passed as a strongly transferred parameter; later accesses could race",
994-
(StringRef, Identifier, Type))
995-
ERROR(regionbasedisolation_named_arg_passed_to_strongly_transferred_param, none,
996-
"%0 %1 passed as a strongly transferred parameter; Uses in callee could race with later %0 uses",
997-
(StringRef, Identifier))
978+
NOTE(regionbasedisolation_named_transfer_into_transferring_param, none,
979+
"%0 %1 is passed as a transferring parameter; Uses in callee may race with later %0 uses",
980+
(StringRef, Identifier))
981+
NOTE(regionbasedisolation_named_notransfer_transfer_into_result, none,
982+
"%0 %1 cannot be a transferring result. %0 uses may race with caller uses",
983+
(StringRef, Identifier))
998984

985+
// Misc Error.
999986
ERROR(regionbasedisolation_task_or_actor_isolated_transferred, none,
1000987
"task or actor isolated value cannot be transferred", ())
1001988

include/swift/SILOptimizer/Utils/VariableNameUtils.h

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#ifndef SWIFT_SILOPTIMIZER_UTILS_VARIABLENAMEUTILS_H
1818
#define SWIFT_SILOPTIMIZER_UTILS_VARIABLENAMEUTILS_H
1919

20+
#include "swift/Basic/Defer.h"
2021
#include "swift/Basic/OptionSet.h"
2122
#include "swift/SIL/ApplySite.h"
2223
#include "swift/SIL/DebugUtils.h"
@@ -40,8 +41,76 @@ class VariableNameInferrer {
4041
using Options = OptionSet<Flag>;
4142

4243
private:
43-
/// The stacklist that we use to process from use->
44-
StackList<PointerUnion<SILInstruction *, SILValue>> variableNamePath;
44+
template <typename T, unsigned smallSize>
45+
class VariableNamePathArray {
46+
SmallVector<T, smallSize> data;
47+
48+
unsigned lastSnapShotIndex = 0;
49+
unsigned insertionPointIndex = 0;
50+
51+
public:
52+
VariableNamePathArray() : data() {}
53+
54+
ArrayRef<T> getData() const {
55+
assert(insertionPointIndex <= data.size());
56+
return ArrayRef<T>(data).take_front(insertionPointIndex);
57+
}
58+
59+
void print(llvm::raw_ostream &os) const {
60+
os << "LastSnapShotIndex: " << lastSnapShotIndex << '\n';
61+
os << "InsertionPointIndex: " << insertionPointIndex << '\n';
62+
}
63+
64+
SWIFT_DEBUG_DUMP { print(llvm::dbgs()); }
65+
66+
/// Pushes a snapshot and returns the old index.
67+
unsigned pushSnapShot() & {
68+
// After we run with a snapshot, we want:
69+
//
70+
// 1. lastSnapShotIndex to return to its value before the continuation
71+
// ran.
72+
// 2. The insertion point index becomes lastSnapShotIndex.
73+
unsigned oldSnapShotIndex = lastSnapShotIndex;
74+
lastSnapShotIndex = insertionPointIndex;
75+
return oldSnapShotIndex;
76+
}
77+
78+
void popSnapShot(unsigned oldIndex) & {
79+
insertionPointIndex = lastSnapShotIndex;
80+
lastSnapShotIndex = oldIndex;
81+
}
82+
83+
void returnSnapShot(unsigned oldIndex) & { lastSnapShotIndex = oldIndex; }
84+
85+
void push_back(const T &newValue) & {
86+
SWIFT_DEFER { assert(insertionPointIndex <= data.size()); };
87+
if (insertionPointIndex == data.size()) {
88+
data.push_back(newValue);
89+
++insertionPointIndex;
90+
return;
91+
}
92+
93+
data[insertionPointIndex] = newValue;
94+
++insertionPointIndex;
95+
}
96+
97+
[[nodiscard]] T pop_back_val() & {
98+
SWIFT_DEFER { assert(insertionPointIndex <= data.size()); };
99+
assert(!lastSnapShotIndex &&
100+
"Can only pop while lastSnapShotIndex is not set");
101+
--insertionPointIndex;
102+
return data[insertionPointIndex];
103+
}
104+
105+
bool empty() const { return !insertionPointIndex; }
106+
};
107+
108+
/// The stacklist that we use to print out variable names.
109+
///
110+
/// Has to be a small vector since we push/pop the last segment start. This
111+
/// lets us speculate when processing phis.
112+
VariableNamePathArray<PointerUnion<SILInstruction *, SILValue>, 4>
113+
variableNamePath;
45114

46115
/// The root value of our string.
47116
///
@@ -59,12 +128,12 @@ class VariableNameInferrer {
59128

60129
public:
61130
VariableNameInferrer(SILFunction *fn, SmallString<64> &resultingString)
62-
: variableNamePath(fn), resultingString(resultingString) {}
131+
: variableNamePath(), resultingString(resultingString) {}
63132

64133
VariableNameInferrer(SILFunction *fn, Options options,
65134
SmallString<64> &resultingString)
66-
: variableNamePath(fn), resultingString(resultingString),
67-
options(options) {}
135+
: variableNamePath(), resultingString(resultingString), options(options) {
136+
}
68137

69138
/// Attempts to infer a name from just uses of \p searchValue.
70139
///
@@ -133,7 +202,12 @@ class VariableNameInferrer {
133202

134203
/// Do not call this directly. Used just to improve logging for
135204
/// findDebugInfoProvidingValue.
136-
SILValue findDebugInfoProvidingValueHelper(SILValue searchValue);
205+
SILValue findDebugInfoProvidingValueHelper(SILValue searchValue,
206+
ValueSet &visitedValues);
207+
208+
/// A special helper for handling phi values. Do not call this directly.
209+
SILValue findDebugInfoProvidingValuePhiArg(SILValue incomingValue,
210+
ValueSet &visitedValues);
137211

138212
/// Given an initialized once allocation inst without a ValueDecl or a
139213
/// DebugVariable provided name, attempt to find a root value from its

lib/SILOptimizer/Mandatory/TransferNonSendable.cpp

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -985,15 +985,14 @@ class TransferNonTransferrableDiagnosticEmitter {
985985
void emitNamedIsolation(SILLocation loc, Identifier name,
986986
ApplyIsolationCrossing isolationCrossing) {
987987
emitNamedOnlyError(loc, name);
988-
diagnoseNote(
989-
loc, diag::regionbasedisolation_transfer_non_transferrable_named_note,
990-
name, isolationCrossing.getCallerIsolation(),
991-
isolationCrossing.getCalleeIsolation());
988+
diagnoseNote(loc,
989+
diag::regionbasedisolation_named_transfer_non_transferrable,
990+
name, isolationCrossing.getCallerIsolation(),
991+
isolationCrossing.getCalleeIsolation());
992992
}
993993

994-
void emitNamedFunctionArgumentApplyStronglyTransferred(
995-
SILLocation loc, Identifier varName,
996-
ValueIsolationRegionInfo isolationRegionInfo) {
994+
void emitNamedFunctionArgumentApplyStronglyTransferred(SILLocation loc,
995+
Identifier varName) {
997996
emitNamedOnlyError(loc, varName);
998997
SmallString<64> descriptiveKindStr;
999998
{
@@ -1005,6 +1004,18 @@ class TransferNonTransferrableDiagnosticEmitter {
10051004
diagnoseNote(loc, diag, descriptiveKindStr, varName);
10061005
}
10071006

1007+
void emitNamedTransferringReturn(SILLocation loc, Identifier varName) {
1008+
emitNamedOnlyError(loc, varName);
1009+
SmallString<64> descriptiveKindStr;
1010+
{
1011+
llvm::raw_svector_ostream os(descriptiveKindStr);
1012+
getIsolationRegionInfo().printForDiagnostics(os);
1013+
}
1014+
auto diag =
1015+
diag::regionbasedisolation_named_notransfer_transfer_into_result;
1016+
diagnoseNote(loc, diag, descriptiveKindStr, varName);
1017+
}
1018+
10081019
private:
10091020
ASTContext &getASTContext() const {
10101021
return getOperand()->getFunction()->getASTContext();
@@ -1106,7 +1117,7 @@ bool TransferNonTransferrableDiagnosticInferrer::run() {
11061117
SmallString<64> resultingName;
11071118
if (auto varName = inferNameFromValue(op->get())) {
11081119
diagnosticEmitter.emitNamedFunctionArgumentApplyStronglyTransferred(
1109-
loc, *varName, diagnosticEmitter.getIsolationRegionInfo());
1120+
loc, *varName);
11101121
return true;
11111122
}
11121123

@@ -1171,6 +1182,33 @@ bool TransferNonTransferrableDiagnosticInferrer::run() {
11711182
}
11721183
}
11731184

1185+
if (auto *ri = dyn_cast<ReturnInst>(op->getUser())) {
1186+
auto fType = ri->getFunction()->getLoweredFunctionType();
1187+
if (fType->getNumResults() &&
1188+
fType->getResults()[0].hasOption(SILResultInfo::IsTransferring)) {
1189+
assert(llvm::all_of(fType->getResults(),
1190+
[](SILResultInfo resultInfo) {
1191+
return resultInfo.hasOption(
1192+
SILResultInfo::IsTransferring);
1193+
}) &&
1194+
"All result info must be the same... if that changes... update "
1195+
"this code!");
1196+
SmallString<64> resultingName;
1197+
if (auto name = inferNameFromValue(op->get())) {
1198+
diagnosticEmitter.emitNamedTransferringReturn(loc, *name);
1199+
return true;
1200+
}
1201+
} else {
1202+
assert(llvm::none_of(fType->getResults(),
1203+
[](SILResultInfo resultInfo) {
1204+
return resultInfo.hasOption(
1205+
SILResultInfo::IsTransferring);
1206+
}) &&
1207+
"All result info must be the same... if that changes... update "
1208+
"this code!");
1209+
}
1210+
}
1211+
11741212
diagnosticEmitter.emitUnknownUse(loc);
11751213
return true;
11761214
}

lib/SILOptimizer/Utils/VariableNameUtils.cpp

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,8 @@ VariableNameInferrer::findDebugInfoProvidingValue(SILValue searchValue) {
214214
return SILValue();
215215
LLVM_DEBUG(llvm::dbgs() << "Searching for debug info providing value for: "
216216
<< searchValue);
217-
SILValue result = findDebugInfoProvidingValueHelper(searchValue);
217+
ValueSet valueSet(searchValue->getFunction());
218+
SILValue result = findDebugInfoProvidingValueHelper(searchValue, valueSet);
218219
if (result) {
219220
LLVM_DEBUG(llvm::dbgs() << "Result: " << result);
220221
} else {
@@ -223,12 +224,45 @@ VariableNameInferrer::findDebugInfoProvidingValue(SILValue searchValue) {
223224
return result;
224225
}
225226

226-
SILValue
227-
VariableNameInferrer::findDebugInfoProvidingValueHelper(SILValue searchValue) {
227+
SILValue VariableNameInferrer::findDebugInfoProvidingValuePhiArg(
228+
SILValue incomingValue, ValueSet &visitedValues) {
229+
// We use pushSnapShot to run recursively and if we fail to find a
230+
// value, we just pop our list to the last snapshot end of list. If we
231+
// succeed, we do not pop and just return recusive value. Our user
232+
// will consume variableNamePath at this point.
233+
LLVM_DEBUG(llvm::dbgs() << "Before pushing a snap shot!\n";
234+
variableNamePath.print(llvm::dbgs()));
235+
236+
unsigned oldSnapShotIndex = variableNamePath.pushSnapShot();
237+
LLVM_DEBUG(llvm::dbgs() << "After pushing a snap shot!\n";
238+
variableNamePath.print(llvm::dbgs()));
239+
240+
if (SILValue recursiveValue =
241+
findDebugInfoProvidingValueHelper(incomingValue, visitedValues)) {
242+
LLVM_DEBUG(llvm::dbgs() << "Returned: " << recursiveValue);
243+
variableNamePath.returnSnapShot(oldSnapShotIndex);
244+
return recursiveValue;
245+
}
246+
247+
variableNamePath.popSnapShot(oldSnapShotIndex);
248+
LLVM_DEBUG(llvm::dbgs() << "After popping a snap shot!\n";
249+
variableNamePath.print(llvm::dbgs()));
250+
return SILValue();
251+
}
252+
253+
SILValue VariableNameInferrer::findDebugInfoProvidingValueHelper(
254+
SILValue searchValue, ValueSet &visitedValues) {
228255
assert(searchValue);
229256

230257
while (true) {
231258
assert(searchValue);
259+
260+
// If we already visited the value, return SILValue(). This prevents issues
261+
// caused by looping phis. We treat this as a failure and visit the either
262+
// phi values.
263+
if (!visitedValues.insert(searchValue))
264+
return SILValue();
265+
232266
LLVM_DEBUG(llvm::dbgs() << "Value: " << *searchValue);
233267

234268
if (auto *allocInst = dyn_cast<AllocationInst>(searchValue)) {
@@ -276,6 +310,12 @@ VariableNameInferrer::findDebugInfoProvidingValueHelper(SILValue searchValue) {
276310
continue;
277311
}
278312

313+
if (auto *uedi = dyn_cast<UncheckedEnumDataInst>(searchValue)) {
314+
variableNamePath.push_back(uedi);
315+
searchValue = uedi->getOperand();
316+
continue;
317+
}
318+
279319
if (auto *tei = dyn_cast<TupleExtractInst>(searchValue)) {
280320
variableNamePath.push_back(tei);
281321
searchValue = tei->getOperand();
@@ -294,6 +334,23 @@ VariableNameInferrer::findDebugInfoProvidingValueHelper(SILValue searchValue) {
294334
continue;
295335
}
296336

337+
if (auto *e = dyn_cast<UncheckedTakeEnumDataAddrInst>(searchValue)) {
338+
variableNamePath.push_back(e);
339+
searchValue = e->getOperand();
340+
continue;
341+
}
342+
343+
// Enums only have a single possible parent and is used sometimes like a
344+
// transformation (e.x.: constructing an optional). We want to look through
345+
// them and add the case to the variableNamePath.
346+
if (auto *e = dyn_cast<EnumInst>(searchValue)) {
347+
if (e->hasOperand()) {
348+
variableNamePath.push_back(e);
349+
searchValue = e->getOperand();
350+
continue;
351+
}
352+
}
353+
297354
if (auto *dti = dyn_cast_or_null<DestructureTupleInst>(
298355
searchValue->getDefiningInstruction())) {
299356
// Append searchValue, so we can find the specific tuple index.
@@ -317,6 +374,27 @@ VariableNameInferrer::findDebugInfoProvidingValueHelper(SILValue searchValue) {
317374
}
318375
}
319376

377+
// If we have a phi argument, visit each of the incoming values and pick the
378+
// first one that gives us a name.
379+
if (auto *phiArg = dyn_cast<SILPhiArgument>(searchValue)) {
380+
if (auto *term = phiArg->getSingleTerminator()) {
381+
if (auto *swi = dyn_cast<SwitchEnumInst>(term)) {
382+
if (auto value = findDebugInfoProvidingValuePhiArg(swi->getOperand(),
383+
visitedValues))
384+
return value;
385+
}
386+
}
387+
388+
SmallVector<SILValue, 8> incomingValues;
389+
if (phiArg->getIncomingPhiValues(incomingValues)) {
390+
for (auto value : incomingValues) {
391+
if (auto resultValue =
392+
findDebugInfoProvidingValuePhiArg(value, visitedValues))
393+
return resultValue;
394+
}
395+
}
396+
}
397+
320398
auto getNamePathComponentFromCallee = [&](FullApplySite call) -> SILValue {
321399
// Use the name of the property being accessed if we can get to it.
322400
if (isa<FunctionRefBaseInst>(call.getCallee()) ||
@@ -473,6 +551,11 @@ void VariableNameInferrer::popSingleVariableName() {
473551
return;
474552
}
475553

554+
if (auto *uedi = dyn_cast<UncheckedEnumDataInst>(inst)) {
555+
resultingString += getNameFromDecl(uedi->getElement());
556+
return;
557+
}
558+
476559
if (auto *sei = dyn_cast<StructElementAddrInst>(inst)) {
477560
resultingString += getNameFromDecl(sei->getField());
478561
return;
@@ -484,6 +567,16 @@ void VariableNameInferrer::popSingleVariableName() {
484567
return;
485568
}
486569

570+
if (auto *uedi = dyn_cast<UncheckedTakeEnumDataAddrInst>(inst)) {
571+
resultingString += getNameFromDecl(uedi->getElement());
572+
return;
573+
}
574+
575+
if (auto *ei = dyn_cast<EnumInst>(inst)) {
576+
resultingString += getNameFromDecl(ei->getElement());
577+
return;
578+
}
579+
487580
resultingString += "<unknown decl>";
488581
return;
489582
}

0 commit comments

Comments
 (0)