Skip to content

Commit 63a436e

Browse files
authored
Merge pull request #81615 from gottesmm/release/6.2-rdar151394209
[6.2] Fix a few issues around nonisolated(nonsending) and protocol witness thunks/vtable thunks
2 parents b3d9155 + f002391 commit 63a436e

17 files changed

+363
-118
lines changed

include/swift/SIL/TypeLowering.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1389,6 +1389,14 @@ CanSILFunctionType getNativeSILFunctionType(
13891389
std::optional<SubstitutionMap> reqtSubs = std::nullopt,
13901390
ProtocolConformanceRef witnessMethodConformance = ProtocolConformanceRef());
13911391

1392+
/// origConstant is the parent decl ref in the case of class methods and the
1393+
/// witness method decl ref if we are working with a protocol witness. Pass in
1394+
/// None otherwise.
1395+
std::optional<ActorIsolation>
1396+
getSILFunctionTypeActorIsolation(CanAnyFunctionType substFnInterfaceType,
1397+
std::optional<SILDeclRef> origConstant,
1398+
std::optional<SILDeclRef> constant);
1399+
13921400
/// The thunk kinds used in the differentiation transform.
13931401
enum class DifferentiationThunkKind {
13941402
/// A reabstraction thunk.

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2391,6 +2391,68 @@ static void destructureYieldsForCoroutine(TypeConverter &TC,
23912391
}
23922392
}
23932393

