]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/CodeGen/ConstantInitBuilder.h
Merge clang trunk r300422 and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / CodeGen / ConstantInitBuilder.h
1 //===- ConstantInitBuilder.h - Builder for LLVM IR constants ----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This class provides a convenient interface for building complex
11 // global initializers of the sort that are frequently required for
12 // language ABIs.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #ifndef LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H
17 #define LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H
18
19 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/IR/Constants.h"
22 #include "llvm/IR/GlobalValue.h"
23 #include "clang/AST/CharUnits.h"
24 #include "clang/CodeGen/ConstantInitFuture.h"
25
26 #include <vector>
27
28 namespace clang {
29 namespace CodeGen {
30
31 class CodeGenModule;
32
33 /// A convenience builder class for complex constant initializers,
34 /// especially for anonymous global structures used by various language
35 /// runtimes.
36 ///
37 /// The basic usage pattern is expected to be something like:
38 ///    ConstantInitBuilder builder(CGM);
39 ///    auto toplevel = builder.beginStruct();
40 ///    toplevel.addInt(CGM.SizeTy, widgets.size());
41 ///    auto widgetArray = builder.beginArray();
42 ///    for (auto &widget : widgets) {
43 ///      auto widgetDesc = widgetArray.beginStruct();
44 ///      widgetDesc.addInt(CGM.SizeTy, widget.getPower());
45 ///      widgetDesc.add(CGM.GetAddrOfConstantString(widget.getName()));
46 ///      widgetDesc.add(CGM.GetAddrOfGlobal(widget.getInitializerDecl()));
47 ///      widgetDesc.finishAndAddTo(widgetArray);
48 ///    }
49 ///    widgetArray.finishAndAddTo(toplevel);
50 ///    auto global = toplevel.finishAndCreateGlobal("WIDGET_LIST", Align,
51 ///                                                 /*constant*/ true);
52 class ConstantInitBuilderBase {
53   struct SelfReference {
54     llvm::GlobalVariable *Dummy;
55     llvm::SmallVector<llvm::Constant*, 4> Indices;
56
57     SelfReference(llvm::GlobalVariable *dummy) : Dummy(dummy) {}
58   };
59   CodeGenModule &CGM;
60   llvm::SmallVector<llvm::Constant*, 16> Buffer;
61   std::vector<SelfReference> SelfReferences;
62   bool Frozen = false;
63
64   friend class ConstantInitFuture;
65   friend class ConstantAggregateBuilderBase;
66   template <class, class>
67   friend class ConstantAggregateBuilderTemplateBase;
68
69 protected:
70   explicit ConstantInitBuilderBase(CodeGenModule &CGM) : CGM(CGM) {}
71
72   ~ConstantInitBuilderBase() {
73     assert(Buffer.empty() && "didn't claim all values out of buffer");
74     assert(SelfReferences.empty() && "didn't apply all self-references");
75   }
76
77 private:
78   llvm::GlobalVariable *createGlobal(llvm::Constant *initializer,
79                                      const llvm::Twine &name,
80                                      CharUnits alignment,
81                                      bool constant = false,
82                                      llvm::GlobalValue::LinkageTypes linkage
83                                        = llvm::GlobalValue::InternalLinkage,
84                                      unsigned addressSpace = 0);
85
86   ConstantInitFuture createFuture(llvm::Constant *initializer);
87
88   void setGlobalInitializer(llvm::GlobalVariable *GV,
89                             llvm::Constant *initializer);
90
91   void resolveSelfReferences(llvm::GlobalVariable *GV);
92
93   void abandon(size_t newEnd);
94 };
95
96 /// A concrete base class for struct and array aggregate
97 /// initializer builders.
98 class ConstantAggregateBuilderBase {
99 protected:
100   ConstantInitBuilderBase &Builder;
101   ConstantAggregateBuilderBase *Parent;
102   size_t Begin;
103   mutable size_t CachedOffsetEnd = 0;
104   bool Finished = false;
105   bool Frozen = false;
106   bool Packed = false;
107   mutable CharUnits CachedOffsetFromGlobal;
108
109   llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() {
110     return Builder.Buffer;
111   }
112
113   const llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() const {
114     return Builder.Buffer;
115   }
116
117   ConstantAggregateBuilderBase(ConstantInitBuilderBase &builder,
118                                ConstantAggregateBuilderBase *parent)
119       : Builder(builder), Parent(parent), Begin(builder.Buffer.size()) {
120     if (parent) {
121       assert(!parent->Frozen && "parent already has child builder active");
122       parent->Frozen = true;
123     } else {
124       assert(!builder.Frozen && "builder already has child builder active");
125       builder.Frozen = true;
126     }
127   }
128
129   ~ConstantAggregateBuilderBase() {
130     assert(Finished && "didn't finish aggregate builder");
131   }
132
133   void markFinished() {
134     assert(!Frozen && "child builder still active");
135     assert(!Finished && "builder already finished");
136     Finished = true;
137     if (Parent) {
138       assert(Parent->Frozen &&
139              "parent not frozen while child builder active");
140       Parent->Frozen = false;
141     } else {
142       assert(Builder.Frozen &&
143              "builder not frozen while child builder active");
144       Builder.Frozen = false;
145     }
146   }
147
148 public:
149   // Not copyable.
150   ConstantAggregateBuilderBase(const ConstantAggregateBuilderBase &) = delete;
151   ConstantAggregateBuilderBase &operator=(const ConstantAggregateBuilderBase &)
152     = delete;
153
154   // Movable, mostly to allow returning.  But we have to write this out
155   // properly to satisfy the assert in the destructor.
156   ConstantAggregateBuilderBase(ConstantAggregateBuilderBase &&other)
157     : Builder(other.Builder), Parent(other.Parent), Begin(other.Begin),
158       CachedOffsetEnd(other.CachedOffsetEnd),
159       Finished(other.Finished), Frozen(other.Frozen), Packed(other.Packed),
160       CachedOffsetFromGlobal(other.CachedOffsetFromGlobal) {
161     other.Finished = true;
162   }
163   ConstantAggregateBuilderBase &operator=(ConstantAggregateBuilderBase &&other)
164     = delete;
165
166   /// Return the number of elements that have been added to
167   /// this struct or array.
168   size_t size() const {
169     assert(!this->Finished && "cannot query after finishing builder");
170     assert(!this->Frozen && "cannot query while sub-builder is active");
171     assert(this->Begin <= this->getBuffer().size());
172     return this->getBuffer().size() - this->Begin;
173   }
174
175   /// Return true if no elements have yet been added to this struct or array.
176   bool empty() const {
177     return size() == 0;
178   }
179
180   /// Abandon this builder completely.
181   void abandon() {
182     markFinished();
183     Builder.abandon(Begin);
184   }
185
186   /// Add a new value to this initializer.
187   void add(llvm::Constant *value) {
188     assert(value && "adding null value to constant initializer");
189     assert(!Finished && "cannot add more values after finishing builder");
190     assert(!Frozen && "cannot add values while subbuilder is active");
191     Builder.Buffer.push_back(value);
192   }
193
194   /// Add an integer value of type size_t.
195   void addSize(CharUnits size);
196
197   /// Add an integer value of a specific type.
198   void addInt(llvm::IntegerType *intTy, uint64_t value,
199               bool isSigned = false) {
200     add(llvm::ConstantInt::get(intTy, value, isSigned));
201   }
202
203   /// Add a null pointer of a specific type.
204   void addNullPointer(llvm::PointerType *ptrTy) {
205     add(llvm::ConstantPointerNull::get(ptrTy));
206   }
207
208   /// Add a bitcast of a value to a specific type.
209   void addBitCast(llvm::Constant *value, llvm::Type *type) {
210     add(llvm::ConstantExpr::getBitCast(value, type));
211   }
212
213   /// Add a bunch of new values to this initializer.
214   void addAll(llvm::ArrayRef<llvm::Constant *> values) {
215     assert(!Finished && "cannot add more values after finishing builder");
216     assert(!Frozen && "cannot add values while subbuilder is active");
217     Builder.Buffer.append(values.begin(), values.end());
218   }
219
220   /// Add a relative offset to the given target address, i.e. the
221   /// static difference between the target address and the address
222   /// of the relative offset.  The target must be known to be defined
223   /// in the current linkage unit.  The offset will have the given
224   /// integer type, which must be no wider than intptr_t.  Some
225   /// targets may not fully support this operation.
226   void addRelativeOffset(llvm::IntegerType *type, llvm::Constant *target) {
227     add(getRelativeOffset(type, target));
228   }
229
230   /// Add a relative offset to the target address, plus a small
231   /// constant offset.  This is primarily useful when the relative
232   /// offset is known to be a multiple of (say) four and therefore
233   /// the tag can be used to express an extra two bits of information.
234   void addTaggedRelativeOffset(llvm::IntegerType *type,
235                                llvm::Constant *address,
236                                unsigned tag) {
237     llvm::Constant *offset = getRelativeOffset(type, address);
238     if (tag) {
239       offset = llvm::ConstantExpr::getAdd(offset,
240                                           llvm::ConstantInt::get(type, tag));
241     }
242     add(offset);
243   }
244
245   /// Return the offset from the start of the initializer to the
246   /// next position, assuming no padding is required prior to it.
247   ///
248   /// This operation will not succeed if any unsized placeholders are
249   /// currently in place in the initializer.
250   CharUnits getNextOffsetFromGlobal() const {
251     assert(!Finished && "cannot add more values after finishing builder");
252     assert(!Frozen && "cannot add values while subbuilder is active");
253     return getOffsetFromGlobalTo(Builder.Buffer.size());
254   }
255
256   /// An opaque class to hold the abstract position of a placeholder.
257   class PlaceholderPosition {
258     size_t Index;
259     friend class ConstantAggregateBuilderBase;
260     PlaceholderPosition(size_t index) : Index(index) {}
261   };
262
263   /// Add a placeholder value to the structure.  The returned position
264   /// can be used to set the value later; it will not be invalidated by
265   /// any intermediate operations except (1) filling the same position or
266   /// (2) finishing the entire builder.
267   ///
268   /// This is useful for emitting certain kinds of structure which
269   /// contain some sort of summary field, generaly a count, before any
270   /// of the data.  By emitting a placeholder first, the structure can
271   /// be emitted eagerly.
272   PlaceholderPosition addPlaceholder() {
273     assert(!Finished && "cannot add more values after finishing builder");
274     assert(!Frozen && "cannot add values while subbuilder is active");
275     Builder.Buffer.push_back(nullptr);
276     return Builder.Buffer.size() - 1;
277   }
278
279   /// Add a placeholder, giving the expected type that will be filled in.
280   PlaceholderPosition addPlaceholderWithSize(llvm::Type *expectedType);
281
282   /// Fill a previously-added placeholder.
283   void fillPlaceholderWithInt(PlaceholderPosition position,
284                               llvm::IntegerType *type, uint64_t value,
285                               bool isSigned = false) {
286     fillPlaceholder(position, llvm::ConstantInt::get(type, value, isSigned));
287   }
288
289   /// Fill a previously-added placeholder.
290   void fillPlaceholder(PlaceholderPosition position, llvm::Constant *value) {
291     assert(!Finished && "cannot change values after finishing builder");
292     assert(!Frozen && "cannot add values while subbuilder is active");
293     llvm::Constant *&slot = Builder.Buffer[position.Index];
294     assert(slot == nullptr && "placeholder already filled");
295     slot = value;
296   }
297
298   /// Produce an address which will eventually point to the the next
299   /// position to be filled.  This is computed with an indexed
300   /// getelementptr rather than by computing offsets.
301   ///
302   /// The returned pointer will have type T*, where T is the given
303   /// position.
304   llvm::Constant *getAddrOfCurrentPosition(llvm::Type *type);
305
306   llvm::ArrayRef<llvm::Constant*> getGEPIndicesToCurrentPosition(
307                            llvm::SmallVectorImpl<llvm::Constant*> &indices) {
308     getGEPIndicesTo(indices, Builder.Buffer.size());
309     return indices;
310   }
311
312 protected:
313   llvm::Constant *finishArray(llvm::Type *eltTy);
314   llvm::Constant *finishStruct(llvm::StructType *structTy);
315
316 private:
317   void getGEPIndicesTo(llvm::SmallVectorImpl<llvm::Constant*> &indices,
318                        size_t position) const;
319
320   llvm::Constant *getRelativeOffset(llvm::IntegerType *offsetType,
321                                     llvm::Constant *target);
322
323   CharUnits getOffsetFromGlobalTo(size_t index) const;
324 };
325
326 template <class Impl, class Traits>
327 class ConstantAggregateBuilderTemplateBase
328     : public Traits::AggregateBuilderBase {
329   using super = typename Traits::AggregateBuilderBase;
330 public:
331   using InitBuilder = typename Traits::InitBuilder;
332   using ArrayBuilder = typename Traits::ArrayBuilder;
333   using StructBuilder = typename Traits::StructBuilder;
334   using AggregateBuilderBase = typename Traits::AggregateBuilderBase;
335
336 protected:
337   ConstantAggregateBuilderTemplateBase(InitBuilder &builder,
338                                        AggregateBuilderBase *parent)
339     : super(builder, parent) {}
340
341   Impl &asImpl() { return *static_cast<Impl*>(this); }
342
343 public:
344   ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) {
345     return ArrayBuilder(static_cast<InitBuilder&>(this->Builder), this, eltTy);
346   }
347
348   StructBuilder beginStruct(llvm::StructType *ty = nullptr) {
349     return StructBuilder(static_cast<InitBuilder&>(this->Builder), this, ty);
350   }
351
352   /// Given that this builder was created by beginning an array or struct
353   /// component on the given parent builder, finish the array/struct
354   /// component and add it to the parent.
355   ///
356   /// It is an intentional choice that the parent is passed in explicitly
357   /// despite it being redundant with information already kept in the
358   /// builder.  This aids in readability by making it easier to find the
359   /// places that add components to a builder, as well as "bookending"
360   /// the sub-builder more explicitly.
361   void finishAndAddTo(AggregateBuilderBase &parent) {
362     assert(this->Parent == &parent && "adding to non-parent builder");
363     parent.add(asImpl().finishImpl());
364   }
365
366   /// Given that this builder was created by beginning an array or struct
367   /// directly on a ConstantInitBuilder, finish the array/struct and
368   /// create a global variable with it as the initializer.
369   template <class... As>
370   llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) {
371     assert(!this->Parent && "finishing non-root builder");
372     return this->Builder.createGlobal(asImpl().finishImpl(),
373                                       std::forward<As>(args)...);
374   }
375
376   /// Given that this builder was created by beginning an array or struct
377   /// directly on a ConstantInitBuilder, finish the array/struct and
378   /// set it as the initializer of the given global variable.
379   void finishAndSetAsInitializer(llvm::GlobalVariable *global) {
380     assert(!this->Parent && "finishing non-root builder");
381     return this->Builder.setGlobalInitializer(global, asImpl().finishImpl());
382   }
383
384   /// Given that this builder was created by beginning an array or struct
385   /// directly on a ConstantInitBuilder, finish the array/struct and
386   /// return a future which can be used to install the initializer in
387   /// a global later.
388   ///
389   /// This is useful for allowing a finished initializer to passed to
390   /// an API which will build the global.  However, the "future" preserves
391   /// a dependency on the original builder; it is an error to pass it aside.
392   ConstantInitFuture finishAndCreateFuture() {
393     assert(!this->Parent && "finishing non-root builder");
394     return this->Builder.createFuture(asImpl().finishImpl());
395   }
396 };
397
398 template <class Traits>
399 class ConstantArrayBuilderTemplateBase
400   : public ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder,
401                                                 Traits> {
402   using super =
403     ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder, Traits>;
404
405 public:
406   using InitBuilder = typename Traits::InitBuilder;
407   using AggregateBuilderBase = typename Traits::AggregateBuilderBase;
408
409 private:
410   llvm::Type *EltTy;
411
412   template <class, class>
413   friend class ConstantAggregateBuilderTemplateBase;
414
415 protected:
416   ConstantArrayBuilderTemplateBase(InitBuilder &builder,
417                                    AggregateBuilderBase *parent,
418                                    llvm::Type *eltTy)
419     : super(builder, parent), EltTy(eltTy) {}
420
421 private:
422   /// Form an array constant from the values that have been added to this
423   /// builder.
424   llvm::Constant *finishImpl() {
425     return AggregateBuilderBase::finishArray(EltTy);
426   }
427 };
428
429 /// A template class designed to allow other frontends to
430 /// easily customize the builder classes used by ConstantInitBuilder,
431 /// and thus to extend the API to work with the abstractions they
432 /// prefer.  This would probably not be necessary if C++ just
433 /// supported extension methods.
434 template <class Traits>
435 class ConstantStructBuilderTemplateBase
436   : public ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder,
437                                                 Traits> {
438   using super =
439     ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder,Traits>;
440
441 public:
442   using InitBuilder = typename Traits::InitBuilder;
443   using AggregateBuilderBase = typename Traits::AggregateBuilderBase;
444
445 private:
446   llvm::StructType *StructTy;
447
448   template <class, class>
449   friend class ConstantAggregateBuilderTemplateBase;
450
451 protected:
452   ConstantStructBuilderTemplateBase(InitBuilder &builder,
453                                     AggregateBuilderBase *parent,
454                                     llvm::StructType *structTy)
455     : super(builder, parent), StructTy(structTy) {
456     if (structTy) this->Packed = structTy->isPacked();
457   }
458
459 public:
460   void setPacked(bool packed) {
461     this->Packed = packed;
462   }
463
464   /// Use the given type for the struct if its element count is correct.
465   /// Don't add more elements after calling this.
466   void suggestType(llvm::StructType *structTy) {
467     if (this->size() == structTy->getNumElements()) {
468       StructTy = structTy;
469     }
470   }
471
472 private:
473   /// Form an array constant from the values that have been added to this
474   /// builder.
475   llvm::Constant *finishImpl() {
476     return AggregateBuilderBase::finishStruct(StructTy);
477   }
478 };
479
480 /// A template class designed to allow other frontends to
481 /// easily customize the builder classes used by ConstantInitBuilder,
482 /// and thus to extend the API to work with the abstractions they
483 /// prefer.  This would probably not be necessary if C++ just
484 /// supported extension methods.
485 template <class Traits>
486 class ConstantInitBuilderTemplateBase : public ConstantInitBuilderBase {
487 protected:
488   ConstantInitBuilderTemplateBase(CodeGenModule &CGM)
489     : ConstantInitBuilderBase(CGM) {}
490
491 public:
492   using InitBuilder = typename Traits::InitBuilder;
493   using ArrayBuilder = typename Traits::ArrayBuilder;
494   using StructBuilder = typename Traits::StructBuilder;
495
496   ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) {
497     return ArrayBuilder(static_cast<InitBuilder&>(*this), nullptr, eltTy);
498   }
499
500   StructBuilder beginStruct(llvm::StructType *structTy = nullptr) {
501     return StructBuilder(static_cast<InitBuilder&>(*this), nullptr, structTy);
502   }
503 };
504
505 class ConstantInitBuilder;
506 class ConstantStructBuilder;
507 class ConstantArrayBuilder;
508
509 struct ConstantInitBuilderTraits {
510   using InitBuilder = ConstantInitBuilder;
511   using AggregateBuilderBase = ConstantAggregateBuilderBase;
512   using ArrayBuilder = ConstantArrayBuilder;
513   using StructBuilder = ConstantStructBuilder;
514 };
515
516 /// The standard implementation of ConstantInitBuilder used in Clang.
517 class ConstantInitBuilder
518     : public ConstantInitBuilderTemplateBase<ConstantInitBuilderTraits> {
519 public:
520   explicit ConstantInitBuilder(CodeGenModule &CGM) :
521     ConstantInitBuilderTemplateBase(CGM) {}
522 };
523
524 /// A helper class of ConstantInitBuilder, used for building constant
525 /// array initializers.
526 class ConstantArrayBuilder
527     : public ConstantArrayBuilderTemplateBase<ConstantInitBuilderTraits> {
528   template <class Traits>
529   friend class ConstantInitBuilderTemplateBase;
530
531   // The use of explicit qualification is a GCC workaround.
532   template <class Impl, class Traits>
533   friend class CodeGen::ConstantAggregateBuilderTemplateBase;
534
535   ConstantArrayBuilder(ConstantInitBuilder &builder,
536                        ConstantAggregateBuilderBase *parent,
537                        llvm::Type *eltTy)
538     : ConstantArrayBuilderTemplateBase(builder, parent, eltTy) {}
539 };
540
541 /// A helper class of ConstantInitBuilder, used for building constant
542 /// struct initializers.
543 class ConstantStructBuilder
544     : public ConstantStructBuilderTemplateBase<ConstantInitBuilderTraits> {
545   template <class Traits>
546   friend class ConstantInitBuilderTemplateBase;
547
548   // The use of explicit qualification is a GCC workaround.
549   template <class Impl, class Traits>
550   friend class CodeGen::ConstantAggregateBuilderTemplateBase;
551
552   ConstantStructBuilder(ConstantInitBuilder &builder,
553                         ConstantAggregateBuilderBase *parent,
554                         llvm::StructType *structTy)
555     : ConstantStructBuilderTemplateBase(builder, parent, structTy) {}
556 };
557
558 }  // end namespace CodeGen
559 }  // end namespace clang
560
561 #endif