Skip to content

Commit a30f804

Browse files
Merge pull request #28044 from aschwaighofer/sil_type_expansion_context
SIL: Use a TypeExpansionContext in SIL lowering to expand opaque type archetypes as part of lowering
2 parents 28d4614 + f3a5d69 commit a30f804

File tree

123 files changed

+3239
-2191
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

123 files changed

+3239
-2191
lines changed

include/swift/AST/SubstitutionMap.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/GenericSignature.h"
2121
#include "swift/AST/ProtocolConformanceRef.h"
2222
#include "swift/AST/Type.h"
23+
#include "swift/AST/TypeExpansionContext.h"
2324
#include "swift/Basic/Debug.h"
2425
#include "llvm/ADT/ArrayRef.h"
2526
#include "llvm/ADT/DenseMapInfo.h"
@@ -176,7 +177,13 @@ class SubstitutionMap {
176177
SubstitutionMap subst(TypeSubstitutionFn subs,
177178
LookupConformanceFn conformances,
178179
SubstOptions options=None) const;
179-
180+
181+
/// Apply type expansion lowering to all types in the substitution map. Opaque
182+
/// archetypes will be lowered to their underlying types if the type expansion
183+
/// context allows.
184+
SubstitutionMap mapIntoTypeExpansionContext(
185+
TypeExpansionContext context) const;
186+
180187
/// Create a substitution map for a protocol conformance.
181188
static SubstitutionMap
182189
getProtocolSubstitutions(ProtocolDecl *protocol,
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
//===--- TypeExpansionContext.h - Swift Type Expansion Context --*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines the TypeExpansionContext class.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_TYPEEXPANSIONCONTEXT_H
18+
#define SWIFT_TYPEEXPANSIONCONTEXT_H
19+
20+
#include "swift/AST/ResilienceExpansion.h"
21+
#include "llvm/ADT/DenseMap.h"
22+
23+
namespace swift {
24+
class DeclContext;
25+
class SILFunction;
26+
27+
/// Describes the context in which SIL types should eventually be expanded.
28+
/// Required for lowering resilient types and deciding whether to look through
29+
/// opaque result types to their underlying type.
30+
class TypeExpansionContext {
31+
ResilienceExpansion expansion;
32+
// The context (module, function, ...) we are expanding the type in.
33+
const DeclContext *inContext;
34+
// Is the context in which we are expanding in the whole module.
35+
bool isContextWholeModule;
36+
37+
// The minimal expansion.
38+
TypeExpansionContext() {
39+
inContext = nullptr;
40+
expansion = ResilienceExpansion::Minimal;
41+
isContextWholeModule = false;
42+
}
43+
44+
public:
45+
46+
// Infer the expansion for the SIL function.
47+
TypeExpansionContext(const SILFunction &f);
48+
49+
TypeExpansionContext(ResilienceExpansion expansion,
50+
const DeclContext *inContext, bool isWholeModuleContext)
51+
: expansion(expansion), inContext(inContext),
52+
isContextWholeModule(isWholeModuleContext) {}
53+
54+
ResilienceExpansion getResilienceExpansion() const { return expansion; }
55+
56+
const DeclContext *getContext() const { return inContext; }
57+
58+
bool isWholeModuleContext() const { return isContextWholeModule; }
59+
60+
bool shouldLookThroughOpaqueTypeArchetypes() const {
61+
return inContext != nullptr;
62+
}
63+
64+
bool isMinimal() const { return *this == TypeExpansionContext(); }
65+
66+
static TypeExpansionContext minimal() {
67+
return TypeExpansionContext();
68+
}
69+
70+
static TypeExpansionContext maximal(const DeclContext *inContext,
71+
bool isContextWholeModule) {
72+
return TypeExpansionContext(ResilienceExpansion::Maximal, inContext,
73+
isContextWholeModule);
74+
}
75+
76+
static TypeExpansionContext maximalResilienceExpansionOnly() {
77+
return maximal(nullptr, false);
78+
}
79+
80+
static TypeExpansionContext
81+
noOpaqueTypeArchetypesSubstitution(ResilienceExpansion expansion) {
82+
return TypeExpansionContext(expansion, nullptr, false);
83+
}
84+
85+
bool operator==(const TypeExpansionContext &other) const {
86+
assert(other.inContext != this->inContext ||
87+
other.isContextWholeModule == this->isContextWholeModule);
88+
return other.inContext == this->inContext &&
89+
other.expansion == this->expansion;
90+
}
91+
92+
bool operator<(const TypeExpansionContext other) const {
93+
assert(other.inContext != this->inContext ||
94+
other.isContextWholeModule == this->isContextWholeModule);
95+
if (this->expansion == other.expansion)
96+
return this->inContext < other.inContext;
97+
return this->expansion < other.expansion;
98+
}
99+
100+
bool operator>(const TypeExpansionContext other) const {
101+
assert(other.inContext != this->inContext ||
102+
other.isContextWholeModule == this->isContextWholeModule);
103+
if (this->expansion == other.expansion)
104+
return this->inContext > other.inContext;
105+
return this->expansion > other.expansion;
106+
}
107+
108+
uintptr_t getHashKey() const {
109+
uintptr_t key = (uintptr_t)inContext | (uintptr_t)expansion;
110+
return key;
111+
}
112+
};
113+
114+
} // namespace swift
115+
116+
namespace llvm {
117+
template <> struct DenseMapInfo<swift::TypeExpansionContext> {
118+
using TypeExpansionContext = swift::TypeExpansionContext;
119+
120+
static TypeExpansionContext getEmptyKey() {
121+
return TypeExpansionContext(
122+
swift::ResilienceExpansion::Minimal,
123+
reinterpret_cast<swift::DeclContext *>(
124+
DenseMapInfo<swift::DeclContext *>::getEmptyKey()),
125+
false);
126+
}
127+
static TypeExpansionContext getTombstoneKey() {
128+
return TypeExpansionContext(
129+
swift::ResilienceExpansion::Minimal,
130+
reinterpret_cast<swift::DeclContext *>(
131+
DenseMapInfo<swift::DeclContext *>::getTombstoneKey()),
132+
false);
133+
}
134+
135+
static unsigned getHashValue(TypeExpansionContext val) {
136+
return DenseMapInfo<uintptr_t>::getHashValue(val.getHashKey());
137+
}
138+
139+
static bool isEqual(TypeExpansionContext LHS, TypeExpansionContext RHS) {
140+
return LHS == RHS;
141+
}
142+
};
143+
} // namespace llvm
144+
145+
#endif

include/swift/AST/Types.h

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "swift/AST/SubstitutionMap.h"
2828
#include "swift/AST/Type.h"
2929
#include "swift/AST/TypeAlignments.h"
30+
#include "swift/AST/TypeExpansionContext.h"
3031
#include "swift/Basic/ArrayRefView.h"
3132
#include "swift/Basic/Debug.h"
3233
#include "swift/Basic/InlineBitfield.h"
@@ -582,7 +583,10 @@ class alignas(1 << TypeAlignInBits) TypeBase {
582583
bool hasOpaqueArchetype() const {
583584
return getRecursiveProperties().hasOpaqueArchetype();
584585
}
585-
586+
/// Determine whether the type has any stored properties or enum cases that
587+
/// involve an opaque type.
588+
bool hasOpaqueArchetypePropertiesOrCases();
589+
586590
/// Determine whether the type is an opened existential type.
587591
///
588592
/// To determine whether there is an opened existential type
@@ -3687,6 +3691,17 @@ enum class SILCoroutineKind : uint8_t {
36873691

36883692
class SILFunctionConventions;
36893693

3694+
3695+
CanType substOpaqueTypesWithUnderlyingTypes(CanType type,
3696+
TypeExpansionContext context,
3697+
bool allowLoweredTypes = false);
3698+
ProtocolConformanceRef
3699+
substOpaqueTypesWithUnderlyingTypes(ProtocolConformanceRef ref, Type origType,
3700+
TypeExpansionContext context);
3701+
namespace Lowering {
3702+
class TypeConverter;
3703+
};
3704+
36903705
/// SILFunctionType - The lowered type of a function value, suitable
36913706
/// for use by SIL.
36923707
///
@@ -4205,10 +4220,14 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode,
42054220
SILFunction &context) const;
42064221

42074222
CanSILFunctionType substGenericArgs(SILModule &silModule,
4208-
SubstitutionMap subs);
4223+
SubstitutionMap subs,
4224+
TypeExpansionContext context);
42094225
CanSILFunctionType substGenericArgs(SILModule &silModule,
42104226
TypeSubstitutionFn subs,
4211-
LookupConformanceFn conformances);
4227+
LookupConformanceFn conformances,
4228+
TypeExpansionContext context);
4229+
CanSILFunctionType substituteOpaqueArchetypes(Lowering::TypeConverter &TC,
4230+
TypeExpansionContext context);
42124231

42134232
SILType substInterfaceType(SILModule &M,
42144233
SILType interfaceType) const;
@@ -4963,9 +4982,12 @@ class ReplaceOpaqueTypesWithUnderlyingTypes {
49634982
public:
49644983
const DeclContext *inContext;
49654984
ResilienceExpansion contextExpansion;
4985+
bool isContextWholeModule;
49664986
ReplaceOpaqueTypesWithUnderlyingTypes(const DeclContext *inContext,
4967-
ResilienceExpansion contextExpansion)
4968-
: inContext(inContext), contextExpansion(contextExpansion) {}
4987+
ResilienceExpansion contextExpansion,
4988+
bool isWholeModuleContext)
4989+
: inContext(inContext), contextExpansion(contextExpansion),
4990+
isContextWholeModule(isWholeModuleContext) {}
49694991

49704992
/// TypeSubstitutionFn
49714993
Type operator()(SubstitutableType *maybeOpaqueType) const;
@@ -5752,5 +5774,5 @@ struct DenseMapInfo<swift::BuiltinIntegerWidth> {
57525774
};
57535775

57545776
}
5755-
5777+
57565778
#endif

