Skip to content

Commit 5cf05f5

Browse files
committed
Implement arity reabstraction for closures
1 parent 3fe4646 commit 5cf05f5

File tree

6 files changed

+499
-326
lines changed

6 files changed

+499
-326
lines changed

lib/SIL/IR/AbstractionPattern.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2310,10 +2310,13 @@ const {
23102310
if (yieldType)
23112311
yieldType = yieldType->getReducedType(substSig);
23122312

2313+
// Note that we specifically do not want to put subMap in the
2314+
// abstraction patterns here, because the types we will be lowering
2315+
// against them will not be substituted.
23132316
return std::make_tuple(
2314-
AbstractionPattern(subMap, substSig, substTy->getReducedType(substSig)),
2317+
AbstractionPattern(substSig, substTy->getReducedType(substSig)),
23152318
subMap,
23162319
yieldType
2317-
? AbstractionPattern(subMap, substSig, yieldType)
2320+
? AbstractionPattern(substSig, yieldType)
23182321
: AbstractionPattern::getInvalid());
23192322
}

lib/SILGen/FunctionInputGenerator.h

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
//===--- FunctionInputGenerator.h - Generator for formal params -*- C++ -*-===//
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+
// This file defines FunctionInputGenerator, which generates the sequence
14+
// of formal parameters for a SIL function given its abstraction pattern,
15+
// informing the caller of important information such as the orig and subst
16+
// types and whether the parameter is passed as part of a pack. (It's this
17+
// latter possibility that makes this relatively complicated.)
18+
//
19+
// The assumption is that this will be used as part of binding the parameters
20+
// for a function and that the client of the traversal will claim those
21+
// parameters one by one as the traversal goes on.
22+
//
23+
// In order to properly handle packs of parameters, and especially empty
24+
// packs of parameters, this generator must claim the pack parameters
25+
// as it goes. As a result, it's actually quite important that clients
26+
// use the pattern above of claiming non-pack parameter values immediately
27+
// while traversing a parameter and before advancing to the next parameter.
28+
//
29+
//===----------------------------------------------------------------------===//
30+
31+
#ifndef SWIFT_SILGEN_FUNCTIONINPUTGENERATOR_H
32+
#define SWIFT_SILGEN_FUNCTIONINPUTGENERATOR_H
33+
34+
#include "ManagedValue.h"
35+
#include "swift/SIL/AbstractionPatternGenerators.h"
36+
#include "swift/AST/Types.h"
37+
#include "swift/Basic/Generators.h"
38+
39+
namespace swift {
40+
namespace Lowering {
41+
42+
/// A class for destructuring a list of formal input parameters given
43+
/// an abstraction pattern for it.
44+
class FunctionInputGenerator {
45+
const ASTContext &ctx;
46+
SimpleGeneratorRef<ManagedValue> inputs;
47+
FunctionParamGenerator origParam;
48+
49+
/// If origParam.isPackExpansion(), this is the pack currently
50+
/// being destructured. The cleanup on it is only for the components
51+
/// starting at substParamIndex.
52+
ManagedValue packValue;
53+
54+
/// If origParam.isPackExpansion(), this is the formal type
55+
/// of the orig parameter pack.
56+
CanPackType formalPackType;
57+
58+
/// The current index within origParam.getSubstParams().
59+
unsigned substParamIndex;
60+
61+
/// Precondition: we aren't finished visiting orig parameters,
62+
/// and we've already readied the current orig parameter.
63+
///
64+
/// Ready the next subst parameter (the one at inputSubstParamIndex)
65+
/// from the current orig parameter. If we've exhausted the supply
66+
/// of subst parameters from this orig parameter, advance to the
67+
/// next orig parameter and repeat.
68+
///
69+
/// Postcondition: we're either finished or properly configured
70+
/// with a subst parameter that hasn't been presented before.
71+
void readyNextSubstParameter() {
72+
while (true) {
73+
assert(!origParam.isFinished());
74+
assert(substParamIndex <= origParam.getSubstParams().size());
75+
76+
// If we haven't reached the limit of the current parameter yet,
77+
// continue.
78+
if (substParamIndex != origParam.getSubstParams().size())
79+
return;
80+
81+
// Otherwise, advance, and ready the next orig parameter if we
82+
// didn't finish.
83+
origParam.advance();
84+
if (origParam.isFinished()) return;
85+
readyOrigParameter();
86+
}
87+
}
88+
89+
/// Ready the current orig parameter.
90+
void readyOrigParameter() {
91+
substParamIndex = 0;
92+
if (origParam.isPackExpansion()) {
93+
// The pack value exists in the lowered parameters and must be
94+
// claimed whether it contains formal parameters or not.
95+
packValue = inputs.claimNext();
96+
97+
// We don't need to do any other set up if we're going to
98+
// immediately move past it, though.
99+
if (origParam.getSubstParams().empty())
100+
return;
101+
102+
// Compute a formal pack type for the pack.
103+
formalPackType = CanPackType::get(ctx, origParam.getSubstParams());
104+
}
105+
}
106+
107+
public:
108+
FunctionInputGenerator(const ASTContext &ctx,
109+
SimpleGeneratorRef<ManagedValue> inputs,
110+
AbstractionPattern origFunctionType,
111+
AnyFunctionType::CanParamArrayRef substParams,
112+
bool ignoreFinalParam)
113+
: ctx(ctx), inputs(inputs),
114+
origParam(origFunctionType, substParams, ignoreFinalParam) {
115+
116+
if (!origParam.isFinished()) {
117+
readyOrigParameter();
118+
readyNextSubstParameter();
119+
}
120+
}
121+
122+
/// Is this generator finished? If so, the getters below may not be used.
123+
bool isFinished() const {
124+
return origParam.isFinished();
125+
}
126+
127+
bool isOrigPackExpansion() const {
128+
return origParam.isPackExpansion();
129+
}
130+
131+
AbstractionPattern getOrigType() const {
132+
return origParam.getOrigType();
133+
}
134+
135+
AnyFunctionType::CanParam getSubstParam() const {
136+
return origParam.getSubstParams()[substParamIndex];
137+
}
138+
139+
ManagedValue getPackValue() const {
140+
assert(isOrigPackExpansion());
141+
return packValue;
142+
}
143+
144+
void updatePackValue(ManagedValue newPackValue) {
145+
assert(isOrigPackExpansion());
146+
packValue = newPackValue;
147+
}
148+
149+
unsigned getPackComponentIndex() const {
150+
assert(isOrigPackExpansion());
151+
return substParamIndex;
152+
}
153+
154+
CanPackType getFormalPackType() const {
155+
assert(isOrigPackExpansion());
156+
return formalPackType;
157+
}
158+
159+
/// Given that we just processed an input, advance to the next,
160+
/// if there is on.
161+
///
162+
/// Postcondition: either isFinished() or all of the invariants
163+
/// for the mutable state have been established.
164+
void advance() {
165+
assert(!isFinished());
166+
assert(substParamIndex < origParam.getSubstParams().size());
167+
substParamIndex++;
168+
169+
readyNextSubstParameter();
170+
}
171+
172+
void finish() {
173+
origParam.finish();
174+
}
175+
176+
/// Project out the current pack component. Do not call this multiple
177+
/// times for the same component.
178+
ManagedValue projectPackComponent(SILGenFunction &SGF, SILLocation loc);
179+
};
180+
181+
} // end namespace Lowering
182+
} // end namespace swift
183+
184+
#endif

lib/SILGen/SILGenFunction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,7 @@ void SILGenFunction::emitClosure(AbstractClosureExpr *ace) {
687687
SILDeclRef(ace));
688688
emitProlog(captureInfo, ace->getParameters(), /*selfParam=*/nullptr,
689689
ace, resultIfaceTy, ace->isBodyThrowing(), ace->getLoc(),
690-
SGM.M.Types.getConstantAbstractionPattern(SILDeclRef(ace)));
690+
OrigFnType);
691691
prepareEpilog(resultIfaceTy, ace->isBodyThrowing(), CleanupLocation(ace));
692692

693693
emitProfilerIncrement(ace);

0 commit comments

Comments
 (0)