15 #ifndef LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H 16 #define LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H 18 #include "llvm/ADT/ArrayRef.h" 19 #include "llvm/ADT/SmallVector.h" 20 #include "llvm/IR/Constants.h" 21 #include "llvm/IR/GlobalValue.h" 52 struct SelfReference {
53 llvm::GlobalVariable *Dummy;
56 SelfReference(llvm::GlobalVariable *dummy) : Dummy(dummy) {}
60 std::vector<SelfReference> SelfReferences;
65 template <
class,
class>
72 assert(Buffer.empty() &&
"didn't claim all values out of buffer");
73 assert(SelfReferences.empty() &&
"didn't apply all self-references");
77 llvm::GlobalVariable *createGlobal(llvm::Constant *initializer,
78 const llvm::Twine &
name,
80 bool constant =
false,
81 llvm::GlobalValue::LinkageTypes linkage
83 unsigned addressSpace = 0);
87 void setGlobalInitializer(llvm::GlobalVariable *GV,
88 llvm::Constant *initializer);
90 void resolveSelfReferences(llvm::GlobalVariable *GV);
92 void abandon(
size_t newEnd);
102 mutable size_t CachedOffsetEnd = 0;
103 bool Finished =
false;
109 return Builder.Buffer;
113 return Builder.Buffer;
118 : Builder(builder), Parent(parent), Begin(builder.Buffer.size()) {
120 assert(!parent->
Frozen &&
"parent already has child builder active");
123 assert(!builder.Frozen &&
"builder already has child builder active");
124 builder.Frozen =
true;
129 assert(Finished &&
"didn't finish aggregate builder");
133 assert(!Frozen &&
"child builder still active");
134 assert(!Finished &&
"builder already finished");
138 "parent not frozen while child builder active");
141 assert(Builder.Frozen &&
142 "builder not frozen while child builder active");
143 Builder.Frozen =
false;
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;
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;
182 Builder.abandon(Begin);
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);
197 void addInt(llvm::IntegerType *intTy, uint64_t value,
198 bool isSigned =
false) {
199 add(llvm::ConstantInt::get(intTy, value, isSigned));
204 add(llvm::ConstantPointerNull::get(ptrTy));
209 add(llvm::ConstantExpr::getBitCast(value, type));
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());
226 add(getRelativeOffset(type, target));
234 llvm::Constant *address,
236 llvm::Constant *offset = getRelativeOffset(type, address);
238 offset = llvm::ConstantExpr::getAdd(offset,
239 llvm::ConstantInt::get(type, tag));
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());
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;
283 llvm::IntegerType *
type, uint64_t value,
284 bool isSigned =
false) {
285 fillPlaceholder(position, llvm::ConstantInt::get(type, value, isSigned));
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");
307 getGEPIndicesTo(indices, Builder.Buffer.size());
312 llvm::Constant *finishArray(
llvm::Type *eltTy);
313 llvm::Constant *finishStruct(llvm::StructType *structTy);
317 size_t position)
const;
319 llvm::Constant *getRelativeOffset(llvm::IntegerType *offsetType,
320 llvm::Constant *target);
322 CharUnits getOffsetFromGlobalTo(
size_t index)
const;
325 template <
class Impl,
class Traits>
327 :
public Traits::AggregateBuilderBase {
328 using super =
typename Traits::AggregateBuilderBase;
338 : super(builder, parent) {}
340 Impl &
asImpl() {
return *
static_cast<Impl*
>(
this); }
344 return ArrayBuilder(static_cast<InitBuilder&>(this->Builder),
this, eltTy);
348 return StructBuilder(static_cast<InitBuilder&>(this->Builder),
this, ty);
361 assert(this->
Parent == &parent &&
"adding to non-parent builder");
362 parent.add(asImpl().finishImpl());
368 template <
class... As>
370 assert(!this->
Parent &&
"finishing non-root builder");
371 return this->Builder.createGlobal(asImpl().finishImpl(),
372 std::forward<As>(args)...);
379 assert(!this->
Parent &&
"finishing non-root builder");
380 return this->Builder.setGlobalInitializer(global, asImpl().finishImpl());
392 assert(!this->
Parent &&
"finishing non-root builder");
393 return this->Builder.createFuture(asImpl().finishImpl());
397 template <
class Traits>
411 template <
class,
class>
418 : super(builder, parent), EltTy(eltTy) {}
423 llvm::Constant *finishImpl() {
424 return AggregateBuilderBase::finishArray(EltTy);
433 template <
class Traits>
445 llvm::StructType *StructTy;
447 template <
class,
class>
453 llvm::StructType *structTy)
454 : super(builder, parent), StructTy(structTy) {
455 if (structTy) this->Packed = structTy->isPacked();
460 this->Packed = packed;
466 if (this->size() == structTy->getNumElements()) {
474 llvm::Constant *finishImpl() {
475 return AggregateBuilderBase::finishStruct(StructTy);
484 template <
class Traits>
496 return ArrayBuilder(static_cast<InitBuilder&>(*
this),
nullptr, eltTy);
500 return StructBuilder(static_cast<InitBuilder&>(*
this),
nullptr, structTy);
527 template <
class Traits>
531 template <
class Impl,
class Traits>
544 template <
class Traits>
548 template <
class Impl,
class Traits>
553 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.