Skip to content

Commit b2a4f7e

Browse files
committed
[sil] Add to SIL and SILGen the ability to emit/represent implicit parameters.
I need this today to add the implicit isolated parameter... but I can imagine us adding more implicit parameters in the future, so it makes sense to formalize it so it is easier to do in the future.
1 parent 0b6ab9a commit b2a4f7e

File tree

13 files changed

+101
-22
lines changed

13 files changed

+101
-22
lines changed

include/swift/AST/TypeAttr.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ SIMPLE_SIL_TYPE_ATTR(captures_generics, CapturesGenerics)
111111
SIMPLE_SIL_TYPE_ATTR(moveOnly, MoveOnly)
112112
SIMPLE_SIL_TYPE_ATTR(sil_isolated, SILIsolated)
113113
SIMPLE_SIL_TYPE_ATTR(sil_sending, SILSending)
114+
SIMPLE_SIL_TYPE_ATTR(sil_implicit_leading_param, SILImplicitLeadingParam)
114115

115116
// SIL metatype attributes.
116117
SIMPLE_SIL_TYPE_ATTR(thin, Thin)

include/swift/AST/Types.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ class PlaceholderTypeRepr;
8383
enum class ReferenceCounting : uint8_t;
8484
enum class ResilienceExpansion : unsigned;
8585
class SILModule;
86+
class SILFunction;
8687
class SILType;
8788
class SourceLoc;
8889
class TypeAliasDecl;
@@ -4438,6 +4439,16 @@ class SILParameterInfo {
44384439
/// that the parameter must be an Optional actor or something that conforms
44394440
/// to AnyActor.
44404441
Isolated = 0x4,
4442+
4443+
/// Set if the given parameter is an implicit parameter that is not part of
4444+
/// the formal type. These are always located after the return values and
4445+
/// before the main parameters. This is because we want to at the SIL level
4446+
/// generally treat them as normal parameters... but when working with the
4447+
/// AST during lowering, we need to handle ignoring them appropriately.
4448+
///
4449+
/// DISCUSSION: These are enforced by the SIL verifier to always be in
4450+
/// between indirect results and the explicit parameters.
4451+
ImplicitLeading = 0x8,
44414452
};
44424453

