Coverage Report

Created: 2020-09-19 12:23

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/CodeGen/ConstantInitBuilder.cpp
Line
Count
Source (jump to first uncovered line)
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
0
llvm::Type *ConstantInitFuture::getType() const {
22
0
  assert(Data && "dereferencing null future");
23
0
  if (Data.is<llvm::Constant*>()) {
24
0
    return Data.get<llvm::Constant*>()->getType();
25
0
  } else {
26
0
    return Data.get<ConstantInitBuilderBase*>()->Buffer[0]->getType();
27
0
  }
28
0
}
29
30
0
void ConstantInitFuture::abandon() {
31
0
  assert(Data && "abandoning null future");
32
0
  if (auto builder = Data.dyn_cast<ConstantInitBuilderBase*>()) {
33
0
    builder->abandon(0);
34
0
  }
35
0
  Data = nullptr;
36
0
}
37
38
0
void ConstantInitFuture::installInGlobal(llvm::GlobalVariable *GV) {
39
0
  assert(Data && "installing null future");
40
0
  if (Data.is<llvm::Constant*>()) {
41
0
    GV->setInitializer(Data.get<llvm::Constant*>());
42
0
  } else {
43
0
    auto &builder = *Data.get<ConstantInitBuilderBase*>();
44
0
    assert(builder.Buffer.size() == 1);
45
0
    builder.setGlobalInitializer(GV, builder.Buffer[0]);
46
0
    builder.Buffer.clear();
47
0
    Data = nullptr;
48
0
  }
49
0
}
50
51
ConstantInitFuture
52
0
ConstantInitBuilderBase::createFuture(llvm::Constant *initializer) {
53
0
  assert(Buffer.empty() && "buffer not current empty");
54
0
  Buffer.push_back(initializer);
55
0
  return ConstantInitFuture(this);
56
0
}
57
58
// Only used in this file.
59
inline ConstantInitFuture::ConstantInitFuture(ConstantInitBuilderBase *builder)
60
0
    : Data(builder) {
61
0
  assert(!builder->Frozen);
62
0
  assert(builder->Buffer.size() == 1);
63
0
  assert(builder->Buffer[0] != nullptr);
64
0
}
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
23.6k
                                      unsigned addressSpace) {
73
23.6k
  auto GV = new llvm::GlobalVariable(CGM.getModule(),
74
23.6k
                                     initializer->getType(),
75
23.6k
                                     constant,
76
23.6k
                                     linkage,
77
23.6k
                                     initializer,
78
23.6k
                                     name,
79
23.6k
                                     /*insert before*/ nullptr,
80
23.6k
                                     llvm::GlobalValue::NotThreadLocal,
81
23.6k
                                     addressSpace);
82
23.6k
  GV->setAlignment(alignment.getAsAlign());
83
23.6k
  resolveSelfReferences(GV);
84
23.6k
  return GV;
85
23.6k
}
86
87
void ConstantInitBuilderBase::setGlobalInitializer(llvm::GlobalVariable *GV,
88
4.63k
                                                   llvm::Constant *initializer){
89
4.63k
  GV->setInitializer(initializer);
90
4.63k
91
4.63k
  if (!SelfReferences.empty())
92
50
    resolveSelfReferences(GV);
93
4.63k
}
94
95
23.6k
void ConstantInitBuilderBase::resolveSelfReferences(llvm::GlobalVariable *GV) {
96
145
  for (auto &entry : SelfReferences) {
97
145
    llvm::Constant *resolvedReference =
98
145
      llvm::ConstantExpr::getInBoundsGetElementPtr(
99
145
        GV->getValueType(), GV, entry.Indices);
100
145
    auto dummy = entry.Dummy;
101
145
    dummy->replaceAllUsesWith(resolvedReference);
102
145
    dummy->eraseFromParent();
103
145
  }
104
23.6k
  SelfReferences.clear();
105
23.6k
}
106
107
788
void ConstantInitBuilderBase::abandon(size_t newEnd) {
108
  // Remove all the entries we've added.
109
788
  Buffer.erase(Buffer.begin() + newEnd, Buffer.end());
110
788
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
788
  if (newEnd == 0) {
115
0
    for (auto &entry : SelfReferences) {
116
0
      auto dummy = entry.Dummy;
117
0
      dummy->replaceAllUsesWith(llvm::UndefValue::get(dummy->getType()));
118
0
      dummy->eraseFromParent();
119
0
    }
120
394
    SelfReferences.clear();
121
394
  }
122
788
}
123
124
0
void ConstantAggregateBuilderBase::addSize(CharUnits size) {
125
0
  add(Builder.CGM.getSize(size));
126
0
}
127
128
llvm::Constant *
129
ConstantAggregateBuilderBase::getRelativeOffset(llvm::IntegerType *offsetType,
130
0
                                                llvm::Constant *target) {
131
0
  return getRelativeOffsetToPosition(offsetType, target,
132
0
                                     Builder.Buffer.size() - Begin);
133
0
}
134
135
llvm::Constant *ConstantAggregateBuilderBase::getRelativeOffsetToPosition(
136
145
    llvm::IntegerType *offsetType, llvm::Constant *target, size_t position) {
137
  // Compute the address of the relative-address slot.
138
145
  auto base = getAddrOfPosition(offsetType, position);
139
145
140
  // Subtract.
141
145
  base = llvm::ConstantExpr::getPtrToInt(base, Builder.CGM.IntPtrTy);
142
145
  target = llvm::ConstantExpr::getPtrToInt(target, Builder.CGM.IntPtrTy);
143
145
  llvm::Constant *offset = llvm::ConstantExpr::getSub(target, base);
144
145
145
  // Truncate to the relative-address type if necessary.
146
145
  if (Builder.CGM.IntPtrTy != offsetType) {
147
145
    offset = llvm::ConstantExpr::getTrunc(offset, offsetType);
148
145
  }
149
145
150
145
  return offset;
151
145
}
152
153
llvm::Constant *
154
ConstantAggregateBuilderBase::getAddrOfPosition(llvm::Type *type,
155
145
                                                size_t position) {
156
  // Make a global variable.  We will replace this with a GEP to this
157
  // position after installing the initializer.
158
145
  auto dummy = new llvm::GlobalVariable(Builder.CGM.getModule(), type, true,
159
145
                                        llvm::GlobalVariable::PrivateLinkage,
160
145
                                        nullptr, "");
161
145
  Builder.SelfReferences.emplace_back(dummy);
162
145
  auto &entry = Builder.SelfReferences.back();
163
145
  (void)getGEPIndicesTo(entry.Indices, position + Begin);
164
145
  return dummy;
165
145
}
166
167
llvm::Constant *
168
0
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.
171
0
  auto dummy =
