clang: lib/CodeGen/ConstantInitBuilder.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
17
18using namespace clang;
20
22 assert(Data && "dereferencing null future");
23 if (const auto *C = dyn_cast<llvm::Constant *>(Data)) {
24 return C->getType();
25 } else {
27 }
28}
29
31 assert(Data && "abandoning null future");
32 if (auto *builder = dyn_cast<ConstantInitBuilderBase *>(Data)) {
33 builder->abandon(0);
34 }
35 Data = nullptr;
36}
37
39 assert(Data && "installing null future");
40 if (auto *C = dyn_cast<llvm::Constant *>(Data)) {
41 GV->setInitializer(C);
42 } else {
44 assert(builder.Buffer.size() == 1);
45 builder.setGlobalInitializer(GV, builder.Buffer[0]);
46 builder.Buffer.clear();
47 Data = nullptr;
48 }
49}
50
52ConstantInitBuilderBase::createFuture(llvm::Constant *initializer) {
53 assert(Buffer.empty() && "buffer not current empty");
54 Buffer.push_back(initializer);
56}
57
58
60 : Data(builder) {
61 assert(!builder->Frozen);
62 assert(builder->Buffer.size() == 1);
63 assert(builder->Buffer[0] != nullptr);
64}
65
66llvm::GlobalVariable *
67ConstantInitBuilderBase::createGlobal(llvm::Constant *initializer,
68 const llvm::Twine &name,
70 bool constant,
71 llvm::GlobalValue::LinkageTypes linkage,
72 unsigned addressSpace) {
73 auto GV = new llvm::GlobalVariable(CGM.getModule(),
74 initializer->getType(),
75 constant,
76 linkage,
77 initializer,
78 name,
79 nullptr,
80 llvm::GlobalValue::NotThreadLocal,
81 addressSpace);
82 GV->setAlignment(alignment.getAsAlign());
83 resolveSelfReferences(GV);
84 return GV;
85}
86
87void ConstantInitBuilderBase::setGlobalInitializer(llvm::GlobalVariable *GV,
88 llvm::Constant *initializer){
89 GV->setInitializer(initializer);
90
91 if (!SelfReferences.empty())
92 resolveSelfReferences(GV);
93}
94
95void 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();
103 }
104 SelfReferences.clear();
105}
106
107void ConstantInitBuilderBase::abandon(size_t newEnd) {
108
109 Buffer.erase(Buffer.begin() + newEnd, Buffer.end());
110
111
112
113
114 if (newEnd == 0) {
115 for (auto &entry : SelfReferences) {
116 auto dummy = entry.Dummy;
117 dummy->replaceAllUsesWith(llvm::PoisonValue::get(dummy->getType()));
118 dummy->eraseFromParent();
119 }
120 SelfReferences.clear();
121 }
122}
123
127
128llvm::Constant *
129ConstantAggregateBuilderBase::getRelativeOffset(llvm::IntegerType *offsetType,
130 llvm::Constant *target) {
131 return getRelativeOffsetToPosition(offsetType, target,
132 Builder.Buffer.size() - Begin);
133}
134
135llvm::Constant *ConstantAggregateBuilderBase::getRelativeOffsetToPosition(
136 llvm::IntegerType *offsetType, llvm::Constant *target, size_t position) {
137
139
140
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);
144
145
146 if (Builder.CGM.IntPtrTy != offsetType) {
147 offset = llvm::ConstantExpr::getTrunc(offset, offsetType);
148 }
149
150 return offset;
151}
152
153llvm::Constant *
155 size_t position) {
156
157
158 auto dummy = new llvm::GlobalVariable(Builder.CGM.getModule(), type, true,
159 llvm::GlobalVariable::PrivateLinkage,
160 nullptr, "");
161 Builder.SelfReferences.emplace_back(dummy);
162 auto &entry = Builder.SelfReferences.back();
163 getGEPIndicesTo(entry.Indices, position + Begin);
164 return dummy;
165}
166
167llvm::Constant *
169
170
171 auto dummy =
172 new llvm::GlobalVariable(Builder.CGM.getModule(), type, true,
173 llvm::GlobalVariable::PrivateLinkage,
174 nullptr, "");
175 Builder.SelfReferences.emplace_back(dummy);
176 auto &entry = Builder.SelfReferences.back();
178 return dummy;
179}
180
181void ConstantAggregateBuilderBase::getGEPIndicesTo(
183 size_t position) const {
184
187
188
189 } else {
190 assert(indices.empty());
191 indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty, 0));
192 }
193
194 assert(position >= Begin);
195
196
197 indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty,
198 position - Begin));
199}
200
203
205
206
208
209
210 auto &layout = Builder.CGM.getDataLayout();
214
217
218 return position;
219}
220
221CharUnits ConstantAggregateBuilderBase::getOffsetFromGlobalTo(size_t end) const{
223 assert(cacheEnd <= end);
224
225
226 if (cacheEnd == end) {
228 }
229
230
231
233 if (cacheEnd < Begin) {
234 assert(cacheEnd == 0);
235 assert(Parent && "Begin != 0 for root builder");
236 cacheEnd = Begin;
237 offset = Parent->getOffsetFromGlobalTo(Begin);
238 } else {
240 }
241
242
243 if (cacheEnd != end) {
244 auto &layout = Builder.CGM.getDataLayout();
245 do {
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();
254 } while (++cacheEnd != end);
255 }
256
257
260 return offset;
261}
262
265
267 assert((Begin < buffer.size() ||
268 (Begin == buffer.size() && eltTy))
269 && "didn't add any array elements without element type");
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());
275 return constant;
276}
277
278llvm::Constant *
281
284
285 if (ty == nullptr && elts.empty())
286 ty = llvm::StructType::get(Builder.CGM.getLLVMContext(), {}, Packed);
287
288 llvm::Constant *constant;
289 if (ty) {
290 assert(ty->isPacked() == Packed);
291 constant = llvm::ConstantStruct::get(ty, elts);
292 } else {
293 constant = llvm::ConstantStruct::getAnon(elts, Packed);
294 }
295
296 buffer.erase(buffer.begin() + Begin, buffer.end());
297 return constant;
298}
299
300
301
305 if (!Schema || .CGM.shouldSignPointer(Schema))
307
308 llvm::Constant *StorageAddress = nullptr;
311 }
312
313 llvm::Constant *SignedPointer = Builder.CGM.getConstantSignedPointer(
314 Pointer, Schema, StorageAddress, CalleeDecl, CalleeType);
315 add(SignedPointer);
316}
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.
Definition ConstantInitBuilder.cpp:154
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)
Definition ConstantInitBuilder.cpp:263
PlaceholderPosition addPlaceholderWithSize(llvm::Type *expectedType)
Add a placeholder, giving the expected type that will be filled in.
Definition ConstantInitBuilder.cpp:202
void addSize(CharUnits size)
Add an integer value of type size_t.
Definition ConstantInitBuilder.cpp:124
llvm::Constant * finishStruct(llvm::StructType *structTy)
Definition ConstantInitBuilder.cpp:279
llvm::Constant * getAddrOfCurrentPosition(llvm::Type *type)
Produce an address which will eventually point to the next position to be filled.
Definition ConstantInitBuilder.cpp:168
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.
Definition ConstantInitBuilder.cpp:302
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.
Definition ConstantInitBuilder.cpp:21
void abandon()
Abandon this initializer.
Definition ConstantInitBuilder.cpp:30
void installInGlobal(llvm::GlobalVariable *global)
Install the initializer into a global variable.
Definition ConstantInitBuilder.cpp:38
GlobalDecl - represents a global declaration.
bool isAddressDiscriminated() const
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.
U cast(CodeGen::Address addr)