44434454
using Options = OptionSet<Flag>;
@@ -4464,6 +4475,11 @@ class SILParameterInfo {
44644475
///
44654476
/// \c t must refer back to the function type this is a parameter for.
44664477
CanType getArgumentType(SILModule &M, const SILFunctionType *t, TypeExpansionContext context) const;
4478+
4479+
/// Helper function that just grabs the module, type, and context out of \arg
4480+
/// fn and then calls getArgumentType.
4481+
CanType getArgumentType(SILFunction *fn) const;
4482+
44674483
ParameterConvention getConvention() const { return convention; }
44684484
// Does this parameter convention require indirect storage? This reflects a
44694485
// SILFunctionType's formal (immutable) conventions, as opposed to the

lib/AST/ASTPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7583,6 +7583,11 @@ void SILParameterInfo::print(
75837583
Printer.printLifetimeDependence(*lifetimeDependence);
75847584
}
75857585

7586+
if (options.contains(SILParameterInfo::ImplicitLeading)) {
7587+
options -= SILParameterInfo::ImplicitLeading;
7588+
Printer << "@sil_implicit_leading_param ";
7589+
}
7590+
75867591
// If we did not handle a case in Options, this code was not updated
75877592
// appropriately.
75887593
assert(!bool(options) && "Code not updated for introduced option");

lib/ASTGen/Sources/ASTGen/TypeAttrs.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ extension ASTGenVisitor {
122122
.silUnowned,
123123
.silWeak,
124124
.silSending,
125+
.silImplicitLeadingParam,
125126
.unownedInnerPointer:
126127
break;
127128

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ CanSILFunctionType SILFunctionType::getUnsubstitutedType(SILModule &M) const {
108108
getWitnessMethodConformanceOrInvalid());
109109
}
110110

111+
CanType SILParameterInfo::getArgumentType(SILFunction *fn) const {
112+
return getArgumentType(fn->getModule(), fn->getLoweredFunctionType(),
113+
fn->getTypeExpansionContext());
114+
}
115+
111116
CanType SILParameterInfo::getArgumentType(SILModule &M,
112117
const SILFunctionType *t,
113118
TypeExpansionContext context) const {
@@ -1817,7 +1822,7 @@ class DestructureInputs {
18171822
/// Add a parameter that we derived from deconstructing the
18181823
/// formal type.
18191824
void addParameter(CanType loweredType, ParameterConvention convention,
1820-
ParameterTypeFlags origFlags) {
1825+
ParameterTypeFlags origFlags, bool isImplicit = false) {
18211826
SILParameterInfo param(loweredType, convention);
18221827

18231828
if (origFlags.isNoDerivative())
@@ -1826,6 +1831,8 @@ class DestructureInputs {
18261831
param = param.addingOption(SILParameterInfo::Sending);
18271832
if (origFlags.isIsolated())
18281833
param = param.addingOption(SILParameterInfo::Isolated);
1834+
if (isImplicit)
1835+
param = param.addingOption(SILParameterInfo::ImplicitLeading);
18291836

18301837
Inputs.push_back(param);
18311838
maybeAddForeignParameters();

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7230,22 +7230,30 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
72307230

72317231
void verifyParentFunctionSILFunctionType(CanSILFunctionType FTy) {
72327232
bool foundIsolatedParameter = false;
7233+
bool foundExplicitParameter = false;
7234+
72337235
for (const auto &parameterInfo : FTy->getParameters()) {
7236+
foundExplicitParameter |=
7237+
!parameterInfo.hasOption(SILParameterInfo::ImplicitLeading);
7238+
require(!foundExplicitParameter ||
7239+
!parameterInfo.hasOption(SILParameterInfo::ImplicitLeading),
7240+
"Implicit parameters must be before /all/ explicit parameters");
7241+
72347242
if (parameterInfo.hasOption(SILParameterInfo::Isolated)) {
7235-
auto argType = parameterInfo.getArgumentType(F.getModule(),
7236-
FTy,
7237-
F.getTypeExpansionContext());
7243+
auto argType = parameterInfo.getArgumentType(
7244+
F.getModule(), FTy, F.getTypeExpansionContext());
72387245

72397246
if (argType->isOptional())
72407247
argType = argType->lookThroughAllOptionalTypes()->getCanonicalType();
72417248

72427249
auto genericSig = FTy->getInvocationGenericSignature();
72437250
auto &ctx = F.getASTContext();
72447251
auto *actorProtocol = ctx.getProtocol(KnownProtocolKind::Actor);
7245-
auto *distributedProtocol = ctx.getProtocol(KnownProtocolKind::DistributedActor);
7252+
auto *distributedProtocol =
7253+
ctx.getProtocol(KnownProtocolKind::DistributedActor);
72467254
require(argType->isAnyActorType() ||
7247-
genericSig->requiresProtocol(argType, actorProtocol) ||
7248-
genericSig->requiresProtocol(argType, distributedProtocol),
7255+
genericSig->requiresProtocol(argType, actorProtocol) ||
7256+
genericSig->requiresProtocol(argType, distributedProtocol),
72497257
"Only any actor types can be isolated");
72507258
require(!foundIsolatedParameter, "Two isolated parameters");
72517259
foundIsolatedParameter = true;

lib/SILGen/SILGenBuilder.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -525,12 +525,12 @@ static ManagedValue createInputFunctionArgument(
525525
SILGenBuilder &B, SILType type, SILLocation loc, ValueDecl *decl = nullptr,
526526
bool isNoImplicitCopy = false,
527527
LifetimeAnnotation lifetimeAnnotation = LifetimeAnnotation::None,
528-
bool isClosureCapture = false,
529-
bool isFormalParameterPack = false) {
528+
bool isClosureCapture = false, bool isFormalParameterPack = false,
529+
bool isImplicitParameter = false) {
530530
auto &SGF = B.getSILGenFunction();
531531
SILFunction &F = B.getFunction();
532-
assert((F.isBare() || isFormalParameterPack || decl) &&
533-
"Function arguments of non-bare functions must have a decl");
532+
assert((F.isBare() || isFormalParameterPack || decl || isImplicitParameter) &&
533+
"explicit function arguments of non-bare functions must have a decl");
534534
auto *arg = F.begin()->createFunctionArgument(type, decl);
535535
if (auto *pd = dyn_cast_or_null<ParamDecl>(decl)) {
536536
if (!arg->getType().isMoveOnly()) {
@@ -585,11 +585,10 @@ static ManagedValue createInputFunctionArgument(
585585
ManagedValue SILGenBuilder::createInputFunctionArgument(
586586
SILType type, ValueDecl *decl, bool isNoImplicitCopy,
587587
LifetimeAnnotation lifetimeAnnotation, bool isClosureCapture,
588-
bool isFormalParameterPack) {
589-
return ::createInputFunctionArgument(*this, type, SILLocation(decl), decl,
590-
isNoImplicitCopy, lifetimeAnnotation,
591-
isClosureCapture,
592-
isFormalParameterPack);
588+
bool isFormalParameterPack, bool isImplicit) {
589+
return ::createInputFunctionArgument(
590+
*this, type, SILLocation(decl), decl, isNoImplicitCopy,
591+
lifetimeAnnotation, isClosureCapture, isFormalParameterPack, isImplicit);
593592
}
594593

595594
ManagedValue SILGenBuilder::createInputFunctionArgument(

lib/SILGen/SILGenBuilder.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,14 @@ class SILGenBuilder : public SILBuilder {
275275

276276
/// Create a SILArgument for an input parameter. Asserts if used to create a
277277
/// function argument for an out parameter.
278+
///
279+
/// \arg isImplicitParameter set to true if this is an implicit parameter that
280+
/// is inserted by SILGen and does not show up at the AST level.
278281
ManagedValue createInputFunctionArgument(
279282
SILType type, ValueDecl *decl, bool isNoImplicitCopy = false,
280283
LifetimeAnnotation lifetimeAnnotation = LifetimeAnnotation::None,
281-
bool isClosureCapture = false, bool isFormalParameterPack = false);
284+
bool isClosureCapture = false, bool isFormalParameterPack = false,
285+
bool isImplicitParameter = false);
282286

283287
/// Create a SILArgument for an input parameter. Uses \p loc to create any
284288
/// copies necessary. Asserts if used to create a function argument for an out

lib/SILGen/SILGenProlog.cpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,36 +98,48 @@ struct LoweredParamGenerator {
9898
ParamDecl *paramDecl = nullptr;
9999
bool isNoImplicitCopy = false;
100100
LifetimeAnnotation lifetimeAnnotation = LifetimeAnnotation::None;
101+
bool isImplicitParameter = false;
101102

102103
void configureParamData(ParamDecl *paramDecl, bool isNoImplicitCopy,
103104
LifetimeAnnotation lifetimeAnnotation) {
104105
this->paramDecl = paramDecl;
105106
this->isNoImplicitCopy = isNoImplicitCopy;
106107
this->lifetimeAnnotation = lifetimeAnnotation;
108+
this->isImplicitParameter = false;
107109
}
110+
111+
void configureParamDataForImplicitParam() { isImplicitParameter = true; }
112+
108113
void resetParamData() {
109114
configureParamData(nullptr, false, LifetimeAnnotation::None);
110115
}
111116

112117
ManagedValue claimNext() {
113118
auto parameterInfo = parameterTypes.claimNext();
114119

115-
// We should only be called without a param decl when pulling
116-
// pack parameters out for multiple formal parameters (or a single
117-
// formal parameter pack).
120+
// We should only be called without a param decl when pulling pack
121+
// parameters out for multiple formal parameters (or a single formal
122+
// parameter pack) or if we have an implicit parameter.
123+
//
118124
// TODO: preserve the parameters captured by the pack into the SIL
119125
// representation.
120-
bool isFormalParameterPack = (paramDecl == nullptr);
126+
bool isFormalParameterPack = (paramDecl == nullptr) && !isImplicitParameter;
121127
assert(!isFormalParameterPack || parameterInfo.isPack());
122128

123129
auto paramType =
124130
SGF.F.mapTypeIntoContext(SGF.getSILType(parameterInfo, fnTy));
125131
ManagedValue mv = SGF.B.createInputFunctionArgument(
126132
paramType, paramDecl, isNoImplicitCopy, lifetimeAnnotation,
127-
/*isClosureCapture*/ false, isFormalParameterPack);
133+
/*isClosureCapture*/ false, isFormalParameterPack, isImplicitParameter);
128134
return mv;
129135
}
130136

137+
std::optional<SILParameterInfo> peek() const {
138+
if (isFinished())
139+
return {};
140+
return parameterTypes.get();
141+
}
142+
131143
bool isFinished() const {
132144
return parameterTypes.isFinished();
133145
}
@@ -655,6 +667,17 @@ class ArgumentInitHelper {
655667
/*ignore final*/ false);
656668
}
657669

670+
// Go through all of our implicit SIL parameters and emit them. These do not
671+
// exist in the AST and always appear in between the results and the
672+
// explicit parameters.
673+
while (auto param = loweredParams.peek()) {
674+
if (!param->hasOption(SILParameterInfo::ImplicitLeading))
675+
break;
676+
loweredParams.configureParamDataForImplicitParam();
677+
loweredParams.advance();
678+
loweredParams.resetParamData();
679+
}
680+
658681
// Emit each of the function's explicit parameters in order.
659682
if (paramList) {
660683
for (auto *param : *paramList)

lib/Sema/TypeCheckType.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4725,6 +4725,10 @@ SILParameterInfo TypeResolver::resolveSILParameter(
47254725
parameterOptions |= SILParameterInfo::Sending;
47264726
return true;
47274727

4728+
case TypeAttrKind::SILImplicitLeadingParam:
4729+
parameterOptions |= SILParameterInfo::ImplicitLeading;
4730+
return true;
4731+
47284732
default:
47294733
return false;
47304734
}

0 commit comments

Comments
 (0)