Skip to content

Commit 4f5a5f5

Browse files
committed
[SILGen] changes for flattened functions
Reabstraction thunks are now used for this flattening/uncurrying as well. First the self parameter is applied, the variables are updated not to include this first parameter and then the "normal" reabstraction takes place.
1 parent 1022d8c commit 4f5a5f5

File tree

4 files changed

+86
-27
lines changed

4 files changed

+86
-27
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,13 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
12321232
}
12331233

12341234
void visitFunctionConversionExpr(FunctionConversionExpr *e) {
1235+
// If this is a flattening function conversion, emit the expression
1236+
// directly.
1237+
if (e->isFlattening()) {
1238+
visitExpr(e);
1239+
return;
1240+
}
1241+
12351242
// FIXME: Check whether this function conversion requires us to build a
12361243
// thunk.
12371244
visit(e->getSubExpr());

lib/SILGen/SILGenExpr.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1257,7 +1257,8 @@ RValue RValueEmitter::visitFunctionConversionExpr(FunctionConversionExpr *e,
12571257
result = convertFunctionRepresentation(SGF, e, result, srcRepTy, srcTy);
12581258

12591259
if (srcTy != destTy)
1260-
result = SGF.emitTransformedValue(e, result, srcTy, destTy);
1260+
result =
1261+
SGF.emitTransformedValue(e, result, srcTy, destTy, e->isFlattening());
12611262

12621263
if (destTy != destRepTy)
12631264
result = convertFunctionRepresentation(SGF, e, result, destTy, destRepTy);

lib/SILGen/SILGenFunction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1460,6 +1460,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
14601460
ManagedValue emitTransformedValue(SILLocation loc, ManagedValue input,
14611461
CanType inputType,
14621462
CanType outputType,
1463+
bool isFlattening = false,
14631464
SGFContext ctx = SGFContext());
14641465

14651466
/// Most general form of the above.
@@ -1468,6 +1469,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
14681469
CanType inputSubstType,
14691470
AbstractionPattern outputOrigType,
14701471
CanType outputSubstType,
1472+
bool isFlattening = false,
14711473
SGFContext ctx = SGFContext());
14721474
RValue emitTransformedValue(SILLocation loc, RValue &&input,
14731475
AbstractionPattern inputOrigType,

lib/SILGen/SILGenPoly.cpp

Lines changed: 75 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,11 @@ namespace {
112112
private:
113113
SILGenFunction &SGF;
114114
SILLocation Loc;
115+
bool Flattening;
115116

116117
public:
117-
Transform(SILGenFunction &SGF, SILLocation loc) : SGF(SGF), Loc(loc) {}
118+
Transform(SILGenFunction &SGF, SILLocation loc, bool flattening = false)
119+
: SGF(SGF), Loc(loc), Flattening(flattening) {}
118120
virtual ~Transform() = default;
119121

120122
/// Transform an arbitrary value.
@@ -1252,7 +1254,7 @@ namespace {
12521254
return SGF.emitTransformedValue(Loc, input,
12531255
inputOrigType, inputSubstType,
12541256
outputOrigType, outputSubstType,
1255-
context);
1257+
/*isFlattening=*/false, context);
12561258
}
12571259

12581260
/// Force the given result into the given initialization.
@@ -2177,7 +2179,7 @@ void ResultPlanner::execute(ArrayRef<SILValue> innerDirectResults,
21772179
Gen.emitTransformedValue(Loc, innerResult,
21782180
op.InnerOrigType, op.InnerSubstType,
21792181
op.OuterOrigType, op.OuterSubstType,
2180-
outerResultCtxt);
2182+
/*isFlattening=*/false, outerResultCtxt);
21812183

21822184
// If the outer is indirect, force it into the context.
21832185
if (outerIsIndirect) {
@@ -2269,26 +2271,72 @@ void ResultPlanner::execute(ArrayRef<SILValue> innerDirectResults,
22692271
/// \param inputSubstType Formal AST type of function value being thunked
22702272
/// \param outputOrigType Abstraction pattern of the thunk
22712273
/// \param outputSubstType Formal AST type of the thunk
2272-
static void buildThunkBody(SILGenFunction &gen, SILLocation loc,
2273-
AbstractionPattern inputOrigType,
2274-
CanAnyFunctionType inputSubstType,
2275-
AbstractionPattern outputOrigType,
2276-
CanAnyFunctionType outputSubstType) {
2274+
static void buildThunkBody(
2275+
SILGenFunction &gen, SILLocation loc, bool isFlattening,
2276+
AbstractionPattern inputOrigType, CanAnyFunctionType inputSubstType,
2277+
AbstractionPattern outputOrigType, CanAnyFunctionType outputSubstType) {
22772278
PrettyStackTraceSILFunction stackTrace("emitting reabstraction thunk in",
22782279
&gen.F);
22792280
auto thunkType = gen.F.getLoweredFunctionType();
22802281

22812282
FullExpr scope(gen.Cleanups, CleanupLocation::get(loc));
22822283

2283-
SmallVector<ManagedValue, 8> params;
2284+
SmallVector<ManagedValue, 8> paramsBuffer;
22842285
// TODO: Could accept +0 arguments here when forwardFunctionArguments/
22852286
// emitApply can.
2286-
gen.collectThunkParams(loc, params, /*allowPlusZero*/ false);
2287-
2288-
ManagedValue fnValue = params.pop_back_val();
2287+
gen.collectThunkParams(loc, paramsBuffer, /*allowPlusZero*/ false);
2288+
ManagedValue fnValue = paramsBuffer.pop_back_val();
22892289
auto fnType = fnValue.getType().castTo<SILFunctionType>();
22902290
assert(!fnType->isPolymorphic());
22912291
auto argTypes = fnType->getParameters();
2292+
2293+
ArrayRef<ManagedValue> params(paramsBuffer);
2294+
if (isFlattening) {
2295+
// Flatten an instance function type.
2296+
assert(
2297+
inputSubstType->getCurryLevel() - outputSubstType->getCurryLevel() == 1 &&
2298+
"Invalid (un)currying");
2299+
2300+
SmallVector<SILValue, 1> selfArg;
2301+
forwardFunctionArguments(gen, loc, fnType, params.front(), selfArg);
2302+
auto inner = gen.emitApplyWithRethrow(loc, fnValue.forward(gen),
2303+
/*substFnType*/ fnValue.getType(),
2304+
/*substitutions*/ {}, selfArg);
2305+
2306+
// For the next steps update the variables by dropping the already applied
2307+
// first parameter (`self`)
2308+
params = params.slice(1);
2309+
fnValue = ManagedValue::forUnmanaged(inner);
2310+
fnType = fnValue.getType().castTo<SILFunctionType>();
2311+
argTypes = fnType->getParameters();
2312+
inputOrigType = inputOrigType.getFunctionResultType();
2313+
inputSubstType = cast<AnyFunctionType>(inputSubstType.getResult());
2314+
2315+
Type newOrigInput, newSubstInput;
2316+
auto origFunction = cast<AnyFunctionType>(outputOrigType.getType());
2317+
if (auto origInput = dyn_cast<TupleType>(origFunction.getInput())) {
2318+
auto substInput = cast<TupleType>(outputSubstType.getInput());
2319+
assert(origInput->getNumElements() == substInput->getNumElements() &&
2320+
"invalid premise");
2321+
newOrigInput = TupleType::get(origInput->getElements().slice(1),
2322+
gen.getASTContext());
2323+
newSubstInput = TupleType::get(substInput->getElements().slice(1),
2324+
gen.getASTContext());
2325+
} else {
2326+
// In this case `self` was the only parameter, which leaves us with an
2327+
// application of `Void`
2328+
assert(!dyn_cast<TupleType>(outputSubstType.getInput()) &&
2329+
"invalid premise");
2330+
newOrigInput = newSubstInput = TupleType::getEmpty(gen.getASTContext());
2331+
}
2332+
2333+
outputOrigType = AbstractionPattern(CanFunctionType::get(
2334+
newOrigInput->getCanonicalType(), origFunction.getResult(),
2335+
origFunction->getExtInfo()));
2336+
outputSubstType = CanFunctionType::get(newSubstInput->getCanonicalType(),
2337+
outputSubstType.getResult(),
2338+
outputSubstType->getExtInfo());
2339+
}
22922340

22932341
// Translate the argument values. Function parameters are
22942342
// contravariant: we want to switch the direction of transformation
@@ -2419,14 +2467,12 @@ CanSILFunctionType SILGenFunction::buildThunkType(
24192467
}
24202468

24212469
/// Create a reabstraction thunk.
2422-
static ManagedValue createThunk(SILGenFunction &gen,
2423-
SILLocation loc,
2424-
ManagedValue fn,
2425-
AbstractionPattern inputOrigType,
2426-
CanAnyFunctionType inputSubstType,
2427-
AbstractionPattern outputOrigType,
2428-
CanAnyFunctionType outputSubstType,
2429-
const TypeLowering &expectedTL) {
2470+
static ManagedValue createThunk(
2471+
SILGenFunction &gen, SILLocation loc, ManagedValue fn,
2472+
AbstractionPattern inputOrigType, CanAnyFunctionType inputSubstType,
2473+
AbstractionPattern outputOrigType, CanAnyFunctionType outputSubstType,
2474+
const TypeLowering &expectedTL, bool isFlattening) {
2475+
24302476
auto expectedType = expectedTL.getLoweredType().castTo<SILFunctionType>();
24312477

24322478
// We can't do bridging here.
@@ -2452,7 +2498,7 @@ static ManagedValue createThunk(SILGenFunction &gen,
24522498
thunk->setContextGenericParams(gen.F.getContextGenericParams());
24532499
SILGenFunction thunkSGF(gen.SGM, *thunk);
24542500
auto loc = RegularLocation::getAutoGeneratedLocation();
2455-
buildThunkBody(thunkSGF, loc,
2501+
buildThunkBody(thunkSGF, loc, isFlattening,
24562502
inputOrigType, inputSubstType,
24572503
outputOrigType, outputSubstType);
24582504
}
@@ -2494,7 +2540,7 @@ ManagedValue Transform::transformFunction(ManagedValue fn,
24942540
return createThunk(SGF, Loc, fn,
24952541
inputOrigType, inputSubstType,
24962542
outputOrigType, outputSubstType,
2497-
expectedTL);
2543+
expectedTL, Flattening);
24982544
}
24992545

25002546
// We do not, conversion is trivial.
@@ -2535,7 +2581,7 @@ SILGenFunction::emitOrigToSubstValue(SILLocation loc, ManagedValue v,
25352581
return emitTransformedValue(loc, v,
25362582
origType, substType,
25372583
AbstractionPattern(substType), substType,
2538-
ctxt);
2584+
/*isFlattening=*/false, ctxt);
25392585
}
25402586

25412587
/// Given a value with the abstraction patterns of the original formal
@@ -2561,7 +2607,7 @@ SILGenFunction::emitSubstToOrigValue(SILLocation loc, ManagedValue v,
25612607
return emitTransformedValue(loc, v,
25622608
AbstractionPattern(substType), substType,
25632609
origType, substType,
2564-
ctxt);
2610+
/*isFlattening=*/false, ctxt);
25652611
}
25662612

25672613
/// Given a value with the abstraction patterns of the substituted
@@ -2594,10 +2640,12 @@ ManagedValue
25942640
SILGenFunction::emitTransformedValue(SILLocation loc, ManagedValue v,
25952641
CanType inputType,
25962642
CanType outputType,
2643+
bool isFlattening,
25972644
SGFContext ctxt) {
25982645
return emitTransformedValue(loc, v,
25992646
AbstractionPattern(inputType), inputType,
2600-
AbstractionPattern(outputType), outputType);
2647+
AbstractionPattern(outputType), outputType,
2648+
isFlattening, ctxt);
26012649
}
26022650

26032651
ManagedValue
@@ -2606,8 +2654,9 @@ SILGenFunction::emitTransformedValue(SILLocation loc, ManagedValue v,
26062654
CanType inputSubstType,
26072655
AbstractionPattern outputOrigType,
26082656
CanType outputSubstType,
2657+
bool isFlattening,
26092658
SGFContext ctxt) {
2610-
return Transform(*this, loc).transform(v,
2659+
return Transform(*this, loc, isFlattening).transform(v,
26112660
inputOrigType,
26122661
inputSubstType,
26132662
outputOrigType,

0 commit comments

Comments
 (0)