@@ -20,6 +20,30 @@ namespace Lowering {
20
20
21
21
class SILGenFunction ;
22
22
23
+ // / TODO: std::variant.
24
+ struct SwitchCaseBranchDest {
25
+ Optional<JumpDest> jumpDest;
26
+ NullablePtr<SILBasicBlock> block;
27
+
28
+ SwitchCaseBranchDest () : jumpDest(), block() {}
29
+
30
+ // / Implicit conversion.
31
+ SwitchCaseBranchDest (JumpDest jumpDest) : jumpDest(jumpDest), block() {}
32
+
33
+ // / Implicit conversion.
34
+ SwitchCaseBranchDest (SILBasicBlock *block) : jumpDest(), block(block) {}
35
+
36
+ explicit operator bool () const {
37
+ return jumpDest.hasValue () || block.isNonNull ();
38
+ }
39
+
40
+ bool hasJumpDest () const { return jumpDest.hasValue (); }
41
+ bool hasBlock () const { return bool (block); }
42
+
43
+ SILBasicBlock *getBlock () { return block.getPtrOrNull (); }
44
+ JumpDest &getJumpDest () { return jumpDest.getValue (); }
45
+ };
46
+
23
47
// / A cleanup scope RAII object, like FullExpr, that comes with a JumpDest for a
24
48
// / continuation block. It is intended to be used to handle switch cases.
25
49
// /
@@ -30,23 +54,31 @@ class SwitchCaseFullExpr {
30
54
SILGenFunction &SGF;
31
55
Scope scope;
32
56
CleanupLocation loc;
33
- NullablePtr<SILBasicBlock> contBlock ;
57
+ SwitchCaseBranchDest branchDest ;
34
58
35
59
public:
36
60
SwitchCaseFullExpr (SILGenFunction &SGF, CleanupLocation loc);
37
61
SwitchCaseFullExpr (SILGenFunction &SGF, CleanupLocation loc,
38
- SILBasicBlock *contBlock );
62
+ SwitchCaseBranchDest branchDest );
39
63
40
- ~SwitchCaseFullExpr () = default ;
64
+ ~SwitchCaseFullExpr ();
41
65
42
66
SwitchCaseFullExpr (const SwitchCaseFullExpr &) = delete ;
43
67
SwitchCaseFullExpr &operator =(const SwitchCaseFullExpr &) = delete ;
44
68
45
- // / Pop the scope and branch to the cont block.
69
+ // / Pop the scope and branch to the branch destination. If this case has an
70
+ // / associated JumpDest as its branch destination, then this will cause
71
+ // / cleanups associated with the jump dest to be emitted.
46
72
void exitAndBranch (SILLocation loc, ArrayRef<SILValue> result = {});
47
73
48
- // / Pop the scope and do not branch to the cont block.
74
+ // / Pop the scope and do not branch to the branch destination. This is
75
+ // / intended to be used in situations where one wants to model a switch region
76
+ // / that ends midway through one of the case blocks.
49
77
void exit ();
78
+
79
+ // / Do not pop the scope and do not branch to the branch destination. But do
80
+ // / invalidate the scope. This can occur when emitting unreachables.
81
+ void unreachableExit ();
50
82
};
51
83
52
84
// / A class for building switch enums that handles all of the ownership
@@ -55,6 +87,9 @@ class SwitchCaseFullExpr {
55
87
// / It assumes that the user passes in a block that takes in a ManagedValue and
56
88
// / returns a ManagedValue for the blocks exit argument. Should return an empty
57
89
// / ManagedValue to signal no result.
90
+ // /
91
+ // / TODO: Allow cases to take JumpDest as continuation blocks and then
92
+ // / force exitBranchAndCleanup to be run.
58
93
class SwitchEnumBuilder {
59
94
public:
60
95
using NormalCaseHandler =
@@ -68,29 +103,29 @@ class SwitchEnumBuilder {
68
103
struct NormalCaseData {
69
104
EnumElementDecl *decl;
70
105
SILBasicBlock *block;
71
- NullablePtr<SILBasicBlock> contBlock ;
106
+ SwitchCaseBranchDest branchDest ;
72
107
NormalCaseHandler handler;
73
108
ProfileCounter count;
74
109
75
110
NormalCaseData (EnumElementDecl *decl, SILBasicBlock *block,
76
- NullablePtr<SILBasicBlock> contBlock ,
77
- NormalCaseHandler handler, ProfileCounter count)
78
- : decl(decl), block(block), contBlock(contBlock ), handler(handler),
111
+ SwitchCaseBranchDest branchDest, NormalCaseHandler handler ,
112
+ ProfileCounter count)
113
+ : decl(decl), block(block), branchDest(branchDest ), handler(handler),
79
114
count (count) {}
80
115
~NormalCaseData () = default ;
81
116
};
82
117
83
118
struct DefaultCaseData {
84
119
SILBasicBlock *block;
85
- NullablePtr<SILBasicBlock> contBlock ;
120
+ SwitchCaseBranchDest branchDest ;
86
121
DefaultCaseHandler handler;
87
122
DefaultDispatchTime dispatchTime;
88
123
ProfileCounter count;
89
124
90
- DefaultCaseData (SILBasicBlock *block, NullablePtr<SILBasicBlock> contBlock ,
125
+ DefaultCaseData (SILBasicBlock *block, SwitchCaseBranchDest branchDest ,
91
126
DefaultCaseHandler handler,
92
127
DefaultDispatchTime dispatchTime, ProfileCounter count)
93
- : block(block), contBlock(contBlock ), handler(handler),
128
+ : block(block), branchDest(branchDest ), handler(handler),
94
129
dispatchTime (dispatchTime), count(count) {}
95
130
~DefaultCaseData () = default ;
96
131
};
@@ -107,18 +142,18 @@ class SwitchEnumBuilder {
107
142
: builder(builder), loc(loc), optional(optional) {}
108
143
109
144
void addDefaultCase (
110
- SILBasicBlock *defaultBlock, NullablePtr<SILBasicBlock> contBlock ,
145
+ SILBasicBlock *defaultBlock, SwitchCaseBranchDest branchDest ,
111
146
DefaultCaseHandler handle,
112
147
DefaultDispatchTime dispatchTime = DefaultDispatchTime::AfterNormalCases,
113
148
ProfileCounter count = ProfileCounter()) {
114
- defaultBlockData.emplace (defaultBlock, contBlock , handle, dispatchTime,
149
+ defaultBlockData.emplace (defaultBlock, branchDest , handle, dispatchTime,
115
150
count);
116
151
}
117
152
118
153
void addCase (EnumElementDecl *decl, SILBasicBlock *caseBlock,
119
- NullablePtr<SILBasicBlock> contBlock , NormalCaseHandler handle,
154
+ SwitchCaseBranchDest branchDest , NormalCaseHandler handle,
120
155
ProfileCounter count = ProfileCounter()) {
121
- caseDataArray.emplace_back (decl, caseBlock, contBlock , handle, count);
156
+ caseDataArray.emplace_back (decl, caseBlock, branchDest , handle, count);
122
157
}
123
158
124
159
void addOptionalSomeCase (SILBasicBlock *caseBlock) {
@@ -138,19 +173,19 @@ class SwitchEnumBuilder {
138
173
}
139
174
140
175
void addOptionalSomeCase (SILBasicBlock *caseBlock,
141
- NullablePtr<SILBasicBlock> contBlock ,
176
+ SwitchCaseBranchDest branchDest ,
142
177
NormalCaseHandler handle,
143
178
ProfileCounter count = ProfileCounter()) {
144
179
auto *decl = getSGF ().getASTContext ().getOptionalSomeDecl ();
145
- caseDataArray.emplace_back (decl, caseBlock, contBlock , handle, count);
180
+ caseDataArray.emplace_back (decl, caseBlock, branchDest , handle, count);
146
181
}
147
182
148
183
void addOptionalNoneCase (SILBasicBlock *caseBlock,
149
- NullablePtr<SILBasicBlock> contBlock ,
184
+ SwitchCaseBranchDest branchDest ,
150
185
NormalCaseHandler handle,
151
186
ProfileCounter count = ProfileCounter()) {
152
187
auto *decl = getSGF ().getASTContext ().getOptionalNoneDecl ();
153
- caseDataArray.emplace_back (decl, caseBlock, contBlock , handle, count);
188
+ caseDataArray.emplace_back (decl, caseBlock, branchDest , handle, count);
154
189
}
155
190
156
191
void emit () &&;
0 commit comments