@@ -36,6 +36,7 @@ namespace swift {
36
36
37
37
namespace irgen {
38
38
using Lowering::AbstractionPattern;
39
+ class ConstantInitBuilder ;
39
40
using clang::CodeGen::ConstantInitFuture;
40
41
class IRGenFunction ;
41
42
@@ -166,48 +167,85 @@ enum class SymbolReferenceKind : uint8_t {
166
167
Far_Relative_Indirectable,
167
168
};
168
169
170
+ // / A lazy constant initializer.
171
+ struct LazyConstantInitializer {
172
+ llvm::Type *DefaultType;
173
+ llvm::function_ref<ConstantInitFuture(ConstantInitBuilder &)> Build;
174
+ llvm::function_ref<void (llvm::GlobalVariable *)> Create;
175
+ };
176
+
169
177
// / An initial value for a definition of an llvm::GlobalVariable.
170
178
class ConstantInit {
171
- llvm::PointerUnion<ConstantInitFuture, llvm::Type*> Data;
179
+ union {
180
+ ConstantInitFuture Future;
181
+ const LazyConstantInitializer *Lazy;
182
+ llvm::Type *Delayed;
183
+ };
184
+ enum class Kind {
185
+ None, Future, Lazy, Delayed
186
+ } TheKind;
187
+
172
188
public:
173
189
// / No initializer is given. When this is used as an argument to
174
190
// / a getAddrOf... API, it means that only a declaration is being
175
191
// / requested.
176
- ConstantInit () {}
192
+ ConstantInit () : TheKind(Kind::None) {}
177
193
178
194
// / Use a concrete value as a concrete initializer.
179
195
ConstantInit (llvm::Constant *initializer)
180
- : Data (ConstantInitFuture(initializer)) {}
196
+ : Future (ConstantInitFuture(initializer)), TheKind(Kind::Future ) {}
181
197
182
198
// / Use a ConstantInitBuilder future as a concrete initializer.
183
- /* implicit*/ ConstantInit(ConstantInitFuture future) : Data(future) {
199
+ /* implicit*/ ConstantInit(ConstantInitFuture future)
200
+ : Future(future), TheKind(Kind::Future) {
184
201
assert (future && " don't pass around null futures" );
185
202
}
186
203
204
+ static ConstantInit getLazy (const LazyConstantInitializer *initializer) {
205
+ assert (initializer && " null lazy initializer" );
206
+ auto result = ConstantInit ();
207
+ result.TheKind = Kind::Lazy;
208
+ result.Lazy = initializer;
209
+ return result;
210
+ }
211
+
187
212
// / There will be a definition (with the given type), but we don't
188
213
// / have it yet.
189
214
static ConstantInit getDelayed (llvm::Type *type) {
190
215
auto result = ConstantInit ();
191
- result.Data = type;
216
+ result.TheKind = Kind::Delayed;
217
+ result.Delayed = type;
192
218
return result;
193
219
}
194
220
195
- explicit operator bool () const { return bool (Data) ; }
221
+ explicit operator bool () const { return TheKind != Kind::None ; }
196
222
197
223
inline llvm::Type *getType () const {
198
- assert (Data && " not a definition" );
199
- if (auto type = Data.dyn_cast <llvm::Type*>()) {
200
- return type;
224
+ assert (TheKind != Kind::None && " not a definition" );
225
+ if (TheKind == Kind::Delayed) {
226
+ return Delayed;
227
+ } else if (TheKind == Kind::Lazy) {
228
+ return Lazy->DefaultType ;
201
229
} else {
202
- return Data.get <ConstantInitFuture>().getType ();
230
+ assert (TheKind == Kind::Future);
231
+ return Future.getType ();
203
232
}
204
233
}
205
234
235
+ bool isLazy () const {
236
+ return TheKind == Kind::Lazy;
237
+ }
238
+ const LazyConstantInitializer *getLazy () const {
239
+ assert (isLazy ());
240
+ return Lazy;
241
+ }
242
+
206
243
bool hasInit () const {
207
- return Data. is <ConstantInitFuture>() ;
244
+ return TheKind == Kind::Future ;
208
245
}
209
246
ConstantInitFuture getInit () const {
210
- return Data.get <ConstantInitFuture>();
247
+ assert (hasInit ());
248
+ return Future;
211
249
}
212
250
};
213
251
0 commit comments