clang  6.0.0svn
ConstantInitBuilder.h
Go to the documentation of this file.
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"
25 
26 #include <vector>
27 
28 namespace clang {
29 namespace CodeGen {
30 
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);
53  struct SelfReference {
54  llvm::GlobalVariable *Dummy;
56 
57  SelfReference(llvm::GlobalVariable *dummy) : Dummy(dummy) {}
58  };
59  CodeGenModule &CGM;
61  std::vector<SelfReference> SelfReferences;
62  bool Frozen = false;
63 
64  friend class ConstantInitFuture;
66  template <class, class>
68 
69 protected:
70  explicit ConstantInitBuilderBase(CodeGenModule &CGM) : CGM(CGM) {}
71 
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
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.
99 protected:
102  size_t Begin;
103  mutable size_t CachedOffsetEnd = 0;
104  bool Finished = false;
105  bool Frozen = false;
106  bool Packed = false;
108 
110  return Builder.Buffer;
111  }
112 
114  return Builder.Buffer;
115  }
116 
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 
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.
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.
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  }
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.
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.
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.
258  size_t Index;
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.
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.
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 
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>
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:
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.
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.
393  assert(!this->Parent && "finishing non-root builder");
394  return this->Builder.createFuture(asImpl().finishImpl());
395  }
396 };
397 
398 template <class Traits>
400  : public ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder,
401  Traits> {
402  using super =
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>
414 
415 protected:
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>
436  : public ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder,
437  Traits> {
438  using super =
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>
450 
451 protected:
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>
487 protected:
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;
508 
514 };
515 
516 /// The standard implementation of ConstantInitBuilder used in Clang.
518  : public ConstantInitBuilderTemplateBase<ConstantInitBuilderTraits> {
519 public:
522 };
523 
524 /// A helper class of ConstantInitBuilder, used for building constant
525 /// array initializers.
527  : public ConstantArrayBuilderTemplateBase<ConstantInitBuilderTraits> {
528  template <class Traits>
530 
531  // The use of explicit qualification is a GCC workaround.
532  template <class Impl, class Traits>
534 
537  llvm::Type *eltTy)
538  : ConstantArrayBuilderTemplateBase(builder, parent, eltTy) {}
539 };
540 
541 /// A helper class of ConstantInitBuilder, used for building constant
542 /// struct initializers.
544  : public ConstantStructBuilderTemplateBase<ConstantInitBuilderTraits> {
545  template <class Traits>
547 
548  // The use of explicit qualification is a GCC workaround.
549  template <class Impl, class Traits>
551 
554  llvm::StructType *structTy)
555  : ConstantStructBuilderTemplateBase(builder, parent, structTy) {}
556 };
557 
558 } // end namespace CodeGen
559 } // end namespace clang
560 
561 #endif
A template class designed to allow other frontends to easily customize the builder classes used by Co...
void abandon()
Abandon this builder completely.
ConstantInitFuture finishAndCreateFuture()
Given that this builder was created by beginning an array or struct directly on a ConstantInitBuilder...
size_t size() const
Return the number of elements that have been added to this struct or array.
The standard implementation of ConstantInitBuilder used in Clang.
CharUnits getNextOffsetFromGlobal() const
Return the offset from the start of the initializer to the next position, assuming no padding is requ...
llvm::GlobalVariable * finishAndCreateGlobal(As &&...args)
Given that this builder was created by beginning an array or struct directly on a ConstantInitBuilder...
ConstantAggregateBuilderBase(ConstantAggregateBuilderBase &&other)
void addBitCast(llvm::Constant *value, llvm::Type *type)
Add a bitcast of a value to a specific type.
PlaceholderPosition addPlaceholder()
Add a placeholder value to the structure.
CharUnits - This is an opaque type for sizes expressed in character units.
Definition: CharUnits.h:38
A template class designed to allow other frontends to easily customize the builder classes used by Co...
void addNullPointer(llvm::PointerType *ptrTy)
Add a null pointer of a specific type.
void suggestType(llvm::StructType *structTy)
Use the given type for the struct if its element count is correct.
NodeId Parent
Definition: ASTDiff.cpp:192
ArrayBuilder beginArray(llvm::Type *eltTy=nullptr)
void fillPlaceholder(PlaceholderPosition position, llvm::Constant *value)
Fill a previously-added placeholder.
SourceLocation Begin
void add(llvm::Constant *value)
Add a new value to this initializer.
ConstantArrayBuilderTemplateBase(InitBuilder &builder, AggregateBuilderBase *parent, llvm::Type *eltTy)
void finishAndAddTo(AggregateBuilderBase &parent)
Given that this builder was created by beginning an array or struct component on the given parent bui...
The l-value was considered opaque, so the alignment was determined from a type.
void finishAndSetAsInitializer(llvm::GlobalVariable *global)
Given that this builder was created by beginning an array or struct directly on a ConstantInitBuilder...
void addInt(llvm::IntegerType *intTy, uint64_t value, bool isSigned=false)
Add an integer value of a specific type.
A "future" for a completed constant initializer, which can be passed around independently of any sub-...
const llvm::SmallVectorImpl< llvm::Constant * > & getBuffer() const
This class organizes the cross-function state that is used while generating LLVM code.
StructBuilder beginStruct(llvm::StructType *ty=nullptr)
Dataflow Directional Tag Classes.
llvm::ArrayRef< llvm::Constant * > getGEPIndicesToCurrentPosition(llvm::SmallVectorImpl< llvm::Constant *> &indices)
void addTaggedRelativeOffset(llvm::IntegerType *type, llvm::Constant *address, unsigned tag)
Add a relative offset to the target address, plus a small constant offset.
void addRelativeOffset(llvm::IntegerType *type, llvm::Constant *target)
Add a relative offset to the given target address, i.e.
llvm::SmallVectorImpl< llvm::Constant * > & getBuffer()
StructBuilder beginStruct(llvm::StructType *structTy=nullptr)
Internal linkage, which indicates that the entity can be referred to from within the translation unit...
Definition: Linkage.h:33
void addAll(llvm::ArrayRef< llvm::Constant *> values)
Add a bunch of new values to this initializer.
ArrayBuilder beginArray(llvm::Type *eltTy=nullptr)
void fillPlaceholderWithInt(PlaceholderPosition position, llvm::IntegerType *type, uint64_t value, bool isSigned=false)
Fill a previously-added placeholder.
A helper class of ConstantInitBuilder, used for building constant struct initializers.
A concrete base class for struct and array aggregate initializer builders.
ConstantStructBuilderTemplateBase(InitBuilder &builder, AggregateBuilderBase *parent, llvm::StructType *structTy)
An opaque class to hold the abstract position of a placeholder.
ConstantAggregateBuilderBase(ConstantInitBuilderBase &builder, ConstantAggregateBuilderBase *parent)
ConstantAggregateBuilderTemplateBase(InitBuilder &builder, AggregateBuilderBase *parent)
A helper class of ConstantInitBuilder, used for building constant array initializers.
bool empty() const
Return true if no elements have yet been added to this struct or array.