2394+
std::optional<ActorIsolation>
2395+
swift::getSILFunctionTypeActorIsolation(CanAnyFunctionType substFnInterfaceType,
2396+
std::optional<SILDeclRef> origConstant,
2397+
std::optional<SILDeclRef> constant) {
2398+
// If we have origConstant then we are creating a protocol method thunk. In
2399+
// such a case, we want to use the origConstant's actor isolation.
2400+
if (origConstant && constant &&
2401+
*origConstant != *constant) {
2402+
if (auto *decl = origConstant->getAbstractFunctionDecl()) {
2403+
if (auto *nonisolatedAttr =
2404+
decl->getAttrs().getAttribute<NonisolatedAttr>()) {
2405+
if (nonisolatedAttr->isNonSending())
2406+
return ActorIsolation::forCallerIsolationInheriting();
2407+
}
2408+
2409+
if (decl->getAttrs().hasAttribute<ConcurrentAttr>()) {
2410+
return ActorIsolation::forNonisolated(false /*unsafe*/);
2411+
}
2412+
}
2413+
2414+
return getActorIsolationOfContext(origConstant->getInnermostDeclContext());
2415+
}
2416+
2417+
if (constant) {
2418+
// TODO: It should to be possible to `getActorIsolation` if
2419+
// reference is to a decl instead of trying to get isolation
2420+
// from the reference kind, the attributes, or the context.
2421+
2422+
if (constant->kind == SILDeclRef::Kind::Deallocator) {
2423+
return ActorIsolation::forNonisolated(false);
2424+
}
2425+
2426+
if (auto *decl = constant->getAbstractFunctionDecl()) {
2427+
if (auto *nonisolatedAttr =
2428+
decl->getAttrs().getAttribute<NonisolatedAttr>()) {
2429+
if (nonisolatedAttr->isNonSending())
2430+
return ActorIsolation::forCallerIsolationInheriting();
2431+
}
2432+
2433+
if (decl->getAttrs().hasAttribute<ConcurrentAttr>()) {
2434+
return ActorIsolation::forNonisolated(false /*unsafe*/);
2435+
}
2436+
}
2437+
2438+
if (auto *closure = constant->getAbstractClosureExpr()) {
2439+
if (auto isolation = closure->getActorIsolation())
2440+
return isolation;
2441+
}
2442+
2443+
return getActorIsolationOfContext(constant->getInnermostDeclContext());
2444+
}
2445+
2446+
if (substFnInterfaceType->hasExtInfo() &&
2447+
substFnInterfaceType->getExtInfo().getIsolation().isNonIsolatedCaller()) {
2448+
// If our function type is a nonisolated caller and we can not infer from
2449+
// our constant, we must be caller isolation inheriting.
2450+
return ActorIsolation::forCallerIsolationInheriting();
2451+
}
2452+
2453+
return {};
2454+
}
2455+
23942456
/// Create the appropriate SIL function type for the given formal type
23952457
/// and conventions.
23962458
///
@@ -2622,39 +2684,8 @@ static CanSILFunctionType getSILFunctionType(
26222684
SmallBitVector addressableParams;
26232685
SmallBitVector conditionallyAddressableParams;
26242686
{
2625-
std::optional<ActorIsolation> actorIsolation;
2626-
if (constant) {
2627-
// TODO: It should to be possible to `getActorIsolation` if
2628-
// reference is to a decl instead of trying to get isolation
2629-
// from the reference kind, the attributes, or the context.
2630-
2631-
if (constant->kind == SILDeclRef::Kind::Deallocator) {
2632-
actorIsolation = ActorIsolation::forNonisolated(false);
2633-
} else if (auto *decl = constant->getAbstractFunctionDecl()) {
2634-
if (auto *nonisolatedAttr =
2635-
decl->getAttrs().getAttribute<NonisolatedAttr>()) {
2636-
if (nonisolatedAttr->isNonSending())
2637-
actorIsolation = ActorIsolation::forCallerIsolationInheriting();
2638-
} else if (decl->getAttrs().hasAttribute<ConcurrentAttr>()) {
2639-
actorIsolation = ActorIsolation::forNonisolated(false /*unsafe*/);
2640-
}
2641-
} else if (auto *closure = constant->getAbstractClosureExpr()) {
2642-
if (auto isolation = closure->getActorIsolation())
2643-
actorIsolation = isolation;
2644-
}
2645-
2646-
if (!actorIsolation) {
2647-
actorIsolation =
2648-
getActorIsolationOfContext(constant->getInnermostDeclContext());
2649-
}
2650-
} else if (substFnInterfaceType->hasExtInfo() &&
2651-
substFnInterfaceType->getExtInfo()
2652-
.getIsolation()
2653-
.isNonIsolatedCaller()) {
2654-
// If our function type is a nonisolated caller and we can not infer from
2655-
// our constant, we must be caller isolation inheriting.
2656-
actorIsolation = ActorIsolation::forCallerIsolationInheriting();
2657-
}
2687+
auto actorIsolation = getSILFunctionTypeActorIsolation(
2688+
substFnInterfaceType, origConstant, constant);
26582689
DestructureInputs destructurer(expansionContext, TC, conventions,
26592690
foreignInfo, actorIsolation, inputs,
26602691
parameterMap,

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 79 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7668,57 +7668,111 @@ void SILVTable::verify(const SILModule &M) const {
76687668
}
76697669

76707670
/// Verify that a witness table follows invariants.
7671-
void SILWitnessTable::verify(const SILModule &M) const {
7672-
if (!verificationEnabled(M))
7671+
void SILWitnessTable::verify(const SILModule &mod) const {
7672+
if (!verificationEnabled(mod))
76737673
return;
76747674

76757675
if (isDeclaration())
76767676
assert(getEntries().empty() &&
76777677
"A witness table declaration should not have any entries.");
76787678

7679-
for (const Entry &E : getEntries())
7680-
if (E.getKind() == SILWitnessTable::WitnessKind::Method) {
7681-
SILFunction *F = E.getMethodWitness().Witness;
7682-
if (F) {
7683-
// If a SILWitnessTable is going to be serialized, it must only
7684-
// reference public or serializable functions.
7685-
if (isAnySerialized()) {
7686-
assert(F->hasValidLinkageForFragileRef(getSerializedKind()) &&
7687-
"Fragile witness tables should not reference "
7688-
"less visible functions.");
7689-
}
7679+
for (const Entry &entry : getEntries()) {
7680+
if (entry.getKind() != SILWitnessTable::WitnessKind::Method)
7681+
continue;
7682+
7683+
auto *witnessFunction = entry.getMethodWitness().Witness;
7684+
if (!witnessFunction)
7685+
continue;
7686+
7687+
// If a SILWitnessTable is going to be serialized, it must only
7688+
// reference public or serializable functions.
7689+
if (isAnySerialized()) {
7690+
assert(
7691+
witnessFunction->hasValidLinkageForFragileRef(getSerializedKind()) &&
7692+
"Fragile witness tables should not reference "
7693+
"less visible functions.");
7694+
}
76907695

7691-
assert(F->getLoweredFunctionType()->getRepresentation() ==
7696+
assert(witnessFunction->getLoweredFunctionType()->getRepresentation() ==
76927697
SILFunctionTypeRepresentation::WitnessMethod &&
7693-
"Witnesses must have witness_method representation.");
7698+
"Witnesses must have witness_method representation.");
7699+
7700+
if (mod.getStage() != SILStage::Lowered &&
7701+
!mod.getASTContext().LangOpts.hasFeature(Feature::Embedded)) {
7702+
// Note the direction of the compatibility check: the witness
7703+
// function must be compatible with being used as the requirement
7704+
// type.
7705+
auto baseInfo = witnessFunction->getModule().Types.getConstantInfo(
7706+
TypeExpansionContext::minimal(),
7707+
entry.getMethodWitness().Requirement);
7708+
SmallString<32> baseName;
7709+
{
7710+
llvm::raw_svector_ostream os(baseName);
7711+
entry.getMethodWitness().Requirement.print(os);
76947712
}
7713+
7714+
SILVerifier(*witnessFunction, /*calleeCache=*/nullptr,
7715+
/*SingleFunction=*/true,
7716+
/*checkLinearLifetime=*/false)
7717+
.requireABICompatibleFunctionTypes(
7718+
witnessFunction->getLoweredFunctionType(),
7719+
baseInfo.getSILType().castTo<SILFunctionType>(),
7720+
"witness table entry for " + baseName + " must be ABI-compatible",
7721+
*witnessFunction);
76957722
}
7723+
}
76967724
}
76977725

76987726
/// Verify that a default witness table follows invariants.
7699-
void SILDefaultWitnessTable::verify(const SILModule &M) const {
7700-
#ifndef NDEBUG
7701-
for (const Entry &E : getEntries()) {
7727+
void SILDefaultWitnessTable::verify(const SILModule &mod) const {
7728+
if (!verificationEnabled(mod))
7729+
return;
7730+
7731+
for (const Entry &entry : getEntries()) {
77027732
// FIXME: associated type witnesses.
7703-
if (!E.isValid() || E.getKind() != SILWitnessTable::Method)
7733+
if (!entry.isValid() || entry.getKind() != SILWitnessTable::Method)
77047734
continue;
77057735

7706-
SILFunction *F = E.getMethodWitness().Witness;
7707-
if (!F)
7736+
auto *witnessFunction = entry.getMethodWitness().Witness;
7737+
if (!witnessFunction)
77087738
continue;
77097739

77107740
#if 0
77117741
// FIXME: For now, all default witnesses are private.
7712-
assert(F->hasValidLinkageForFragileRef(IsSerialized) &&
7742+
assert(witnessFunction->hasValidLinkageForFragileRef(IsSerialized) &&
77137743
"Default witness tables should not reference "
77147744
"less visible functions.");
77157745
#endif
77167746

7717-
assert(F->getLoweredFunctionType()->getRepresentation() ==
7718-
SILFunctionTypeRepresentation::WitnessMethod &&
7747+
assert(witnessFunction->getLoweredFunctionType()->getRepresentation() ==
7748+
SILFunctionTypeRepresentation::WitnessMethod &&
77197749
"Default witnesses must have witness_method representation.");
7750+
7751+
if (mod.getStage() != SILStage::Lowered &&
7752+
!mod.getASTContext().LangOpts.hasFeature(Feature::Embedded)) {
7753+
// Note the direction of the compatibility check: the witness
7754+
// function must be compatible with being used as the requirement
7755+
// type.
7756+
auto baseInfo = witnessFunction->getModule().Types.getConstantInfo(
7757+
TypeExpansionContext::minimal(),
7758+
entry.getMethodWitness().Requirement);
7759+
SmallString<32> baseName;
7760+
{
7761+
llvm::raw_svector_ostream os(baseName);
7762+
entry.getMethodWitness().Requirement.print(os);
7763+
}
7764+
7765+
SILVerifier(*witnessFunction, /*calleeCache=*/nullptr,
7766+
/*SingleFunction=*/true,
7767+
/*checkLinearLifetime=*/false)
7768+
.requireABICompatibleFunctionTypes(
7769+
witnessFunction->getLoweredFunctionType(),
7770+
baseInfo.getSILType().castTo<SILFunctionType>(),
7771+
"default witness table entry for " + baseName +
7772+
" must be ABI-compatible",
7773+
*witnessFunction);
7774+
}
77207775
}
7721-
#endif
77227776
}
77237777

77247778
/// Verify that a global variable follows invariants.

lib/SILGen/SILGenFunction.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2624,8 +2624,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
26242624
void collectThunkParams(
26252625
SILLocation loc, SmallVectorImpl<ManagedValue> &params,
26262626
SmallVectorImpl<ManagedValue> *indirectResultParams = nullptr,
2627-
SmallVectorImpl<ManagedValue> *indirectErrorParams = nullptr,
2628-
ThunkGenOptions options = {});
2627+
SmallVectorImpl<ManagedValue> *indirectErrorParams = nullptr);
26292628

26302629
/// Build the type of a function transformation thunk.
26312630
CanSILFunctionType buildThunkType(CanSILFunctionType &sourceType,

0 commit comments

Comments
 (0)