Skip to content

Commit 24d6a29

Browse files
committed
Lower lifetime dependence info into SIL types
1 parent 3ed0932 commit 24d6a29

File tree

12 files changed

+196
-38
lines changed

12 files changed

+196
-38
lines changed

include/swift/AST/ExtInfo.h

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ class LifetimeDependenceInfo {
176176
return copyLifetimeParamIndices == nullptr &&
177177
borrowLifetimeParamIndices == nullptr;
178178
}
179+
std::string getString() const;
179180
};
180181

181182
// MARK: - UnexpectedClangTypeError
@@ -922,11 +923,15 @@ class SILExtInfoBuilder {
922923

923924
ClangTypeInfo clangTypeInfo;
924925

926+
LifetimeDependenceInfo lifetimeDependenceInfo;
927+
925928
using Language = SILFunctionLanguage;
926929
using Representation = SILFunctionTypeRepresentation;
927930

928-
SILExtInfoBuilder(unsigned bits, ClangTypeInfo clangTypeInfo)
929-
: bits(bits), clangTypeInfo(clangTypeInfo.getCanonical()) {}
931+
SILExtInfoBuilder(unsigned bits, ClangTypeInfo clangTypeInfo,
932+
LifetimeDependenceInfo lifetimeDependenceInfo)
933+
: bits(bits), clangTypeInfo(clangTypeInfo.getCanonical()),
934+
lifetimeDependenceInfo(lifetimeDependenceInfo) {}
930935

931936
static constexpr unsigned makeBits(Representation rep, bool isPseudogeneric,
932937
bool isNoEscape, bool isSendable,
@@ -948,23 +953,24 @@ class SILExtInfoBuilder {
948953
: SILExtInfoBuilder(makeBits(SILFunctionTypeRepresentation::Thick, false,
949954
false, false, false, false,
950955
DifferentiabilityKind::NonDifferentiable),
951-
ClangTypeInfo(nullptr)) {}
956+
ClangTypeInfo(nullptr), LifetimeDependenceInfo()) {}
952957

953958
SILExtInfoBuilder(Representation rep, bool isPseudogeneric, bool isNoEscape,
954959
bool isSendable, bool isAsync, bool isUnimplementable,
955-
DifferentiabilityKind diffKind, const clang::Type *type)
956-
: SILExtInfoBuilder(makeBits(rep, isPseudogeneric, isNoEscape,
957-
isSendable, isAsync, isUnimplementable,
958-
diffKind),
959-
ClangTypeInfo(type)) {}
960+
DifferentiabilityKind diffKind, const clang::Type *type,
961+
LifetimeDependenceInfo lifetimeDependenceInfo)
962+
: SILExtInfoBuilder(makeBits(rep, isPseudogeneric, isNoEscape, isSendable,
963+
isAsync, isUnimplementable, diffKind),
964+
ClangTypeInfo(type), lifetimeDependenceInfo) {}
960965

961966
// Constructor for polymorphic type.
962967
SILExtInfoBuilder(ASTExtInfoBuilder info, bool isPseudogeneric)
963968
: SILExtInfoBuilder(makeBits(info.getSILRepresentation(), isPseudogeneric,
964969
info.isNoEscape(), info.isSendable(),
965970
info.isAsync(), /*unimplementable*/ false,
966971
info.getDifferentiabilityKind()),
967-
info.getClangTypeInfo()) {}
972+
info.getClangTypeInfo(),
973+
info.getLifetimeDependenceInfo()) {}
968974

969975
void checkInvariants() const;
970976

