Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===- ConstantInitBuilder.h - Builder for LLVM IR constants ----*- C++ -*-===//
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 class provides a convenient interface for building complex
10
// global initializers of the sort that are frequently required for
11
// language ABIs.
12
//
13
//===----------------------------------------------------------------------===//
14
 
15
#ifndef LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H
16
#define LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H
17
 
18
#include "llvm/ADT/ArrayRef.h"
19
#include "llvm/ADT/SmallVector.h"
20
#include "llvm/IR/Constants.h"
21
#include "llvm/IR/GlobalValue.h"
22
#include "clang/AST/CharUnits.h"
23
#include "clang/CodeGen/ConstantInitFuture.h"
24
 
25
#include <vector>
26
 
27
namespace clang {
28
namespace CodeGen {
29
 
30
class CodeGenModule;
31
 
32
/// A convenience builder class for complex constant initializers,
33
/// especially for anonymous global structures used by various language
34
/// runtimes.
35
///
36
/// The basic usage pattern is expected to be something like:
37
///    ConstantInitBuilder builder(CGM);
38
///    auto toplevel = builder.beginStruct();
39
///    toplevel.addInt(CGM.SizeTy, widgets.size());
40
///    auto widgetArray = builder.beginArray();
41
///    for (auto &widget : widgets) {
42
///      auto widgetDesc = widgetArray.beginStruct();
43
///      widgetDesc.addInt(CGM.SizeTy, widget.getPower());
44
///      widgetDesc.add(CGM.GetAddrOfConstantString(widget.getName()));
45
///      widgetDesc.add(CGM.GetAddrOfGlobal(widget.getInitializerDecl()));
46
///      widgetDesc.finishAndAddTo(widgetArray);
47
///    }
48
///    widgetArray.finishAndAddTo(toplevel);
49
///    auto global = toplevel.finishAndCreateGlobal("WIDGET_LIST", Align,
50
///                                                 /*constant*/ true);
51
class ConstantInitBuilderBase {
52
  struct SelfReference {
53
    llvm::GlobalVariable *Dummy;
54
    llvm::SmallVector<llvm::Constant*, 4> Indices;
55
 
56
    SelfReference(llvm::GlobalVariable *dummy) : Dummy(dummy) {}
57
  };
58
  CodeGenModule &CGM;
59
  llvm::SmallVector<llvm::Constant*, 16> Buffer;
60
  std::vector<SelfReference> SelfReferences;
61
  bool Frozen = false;
62
 
63
  friend class ConstantInitFuture;
64
  friend class ConstantAggregateBuilderBase;
65
  template <class, class>
66
  friend class ConstantAggregateBuilderTemplateBase;
67
 
68
protected:
69
  explicit ConstantInitBuilderBase(CodeGenModule &CGM) : CGM(CGM) {}
70
 
71
  ~ConstantInitBuilderBase() {
72
    assert(Buffer.empty() && "didn't claim all values out of buffer");
73
    assert(SelfReferences.empty() && "didn't apply all self-references");
74
  }
75
 
76
private:
77
  llvm::GlobalVariable *createGlobal(llvm::Constant *initializer,
78
                                     const llvm::Twine &name,
79
                                     CharUnits alignment,
80
                                     bool constant = false,
81
                                     llvm::GlobalValue::LinkageTypes linkage
82
                                       = llvm::GlobalValue::InternalLinkage,
83
                                     unsigned addressSpace = 0);
84
 
85
  ConstantInitFuture createFuture(llvm::Constant *initializer);
86
 
87
  void setGlobalInitializer(llvm::GlobalVariable *GV,
88
                            llvm::Constant *initializer);
89
 
90
  void resolveSelfReferences(llvm::GlobalVariable *GV);
91
 
92
  void abandon(size_t newEnd);
93
};
94
 
95
/// A concrete base class for struct and array aggregate
96
/// initializer builders.
97
class ConstantAggregateBuilderBase {
98
protected:
99
  ConstantInitBuilderBase &Builder;
100
  ConstantAggregateBuilderBase *Parent;
101
  size_t Begin;
102
  mutable size_t CachedOffsetEnd = 0;
103
  bool Finished = false;
104
  bool Frozen = false;
105
  bool Packed = false;
106
  mutable CharUnits CachedOffsetFromGlobal;
107
 
108
  llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() {
109
    return Builder.Buffer;
110
  }
111
 
112
  const llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() const {
113
    return Builder.Buffer;
114
  }
115
 
116
  ConstantAggregateBuilderBase(ConstantInitBuilderBase &builder,
117
                               ConstantAggregateBuilderBase *parent)
118
      : Builder(builder), Parent(parent), Begin(builder.Buffer.size()) {
119
    if (parent) {
120
      assert(!parent->Frozen && "parent already has child builder active");
121
      parent->Frozen = true;
122
    } else {
123
      assert(!builder.Frozen && "builder already has child builder active");
124
      builder.Frozen = true;
125
    }
126
  }
127
 
128
  ~ConstantAggregateBuilderBase() {
129
    assert(Finished && "didn't finish aggregate builder");
130
  }
131
 
132
  void markFinished() {
133
    assert(!Frozen && "child builder still active");
134
    assert(!Finished && "builder already finished");
135
    Finished = true;
136
    if (Parent) {
137
      assert(Parent->Frozen &&
138
             "parent not frozen while child builder active");
139
      Parent->Frozen = false;
140
    } else {
141
      assert(Builder.Frozen &&
142
             "builder not frozen while child builder active");
143
      Builder.Frozen = false;
144
    }
145
  }
146
 
147
public:
148
  // Not copyable.
149
  ConstantAggregateBuilderBase(const ConstantAggregateBuilderBase &) = delete;
150
  ConstantAggregateBuilderBase &operator=(const ConstantAggregateBuilderBase &)
151
    = delete;
152
 
153
  // Movable, mostly to allow returning.  But we have to write this out
154
  // properly to satisfy the assert in the destructor.
155
  ConstantAggregateBuilderBase(ConstantAggregateBuilderBase &&other)
156
    : Builder(other.Builder), Parent(other.Parent), Begin(other.Begin),
157
      CachedOffsetEnd(other.CachedOffsetEnd),
158
      Finished(other.Finished), Frozen(other.Frozen), Packed(other.Packed),
159
      CachedOffsetFromGlobal(other.CachedOffsetFromGlobal) {
160
    other.Finished = true;
161
  }
162
  ConstantAggregateBuilderBase &operator=(ConstantAggregateBuilderBase &&other)
163
    = delete;
164
 
165
  /// Return the number of elements that have been added to
166
  /// this struct or array.
167
  size_t size() const {
168
    assert(!this->Finished && "cannot query after finishing builder");
169
    assert(!this->Frozen && "cannot query while sub-builder is active");
170
    assert(this->Begin <= this->getBuffer().size());
171
    return this->getBuffer().size() - this->Begin;
172
  }
173
 
174
  /// Return true if no elements have yet been added to this struct or array.
175
  bool empty() const {
176
    return size() == 0;
177
  }
178
 
179
  /// Abandon this builder completely.
180
  void abandon() {
181
    markFinished();
182
    Builder.abandon(Begin);
183
  }
184
 
185
  /// Add a new value to this initializer.
186
  void add(llvm::Constant *value) {
187
    assert(value && "adding null value to constant initializer");
188
    assert(!Finished && "cannot add more values after finishing builder");
189
    assert(!Frozen && "cannot add values while subbuilder is active");
190
    Builder.Buffer.push_back(value);
191
  }
192
 
193
  /// Add an integer value of type size_t.
194
  void addSize(CharUnits size);
195
 
196
  /// Add an integer value of a specific type.
197
  void addInt(llvm::IntegerType *intTy, uint64_t value,
198
              bool isSigned = false) {
199
    add(llvm::ConstantInt::get(intTy, value, isSigned));
200
  }
201
 
202
  /// Add a null pointer of a specific type.
203
  void addNullPointer(llvm::PointerType *ptrTy) {
204
    add(llvm::ConstantPointerNull::get(ptrTy));
205
  }
206
 
207
  /// Add a bitcast of a value to a specific type.
208
  void addBitCast(llvm::Constant *value, llvm::Type *type) {
209
    add(llvm::ConstantExpr::getBitCast(value, type));
210
  }
211
 
212
  /// Add a bunch of new values to this initializer.
213
  void addAll(llvm::ArrayRef<llvm::Constant *> values) {
214
    assert(!Finished && "cannot add more values after finishing builder");
215
    assert(!Frozen && "cannot add values while subbuilder is active");
216
    Builder.Buffer.append(values.begin(), values.end());
217
  }
218
 
219
  /// Add a relative offset to the given target address, i.e. the
220
  /// static difference between the target address and the address
221
  /// of the relative offset.  The target must be known to be defined
222
  /// in the current linkage unit.  The offset will have the given
223
  /// integer type, which must be no wider than intptr_t.  Some
224
  /// targets may not fully support this operation.
225
  void addRelativeOffset(llvm::IntegerType *type, llvm::Constant *target) {
226
    add(getRelativeOffset(type, target));
227
  }
228
 
229
  /// Same as addRelativeOffset(), but instead relative to an element in this
230
  /// aggregate, identified by its index.
231
  void addRelativeOffsetToPosition(llvm::IntegerType *type,
232
                                   llvm::Constant *target, size_t position) {
233
    add(getRelativeOffsetToPosition(type, target, position));
234
  }
235
 
236
  /// Add a relative offset to the target address, plus a small
237
  /// constant offset.  This is primarily useful when the relative
238
  /// offset is known to be a multiple of (say) four and therefore
239
  /// the tag can be used to express an extra two bits of information.
240
  void addTaggedRelativeOffset(llvm::IntegerType *type,
241
                               llvm::Constant *address,
242
                               unsigned tag) {
243
    llvm::Constant *offset = getRelativeOffset(type, address);
244
    if (tag) {
245
      offset = llvm::ConstantExpr::getAdd(offset,
246
                                          llvm::ConstantInt::get(type, tag));
247
    }
248
    add(offset);
249
  }
250
 
251
  /// Return the offset from the start of the initializer to the
252
  /// next position, assuming no padding is required prior to it.
253
  ///
254
  /// This operation will not succeed if any unsized placeholders are
255
  /// currently in place in the initializer.
256
  CharUnits getNextOffsetFromGlobal() const {
257
    assert(!Finished && "cannot add more values after finishing builder");
258
    assert(!Frozen && "cannot add values while subbuilder is active");
259
    return getOffsetFromGlobalTo(Builder.Buffer.size());
260
  }
261
 
262
  /// An opaque class to hold the abstract position of a placeholder.
263
  class PlaceholderPosition {
264
    size_t Index;
265
    friend class ConstantAggregateBuilderBase;
266
    PlaceholderPosition(size_t index) : Index(index) {}
267
  };
268
 
269
  /// Add a placeholder value to the structure.  The returned position
270
  /// can be used to set the value later; it will not be invalidated by
271
  /// any intermediate operations except (1) filling the same position or
272
  /// (2) finishing the entire builder.
273
  ///
274
  /// This is useful for emitting certain kinds of structure which
275
  /// contain some sort of summary field, generally a count, before any
276
  /// of the data.  By emitting a placeholder first, the structure can
277
  /// be emitted eagerly.
278
  PlaceholderPosition addPlaceholder() {
279
    assert(!Finished && "cannot add more values after finishing builder");
280
    assert(!Frozen && "cannot add values while subbuilder is active");
281
    Builder.Buffer.push_back(nullptr);
282
    return Builder.Buffer.size() - 1;
283
  }
284
 
285
  /// Add a placeholder, giving the expected type that will be filled in.
286
  PlaceholderPosition addPlaceholderWithSize(llvm::Type *expectedType);
287
 
288
  /// Fill a previously-added placeholder.
289
  void fillPlaceholderWithInt(PlaceholderPosition position,
290
                              llvm::IntegerType *type, uint64_t value,
291
                              bool isSigned = false) {
292
    fillPlaceholder(position, llvm::ConstantInt::get(type, value, isSigned));
293
  }
294
 
295
  /// Fill a previously-added placeholder.
296
  void fillPlaceholder(PlaceholderPosition position, llvm::Constant *value) {
297
    assert(!Finished && "cannot change values after finishing builder");
298
    assert(!Frozen && "cannot add values while subbuilder is active");
299
    llvm::Constant *&slot = Builder.Buffer[position.Index];
300
    assert(slot == nullptr && "placeholder already filled");
301
    slot = value;
302
  }
303
 
304
  /// Produce an address which will eventually point to the next
305
  /// position to be filled.  This is computed with an indexed
306
  /// getelementptr rather than by computing offsets.
307
  ///
308
  /// The returned pointer will have type T*, where T is the given type. This
309
  /// type can differ from the type of the actual element.
310
  llvm::Constant *getAddrOfCurrentPosition(llvm::Type *type);
311
 
312
  /// Produce an address which points to a position in the aggregate being
313
  /// constructed. This is computed with an indexed getelementptr rather than by
314
  /// computing offsets.
315
  ///
316
  /// The returned pointer will have type T*, where T is the given type. This
317
  /// type can differ from the type of the actual element.
318
  llvm::Constant *getAddrOfPosition(llvm::Type *type, size_t position);
319
 
320
  llvm::ArrayRef<llvm::Constant*> getGEPIndicesToCurrentPosition(
321
                           llvm::SmallVectorImpl<llvm::Constant*> &indices) {
322
    getGEPIndicesTo(indices, Builder.Buffer.size());
323
    return indices;
324
  }
325
 
326
protected:
327
  llvm::Constant *finishArray(llvm::Type *eltTy);
328
  llvm::Constant *finishStruct(llvm::StructType *structTy);
329
 
330
private:
331
  void getGEPIndicesTo(llvm::SmallVectorImpl<llvm::Constant*> &indices,
332
                       size_t position) const;
333
 
334
  llvm::Constant *getRelativeOffset(llvm::IntegerType *offsetType,
335
                                    llvm::Constant *target);
336
 
337
  llvm::Constant *getRelativeOffsetToPosition(llvm::IntegerType *offsetType,
338
                                              llvm::Constant *target,
339
                                              size_t position);
340
 
341
  CharUnits getOffsetFromGlobalTo(size_t index) const;
342
};
343
 
344
template <class Impl, class Traits>
345
class ConstantAggregateBuilderTemplateBase
346
    : public Traits::AggregateBuilderBase {
347
  using super = typename Traits::AggregateBuilderBase;
348
public:
349
  using InitBuilder = typename Traits::InitBuilder;
350
  using ArrayBuilder = typename Traits::ArrayBuilder;
351
  using StructBuilder = typename Traits::StructBuilder;
352
  using AggregateBuilderBase = typename Traits::AggregateBuilderBase;
353
 
354
protected:
355
  ConstantAggregateBuilderTemplateBase(InitBuilder &builder,
356
                                       AggregateBuilderBase *parent)
357
    : super(builder, parent) {}
358
 
359
  Impl &asImpl() { return *static_cast<Impl*>(this); }
360
 
361
public:
362
  ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) {
363
    return ArrayBuilder(static_cast<InitBuilder&>(this->Builder), this, eltTy);
364
  }
365
 
366
  StructBuilder beginStruct(llvm::StructType *ty = nullptr) {
367
    return StructBuilder(static_cast<InitBuilder&>(this->Builder), this, ty);
368
  }
369
 
370
  /// Given that this builder was created by beginning an array or struct
371
  /// component on the given parent builder, finish the array/struct
372
  /// component and add it to the parent.
373
  ///
374
  /// It is an intentional choice that the parent is passed in explicitly
375
  /// despite it being redundant with information already kept in the
376
  /// builder.  This aids in readability by making it easier to find the
377
  /// places that add components to a builder, as well as "bookending"
378
  /// the sub-builder more explicitly.
379
  void finishAndAddTo(AggregateBuilderBase &parent) {
380
    assert(this->Parent == &parent && "adding to non-parent builder");
381
    parent.add(asImpl().finishImpl());
382
  }
383
 
384
  /// Given that this builder was created by beginning an array or struct
385
  /// directly on a ConstantInitBuilder, finish the array/struct and
386
  /// create a global variable with it as the initializer.
387
  template <class... As>
388
  llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) {
389
    assert(!this->Parent && "finishing non-root builder");
390
    return this->Builder.createGlobal(asImpl().finishImpl(),
391
                                      std::forward<As>(args)...);
392
  }
393
 
394
  /// Given that this builder was created by beginning an array or struct
395
  /// directly on a ConstantInitBuilder, finish the array/struct and
396
  /// set it as the initializer of the given global variable.
397
  void finishAndSetAsInitializer(llvm::GlobalVariable *global) {
398
    assert(!this->Parent && "finishing non-root builder");
399
    return this->Builder.setGlobalInitializer(global, asImpl().finishImpl());
400
  }
401
 
402
  /// Given that this builder was created by beginning an array or struct
403
  /// directly on a ConstantInitBuilder, finish the array/struct and
404
  /// return a future which can be used to install the initializer in
405
  /// a global later.
406
  ///
407
  /// This is useful for allowing a finished initializer to passed to
408
  /// an API which will build the global.  However, the "future" preserves
409
  /// a dependency on the original builder; it is an error to pass it aside.
410
  ConstantInitFuture finishAndCreateFuture() {
411
    assert(!this->Parent && "finishing non-root builder");
412
    return this->Builder.createFuture(asImpl().finishImpl());
413
  }
414
};
415
 
