Skip to content

Commit b76c0ab

Browse files
committed
SIL: Lower closure capture params out-of-band from the formal type.
Instead of bodging a representation of the SIL capture parameters for a closure into the formal type of closure SILDeclRefs, introduce those parameters in a separate lowering step. This lets us clean up some TypeLowering code that was tolerating things like SILBoxTypes and naked LValueTypes in formal types for nefarious ends (though requires some hacks in SILGen to keep the representation of curry levels consistent, which is something I hope to clean up next). This also decouples the handling of captures from the handling of other parameters, which should enable us to make them +0. For now, there should be NFC.
1 parent cf7af45 commit b76c0ab

File tree

4 files changed

+266
-229
lines changed

4 files changed

+266
-229
lines changed

include/swift/SIL/AbstractionPattern.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -267,13 +267,6 @@ class AbstractionPattern {
267267

268268
Kind getKind() const { return Kind(TheKind); }
269269

270-
CanGenericSignature getGenericSignature() const {
271-
assert(getKind() == Kind::Type ||
272-
hasStoredClangType() ||
273-
hasStoredObjCMethod());
274-
return CanGenericSignature(GenericSig);
275-
}
276-
277270
CanGenericSignature getGenericSignatureForFunctionComponent() const {
278271
if (auto genericFn = dyn_cast<GenericFunctionType>(getType())) {
279272
return genericFn.getGenericSignature();
@@ -362,6 +355,13 @@ class AbstractionPattern {
362355
return AbstractionPattern(Kind::Invalid);
363356
}
364357

358+
CanGenericSignature getGenericSignature() const {
359+
assert(getKind() == Kind::Type ||
360+
hasStoredClangType() ||
361+
hasStoredObjCMethod());
362+
return CanGenericSignature(GenericSig);
363+
}
364+
365365
/// Return an open-coded abstraction pattern for a tuple. The
366366
/// caller is responsible for ensuring that the storage for the
367367
/// tuple elements is valid for as long as the abstraction pattern is.

lib/SIL/SILFunctionType.cpp

Lines changed: 110 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ enum class ConventionsKind : uint8_t {
122122
CFunction = 4,
123123
SelectorFamily = 5,
124124
Deallocator = 6,
125+
Capture = 7,
125126
};
126127

127128
class Conventions {
@@ -359,9 +360,6 @@ enum class ConventionsKind : uint8_t {
359360
if (isa<InOutType>(substType)) {
360361
assert(origType.isOpaque() || origType.getAs<InOutType>());
361362
convention = ParameterConvention::Indirect_Inout;
362-
} else if (isa<LValueType>(substType)) {
363-
assert(origType.isOpaque() || origType.getAs<LValueType>());
364-
convention = ParameterConvention::Indirect_InoutAliasable;
365363
} else if (isPassedIndirectly(origType, substType, substTL)) {
366364
convention = Convs.getIndirectParameter(origParamIndex, origType);
367365
assert(isIndirectParameter(convention));
@@ -430,7 +428,8 @@ static CanSILFunctionType getSILFunctionType(SILModule &M,
430428
CanAnyFunctionType substFnInterfaceType,
431429
AnyFunctionType::ExtInfo extInfo,
432430
const Conventions &conventions,
433-
const Optional<ForeignErrorConvention> &foreignError) {
431+
const Optional<ForeignErrorConvention> &foreignError,
432+
Optional<SILDeclRef> constant) {
434433
SmallVector<SILParameterInfo, 8> inputs;
435434

436435
// Per above, only fully honor opaqueness in the abstraction pattern
@@ -564,7 +563,92 @@ static CanSILFunctionType getSILFunctionType(SILModule &M,
564563
substFnInterfaceType.getInput(),
565564
extInfo);
566565
}
567-
566+
567+
// Lower the capture context parameters, if any.
568+
if (constant)
569+
if (auto function = constant->getAnyFunctionRef()) {
570+
auto &Types = M.Types;
571+
auto loweredCaptures = Types.getLoweredLocalCaptures(*function);
572+
573+
for (auto capture : loweredCaptures.getCaptures()) {
574+
auto *VD = capture.getDecl();
575+
auto type = VD->getType()->getCanonicalType();
576+
577+
type = Types.getInterfaceTypeOutOfContext(type,
578+
function->getAsDeclContext());
579+
580+
auto loweredTy = Types.getLoweredType(
581+
AbstractionPattern(genericSig, type), type);
582+
583+
switch (Types.getDeclCaptureKind(capture)) {
584+
case CaptureKind::None:
585+
break;
586+
case CaptureKind::Constant: {
587+
class CaptureConventions final : public Conventions {
588+
public:
589+
ParameterConvention getIndirectParameter(unsigned index,
590+
const AbstractionPattern &type)
591+
const override {
592+
return ParameterConvention::Indirect_In;
593+
}
594+
ParameterConvention getDirectParameter(unsigned index,
595+
const AbstractionPattern &type)
596+
const override {
597+
return ParameterConvention::Direct_Owned;
598+
}
599+
ParameterConvention getCallee() const override {
600+
llvm_unreachable("captures are never callees");
601+
}
602+
ResultConvention getResult(const TypeLowering &) const override {
603+
llvm_unreachable("captures are never results");
604+
}
605+
ParameterConvention getIndirectSelfParameter(
606+
const AbstractionPattern &type)
607+
const override {
608+
llvm_unreachable("captures are never self");
609+
}
610+
ParameterConvention getDirectSelfParameter(
611+
const AbstractionPattern &type)
612+
const override {
613+
llvm_unreachable("captures are never self");
614+
}
615+
616+
CaptureConventions() : Conventions(ConventionsKind::Capture) {}
617+
618+
static bool classof(const Conventions *C) {
619+
return C->getKind() == ConventionsKind::Capture;
620+
}
621+
};
622+
623+
// Constants are captured by value. Destructure like a value parameter.
624+
Optional<ForeignErrorConvention> foreignError;
625+
DestructureInputs DestructureCaptures(M, CaptureConventions(),
626+
foreignError, inputs);
627+
DestructureCaptures.destructure(AbstractionPattern(genericSig, type),
628+
type, extInfo);
629+
break;
630+
}
631+
case CaptureKind::Box: {
632+
// Lvalues are captured as a box that owns the captured value.
633+
SILType ty = loweredTy.getAddressType();
634+
CanType boxTy = SILBoxType::get(ty.getSwiftRValueType());
635+
auto param = SILParameterInfo(boxTy,
636+
ParameterConvention::Direct_Owned);
637+
inputs.push_back(param);
638+
break;
639+
}
640+
case CaptureKind::StorageAddress: {
641+
// Non-escaping lvalues are captured as the address of the value.
642+
SILType ty = loweredTy.getAddressType();
643+
auto param = SILParameterInfo(ty.getSwiftRValueType(),
644+
ParameterConvention::Indirect_InoutAliasable);
645+
inputs.push_back(param);
646+
break;
647+
}
648+
}
649+
}
650+
}
651+
568652
auto calleeConvention = ParameterConvention::Direct_Unowned;
569653
if (extInfo.hasContext())
570654
calleeConvention = conventions.getCallee();
@@ -730,17 +814,19 @@ namespace {
730814
}
731815

732816
static CanSILFunctionType getNativeSILFunctionType(SILModule &M,
733-
AbstractionPattern origType,
734-
CanAnyFunctionType substType,
735-
CanAnyFunctionType substInterfaceType,
736-
AnyFunctionType::ExtInfo extInfo,
737-
SILDeclRef::Kind kind) {
817+
AbstractionPattern origType,
818+
CanAnyFunctionType substType,
819+
CanAnyFunctionType substInterfaceType,
820+
AnyFunctionType::ExtInfo extInfo,
821+
Optional<SILDeclRef> constant,
822+
SILDeclRef::Kind kind) {
738823
switch (extInfo.getSILRepresentation()) {
739824
case SILFunctionType::Representation::Block:
740825
case SILFunctionType::Representation::CFunctionPointer:
826+
// TODO: Ought to support captures in block funcs.
741827
return getSILFunctionType(M, origType, substType, substInterfaceType,
742828
extInfo, DefaultBlockConventions(),
743-
None);
829+
None, constant);
744830

745831
case SILFunctionType::Representation::Thin:
746832
case SILFunctionType::Representation::ObjCMethod:
@@ -751,7 +837,7 @@ static CanSILFunctionType getNativeSILFunctionType(SILModule &M,
751837
case SILDeclRef::Kind::Initializer:
752838
return getSILFunctionType(M, origType, substType, substInterfaceType,
753839
extInfo, DefaultInitializerConventions(),
754-
None);
840+
None, constant);
755841

756842
case SILDeclRef::Kind::Func:
757843
case SILDeclRef::Kind::Allocator:
@@ -764,10 +850,11 @@ static CanSILFunctionType getNativeSILFunctionType(SILModule &M,
764850
case SILDeclRef::Kind::EnumElement:
765851
return getSILFunctionType(M, origType, substType, substInterfaceType,
766852
extInfo, DefaultConventions(),
767-
None);
853+
None, constant);
768854
case SILDeclRef::Kind::Deallocator:
769855
return getSILFunctionType(M, origType, substType, substInterfaceType,
770-
extInfo, DeallocatorConventions(), None);
856+
extInfo, DeallocatorConventions(), None,
857+
constant);
771858
}
772859
}
773860
}
@@ -789,7 +876,7 @@ CanSILFunctionType swift::getNativeSILFunctionType(SILModule &M,
789876
extInfo = substType->getExtInfo();
790877
}
791878
return ::getNativeSILFunctionType(M, origType, substType, substInterfaceType,
792-
extInfo, kind);
879+
extInfo, None, kind);
793880
}
794881

795882
//===----------------------------------------------------------------------===//
@@ -1101,15 +1188,15 @@ getSILFunctionTypeForClangDecl(SILModule &M, const clang::Decl *clangDecl,
11011188
AbstractionPattern::getObjCMethod(origType, method, foreignError);
11021189
return getSILFunctionType(M, origPattern, substType, substInterfaceType,
11031190
extInfo, ObjCMethodConventions(method),
1104-
foreignError);
1191+
foreignError, None);
11051192
}
11061193

