File indexing completed on 2026-05-10 08:36:52
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H
0016 #define LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H
0017
0018 #include "llvm/ADT/ArrayRef.h"
0019 #include "llvm/ADT/SmallVector.h"
0020 #include "llvm/IR/Constants.h"
0021 #include "llvm/IR/GlobalValue.h"
0022 #include "clang/AST/CharUnits.h"
0023 #include "clang/CodeGen/ConstantInitFuture.h"
0024
0025 #include <vector>
0026
0027 namespace clang {
0028 class GlobalDecl;
0029 class PointerAuthSchema;
0030 class QualType;
0031
0032 namespace CodeGen {
0033 class CodeGenModule;
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 class ConstantInitBuilderBase {
0055 struct SelfReference {
0056 llvm::GlobalVariable *Dummy;
0057 llvm::SmallVector<llvm::Constant*, 4> Indices;
0058
0059 SelfReference(llvm::GlobalVariable *dummy) : Dummy(dummy) {}
0060 };
0061 CodeGenModule &CGM;
0062 llvm::SmallVector<llvm::Constant*, 16> Buffer;
0063 std::vector<SelfReference> SelfReferences;
0064 bool Frozen = false;
0065
0066 friend class ConstantInitFuture;
0067 friend class ConstantAggregateBuilderBase;
0068 template <class, class>
0069 friend class ConstantAggregateBuilderTemplateBase;
0070
0071 protected:
0072 explicit ConstantInitBuilderBase(CodeGenModule &CGM) : CGM(CGM) {}
0073
0074 ~ConstantInitBuilderBase() {
0075 assert(Buffer.empty() && "didn't claim all values out of buffer");
0076 assert(SelfReferences.empty() && "didn't apply all self-references");
0077 }
0078
0079 private:
0080 llvm::GlobalVariable *createGlobal(llvm::Constant *initializer,
0081 const llvm::Twine &name,
0082 CharUnits alignment,
0083 bool constant = false,
0084 llvm::GlobalValue::LinkageTypes linkage
0085 = llvm::GlobalValue::InternalLinkage,
0086 unsigned addressSpace = 0);
0087
0088 ConstantInitFuture createFuture(llvm::Constant *initializer);
0089
0090 void setGlobalInitializer(llvm::GlobalVariable *GV,
0091 llvm::Constant *initializer);
0092
0093 void resolveSelfReferences(llvm::GlobalVariable *GV);
0094
0095 void abandon(size_t newEnd);
0096 };
0097
0098
0099
0100 class ConstantAggregateBuilderBase {
0101 protected:
0102 ConstantInitBuilderBase &Builder;
0103 ConstantAggregateBuilderBase *Parent;
0104 size_t Begin;
0105 mutable size_t CachedOffsetEnd = 0;
0106 bool Finished = false;
0107 bool Frozen = false;
0108 bool Packed = false;
0109 mutable CharUnits CachedOffsetFromGlobal;
0110
0111 llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() {
0112 return Builder.Buffer;
0113 }
0114
0115 const llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() const {
0116 return Builder.Buffer;
0117 }
0118
0119 ConstantAggregateBuilderBase(ConstantInitBuilderBase &builder,
0120 ConstantAggregateBuilderBase *parent)
0121 : Builder(builder), Parent(parent), Begin(builder.Buffer.size()) {
0122 if (parent) {
0123 assert(!parent->Frozen && "parent already has child builder active");
0124 parent->Frozen = true;
0125 } else {
0126 assert(!builder.Frozen && "builder already has child builder active");
0127 builder.Frozen = true;
0128 }
0129 }
0130
0131 ~ConstantAggregateBuilderBase() {
0132 assert(Finished && "didn't finish aggregate builder");
0133 }
0134
0135 void markFinished() {
0136 assert(!Frozen && "child builder still active");
0137 assert(!Finished && "builder already finished");
0138 Finished = true;
0139 if (Parent) {
0140 assert(Parent->Frozen &&
0141 "parent not frozen while child builder active");
0142 Parent->Frozen = false;
0143 } else {
0144 assert(Builder.Frozen &&
0145 "builder not frozen while child builder active");
0146 Builder.Frozen = false;
0147 }
0148 }
0149
0150 public:
0151
0152 ConstantAggregateBuilderBase(const ConstantAggregateBuilderBase &) = delete;
0153 ConstantAggregateBuilderBase &operator=(const ConstantAggregateBuilderBase &)
0154 = delete;
0155
0156
0157
0158 ConstantAggregateBuilderBase(ConstantAggregateBuilderBase &&other)
0159 : Builder(other.Builder), Parent(other.Parent), Begin(other.Begin),
0160 CachedOffsetEnd(other.CachedOffsetEnd),
0161 Finished(other.Finished), Frozen(other.Frozen), Packed(other.Packed),
0162 CachedOffsetFromGlobal(other.CachedOffsetFromGlobal) {
0163 other.Finished = true;
0164 }
0165 ConstantAggregateBuilderBase &operator=(ConstantAggregateBuilderBase &&other)
0166 = delete;
0167
0168
0169
0170 size_t size() const {
0171 assert(!this->Finished && "cannot query after finishing builder");
0172 assert(!this->Frozen && "cannot query while sub-builder is active");
0173 assert(this->Begin <= this->getBuffer().size());
0174 return this->getBuffer().size() - this->Begin;
0175 }
0176
0177
0178 bool empty() const {
0179 return size() == 0;
0180 }
0181
0182
0183 void abandon() {
0184 markFinished();
0185 Builder.abandon(Begin);
0186 }
0187
0188
0189 void add(llvm::Constant *value) {
0190 assert(value && "adding null value to constant initializer");
0191 assert(!Finished && "cannot add more values after finishing builder");
0192 assert(!Frozen && "cannot add values while subbuilder is active");
0193 Builder.Buffer.push_back(value);
0194 }
0195
0196
0197 void addSize(CharUnits size);
0198
0199
0200 void addInt(llvm::IntegerType *intTy, uint64_t value,
0201 bool isSigned = false) {
0202 add(llvm::ConstantInt::get(intTy, value, isSigned));
0203 }
0204
0205
0206 void addSignedPointer(llvm::Constant *Pointer,
0207 const PointerAuthSchema &Schema, GlobalDecl CalleeDecl,
0208 QualType CalleeType);
0209
0210
0211 void addNullPointer(llvm::PointerType *ptrTy) {
0212 add(llvm::ConstantPointerNull::get(ptrTy));
0213 }
0214
0215
0216 void addAll(llvm::ArrayRef<llvm::Constant *> values) {
0217 assert(!Finished && "cannot add more values after finishing builder");
0218 assert(!Frozen && "cannot add values while subbuilder is active");
0219 Builder.Buffer.append(values.begin(), values.end());
0220 }
0221
0222
0223
0224
0225
0226
0227
0228 void addRelativeOffset(llvm::IntegerType *type, llvm::Constant *target) {
0229 add(getRelativeOffset(type, target));
0230 }
0231
0232
0233
0234 void addRelativeOffsetToPosition(llvm::IntegerType *type,
0235 llvm::Constant *target, size_t position) {
0236 add(getRelativeOffsetToPosition(type, target, position));
0237 }
0238
0239
0240
0241
0242
0243 void addTaggedRelativeOffset(llvm::IntegerType *type,
0244 llvm::Constant *address,
0245 unsigned tag) {
0246 llvm::Constant *offset = getRelativeOffset(type, address);
0247 if (tag) {
0248 offset = llvm::ConstantExpr::getAdd(offset,
0249 llvm::ConstantInt::get(type, tag));
0250 }
0251 add(offset);
0252 }
0253
0254
0255
0256
0257
0258
0259 CharUnits getNextOffsetFromGlobal() const {
0260 assert(!Finished && "cannot add more values after finishing builder");
0261 assert(!Frozen && "cannot add values while subbuilder is active");
0262 return getOffsetFromGlobalTo(Builder.Buffer.size());
0263 }
0264
0265
0266 class PlaceholderPosition {
0267 size_t Index;
0268 friend class ConstantAggregateBuilderBase;
0269 PlaceholderPosition(size_t index) : Index(index) {}
0270 };
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281 PlaceholderPosition addPlaceholder() {
0282 assert(!Finished && "cannot add more values after finishing builder");
0283 assert(!Frozen && "cannot add values while subbuilder is active");
0284 Builder.Buffer.push_back(nullptr);
0285 return Builder.Buffer.size() - 1;
0286 }
0287
0288
0289 PlaceholderPosition addPlaceholderWithSize(llvm::Type *expectedType);
0290
0291
0292 void fillPlaceholderWithInt(PlaceholderPosition position,
0293 llvm::IntegerType *type, uint64_t value,
0294 bool isSigned = false) {
0295 fillPlaceholder(position, llvm::ConstantInt::get(type, value, isSigned));
0296 }
0297
0298
0299 void fillPlaceholder(PlaceholderPosition position, llvm::Constant *value) {
0300 assert(!Finished && "cannot change values after finishing builder");
0301 assert(!Frozen && "cannot add values while subbuilder is active");
0302 llvm::Constant *&slot = Builder.Buffer[position.Index];
0303 assert(slot == nullptr && "placeholder already filled");
0304 slot = value;
0305 }
0306
0307
0308
0309
0310
0311
0312
0313 llvm::Constant *getAddrOfCurrentPosition(llvm::Type *type);
0314
0315
0316
0317
0318
0319
0320
0321 llvm::Constant *getAddrOfPosition(llvm::Type *type, size_t position);
0322
0323 llvm::ArrayRef<llvm::Constant*> getGEPIndicesToCurrentPosition(
0324 llvm::SmallVectorImpl<llvm::Constant*> &indices) {
0325 getGEPIndicesTo(indices, Builder.Buffer.size());
0326 return indices;
0327 }
0328
0329 protected:
0330 llvm::Constant *finishArray(llvm::Type *eltTy);
0331 llvm::Constant *finishStruct(llvm::StructType *structTy);
0332
0333 private:
0334 void getGEPIndicesTo(llvm::SmallVectorImpl<llvm::Constant*> &indices,
0335 size_t position) const;
0336
0337 llvm::Constant *getRelativeOffset(llvm::IntegerType *offsetType,
0338 llvm::Constant *target);
0339
0340 llvm::Constant *getRelativeOffsetToPosition(llvm::IntegerType *offsetType,
0341 llvm::Constant *target,
0342 size_t position);
0343
0344 CharUnits getOffsetFromGlobalTo(size_t index) const;
0345 };
0346
0347 template <class Impl, class Traits>
0348 class ConstantAggregateBuilderTemplateBase
0349 : public Traits::AggregateBuilderBase {
0350 using super = typename Traits::AggregateBuilderBase;
0351 public:
0352 using InitBuilder = typename Traits::InitBuilder;
0353 using ArrayBuilder = typename Traits::ArrayBuilder;
0354 using StructBuilder = typename Traits::StructBuilder;
0355 using AggregateBuilderBase = typename Traits::AggregateBuilderBase;
0356
0357 protected:
0358 ConstantAggregateBuilderTemplateBase(InitBuilder &builder,
0359 AggregateBuilderBase *parent)
0360 : super(builder, parent) {}
0361
0362 Impl &asImpl() { return *static_cast<Impl*>(this); }
0363
0364 public:
0365 ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) {
0366 return ArrayBuilder(static_cast<InitBuilder&>(this->Builder), this, eltTy);
0367 }
0368
0369 StructBuilder beginStruct(llvm::StructType *ty = nullptr) {
0370 return StructBuilder(static_cast<InitBuilder&>(this->Builder), this, ty);
0371 }
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382 void finishAndAddTo(AggregateBuilderBase &parent) {
0383 assert(this->Parent == &parent && "adding to non-parent builder");
0384 parent.add(asImpl().finishImpl());
0385 }
0386
0387
0388
0389
0390 template <class... As>
0391 llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) {
0392 assert(!this->Parent && "finishing non-root builder");
0393 return this->Builder.createGlobal(asImpl().finishImpl(),
0394 std::forward<As>(args)...);
0395 }
0396
0397
0398
0399
0400 void finishAndSetAsInitializer(llvm::GlobalVariable *global) {
0401 assert(!this->Parent && "finishing non-root builder");
0402 return this->Builder.setGlobalInitializer(global, asImpl().finishImpl());
0403 }
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413 ConstantInitFuture finishAndCreateFuture() {
0414 assert(!this->Parent && "finishing non-root builder");
0415 return this->Builder.createFuture(asImpl().finishImpl());
0416 }
0417 };
0418
0419 template <class Traits>
0420 class ConstantArrayBuilderTemplateBase
0421 : public ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder,
0422 Traits> {
0423 using super =
0424 ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder, Traits>;
0425
0426 public:
0427 using InitBuilder = typename Traits::InitBuilder;
0428 using AggregateBuilderBase = typename Traits::AggregateBuilderBase;
0429
0430 private:
0431 llvm::Type *EltTy;
0432
0433 template <class, class>
0434 friend class ConstantAggregateBuilderTemplateBase;
0435
0436 protected:
0437 ConstantArrayBuilderTemplateBase(InitBuilder &builder,
0438 AggregateBuilderBase *parent,
0439 llvm::Type *eltTy)
0440 : super(builder, parent), EltTy(eltTy) {}
0441
0442 private:
0443
0444
0445 llvm::Constant *finishImpl() {
0446 return AggregateBuilderBase::finishArray(EltTy);
0447 }
0448 };
0449
0450
0451
0452
0453
0454
0455 template <class Traits>
0456 class ConstantStructBuilderTemplateBase
0457 : public ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder,
0458 Traits> {
0459 using super =
0460 ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder,Traits>;
0461
0462 public:
0463 using InitBuilder = typename Traits::InitBuilder;
0464 using AggregateBuilderBase = typename Traits::AggregateBuilderBase;
0465
0466 private:
0467 llvm::StructType *StructTy;
0468
0469 template <class, class>
0470 friend class ConstantAggregateBuilderTemplateBase;
0471
0472 protected:
0473 ConstantStructBuilderTemplateBase(InitBuilder &builder,
0474 AggregateBuilderBase *parent,
0475 llvm::StructType *structTy)
0476 : super(builder, parent), StructTy(structTy) {
0477 if (structTy) this->Packed = structTy->isPacked();
0478 }
0479
0480 public:
0481 void setPacked(bool packed) {
0482 this->Packed = packed;
0483 }
0484
0485
0486
0487 void suggestType(llvm::StructType *structTy) {
0488 if (this->size() == structTy->getNumElements()) {
0489 StructTy = structTy;
0490 }
0491 }
0492
0493 private:
0494
0495
0496 llvm::Constant *finishImpl() {
0497 return AggregateBuilderBase::finishStruct(StructTy);
0498 }
0499 };
0500
0501
0502
0503
0504
0505
0506 template <class Traits>
0507 class ConstantInitBuilderTemplateBase : public ConstantInitBuilderBase {
0508 protected:
0509 ConstantInitBuilderTemplateBase(CodeGenModule &CGM)
0510 : ConstantInitBuilderBase(CGM) {}
0511
0512 public:
0513 using InitBuilder = typename Traits::InitBuilder;
0514 using ArrayBuilder = typename Traits::ArrayBuilder;
0515 using StructBuilder = typename Traits::StructBuilder;
0516
0517 ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) {
0518 return ArrayBuilder(static_cast<InitBuilder&>(*this), nullptr, eltTy);
0519 }
0520
0521 StructBuilder beginStruct(llvm::StructType *structTy = nullptr) {
0522 return StructBuilder(static_cast<InitBuilder&>(*this), nullptr, structTy);
0523 }
0524 };
0525
0526 class ConstantInitBuilder;
0527 class ConstantStructBuilder;
0528 class ConstantArrayBuilder;
0529
0530 struct ConstantInitBuilderTraits {
0531 using InitBuilder = ConstantInitBuilder;
0532 using AggregateBuilderBase = ConstantAggregateBuilderBase;
0533 using ArrayBuilder = ConstantArrayBuilder;
0534 using StructBuilder = ConstantStructBuilder;
0535 };
0536
0537
0538 class ConstantInitBuilder
0539 : public ConstantInitBuilderTemplateBase<ConstantInitBuilderTraits> {
0540 public:
0541 explicit ConstantInitBuilder(CodeGenModule &CGM) :
0542 ConstantInitBuilderTemplateBase(CGM) {}
0543 };
0544
0545
0546
0547 class ConstantArrayBuilder
0548 : public ConstantArrayBuilderTemplateBase<ConstantInitBuilderTraits> {
0549 template <class Traits>
0550 friend class ConstantInitBuilderTemplateBase;
0551
0552
0553 template <class Impl, class Traits>
0554 friend class CodeGen::ConstantAggregateBuilderTemplateBase;
0555
0556 ConstantArrayBuilder(ConstantInitBuilder &builder,
0557 ConstantAggregateBuilderBase *parent,
0558 llvm::Type *eltTy)
0559 : ConstantArrayBuilderTemplateBase(builder, parent, eltTy) {}
0560 };
0561
0562
0563
0564 class ConstantStructBuilder
0565 : public ConstantStructBuilderTemplateBase<ConstantInitBuilderTraits> {
0566 template <class Traits>
0567 friend class ConstantInitBuilderTemplateBase;
0568
0569
0570 template <class Impl, class Traits>
0571 friend class CodeGen::ConstantAggregateBuilderTemplateBase;
0572
0573 ConstantStructBuilder(ConstantInitBuilder &builder,
0574 ConstantAggregateBuilderBase *parent,
0575 llvm::StructType *structTy)
0576 : ConstantStructBuilderTemplateBase(builder, parent, structTy) {}
0577 };
0578
0579 }
0580 }
0581
0582 #endif