comparison gen/toobj.c @ 73:b706170e24a9 trunk

[svn r77] Fixed foreach on slice. Fixed some nested function problems when accessing outer function parameters. Major changes to handling of structs. Initial support for unions. Probably more...
author lindquist
date Wed, 31 Oct 2007 03:11:32 +0100
parents d7e764e62462
children eb379601d445
comparison
equal deleted inserted replaced
72:d7e764e62462 73:b706170e24a9
63 std::string target_triple(global.params.tt_arch); 63 std::string target_triple(global.params.tt_arch);
64 target_triple.append(global.params.tt_os); 64 target_triple.append(global.params.tt_os);
65 ir.module->setTargetTriple(target_triple); 65 ir.module->setTargetTriple(target_triple);
66 ir.module->setDataLayout(global.params.data_layout); 66 ir.module->setDataLayout(global.params.data_layout);
67 67
68 gTargetData = new llvm::TargetData(ir.module); 68 // heavily inspired by tools/llc/llc.cpp:200-230
69 const llvm::TargetMachineRegistry::Entry* targetEntry;
70 std::string targetError;
71 targetEntry = llvm::TargetMachineRegistry::getClosestStaticTargetForModule(*ir.module, targetError);
72 assert(targetEntry && "Failed to find a static target for module");
73 std::auto_ptr<llvm::TargetMachine> targetPtr(targetEntry->CtorFn(*ir.module, "")); // TODO: replace "" with features
74 assert(targetPtr.get() && "Could not allocate target machine!");
75 llvm::TargetMachine &targetMachine = *targetPtr.get();
76 gTargetData = targetMachine.getTargetData();
69 77
70 // process module members 78 // process module members
71 for (int k=0; k < members->dim; k++) { 79 for (int k=0; k < members->dim; k++) {
72 Dsymbol* dsym = (Dsymbol*)(members->data[k]); 80 Dsymbol* dsym = (Dsymbol*)(members->data[k]);
73 assert(dsym); 81 assert(dsym);
74 dsym->toObjFile(); 82 dsym->toObjFile();
75 } 83 }
76 84
77 delete gTargetData;
78 gTargetData = 0; 85 gTargetData = 0;
79 86
80 // emit the llvm main function if necessary 87 // emit the llvm main function if necessary
81 if (ir.emitMain) { 88 if (ir.emitMain) {
82 LLVM_DtoMain(); 89 LLVM_DtoMain();
140 } 147 }
141 148
142 /* ================================================================== */ 149 /* ================================================================== */
143 150
144 /// Returns the LLVM style index from a DMD style offset 151 /// Returns the LLVM style index from a DMD style offset
145 void AggregateDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result) 152 size_t AggregateDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result)
146 { 153 {
147 Logger::println("checking for offset %u type %s:", os, t->toChars()); 154 Logger::println("checking for offset %u type %s:", os, t->toChars());
148 LOG_SCOPE; 155 LOG_SCOPE;
149 for (unsigned i=0; i<fields.dim; ++i) { 156 for (unsigned i=0; i<fields.dim; ++i) {
150 VarDeclaration* vd = (VarDeclaration*)fields.data[i]; 157 VarDeclaration* vd = (VarDeclaration*)fields.data[i];
151 Type* vdtype = LLVM_DtoDType(vd->type); 158 Type* vdtype = LLVM_DtoDType(vd->type);
152 Logger::println("found %u type %s", vd->offset, vdtype->toChars()); 159 Logger::println("found %u type %s", vd->offset, vdtype->toChars());
153 if (os == vd->offset && vdtype == t) { 160 if (os == vd->offset && vdtype == t) {
154 result.push_back(i); 161 assert(vd->llvmFieldIndex >= 0);
155 return; 162 result.push_back(vd->llvmFieldIndex);
163 return vd->llvmFieldIndexOffset;
156 } 164 }
157 else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) { 165 else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) {
158 TypeStruct* ts = (TypeStruct*)vdtype; 166 TypeStruct* ts = (TypeStruct*)vdtype;
159 StructDeclaration* sd = ts->sym; 167 StructDeclaration* sd = ts->sym;
160 result.push_back(i); 168 result.push_back(i);
161 sd->offsetToIndex(t, os - vd->offset, result); 169 return sd->offsetToIndex(t, os - vd->offset, result);
162 return; 170 }
163 } 171 }
164 } 172 //assert(0 && "Offset not found in any aggregate field");
165 assert(0 && "Offset not found in any aggregate field"); 173 return (size_t)-1;
166 } 174 }
167 175
168 /* ================================================================== */ 176 /* ================================================================== */
169 177
170 static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx) 178 static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx)
188 return (unsigned)-1; 196 return (unsigned)-1;
189 } 197 }
190 198
191 /// Returns the LLVM style index from a DMD style offset 199 /// Returns the LLVM style index from a DMD style offset
192 /// Handles class inheritance 200 /// Handles class inheritance
193 void ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result) 201 size_t ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result)
194 { 202 {
195 unsigned idx = 0; 203 unsigned idx = 0;
196 unsigned r = LLVM_ClassOffsetToIndex(this, os, idx); 204 unsigned r = LLVM_ClassOffsetToIndex(this, os, idx);
197 assert(r != (unsigned)-1 && "Offset not found in any aggregate field"); 205 assert(r != (unsigned)-1 && "Offset not found in any aggregate field");
198 result.push_back(r+1); // vtable is 0 206 result.push_back(r+1); // vtable is 0
207 return 0;
199 } 208 }
200 209
201 /* ================================================================== */ 210 /* ================================================================== */
202 211
203 void InterfaceDeclaration::toObjFile() 212 void InterfaceDeclaration::toObjFile()
222 for (int k=0; k < members->dim; k++) { 231 for (int k=0; k < members->dim; k++) {
223 Dsymbol* dsym = (Dsymbol*)(members->data[k]); 232 Dsymbol* dsym = (Dsymbol*)(members->data[k]);
224 dsym->toObjFile(); 233 dsym->toObjFile();
225 } 234 }
226 235
227 if (gIR->topstruct().fields.empty()) 236 Logger::println("doing struct fields");
228 { 237
229 gIR->topstruct().fields.push_back(llvm::Type::Int8Ty); 238 llvm::StructType* structtype = 0;
230 gIR->topstruct().inits.push_back(llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false)); 239 std::vector<llvm::Constant*> fieldinits;
231 } 240
232 241 if (gIR->topstruct().offsets.empty())
233 llvm::StructType* structtype = llvm::StructType::get(gIR->topstruct().fields); 242 {
243 std::vector<const llvm::Type*> fieldtypes;
244 Logger::println("has no fields");
245 fieldtypes.push_back(llvm::Type::Int8Ty);
246 fieldinits.push_back(llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
247 structtype = llvm::StructType::get(fieldtypes);
248 }
249 else
250 {
251 Logger::println("has fields");
252 std::vector<const llvm::Type*> fieldtypes;
253 unsigned prevsize = (unsigned)-1;
254 unsigned lastoffset = (unsigned)-1;
255 const llvm::Type* fieldtype = NULL;
256 llvm::Constant* fieldinit = NULL;
257 size_t fieldpad = 0;
258 int idx = 0;
259 for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) {
260 // first iteration
261 if (lastoffset == (unsigned)-1) {
262 lastoffset = i->first;
263 assert(lastoffset == 0);
264 fieldtype = LLVM_DtoType(i->second.var->type);
265 fieldinit = i->second.init;
266 prevsize = gTargetData->getTypeSize(fieldtype);
267 i->second.var->llvmFieldIndex = idx;
268 }
269 // colliding offset?
270 else if (lastoffset == i->first) {
271 const llvm::Type* t = LLVM_DtoType(i->second.var->type);
272 size_t s = gTargetData->getTypeSize(t);
273 if (s > prevsize) {
274 fieldpad = s - prevsize;
275 prevsize = s;
276 }
277 llvmHasUnions = true;
278 i->second.var->llvmFieldIndex = idx;
279 }
280 // intersecting offset?
281 else if (i->first < (lastoffset + prevsize)) {
282 const llvm::Type* t = LLVM_DtoType(i->second.var->type);
283 size_t s = gTargetData->getTypeSize(t);
284 assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size
285 llvmHasUnions = true;
286 i->second.var->llvmFieldIndex = idx;
287 i->second.var->llvmFieldIndexOffset = (i->first - lastoffset) / s;
288 }
289 // fresh offset
290 else {
291 // commit the field
292 fieldtypes.push_back(fieldtype);
293 fieldinits.push_back(fieldinit);
294 if (fieldpad) {
295 // match up with below
296 std::vector<llvm::Constant*> vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
297 llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals);
298 fieldtypes.push_back(c->getType());
299 fieldinits.push_back(c);
300 idx++;
301 }
302
303 idx++;
304
305 // start new
306 lastoffset = i->first;
307 fieldtype = LLVM_DtoType(i->second.var->type);
308 fieldinit = i->second.init;
309 prevsize = gTargetData->getTypeSize(fieldtype);
310 i->second.var->llvmFieldIndex = idx;
311 fieldpad = 0;
312 }
313 }
314 fieldtypes.push_back(fieldtype);
315 fieldinits.push_back(fieldinit);
316 if (fieldpad) {
317 // match up with above
318 std::vector<llvm::Constant*> vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
319 llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals);
320 fieldtypes.push_back(c->getType());
321 fieldinits.push_back(c);
322 }
323
324 Logger::println("creating struct type");
325 structtype = llvm::StructType::get(fieldtypes);
326 }
234 327
235 // refine abstract types for stuff like: struct S{S* next;} 328 // refine abstract types for stuff like: struct S{S* next;}
236 if (gIR->topstruct().recty != 0) 329 if (gIR->topstruct().recty != 0)
237 { 330 {
238 llvm::PATypeHolder& pa = gIR->topstruct().recty; 331 llvm::PATypeHolder& pa = gIR->topstruct().recty;
252 llvm::Constant* _init = 0; 345 llvm::Constant* _init = 0;
253 346
254 // always generate the constant initalizer 347 // always generate the constant initalizer
255 if (!zeroInit) { 348 if (!zeroInit) {
256 Logger::println("Not zero initialized"); 349 Logger::println("Not zero initialized");
257 //assert(tk == gIR->topstruct().size()); 350 //assert(tk == gIR->gIR->topstruct()().size());
258 #ifndef LLVMD_NO_LOGGER 351 #ifndef LLVMD_NO_LOGGER
259 Logger::cout() << *structtype << '\n'; 352 Logger::cout() << "struct type: " << *structtype << '\n';
260 for (size_t k=0; k<gIR->topstruct().inits.size(); ++k) { 353 for (size_t k=0; k<fieldinits.size(); ++k) {
261 Logger::cout() << "Type:" << '\n'; 354 Logger::cout() << "Type:" << '\n';
262 Logger::cout() << *gIR->topstruct().inits[k]->getType() << '\n'; 355 Logger::cout() << *fieldinits[k]->getType() << '\n';
263 Logger::cout() << "Value:" << '\n'; 356 Logger::cout() << "Value:" << '\n';
264 Logger::cout() << *gIR->topstruct().inits[k] << '\n'; 357 Logger::cout() << *fieldinits[k] << '\n';
265 } 358 }
266 Logger::cout() << "Initializer printed" << '\n'; 359 Logger::cout() << "Initializer printed" << '\n';
267 #endif 360 #endif
268 llvmInitZ = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits); 361 llvmInitZ = llvm::ConstantStruct::get(structtype,fieldinits);
269 } 362 }
270 else { 363 else {
271 Logger::println("Zero initialized"); 364 Logger::println("Zero initialized");
272 llvmInitZ = llvm::ConstantAggregateZero::get(structtype); 365 llvmInitZ = llvm::ConstantAggregateZero::get(structtype);
273 } 366 }
276 if (getModule() == gIR->dmodule) 369 if (getModule() == gIR->dmodule)
277 { 370 {
278 _init = llvmInitZ; 371 _init = llvmInitZ;
279 } 372 }
280 373
281 std::string initname(mangle()); 374 std::string initname("_D");
282 initname.append("__initZ"); 375 initname.append(mangle());
376 initname.append("6__initZ");
283 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, _init, initname, gIR->module); 377 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, _init, initname, gIR->module);
284 ts->llvmInit = initvar; 378 ts->llvmInit = initvar;
285 379
286 // generate member function definitions 380 // generate member function definitions
287 gIR->topstruct().queueFuncs = false; 381 gIR->topstruct().queueFuncs = false;
288 IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs; 382 IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs;
289 size_t n = mfs.size(); 383 size_t n = mfs.size();
290 for (size_t i=0; i<n; ++i) { 384 for (size_t i=0; i<n; ++i) {
291 mfs[i]->toObjFile(); 385 mfs[i]->toObjFile();
292 } 386 }
293 387
294 llvmDModule = gIR->dmodule; 388 llvmDModule = gIR->dmodule;
295 389
296 gIR->structs.pop_back(); 390 gIR->structs.pop_back();
297 391
298 // generate typeinfo 392 // generate typeinfo
299 if (getModule() == gIR->dmodule) 393 if (getModule() == gIR->dmodule && llvmInternal != LLVMnotypeinfo)
300 type->getTypeInfo(NULL); 394 type->getTypeInfo(NULL);
301 } 395 }
302 396
303 /* ================================================================== */ 397 /* ================================================================== */
304 398
339 gIR->classes.push_back(this); 433 gIR->classes.push_back(this);
340 434
341 // add vtable 435 // add vtable
342 llvm::PATypeHolder pa = llvm::OpaqueType::get(); 436 llvm::PATypeHolder pa = llvm::OpaqueType::get();
343 const llvm::Type* vtabty = llvm::PointerType::get(pa); 437 const llvm::Type* vtabty = llvm::PointerType::get(pa);
344 gIR->topstruct().fields.push_back(vtabty); 438
345 gIR->topstruct().inits.push_back(0); 439 std::vector<const llvm::Type*> fieldtypes;
440 fieldtypes.push_back(vtabty);
441
442 std::vector<llvm::Constant*> fieldinits;
443 fieldinits.push_back(0);
346 444
347 // base classes first 445 // base classes first
348 LLVM_AddBaseClassData(&baseclasses); 446 LLVM_AddBaseClassData(&baseclasses);
349 447
350 // then add own members 448 // then add own members
351 for (int k=0; k < members->dim; k++) { 449 for (int k=0; k < members->dim; k++) {
352 Dsymbol* dsym = (Dsymbol*)(members->data[k]); 450 Dsymbol* dsym = (Dsymbol*)(members->data[k]);
353 dsym->toObjFile(); 451 dsym->toObjFile();
354 } 452 }
355 453
356 llvm::StructType* structtype = llvm::StructType::get(gIR->topstruct().fields); 454 // fill out fieldtypes/inits
455 for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) {
456 fieldtypes.push_back(LLVM_DtoType(i->second.var->type));
457 fieldinits.push_back(i->second.init);
458 }
459
460 llvm::StructType* structtype = llvm::StructType::get(fieldtypes);
357 // refine abstract types for stuff like: class C {C next;} 461 // refine abstract types for stuff like: class C {C next;}
358 if (gIR->topstruct().recty != 0) 462 if (gIR->topstruct().recty != 0)
359 { 463 {
360 llvm::PATypeHolder& pa = gIR->topstruct().recty; 464 llvm::PATypeHolder& pa = gIR->topstruct().recty;
361 llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype); 465 llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype);
439 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; 543 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
440 llvm::Constant* _init = 0; 544 llvm::Constant* _init = 0;
441 545
442 // first field is always the vtable 546 // first field is always the vtable
443 assert(svtblVar != 0); 547 assert(svtblVar != 0);
444 gIR->topstruct().inits[0] = svtblVar; 548 fieldinits[0] = svtblVar;
445 549
446 llvmInitZ = _init = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits); 550 llvmInitZ = _init = llvm::ConstantStruct::get(structtype,fieldinits);
447 assert(_init); 551 assert(_init);
448 552
449 std::string initname("_D"); 553 std::string initname("_D");
450 initname.append(mangle()); 554 initname.append(mangle());
451 initname.append("6__initZ"); 555 initname.append("6__initZ");
455 559
456 if (needs_definition) { 560 if (needs_definition) {
457 initvar->setInitializer(_init); 561 initvar->setInitializer(_init);
458 // generate member functions 562 // generate member functions
459 gIR->topstruct().queueFuncs = false; 563 gIR->topstruct().queueFuncs = false;
460 IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs; 564 IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs;
461 size_t n = mfs.size(); 565 size_t n = mfs.size();
462 for (size_t i=0; i<n; ++i) { 566 for (size_t i=0; i<n; ++i) {
463 mfs[i]->toObjFile(); 567 mfs[i]->toObjFile();
464 } 568 }
465 } 569 }
571 { 675 {
572 Logger::println("Aggregate var declaration: '%s' offset=%d", toChars(), offset); 676 Logger::println("Aggregate var declaration: '%s' offset=%d", toChars(), offset);
573 677
574 Type* t = LLVM_DtoDType(type); 678 Type* t = LLVM_DtoDType(type);
575 const llvm::Type* _type = LLVM_DtoType(t); 679 const llvm::Type* _type = LLVM_DtoType(t);
576 gIR->topstruct().fields.push_back(_type);
577 680
578 llvm::Constant*_init = LLVM_DtoConstInitializer(t, init); 681 llvm::Constant*_init = LLVM_DtoConstInitializer(t, init);
579 assert(_init); 682 assert(_init);
580 Logger::cout() << "field init is: " << *_init << " type should be " << *_type << '\n'; 683 Logger::cout() << "field init is: " << *_init << " type should be " << *_type << '\n';
581 if (_type != _init->getType()) 684 if (_type != _init->getType())
608 else { 711 else {
609 Logger::println("failed for type %s", type->toChars()); 712 Logger::println("failed for type %s", type->toChars());
610 assert(0); 713 assert(0);
611 } 714 }
612 } 715 }
613 gIR->topstruct().inits.push_back(_init); 716
717 // add the field in the IRStruct
718 gIR->topstruct().offsets.insert(std::make_pair(offset, IRStruct::Offset(this,_init)));
614 } 719 }
615 720
616 Logger::println("VarDeclaration::toObjFile is done"); 721 Logger::println("VarDeclaration::toObjFile is done");
617 } 722 }
618 723