@@ -36,6 +36,7 @@ namespace swift {
3636
3737namespace irgen {
3838 using Lowering::AbstractionPattern;
39+ class ConstantInitBuilder ;
3940 using clang::CodeGen::ConstantInitFuture;
4041 class IRGenFunction ;
4142
@@ -166,48 +167,85 @@ enum class SymbolReferenceKind : uint8_t {
166167 Far_Relative_Indirectable,
167168};
168169
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+
169177// / An initial value for a definition of an llvm::GlobalVariable.
170178class 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+
172188public:
173189 // / No initializer is given. When this is used as an argument to
174190 // / a getAddrOf... API, it means that only a declaration is being
175191 // / requested.
176- ConstantInit () {}
192+ ConstantInit () : TheKind(Kind::None) {}
177193
178194 // / Use a concrete value as a concrete initializer.
179195 ConstantInit (llvm::Constant *initializer)
180- : Data (ConstantInitFuture(initializer)) {}
196+ : Future (ConstantInitFuture(initializer)), TheKind(Kind::Future ) {}
181197
182198 // / 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) {
184201 assert (future && " don't pass around null futures" );
185202 }
186203
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+
187212 // / There will be a definition (with the given type), but we don't
188213 // / have it yet.
189214 static ConstantInit getDelayed (llvm::Type *type) {
190215 auto result = ConstantInit ();
191- result.Data = type;
216+ result.TheKind = Kind::Delayed;
217+ result.Delayed = type;
192218 return result;
193219 }
194220
195- explicit operator bool () const { return bool (Data) ; }
221+ explicit operator bool () const { return TheKind != Kind::None ; }
196222
197223 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 ;
201229 } else {
202- return Data.get <ConstantInitFuture>().getType ();
230+ assert (TheKind == Kind::Future);
231+ return Future.getType ();
203232 }
204233 }
205234
235+ bool isLazy () const {
236+ return TheKind == Kind::Lazy;
237+ }
238+ const LazyConstantInitializer *getLazy () const {
239+ assert (isLazy ());
240+ return Lazy;
241+ }
242+
206243 bool hasInit () const {
207- return Data. is <ConstantInitFuture>() ;
244+ return TheKind == Kind::Future ;
208245 }
209246 ConstantInitFuture getInit () const {
210- return Data.get <ConstantInitFuture>();
247+ assert (hasInit ());
248+ return Future;
211249 }
212250};
213251
0 commit comments