clang 8.0.0

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