416
template <class Traits>
417
class ConstantArrayBuilderTemplateBase
418
  : public ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder,
419
                                                Traits> {
420
  using super =
421
    ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder, Traits>;
422
 
423
public:
424
  using InitBuilder = typename Traits::InitBuilder;
425
  using AggregateBuilderBase = typename Traits::AggregateBuilderBase;
426
 
427
private:
428
  llvm::Type *EltTy;
429
 
430
  template <class, class>
431
  friend class ConstantAggregateBuilderTemplateBase;
432
 
433
protected:
434
  ConstantArrayBuilderTemplateBase(InitBuilder &builder,
435
                                   AggregateBuilderBase *parent,
436
                                   llvm::Type *eltTy)
437
    : super(builder, parent), EltTy(eltTy) {}
438
 
439
private:
440
  /// Form an array constant from the values that have been added to this
441
  /// builder.
442
  llvm::Constant *finishImpl() {
443
    return AggregateBuilderBase::finishArray(EltTy);
444
  }
445
};
446
 
447
/// A template class designed to allow other frontends to
448
/// easily customize the builder classes used by ConstantInitBuilder,
449
/// and thus to extend the API to work with the abstractions they
450
/// prefer.  This would probably not be necessary if C++ just
451
/// supported extension methods.
452
template <class Traits>
453
class ConstantStructBuilderTemplateBase
454
  : public ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder,