@@ -1008,6 +1014,10 @@ class SILExtInfoBuilder {
10081014
/// Get the underlying ClangTypeInfo value.
10091015
ClangTypeInfo getClangTypeInfo() const { return clangTypeInfo; }
10101016

1017+
LifetimeDependenceInfo getLifetimeDependenceInfo() const {
1018+
return lifetimeDependenceInfo;
1019+
}
1020+
10111021
constexpr bool hasSelfParam() const {
10121022
switch (getRepresentation()) {
10131023
case Representation::Thick:
@@ -1057,50 +1067,55 @@ class SILExtInfoBuilder {
10571067
SILExtInfoBuilder withRepresentation(Representation rep) const {
10581068
return SILExtInfoBuilder((bits & ~RepresentationMask) | (unsigned)rep,
10591069
shouldStoreClangType(rep) ? clangTypeInfo
1060-
: ClangTypeInfo());
1070+
: ClangTypeInfo(),
1071+
lifetimeDependenceInfo);
10611072
}
10621073
[[nodiscard]]
10631074
SILExtInfoBuilder withIsPseudogeneric(bool isPseudogeneric = true) const {
10641075
return SILExtInfoBuilder(isPseudogeneric ? (bits | PseudogenericMask)
10651076
: (bits & ~PseudogenericMask),
1066-
clangTypeInfo);
1077+
clangTypeInfo, lifetimeDependenceInfo);
10671078
}
10681079
[[nodiscard]]
10691080
SILExtInfoBuilder withNoEscape(bool noEscape = true) const {
10701081
return SILExtInfoBuilder(noEscape ? (bits | NoEscapeMask)
10711082
: (bits & ~NoEscapeMask),
1072-
clangTypeInfo);
1083+
clangTypeInfo, lifetimeDependenceInfo);
10731084
}
10741085
[[nodiscard]]
10751086
SILExtInfoBuilder withConcurrent(bool isSendable = true) const {
10761087
return SILExtInfoBuilder(isSendable ? (bits | SendableMask)
1077-
: (bits & ~SendableMask),
1078-
clangTypeInfo);
1088+
: (bits & ~SendableMask),
1089+
clangTypeInfo, lifetimeDependenceInfo);
10791090
}
10801091
[[nodiscard]]
10811092
SILExtInfoBuilder withAsync(bool isAsync = true) const {
10821093
return SILExtInfoBuilder(isAsync ? (bits | AsyncMask) : (bits & ~AsyncMask),
1083-
clangTypeInfo);
1094+
clangTypeInfo, lifetimeDependenceInfo);
10841095
}
10851096
[[nodiscard]]
10861097
SILExtInfoBuilder withUnimplementable(bool isUnimplementable = true) const {
10871098
return SILExtInfoBuilder(isUnimplementable ? (bits | UnimplementableMask)
10881099
: (bits & ~UnimplementableMask),
1089-
clangTypeInfo);
1100+
clangTypeInfo, lifetimeDependenceInfo);
10901101
}
10911102
[[nodiscard]]
10921103
SILExtInfoBuilder
10931104
withDifferentiabilityKind(DifferentiabilityKind differentiability) const {
10941105
return SILExtInfoBuilder(
10951106
(bits & ~DifferentiabilityMask) |
10961107
((unsigned)differentiability << DifferentiabilityMaskOffset),
1097-
clangTypeInfo);
1108+
clangTypeInfo, lifetimeDependenceInfo);
10981109
}
10991110
[[nodiscard]]
11001111
SILExtInfoBuilder withClangFunctionType(const clang::Type *type) const {
1101-
return SILExtInfoBuilder(bits, ClangTypeInfo(type).getCanonical());
1112+
return SILExtInfoBuilder(bits, ClangTypeInfo(type).getCanonical(),
1113+
lifetimeDependenceInfo);
1114+
}
1115+
[[nodiscard]] SILExtInfoBuilder withLifetimeDependenceInfo(
1116+
LifetimeDependenceInfo lifetimeDependenceInfo) const {
1117+
return SILExtInfoBuilder(bits, clangTypeInfo, lifetimeDependenceInfo);
11021118
}
1103-
11041119

