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" 53 struct SelfReference {
54 llvm::GlobalVariable *Dummy;
57 SelfReference(llvm::GlobalVariable *dummy) : Dummy(dummy) {}
61 std::vector<SelfReference> SelfReferences;
66 template <
class,
class>
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
84 unsigned addressSpace = 0);
88 void setGlobalInitializer(llvm::GlobalVariable *GV,
89 llvm::Constant *initializer);
91 void resolveSelfReferences(llvm::GlobalVariable *GV);
93 void abandon(
size_t newEnd);
103 mutable size_t CachedOffsetEnd = 0;
104 bool Finished =
false;
110 return Builder.Buffer;
114 return Builder.Buffer;
119 : Builder(builder), Parent(parent), Begin(builder.Buffer.size()) {
121 assert(!parent->
Frozen &&
"parent already has child builder active");
124 assert(!builder.Frozen &&
"builder already has child builder active");
125 builder.Frozen =
true;
130 assert(Finished &&
"didn't finish aggregate builder");
134 assert(!Frozen &&
"child builder still active");
135 assert(!Finished &&
"builder already finished");
139 "parent not frozen while child builder active");
142 assert(Builder.Frozen &&
143 "builder not frozen while child builder active");
144 Builder.Frozen =
false;
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;
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;
183 Builder.abandon(Begin);
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);
198 void addInt(llvm::IntegerType *intTy, uint64_t value,
199 bool isSigned =
false) {
200 add(llvm::ConstantInt::get(intTy, value, isSigned));
205 add(llvm::ConstantPointerNull::get(ptrTy));
210 add(llvm::ConstantExpr::getBitCast(value, type));
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());
227 add(getRelativeOffset(type, target));
235 llvm::Constant *address,
237 llvm::Constant *offset = getRelativeOffset(type, address);
239 offset = llvm::ConstantExpr::getAdd(offset,
240 llvm::ConstantInt::get(type, tag));
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());
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;
284 llvm::IntegerType *
type, uint64_t value,
285 bool isSigned =
false) {
286 fillPlaceholder(position, llvm::ConstantInt::get(type, value, isSigned));
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");
308 getGEPIndicesTo(indices, Builder.Buffer.size());
313 llvm::Constant *finishArray(
llvm::Type *eltTy);
314 llvm::Constant *finishStruct(llvm::StructType *structTy);
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>
328 :
public Traits::AggregateBuilderBase {
329 using super =
typename Traits::AggregateBuilderBase;
339 : super(builder, parent) {}
341 Impl &
asImpl() {
return *
static_cast<Impl*
>(
this); }
345 return ArrayBuilder(static_cast<InitBuilder&>(this->Builder),
this, eltTy);
349 return StructBuilder(static_cast<InitBuilder&>(this->Builder),
this, ty);
362 assert(this->
Parent == &parent &&
"adding to non-parent builder");
363 parent.add(asImpl().finishImpl());
369 template <
class... As>
371 assert(!this->
Parent &&
"finishing non-root builder");
372 return this->Builder.createGlobal(asImpl().finishImpl(),
373 std::forward<As>(args)...);
380 assert(!this->
Parent &&
"finishing non-root builder");
381 return this->Builder.setGlobalInitializer(global, asImpl().finishImpl());
393 assert(!this->
Parent &&
"finishing non-root builder");
394 return this->Builder.createFuture(asImpl().finishImpl());
398 template <
class Traits>
412 template <
class,
class>
419 : super(builder, parent), EltTy(eltTy) {}
424 llvm::Constant *finishImpl() {
425 return AggregateBuilderBase::finishArray(EltTy);
434 template <
class Traits>
446 llvm::StructType *StructTy;
448 template <
class,
class>
454 llvm::StructType *structTy)
455 : super(builder, parent), StructTy(structTy) {
456 if (structTy) this->Packed = structTy->isPacked();
461 this->Packed = packed;
467 if (this->size() == structTy->getNumElements()) {
475 llvm::Constant *finishImpl() {
476 return AggregateBuilderBase::finishStruct(StructTy);
485 template <
class Traits>
497 return ArrayBuilder(static_cast<InitBuilder&>(*
this),
nullptr, eltTy);
501 return StructBuilder(static_cast<InitBuilder&>(*
this),
nullptr, structTy);
528 template <
class Traits>
532 template <
class Impl,
class Traits>
545 template <
class Traits>
549 template <
class Impl,
class Traits>
554 llvm::StructType *structTy)
A template class designed to allow other frontends to easily customize the builder classes used by Co...
typename ConstantInitBuilderTraits ::StructBuilder StructBuilder
ConstantInitBuilderBase(CodeGenModule &CGM)
typename ConstantInitBuilderTraits ::InitBuilder InitBuilder
void abandon()
Abandon this builder completely.
friend class ConstantAggregateBuilderBase
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.
~ConstantInitBuilderBase()
CharUnits - This is an opaque type for sizes expressed in character units.
A template class designed to allow other frontends to easily customize the builder classes used by Co...
void setPacked(bool packed)
void addNullPointer(llvm::PointerType *ptrTy)
Add a null pointer of a specific type.
typename ConstantInitBuilderTraits ::StructBuilder StructBuilder
void suggestType(llvm::StructType *structTy)
Use the given type for the struct if its element count is correct.
typename ConstantInitBuilderTraits ::ArrayBuilder ArrayBuilder
ArrayBuilder beginArray(llvm::Type *eltTy=nullptr)
void fillPlaceholder(PlaceholderPosition position, llvm::Constant *value)
Fill a previously-added placeholder.
typename ConstantInitBuilderTraits ::AggregateBuilderBase AggregateBuilderBase
typename ConstantInitBuilderTraits ::InitBuilder InitBuilder
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.
ConstantAggregateBuilderBase * Parent
CharUnits CachedOffsetFromGlobal
A "future" for a completed constant initializer, which can be passed around independently of any sub-...
const llvm::SmallVectorImpl< llvm::Constant * > & getBuffer() const
typename ConstantInitBuilderTraits ::ArrayBuilder ArrayBuilder
~ConstantAggregateBuilderBase()
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.
ConstantInitBuilderTemplateBase(CodeGenModule &CGM)
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...
void addAll(llvm::ArrayRef< llvm::Constant *> values)
Add a bunch of new values to this initializer.
ConstantInitBuilder(CodeGenModule &CGM)
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.
ConstantInitBuilderBase & Builder
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.