Skip to content

Commit 1795f7f

Browse files
authored
Merge pull request #71429 from gottesmm/fixes-for-stdlib
[region-isolation] Fixes that enable the stdlib to build with region based isolation
2 parents 747cbfc + c25b39b commit 1795f7f

17 files changed

+1048
-380
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -894,8 +894,20 @@ NOTE(sil_referencebinding_inout_binding_here, none,
894894
"inout binding here",
895895
())
896896

897-
// Warnings arising from the flow-sensitive checking of Sendability of
898-
// non-Sendable values
897+
//===----------------------------------------------------------------------===//
898+
// MARK: Region Based Isolation Diagnostics
899+
//===----------------------------------------------------------------------===//
900+
901+
NOTE(regionbasedisolation_maybe_race, none,
902+
"access here could race", ())
903+
ERROR(regionbasedisolation_unknown_pattern, none,
904+
"pattern that the region based isolation checker does not understand how to check. Please file a bug",
905+
())
906+
907+
//===---
908+
// Old Transfer Non Sendable Diagnostics
909+
//
910+
899911
ERROR(regionbasedisolation_selforargtransferred, none,
900912
"call site passes `self` or a non-sendable argument of this function to another thread, potentially yielding a race with the caller", ())
901913
ERROR(regionbasedisolation_transfer_yields_race_no_isolation, none,
@@ -919,14 +931,28 @@ ERROR(regionbasedisolation_arg_transferred, none,
919931
ERROR(regionbasedisolation_arg_passed_to_strongly_transferred_param, none,
920932
"task isolated value of type %0 passed as a strongly transferred parameter; later accesses could race",
921933
(Type))
922-
NOTE(regionbasedisolation_maybe_race, none,
923-
"access here could race", ())
924934
NOTE(regionbasedisolation_isolated_since_in_same_region_basename, none,
925935
"value is %0 since it is in the same region as %1",
926936
(StringRef, DeclBaseName))
927-
ERROR(regionbasedisolation_unknown_pattern, none,
928-
"pattern that the region based isolation checker does not understand how to check. Please file a bug",
929-
())
937+
938+
//===---
939+
// New Transfer Non Sendable Diagnostics
940+
//
941+
942+
ERROR(regionbasedisolation_named_transfer_yields_race, none,
943+
"transferring non-Sendable value %0 could yield races with later accesses",
944+
(Identifier))
945+
NOTE(regionbasedisolation_named_info_transfer_yields_race, none,
946+
"%0 is transferred from %1 caller to %2 callee. Later uses in caller could race with potential uses in callee",
947+
(Identifier, ActorIsolation, ActorIsolation))
948+
NOTE(regionbasedisolation_named_info_isolated_capture, none,
949+
"%1 value %0 is captured by %2 closure. Later local uses could race",
950+
(Identifier, ActorIsolation, ActorIsolation))
951+
NOTE(regionbasedisolation_named_arg_info, none,
952+
"Transferring task isolated function argument %0 could yield races with caller uses",
953+
(Identifier))
954+
NOTE(regionbasedisolation_named_stronglytransferred_binding, none,
955+
"Cannot access a transferring parameter after the parameter has been transferred", ())
930956

931957
// TODO: print the name of the nominal type
932958
ERROR(deinit_not_visible, none,

include/swift/SIL/DebugUtils.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,19 @@ struct DebugVarCarryingInst : VarDeclCarryingInst {
531531
return varName;
532532
}
533533

534+
std::optional<StringRef> maybeGetName() const {
535+
assert(getKind() != Kind::Invalid);
536+
if (auto varInfo = getVarInfo()) {
537+
return varInfo->Name;
538+
}
539+
540+
if (auto *decl = getDecl()) {
541+
return decl->getBaseName().userFacingName();
542+
}
543+
544+
return {};
545+
}
546+
534547
/// Take in \p inst, a potentially invalid DebugVarCarryingInst, and returns a
535548
/// name for it. If we have an invalid value or don't find var info or a decl,
536549
/// return "unknown".
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
//===--- VariableNameUtils.h ----------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
///
13+
/// Utilities for inferring the name of a value.
14+
///
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_SILOPTIMIZER_UTILS_VARIABLENAMEUTILS_H
18+
#define SWIFT_SILOPTIMIZER_UTILS_VARIABLENAMEUTILS_H
19+
20+
#include "swift/SIL/ApplySite.h"
21+
#include "swift/SIL/DebugUtils.h"
22+
#include "swift/SIL/MemAccessUtils.h"
23+
#include "swift/SIL/SILInstruction.h"
24+
#include "swift/SIL/StackList.h"
25+
26+
namespace swift {
27+
28+
class VariableNameInferrer {
29+
/// The stacklist that we use to process from use->
30+
StackList<PointerUnion<SILInstruction *, SILValue>> variableNamePath;
31+
32+
/// The root value of our string.
33+
///
34+
/// If set, a diagnostic should do a 'root' is defined here error.
35+
SILValue rootValue;
36+
37+
/// The final string we computed.
38+
SmallString<64> &resultingString;
39+
40+
public:
41+
VariableNameInferrer(SILFunction *fn, SmallString<64> &resultingString)
42+
: variableNamePath(fn), resultingString(resultingString) {}
43+
44+
/// Attempts to infer a name from just uses of \p searchValue.
45+
///
46+
/// Returns true if we found a name.
47+
bool tryInferNameFromUses(SILValue searchValue) {
48+
auto *use = getAnyDebugUse(searchValue);
49+
if (!use)
50+
return false;
51+
52+
auto debugVar = DebugVarCarryingInst(use->getUser());
53+
if (!debugVar)
54+
return false;
55+
56+
assert(debugVar.getKind() == DebugVarCarryingInst::Kind::DebugValue);
57+
resultingString += debugVar.getName();
58+
return true;
59+
}
60+
61+
/// See if \p searchValue or one of its defs (walking use->def) has a name
62+
/// that we can use.
63+
///
64+
/// \p failInsteadOfEmittingUnknown set to true if we should return false
65+
/// rather than emitting unknown (and always succeeding).
66+
///
67+
/// \returns true if we inferred anything. Returns false otherwise.
68+
bool inferByWalkingUsesToDefs(SILValue searchValue) {
69+
// Look up our root value while adding to the variable name path list.
70+
auto rootValue = findDebugInfoProvidingValue(searchValue);
71+
if (!rootValue) {
72+
// If we do not pattern match successfully, just set resulting string to
73+
// unknown and return early.
74+
resultingString += "unknown";
75+
return true;
76+
}
77+
78+
drainVariableNamePath();
79+
return true;
80+
}
81+
82+
/// Infers the value that provides the debug info. This can be something like
83+
/// an alloc_stack that provides the information directly or a value that has
84+
/// a debug_value as a user.
85+
///
86+
/// \returns SILValue() if we did not find anything.
87+
SILValue inferByWalkingUsesToDefsReturningRoot(SILValue searchValue) {
88+
// Look up our root value while adding to the variable name path list.
89+
auto rootValue = findDebugInfoProvidingValue(searchValue);
90+
if (!rootValue) {
91+
// If we do not pattern match successfully, return SILValue() early.
92+
return SILValue();
93+
}
94+
95+
drainVariableNamePath();
96+
return rootValue;
97+
}
98+
99+
StringRef getName() const { return resultingString; }
100+
101+
private:
102+
void drainVariableNamePath();
103+
104+
/// Finds the SILValue that either provides the direct debug information or
105+
/// that has a debug_value user that provides the name of the value.
106+
SILValue findDebugInfoProvidingValue(SILValue searchValue);
107+
108+
/// Given an initialized once allocation inst without a ValueDecl or a
109+
/// DebugVariable provided name, attempt to find a root value from its
110+
/// initialization.
111+
SILValue getRootValueForTemporaryAllocation(AllocationInst *allocInst);
112+
};
113+
114+
} // namespace swift
115+
116+
#endif

lib/SILOptimizer/Analysis/RegionAnalysis.cpp

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,17 @@ struct UseDefChainVisitor
126126
// do not want to treat this as a merge.
127127
if (auto p = Projection(inst)) {
128128
switch (p.getKind()) {
129+
// Currently if we load and then project_box from a memory location,
130+
// we treat that as a projection. This follows the semantics/notes in
131+
// getAccessProjectionOperand.
132+
case ProjectionKind::Box:
133+
return cast<ProjectBoxInst>(inst)->getOperand();
129134
case ProjectionKind::Upcast:
130135
case ProjectionKind::RefCast:
131136
case ProjectionKind::BlockStorageCast:
132137
case ProjectionKind::BitwiseCast:
133-
case ProjectionKind::TailElems:
134-
case ProjectionKind::Box:
135138
case ProjectionKind::Class:
139+
case ProjectionKind::TailElems:
136140
llvm_unreachable("Shouldn't see this here");
137141
case ProjectionKind::Index:
138142
// Index is always a merge.
@@ -1289,8 +1293,7 @@ class PartitionOpTranslator {
12891293
continue;
12901294
}
12911295
if (auto *pbi = dyn_cast<ProjectBoxInst>(val)) {
1292-
if (isNonSendableType(
1293-
pbi->getType().getSILBoxFieldType(function))) {
1296+
if (isNonSendableType(pbi->getType())) {
12941297
auto trackVal = getTrackableValue(val, true);
12951298
(void)trackVal;
12961299
continue;
@@ -1431,8 +1434,12 @@ class PartitionOpTranslator {
14311434

14321435
if (auto tryApplyInst = dyn_cast<TryApplyInst>(inst)) {
14331436
foundResults.emplace_back(tryApplyInst->getNormalBB()->getArgument(0));
1434-
if (tryApplyInst->getErrorBB()->getNumArguments() > 0)
1437+
if (tryApplyInst->getErrorBB()->getNumArguments() > 0) {
14351438
foundResults.emplace_back(tryApplyInst->getErrorBB()->getArgument(0));
1439+
}
1440+
for (auto indirectResults : tryApplyInst->getIndirectSILResults()) {
1441+
foundResults.emplace_back(indirectResults);
1442+
}
14361443
return;
14371444
}
14381445

@@ -1797,10 +1804,10 @@ class PartitionOpTranslator {
17971804
};
17981805

17991806
if (applySite.hasSelfArgument()) {
1800-
handleSILOperands(applySite.getOperandsWithoutSelf());
1807+
handleSILOperands(applySite.getOperandsWithoutIndirectResultsOrSelf());
18011808
handleSILSelf(&applySite.getSelfArgumentOperand());
18021809
} else {
1803-
handleSILOperands(applySite->getAllOperands());
1810+
handleSILOperands(applySite.getOperandsWithoutIndirectResults());
18041811
}
18051812

18061813
// non-sendable results can't be returned from cross-isolation calls without
@@ -2109,6 +2116,7 @@ class PartitionOpTranslator {
21092116
}
21102117

21112118
case TranslationSemantics::Asserting:
2119+
llvm::errs() << "BannedInst: " << *inst;
21122120
llvm::report_fatal_error(
21132121
"transfer-non-sendable: Found banned instruction?!");
21142122
return;
@@ -2119,6 +2127,7 @@ class PartitionOpTranslator {
21192127
return ::isNonSendableType(value->getType(), inst->getFunction());
21202128
}))
21212129
return;
2130+
llvm::errs() << "BadInst: " << *inst;
21222131
llvm::report_fatal_error(
21232132
"transfer-non-sendable: Found instruction that is not allowed to "
21242133
"have non-Sendable parameters with such parameters?!");
@@ -2304,7 +2313,6 @@ CONSTANT_TRANSLATION(TupleInst, Assign)
23042313
CONSTANT_TRANSLATION(BeginAccessInst, LookThrough)
23052314
CONSTANT_TRANSLATION(BeginBorrowInst, LookThrough)
23062315
CONSTANT_TRANSLATION(BeginDeallocRefInst, LookThrough)
2307-
CONSTANT_TRANSLATION(RefToBridgeObjectInst, LookThrough)
23082316
CONSTANT_TRANSLATION(BridgeObjectToRefInst, LookThrough)
23092317
CONSTANT_TRANSLATION(CopyValueInst, LookThrough)
23102318
CONSTANT_TRANSLATION(ExplicitCopyValueInst, LookThrough)
@@ -2414,6 +2422,8 @@ CONSTANT_TRANSLATION(BeginUnpairedAccessInst, Require)
24142422
CONSTANT_TRANSLATION(ValueMetatypeInst, Require)
24152423
// Require of the value we extract the metatype from.
24162424
CONSTANT_TRANSLATION(ExistentialMetatypeInst, Require)
2425+
// These can take a parameter. If it is non-Sendable, use a require.
2426+
CONSTANT_TRANSLATION(GetAsyncContinuationAddrInst, Require)
24172427

24182428
//===---
24192429
// Asserting If Non Sendable Parameter
@@ -2454,7 +2464,6 @@ CONSTANT_TRANSLATION(DynamicMethodBranchInst, TerminatorPhi)
24542464
// (UnsafeContinuation and UnsafeThrowingContinuation).
24552465
CONSTANT_TRANSLATION(AwaitAsyncContinuationInst, AssertingIfNonSendable)
24562466
CONSTANT_TRANSLATION(GetAsyncContinuationInst, AssertingIfNonSendable)
2457-
CONSTANT_TRANSLATION(GetAsyncContinuationAddrInst, AssertingIfNonSendable)
24582467
CONSTANT_TRANSLATION(ExtractExecutorInst, AssertingIfNonSendable)
24592468

24602469
//===---
@@ -2614,6 +2623,13 @@ CAST_WITH_MAYBE_SENDABLE_NONSENDABLE_OP_AND_RESULT(UncheckedValueCastInst)
26142623
// Custom Handling
26152624
//
26162625

2626+
TranslationSemantics
2627+
PartitionOpTranslator::visitRefToBridgeObjectInst(RefToBridgeObjectInst *r) {
2628+
translateSILLookThrough(
2629+
SILValue(r), r->getOperand(RefToBridgeObjectInst::ConvertedOperand));
2630+
return TranslationSemantics::Special;
2631+
}
2632+
26172633
TranslationSemantics
26182634
PartitionOpTranslator::visitPackElementGetInst(PackElementGetInst *r) {
26192635
if (!isNonSendableType(r->getType()))

0 commit comments

Comments
 (0)