Mercurial > projects > ldc
comparison gen/structs.cpp @ 100:5071469303d4 trunk
[svn r104] TONS OF FIXES.
Split up declaration, constant initializer gen and definition for globals, structs, classes and functions.
Improved ClassInfo support (not complete), not in vtable yet.
Fixed a bunch of forward reference problems.
Much more. Major commit! :)
author | lindquist |
---|---|
date | Fri, 16 Nov 2007 08:21:47 +0100 |
parents | ce7ed8f59b99 |
children | 027b8d8b71ec |
comparison
equal
deleted
inserted
replaced
99:a676a7743642 | 100:5071469303d4 |
---|---|
76 llvm::Constant* DtoConstStructInitializer(StructInitializer* si) | 76 llvm::Constant* DtoConstStructInitializer(StructInitializer* si) |
77 { | 77 { |
78 Logger::println("DtoConstStructInitializer: %s", si->toChars()); | 78 Logger::println("DtoConstStructInitializer: %s", si->toChars()); |
79 LOG_SCOPE; | 79 LOG_SCOPE; |
80 | 80 |
81 const llvm::StructType* structtype = isaStruct(si->ad->llvmType); | 81 TypeStruct* ts = (TypeStruct*)si->ad->type; |
82 | |
83 const llvm::StructType* structtype = isaStruct(ts->llvmType->get()); | |
82 Logger::cout() << "llvm struct type: " << *structtype << '\n'; | 84 Logger::cout() << "llvm struct type: " << *structtype << '\n'; |
83 | 85 |
84 assert(si->value.dim == si->vars.dim); | 86 assert(si->value.dim == si->vars.dim); |
85 | 87 |
86 std::vector<DUnionIdx> inits; | 88 std::vector<DUnionIdx> inits; |
158 size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0)); | 160 size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0)); |
159 assert(os % llt_sz == 0); | 161 assert(os % llt_sz == 0); |
160 ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); | 162 ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); |
161 return new llvm::GetElementPtrInst(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb()); | 163 return new llvm::GetElementPtrInst(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb()); |
162 } | 164 } |
165 | |
166 ////////////////////////////////////////////////////////////////////////////////////////// | |
167 | |
168 void DtoDeclareStruct(StructDeclaration* sd) | |
169 { | |
170 if (sd->llvmTouched) return; | |
171 sd->llvmTouched = true; | |
172 | |
173 Logger::println("DtoDeclareStruct(%s)", sd->toChars()); | |
174 LOG_SCOPE; | |
175 | |
176 TypeStruct* ts = (TypeStruct*)DtoDType(sd->type); | |
177 | |
178 IRStruct* irstruct = new IRStruct(ts); | |
179 sd->llvmIRStruct = irstruct; | |
180 gIR->structs.push_back(irstruct); | |
181 | |
182 for (int k=0; k < sd->members->dim; k++) { | |
183 Dsymbol* dsym = (Dsymbol*)(sd->members->data[k]); | |
184 dsym->toObjFile(); | |
185 } | |
186 | |
187 Logger::println("doing struct fields"); | |
188 | |
189 const llvm::StructType* structtype = 0; | |
190 std::vector<const llvm::Type*> fieldtypes; | |
191 | |
192 if (irstruct->offsets.empty()) | |
193 { | |
194 Logger::println("has no fields"); | |
195 fieldtypes.push_back(llvm::Type::Int8Ty); | |
196 structtype = llvm::StructType::get(fieldtypes); | |
197 } | |
198 else | |
199 { | |
200 Logger::println("has fields"); | |
201 unsigned prevsize = (unsigned)-1; | |
202 unsigned lastoffset = (unsigned)-1; | |
203 const llvm::Type* fieldtype = NULL; | |
204 VarDeclaration* fieldinit = NULL; | |
205 size_t fieldpad = 0; | |
206 int idx = 0; | |
207 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { | |
208 // first iteration | |
209 if (lastoffset == (unsigned)-1) { | |
210 lastoffset = i->first; | |
211 assert(lastoffset == 0); | |
212 fieldtype = i->second.type; | |
213 fieldinit = i->second.var; | |
214 prevsize = gTargetData->getTypeSize(fieldtype); | |
215 i->second.var->llvmFieldIndex = idx; | |
216 } | |
217 // colliding offset? | |
218 else if (lastoffset == i->first) { | |
219 size_t s = gTargetData->getTypeSize(i->second.type); | |
220 if (s > prevsize) { | |
221 fieldpad += s - prevsize; | |
222 prevsize = s; | |
223 } | |
224 sd->llvmHasUnions = true; | |
225 i->second.var->llvmFieldIndex = idx; | |
226 } | |
227 // intersecting offset? | |
228 else if (i->first < (lastoffset + prevsize)) { | |
229 size_t s = gTargetData->getTypeSize(i->second.type); | |
230 assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size | |
231 sd->llvmHasUnions = true; | |
232 i->second.var->llvmFieldIndex = idx; | |
233 i->second.var->llvmFieldIndexOffset = (i->first - lastoffset) / s; | |
234 } | |
235 // fresh offset | |
236 else { | |
237 // commit the field | |
238 fieldtypes.push_back(fieldtype); | |
239 irstruct->defaultFields.push_back(fieldinit); | |
240 if (fieldpad) { | |
241 fieldtypes.push_back(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad)); | |
242 irstruct->defaultFields.push_back(NULL); | |
243 idx++; | |
244 } | |
245 | |
246 idx++; | |
247 | |
248 // start new | |
249 lastoffset = i->first; | |
250 fieldtype = i->second.type; | |
251 fieldinit = i->second.var; | |
252 prevsize = gTargetData->getTypeSize(fieldtype); | |
253 i->second.var->llvmFieldIndex = idx; | |
254 fieldpad = 0; | |
255 } | |
256 } | |
257 fieldtypes.push_back(fieldtype); | |
258 irstruct->defaultFields.push_back(fieldinit); | |
259 if (fieldpad) { | |
260 fieldtypes.push_back(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad)); | |
261 irstruct->defaultFields.push_back(NULL); | |
262 } | |
263 | |
264 Logger::println("creating struct type"); | |
265 structtype = llvm::StructType::get(fieldtypes); | |
266 } | |
267 | |
268 // refine abstract types for stuff like: struct S{S* next;} | |
269 if (irstruct->recty != 0) | |
270 { | |
271 llvm::PATypeHolder& pa = irstruct->recty; | |
272 llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype); | |
273 structtype = isaStruct(pa.get()); | |
274 } | |
275 | |
276 assert(ts->llvmType == 0); | |
277 ts->llvmType = new llvm::PATypeHolder(structtype); | |
278 | |
279 if (sd->parent->isModule()) { | |
280 gIR->module->addTypeName(sd->mangle(),structtype); | |
281 } | |
282 | |
283 std::string initname("_D"); | |
284 initname.append(sd->mangle()); | |
285 initname.append("6__initZ"); | |
286 | |
287 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; | |
288 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module); | |
289 ts->llvmInit = initvar; | |
290 | |
291 gIR->structs.pop_back(); | |
292 | |
293 gIR->constInitQueue.push_back(sd); | |
294 if (sd->getModule() == gIR->dmodule) | |
295 gIR->defineQueue.push_back(sd); | |
296 | |
297 // declare typeinfo | |
298 if (sd->getModule() == gIR->dmodule && sd->llvmInternal != LLVMnotypeinfo) | |
299 sd->type->getTypeInfo(NULL); | |
300 } | |
301 | |
302 ////////////////////////////////////////////////////////////////////////////////////////// | |
303 | |
304 void DtoConstInitStruct(StructDeclaration* sd) | |
305 { | |
306 IRStruct* irstruct = sd->llvmIRStruct; | |
307 if (irstruct->constinited) return; | |
308 irstruct->constinited = true; | |
309 | |
310 Logger::println("DtoConstInitStruct(%s)", sd->toChars()); | |
311 LOG_SCOPE; | |
312 | |
313 gIR->structs.push_back(irstruct); | |
314 | |
315 // make sure each offset knows its default initializer | |
316 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) | |
317 { | |
318 IRStruct::Offset* so = &i->second; | |
319 llvm::Constant* finit = DtoConstFieldInitializer(so->var->type, so->var->init); | |
320 so->init = finit; | |
321 so->var->llvmConstInit = finit; | |
322 } | |
323 | |
324 const llvm::StructType* structtype = isaStruct(sd->type->llvmType->get()); | |
325 | |
326 // go through the field inits and build the default initializer | |
327 std::vector<llvm::Constant*> fieldinits_ll; | |
328 size_t nfi = irstruct->defaultFields.size(); | |
329 for (size_t i=0; i<nfi; ++i) { | |
330 llvm::Constant* c; | |
331 if (irstruct->defaultFields[i] != NULL) { | |
332 c = irstruct->defaultFields[i]->llvmConstInit; | |
333 assert(c); | |
334 } | |
335 else { | |
336 const llvm::ArrayType* arrty = isaArray(structtype->getElementType(i)); | |
337 std::vector<llvm::Constant*> vals(arrty->getNumElements(), llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false)); | |
338 c = llvm::ConstantArray::get(arrty, vals); | |
339 } | |
340 fieldinits_ll.push_back(c); | |
341 } | |
342 | |
343 // generate the union mapper | |
344 sd->llvmUnion = new DUnion; // uses gIR->topstruct() | |
345 | |
346 // always generate the constant initalizer | |
347 if (!sd->zeroInit) { | |
348 Logger::println("Not zero initialized"); | |
349 //assert(tk == gIR->gIR->topstruct()().size()); | |
350 #ifndef LLVMD_NO_LOGGER | |
351 Logger::cout() << "struct type: " << *structtype << '\n'; | |
352 for (size_t k=0; k<fieldinits_ll.size(); ++k) { | |
353 Logger::cout() << "Type:" << '\n'; | |
354 Logger::cout() << *fieldinits_ll[k]->getType() << '\n'; | |
355 Logger::cout() << "Value:" << '\n'; | |
356 Logger::cout() << *fieldinits_ll[k] << '\n'; | |
357 } | |
358 Logger::cout() << "Initializer printed" << '\n'; | |
359 #endif | |
360 sd->llvmInitZ = llvm::ConstantStruct::get(structtype,fieldinits_ll); | |
361 } | |
362 else { | |
363 Logger::println("Zero initialized"); | |
364 sd->llvmInitZ = llvm::ConstantAggregateZero::get(structtype); | |
365 } | |
366 | |
367 gIR->structs.pop_back(); | |
368 } | |
369 | |
370 ////////////////////////////////////////////////////////////////////////////////////////// | |
371 | |
372 void DtoDefineStruct(StructDeclaration* sd) | |
373 { | |
374 IRStruct* irstruct = sd->llvmIRStruct; | |
375 if (irstruct->defined) return; | |
376 irstruct->defined = true; | |
377 | |
378 DtoConstInitStruct(sd); | |
379 | |
380 Logger::println("DtoDefineStruct(%s)", sd->toChars()); | |
381 LOG_SCOPE; | |
382 | |
383 assert(sd->type->ty == Tstruct); | |
384 TypeStruct* ts = (TypeStruct*)sd->type; | |
385 ts->llvmInit->setInitializer(sd->llvmInitZ); | |
386 | |
387 sd->llvmDModule = gIR->dmodule; | |
388 } | |
389 | |
163 ////////////////////////////////////////////////////////////////////////////////////////// | 390 ////////////////////////////////////////////////////////////////////////////////////////// |
164 //////////////////////////// D UNION HELPER CLASS //////////////////////////////////// | 391 //////////////////////////// D UNION HELPER CLASS //////////////////////////////////// |
165 ////////////////////////////////////////////////////////////////////////////////////////// | 392 ////////////////////////////////////////////////////////////////////////////////////////// |
166 | 393 |
167 DUnion::DUnion() | 394 DUnion::DUnion() |
168 { | 395 { |
169 DUnionField* f = NULL; | 396 DUnionField* f = NULL; |
170 IRStruct& topstruct = gIR->topstruct(); | 397 IRStruct* topstruct = gIR->topstruct(); |
171 bool unions = false; | 398 bool unions = false; |
172 for (IRStruct::OffsetMap::iterator i=topstruct.offsets.begin(); i!=topstruct.offsets.end(); ++i) | 399 for (IRStruct::OffsetMap::iterator i=topstruct->offsets.begin(); i!=topstruct->offsets.end(); ++i) |
173 { | 400 { |
174 unsigned o = i->first; | 401 unsigned o = i->first; |
175 IRStruct::Offset* so = &i->second; | 402 IRStruct::Offset* so = &i->second; |
176 const llvm::Type* ft = so->init->getType(); | 403 const llvm::Type* ft = so->init->getType(); |
177 size_t sz = gTargetData->getTypeSize(ft); | 404 size_t sz = gTargetData->getTypeSize(ft); |