11071194
if (auto func = dyn_cast<clang::FunctionDecl>(clangDecl)) {
11081195
AbstractionPattern origPattern(origType,
11091196
func->getType().getTypePtr());
11101197
return getSILFunctionType(M, origPattern, substType, substInterfaceType,
11111198
extInfo, CFunctionConventions(func),
1112-
foreignError);
1199+
foreignError, None);
11131200
}
11141201

11151202
llvm_unreachable("call to unknown kind of C function");
@@ -1297,7 +1384,7 @@ getSILFunctionTypeForSelectorFamily(SILModule &M, SelectorFamily family,
12971384
substType, substInterfaceType,
12981385
extInfo,
12991386
SelectorFamilyConventions(family),
1300-
foreignError);
1387+
foreignError, None);
13011388
}
13021389

13031390
static CanSILFunctionType
@@ -1334,10 +1421,11 @@ getUncachedSILFunctionTypeForConstant(SILModule &M, SILDeclRef constant,
13341421

13351422
if (!constant.isForeign) {
13361423
return getNativeSILFunctionType(M, AbstractionPattern(origLoweredType),
1337-
substLoweredType,
1338-
substLoweredInterfaceType,
1339-
extInfo,
1340-
constant.kind);
1424+
substLoweredType,
1425+
substLoweredInterfaceType,
1426+
extInfo,
1427+
constant,
1428+
constant.kind);
13411429
}
13421430

13431431
Optional<ForeignErrorConvention> foreignError;

0 commit comments

Comments
 (0)