1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
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 | (0) . __assert_fail ("Data && \"dereferencing null future\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ConstantInitBuilder.cpp", 22, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">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 | (0) . __assert_fail ("Data && \"abandoning null future\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ConstantInitBuilder.cpp", 31, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">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 | (0) . __assert_fail ("Data && \"installing null future\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ConstantInitBuilder.cpp", 39, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">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 | (0) . __assert_fail ("Buffer.empty() && \"buffer not current empty\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ConstantInitBuilder.cpp", 53, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Buffer.empty() && "buffer not current empty"); |
54 | Buffer.push_back(initializer); |
55 | return ConstantInitFuture(this); |
56 | } |
57 | |
58 | |
59 | inline ConstantInitFuture::ConstantInitFuture(ConstantInitBuilderBase *builder) |
60 | : Data(builder) { |
61 | Frozen", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ConstantInitBuilder.cpp", 61, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!builder->Frozen); |
62 | Buffer.size() == 1", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ConstantInitBuilder.cpp", 62, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(builder->Buffer.size() == 1); |
63 | Buffer[0] != nullptr", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ConstantInitBuilder.cpp", 63, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">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 | 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 | |
109 | Buffer.erase(Buffer.begin() + newEnd, Buffer.end()); |
110 | |
111 | |
112 | |
113 | |
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 | |
132 | auto base = getAddrOfCurrentPosition(offsetType); |
133 | |
134 | |
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 | |
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 | |
150 | |
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 | |
165 | if (Parent) { |
166 | Parent->getGEPIndicesTo(indices, Begin); |
167 | |
168 | |
169 | } else { |
170 | assert(indices.empty()); |
171 | indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty, 0)); |
172 | } |
173 | |
174 | = Begin", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ConstantInitBuilder.cpp", 174, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(position >= Begin); |
175 | |
176 | |
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 | |
184 | CharUnits offset = getNextOffsetFromGlobal(); |
185 | |
186 | |
187 | auto position = addPlaceholder(); |
188 | |
189 | |
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 | |
207 | if (cacheEnd == end) { |
208 | return CachedOffsetFromGlobal; |
209 | } |
210 | |
211 | |
212 | |
213 | CharUnits offset; |
214 | if (cacheEnd < Begin) { |
215 | assert(cacheEnd == 0); |
216 | (0) . __assert_fail ("Parent && \"Begin != 0 for root builder\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ConstantInitBuilder.cpp", 216, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Parent && "Begin != 0 for root builder"); |
217 | cacheEnd = Begin; |
218 | offset = Parent->getOffsetFromGlobalTo(Begin); |
219 | } else { |
220 | offset = CachedOffsetFromGlobal; |
221 | } |
222 | |
223 | |
224 | if (cacheEnd != end) { |
225 | auto &layout = Builder.CGM.getDataLayout(); |
226 | do { |
227 | llvm::Constant *element = Builder.Buffer[cacheEnd]; |
228 | (0) . __assert_fail ("element != nullptr && \"cannot compute offset when a placeholder is present\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ConstantInitBuilder.cpp", 229, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(element != nullptr && |
229 | (0) . __assert_fail ("element != nullptr && \"cannot compute offset when a placeholder is present\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ConstantInitBuilder.cpp", 229, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "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 | |
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 | (0) . __assert_fail ("(Begin < buffer.size() || (Begin == buffer.size() && eltTy)) && \"didn't add any array elements without element type\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ConstantInitBuilder.cpp", 250, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert((Begin < buffer.size() || |
249 | (0) . __assert_fail ("(Begin < buffer.size() || (Begin == buffer.size() && eltTy)) && \"didn't add any array elements without element type\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ConstantInitBuilder.cpp", 250, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> (Begin == buffer.size() && eltTy)) |
250 | (0) . __assert_fail ("(Begin < buffer.size() || (Begin == buffer.size() && eltTy)) && \"didn't add any array elements without element type\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ConstantInitBuilder.cpp", 250, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> && "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 | isPacked() == Packed", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/ConstantInitBuilder.cpp", 271, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">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 | |