1 //===--- ConstantInitBuilder.cpp - Global initializer builder -------------===// 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 file defines out-of-line routines for building initializers for 11 // global variables, in particular the kind of globals that are implicitly 12 // introduced by various language ABIs. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "clang/CodeGen/ConstantInitBuilder.h" 17 #include "CodeGenModule.h" 18 19 using namespace clang; 20 using namespace CodeGen; 21 22 llvm::GlobalVariable * 23 ConstantInitBuilder::createGlobal(llvm::Constant *initializer, 24 const llvm::Twine &name, 25 CharUnits alignment, 26 bool constant, 27 llvm::GlobalValue::LinkageTypes linkage, 28 unsigned addressSpace) { 29 auto GV = new llvm::GlobalVariable(CGM.getModule(), 30 initializer->getType(), 31 constant, 32 linkage, 33 initializer, 34 name, 35 /*insert before*/ nullptr, 36 llvm::GlobalValue::NotThreadLocal, 37 addressSpace); 38 GV->setAlignment(alignment.getQuantity()); 39 resolveSelfReferences(GV); 40 return GV; 41 } 42 43 void ConstantInitBuilder::setGlobalInitializer(llvm::GlobalVariable *GV, 44 llvm::Constant *initializer) { 45 GV->setInitializer(initializer); 46 47 if (!SelfReferences.empty()) 48 resolveSelfReferences(GV); 49 } 50 51 void ConstantInitBuilder::resolveSelfReferences(llvm::GlobalVariable *GV) { 52 for (auto &entry : SelfReferences) { 53 llvm::Constant *resolvedReference = 54 llvm::ConstantExpr::getInBoundsGetElementPtr( 55 GV->getValueType(), GV, entry.Indices); 56 entry.Dummy->replaceAllUsesWith(resolvedReference); 57 entry.Dummy->eraseFromParent(); 58 } 59 } 60 61 void ConstantInitBuilder::AggregateBuilderBase::addSize(CharUnits size) { 62 add(Builder.CGM.getSize(size)); 63 } 64 65 llvm::Constant * 66 ConstantInitBuilder::AggregateBuilderBase::getAddrOfCurrentPosition( 67 llvm::Type *type) { 68 // Make a global variable. We will replace this with a GEP to this 69 // position after installing the initializer. 70 auto dummy = 71 new llvm::GlobalVariable(Builder.CGM.getModule(), type, true, 72 llvm::GlobalVariable::PrivateLinkage, 73 nullptr, ""); 74 Builder.SelfReferences.emplace_back(dummy); 75 auto &entry = Builder.SelfReferences.back(); 76 (void) getGEPIndicesToCurrentPosition(entry.Indices); 77 return dummy; 78 } 79 80 void ConstantInitBuilder::AggregateBuilderBase::getGEPIndicesTo( 81 llvm::SmallVectorImpl<llvm::Constant*> &indices, 82 size_t position) const { 83 // Recurse on the parent builder if present. 84 if (Parent) { 85 Parent->getGEPIndicesTo(indices, Begin); 86 87 // Otherwise, add an index to drill into the first level of pointer. 88 } else { 89 assert(indices.empty()); 90 indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty, 0)); 91 } 92 93 assert(position >= Begin); 94 // We have to use i32 here because struct GEPs demand i32 indices. 95 // It's rather unlikely to matter in practice. 96 indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty, 97 position - Begin)); 98 } 99 100 llvm::Constant *ConstantArrayBuilder::finishImpl() { 101 markFinished(); 102 103 auto &buffer = getBuffer(); 104 assert((Begin < buffer.size() || 105 (Begin == buffer.size() && EltTy)) 106 && "didn't add any array elements without element type"); 107 auto elts = llvm::makeArrayRef(buffer).slice(Begin); 108 auto eltTy = EltTy ? EltTy : elts[0]->getType(); 109 auto type = llvm::ArrayType::get(eltTy, elts.size()); 110 auto constant = llvm::ConstantArray::get(type, elts); 111 buffer.erase(buffer.begin() + Begin, buffer.end()); 112 return constant; 113 } 114 115 llvm::Constant *ConstantStructBuilder::finishImpl() { 116 markFinished(); 117 118 auto &buffer = getBuffer(); 119 assert(Begin < buffer.size() && "didn't add any struct elements?"); 120 auto elts = llvm::makeArrayRef(buffer).slice(Begin); 121 122 llvm::Constant *constant; 123 if (Ty) { 124 constant = llvm::ConstantStruct::get(Ty, elts); 125 } else { 126 constant = llvm::ConstantStruct::getAnon(elts, /*packed*/ false); 127 } 128 129 buffer.erase(buffer.begin() + Begin, buffer.end()); 130 return constant; 131 } 132