172
0
    new llvm::GlobalVariable(Builder.CGM.getModule(), type, true,
173
0
                             llvm::GlobalVariable::PrivateLinkage,
174
0
                             nullptr, "");
175
0
  Builder.SelfReferences.emplace_back(dummy);
176
0
  auto &entry = Builder.SelfReferences.back();
177
0
  (void) getGEPIndicesToCurrentPosition(entry.Indices);
178
0
  return dummy;
179
0
}
180
181
void ConstantAggregateBuilderBase::getGEPIndicesTo(
182
                               llvm::SmallVectorImpl<llvm::Constant*> &indices,
183
290
                               size_t position) const {
184
  // Recurse on the parent builder if present.
185
290
  if (Parent) {
186
145
    Parent->getGEPIndicesTo(indices, Begin);
187
145
188
  // Otherwise, add an index to drill into the first level of pointer.
189
145
  } else {
190
145
    assert(indices.empty());
191
145
    indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty, 0));
192
145
  }
193
290
194
290
  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
290
  indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty,
198
290
                                           position - Begin));
199
290
}
200
201
ConstantAggregateBuilderBase::PlaceholderPosition
202
0
ConstantAggregateBuilderBase::addPlaceholderWithSize(llvm::Type *type) {
203
  // Bring the offset up to the last field.
204
0
  CharUnits offset = getNextOffsetFromGlobal();
205
0
206
  // Create the placeholder.
207
0
  auto position = addPlaceholder();
208
0
209
  // Advance the offset past that field.
210
0
  auto &layout = Builder.CGM.getDataLayout();
211
0
  if (!Packed)
212
0
    offset = offset.alignTo(CharUnits::fromQuantity(
213
0
                                layout.getABITypeAlignment(type)));
214
0
  offset += CharUnits::fromQuantity(layout.getTypeStoreSize(type));
215
0
216
0
  CachedOffsetEnd = Builder.Buffer.size();
217
0
  CachedOffsetFromGlobal = offset;
218
0
219
0
  return position;
220
0
}
221
222
0
CharUnits ConstantAggregateBuilderBase::getOffsetFromGlobalTo(size_t end) const{
223
0
  size_t cacheEnd = CachedOffsetEnd;
224
0
  assert(cacheEnd <= end);
225
0
226
  // Fast path: if the cache is valid, just use it.
227
0
  if (cacheEnd == end) {
228
0
    return CachedOffsetFromGlobal;
229
0
  }
230
0
231
  // If the cached range ends before the index at which the current
232
  // aggregate starts, recurse for the parent.
233
0
  CharUnits offset;
234
0
  if (cacheEnd < Begin) {
235
0
    assert(cacheEnd == 0);
236
0
    assert(Parent && "Begin != 0 for root builder");
237
0
    cacheEnd = Begin;
238
0
    offset = Parent->getOffsetFromGlobalTo(Begin);
239
0
  } else {
240
0
    offset = CachedOffsetFromGlobal;
241
0
  }
242
0
243
  // Perform simple layout on the elements in cacheEnd..<end.
244
0
  if (cacheEnd != end) {
245
0
    auto &layout = Builder.CGM.getDataLayout();
246
0
    do {
247
0
      llvm::Constant *element = Builder.Buffer[cacheEnd];
248
0
      assert(element != nullptr &&
249
0
             "cannot compute offset when a placeholder is present");
250
0
      llvm::Type *elementType = element->getType();
251
0
      if (!Packed)
252
0
        offset = offset.alignTo(CharUnits::fromQuantity(
253
0
                                  layout.getABITypeAlignment(elementType)));
254
0
      offset += CharUnits::fromQuantity(layout.getTypeStoreSize(elementType));
255
0
    } while (++cacheEnd != end);
256
0
  }
257
0
258
  // Cache and return.
259
0
  CachedOffsetEnd = cacheEnd;
260
0
  CachedOffsetFromGlobal = offset;
261
0
  return offset;
262
0
}
263
264
8.82k
llvm::Constant *ConstantAggregateBuilderBase::finishArray(llvm::Type *eltTy) {
265
8.82k
  markFinished();
266
8.82k
267
8.82k
  auto &buffer = getBuffer();
268
8.82k
  assert((Begin < buffer.size() ||
269
8.82k
          (Begin == buffer.size() && eltTy))
270
8.82k
         && "didn't add any array elements without element type");
271
8.82k
  auto elts = llvm::makeArrayRef(buffer).slice(Begin);
272
8.82k
  if (!eltTy) 
eltTy = elts[0]->getType()17
;
273
8.82k
  auto type = llvm::ArrayType::get(eltTy, elts.size());
274
8.82k
  auto constant = llvm::ConstantArray::get(type, elts);
275
8.82k
  buffer.erase(buffer.begin() + Begin, buffer.end());
276
8.82k
  return constant;
277
8.82k
}
278
279
llvm::Constant *
280
33.7k
ConstantAggregateBuilderBase::finishStruct(llvm::StructType *ty) {
281
33.7k
  markFinished();
282
33.7k
283
33.7k
  auto &buffer = getBuffer();
284
33.7k
  auto elts = llvm::makeArrayRef(buffer).slice(Begin);
285
33.7k
286
33.7k
  if (ty == nullptr && 
elts.empty()6.58k
)
287
0
    ty = llvm::StructType::get(Builder.CGM.getLLVMContext(), {}, Packed);
288
33.7k
289
33.7k
  llvm::Constant *constant;
290
33.7k
  if (ty) {
291
27.1k
    assert(ty->isPacked() == Packed);
292
27.1k
    constant = llvm::ConstantStruct::get(ty, elts);
293
6.58k
  } else {
294
6.58k
    constant = llvm::ConstantStruct::getAnon(elts, Packed);
295
6.58k
  }
296
33.7k
297
33.7k
  buffer.erase(buffer.begin() + Begin, buffer.end());
298
33.7k
  return constant;
299
33.7k
}