Skip to content

Commit 4499e3d

Browse files
committed
[NFC] Introduce new APIs for traversing orig/subst parameters in parallel
1 parent d524c7d commit 4499e3d

File tree

4 files changed

+124
-53
lines changed

4 files changed

+124
-53
lines changed

include/swift/SIL/AbstractionPattern.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,6 +1488,30 @@ class AbstractionPattern {
14881488
/// parameters in the pattern.
14891489
unsigned getNumFunctionParams() const;
14901490

1491+
/// Perform a parallel visitation of the parameters of a function.
1492+
///
1493+
/// If this is a function pattern, calls handleScalar or
1494+
/// handleExpansion as appropriate for each parameter of the
1495+
/// original function, in order.
1496+
///
1497+
/// If this is not a function pattern, calls handleScalar for each
1498+
/// parameter of the substituted function type. Functions with
1499+
/// pack expansions cannot be abstracted legally this way.
1500+
void forEachFunctionParam(AnyFunctionType::CanParamArrayRef substParams,
1501+
bool ignoreFinalParam,
1502+
llvm::function_ref<void(unsigned origParamIndex,
1503+
unsigned substParamIndex,
1504+
ParameterTypeFlags origFlags,
1505+
AbstractionPattern origParamType,
1506+
AnyFunctionType::CanParam substParam)>
1507+
handleScalar,
1508+
llvm::function_ref<void(unsigned origParamIndex,
1509+
unsigned substParamIndex,
1510+
ParameterTypeFlags origFlags,
1511+
AbstractionPattern origExpansionType,
1512+
AnyFunctionType::CanParamArrayRef substParams)>
1513+
handleExpansion) const;
1514+
14911515
/// Given that the value being abstracted is optional, return the
14921516
/// abstraction pattern for its object type.
14931517
AbstractionPattern getOptionalObjectType() const;

lib/SIL/IR/AbstractionPattern.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,6 +1221,56 @@ unsigned AbstractionPattern::getNumFunctionParams() const {
12211221
return cast<AnyFunctionType>(getType()).getParams().size();
12221222
}
12231223

1224+
void AbstractionPattern::
1225+
forEachFunctionParam(AnyFunctionType::CanParamArrayRef substParams,
1226+
bool ignoreFinalParam,
1227+
llvm::function_ref<void(unsigned origParamIndex,
1228+
unsigned substParamIndex,
1229+
ParameterTypeFlags origFlags,
1230+
AbstractionPattern origParamType,
1231+
AnyFunctionType::CanParam substParam)>
1232+
handleScalar,
1233+
llvm::function_ref<void(unsigned origParamIndex,
1234+
unsigned substParamIndex,
1235+
ParameterTypeFlags origFlags,
1236+
AbstractionPattern origExpansionType,
1237+
AnyFunctionType::CanParamArrayRef substParams)>
1238+
handleExpansion) const {
1239+
// Honor ignoreFinalParam for the substituted parameters on all paths.
1240+
if (ignoreFinalParam) substParams = substParams.drop_back();
1241+
1242+
// If this isn't a function type, use the substituted type.
1243+
if (isTypeParameterOrOpaqueArchetype()) {
1244+
for (auto substParamIndex : indices(substParams)) {
1245+
handleScalar(substParamIndex, substParamIndex,
1246+
substParams[substParamIndex].getParameterFlags(),
1247+
*this, substParams[substParamIndex]);
1248+
}
1249+
return;
1250+
}
1251+
1252+
size_t numOrigParams = getNumFunctionParams();
1253+
if (ignoreFinalParam) numOrigParams--;
1254+
1255+
size_t substParamIndex = 0;
1256+
for (auto origParamIndex : range(numOrigParams)) {
1257+
auto origParamType = getFunctionParamType(origParamIndex);
1258+
if (origParamType.isPackExpansion()) {
1259+
unsigned numComponents = origParamType.getNumPackExpandedComponents();
1260+
handleExpansion(origParamIndex, substParamIndex,
1261+
getFunctionParamFlags(origParamIndex), origParamType,
1262+
substParams.slice(substParamIndex, numComponents));
1263+
substParamIndex += numComponents;
1264+
} else {
1265+
handleScalar(origParamIndex, substParamIndex,
1266+
getFunctionParamFlags(origParamIndex), origParamType,
1267+
substParams[substParamIndex]);
1268+
substParamIndex++;
1269+
}
1270+
}
1271+
assert(substParamIndex == substParams.size());
1272+
}
1273+
12241274
static CanType getOptionalObjectType(CanType type) {
12251275
auto objectType = type.getOptionalObjectType();
12261276
assert(objectType && "type was not optional");

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 36 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1525,20 +1525,26 @@ class DestructureInputs {
15251525
origType.isTypeParameter()
15261526
? params.size()
15271527
: origType.getNumFunctionParams();
1528-
unsigned nextParamIndex = 0;
15291528

1529+
// If we're importing a freestanding foreign function as a member
1530+
// function, the formal types (subst and orig) will conspire to
1531+
// pretend that there is a self parameter in the position Swift
1532+
// expects it: the end of the parameter lists. In the lowered type,
1533+
// we need to put this in its proper place, which for static methods
1534+
// generally means dropping it entirely.
1535+
bool hasForeignSelf = Foreign.self.isImportAsMember();
1536+
1537+
// Is there a self parameter in the formal parameter lists?
15301538
bool hasSelf =
1531-
(extInfoBuilder.hasSelfParam() || Foreign.self.isImportAsMember());
1532-
unsigned numOrigNonSelfParams =
1533-
(hasSelf ? numOrigParams - 1 : numOrigParams);
1539+
(extInfoBuilder.hasSelfParam() || hasForeignSelf);
15341540

15351541
TopLevelOrigType = origType;
15361542
// If we have a foreign self parameter, set up the ForeignSelfInfo
15371543
// for the use of maybeAddForeignParameters.
15381544
if (Foreign.self.isInstance()) {
15391545
assert(hasSelf && numOrigParams > 0);
15401546
ForeignSelf = ForeignSelfInfo{
1541-
origType.getFunctionParamType(numOrigNonSelfParams),
1547+
origType.getFunctionParamType(numOrigParams - 1),
15421548
params.back()
15431549
};
15441550
}
@@ -1549,55 +1555,47 @@ class DestructureInputs {
15491555
maybeAddForeignParameters();
15501556

15511557
// Process all the non-self parameters.
1552-
for (unsigned i = 0; i != numOrigNonSelfParams; ++i) {
1553-
auto origParamType = origType.getFunctionParamType(i);
1554-
1558+
origType.forEachFunctionParam(params, hasSelf,
1559+
[&](unsigned origParamIndex, unsigned substParamIndex,
1560+
ParameterTypeFlags origFlags,
1561+
AbstractionPattern origParamType,
1562+
AnyFunctionType::CanParam substParam) {
15551563
// If the parameter is not a pack expansion, just pull off the
15561564
// next parameter and destructure it in parallel with the abstraction
15571565
// pattern for the type.
1558-
if (!origParamType.isPackExpansion()) {
1559-
visit(origParamType, params[nextParamIndex++], /*forSelf*/false);
1560-
continue;
1561-
}
1562-
1566+
visit(origParamType, substParam, /*forSelf*/false);
1567+
}, [&](unsigned origParamIndex, unsigned substParamIndex,
1568+
ParameterTypeFlags origFlags,
1569+
AbstractionPattern origExpansionType,
1570+
AnyFunctionType::CanParamArrayRef substParams) {
15631571
// Otherwise, collect the substituted components into a pack.
1564-
1565-
// If the parameter *is* a pack expansion, it must not be an
1566-
// opaque pattern, so we can safely call this.
1567-
auto origFlags = origType.getFunctionParamFlags(i);
1568-
15691572
SmallVector<CanType, 8> packElts;
1570-
origParamType.forEachPackExpandedComponent(
1571-
[&](AbstractionPattern origParamComponent) {
1572-
auto substParam = params[nextParamIndex++];
1573+
for (auto substParam : substParams) {
15731574
auto substParamType = substParam.getParameterType();
1575+
auto origParamType =
1576+
origExpansionType.getPackExpansionComponentType(substParamType);
1577+
auto loweredParamTy = TC.getLoweredRValueType(expansion,
1578+
origParamType, substParamType);
1579+
packElts.push_back(loweredParamTy);
1580+
}
15741581

1575-
auto substTy = TC.getLoweredType(origParamType, substParamType,
1576-
expansion);
1577-
packElts.push_back(substTy.getASTType());
1578-
});
1579-
1580-
bool indirect = origParamType.arePackElementsPassedIndirectly(TC);
1582+
bool indirect = origExpansionType.arePackElementsPassedIndirectly(TC);
15811583
SILPackType::ExtInfo extInfo(/*address*/ indirect);
15821584
auto packTy = SILPackType::get(TC.Context, extInfo, packElts);
15831585

15841586
addPackParameter(packTy, origFlags.getValueOwnership(),
15851587
origFlags.isNoDerivative());
1586-
}
1588+
});
15871589

1588-
// Process the self parameter.
1589-
if (hasSelf && Foreign.self.isImportAsMember()) {
1590-
// Drop the formal foreign self parameter at this point if we
1591-
// set it up earlier.
1592-
nextParamIndex++;
1593-
} else if (hasSelf) {
1594-
auto origParamType = origType.getFunctionParamType(numOrigNonSelfParams);
1595-
auto substParam = params[nextParamIndex++];
1590+
// Process the self parameter. But if we have a formal foreign self
1591+
// parameter, we should have processed it earlier in a call to
1592+
// maybeAddForeignParameters().
1593+
if (hasSelf && !hasForeignSelf) {
1594+
auto origParamType = origType.getFunctionParamType(numOrigParams - 1);
1595+
auto substParam = params.back();
15961596
visit(origParamType, substParam, /*forSelf*/true);
15971597
}
15981598

1599-
assert(nextParamIndex == params.size());
1600-
16011599
TopLevelOrigType = AbstractionPattern::getInvalid();
16021600
ForeignSelf = None;
16031601
}

lib/SILGen/SILGenApply.cpp

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3239,13 +3239,13 @@ class ArgEmitter {
32393239

32403240
// Otherwise we need to emit a pack argument.
32413241
} else {
3242-
auto origPackEltPatterns =
3243-
origFormalParamType.getPackExpandedComponents();
3242+
auto numComponents =
3243+
origFormalParamType.getNumPackExpandedComponents();
32443244

32453245
auto argSourcesSlice =
3246-
argSources.slice(nextArgSourceIndex, origPackEltPatterns.size());
3247-
emitPackArg(argSourcesSlice, origPackEltPatterns);
3248-
nextArgSourceIndex += origPackEltPatterns.size();
3246+
argSources.slice(nextArgSourceIndex, numComponents);
3247+
emitPackArg(argSourcesSlice, origFormalParamType);
3248+
nextArgSourceIndex += numComponents;
32493249
}
32503250
}
32513251

@@ -3690,7 +3690,7 @@ class ArgEmitter {
36903690
}
36913691

36923692
void emitPackArg(MutableArrayRef<ArgumentSource> args,
3693-
ArrayRef<AbstractionPattern> origFormalTypes) {
3693+
AbstractionPattern origExpansionType) {
36943694
// Adjust for the foreign error or async argument if necessary.
36953695
maybeEmitForeignArgument();
36963696

@@ -3722,7 +3722,7 @@ class ArgEmitter {
37223722
auto formalPackType = getFormalPackType(args);
37233723

37243724
bool consumed = param.getConvention() == ParameterConvention::Pack_Owned;
3725-
emitIndirectIntoPack(args, origFormalTypes, pack, formalPackType,
3725+
emitIndirectIntoPack(args, origExpansionType, pack, formalPackType,
37263726
consumed);
37273727
}
37283728

@@ -3735,12 +3735,10 @@ class ArgEmitter {
37353735
}
37363736

37373737
void emitIndirectIntoPack(MutableArrayRef<ArgumentSource> args,
3738-
ArrayRef<AbstractionPattern> origFormalTypes,
3738+
AbstractionPattern origExpansionType,
37393739
SILValue packAddr,
37403740
CanPackType formalPackType,
37413741
bool consumed) {
3742-
assert(args.size() == origFormalTypes.size());
3743-
37443742
auto packTy = packAddr->getType().castTo<SILPackType>();
37453743
assert(packTy->getNumElements() == args.size() &&
37463744
"wrong pack shape for arguments");
@@ -3749,11 +3747,14 @@ class ArgEmitter {
37493747

37503748
for (auto i : indices(args)) {
37513749
ArgumentSource &&arg = std::move(args[i]);
3752-
const AbstractionPattern &origFormalType = origFormalTypes[i];
37533750
auto expectedEltTy = packTy->getSILElementType(i);
37543751

3752+
bool isPackExpansion = expectedEltTy.is<PackExpansionType>();
3753+
AbstractionPattern origFormalType =
3754+
origExpansionType.getPackExpansionComponentType(isPackExpansion);
3755+
37553756
auto cleanup = CleanupHandle::invalid();
3756-
if (origFormalType.isPackExpansion()) {
3757+
if (isPackExpansion) {
37573758
cleanup =
37583759
emitPackExpansionIntoPack(std::move(arg), origFormalType,
37593760
expectedEltTy, consumed,
@@ -4400,9 +4401,7 @@ struct ParamLowering {
44004401
auto origParamType = origFormalType.getFunctionParamType(i);
44014402
if (origParamType.isPackExpansion()) {
44024403
count++;
4403-
origParamType.forEachPackExpandedComponent([&](AbstractionPattern) {
4404-
nextSubstParamIndex++;
4405-
});
4404+
nextSubstParamIndex += origParamType.getNumPackExpandedComponents();
44064405
} else {
44074406
auto substParam = substParams[nextSubstParamIndex++];
44084407
if (substParam.isInOut()) {

0 commit comments

Comments
 (0)