Mercurial > projects > ldc
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 |