Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions include/swift/AST/DiagnosticsSIL.def
Original file line number Diff line number Diff line change
Expand Up @@ -998,23 +998,23 @@ GROUPED_ERROR(regionbasedisolation_type_send_yields_race, SendingRisksDataRace,
(Type))
NOTE(regionbasedisolation_type_use_after_send, none,
"sending value of non-Sendable type %0 to %1 callee risks causing data races between %1 and local %2 uses",
(Type, ActorIsolation, ActorIsolation))
(Type, StringRef, StringRef))
NOTE(regionbasedisolation_type_use_after_send_callee, none,
"sending value of non-Sendable type %0 to %1 %kind2 risks causing data "
"races between %1 and local %3 uses",
(Type, ActorIsolation, const ValueDecl *, ActorIsolation))
(Type, StringRef, const ValueDecl *, StringRef))

NOTE(regionbasedisolation_named_info_send_yields_race, none,
"sending %1%0 to %2 callee risks causing data races between %2 and local %3 uses",
(Identifier, StringRef, ActorIsolation, ActorIsolation))
(Identifier, StringRef, StringRef, StringRef))
NOTE(regionbasedisolation_named_info_send_yields_race_callee, none,
"sending %1%0 to %2 %kind3 risks causing data races between %2 and local %4 uses",
(Identifier, StringRef, ActorIsolation, const ValueDecl *, ActorIsolation))
(Identifier, StringRef, StringRef, const ValueDecl *, StringRef))

// Use after send closure.
NOTE(regionbasedisolation_type_isolated_capture_yields_race, none,
"sending value of non-Sendable type %0 to %1 closure due to closure capture risks causing races in between %1 and %2 uses",
(Type, ActorIsolation, ActorIsolation))
(Type, StringRef, StringRef))

// Value captured in async let and reused.
NOTE(regionbasedisolation_named_nonisolated_asynclet_name, none,
Expand All @@ -1026,7 +1026,7 @@ NOTE(regionbasedisolation_named_value_used_after_explicit_sending, none,
(Identifier))
NOTE(regionbasedisolation_named_isolated_closure_yields_race, none,
"%0%1 is captured by a %2 closure. %2 uses in closure may race against later %3 uses",
(StringRef, Identifier, ActorIsolation, ActorIsolation))
(StringRef, Identifier, StringRef, StringRef))

NOTE(regionbasedisolation_typed_use_after_sending, none,
"Passing value of non-Sendable type %0 as a 'sending' argument risks causing races in between local and caller code",
Expand All @@ -1040,10 +1040,10 @@ NOTE(regionbasedisolation_typed_use_after_sending_callee, none,

NOTE(regionbasedisolation_named_send_never_sendable, none,
"sending %1%0 to %2 callee risks causing data races between %2 and %3 uses",
(Identifier, StringRef, ActorIsolation, StringRef))
(Identifier, StringRef, StringRef, StringRef))
NOTE(regionbasedisolation_named_send_never_sendable_callee, none,
"sending %1%0 to %2 %kind3 risks causing data races between %2 and %4 uses",
(Identifier, StringRef, ActorIsolation, const ValueDecl *, StringRef))
(Identifier, StringRef, StringRef, const ValueDecl *, StringRef))

NOTE(regionbasedisolation_named_send_into_sending_param, none,
"%0%1 is passed as a 'sending' parameter; Uses in callee may race with "
Expand Down Expand Up @@ -1092,10 +1092,10 @@ NOTE(regionbasedisolation_named_send_nt_asynclet_capture, none,
(Identifier, StringRef))
NOTE(regionbasedisolation_typed_sendneversendable_via_arg, none,
"sending %0 value of non-Sendable type %1 to %2 callee risks causing races in between %0 and %2 uses",
(StringRef, Type, ActorIsolation))
(StringRef, Type, StringRef))
NOTE(regionbasedisolation_typed_sendneversendable_via_arg_callee, none,
"sending %0 value of non-Sendable type %1 to %2 %kind3 risks causing races in between %0 and %2 uses",
(StringRef, Type, ActorIsolation, const ValueDecl *))
(StringRef, Type, StringRef, const ValueDecl *))

