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