clang  6.0.0svn
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 
17 #include "CodeGenModule.h"
18 
19 using namespace clang;
20 using namespace CodeGen;
21 
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 
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 
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.
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 
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 *
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(
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 
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 
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 *
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 }
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
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
void addSize(CharUnits size)
Add an integer value of type size_t.
CharUnits - This is an opaque type for sizes expressed in character units.
Definition: CharUnits.h:38
llvm::Constant * getAddrOfCurrentPosition(llvm::Type *type)
Produce an address which will eventually point to the the next position to be filled.
llvm::Constant * finishArray(llvm::Type *eltTy)
NodeId Parent
Definition: ASTDiff.cpp:192
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition: CharUnits.h:179
void abandon()
Abandon this initializer.
llvm::Type * getType() const
Return the type of the initializer.
SourceLocation Begin
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition: CharUnits.h:63
The l-value was considered opaque, so the alignment was determined from a type.
A "future" for a completed constant initializer, which can be passed around independently of any sub-...
Dataflow Directional Tag Classes.
llvm::Constant * finishStruct(llvm::StructType *structTy)
PlaceholderPosition addPlaceholderWithSize(llvm::Type *expectedType)
Add a placeholder, giving the expected type that will be filled in.
An opaque class to hold the abstract position of a placeholder.
void installInGlobal(llvm::GlobalVariable *global)
Install the initializer into a global variable.