// Error that is only used when the send non sendable emitter cannot discover any
// information to give a better diagnostic.
Expand Down Expand Up @@ -1137,10 +1137,10 @@ NOTE(regionbasedisolation_out_sending_cannot_be_actor_isolated_note_named, none,
// Example: returning main-actor isolated result to a custom-actor isolated context risks causing data races
ERROR(rbi_isolation_crossing_result, none,
"non-Sendable %0-typed result can not be returned from %1 %kind2 to %3 context",
(Type, ActorIsolation, const ValueDecl *, ActorIsolation))
(Type, StringRef, const ValueDecl *, StringRef))
ERROR(rbi_isolation_crossing_result_no_decl, none,
"non-Sendable %0-typed result can not be returned from %1 function to %2 context",
(Type, ActorIsolation, ActorIsolation))
(Type, StringRef, StringRef))
NOTE(rbi_non_sendable_nominal,none,
"%kind0 does not conform to the 'Sendable' protocol",
(const ValueDecl *))
Expand Down
28 changes: 15 additions & 13 deletions include/swift/SILOptimizer/Analysis/RegionAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,16 +179,16 @@ class regionanalysisimpl::TrackableValueState {

void removeFlag(TrackableValueFlag flag) { flagSet -= flag; }

void print(llvm::raw_ostream &os) const {
void print(SILFunction *fn, llvm::raw_ostream &os) const {
os << "TrackableValueState[id: " << id
<< "][is_no_alias: " << (isNoAlias() ? "yes" : "no")
<< "][is_sendable: " << (isSendable() ? "yes" : "no")
<< "][region_value_kind: ";
getIsolationRegionInfo().printForOneLineLogging(os);
getIsolationRegionInfo().printForOneLineLogging(fn, os);
os << "].";
}

SWIFT_DEBUG_DUMP { print(llvm::dbgs()); }
SWIFT_DEBUG_DUMPER(dump(SILFunction *fn)) { print(fn, llvm::dbgs()); }

private:
bool hasIsolationRegionInfo() const { return bool(regionInfo); }
Expand Down Expand Up @@ -249,26 +249,26 @@ class regionanalysisimpl::TrackableValue {
/// parameter.
bool isSendingParameter() const;

void printIsolationInfo(SmallString<64> &outString) const {
void printIsolationInfo(SILFunction *fn, SmallString<64> &outString) const {
llvm::raw_svector_ostream os(outString);
getIsolationRegionInfo().printForDiagnostics(os);
getIsolationRegionInfo().printForDiagnostics(fn, os);
}

void print(llvm::raw_ostream &os) const {
void print(SILFunction *fn, llvm::raw_ostream &os) const {
os << "TrackableValue. State: ";
valueState.print(os);
valueState.print(fn, os);
os << "\n Rep Value: ";
getRepresentative().print(os);
}

void printVerbose(llvm::raw_ostream &os) const {
void printVerbose(SILFunction *fn, llvm::raw_ostream &os) const {
os << "TrackableValue. State: ";
valueState.print(os);
valueState.print(fn, os);
os << "\n Rep Value: " << getRepresentative();
}

SWIFT_DEBUG_DUMP {
print(llvm::dbgs());
SWIFT_DEBUG_DUMPER(dump(SILFunction *fn)) {
print(fn, llvm::dbgs());
llvm::dbgs() << '\n';
}
};
Expand All @@ -288,8 +288,8 @@ struct regionanalysisimpl::TrackableValueLookupResult {
/// TrackableValue.
std::optional<TrackableValue> base;

void print(llvm::raw_ostream &os) const;
SWIFT_DEBUG_DUMP { print(llvm::dbgs()); }
void print(SILFunction *fn, llvm::raw_ostream &os) const;
SWIFT_DEBUG_DUMPER(dumper(SILFunction *fn)) { print(fn, llvm::dbgs()); }
};

class RegionAnalysis;
Expand Down Expand Up @@ -390,6 +390,8 @@ class RegionAnalysisValueMap {
return getUnderlyingTrackedValue(value).value;
}

SILFunction *getFunction() const { return fn; }

/// Returns the value for this instruction if it isn't a fake "represenative
/// value" to inject actor isolation. Asserts in such a case.
SILValue getRepresentative(Element trackableValueID) const;
Expand Down
82 changes: 47 additions & 35 deletions include/swift/SILOptimizer/Utils/SILIsolationInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ class SILIsolationInfo {
/// parameter and should be allowed to merge into a self parameter.
UnappliedIsolatedAnyParameter = 0x2,

/// If set, this was a TaskIsolated value from a nonisolated(nonsending)
/// parameter.
NonisolatedNonsendingTaskIsolated = 0x4,

/// The maximum number of bits used by a Flag.
MaxNumBits = 2,
};
Expand Down Expand Up @@ -269,6 +273,25 @@ class SILIsolationInfo {
return self;
}

bool isNonisolatedNonsendingTaskIsolated() const {
return getOptions().contains(Flag::NonisolatedNonsendingTaskIsolated);
}

SILIsolationInfo
withNonisolatedNonsendingTaskIsolated(bool newValue = true) const {
assert(*this && "Cannot be unknown");
assert(isTaskIsolated() && "Can only be task isolated");
auto self = *this;
if (newValue) {
self.options =
(self.getOptions() | Flag::NonisolatedNonsendingTaskIsolated).toRaw();
} else {
self.options = self.getOptions().toRaw() &
~Options(Flag::NonisolatedNonsendingTaskIsolated).toRaw();
}
return self;
}

/// Returns true if this actor isolation is derived from an unapplied
/// isolation parameter. When merging, we allow for this to be merged with a
/// more specific isolation kind.
Expand All @@ -289,16 +312,16 @@ class SILIsolationInfo {
return self;
}

void print(llvm::raw_ostream &os) const;
void print(SILFunction *fn, llvm::raw_ostream &os) const;

/// Print a textual representation of the text info that is meant to be
/// included in other logging output for types that compose with
/// SILIsolationInfo. As a result, we only print state that can fit on
/// one line.
void printForOneLineLogging(llvm::raw_ostream &os) const;
void printForOneLineLogging(SILFunction *fn, llvm::raw_ostream &os) const;

SWIFT_DEBUG_DUMP {
print(llvm::dbgs());
SWIFT_DEBUG_DUMPER(dump(SILFunction *fn)) {
print(fn, llvm::dbgs());
llvm::dbgs() << '\n';
}

Expand All @@ -307,12 +330,12 @@ class SILIsolationInfo {
///
/// We do this programatically since task-isolated code needs a very different
/// form of diagnostic than other cases.
void printForCodeDiagnostic(llvm::raw_ostream &os) const;
void printForCodeDiagnostic(SILFunction *fn, llvm::raw_ostream &os) const;

void printForDiagnostics(llvm::raw_ostream &os) const;
void printForDiagnostics(SILFunction *fn, llvm::raw_ostream &os) const;

SWIFT_DEBUG_DUMPER(dumpForDiagnostics()) {
printForDiagnostics(llvm::dbgs());
SWIFT_DEBUG_DUMPER(dumpForDiagnostics(SILFunction *fn)) {
printForDiagnostics(fn, llvm::dbgs());
llvm::dbgs() << '\n';
}

Expand Down Expand Up @@ -494,6 +517,13 @@ class SILIsolationInfo {
/// that the isolation and the isolated value match.
bool isEqual(const SILIsolationInfo &other) const;

/// A helper function that prints ActorIsolation like we normally do except
/// that it prints nonisolated(nonsending) as nonisolated. This is needed in
/// certain cases when talking about use-after-free uses in send non sendable.
static void printActorIsolationForDiagnostics(
SILFunction *fn, ActorIsolation iso, llvm::raw_ostream &os,
StringRef openingQuotationMark = "'", bool asNoun = false);

void Profile(llvm::FoldingSetNodeID &id) const;

private:
Expand Down Expand Up @@ -557,43 +587,25 @@ class SILDynamicMergedIsolationInfo {
SILIsolationInfo::getDisconnected(isUnsafeNonIsolated));
}

SWIFT_DEBUG_DUMP { innerInfo.dump(); }
SWIFT_DEBUG_DUMPER(dump(SILFunction *fn)) { innerInfo.dump(fn); }

void printForDiagnostics(llvm::raw_ostream &os) const {
innerInfo.printForDiagnostics(os);
void printForDiagnostics(SILFunction *fn, llvm::raw_ostream &os) const {
innerInfo.printForDiagnostics(fn, os);
}

SWIFT_DEBUG_DUMPER(dumpForDiagnostics()) {
innerInfo.dumpForDiagnostics();
SWIFT_DEBUG_DUMPER(dumpForDiagnostics(SILFunction *fn)) {
innerInfo.dumpForDiagnostics(fn);
}

void printForCodeDiagnostic(llvm::raw_ostream &os) const {
innerInfo.printForCodeDiagnostic(os);
void printForCodeDiagnostic(SILFunction *fn, llvm::raw_ostream &os) const {
innerInfo.printForCodeDiagnostic(fn, os);
}

void printForOneLineLogging(llvm::raw_ostream &os) const {
innerInfo.printForOneLineLogging(os);
void printForOneLineLogging(SILFunction *fn, llvm::raw_ostream &os) const {
innerInfo.printForOneLineLogging(fn, os);
}
};

} // namespace swift

namespace llvm {

inline llvm::raw_ostream &
operator<<(llvm::raw_ostream &os,
const swift::SILIsolationInfo &isolationInfo) {
isolationInfo.printForOneLineLogging(os);
return os;
}

inline llvm::raw_ostream &
operator<<(llvm::raw_ostream &os,
const swift::SILDynamicMergedIsolationInfo &isolationInfo) {
isolationInfo.printForOneLineLogging(os);
return os;
}

} // namespace llvm

#endif
30 changes: 19 additions & 11 deletions lib/SILOptimizer/Analysis/RegionAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,7 @@ void RegionAnalysisValueMap::print(llvm::raw_ostream &os) const {
for (auto p : temp) {
os << "%%" << p.first << ": ";
auto value = getValueForId(Element(p.first));
value->print(os);
value->print(getFunction(), os);
}
#endif
}
Expand Down Expand Up @@ -1130,12 +1130,13 @@ bool TrackableValue::isSendingParameter() const {
// MARK: TrackableValueLookupResult
//===----------------------------------------------------------------------===//

void TrackableValueLookupResult::print(llvm::raw_ostream &os) const {
void TrackableValueLookupResult::print(SILFunction *fn,
llvm::raw_ostream &os) const {
os << "Value:\n";
value.print(os);
value.print(fn, os);
if (base) {
os << "Base:\n";
base->print(os);
base->print(fn, os);
}
}

Expand Down Expand Up @@ -1633,6 +1634,11 @@ struct PartitionOpBuilder {
initialPartitionOpIndex = currentInstPartitionOps->size();
}

SILFunction *getFunction() const {
assert(currentInst);
return currentInst->getFunction();
}

void reset(SILInstruction *inst) {
assert(currentInstPartitionOps);
currentInst = inst;
Expand Down Expand Up @@ -2006,7 +2012,8 @@ class PartitionOpTranslator {
isNonSendableType(val->getType())) {
auto trackVal = getTrackableValue(val, true);
(void)trackVal;
REGIONBASEDISOLATION_LOG(trackVal.print(llvm::dbgs()));
REGIONBASEDISOLATION_LOG(
trackVal.print(val->getFunction(), llvm::dbgs()));
continue;
}
if (auto *pbi = dyn_cast<ProjectBoxInst>(val)) {
Expand Down Expand Up @@ -2083,7 +2090,7 @@ class PartitionOpTranslator {
// send list and to the region join list.
REGIONBASEDISOLATION_LOG(
llvm::dbgs() << " %%" << value.getID() << ": ";
value.print(llvm::dbgs()); llvm::dbgs() << *arg);
value.print(function, llvm::dbgs()); llvm::dbgs() << *arg);
nonSendableJoinedIndices.push_back(value.getID());
} else {
REGIONBASEDISOLATION_LOG(llvm::dbgs() << " Sendable: " << *arg);
Expand Down Expand Up @@ -2258,14 +2265,15 @@ class PartitionOpTranslator {
REGIONBASEDISOLATION_LOG(
llvm::dbgs() << "Merge Failure!\n"
<< "Original Info: ";
if (originalMergedInfo)
originalMergedInfo->printForDiagnostics(llvm::dbgs());
if (originalMergedInfo) originalMergedInfo->printForDiagnostics(
builder.getFunction(), llvm::dbgs());
else llvm::dbgs() << "nil";
llvm::dbgs() << "\nValue Rep: "
<< value.getRepresentative().getValue();
llvm::dbgs() << "Original Src: " << src;
llvm::dbgs() << "Value Info: ";
value.getIsolationRegionInfo().printForDiagnostics(llvm::dbgs());
value.getIsolationRegionInfo().printForDiagnostics(
builder.getFunction(), llvm::dbgs());
llvm::dbgs() << "\n");
builder.addUnknownPatternError(src);
continue;
Expand Down Expand Up @@ -3222,7 +3230,7 @@ void PartitionOpBuilder::print(llvm::raw_ostream &os) const {
auto trackableValue = translator->getValueForId(opArg);
assert(trackableValue);
llvm::dbgs() << "State: %%" << opArg << ". ";
trackableValue->getValueState().print(llvm::dbgs());
trackableValue->getValueState().print(getFunction(), llvm::dbgs());
llvm::dbgs() << "\n Rep Value: "
<< trackableValue->getRepresentative();
if (auto value = trackableValue->getRepresentative().maybeGetValue()) {
Expand Down Expand Up @@ -4300,7 +4308,7 @@ static FunctionTest
RegionAnalysisValueMap valueMap(&function);
auto value = arguments.takeValue();
auto trackableValue = valueMap.getTrackableValue(value);
trackableValue.print(llvm::outs());
trackableValue.print(&function, llvm::outs());
llvm::outs() << '\n';
});

Expand Down
Loading