SILGen: Emit literal closures at the abstraction level of their context.

Literal closures are only ever directly referenced in the context of the expression they're written in,
so it's wasteful to emit them at their fully-substituted calling convention and then reabstract them if
they're passed directly to a generic function. Avoid this by saving the abstraction pattern of the context
before emitting the closure, and then lowering its main entry point's calling convention at that
level of abstraction. Generalize some of the prolog/epilog code to handle converting arguments and returns
to the correct representation for a different abstraction level.
This commit is contained in:
Joe Groff
2021-08-07 14:46:05 -07:00
parent c0350229f7
commit 309500d4bf
33 changed files with 524 additions and 156 deletions

View File

@@ -18,16 +18,17 @@
using namespace swift;
using namespace Lowering;
void SILGenFunction::prepareEpilog(bool hasDirectResults, bool isThrowing,
void SILGenFunction::prepareEpilog(Optional<Type> directResultType,
bool isThrowing,
CleanupLocation CleanupL) {
auto *epilogBB = createBasicBlock();
// If we have any direct results, receive them via BB arguments.
if (hasDirectResults) {
if (directResultType) {
auto fnConv = F.getConventions();
// Set NeedsReturn for indirect or direct results. This ensures that SILGen
// emits unreachable if there is no source level return.
NeedsReturn = (fnConv.funcTy->getNumResults() != 0);
NeedsReturn = !(*directResultType)->isEqual(TupleType::getEmpty(getASTContext()));
for (auto directResult : fnConv.getDirectSILResults()) {
SILType resultType = F.getLoweredType(F.mapTypeIntoContext(
fnConv.getSILType(directResult, getTypeExpansionContext())));