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"
29class PointerAuthSchema;
55 struct SelfReference {
56 llvm::GlobalVariable *Dummy;
59 SelfReference(llvm::GlobalVariable *dummy) : Dummy(dummy) {}
63 std::vector<SelfReference> SelfReferences;
68 template <
class,
class>
75 assert(Buffer.empty() &&
"didn't claim all values out of buffer");
76 assert(SelfReferences.empty() &&
"didn't apply all self-references");
80 llvm::GlobalVariable *createGlobal(llvm::Constant *initializer,
81 const llvm::Twine &name,
83 bool constant =
false,
84 llvm::GlobalValue::LinkageTypes linkage
85 = llvm::GlobalValue::InternalLinkage,
86 unsigned addressSpace = 0);
90 void setGlobalInitializer(llvm::GlobalVariable *GV,
91 llvm::Constant *initializer);
93 void resolveSelfReferences(llvm::GlobalVariable *GV);
95 void abandon(
size_t newEnd);
123 assert(!parent->
Frozen &&
"parent already has child builder active");
126 assert(!builder.Frozen &&
"builder already has child builder active");
127 builder.Frozen =
true;
132 assert(
Finished &&
"didn't finish aggregate builder");
136 assert(!
Frozen &&
"child builder still active");
137 assert(!
Finished &&
"builder already finished");
141 "parent not frozen while child builder active");
145 "builder not frozen while child builder active");
163 other.Finished =
true;
171 assert(!this->Finished &&
"cannot query after finishing builder");
172 assert(!this->Frozen &&
"cannot query while sub-builder is active");
185 Builder.abandon(
Begin);
189 void add(llvm::Constant *value) {
190 assert(value &&
"adding null value to constant initializer");
191 assert(!
Finished &&
"cannot add more values after finishing builder");
192 assert(!
Frozen &&
"cannot add values while subbuilder is active");
193 Builder.Buffer.push_back(value);
200 void addInt(llvm::IntegerType *intTy, uint64_t value,
201 bool isSigned =
false) {
202 add(llvm::ConstantInt::get(intTy, value, isSigned));
212 add(llvm::ConstantPointerNull::get(ptrTy));
217 assert(!
Finished &&
"cannot add more values after finishing builder");
218 assert(!
Frozen &&
"cannot add values while subbuilder is active");
219 Builder.Buffer.append(values.begin(), values.end());
229 add(getRelativeOffset(
type, target));
235 llvm::Constant *target,
size_t position) {
236 add(getRelativeOffsetToPosition(
type, target, position));
244 llvm::Constant *address,
246 llvm::Constant *offset = getRelativeOffset(
type, address);
248 offset = llvm::ConstantExpr::getAdd(offset,
249 llvm::ConstantInt::get(
type, tag));
260 assert(!
Finished &&
"cannot add more values after finishing builder");
261 assert(!
Frozen &&
"cannot add values while subbuilder is active");
262 return getOffsetFromGlobalTo(
Builder.Buffer.size());
282 assert(!
Finished &&
"cannot add more values after finishing builder");
283 assert(!
Frozen &&
"cannot add values while subbuilder is active");
284 Builder.Buffer.push_back(
nullptr);
285 return Builder.Buffer.size() - 1;
293 llvm::IntegerType *
type, uint64_t value,
294 bool isSigned =
false) {
300 assert(!
Finished &&
"cannot change values after finishing builder");
301 assert(!
Frozen &&
"cannot add values while subbuilder is active");
302 llvm::Constant *&slot =
Builder.Buffer[position.Index];
303 assert(slot ==
nullptr &&
"placeholder already filled");
325 getGEPIndicesTo(indices,
Builder.Buffer.size());
331 llvm::Constant *
finishStruct(llvm::StructType *structTy);
335 size_t position)
const;
337 llvm::Constant *getRelativeOffset(llvm::IntegerType *offsetType,
338 llvm::Constant *target);
340 llvm::Constant *getRelativeOffsetToPosition(llvm::IntegerType *offsetType,
341 llvm::Constant *target,
344 CharUnits getOffsetFromGlobalTo(
size_t index)
const;
347template <
class Impl,
class Traits>
349 :
public Traits::AggregateBuilderBase {
350 using super =
typename Traits::AggregateBuilderBase;
360 : super(builder, parent) {}
362 Impl &
asImpl() {
return *
static_cast<Impl*
>(
this); }
383 assert(this->
Parent == &parent &&
"adding to non-parent builder");
384 parent.add(
asImpl().finishImpl());
390 template <
class... As>
392 assert(!this->
Parent &&
"finishing non-root builder");
393 return this->Builder.createGlobal(
asImpl().finishImpl(),
394 std::forward<As>(args)...);
401 assert(!this->
Parent &&
"finishing non-root builder");
402 return this->Builder.setGlobalInitializer(global,
asImpl().finishImpl());
414 assert(!this->
Parent &&
"finishing non-root builder");
415 return this->Builder.createFuture(
asImpl().finishImpl());
419template <
class Traits>
433 template <
class,
class>
440 :
super(builder, parent), EltTy(eltTy) {}
445 llvm::Constant *finishImpl() {
446 return AggregateBuilderBase::finishArray(EltTy);
455template <
class Traits>
467 llvm::StructType *StructTy;
469 template <
class,
class>
475 llvm::StructType *structTy)
476 :
super(builder, parent), StructTy(structTy) {
477 if (structTy) this->Packed = structTy->isPacked();
482 this->Packed = packed;
488 if (this->size() == structTy->getNumElements()) {
496 llvm::Constant *finishImpl() {
497 return AggregateBuilderBase::finishStruct(StructTy);
506template <
class Traits>
526class ConstantInitBuilder;
527class ConstantStructBuilder;
528class ConstantArrayBuilder;
549 template <
class Traits>
553 template <
class Impl,
class Traits>
566 template <
class Traits>
570 template <
class Impl,
class Traits>
575 llvm::StructType *structTy)
CharUnits - This is an opaque type for sizes expressed in character units.
This class organizes the cross-function state that is used while generating LLVM code.
An opaque class to hold the abstract position of a placeholder.
A concrete base class for struct and array aggregate initializer builders.
ConstantAggregateBuilderBase & operator=(ConstantAggregateBuilderBase &&other)=delete
bool empty() const
Return true if no elements have yet been added to this struct or array.
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::Constant * getAddrOfPosition(llvm::Type *type, size_t position)
Produce an address which points to a position in the aggregate being constructed.
CharUnits CachedOffsetFromGlobal
PlaceholderPosition addPlaceholder()
Add a placeholder value to the structure.
ConstantAggregateBuilderBase & operator=(const ConstantAggregateBuilderBase &)=delete
void addRelativeOffsetToPosition(llvm::IntegerType *type, llvm::Constant *target, size_t position)
Same as addRelativeOffset(), but instead relative to an element in this aggregate,...
void fillPlaceholder(PlaceholderPosition position, llvm::Constant *value)
Fill a previously-added placeholder.
llvm::SmallVectorImpl< llvm::Constant * > & getBuffer()
void abandon()
Abandon this builder completely.
void add(llvm::Constant *value)
Add a new value to this initializer.
llvm::Constant * finishArray(llvm::Type *eltTy)
PlaceholderPosition addPlaceholderWithSize(llvm::Type *expectedType)
Add a placeholder, giving the expected type that will be filled in.
void addSize(CharUnits size)
Add an integer value of type size_t.
void addInt(llvm::IntegerType *intTy, uint64_t value, bool isSigned=false)
Add an integer value of a specific type.
ConstantAggregateBuilderBase(ConstantAggregateBuilderBase &&other)
llvm::Constant * finishStruct(llvm::StructType *structTy)
llvm::Constant * getAddrOfCurrentPosition(llvm::Type *type)
Produce an address which will eventually point to the next position to be filled.
ConstantAggregateBuilderBase(ConstantInitBuilderBase &builder, ConstantAggregateBuilderBase *parent)
void addNullPointer(llvm::PointerType *ptrTy)
Add a null pointer of a specific type.
CharUnits getNextOffsetFromGlobal() const
Return the offset from the start of the initializer to the next position, assuming no padding is requ...
llvm::ArrayRef< llvm::Constant * > getGEPIndicesToCurrentPosition(llvm::SmallVectorImpl< llvm::Constant * > &indices)
void addAll(llvm::ArrayRef< llvm::Constant * > values)
Add a bunch of new values to this initializer.
const llvm::SmallVectorImpl< llvm::Constant * > & getBuffer() const
size_t size() const
Return the number of elements that have been added to this struct or array.
~ConstantAggregateBuilderBase()
void addSignedPointer(llvm::Constant *Pointer, const PointerAuthSchema &Schema, GlobalDecl CalleeDecl, QualType CalleeType)
Add a signed pointer using the given pointer authentication schema.
ConstantInitBuilderBase & Builder
void fillPlaceholderWithInt(PlaceholderPosition position, llvm::IntegerType *type, uint64_t value, bool isSigned=false)
Fill a previously-added placeholder.
ConstantAggregateBuilderBase * Parent
ConstantAggregateBuilderBase(const ConstantAggregateBuilderBase &)=delete
ArrayBuilder beginArray(llvm::Type *eltTy=nullptr)
llvm::GlobalVariable * finishAndCreateGlobal(As &&...args)
Given that this builder was created by beginning an array or struct directly on a ConstantInitBuilder...
ConstantInitFuture finishAndCreateFuture()
Given that this builder was created by beginning an array or struct directly on a ConstantInitBuilder...
ConstantAggregateBuilderTemplateBase(InitBuilder &builder, AggregateBuilderBase *parent)
typename Traits::StructBuilder StructBuilder
typename Traits::ArrayBuilder ArrayBuilder
void finishAndSetAsInitializer(llvm::GlobalVariable *global)
Given that this builder was created by beginning an array or struct directly on a ConstantInitBuilder...
typename Traits::InitBuilder InitBuilder
StructBuilder beginStruct(llvm::StructType *ty=nullptr)
typename Traits::AggregateBuilderBase AggregateBuilderBase
void finishAndAddTo(AggregateBuilderBase &parent)
Given that this builder was created by beginning an array or struct component on the given parent bui...
typename Traits::InitBuilder InitBuilder
ConstantArrayBuilderTemplateBase(InitBuilder &builder, AggregateBuilderBase *parent, llvm::Type *eltTy)
typename Traits::AggregateBuilderBase AggregateBuilderBase
A helper class of ConstantInitBuilder, used for building constant array initializers.
A convenience builder class for complex constant initializers, especially for anonymous global struct...
~ConstantInitBuilderBase()
ConstantInitBuilderBase(CodeGenModule &CGM)
A template class designed to allow other frontends to easily customize the builder classes used by Co...
StructBuilder beginStruct(llvm::StructType *structTy=nullptr)
ArrayBuilder beginArray(llvm::Type *eltTy=nullptr)
typename Traits::StructBuilder StructBuilder
typename Traits::InitBuilder InitBuilder
ConstantInitBuilderTemplateBase(CodeGenModule &CGM)
typename Traits::ArrayBuilder ArrayBuilder
The standard implementation of ConstantInitBuilder used in Clang.
ConstantInitBuilder(CodeGenModule &CGM)
A "future" for a completed constant initializer, which can be passed around independently of any sub-...
A template class designed to allow other frontends to easily customize the builder classes used by Co...
ConstantStructBuilderTemplateBase(InitBuilder &builder, AggregateBuilderBase *parent, llvm::StructType *structTy)
void suggestType(llvm::StructType *structTy)
Use the given type for the struct if its element count is correct.
void setPacked(bool packed)
typename Traits::AggregateBuilderBase AggregateBuilderBase
typename Traits::InitBuilder InitBuilder
A helper class of ConstantInitBuilder, used for building constant struct initializers.
GlobalDecl - represents a global declaration.
A (possibly-)qualified type.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
The JSON file list parser is used to communicate input to InstallAPI.