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