ConstantInitBuilder.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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. #include "clang/CodeGen/ConstantInitBuilder.h"
  15. #include "CodeGenModule.h"
  16. using namespace clang;
  17. using namespace CodeGen;
  18. llvm::Type *ConstantInitFuture::getType() const {
  19. assert(Data && "dereferencing null future");
  20. if (Data.is<llvm::Constant*>()) {
  21. return Data.get<llvm::Constant*>()->getType();
  22. } else {
  23. return Data.get<ConstantInitBuilderBase*>()->Buffer[0]->getType();
  24. }
  25. }
  26. void ConstantInitFuture::abandon() {
  27. assert(Data && "abandoning null future");
  28. if (auto builder = Data.dyn_cast<ConstantInitBuilderBase*>()) {
  29. builder->abandon(0);
  30. }
  31. Data = nullptr;
  32. }
  33. void ConstantInitFuture::installInGlobal(llvm::GlobalVariable *GV) {
  34. assert(Data && "installing null future");
  35. if (Data.is<llvm::Constant*>()) {
  36. GV->setInitializer(Data.get<llvm::Constant*>());
  37. } else {
  38. auto &builder = *Data.get<ConstantInitBuilderBase*>();
  39. assert(builder.Buffer.size() == 1);
  40. builder.setGlobalInitializer(GV, builder.Buffer[0]);
  41. builder.Buffer.clear();
  42. Data = nullptr;
  43. }
  44. }
  45. ConstantInitFuture
  46. ConstantInitBuilderBase::createFuture(llvm::Constant *initializer) {
  47. assert(Buffer.empty() && "buffer not current empty");
  48. Buffer.push_back(initializer);
  49. return ConstantInitFuture(this);
  50. }
  51. // Only used in this file.
  52. inline ConstantInitFuture::ConstantInitFuture(ConstantInitBuilderBase *builder)
  53. : Data(builder) {
  54. assert(!builder->Frozen);
  55. assert(builder->Buffer.size() == 1);
  56. assert(builder->Buffer[0] != nullptr);
  57. }
  58. llvm::GlobalVariable *
  59. ConstantInitBuilderBase::createGlobal(llvm::Constant *initializer,
  60. const llvm::Twine &name,
  61. CharUnits alignment,
  62. bool constant,
  63. llvm::GlobalValue::LinkageTypes linkage,
  64. unsigned addressSpace) {
  65. auto GV = new llvm::GlobalVariable(CGM.getModule(),
  66. initializer->getType(),
  67. constant,
  68. linkage,
  69. initializer,
  70. name,
  71. /*insert before*/ nullptr,
  72. llvm::GlobalValue::NotThreadLocal,
  73. addressSpace);
  74. GV->setAlignment(alignment.getAsAlign());
  75. resolveSelfReferences(GV);
  76. return GV;
  77. }
  78. void ConstantInitBuilderBase::setGlobalInitializer(llvm::GlobalVariable *GV,
  79. llvm::Constant *initializer){
  80. GV->setInitializer(initializer);
  81. if (!SelfReferences.empty())
  82. resolveSelfReferences(GV);
  83. }
  84. void ConstantInitBuilderBase::resolveSelfReferences(llvm::GlobalVariable *GV) {
  85. for (auto &entry : SelfReferences) {
  86. llvm::Constant *resolvedReference =
  87. llvm::ConstantExpr::getInBoundsGetElementPtr(
  88. GV->getValueType(), GV, entry.Indices);
  89. auto dummy = entry.Dummy;
  90. dummy->replaceAllUsesWith(resolvedReference);
  91. dummy->eraseFromParent();
  92. }
  93. SelfReferences.clear();
  94. }
  95. void ConstantInitBuilderBase::abandon(size_t newEnd) {
  96. // Remove all the entries we've added.
  97. Buffer.erase(Buffer.begin() + newEnd, Buffer.end());
  98. // If we're abandoning all the way to the beginning, destroy
  99. // all the self-references, because we might not get another
  100. // opportunity.
  101. if (newEnd == 0) {
  102. for (auto &entry : SelfReferences) {
  103. auto dummy = entry.Dummy;
  104. dummy->replaceAllUsesWith(llvm::PoisonValue::get(dummy->getType()));
  105. dummy->eraseFromParent();
  106. }
  107. SelfReferences.clear();
  108. }
  109. }
  110. void ConstantAggregateBuilderBase::addSize(CharUnits size) {
  111. add(Builder.CGM.getSize(size));
  112. }
  113. llvm::Constant *
  114. ConstantAggregateBuilderBase::getRelativeOffset(llvm::IntegerType *offsetType,
  115. llvm::Constant *target) {
  116. return getRelativeOffsetToPosition(offsetType, target,
  117. Builder.Buffer.size() - Begin);
  118. }
  119. llvm::Constant *ConstantAggregateBuilderBase::getRelativeOffsetToPosition(
  120. llvm::IntegerType *offsetType, llvm::Constant *target, size_t position) {
  121. // Compute the address of the relative-address slot.
  122. auto base = getAddrOfPosition(offsetType, position);
  123. // Subtract.
  124. base = llvm::ConstantExpr::getPtrToInt(base, Builder.CGM.IntPtrTy);
  125. target = llvm::ConstantExpr::getPtrToInt(target, Builder.CGM.IntPtrTy);
  126. llvm::Constant *offset = llvm::ConstantExpr::getSub(target, base);
  127. // Truncate to the relative-address type if necessary.
  128. if (Builder.CGM.IntPtrTy != offsetType) {
  129. offset = llvm::ConstantExpr::getTrunc(offset, offsetType);
  130. }
  131. return offset;
  132. }
  133. llvm::Constant *
  134. ConstantAggregateBuilderBase::getAddrOfPosition(llvm::Type *type,
  135. size_t position) {
  136. // Make a global variable. We will replace this with a GEP to this
  137. // position after installing the initializer.
  138. auto dummy = new llvm::GlobalVariable(Builder.CGM.getModule(), type, true,
  139. llvm::GlobalVariable::PrivateLinkage,
  140. nullptr, "");
  141. Builder.SelfReferences.emplace_back(dummy);
  142. auto &entry = Builder.SelfReferences.back();
  143. (void)getGEPIndicesTo(entry.Indices, position + Begin);
  144. return dummy;
  145. }
  146. llvm::Constant *
  147. ConstantAggregateBuilderBase::getAddrOfCurrentPosition(llvm::Type *type) {
  148. // Make a global variable. We will replace this with a GEP to this
  149. // position after installing the initializer.
  150. auto dummy =
  151. new llvm::GlobalVariable(Builder.CGM.getModule(), type, true,
  152. llvm::GlobalVariable::PrivateLinkage,
  153. nullptr, "");
  154. Builder.SelfReferences.emplace_back(dummy);
  155. auto &entry = Builder.SelfReferences.back();
  156. (void) getGEPIndicesToCurrentPosition(entry.Indices);
  157. return dummy;
  158. }
  159. void ConstantAggregateBuilderBase::getGEPIndicesTo(
  160. llvm::SmallVectorImpl<llvm::Constant*> &indices,
  161. size_t position) const {
  162. // Recurse on the parent builder if present.
  163. if (Parent) {
  164. Parent->getGEPIndicesTo(indices, Begin);
  165. // Otherwise, add an index to drill into the first level of pointer.
  166. } else {
  167. assert(indices.empty());
  168. indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty, 0));
  169. }
  170. assert(position >= Begin);
  171. // We have to use i32 here because struct GEPs demand i32 indices.
  172. // It's rather unlikely to matter in practice.
  173. indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty,
  174. position - Begin));
  175. }
  176. ConstantAggregateBuilderBase::PlaceholderPosition
  177. ConstantAggregateBuilderBase::addPlaceholderWithSize(llvm::Type *type) {
  178. // Bring the offset up to the last field.
  179. CharUnits offset = getNextOffsetFromGlobal();
  180. // Create the placeholder.
  181. auto position = addPlaceholder();
  182. // Advance the offset past that field.
  183. auto &layout = Builder.CGM.getDataLayout();
  184. if (!Packed)
  185. offset = offset.alignTo(CharUnits::fromQuantity(layout.getABITypeAlign(type)));
  186. offset += CharUnits::fromQuantity(layout.getTypeStoreSize(type));
  187. CachedOffsetEnd = Builder.Buffer.size();
  188. CachedOffsetFromGlobal = offset;
  189. return position;
  190. }
  191. CharUnits ConstantAggregateBuilderBase::getOffsetFromGlobalTo(size_t end) const{
  192. size_t cacheEnd = CachedOffsetEnd;
  193. assert(cacheEnd <= end);
  194. // Fast path: if the cache is valid, just use it.
  195. if (cacheEnd == end) {
  196. return CachedOffsetFromGlobal;
  197. }
  198. // If the cached range ends before the index at which the current
  199. // aggregate starts, recurse for the parent.
  200. CharUnits offset;
  201. if (cacheEnd < Begin) {
  202. assert(cacheEnd == 0);
  203. assert(Parent && "Begin != 0 for root builder");
  204. cacheEnd = Begin;
  205. offset = Parent->getOffsetFromGlobalTo(Begin);
  206. } else {
  207. offset = CachedOffsetFromGlobal;
  208. }
  209. // Perform simple layout on the elements in cacheEnd..<end.
  210. if (cacheEnd != end) {
  211. auto &layout = Builder.CGM.getDataLayout();
  212. do {
  213. llvm::Constant *element = Builder.Buffer[cacheEnd];
  214. assert(element != nullptr &&
  215. "cannot compute offset when a placeholder is present");
  216. llvm::Type *elementType = element->getType();
  217. if (!Packed)
  218. offset = offset.alignTo(
  219. CharUnits::fromQuantity(layout.getABITypeAlign(elementType)));
  220. offset += CharUnits::fromQuantity(layout.getTypeStoreSize(elementType));
  221. } while (++cacheEnd != end);
  222. }
  223. // Cache and return.
  224. CachedOffsetEnd = cacheEnd;
  225. CachedOffsetFromGlobal = offset;
  226. return offset;
  227. }
  228. llvm::Constant *ConstantAggregateBuilderBase::finishArray(llvm::Type *eltTy) {
  229. markFinished();
  230. auto &buffer = getBuffer();
  231. assert((Begin < buffer.size() ||
  232. (Begin == buffer.size() && eltTy))
  233. && "didn't add any array elements without element type");
  234. auto elts = llvm::ArrayRef(buffer).slice(Begin);
  235. if (!eltTy) eltTy = elts[0]->getType();
  236. auto type = llvm::ArrayType::get(eltTy, elts.size());
  237. auto constant = llvm::ConstantArray::get(type, elts);
  238. buffer.erase(buffer.begin() + Begin, buffer.end());
  239. return constant;
  240. }
  241. llvm::Constant *
  242. ConstantAggregateBuilderBase::finishStruct(llvm::StructType *ty) {
  243. markFinished();
  244. auto &buffer = getBuffer();
  245. auto elts = llvm::ArrayRef(buffer).slice(Begin);
  246. if (ty == nullptr && elts.empty())
  247. ty = llvm::StructType::get(Builder.CGM.getLLVMContext(), {}, Packed);
  248. llvm::Constant *constant;
  249. if (ty) {
  250. assert(ty->isPacked() == Packed);
  251. constant = llvm::ConstantStruct::get(ty, elts);
  252. } else {
  253. constant = llvm::ConstantStruct::getAnon(elts, Packed);
  254. }
  255. buffer.erase(buffer.begin() + Begin, buffer.end());
  256. return constant;
  257. }