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