22 assert(Data &&
"dereferencing null future");
23 if (
const auto *
C = dyn_cast<llvm::Constant *>(Data)) {
31 assert(Data &&
"abandoning null future");
32 if (
auto *builder = dyn_cast<ConstantInitBuilderBase *>(Data)) {
39 assert(Data &&
"installing null future");
40 if (
auto *
C = dyn_cast<llvm::Constant *>(Data)) {
41 GV->setInitializer(
C);
44 assert(builder.Buffer.size() == 1);
45 builder.setGlobalInitializer(GV, builder.Buffer[0]);
46 builder.Buffer.clear();
52ConstantInitBuilderBase::createFuture(llvm::Constant *initializer) {
53 assert(Buffer.empty() &&
"buffer not current empty");
54 Buffer.push_back(initializer);
61 assert(!builder->Frozen);
62 assert(builder->Buffer.size() == 1);
63 assert(builder->Buffer[0] !=
nullptr);
66llvm::GlobalVariable *ConstantInitBuilderBase::createGlobal(
67 llvm::Constant *initializer,
const llvm::Twine &name,
CharUnits alignment,
68 bool constant, llvm::GlobalValue::LinkageTypes linkage,
69 std::optional<unsigned> addressSpace) {
70 auto GV =
new llvm::GlobalVariable(CGM.
getModule(),
71 initializer->getType(),
77 llvm::GlobalValue::NotThreadLocal,
80 resolveSelfReferences(GV);
84void ConstantInitBuilderBase::setGlobalInitializer(llvm::GlobalVariable *GV,
85 llvm::Constant *initializer){
86 GV->setInitializer(initializer);
88 if (!SelfReferences.empty())
89 resolveSelfReferences(GV);
92void ConstantInitBuilderBase::resolveSelfReferences(llvm::GlobalVariable *GV) {
93 for (
auto &entry : SelfReferences) {
94 llvm::Constant *resolvedReference =
95 llvm::ConstantExpr::getInBoundsGetElementPtr(
96 GV->getValueType(), GV, entry.Indices);
97 auto dummy = entry.Dummy;
98 dummy->replaceAllUsesWith(resolvedReference);
99 dummy->eraseFromParent();
101 SelfReferences.clear();
104void ConstantInitBuilderBase::abandon(
size_t newEnd) {
106 Buffer.erase(Buffer.begin() + newEnd, Buffer.end());
112 for (
auto &entry : SelfReferences) {
113 auto dummy = entry.Dummy;
114 dummy->replaceAllUsesWith(llvm::PoisonValue::get(dummy->getType()));
115 dummy->eraseFromParent();
117 SelfReferences.clear();
126ConstantAggregateBuilderBase::getRelativeOffset(llvm::IntegerType *offsetType,
127 llvm::Constant *target) {
128 return getRelativeOffsetToPosition(offsetType, target,
129 Builder.Buffer.size() -
Begin);
132llvm::Constant *ConstantAggregateBuilderBase::getRelativeOffsetToPosition(
133 llvm::IntegerType *offsetType, llvm::Constant *target,
size_t position) {
138 base = llvm::ConstantExpr::getPtrToInt(base, Builder.CGM.IntPtrTy);
139 target = llvm::ConstantExpr::getPtrToInt(target, Builder.CGM.IntPtrTy);
140 llvm::Constant *offset = llvm::ConstantExpr::getSub(target, base);
143 if (Builder.CGM.IntPtrTy != offsetType) {
144 offset = llvm::ConstantExpr::getTrunc(offset, offsetType);
155 auto dummy =
new llvm::GlobalVariable(
Builder.CGM.getModule(),
type,
true,
156 llvm::GlobalVariable::PrivateLinkage,
158 Builder.SelfReferences.emplace_back(dummy);
159 auto &entry =
Builder.SelfReferences.back();
160 getGEPIndicesTo(entry.Indices, position +
Begin);
169 new llvm::GlobalVariable(
Builder.CGM.getModule(),
type,
true,
170 llvm::GlobalVariable::PrivateLinkage,
172 Builder.SelfReferences.emplace_back(dummy);
173 auto &entry =
Builder.SelfReferences.back();
178void ConstantAggregateBuilderBase::getGEPIndicesTo(
180 size_t position)
const {
187 assert(indices.empty());
188 indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty, 0));
191 assert(position >=
Begin);
194 indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty,
207 auto &layout =
Builder.CGM.getDataLayout();
218CharUnits ConstantAggregateBuilderBase::getOffsetFromGlobalTo(
size_t end)
const{
220 assert(cacheEnd <= end);
223 if (cacheEnd == end) {
230 if (cacheEnd <
Begin) {
231 assert(cacheEnd == 0);
232 assert(
Parent &&
"Begin != 0 for root builder");
240 if (cacheEnd != end) {
241 auto &layout =
Builder.CGM.getDataLayout();
243 llvm::Constant *element =
Builder.Buffer[cacheEnd];
244 assert(element !=
nullptr &&
245 "cannot compute offset when a placeholder is present");
246 llvm::Type *elementType = element->getType();
251 }
while (++cacheEnd != end);
264 assert((
Begin < buffer.size() ||
265 (
Begin == buffer.size() && eltTy))
266 &&
"didn't add any array elements without element type");
268 if (!eltTy) eltTy = elts[0]->getType();
269 auto type = llvm::ArrayType::get(eltTy, elts.size());
270 auto constant = llvm::ConstantArray::get(
type, elts);
271 buffer.erase(buffer.begin() +
Begin, buffer.end());
282 if (ty ==
nullptr && elts.empty())
283 ty = llvm::StructType::get(
Builder.CGM.getLLVMContext(), {},
Packed);
285 llvm::Constant *constant;
287 assert(ty->isPacked() ==
Packed);
288 constant = llvm::ConstantStruct::get(ty, elts);
290 constant = llvm::ConstantStruct::getAnon(elts,
Packed);
293 buffer.erase(buffer.begin() +
Begin, buffer.end());
302 if (!Schema || !
Builder.CGM.shouldSignPointer(Schema))
305 llvm::Constant *StorageAddress =
nullptr;
310 llvm::Constant *SignedPointer =
Builder.CGM.getConstantSignedPointer(
311 Pointer, Schema, StorageAddress, CalleeDecl, CalleeType);
CharUnits - This is an opaque type for sizes expressed in character units.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
llvm::Module & getModule() const
An opaque class to hold the abstract position of a placeholder.
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.
llvm::SmallVectorImpl< llvm::Constant * > & getBuffer()
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.
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.
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)
size_t size() const
Return the number of elements that have been added to this struct or array.
void addSignedPointer(llvm::Constant *Pointer, const PointerAuthSchema &Schema, GlobalDecl CalleeDecl, QualType CalleeType)
Add a signed pointer using the given pointer authentication schema.
ConstantInitBuilderBase & Builder
ConstantAggregateBuilderBase * Parent
A convenience builder class for complex constant initializers, especially for anonymous global struct...
friend class ConstantInitFuture
A "future" for a completed constant initializer, which can be passed around independently of any sub-...
llvm::Type * getType() const
Return the type of the initializer.
void abandon()
Abandon this initializer.
void installInGlobal(llvm::GlobalVariable *global)
Install the initializer into a global variable.
GlobalDecl - represents a global declaration.
bool isAddressDiscriminated() const
A (possibly-)qualified type.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
Top level wrappers for InstallAPI frontend operations.
U cast(CodeGen::Address addr)