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