455
                                                Traits> {
456
  using super =
457
    ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder,Traits>;
458
 
459
public:
460
  using InitBuilder = typename Traits::InitBuilder;
461
  using AggregateBuilderBase = typename Traits::AggregateBuilderBase;
462
 
463
private:
464
  llvm::StructType *StructTy;
465
 
466
  template <class, class>
467
  friend class ConstantAggregateBuilderTemplateBase;
468
 
469
protected:
470
  ConstantStructBuilderTemplateBase(InitBuilder &builder,
471
                                    AggregateBuilderBase *parent,
472
                                    llvm::StructType *structTy)
473
    : super(builder, parent), StructTy(structTy) {
474
    if (structTy) this->Packed = structTy->isPacked();
475
  }
476
 
477
public:
478
  void setPacked(bool packed) {
479
    this->Packed = packed;
480
  }
481
 
482
  /// Use the given type for the struct if its element count is correct.
483
  /// Don't add more elements after calling this.
484
  void suggestType(llvm::StructType *structTy) {
485
    if (this->size() == structTy->getNumElements()) {
486
      StructTy = structTy;
487
    }
488
  }
489
 
490
private:
491
  /// Form an array constant from the values that have been added to this
492
  /// builder.
493
  llvm::Constant *finishImpl() {
494
    return AggregateBuilderBase::finishStruct(StructTy);
495
  }
496
};
497
 
