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);