Skip to content

Commit 6f3d452

Browse files
committed
[ast] Represent a parameter's isolation at the SIL level.
I did this by adding flag on SILParamInfo. rdar://121387872
1 parent 0e8ffef commit 6f3d452

30 files changed

+252
-121
lines changed

include/swift/AST/ASTBridging.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1206,7 +1206,8 @@ enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedTypeAttrKind : size_t {
12061206
BridgedTypeAttrKind_moveOnly,
12071207
BridgedTypeAttrKind_thin,
12081208
BridgedTypeAttrKind_thick,
1209-
BridgedTypeAttrKind_Count
1209+
BridgedTypeAttrKind_Count,
1210+
BridgedTypeAttrKind_isolated,
12101211
};
12111212

12121213
SWIFT_NAME("BridgedTypeAttrKind.init(from:)")

include/swift/AST/Attr.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ TYPE_ATTR(yield_many)
9999
TYPE_ATTR(captures_generics)
100100
// Used at the SIL level to mark a type as moveOnly.
101101
TYPE_ATTR(moveOnly)
102+
TYPE_ATTR(isolated)
102103

103104
// SIL metatype attributes.
104105
TYPE_ATTR(thin)

include/swift/AST/TypeDifferenceVisitor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ class CanTypeDifferenceVisitor : public CanTypePairVisitor<Impl, bool> {
291291
bool visitComponent(CanType type1, CanType type2,
292292
SILParameterInfo param1, SILParameterInfo param2) {
293293
if (param1.getConvention() != param2.getConvention() ||
294-
param1.getOptions().containsOnly(param2.getOptions()))
294+
!param1.getOptions().containsOnly(param2.getOptions()))
295295
return asImpl().visitDifferentTypeStructure(type1, type2);
296296

297297
return asImpl().visit(param1.getInterfaceType(),
@@ -410,6 +410,7 @@ class CanTypeDifferenceVisitor : public CanTypePairVisitor<Impl, bool> {
410410
return asImpl().visit(CanType(componentType1), CanType(componentType2));
411411
}
412412

413+
protected:
413414
template <class T>
414415
bool visitComponentArray(CanType type1, CanType type2, T array1, T array2) {
415416
if (array1.size() != array2.size())

include/swift/AST/Types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4129,6 +4129,9 @@ class SILParameterInfo {
41294129

41304130
/// Set if the given parameter is transferring.
41314131
Transferring = 0x2,
4132+
4133+
/// Set if the given parameter is isolated.
4134+
Isolated = 0x4,
41324135
};
41334136

41344137
using Options = OptionSet<Flag>;

lib/AST/ASTPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8086,6 +8086,11 @@ void SILParameterInfo::print(ASTPrinter &Printer,
80868086
Printer << "@transferring ";
80878087
}
80888088

8089+
if (options.contains(SILParameterInfo::Isolated)) {
8090+
options -= SILParameterInfo::Isolated;
8091+
Printer << "@isolated ";
8092+
}
8093+
80898094
// If we did not handle a case in Options, this code was not updated
80908095
// appropriately.
80918096
assert(!bool(options) && "Code not updated for introduced option");

lib/AST/TypeRepr.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,8 @@ void AttributedTypeRepr::printAttrs(ASTPrinter &Printer,
236236
Printer.printSimpleAttr("@Sendable") << " ";
237237
if (hasAttr(TAK_noDerivative))
238238
Printer.printSimpleAttr("@noDerivative") << " ";
239+
if (hasAttr(TAK_isolated))
240+
Printer.printSimpleAttr("@isolated") << " ";
239241

240242
if (hasAttr(TAK_differentiable)) {
241243
Printer.callPrintStructurePre(PrintStructureKind::BuiltinAttribute);

lib/ASTGen/Sources/ASTGen/Types.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,8 @@ extension ASTGenVisitor {
415415
.sil_weak, .sil_unowned, .inout, .block_storage, .box,
416416
.dynamic_self, .sil_unmanaged, .error, .error_indirect,
417417
.error_unowned, .direct, .inout_aliasable,
418-
.in_guaranteed, .in_constant, .captures_generics, .moveOnly:
418+
.in_guaranteed, .in_constant, .captures_generics, .moveOnly,
419+
.isolated:
419420
fallthrough
420421

421422
case .autoclosure, .escaping, .noescape, .noDerivative, .async,

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1737,6 +1737,8 @@ class DestructureInputs {
17371737
param = param.addingOption(SILParameterInfo::NotDifferentiable);
17381738
if (origFlags.isTransferring())
17391739
param = param.addingOption(SILParameterInfo::Transferring);
1740+
if (origFlags.isIsolated())
1741+
param = param.addingOption(SILParameterInfo::Isolated);
17401742

17411743
Inputs.push_back(param);
17421744
maybeAddForeignParameters();

lib/SILGen/SILGenThunk.cpp

Lines changed: 71 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "swift/AST/ForeignAsyncConvention.h"
3333
#include "swift/AST/ForeignErrorConvention.h"
3434
#include "swift/AST/GenericEnvironment.h"
35+
#include "swift/AST/TypeDifferenceVisitor.h"
3536
#include "swift/Basic/STLExtras.h"
3637
#include "swift/SIL/FormalLinkage.h"
3738
#include "swift/SIL/PrettyStackTrace.h"
@@ -139,6 +140,51 @@ void SILGenModule::emitBackDeploymentThunk(SILDeclRef thunk) {
139140
emitFunctionDefinition(thunk, getFunction(thunk, ForDefinition));
140141
}
141142

143+
namespace {
144+
145+
/// Checker that validates that a distributed thunk is completely the same
146+
/// except that self can vary by isolation.
147+
struct DistributedThunkDiffChecker
148+
: CanTypeDifferenceVisitor<DistributedThunkDiffChecker> {
149+
using SuperTy = CanTypeDifferenceVisitor<DistributedThunkDiffChecker>;
150+
151+
bool visitSILFunctionTypeComponents(CanSILFunctionType type1,
152+
CanSILFunctionType type2) {
153+
// If they do not both have a self param. Just delegate to our parent.
154+
if (!type1->hasSelfParam() || !type2->hasSelfParam()) {
155+
return SuperTy::visitSILFunctionTypeComponents(type1, type2);
156+
}
157+
158+
// Otherwise, we both have self. First check if we have the same number of
159+
// parameters.
160+
auto type1Params = type1->getParameters();
161+
auto type2Params = type2->getParameters();
162+
if (type1Params.size() != type2Params.size())
163+
return visitDifferentTypeStructure(type1, type2);
164+
165+
// Then check if self is the same ignoring isolation.
166+
auto self1 = type1Params.back();
167+
auto self2 = type2Params.back();
168+
auto self1Options = self1.getOptions() - SILParameterInfo::Isolated;
169+
auto self2Options = self2.getOptions() - SILParameterInfo::Isolated;
170+
171+
if (self1.getConvention() != self2.getConvention() ||
172+
!self1Options.containsOnly(self2Options))
173+
return visitDifferentTypeStructure(type1, type2);
174+
175+
// Finally, check our self type, non-self components, results, and yields.
176+
return visit(self1.getInterfaceType(), self2.getInterfaceType()) ||
177+
visitComponentArray(type1, type2, type1Params.drop_back(),
178+
type2Params.drop_back()) ||
179+
visitComponentArray(type1, type2, type1->getResults(),
180+
type2->getResults()) ||
181+
visitComponentArray(type1, type2, type1->getYields(),
182+
type2->getYields());
183+
}
184+
};
185+
186+
} // namespace
187+
142188
SILValue
143189
SILGenFunction::emitGlobalFunctionRef(SILLocation loc, SILDeclRef constant,
144190
SILConstantInfo constantInfo,
@@ -171,18 +217,35 @@ SILGenFunction::emitGlobalFunctionRef(SILLocation loc, SILDeclRef constant,
171217
auto existingType =
172218
f->getLoweredFunctionTypeInContext(B.getTypeExpansionContext());
173219
if (existingType != constantFnTypeInContext) {
174-
// This can happen for example when using @_silgen_name or @_extern(c)
175-
// attributes
176-
SGM.diagnose(loc.getSourceLoc(), diag::function_type_mismatch, existingType,
177-
constantFnTypeInContext);
178-
SGM.diagnose(f->getLocation().getSourceLoc(), diag::function_declared_here);
179-
return SILUndef::get(constantInfo.getSILType(), F);
220+
auto emitError = [&] {
221+
// This can happen for example when using @_silgen_name or @_extern(c)
222+
// attributes
223+
SGM.diagnose(loc.getSourceLoc(), diag::function_type_mismatch,
224+
existingType, constantFnTypeInContext);
225+
SGM.diagnose(f->getLocation().getSourceLoc(),
226+
diag::function_declared_here);
227+
return SILUndef::get(constantInfo.getSILType(), F);
228+
};
229+
230+
// If we have a distributed thunk, see if we only differ by isolation.
231+
if (f->isDistributed() && f->isThunk()) {
232+
DistributedThunkDiffChecker diffChecker;
233+
if (diffChecker.visit(existingType, constantFnTypeInContext)) {
234+
return emitError();
235+
}
236+
237+
// We differ only by isolation... so do not error.
238+
} else {
239+
// This can happen for example when using @_silgen_name or @_extern(c)
240+
// attributes
241+
return emitError();
242+
}
180243
}
181244

182245
if (callPreviousDynamicReplaceableImpl)
183246
return B.createPreviousDynamicFunctionRef(loc, f);
184-
else
185-
return B.createFunctionRefFor(loc, f);
247+
248+
return B.createFunctionRefFor(loc, f);
186249
}
187250

188251
static const clang::Type *prependParameterType(

lib/Sema/TypeCheckType.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2998,13 +2998,10 @@ TypeResolver::resolveAttributedType(TypeAttributes &attrs, TypeRepr *repr,
29982998
// Some function representation attributes are not supported at source level;
29992999
// only SIL knows how to handle them. Reject them unless this is a SIL input.
30003000
if (!(options & TypeResolutionFlags::SILType)) {
3001-
for (auto silOnlyAttr : {TAK_pseudogeneric,
3002-
TAK_unimplementable,
3003-
TAK_callee_owned,
3004-
TAK_callee_guaranteed,
3005-
TAK_noescape,
3006-
TAK_yield_once,
3007-
TAK_yield_many}) {
3001+
for (auto silOnlyAttr :
3002+
{TAK_pseudogeneric, TAK_unimplementable, TAK_callee_owned,
3003+
TAK_callee_guaranteed, TAK_noescape, TAK_yield_once, TAK_yield_many,
3004+
TAK_isolated}) {
30083005
checkUnsupportedAttr(silOnlyAttr);
30093006
}
30103007
}
@@ -4103,6 +4100,10 @@ SILParameterInfo TypeResolver::resolveSILParameter(
41034100
attrs.clearAttribute(TAK_noDerivative);
41044101
parameterOptions |= SILParameterInfo::NotDifferentiable;
41054102
}
4103+
if (attrs.has(TAK_isolated)) {
4104+
attrs.clearAttribute(TAK_isolated);
4105+
parameterOptions |= SILParameterInfo::Isolated;
4106+
}
41064107

41074108
type = resolveAttributedType(attrs, attrRepr->getTypeRepr(), options);
41084109
} else {

0 commit comments

Comments
 (0)