498
/// A template class designed to allow other frontends to
499
/// easily customize the builder classes used by ConstantInitBuilder,
500
/// and thus to extend the API to work with the abstractions they
501
/// prefer.  This would probably not be necessary if C++ just
502
/// supported extension methods.
503
template <class Traits>
504
class ConstantInitBuilderTemplateBase : public ConstantInitBuilderBase {
505
protected:
506
  ConstantInitBuilderTemplateBase(CodeGenModule &CGM)
507
    : ConstantInitBuilderBase(CGM) {}
508
 
509
public:
510
  using InitBuilder = typename Traits::InitBuilder;
511
  using ArrayBuilder = typename Traits::ArrayBuilder;
512
  using StructBuilder = typename Traits::StructBuilder;
513
 
514
  ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) {
515
    return ArrayBuilder(static_cast<InitBuilder&>(*this), nullptr, eltTy);
516
  }
517
 
518
  StructBuilder beginStruct(llvm::StructType *structTy = nullptr) {
519
    return StructBuilder(static_cast<InitBuilder&>(*this), nullptr, structTy);
520
  }
521
};
522
 
523
class ConstantInitBuilder;
524
class ConstantStructBuilder;
525
class ConstantArrayBuilder;
526
 
527
struct ConstantInitBuilderTraits {
528
  using InitBuilder = ConstantInitBuilder;
529
  using AggregateBuilderBase = ConstantAggregateBuilderBase;
530
  using ArrayBuilder = ConstantArrayBuilder;
531
  using StructBuilder = ConstantStructBuilder;
532
};
533
 