11051120
bool isEqualTo(SILExtInfoBuilder other, bool useClangTypes) const {
11061121
return bits == other.bits &&
@@ -1129,8 +1144,9 @@ class SILExtInfo {
11291144
// Only for use by SILExtInfoBuilder::build. Don't use it elsewhere!
11301145
SILExtInfo(SILExtInfoBuilder builder) : builder(builder) {}
11311146

1132-
SILExtInfo(unsigned bits, ClangTypeInfo clangTypeInfo)
1133-
: builder(bits, clangTypeInfo) {
1147+
SILExtInfo(unsigned bits, ClangTypeInfo clangTypeInfo,
1148+
LifetimeDependenceInfo lifetimeDependenceInfo)
1149+
: builder(bits, clangTypeInfo, lifetimeDependenceInfo) {
11341150
builder.checkInvariants();
11351151
};
11361152

@@ -1148,7 +1164,8 @@ class SILExtInfo {
11481164
static SILExtInfo getThin() {
11491165
return SILExtInfoBuilder(SILExtInfoBuilder::Representation::Thin, false,
11501166
false, false, false, false,
1151-
DifferentiabilityKind::NonDifferentiable, nullptr)
1167+
DifferentiabilityKind::NonDifferentiable, nullptr,
1168+
LifetimeDependenceInfo())
11521169
.build();
11531170
}
11541171

@@ -1187,6 +1204,10 @@ class SILExtInfo {
11871204

11881205
ClangTypeInfo getClangTypeInfo() const { return builder.getClangTypeInfo(); }
11891206

1207+
LifetimeDependenceInfo getLifetimeDependenceInfo() const {
1208+
return builder.getLifetimeDependenceInfo();
1209+
}
1210+
11901211
constexpr bool hasSelfParam() const { return builder.hasSelfParam(); }
11911212

11921213
constexpr bool hasContext() const { return builder.hasContext(); }

include/swift/AST/Types.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -444,14 +444,15 @@ class alignas(1 << TypeAlignInBits) TypeBase
444444
NumTerms : 32
445445
);
446446

447-
SWIFT_INLINE_BITFIELD(SILFunctionType, TypeBase, NumSILExtInfoBits+1+4+1+2+1+1,
447+
SWIFT_INLINE_BITFIELD(SILFunctionType, TypeBase, NumSILExtInfoBits+1+4+1+2+1+1+1,
448448
ExtInfoBits : NumSILExtInfoBits,
449449
HasClangTypeInfo : 1,
450450
CalleeConvention : 4,
451451
HasErrorResult : 1,
452452
CoroutineKind : 2,
453453
HasInvocationSubs : 1,
454-
HasPatternSubs : 1
454+
HasPatternSubs : 1,
455+
HasLifetimeDependenceInfo : 1
455456
);
456457

457458
SWIFT_INLINE_BITFIELD(AnyMetatypeType, TypeBase, 2,
@@ -4688,9 +4689,9 @@ namespace Lowering {
46884689
class SILFunctionType final
46894690
: public TypeBase,
46904691
public llvm::FoldingSetNode,
4691-
private llvm::TrailingObjects<SILFunctionType, SILParameterInfo,
4692-
SILResultInfo, SILYieldInfo,
4693-
SubstitutionMap, CanType, ClangTypeInfo> {
4692+
private llvm::TrailingObjects<
4693+
SILFunctionType, SILParameterInfo, SILResultInfo, SILYieldInfo,
4694+
SubstitutionMap, CanType, ClangTypeInfo, LifetimeDependenceInfo> {
46944695
friend TrailingObjects;
46954696

46964697
size_t numTrailingObjects(OverloadToken<SILParameterInfo>) const {
@@ -4718,6 +4719,10 @@ class SILFunctionType final
47184719
return Bits.SILFunctionType.HasClangTypeInfo ? 1 : 0;
47194720
}
47204721

4722+
size_t numTrailingObjects(OverloadToken<LifetimeDependenceInfo>) const {
4723+
return Bits.SILFunctionType.HasLifetimeDependenceInfo ? 1 : 0;
4724+
}
4725+
47214726
public:
47224727
using ExtInfo = SILExtInfo;
47234728
using ExtInfoBuilder = SILExtInfoBuilder;
@@ -5205,6 +5210,8 @@ class SILFunctionType final
52055210

52065211
ClangTypeInfo getClangTypeInfo() const;
52075212

5213+
LifetimeDependenceInfo getLifetimeDependenceInfo() const;
5214+
52085215
/// Returns true if the function type stores a Clang type that cannot
52095216
/// be derived from its Swift type. Returns false otherwise, including if
52105217
/// the function type is not @convention(c) or @convention(block).
@@ -5368,7 +5375,8 @@ class SILFunctionType final
53685375
CanGenericSignature transposeFunctionGenericSignature = nullptr);
53695376

53705377
ExtInfo getExtInfo() const {
5371-
return ExtInfo(Bits.SILFunctionType.ExtInfoBits, getClangTypeInfo());
5378+
return ExtInfo(Bits.SILFunctionType.ExtInfoBits, getClangTypeInfo(),
5379+
getLifetimeDependenceInfo());
53725380
}
53735381

53745382
/// Returns the language-level calling convention of the function.

lib/AST/ASTContext.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4494,6 +4494,8 @@ SILFunctionType::SILFunctionType(
44944494
static_assert(SILExtInfoBuilder::NumMaskBits == NumSILExtInfoBits,
44954495
"ExtInfo and SILFunctionTypeBitfields must agree on bit size");
44964496
Bits.SILFunctionType.HasClangTypeInfo = !ext.getClangTypeInfo().empty();
4497+
Bits.SILFunctionType.HasLifetimeDependenceInfo =
4498+
!ext.getLifetimeDependenceInfo().empty();
44974499
Bits.SILFunctionType.CoroutineKind = unsigned(coroutineKind);
44984500
NumParameters = params.size();
44994501
if (coroutineKind == SILCoroutineKind::None) {
@@ -4544,6 +4546,10 @@ SILFunctionType::SILFunctionType(
45444546
if (!ext.getClangTypeInfo().empty())
45454547
*getTrailingObjects<ClangTypeInfo>() = ext.getClangTypeInfo();
45464548

4549+
if (!ext.getLifetimeDependenceInfo().empty())
4550+
*getTrailingObjects<LifetimeDependenceInfo>() =
4551+
ext.getLifetimeDependenceInfo();
4552+
45474553
#ifndef NDEBUG
45484554
if (ext.getRepresentation() == Representation::WitnessMethod)
45494555
assert(!WitnessMethodConformance.isInvalid() &&
@@ -4730,10 +4736,12 @@ CanSILFunctionType SILFunctionType::get(
47304736
// See [NOTE: SILFunctionType-layout]
47314737
bool hasResultCache = normalResults.size() > 1;
47324738
size_t bytes = totalSizeToAlloc<SILParameterInfo, SILResultInfo, SILYieldInfo,
4733-
SubstitutionMap, CanType, ClangTypeInfo>(
4739+
SubstitutionMap, CanType, ClangTypeInfo,
4740+
LifetimeDependenceInfo>(
47344741
params.size(), normalResults.size() + (errorResult ? 1 : 0),
47354742
yields.size(), (patternSubs ? 1 : 0) + (invocationSubs ? 1 : 0),
4736-
hasResultCache ? 2 : 0, ext.getClangTypeInfo().empty() ? 0 : 1);
4743+
hasResultCache ? 2 : 0, ext.getClangTypeInfo().empty() ? 0 : 1,
4744+
ext.getLifetimeDependenceInfo().empty() ? 0 : 1);
47374745

47384746
void *mem = ctx.Allocate(bytes, alignof(SILFunctionType));
47394747

lib/AST/ASTDemangler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -652,8 +652,8 @@ Type ASTBuilder::createImplFunctionType(
652652
}
653653
auto einfo = SILFunctionType::ExtInfoBuilder(
654654
representation, flags.isPseudogeneric(), !flags.isEscaping(),
655-
flags.isSendable(), flags.isAsync(),
656-
unimplementable, diffKind, clangFnType)
655+
flags.isSendable(), flags.isAsync(), unimplementable,
656+
diffKind, clangFnType, LifetimeDependenceInfo())
657657
.build();
658658

659659
return SILFunctionType::get(genericSig, einfo, funcCoroutineKind,

lib/AST/ASTPrinter.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7201,6 +7201,12 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
72017201

72027202
Printer << " -> ";
72037203

7204+
if (T->hasLifetimeDependenceInfo()) {
7205+
auto lifetimeDependenceInfo = T->getExtInfo().getLifetimeDependenceInfo();
7206+
assert(!lifetimeDependenceInfo.empty());
7207+
Printer << lifetimeDependenceInfo.getString() << " ";
7208+
}
7209+
72047210
Printer.callPrintStructurePre(PrintStructureKind::FunctionReturnType);
72057211
T->getResult().print(Printer, Options);
72067212
Printer.printStructurePost(PrintStructureKind::FunctionReturnType);
@@ -7360,6 +7366,11 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
73607366
}
73617367
sub->Printer << ") -> ";
73627368

7369+
auto lifetimeDependenceInfo = T->getLifetimeDependenceInfo();
7370+
if (!lifetimeDependenceInfo.empty()) {
7371+
sub->Printer << lifetimeDependenceInfo.getString() << " ";
7372+
}
7373+
73637374
bool parenthesizeResults = mustParenthesizeResults(T);
73647375
if (parenthesizeResults)
73657376
sub->Printer << "(";

lib/AST/ExtInfo.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,33 @@ void ClangTypeInfo::dump(llvm::raw_ostream &os,
5858
}
5959
}
6060

61+
std::string LifetimeDependenceInfo::getString() const {
62+
std::string lifetimeDependenceString;
63+
auto getOnIndices = [](IndexSubset *bitvector) {
64+
std::string result;
65+
bool isFirstSetBit = true;
66+
for (unsigned i = 0; i < bitvector->getCapacity(); i++) {
67+
if (bitvector->contains(i)) {
68+
if (!isFirstSetBit) {
69+
result += ", ";
70+
}
71+
result += std::to_string(i);
72+
isFirstSetBit = false;
73+
}
74+
}
75+
return result;
76+
};
77+
if (!copyLifetimeParamIndices->isEmpty()) {
78+
lifetimeDependenceString =
79+
"_copy(" + getOnIndices(copyLifetimeParamIndices) + ")";
80+
}
81+
if (!borrowLifetimeParamIndices->isEmpty()) {
82+
lifetimeDependenceString +=
83+
"_borrow(" + getOnIndices(borrowLifetimeParamIndices) + ")";
84+
}
85+
return lifetimeDependenceString;
86+
}
87+
6188
// MARK: - UnexpectedClangTypeError
6289

6390
llvm::Optional<UnexpectedClangTypeError>

lib/AST/Type.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4298,6 +4298,16 @@ ClangTypeInfo SILFunctionType::getClangTypeInfo() const {
42984298
return *info;
42994299
}
43004300

4301+
LifetimeDependenceInfo SILFunctionType::getLifetimeDependenceInfo() const {
4302+
if (!Bits.SILFunctionType.HasLifetimeDependenceInfo)
4303+
return LifetimeDependenceInfo();
4304+
auto *info = getTrailingObjects<LifetimeDependenceInfo>();
4305+
assert(
4306+
!info->empty() &&
4307+
"If the LifetimeDependenceInfo was empty, we shouldn't have stored it.");
4308+
return *info;
4309+
}
4310+
43014311
bool SILFunctionType::hasNonDerivableClangType() {
43024312
auto clangTypeInfo = getClangTypeInfo();
43034313
if (clangTypeInfo.empty())

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2380,6 +2380,8 @@ static CanSILFunctionType getSILFunctionType(
23802380
.withConcurrent(isSendable)
23812381
.withAsync(isAsync)
23822382
.withUnimplementable(unimplementable)
2383+
.withLifetimeDependenceInfo(
2384+
extInfoBuilder.getLifetimeDependenceInfo())
23832385
.build();
23842386

23852387
return SILFunctionType::get(genericSig, silExtInfo, coroutineKind,

lib/SIL/IR/TypeLowering.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3682,6 +3682,7 @@ getFunctionInterfaceTypeWithCaptures(TypeConverter &TC,
36823682
.withConcurrent(funcType->isSendable())
36833683
.withAsync(funcType->isAsync())
36843684
.withIsolation(funcType->getIsolation())
3685+
.withLifetimeDependenceInfo(funcType->getLifetimeDependenceInfo())
36853686
.build();
36863687

36873688
return CanAnyFunctionType::get(

lib/Sema/TypeCheckType.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4186,9 +4186,10 @@ NeverNullType TypeResolver::resolveSILFunctionType(FunctionTypeRepr *repr,
41864186
bool async = claim<AsyncTypeAttr>(attrs);
41874187
bool unimplementable = claim<UnimplementableTypeAttr>(attrs);
41884188

4189+
// TODO: Handle LifetimeDependenceInfo here.
41894190
auto extInfoBuilder = SILFunctionType::ExtInfoBuilder(
4190-
representation, pseudogeneric, noescape, sendable, async,
4191-
unimplementable, diffKind, clangFnType);
4191+
representation, pseudogeneric, noescape, sendable, async, unimplementable,
4192+
diffKind, clangFnType, LifetimeDependenceInfo());
41924193

41934194
// Resolve parameter and result types using the function's generic
41944195
// environment.

0 commit comments

Comments
 (0)