Skip to content

Commit 62a94f6

Browse files
committed
SILGen: Wean reabstraction thunk emission off getFunctionInputType()
Treat the top level of the parameter list specially, instead of looking at FunctionType::getInput(). There are three cases where we don't translate parameters 1-1: - Imploding the parameter list into a single value when reabstracting a function with the opaque abstraction pattern. This will go away once Swift 3 compatibility is fully removed. - Exploding the parameter list from a single value. This is the dual of the above. - Exploding the parameter list for an SE-0110 "tuple splat" conversion. This is the one case that will need to be supported on an on-going basis, but it is not too bad to handle directly.
1 parent c8a4939 commit 62a94f6

File tree

2 files changed

+134
-5
lines changed

2 files changed

+134
-5
lines changed

lib/SILGen/SILGenPoly.cpp

Lines changed: 96 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -892,11 +892,102 @@ namespace {
892892
AnyFunctionType::CanParamArrayRef inputSubstTypes,
893893
AbstractionPattern outputOrigFunctionType,
894894
AnyFunctionType::CanParamArrayRef outputSubstTypes) {
895+
// FIXME: Do we ever do opaque-to-opaque reabstractions?
896+
assert(!inputOrigFunctionType.isTypeParameter() ||
897+
!outputOrigFunctionType.isTypeParameter());
898+
899+
auto getSubstTupleType = [&](AnyFunctionType::CanParamArrayRef params) {
900+
return cast<TupleType>(
901+
AnyFunctionType::composeInput(SGF.getASTContext(),
902+
params, /*canonicalVararg=*/true)
903+
->getCanonicalType());
904+
};
905+
906+
auto getOrigParamTypes = [&](AbstractionPattern origFunctionType) {
907+
SmallVector<AbstractionPattern, 8> origTypes;
908+
for (unsigned i = 0, e = origFunctionType.getNumFunctionParams();
909+
i < e; ++i) {
910+
origTypes.push_back(origFunctionType.getFunctionParamType(i));
911+
}
912+
913+
return origTypes;
914+
};
915+
916+
if (inputOrigFunctionType.isTypeParameter() &&
917+
!outputOrigFunctionType.isTypeParameter() &&
918+
inputSubstTypes.size() != 1 &&
919+
!shouldExpandParams(inputSubstTypes)) {
920+
// The output is exploded and the input is not. Decompose an
921+
// input tuple and translate the elements.
922+
auto inputTupleType = getSubstTupleType(inputSubstTypes);
923+
auto outputTupleType = getSubstTupleType(outputSubstTypes);
924+
925+
auto outputOrigTypes = getOrigParamTypes(outputOrigFunctionType);
926+
auto outputOrigType = AbstractionPattern::getTuple(outputOrigTypes);
927+
928+
translateAndExplodeOutOf(AbstractionPattern::getOpaque(),
929+
inputTupleType,
930+
outputOrigType,
931+
outputTupleType,
932+
claimNextInput());
933+
return;
934+
}
935+
936+
if (!inputOrigFunctionType.isTypeParameter() &&
937+
outputOrigFunctionType.isTypeParameter() &&
938+
outputSubstTypes.size() != 1 &&
939+
!shouldExpandParams(outputSubstTypes)) {
940+
// The input is exploded and the output is not. Translate values
941+
// and store them to a result tuple in memory.
942+
auto inputTupleType = getSubstTupleType(inputSubstTypes);
943+
auto outputTupleType = getSubstTupleType(outputSubstTypes);
944+
945+
auto inputOrigTypes = getOrigParamTypes(inputOrigFunctionType);
946+
auto inputOrigType = AbstractionPattern::getTuple(inputOrigTypes);
947+
948+
auto outputTy = SGF.getSILType(claimNextOutputType());
949+
auto &outputTL = SGF.getTypeLowering(outputTy);
950+
if (SGF.silConv.useLoweredAddresses()) {
951+
auto temp = SGF.emitTemporary(Loc, outputTL);
952+
translateAndImplodeInto(
953+
inputOrigType,
954+
inputTupleType,
955+
AbstractionPattern::getOpaque(),
956+
outputTupleType,
957+
*temp);
958+
Outputs.push_back(temp->getManagedAddress());
959+
} else {
960+
auto result = translateAndImplodeIntoValue(
961+
inputOrigType,
962+
inputTupleType,
963+
AbstractionPattern::getOpaque(),
964+
outputTupleType,
965+
outputTL.getLoweredType());
966+
Outputs.push_back(result);
967+
}
968+
return;
969+
}
970+
971+
if (inputSubstTypes.size() == 1 &&
972+
outputSubstTypes.size() != 1) {
973+
// SE-0110 tuple splat. Turn the output into a single value of tuple
974+
// type, and translate.
975+
auto inputOrigType = inputOrigFunctionType.getFunctionParamType(0);
976+
auto inputSubstType = inputSubstTypes[0].getPlainType();
977+
978+
auto outputOrigTypes = getOrigParamTypes(outputOrigFunctionType);
979+
auto outputOrigType = AbstractionPattern::getTuple(outputOrigTypes);
980+
auto outputSubstType = getSubstTupleType(outputSubstTypes);
981+
982+
translate(inputOrigType, inputSubstType,
983+
outputOrigType, outputSubstType);
984+
return;
985+
}
986+
895987
assert(inputSubstTypes.size() == outputSubstTypes.size());
896988

897989
SmallVector<AbstractionPattern, 8> inputOrigTypes;
898990
SmallVector<AbstractionPattern, 8> outputOrigTypes;
899-
900991
for (auto i : indices(inputSubstTypes)) {
901992
inputOrigTypes.push_back(inputOrigFunctionType.getFunctionParamType(i));
902993
outputOrigTypes.push_back(outputOrigFunctionType.getFunctionParamType(i));
@@ -2854,10 +2945,10 @@ static void buildThunkBody(SILGenFunction &SGF, SILLocation loc,
28542945
// like a normal Int when calling the inner function).
28552946
SmallVector<ManagedValue, 8> args;
28562947
TranslateArguments(SGF, loc, params, args, argTypes)
2857-
.translate(outputOrigType.getFunctionInputType(),
2858-
outputSubstType.getInput(),
2859-
inputOrigType.getFunctionInputType(),
2860-
inputSubstType.getInput());
2948+
.translate(outputOrigType,
2949+
outputSubstType.getParams(),
2950+
inputOrigType,
2951+
inputSubstType.getParams());
28612952

28622953
SmallVector<SILValue, 8> argValues;
28632954

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
2+
// RUN: %target-swift-emit-silgen -module-name function_conversion -enable-sil-ownership -primary-file %s | %FileCheck %s
3+
4+
// Check SILGen against various FunctionConversionExprs emitted by Sema.
5+
6+
// SE-0110 allows 'tuple splat' in a few narrow cases. Make sure SILGen supports them.
7+
8+
func takesTwo(_: ((Int, Int)) -> ()) {}
9+
10+
func givesTwo(_ fn: (Any, Any) -> ()) {
11+
takesTwo(fn)
12+
}
13+
14+
// reabstraction thunk helper from @callee_guaranteed (@in_guaranteed Any, @in_guaranteed Any) -> () to @escaping @callee_guaranteed (@unowned Swift.Int, @unowned Swift.Int) -> ()
15+
// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$sypypIgnn_S2iIegyy_TR : $@convention(thin) (Int, Int, @noescape @callee_guaranteed (@in_guaranteed Any, @in_guaranteed Any) -> ()) -> ()
16+
17+
18+
func takesTwoGeneric<T>(_: (T) -> ()) -> T {}
19+
20+
func givesTwoGeneric(_ fn: (Int, Int) -> ()) {
21+
_ = takesTwoGeneric(fn)
22+
}
23+
24+
// reabstraction thunk helper from @callee_guaranteed (@unowned Swift.Int, @unowned Swift.Int) -> () to @escaping @callee_guaranteed (@in_guaranteed (Swift.Int, Swift.Int)) -> ()
25+
// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$sS2iIgyy_Si_SitIegn_TR : $@convention(thin) (@in_guaranteed (Int, Int), @noescape @callee_guaranteed (Int, Int) -> ()) -> ()
26+
27+
28+
// Use a silly trick to bind T := (Int, Int) here
29+
func givesTwoGenericAny(_ fn: (Any, Any) -> ()) -> (Int, Int) {
30+
return takesTwoGeneric(fn)
31+
}
32+
33+
func givesNoneGeneric(_ fn: () -> ()) {
34+
_ = takesTwoGeneric(fn)
35+
}
36+
37+
// reabstraction thunk helper from @callee_guaranteed () -> () to @escaping @callee_guaranteed (@in_guaranteed ()) -> ()
38+
// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$sIg_ytIegn_TR : $@convention(thin) (@in_guaranteed (), @noescape @callee_guaranteed () -> ()) -> ()

0 commit comments

Comments
 (0)