Skip to content

Commit 957dc8e

Browse files
committed
[Constant Evaluator] Make symbolic closures, which are representations
of closure literals in the constant evaluator, store the substitution map that was in the constant evaluator state when the closure creation site (partial_apply or thin_to_thick_function) that created the symbolic closure was evaluated. A substitution map is a mapping from generic type parameters to types. This map is updated and maintained by the constant evaluator as it evaluates function calls. At a partial-application site, the substitution map captures the mapping from the types of the captured arguments (which could be generic types) to the types of the symbolic value they represent (which has to be concrete types). The substitution map would be necessary to fold the symbolic closure into SIL code that constructs the closure it represents.
1 parent 1a81074 commit 957dc8e

File tree

3 files changed

+38
-9
lines changed

3 files changed

+38
-9
lines changed

include/swift/SIL/SILConstants.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818
#ifndef SWIFT_SIL_CONSTANTS_H
1919
#define SWIFT_SIL_CONSTANTS_H
2020

21+
#include "swift/AST/SubstitutionMap.h"
2122
#include "swift/SIL/SILValue.h"
2223
#include "llvm/Support/CommandLine.h"
2324

24-
2525
namespace swift {
2626
class SingleValueInstruction;
2727
class SILValue;
@@ -572,6 +572,7 @@ class SymbolicValue {
572572
static SymbolicValue makeClosure(
573573
SILFunction *target,
574574
ArrayRef<std::pair<SILValue, Optional<SymbolicValue>>> capturedArguments,
575+
SubstitutionMap substMap, SILType closureType,
575576
SymbolicValueAllocator &allocator);
576577

577578
SymbolicClosure *getClosure() const {
@@ -680,19 +681,29 @@ struct SymbolicClosure final
680681
// The number of SIL values captured by the closure.
681682
unsigned numCaptures;
682683

683-
// True iff there exists captured arguments whose constant value is not known.
684+
// True iff there exists a captured argument whose constant value is not
685+
// known.
684686
bool hasNonConstantCaptures = true;
685687

688+
// A substitution map that partially maps the generic paramters of the
689+
// applied function to the generic arguments of passed to the call.
690+
SubstitutionMap substitutionMap;
691+
692+
SILType closureType;
693+
686694
SymbolicClosure() = delete;
687695
SymbolicClosure(const SymbolicClosure &) = delete;
688696
SymbolicClosure(SILFunction *callee, unsigned numArguments,
697+
SubstitutionMap substMap, SILType closureType,
689698
bool nonConstantCaptures)
690699
: target(callee), numCaptures(numArguments),
691-
hasNonConstantCaptures(nonConstantCaptures) {}
700+
hasNonConstantCaptures(nonConstantCaptures), substitutionMap(substMap),
701+
closureType(closureType) {}
692702

693703
public:
694704
static SymbolicClosure *create(SILFunction *callee,
695705
ArrayRef<SymbolicClosureArgument> args,
706+
SubstitutionMap substMap, SILType closureType,
696707
SymbolicValueAllocator &allocator);
697708

698709
ArrayRef<SymbolicClosureArgument> getCaptures() const {
@@ -707,6 +718,10 @@ struct SymbolicClosure final
707718
SILFunction *getTarget() {
708719
return target;
709720
}
721+
722+
SILType getClosureType() { return closureType; }
723+
724+
SubstitutionMap getCallSubstitutionMap() { return substitutionMap; }
710725
};
711726

712727
} // end namespace swift

lib/SIL/SILConstants.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,9 @@ SymbolicValue::cloneInto(SymbolicValueAllocator &allocator) const {
247247
case RK_Closure: {
248248
SymbolicClosure *clo = getClosure();
249249
ArrayRef<SymbolicClosureArgument> closureArgs = clo->getCaptures();
250-
return SymbolicValue::makeClosure(clo->getTarget(), closureArgs, allocator);
250+
return SymbolicValue::makeClosure(clo->getTarget(), closureArgs,
251+
clo->getCallSubstitutionMap(),
252+
clo->getClosureType(), allocator);
251253
}
252254
}
253255
llvm_unreachable("covered switch");
@@ -744,8 +746,11 @@ Type SymbolicValue::getArrayType() const {
744746

745747
SymbolicValue SymbolicValue::makeClosure(SILFunction *target,
746748
ArrayRef<SymbolicClosureArgument> args,
749+
SubstitutionMap substMap,
750+
SILType closureType,
747751
SymbolicValueAllocator &allocator) {
748-
auto clo = SymbolicClosure::create(target, args, allocator);
752+
auto clo =
753+
SymbolicClosure::create(target, args, substMap, closureType, allocator);
749754
SymbolicValue result;
750755
result.representationKind = RK_Closure;
751756
result.value.closure = clo;
@@ -754,6 +759,8 @@ SymbolicValue SymbolicValue::makeClosure(SILFunction *target,
754759

755760
SymbolicClosure *SymbolicClosure::create(SILFunction *target,
756761
ArrayRef<SymbolicClosureArgument> args,
762+
SubstitutionMap substMap,
763+
SILType closureType,
757764
SymbolicValueAllocator &allocator) {
758765
// Determine whether there are captured arguments without a symbolic value.
759766
bool hasNonConstantCapture = false;
@@ -768,8 +775,8 @@ SymbolicClosure *SymbolicClosure::create(SILFunction *target,
768775
SymbolicClosure::totalSizeToAlloc<SymbolicClosureArgument>(args.size());
769776
auto rawMem = allocator.allocate(byteSizeOfArgs, alignof(SymbolicClosure));
770777
// Placement initialize the object.
771-
auto closure = ::new (rawMem)
772-
SymbolicClosure(target, args.size(), hasNonConstantCapture);
778+
auto closure = ::new (rawMem) SymbolicClosure(
779+
target, args.size(), substMap, closureType, hasNonConstantCapture);
773780
std::uninitialized_copy(
774781
args.begin(), args.end(),
775782
closure->getTrailingObjects<SymbolicClosureArgument>());

lib/SILOptimizer/Utils/ConstExpr.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1590,6 +1590,10 @@ llvm::Optional<SymbolicValue> ConstExprFunctionState::evaluateClosureCreation(
15901590

15911591
SmallVector<SymbolicClosureArgument, 4> captures;
15921592

1593+
// Map generic parameters of the target to the generic arguments passed to the
1594+
// call.
1595+
SubstitutionMap callSubstMap;
1596+
15931597
// If this is a partial-apply instruction, arguments to this partial-apply
15941598
// instruction are the captures of the closure.
15951599
if (PartialApplyInst *papply = dyn_cast<PartialApplyInst>(closureInst)) {
@@ -1601,10 +1605,13 @@ llvm::Optional<SymbolicValue> ConstExprFunctionState::evaluateClosureCreation(
16011605
}
16021606
captures.push_back({capturedSILValue, capturedSymbolicValue});
16031607
}
1608+
callSubstMap = papply->getSubstitutionMap().subst(this->substitutionMap);
16041609
}
16051610

1606-
auto closureVal =
1607-
SymbolicValue::makeClosure(target, captures, evaluator.getAllocator());
1611+
SILType closureType = closureInst->getType();
1612+
assert(closureType.is<SILFunctionType>());
1613+
auto closureVal = SymbolicValue::makeClosure(
1614+
target, captures, callSubstMap, closureType, evaluator.getAllocator());
16081615
setValue(closureInst, closureVal);
16091616
return None;
16101617
}

0 commit comments

Comments
 (0)