Skip to content

Commit 0d4ff45

Browse files
authored
Merge pull request #74020 from slavapestov/pack-expansion-closures-part-7
Pack expansion closures part 7
2 parents 2a75075 + 8a7f0b8 commit 0d4ff45

File tree

15 files changed

+427
-89
lines changed

15 files changed

+427
-89
lines changed

include/swift/AST/CaptureInfo.h

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,12 @@ template <> struct DenseMapInfo<swift::CapturedValue>;
4141
namespace swift {
4242
class ValueDecl;
4343
class FuncDecl;
44+
class Expr;
4445
class OpaqueValueExpr;
46+
class PackElementExpr;
4547
class VarDecl;
4648
class GenericEnvironment;
49+
class Type;
4750

4851
/// CapturedValue includes both the declaration being captured, along with flags
4952
/// that indicate how it is captured.
@@ -52,7 +55,7 @@ class CapturedValue {
5255

5356
public:
5457
using Storage =
55-
llvm::PointerIntPair<llvm::PointerUnion<ValueDecl*, OpaqueValueExpr*>, 2,
58+
llvm::PointerIntPair<llvm::PointerUnion<ValueDecl *, Expr *>, 2,
5659
unsigned>;
5760

5861
private:
@@ -78,15 +81,7 @@ class CapturedValue {
7881
CapturedValue(ValueDecl *Val, unsigned Flags, SourceLoc Loc)
7982
: Value(Val, Flags), Loc(Loc) {}
8083

81-
private:
82-
// This is only used in TypeLowering when forming Lowered Capture
83-
// Info. OpaqueValueExpr captured value should never show up in the AST
84-
// itself.
85-
//
86-
// NOTE: AbstractClosureExpr::getIsolationCrossing relies upon this and
87-
// asserts that it never sees one of these.
88-
explicit CapturedValue(OpaqueValueExpr *Val, unsigned Flags)
89-
: Value(Val, Flags), Loc(SourceLoc()) {}
84+
CapturedValue(Expr *Val, unsigned Flags);
9085

9186
public:
9287
static CapturedValue getDynamicSelfMetadata() {
@@ -97,36 +92,38 @@ class CapturedValue {
9792
bool isNoEscape() const { return Value.getInt() & IsNoEscape; }
9893

9994
bool isDynamicSelfMetadata() const { return !Value.getPointer(); }
100-
bool isOpaqueValue() const {
101-
return Value.getPointer().is<OpaqueValueExpr *>();
95+
96+
bool isExpr() const {
97+
return Value.getPointer().dyn_cast<Expr *>();
10298
}
10399

100+
bool isPackElement() const;
101+
bool isOpaqueValue() const;
102+
104103
/// Returns true if this captured value is a local capture.
105104
///
106105
/// NOTE: This implies that the value is not dynamic self metadata, since
107106
/// values with decls are the only values that are able to be local captures.
108107
bool isLocalCapture() const;
109108

110-
CapturedValue mergeFlags(CapturedValue cv) {
111-
assert(Value.getPointer() == cv.Value.getPointer() &&
112-
"merging flags on two different value decls");
113-
return CapturedValue(
114-
Storage(Value.getPointer(), getFlags() & cv.getFlags()),
115-
Loc);
109+
CapturedValue mergeFlags(unsigned flags) const {
110+
return CapturedValue(Storage(Value.getPointer(), getFlags() & flags), Loc);
116111
}
117112

118113
ValueDecl *getDecl() const {
119-
assert(Value.getPointer() && "dynamic Self metadata capture does not "
120-
"have a value");
121114
return Value.getPointer().dyn_cast<ValueDecl *>();
122115
}
123116

124-
OpaqueValueExpr *getOpaqueValue() const {
125-
assert(Value.getPointer() && "dynamic Self metadata capture does not "
126-
"have a value");
127-
return Value.getPointer().dyn_cast<OpaqueValueExpr *>();
117+
Expr *getExpr() const {
118+
return Value.getPointer().dyn_cast<Expr *>();
128119
}
129120

121+
OpaqueValueExpr *getOpaqueValue() const;
122+
123+
PackElementExpr *getPackElement() const;
124+
125+
Type getPackElementType() const;
126+
130127
SourceLoc getLoc() const { return Loc; }
131128

132129
unsigned getFlags() const { return Value.getInt(); }

lib/AST/CaptureInfo.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,36 @@
1313
#include "swift/AST/CaptureInfo.h"
1414
#include "swift/AST/ASTContext.h"
1515
#include "swift/AST/Decl.h"
16+
#include "swift/AST/Expr.h"
1617
#include "swift/AST/GenericEnvironment.h"
1718
#include "llvm/Support/raw_ostream.h"
1819

1920
using namespace swift;
2021

22+
CapturedValue::CapturedValue(Expr *Val, unsigned Flags)
23+
: Value(Val, Flags), Loc(SourceLoc()) {
24+
assert(isa<OpaqueValueExpr>(Val) || isa<PackElementExpr>(Val));
25+
}
26+
27+
bool CapturedValue::isPackElement() const {
28+
return isExpr() && isa<PackElementExpr>(getExpr());
29+
}
30+
bool CapturedValue::isOpaqueValue() const {
31+
return isExpr() && isa<OpaqueValueExpr>(getExpr());
32+
}
33+
34+
OpaqueValueExpr *CapturedValue::getOpaqueValue() const {
35+
return dyn_cast_or_null<OpaqueValueExpr>(getExpr());
36+
}
37+
38+
PackElementExpr *CapturedValue::getPackElement() const {
39+
return dyn_cast_or_null<PackElementExpr>(getExpr());
40+
}
41+
42+
Type CapturedValue::getPackElementType() const {
43+
return getPackElement()->getType();
44+
}
45+
2146
ArrayRef<CapturedValue>
2247
CaptureInfo::CaptureInfoStorage::getCaptures() const {
2348
return llvm::ArrayRef(this->getTrailingObjects<CapturedValue>(), NumCapturedValues);
@@ -126,7 +151,18 @@ void CaptureInfo::print(raw_ostream &OS) const {
126151

127152
interleave(getCaptures(),
128153
[&](const CapturedValue &capture) {
129-
OS << capture.getDecl()->getBaseName();
154+
if (capture.getDecl())
155+
OS << capture.getDecl()->getBaseName();
156+
else if (capture.isPackElement()) {
157+
OS << "[pack element] ";
158+
capture.getPackElement()->dump(OS);
159+
} else if (capture.isOpaqueValue()) {
160+
OS << "[opaque] ";
161+
capture.getOpaqueValue()->dump(OS);
162+
} else {
163+
OS << "[unknown] ";
164+
assert(false);
165+
}
130166

131167
if (capture.isDirect())
132168
OS << "<direct>";

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2007,33 +2007,39 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
20072007
continue;
20082008
}
20092009

2010-
auto *varDecl = cast<VarDecl>(capture.getDecl());
2010+
auto options = SILParameterInfo::Options();
2011+
2012+
Type type;
2013+
VarDecl *varDecl = nullptr;
2014+
if (auto *expr = capture.getPackElement()) {
2015+
type = expr->getType();
2016+
} else {
2017+
varDecl = cast<VarDecl>(capture.getDecl());
2018+
type = varDecl->getTypeInContext();
2019+
2020+
// If we're capturing a parameter pack, wrap it in a tuple.
2021+
if (type->is<PackExpansionType>()) {
2022+
assert(!cast<ParamDecl>(varDecl)->supportsMutation() &&
2023+
"Cannot capture a pack as an lvalue");
2024+
2025+
SmallVector<TupleTypeElt, 1> elts;
2026+
elts.push_back(type);
2027+
type = TupleType::get(elts, TC.Context);
2028+
}
2029+
2030+
if (isolatedParam == varDecl) {
2031+
options |= SILParameterInfo::Isolated;
2032+
isolatedParam = nullptr;
2033+
}
2034+
}
20112035

2012-
auto type = varDecl->getTypeInContext();
20132036
assert(!type->hasLocalArchetype() ||
20142037
(genericSig && origGenericSig &&
20152038
!genericSig->isEqual(origGenericSig)));
20162039
type = mapTypeOutOfContext(type);
20172040

20182041
auto canType = type->getReducedType(
20192042
genericSig ? genericSig : origGenericSig);
2020-
2021-
auto options = SILParameterInfo::Options();
2022-
if (isolatedParam == varDecl) {
2023-
options |= SILParameterInfo::Isolated;
2024-
isolatedParam = nullptr;
2025-
}
2026-
2027-
// If we're capturing a parameter pack, wrap it in a tuple.
2028-
if (isa<PackExpansionType>(canType)) {
2029-
assert(!cast<ParamDecl>(varDecl)->supportsMutation() &&
2030-
"Cannot capture a pack as an lvalue");
2031-
2032-
SmallVector<TupleTypeElt, 1> elts;
2033-
elts.push_back(canType);
2034-
canType = CanTupleType(TupleType::get(elts, TC.Context));
2035-
}
2036-
20372043
auto &loweredTL =
20382044
TC.getTypeLowering(AbstractionPattern(genericSig, canType), canType,
20392045
expansion);
@@ -2055,6 +2061,8 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
20552061
break;
20562062
}
20572063
case CaptureKind::Box: {
2064+
assert(varDecl);
2065+
20582066
// The type in the box is lowered in the minimal context.
20592067
auto minimalLoweredTy =
20602068
TC.getTypeLowering(AbstractionPattern(genericSig, canType), canType,
@@ -2072,6 +2080,8 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
20722080
break;
20732081
}
20742082
case CaptureKind::ImmutableBox: {
2083+
assert(varDecl);
2084+
20752085
// The type in the box is lowered in the minimal context.
20762086
auto minimalLoweredTy =
20772087
TC.getTypeLowering(AbstractionPattern(genericSig, canType), canType,

lib/SIL/IR/TypeLowering.cpp

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,19 @@ static bool hasSingletonMetatype(CanType instanceType) {
118118

119119
CaptureKind TypeConverter::getDeclCaptureKind(CapturedValue capture,
120120
TypeExpansionContext expansion) {
121+
if (auto *expr = capture.getPackElement()) {
122+
auto contextTy = expr->getType();
123+
auto &lowering = getTypeLowering(
124+
contextTy, TypeExpansionContext::noOpaqueTypeArchetypesSubstitution(
125+
expansion.getResilienceExpansion()));
126+
127+
assert(!contextTy->isNoncopyable() && "Not implemented");
128+
if (!lowering.isAddressOnly())
129+
return CaptureKind::Constant;
130+
131+
return CaptureKind::Immutable;
132+
}
133+
121134
auto decl = capture.getDecl();
122135
auto *var = cast<VarDecl>(decl);
123136
assert(var->hasStorage() &&
@@ -4241,7 +4254,10 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
42414254

42424255
// Recursively collect transitive captures from captured local functions.
42434256
llvm::DenseSet<AnyFunctionRef> visitedFunctions;
4244-
llvm::MapVector<ValueDecl*,CapturedValue> captures;
4257+
4258+
// FIXME: CapturedValue should just be a hash key
4259+
llvm::MapVector<VarDecl *, CapturedValue> varCaptures;
4260+
llvm::MapVector<PackElementExpr *, CapturedValue> packElementCaptures;
42454261

42464262
// If there is a capture of 'self' with dynamic 'Self' type, it goes last so
42474263
// that IRGen can pass dynamic 'Self' metadata.
@@ -4259,12 +4275,23 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
42594275
std::function<void (SILDeclRef)> collectConstantCaptures;
42604276

42614277
auto recordCapture = [&](CapturedValue capture) {
4262-
ValueDecl *value = capture.getDecl();
4263-
auto existing = captures.find(value);
4264-
if (existing != captures.end()) {
4265-
existing->second = existing->second.mergeFlags(capture);
4278+
if (auto *expr = capture.getPackElement()) {
4279+
auto existing = packElementCaptures.find(expr);
4280+
if (existing != packElementCaptures.end()) {
4281+
existing->second = existing->second.mergeFlags(capture.getFlags());
4282+
} else {
4283+
packElementCaptures.insert(std::pair<PackElementExpr *, CapturedValue>(
4284+
expr, capture));
4285+
}
42664286
} else {
4267-
captures.insert(std::pair<ValueDecl *, CapturedValue>(value, capture));
4287+
VarDecl *value = cast<VarDecl>(capture.getDecl());
4288+
auto existing = varCaptures.find(value);
4289+
if (existing != varCaptures.end()) {
4290+
existing->second = existing->second.mergeFlags(capture.getFlags());
4291+
} else {
4292+
varCaptures.insert(std::pair<VarDecl *, CapturedValue>(
4293+
value, capture));
4294+
}
42684295
}
42694296
};
42704297

@@ -4284,6 +4311,11 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
42844311
}
42854312

42864313
for (auto capture : captureInfo.getCaptures()) {
4314+
if (capture.isPackElement()) {
4315+
recordCapture(capture);
4316+
continue;
4317+
}
4318+
42874319
if (!capture.isLocalCapture())
42884320
continue;
42894321

@@ -4398,7 +4430,7 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
43984430
// If we've already captured the same value already, just merge
43994431
// flags.
44004432
if (selfCapture && selfCapture->getDecl() == capture.getDecl()) {
4401-
selfCapture = selfCapture->mergeFlags(capture);
4433+
selfCapture = selfCapture->mergeFlags(capture.getFlags());
44024434
continue;
44034435

44044436
// Otherwise, record the canonical self capture. It will appear
@@ -4492,7 +4524,10 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
44924524
collectConstantCaptures(fn);
44934525

44944526
SmallVector<CapturedValue, 4> resultingCaptures;
4495-
for (auto capturePair : captures) {
4527+
for (auto capturePair : varCaptures) {
4528+
resultingCaptures.push_back(capturePair.second);
4529+
}
4530+
for (auto capturePair : packElementCaptures) {
44964531
resultingCaptures.push_back(capturePair.second);
44974532
}
44984533

@@ -4511,7 +4546,7 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
45114546
resultingCaptures.push_back(*selfCapture);
45124547
}
45134548

4514-
// Cache the uniqued set of transitive captures.
4549+
// Cache the result.
45154550
CaptureInfo info(Context, resultingCaptures,
45164551
capturesDynamicSelf, capturesOpaqueValue,
45174552
capturesGenericParams, genericEnv.getArrayRef());

lib/SILGen/SILGenExpr.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1667,6 +1667,14 @@ RValueEmitter::visitPackExpansionExpr(PackExpansionExpr *E,
16671667

16681668
RValue
16691669
RValueEmitter::visitPackElementExpr(PackElementExpr *E, SGFContext C) {
1670+
// If this is a captured pack element reference, just emit the parameter value
1671+
// that was passed to the closure.
1672+
auto found = SGF.OpaqueValues.find(E);
1673+
if (found != SGF.OpaqueValues.end())
1674+
return RValue(SGF, E, SGF.manageOpaqueValue(found->second, E, C));
1675+
1676+
// Otherwise, we're going to project the address of an element from the pack
1677+
// itself.
16701678
FormalEvaluationScope scope(SGF);
16711679

16721680
LValue lv = SGF.emitLValue(E, SGFAccessKind::OwnedObjectRead);
@@ -5972,9 +5980,9 @@ RValue RValueEmitter::visitMakeTemporarilyEscapableExpr(
59725980
}
59735981

59745982
RValue RValueEmitter::visitOpaqueValueExpr(OpaqueValueExpr *E, SGFContext C) {
5975-
assert(SGF.OpaqueValues.count(E) && "Didn't bind OpaqueValueExpr");
5976-
auto value = SGF.OpaqueValues[E];
5977-
return RValue(SGF, E, SGF.manageOpaqueValue(value, E, C));
5983+
auto found = SGF.OpaqueValues.find(E);
5984+
assert(found != SGF.OpaqueValues.end());
5985+
return RValue(SGF, E, SGF.manageOpaqueValue(found->second, E, C));
59785986
}
59795987

59805988
RValue RValueEmitter::visitPropertyWrapperValuePlaceholderExpr(

lib/SILGen/SILGenFunction.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -569,10 +569,9 @@ void SILGenFunction::emitCaptures(SILLocation loc,
569569
continue;
570570
}
571571

572-
if (capture.isOpaqueValue()) {
573-
OpaqueValueExpr *opaqueValue = capture.getOpaqueValue();
572+
if (capture.isOpaqueValue() || capture.isPackElement()) {
574573
capturedArgs.push_back(
575-
emitRValueAsSingleValue(opaqueValue).ensurePlusOne(*this, loc));
574+
emitRValueAsSingleValue(capture.getExpr()).ensurePlusOne(*this, loc));
576575
continue;
577576
}
578577

lib/SILGen/SILGenFunction.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2185,9 +2185,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
21852185
emitOpenExistentialExprImpl(e, emitSubExpr);
21862186
}
21872187

2188-
/// Mapping from active opaque value expressions to their values.
2189-
llvm::SmallDenseMap<OpaqueValueExpr *, ManagedValue>
2190-
OpaqueValues;
2188+
/// Mapping from OpaqueValueExpr/PackElementExpr to their values.
2189+
llvm::SmallDenseMap<Expr *, ManagedValue> OpaqueValues;
21912190

21922191
/// A mapping from opaque value expressions to the open-existential
21932192
/// expression that determines them, used while lowering lvalues.

0 commit comments

Comments
 (0)