534
/// The standard implementation of ConstantInitBuilder used in Clang.
535
class ConstantInitBuilder
536
    : public ConstantInitBuilderTemplateBase<ConstantInitBuilderTraits> {
537
public:
538
  explicit ConstantInitBuilder(CodeGenModule &CGM) :
539
    ConstantInitBuilderTemplateBase(CGM) {}
540
};
541
 
542
/// A helper class of ConstantInitBuilder, used for building constant
543
/// array initializers.
544
class ConstantArrayBuilder
545
    : public ConstantArrayBuilderTemplateBase<ConstantInitBuilderTraits> {
546
  template <class Traits>
547
  friend class ConstantInitBuilderTemplateBase;
548
 
549
  // The use of explicit qualification is a GCC workaround.
550
  template <class Impl, class Traits>
551
  friend class CodeGen::ConstantAggregateBuilderTemplateBase;
552
 
553
  ConstantArrayBuilder(ConstantInitBuilder &builder,
554
                       ConstantAggregateBuilderBase *parent,
555
                       llvm::Type *eltTy)
556
    : ConstantArrayBuilderTemplateBase(builder, parent, eltTy) {}
557
};
558
 
559
/// A helper class of ConstantInitBuilder, used for building constant
560
/// struct initializers.
561
class ConstantStructBuilder
562
    : public ConstantStructBuilderTemplateBase<ConstantInitBuilderTraits> {
563
  template <class Traits>
564
  friend class ConstantInitBuilderTemplateBase;
565
 
566
  // The use of explicit qualification is a GCC workaround.
567
  template <class Impl, class Traits>
568
  friend class CodeGen::ConstantAggregateBuilderTemplateBase;
569
 
570
  ConstantStructBuilder(ConstantInitBuilder &builder,
571
                        ConstantAggregateBuilderBase *parent,
572
                        llvm::StructType *structTy)
573
    : ConstantStructBuilderTemplateBase(builder, parent, structTy) {}
574
};
575
 
576
}  // end namespace CodeGen
577
}  // end namespace clang
578
 
579
#endif