Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 8 additions & 12 deletions lib/SILGen/ResultPlan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,9 +529,13 @@ class PackTransformResultPlan final : public ResultPlan {
auto eltPatternTy =
PackAddr->getType().castTo<SILPackType>()
->getSILElementType(ComponentIndex);
auto result = SGF.createOpenedElementValueEnvironment(eltPatternTy);
auto openedEnv = result.first;
auto eltAddrTy = result.second;
auto substPatternType = FormalPackType.getElementType(ComponentIndex);

SILType eltAddrTy;
CanType substEltType;
auto openedEnv =
SGF.createOpenedElementValueEnvironment({eltPatternTy}, {&eltAddrTy},
{substPatternType}, {&substEltType});

// Loop over the pack, initializing each value with the appropriate
// element.
Expand Down Expand Up @@ -560,18 +564,10 @@ class PackTransformResultPlan final : public ResultPlan {
return eltMV;
}();

// Map the formal type into the generic environment.
auto substType = FormalPackType.getElementType(ComponentIndex);
substType = cast<PackExpansionType>(substType).getPatternType();
if (openedEnv) {
substType = openedEnv->mapContextualPackTypeIntoElementContext(
substType);
}

// Finish in the normal way for scalar results.
RValue rvalue =
ScalarResultPlan::finish(SGF, loc, eltMV, OrigPatternType,
substType, eltInit, Rep);
substEltType, eltInit, Rep);
assert(rvalue.isInContext()); (void) rvalue;
});
});
Expand Down
5 changes: 5 additions & 0 deletions lib/SILGen/SILGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -2697,6 +2697,11 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
GenericEnvironment *
createOpenedElementValueEnvironment(ArrayRef<SILType> packExpansionTys,
ArrayRef<SILType*> eltTys);
GenericEnvironment *
createOpenedElementValueEnvironment(ArrayRef<SILType> packExpansionTys,
ArrayRef<SILType*> eltTys,
ArrayRef<CanType> formalPackExpansionTys,
ArrayRef<CanType*> formalEltTys);

/// Emit a dynamic loop over a single pack-expansion component of a pack.
///
Expand Down
75 changes: 47 additions & 28 deletions lib/SILGen/SILGenPack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,44 +452,63 @@ GenericEnvironment *
SILGenFunction::createOpenedElementValueEnvironment(
ArrayRef<SILType> expansionTys,
ArrayRef<SILType*> eltTys) {
// The element-types output array should be the same size as the
// expansion-types input array. We don't currently have a reason
// to allow them to be empty --- we never do this with a dynamic
// set of types --- but maybe it's justifiable.
return createOpenedElementValueEnvironment(expansionTys, eltTys, {}, {});
}


GenericEnvironment *
SILGenFunction::createOpenedElementValueEnvironment(
ArrayRef<SILType> expansionTys,
ArrayRef<SILType*> eltTys,
ArrayRef<CanType> formalExpansionTypes,
ArrayRef<CanType*> formalEltTypes) {
// The element-types output arrays should be the same size as their
// corresponding expansion-types input arrays.
assert(expansionTys.size() == eltTys.size());
assert(!expansionTys.empty());
if (expansionTys.empty()) return nullptr;
assert(formalExpansionTypes.size() == formalEltTypes.size());

auto countArchetype = cast<PackArchetypeType>(
expansionTys[0].castTo<PackExpansionType>().getCountType());
assert(!expansionTys.empty() || !formalExpansionTypes.empty());
auto countArchetype =
cast<PackArchetypeType>(
(expansionTys.empty()
? cast<PackExpansionType>(formalExpansionTypes[0])
: expansionTys[0].castTo<PackExpansionType>()).getCountType());

GenericEnvironment *env = nullptr;
for (auto i : indices(expansionTys)) {
auto exp = expansionTys[i].castTo<PackExpansionType>();
assert((i == 0 ||
countArchetype->getReducedShape() ==
cast<PackArchetypeType>(exp.getCountType())->getReducedShape())
auto processExpansion = [&](CanPackExpansionType expansion) -> CanType {
assert(countArchetype->getReducedShape() ==
cast<PackArchetypeType>(expansion.getCountType())->getReducedShape()
&& "expansions are over packs with different shapes");

// The lowered element type is the lowered pattern type, if that's
// invariant to expansion, or else the expansion mapping of that in
// the opened-element environment.
auto loweredPatternTy = exp.getPatternType();
auto loweredEltTy = loweredPatternTy;
if (!isPatternInvariantToExpansion(loweredPatternTy, countArchetype)) {
// Lazily create the opened-element environment if we find a
// pattern type that's not invariant to expansion.
if (!env) {
auto context = OpenedElementContext::
createForContextualExpansion(SGM.getASTContext(), exp);
env = context.environment;
}
loweredEltTy =
env->mapContextualPackTypeIntoElementContext(loweredPatternTy);
// The element type is the pattern type, if that's invariant to
// expansion, or else the expansion mapping of that in the
// opened-element environment.
auto patternType = expansion.getPatternType();
if (isPatternInvariantToExpansion(patternType, countArchetype))
return patternType;

// Lazily create the opened-element environment if we find a
// pattern type that's not invariant to expansion.
if (!env) {
auto context = OpenedElementContext::
createForContextualExpansion(SGM.getASTContext(), expansion);
env = context.environment;
}
return env->mapContextualPackTypeIntoElementContext(patternType);
};

for (auto i : indices(expansionTys)) {
auto exp = expansionTys[i].castTo<PackExpansionType>();
auto loweredEltTy = processExpansion(exp);
*eltTys[i] = SILType::getPrimitiveAddressType(loweredEltTy);
}

for (auto i : indices(formalExpansionTypes)) {
auto exp = cast<PackExpansionType>(formalExpansionTypes[i]);
auto eltType = processExpansion(exp);
*formalEltTypes[i] = eltType;
}

return env;
}

Expand Down
Loading