1 //===- ConstantInitBuilder.h - Builder for LLVM IR constants ----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This class provides a convenient interface for building complex
11 // global initializers of the sort that are frequently required for
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H
17 #define LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H
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"
33 /// A convenience builder class for complex constant initializers,
34 /// especially for anonymous global structures used by various language
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);
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;
57 SelfReference(llvm::GlobalVariable *dummy) : Dummy(dummy) {}
60 llvm::SmallVector<llvm::Constant*, 16> Buffer;
61 std::vector<SelfReference> SelfReferences;
64 friend class ConstantInitFuture;
65 friend class ConstantAggregateBuilderBase;
66 template <class, class>
67 friend class ConstantAggregateBuilderTemplateBase;
70 explicit ConstantInitBuilderBase(CodeGenModule &CGM) : CGM(CGM) {}
72 ~ConstantInitBuilderBase() {
73 assert(Buffer.empty() && "didn't claim all values out of buffer");
74 assert(SelfReferences.empty() && "didn't apply all self-references");
78 llvm::GlobalVariable *createGlobal(llvm::Constant *initializer,
79 const llvm::Twine &name,
81 bool constant = false,
82 llvm::GlobalValue::LinkageTypes linkage
83 = llvm::GlobalValue::InternalLinkage,
84 unsigned addressSpace = 0);
86 ConstantInitFuture createFuture(llvm::Constant *initializer);
88 void setGlobalInitializer(llvm::GlobalVariable *GV,
89 llvm::Constant *initializer);
91 void resolveSelfReferences(llvm::GlobalVariable *GV);
93 void abandon(size_t newEnd);
96 /// A concrete base class for struct and array aggregate
97 /// initializer builders.
98 class ConstantAggregateBuilderBase {
100 ConstantInitBuilderBase &Builder;
101 ConstantAggregateBuilderBase *Parent;
103 mutable size_t CachedOffsetEnd = 0;
104 bool Finished = false;
107 mutable CharUnits CachedOffsetFromGlobal;
109 llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() {
110 return Builder.Buffer;
113 const llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() const {
114 return Builder.Buffer;
117 ConstantAggregateBuilderBase(ConstantInitBuilderBase &builder,
118 ConstantAggregateBuilderBase *parent)
119 : Builder(builder), Parent(parent), Begin(builder.Buffer.size()) {
121 assert(!parent->Frozen && "parent already has child builder active");
122 parent->Frozen = true;
124 assert(!builder.Frozen && "builder already has child builder active");
125 builder.Frozen = true;
129 ~ConstantAggregateBuilderBase() {
130 assert(Finished && "didn't finish aggregate builder");
133 void markFinished() {
134 assert(!Frozen && "child builder still active");
135 assert(!Finished && "builder already finished");
138 assert(Parent->Frozen &&
139 "parent not frozen while child builder active");
140 Parent->Frozen = false;
142 assert(Builder.Frozen &&
143 "builder not frozen while child builder active");
144 Builder.Frozen = false;
150 ConstantAggregateBuilderBase(const ConstantAggregateBuilderBase &) = delete;
151 ConstantAggregateBuilderBase &operator=(const ConstantAggregateBuilderBase &)
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;
163 ConstantAggregateBuilderBase &operator=(ConstantAggregateBuilderBase &&other)
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;
175 /// Return true if no elements have yet been added to this struct or array.
180 /// Abandon this builder completely.
183 Builder.abandon(Begin);
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);
194 /// Add an integer value of type size_t.
195 void addSize(CharUnits size);
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));
203 /// Add a null pointer of a specific type.
204 void addNullPointer(llvm::PointerType *ptrTy) {
205 add(llvm::ConstantPointerNull::get(ptrTy));
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));
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());
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));
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,
237 llvm::Constant *offset = getRelativeOffset(type, address);
239 offset = llvm::ConstantExpr::getAdd(offset,
240 llvm::ConstantInt::get(type, tag));
245 /// Return the offset from the start of the initializer to the
246 /// next position, assuming no padding is required prior to it.
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());
256 /// An opaque class to hold the abstract position of a placeholder.
257 class PlaceholderPosition {
259 friend class ConstantAggregateBuilderBase;
260 PlaceholderPosition(size_t index) : Index(index) {}
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.
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;
279 /// Add a placeholder, giving the expected type that will be filled in.
280 PlaceholderPosition addPlaceholderWithSize(llvm::Type *expectedType);
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));
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");
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.
302 /// The returned pointer will have type T*, where T is the given
304 llvm::Constant *getAddrOfCurrentPosition(llvm::Type *type);
306 llvm::ArrayRef<llvm::Constant*> getGEPIndicesToCurrentPosition(
307 llvm::SmallVectorImpl<llvm::Constant*> &indices) {
308 getGEPIndicesTo(indices, Builder.Buffer.size());
313 llvm::Constant *finishArray(llvm::Type *eltTy);
314 llvm::Constant *finishStruct(llvm::StructType *structTy);
317 void getGEPIndicesTo(llvm::SmallVectorImpl<llvm::Constant*> &indices,
318 size_t position) const;
320 llvm::Constant *getRelativeOffset(llvm::IntegerType *offsetType,
321 llvm::Constant *target);
323 CharUnits getOffsetFromGlobalTo(size_t index) const;
326 template <class Impl, class Traits>
327 class ConstantAggregateBuilderTemplateBase
328 : public Traits::AggregateBuilderBase {
329 using super = typename Traits::AggregateBuilderBase;
331 using InitBuilder = typename Traits::InitBuilder;
332 using ArrayBuilder = typename Traits::ArrayBuilder;
333 using StructBuilder = typename Traits::StructBuilder;
334 using AggregateBuilderBase = typename Traits::AggregateBuilderBase;
337 ConstantAggregateBuilderTemplateBase(InitBuilder &builder,
338 AggregateBuilderBase *parent)
339 : super(builder, parent) {}
341 Impl &asImpl() { return *static_cast<Impl*>(this); }
344 ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) {
345 return ArrayBuilder(static_cast<InitBuilder&>(this->Builder), this, eltTy);
348 StructBuilder beginStruct(llvm::StructType *ty = nullptr) {
349 return StructBuilder(static_cast<InitBuilder&>(this->Builder), this, ty);
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.
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());
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)...);
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());
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
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());
398 template <class Traits>
399 class ConstantArrayBuilderTemplateBase
400 : public ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder,
403 ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder, Traits>;
406 using InitBuilder = typename Traits::InitBuilder;
407 using AggregateBuilderBase = typename Traits::AggregateBuilderBase;
412 template <class, class>
413 friend class ConstantAggregateBuilderTemplateBase;
416 ConstantArrayBuilderTemplateBase(InitBuilder &builder,
417 AggregateBuilderBase *parent,
419 : super(builder, parent), EltTy(eltTy) {}
422 /// Form an array constant from the values that have been added to this
424 llvm::Constant *finishImpl() {
425 return AggregateBuilderBase::finishArray(EltTy);
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,
439 ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder,Traits>;
442 using InitBuilder = typename Traits::InitBuilder;
443 using AggregateBuilderBase = typename Traits::AggregateBuilderBase;
446 llvm::StructType *StructTy;
448 template <class, class>
449 friend class ConstantAggregateBuilderTemplateBase;
452 ConstantStructBuilderTemplateBase(InitBuilder &builder,
453 AggregateBuilderBase *parent,
454 llvm::StructType *structTy)
455 : super(builder, parent), StructTy(structTy) {
456 if (structTy) this->Packed = structTy->isPacked();
460 void setPacked(bool packed) {
461 this->Packed = packed;
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()) {
473 /// Form an array constant from the values that have been added to this
475 llvm::Constant *finishImpl() {
476 return AggregateBuilderBase::finishStruct(StructTy);
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 {
488 ConstantInitBuilderTemplateBase(CodeGenModule &CGM)
489 : ConstantInitBuilderBase(CGM) {}
492 using InitBuilder = typename Traits::InitBuilder;
493 using ArrayBuilder = typename Traits::ArrayBuilder;
494 using StructBuilder = typename Traits::StructBuilder;
496 ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) {
497 return ArrayBuilder(static_cast<InitBuilder&>(*this), nullptr, eltTy);
500 StructBuilder beginStruct(llvm::StructType *structTy = nullptr) {
501 return StructBuilder(static_cast<InitBuilder&>(*this), nullptr, structTy);
505 class ConstantInitBuilder;
506 class ConstantStructBuilder;
507 class ConstantArrayBuilder;
509 struct ConstantInitBuilderTraits {
510 using InitBuilder = ConstantInitBuilder;
511 using AggregateBuilderBase = ConstantAggregateBuilderBase;
512 using ArrayBuilder = ConstantArrayBuilder;
513 using StructBuilder = ConstantStructBuilder;
516 /// The standard implementation of ConstantInitBuilder used in Clang.
517 class ConstantInitBuilder
518 : public ConstantInitBuilderTemplateBase<ConstantInitBuilderTraits> {
520 explicit ConstantInitBuilder(CodeGenModule &CGM) :
521 ConstantInitBuilderTemplateBase(CGM) {}
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;
531 // The use of explicit qualification is a GCC workaround.
532 template <class Impl, class Traits>
533 friend class CodeGen::ConstantAggregateBuilderTemplateBase;
535 ConstantArrayBuilder(ConstantInitBuilder &builder,
536 ConstantAggregateBuilderBase *parent,
538 : ConstantArrayBuilderTemplateBase(builder, parent, eltTy) {}
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;
548 // The use of explicit qualification is a GCC workaround.
549 template <class Impl, class Traits>
550 friend class CodeGen::ConstantAggregateBuilderTemplateBase;
552 ConstantStructBuilder(ConstantInitBuilder &builder,
553 ConstantAggregateBuilderBase *parent,
554 llvm::StructType *structTy)
555 : ConstantStructBuilderTemplateBase(builder, parent, structTy) {}
558 } // end namespace CodeGen
559 } // end namespace clang