clang 10.0.0git

ConstantInitBuilder.cpp
Go to the documentation of this file.
1 //===--- ConstantInitBuilder.cpp - Global initializer builder -------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
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.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "clang/CodeGen/ConstantInitBuilder.h"
16 #include "CodeGenModule.h"
17
18 using namespace clang;
19 using namespace CodeGen;
20
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();
25 } else {
26 return Data.get<ConstantInitBuilderBase*>()->Buffer[0]->getType();
27 }
28 }
29
30 void ConstantInitFuture::abandon() {
31 assert(Data && "abandoning null future");
32 if (auto builder = Data.dyn_cast<ConstantInitBuilderBase*>()) {
33 builder->abandon(0);
34 }
35 Data = nullptr;
36 }
37
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*>());
42 } else {
43 auto &builder = *Data.get<ConstantInitBuilderBase*>();
44 assert(builder.Buffer.size() == 1);
45 builder.setGlobalInitializer(GV, builder.Buffer[0]);
46 builder.Buffer.clear();
47 Data = nullptr;
48 }
49 }
50
51 ConstantInitFuture
52 ConstantInitBuilderBase::createFuture(llvm::Constant *initializer) {
53 assert(Buffer.empty() && "buffer not current empty");
54 Buffer.push_back(initializer);
55 return ConstantInitFuture(this);
56 }
57
58 // Only used in this file.
59 inline ConstantInitFuture::ConstantInitFuture(ConstantInitBuilderBase *builder)
60 : Data(builder) {
61 assert(!builder->Frozen);
62 assert(builder->Buffer.size() == 1);
63 assert(builder->Buffer[0] != nullptr);
64 }
65
66 llvm::GlobalVariable *
67 ConstantInitBuilderBase::createGlobal(llvm::Constant *initializer,
68 const llvm::Twine &name,
69 CharUnits alignment,
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 /*insert before*/ nullptr,
80 llvm::GlobalValue::NotThreadLocal,
81 addressSpace);
82 GV->setAlignment(alignment.getAsAlign());
83 resolveSelfReferences(GV);
84 return GV;
85 }
86
87 void ConstantInitBuilderBase::setGlobalInitializer(llvm::GlobalVariable *GV,
88 llvm::Constant *initializer){
89 GV->setInitializer(initializer);
90
91 if (!SelfReferences.empty())
92 resolveSelfReferences(GV);
93 }
94
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();
103 }
104 SelfReferences.clear();
105 }
106
107 void ConstantInitBuilderBase::abandon(size_t newEnd) {
108 // Remove all the entries we've added.
109 Buffer.erase(Buffer.begin() + newEnd, Buffer.end());
110
111 // If we're abandoning all the way to the beginning, destroy
112 // all the self-references, because we might not get another
113 // opportunity.
114 if (newEnd == 0) {
115 for (auto &entry : SelfReferences) {
116 auto dummy = entry.Dummy;
117 dummy->replaceAllUsesWith(llvm::UndefValue::get(dummy->getType()));
118 dummy->eraseFromParent();
119 }
120 SelfReferences.clear();
121 }
122 }
123
124 void ConstantAggregateBuilderBase::addSize(CharUnits size) {
125 add(Builder.CGM.getSize(size));
126 }
127
128 llvm::Constant *
129 ConstantAggregateBuilderBase::getRelativeOffset(llvm::IntegerType *offsetType,
130 llvm::Constant *target) {
131 // Compute the address of the relative-address slot.
132 auto base = getAddrOfCurrentPosition(offsetType);
133
134 // Subtract.
135 base = llvm::ConstantExpr::getPtrToInt(base, Builder.CGM.IntPtrTy);
136 target = llvm::ConstantExpr::getPtrToInt(target, Builder.CGM.IntPtrTy);
137 llvm::Constant *offset = llvm::ConstantExpr::getSub(target, base);
138
139 // Truncate to the relative-address type if necessary.
140 if (Builder.CGM.IntPtrTy != offsetType) {
141 offset = llvm::ConstantExpr::getTrunc(offset, offsetType);
142 }
143
144 return offset;
145 }
146
147 llvm::Constant *
148 ConstantAggregateBuilderBase::getAddrOfCurrentPosition(llvm::Type *type) {
149 // Make a global variable. We will replace this with a GEP to this
150 // position after installing the initializer.
151 auto dummy =
152 new llvm::GlobalVariable(Builder.CGM.getModule(), type, true,
153 llvm::GlobalVariable::PrivateLinkage,
154 nullptr, "");
155 Builder.SelfReferences.emplace_back(dummy);
156 auto &entry = Builder.SelfReferences.back();
157 (void) getGEPIndicesToCurrentPosition(entry.Indices);
158 return dummy;
159 }
160
161 void ConstantAggregateBuilderBase::getGEPIndicesTo(
162 llvm::SmallVectorImpl<llvm::Constant*> &indices,
163 size_t position) const {
164 // Recurse on the parent builder if present.
165 if (Parent) {
166 Parent->getGEPIndicesTo(indices, Begin);
167
168 // Otherwise, add an index to drill into the first level of pointer.
169 } else {
170 assert(indices.empty());
171 indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty, 0));
172 }
173
174 assert(position >= Begin);
175 // We have to use i32 here because struct GEPs demand i32 indices.
176 // It's rather unlikely to matter in practice.
177 indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty,
178 position - Begin));
179 }
180
181 ConstantAggregateBuilderBase::PlaceholderPosition
182 ConstantAggregateBuilderBase::addPlaceholderWithSize(llvm::Type *type) {
183 // Bring the offset up to the last field.
184 CharUnits offset = getNextOffsetFromGlobal();
185
186 // Create the placeholder.
187 auto position = addPlaceholder();
188
189 // Advance the offset past that field.
190 auto &layout = Builder.CGM.getDataLayout();
191 if (!Packed)
192 offset = offset.alignTo(CharUnits::fromQuantity(
193 layout.getABITypeAlignment(type)));
194 offset += CharUnits::fromQuantity(layout.getTypeStoreSize(type));
195
196 CachedOffsetEnd = Builder.Buffer.size();
197 CachedOffsetFromGlobal = offset;
198
199 return position;
200 }
201
202 CharUnits ConstantAggregateBuilderBase::getOffsetFromGlobalTo(size_t end) const{
203 size_t cacheEnd = CachedOffsetEnd;
204 assert(cacheEnd <= end);
205
206 // Fast path: if the cache is valid, just use it.
207 if (cacheEnd == end) {
208 return CachedOffsetFromGlobal;
209 }
210
211 // If the cached range ends before the index at which the current
212 // aggregate starts, recurse for the parent.
213 CharUnits offset;
214 if (cacheEnd < Begin) {
215 assert(cacheEnd == 0);
216 assert(Parent && "Begin != 0 for root builder");
217 cacheEnd = Begin;
218 offset = Parent->getOffsetFromGlobalTo(Begin);
219 } else {
220 offset = CachedOffsetFromGlobal;
221 }
222
223 // Perform simple layout on the elements in cacheEnd..<end.
224 if (cacheEnd != end) {
225 auto &layout = Builder.CGM.getDataLayout();
226 do {
227 llvm::Constant *element = Builder.Buffer[cacheEnd];
228 assert(element != nullptr &&
229 "cannot compute offset when a placeholder is present");
230 llvm::Type *elementType = element->getType();
231 if (!Packed)
232 offset = offset.alignTo(CharUnits::fromQuantity(
233 layout.getABITypeAlignment(elementType)));
234 offset += CharUnits::fromQuantity(layout.getTypeStoreSize(elementType));
235 } while (++cacheEnd != end);
236 }
237
238 // Cache and return.
239 CachedOffsetEnd = cacheEnd;
240 CachedOffsetFromGlobal = offset;
241 return offset;
242 }
243
244 llvm::Constant *ConstantAggregateBuilderBase::finishArray(llvm::Type *eltTy) {
245 markFinished();
246
247 auto &buffer = getBuffer();
248 assert((Begin < buffer.size() ||
249 (Begin == buffer.size() && eltTy))
250 && "didn't add any array elements without element type");
251 auto elts = llvm::makeArrayRef(buffer).slice(Begin);
252 if (!eltTy) eltTy = elts[0]->getType();
253 auto type = llvm::ArrayType::get(eltTy, elts.size());
254 auto constant = llvm::ConstantArray::get(type, elts);
255 buffer.erase(buffer.begin() + Begin, buffer.end());
256 return constant;
257 }
258
259 llvm::Constant *
260 ConstantAggregateBuilderBase::finishStruct(llvm::StructType *ty) {
261 markFinished();
262
263 auto &buffer = getBuffer();
264 auto elts = llvm::makeArrayRef(buffer).slice(Begin);
265
266 if (ty == nullptr && elts.empty())
267 ty = llvm::StructType::get(Builder.CGM.getLLVMContext(), {}, Packed);
268
269 llvm::Constant *constant;
270 if (ty) {
271 assert(ty->isPacked() == Packed);
272 constant = llvm::ConstantStruct::get(ty, elts);
273 } else {
274 constant = llvm::ConstantStruct::getAnon(elts, Packed);
275 }
276
277 buffer.erase(buffer.begin() + Begin, buffer.end());
278 return constant;
279 }
clang::ast_matchers::type
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
Definition: ASTMatchersInternal.cpp:638
clang::CharUnits::alignTo
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 ...
Definition: CharUnits.h:188
clang::CodeGen::ConstantAggregateBuilderBase::addSize
void addSize(CharUnits size)
Add an integer value of type size_t.
Definition: ConstantInitBuilder.cpp:124
clang::CodeGen::ConstantInitFuture::ConstantInitFuture
ConstantInitFuture()
Definition: ConstantInitFuture.h:56
llvm::SmallVectorImpl
Definition: LLVM.h:36
clang::CharUnits
CharUnits - This is an opaque type for sizes expressed in character units.
Definition: CharUnits.h:38
clang::CharUnits::getAsAlign
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
Definition: CharUnits.h:183
clang::transformer::name
RangeSelector name(std::string ID)
Given a node with a "name", (like NamedDecl, DeclRefExpr or CxxCtorInitializer) selects the name&#39;s to...
Definition: RangeSelector.cpp:186
clang::CodeGen::ConstantAggregateBuilderBase::getAddrOfCurrentPosition
llvm::Constant * getAddrOfCurrentPosition(llvm::Type *type)
Produce an address which will eventually point to the next position to be filled. ...
Definition: ConstantInitBuilder.cpp:148
clang::CodeGen::ConstantAggregateBuilderBase::finishArray
llvm::Constant * finishArray(llvm::Type *eltTy)
Definition: ConstantInitBuilder.cpp:244
Parent
NodeId Parent
Definition: ASTDiff.cpp:191
clang::CodeGen::ConstantInitFuture::abandon
void abandon()
Abandon this initializer.
Definition: ConstantInitBuilder.cpp:30
CodeGenModule.h
clang::CodeGen::ConstantInitFuture::getType
llvm::Type * getType() const
Return the type of the initializer.
Definition: ConstantInitBuilder.cpp:21
Begin
SourceLocation Begin
Definition: USRLocFinder.cpp:164
clang::CharUnits::fromQuantity
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition: CharUnits.h:63
clang::CodeGen::AlignmentSource::Type
The l-value was considered opaque, so the alignment was determined from a type.
clang::CodeGen::ConstantInitFuture
A "future" for a completed constant initializer, which can be passed around independently of any sub-...
Definition: ConstantInitFuture.h:47
clang
Dataflow Directional Tag Classes.
Definition: CFGReachabilityAnalysis.h:21
type
clang::CodeGen::ConstantAggregateBuilderBase::finishStruct
llvm::Constant * finishStruct(llvm::StructType *structTy)
Definition: ConstantInitBuilder.cpp:260
clang::CodeGen::ConstantAggregateBuilderBase::addPlaceholderWithSize
PlaceholderPosition addPlaceholderWithSize(llvm::Type *expectedType)
Add a placeholder, giving the expected type that will be filled in.
Definition: ConstantInitBuilder.cpp:182
ConstantInitBuilder.h
clang::CodeGen::ConstantAggregateBuilderBase::PlaceholderPosition
An opaque class to hold the abstract position of a placeholder.
Definition: ConstantInitBuilder.h:256
clang::CodeGen::ConstantInitFuture::installInGlobal
void installInGlobal(llvm::GlobalVariable *global)
Install the initializer into a global variable.
Definition: ConstantInitBuilder.cpp:38
clang::CodeGen::ConstantInitBuilderBase
Definition: ConstantInitBuilder.h:51