include/swift/SIL/Projection.h

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,8 @@ class Projection {
293293
///
294294
/// WARNING: This is not a constant time operation because it is implemented
295295
/// in terms of getVarDecl, which requests all BaseType's stored properties.
296-
SILType getType(SILType BaseType, SILModule &M) const;
296+
SILType getType(SILType BaseType, SILModule &M,
297+
TypeExpansionContext context) const;
297298

298299
VarDecl *getVarDecl(SILType BaseType) const {
299300
assert(isValid());
@@ -402,6 +403,7 @@ class Projection {
402403
/// Given a specific SILType, return all first level projections if it is an
403404
/// aggregate.
404405
static void getFirstLevelProjections(SILType V, SILModule &Mod,
406+
TypeExpansionContext context,
405407
llvm::SmallVectorImpl<Projection> &Out);
406408

407409
/// Is this cast which only allows for equality?
@@ -584,6 +586,7 @@ class ProjectionPath {
584586
/// is a leaf node in the type tree.
585587
static void expandTypeIntoLeafProjectionPaths(SILType BaseType,
586588
SILModule *Mod,
589+
TypeExpansionContext context,
587590
ProjectionPathList &P);
588591

589592
/// Return true if the given projection paths in \p CPaths does not cover
@@ -626,26 +629,27 @@ class ProjectionPath {
626629
SILType getBaseType() const { return BaseType; }
627630

628631
/// Returns the most derived type of the projection path.
629-
SILType getMostDerivedType(SILModule &M) {
632+
SILType getMostDerivedType(SILModule &M, TypeExpansionContext context) {
630633
if (Path.empty())
631634
return getBaseType();
632635
if (MostDerivedType)
633636
return MostDerivedType;
634-
MostDerivedType = getDerivedType(Path.size(), M);
637+
MostDerivedType = getDerivedType(Path.size(), M, context);
635638
return MostDerivedType;
636639
}
637640

638641
/// Returns the ith derived type of the path. This is zero indexed with 0
639642
/// being the base type and n consisting of applying the up to n projections
640643
/// to the base type.
641-
SILType getDerivedType(unsigned i, SILModule &M) const {
644+
SILType getDerivedType(unsigned i, SILModule &M,
645+
TypeExpansionContext context) const {
642646
assert(i <= Path.size());
643647
SILType IterTy = getBaseType();
644648
if (i == 0)
645649
return IterTy;
646650
for (unsigned j : range(i)) {
647651
auto &Proj = Path[j];
648-
IterTy = Proj.getType(IterTy, M);
652+
IterTy = Proj.getType(IterTy, M, context);
649653
}
650654
return IterTy;
651655
}
@@ -671,10 +675,11 @@ class ProjectionPath {
671675
const_reverse_iterator rbegin() const { return Path.rbegin(); }
672676
const_reverse_iterator rend() const { return Path.rend(); }
673677

674-
void verify(SILModule &M);
678+
void verify(SILModule &M, TypeExpansionContext context);
675679

676-
raw_ostream &print(raw_ostream &OS, SILModule &M) const;
677-
void dump(SILModule &M) const;
680+
raw_ostream &print(raw_ostream &OS, SILModule &M,
681+
TypeExpansionContext context) const;
682+
void dump(SILModule &M, TypeExpansionContext context) const;
678683
};
679684

680685
/// Returns the hashcode for the new projection path.
@@ -813,9 +818,11 @@ class ProjectionTreeNode {
813818
llvm::SmallVectorImpl<ValueNodePair> &Worklist,
814819
SILValue Value);
815820

816-
void createNextLevelChildren(ProjectionTree &Tree);
821+
void createNextLevelChildren(ProjectionTree &Tree, TypeExpansionContext context);
817822

818-
void createNextLevelChildrenForStruct(ProjectionTree &Tree, StructDecl *SD);
823+
void createNextLevelChildrenForStruct(ProjectionTree &Tree,
824+
TypeExpansionContext context,
825+
StructDecl *SD);
819826

820827
void createNextLevelChildrenForTuple(ProjectionTree &Tree, TupleType *TT);
821828
};

include/swift/SIL/SILBasicBlock.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,8 @@ public llvm::ilist_node<SILBasicBlock>, public SILAllocated<SILBasicBlock> {
214214
/// Allocate a new argument of type \p Ty and append it to the argument
215215
/// list. Optionally you can pass in a value decl parameter.
216216
SILFunctionArgument *createFunctionArgument(SILType Ty,
217-
const ValueDecl *D = nullptr);
217+
const ValueDecl *D = nullptr,
218+
bool disableEntryBlockVerification = false);
218219

219220
SILFunctionArgument *insertFunctionArgument(unsigned Index, SILType Ty,
220221
ValueOwnershipKind OwnershipKind,

0 commit comments

Comments
 (0)