1 //===--- ConstantInitBuilder.cpp - Global initializer builder -------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines out-of-line routines for building initializers for
10 // global variables, in particular the kind of globals that are implicitly
11 // introduced by various language ABIs.
13 //===----------------------------------------------------------------------===//
15 #include "clang/CodeGen/ConstantInitBuilder.h"
16 #include "CodeGenModule.h"
18 using namespace clang
;
19 using namespace CodeGen
;
21 llvm::Type
*ConstantInitFuture::getType() const {
22 assert(Data
&& "dereferencing null future");
23 if (Data
.is
<llvm::Constant
*>()) {
24 return Data
.get
<llvm::Constant
*>()->getType();
26 return Data
.get
<ConstantInitBuilderBase
*>()->Buffer
[0]->getType();
30 void ConstantInitFuture::abandon() {
31 assert(Data
&& "abandoning null future");
32 if (auto builder
= Data
.dyn_cast
<ConstantInitBuilderBase
*>()) {
38 void ConstantInitFuture::installInGlobal(llvm::GlobalVariable
*GV
) {
39 assert(Data
&& "installing null future");
40 if (Data
.is
<llvm::Constant
*>()) {
41 GV
->setInitializer(Data
.get
<llvm::Constant
*>());
43 auto &builder
= *Data
.get
<ConstantInitBuilderBase
*>();
44 assert(builder
.Buffer
.size() == 1);
45 builder
.setGlobalInitializer(GV
, builder
.Buffer
[0]);
46 builder
.Buffer
.clear();
52 ConstantInitBuilderBase::createFuture(llvm::Constant
*initializer
) {
53 assert(Buffer
.empty() && "buffer not current empty");
54 Buffer
.push_back(initializer
);
55 return ConstantInitFuture(this);
58 // Only used in this file.
59 inline ConstantInitFuture::ConstantInitFuture(ConstantInitBuilderBase
*builder
)
61 assert(!builder
->Frozen
);
62 assert(builder
->Buffer
.size() == 1);
63 assert(builder
->Buffer
[0] != nullptr);
66 llvm::GlobalVariable
*
67 ConstantInitBuilderBase::createGlobal(llvm::Constant
*initializer
,
68 const llvm::Twine
&name
,
71 llvm::GlobalValue::LinkageTypes linkage
,
72 unsigned addressSpace
) {
73 auto GV
= new llvm::GlobalVariable(CGM
.getModule(),
74 initializer
->getType(),
79 /*insert before*/ nullptr,
80 llvm::GlobalValue::NotThreadLocal
,
82 GV
->setAlignment(alignment
.getAsAlign());
83 resolveSelfReferences(GV
);
87 void ConstantInitBuilderBase::setGlobalInitializer(llvm::GlobalVariable
*GV
,
88 llvm::Constant
*initializer
){
89 GV
->setInitializer(initializer
);
91 if (!SelfReferences
.empty())
92 resolveSelfReferences(GV
);
95 void ConstantInitBuilderBase::resolveSelfReferences(llvm::GlobalVariable
*GV
) {
96 for (auto &entry
: SelfReferences
) {
97 llvm::Constant
*resolvedReference
=
98 llvm::ConstantExpr::getInBoundsGetElementPtr(
99 GV
->getValueType(), GV
, entry
.Indices
);
100 auto dummy
= entry
.Dummy
;
101 dummy
->replaceAllUsesWith(resolvedReference
);
102 dummy
->eraseFromParent();
104 SelfReferences
.clear();
107 void ConstantInitBuilderBase::abandon(size_t newEnd
) {
108 // Remove all the entries we've added.
109 Buffer
.erase(Buffer
.begin() + newEnd
, Buffer
.end());
111 // If we're abandoning all the way to the beginning, destroy
112 // all the self-references, because we might not get another
115 for (auto &entry
: SelfReferences
) {
116 auto dummy
= entry
.Dummy
;
117 dummy
->replaceAllUsesWith(llvm::PoisonValue::get(dummy
->getType()));
118 dummy
->eraseFromParent();
120 SelfReferences
.clear();
124 void ConstantAggregateBuilderBase::addSize(CharUnits size
) {
125 add(Builder
.CGM
.getSize(size
));
129 ConstantAggregateBuilderBase::getRelativeOffset(llvm::IntegerType
*offsetType
,
130 llvm::Constant
*target
) {
131 return getRelativeOffsetToPosition(offsetType
, target
,
132 Builder
.Buffer
.size() - Begin
);
135 llvm::Constant
*ConstantAggregateBuilderBase::getRelativeOffsetToPosition(
136 llvm::IntegerType
*offsetType
, llvm::Constant
*target
, size_t position
) {
137 // Compute the address of the relative-address slot.
138 auto base
= getAddrOfPosition(offsetType
, position
);
141 base
= llvm::ConstantExpr::getPtrToInt(base
, Builder
.CGM
.IntPtrTy
);
142 target
= llvm::ConstantExpr::getPtrToInt(target
, Builder
.CGM
.IntPtrTy
);
143 llvm::Constant
*offset
= llvm::ConstantExpr::getSub(target
, base
);
145 // Truncate to the relative-address type if necessary.
146 if (Builder
.CGM
.IntPtrTy
!= offsetType
) {
147 offset
= llvm::ConstantExpr::getTrunc(offset
, offsetType
);
154 ConstantAggregateBuilderBase::getAddrOfPosition(llvm::Type
*type
,
156 // Make a global variable. We will replace this with a GEP to this
157 // position after installing the initializer.
158 auto dummy
= new llvm::GlobalVariable(Builder
.CGM
.getModule(), type
, true,
159 llvm::GlobalVariable::PrivateLinkage
,
161 Builder
.SelfReferences
.emplace_back(dummy
);
162 auto &entry
= Builder
.SelfReferences
.back();
163 (void)getGEPIndicesTo(entry
.Indices
, position
+ Begin
);
168 ConstantAggregateBuilderBase::getAddrOfCurrentPosition(llvm::Type
*type
) {
169 // Make a global variable. We will replace this with a GEP to this
170 // position after installing the initializer.
172 new llvm::GlobalVariable(Builder
.CGM
.getModule(), type
, true,
173 llvm::GlobalVariable::PrivateLinkage
,
175 Builder
.SelfReferences
.emplace_back(dummy
);
176 auto &entry
= Builder
.SelfReferences
.back();
177 (void) getGEPIndicesToCurrentPosition(entry
.Indices
);
181 void ConstantAggregateBuilderBase::getGEPIndicesTo(
182 llvm::SmallVectorImpl
<llvm::Constant
*> &indices
,
183 size_t position
) const {
184 // Recurse on the parent builder if present.
186 Parent
->getGEPIndicesTo(indices
, Begin
);
188 // Otherwise, add an index to drill into the first level of pointer.
190 assert(indices
.empty());
191 indices
.push_back(llvm::ConstantInt::get(Builder
.CGM
.Int32Ty
, 0));
194 assert(position
>= Begin
);
195 // We have to use i32 here because struct GEPs demand i32 indices.
196 // It's rather unlikely to matter in practice.
197 indices
.push_back(llvm::ConstantInt::get(Builder
.CGM
.Int32Ty
,
201 ConstantAggregateBuilderBase::PlaceholderPosition
202 ConstantAggregateBuilderBase::addPlaceholderWithSize(llvm::Type
*type
) {
203 // Bring the offset up to the last field.
204 CharUnits offset
= getNextOffsetFromGlobal();
206 // Create the placeholder.
207 auto position
= addPlaceholder();
209 // Advance the offset past that field.
210 auto &layout
= Builder
.CGM
.getDataLayout();
212 offset
= offset
.alignTo(CharUnits::fromQuantity(layout
.getABITypeAlign(type
)));
213 offset
+= CharUnits::fromQuantity(layout
.getTypeStoreSize(type
));
215 CachedOffsetEnd
= Builder
.Buffer
.size();
216 CachedOffsetFromGlobal
= offset
;
221 CharUnits
ConstantAggregateBuilderBase::getOffsetFromGlobalTo(size_t end
) const{
222 size_t cacheEnd
= CachedOffsetEnd
;
223 assert(cacheEnd
<= end
);
225 // Fast path: if the cache is valid, just use it.
226 if (cacheEnd
== end
) {
227 return CachedOffsetFromGlobal
;
230 // If the cached range ends before the index at which the current
231 // aggregate starts, recurse for the parent.
233 if (cacheEnd
< Begin
) {
234 assert(cacheEnd
== 0);
235 assert(Parent
&& "Begin != 0 for root builder");
237 offset
= Parent
->getOffsetFromGlobalTo(Begin
);
239 offset
= CachedOffsetFromGlobal
;
242 // Perform simple layout on the elements in cacheEnd..<end.
243 if (cacheEnd
!= end
) {
244 auto &layout
= Builder
.CGM
.getDataLayout();
246 llvm::Constant
*element
= Builder
.Buffer
[cacheEnd
];
247 assert(element
!= nullptr &&
248 "cannot compute offset when a placeholder is present");
249 llvm::Type
*elementType
= element
->getType();
251 offset
= offset
.alignTo(
252 CharUnits::fromQuantity(layout
.getABITypeAlign(elementType
)));
253 offset
+= CharUnits::fromQuantity(layout
.getTypeStoreSize(elementType
));
254 } while (++cacheEnd
!= end
);
258 CachedOffsetEnd
= cacheEnd
;
259 CachedOffsetFromGlobal
= offset
;
263 llvm::Constant
*ConstantAggregateBuilderBase::finishArray(llvm::Type
*eltTy
) {
266 auto &buffer
= getBuffer();
267 assert((Begin
< buffer
.size() ||
268 (Begin
== buffer
.size() && eltTy
))
269 && "didn't add any array elements without element type");
270 auto elts
= llvm::ArrayRef(buffer
).slice(Begin
);
271 if (!eltTy
) eltTy
= elts
[0]->getType();
272 auto type
= llvm::ArrayType::get(eltTy
, elts
.size());
273 auto constant
= llvm::ConstantArray::get(type
, elts
);
274 buffer
.erase(buffer
.begin() + Begin
, buffer
.end());
279 ConstantAggregateBuilderBase::finishStruct(llvm::StructType
*ty
) {
282 auto &buffer
= getBuffer();
283 auto elts
= llvm::ArrayRef(buffer
).slice(Begin
);
285 if (ty
== nullptr && elts
.empty())
286 ty
= llvm::StructType::get(Builder
.CGM
.getLLVMContext(), {}, Packed
);
288 llvm::Constant
*constant
;
290 assert(ty
->isPacked() == Packed
);
291 constant
= llvm::ConstantStruct::get(ty
, elts
);
293 constant
= llvm::ConstantStruct::getAnon(elts
, Packed
);
296 buffer
.erase(buffer
.begin() + Begin
, buffer
.end());