Mercurial > projects > ldc
comparison gen/classes.cpp @ 136:0e28624814e8 trunk
[svn r140] did a lot of the work towards being able to pass multiple modules on the command line. not complete yet though
author | lindquist |
---|---|
date | Thu, 17 Jan 2008 03:15:12 +0100 |
parents | 44a95ac7368a |
children | ce7b81fb957f |
comparison
equal
deleted
inserted
replaced
135:176bd52b3cf5 | 136:0e28624814e8 |
---|---|
14 #include "gen/structs.h" | 14 #include "gen/structs.h" |
15 #include "gen/functions.h" | 15 #include "gen/functions.h" |
16 #include "gen/runtime.h" | 16 #include "gen/runtime.h" |
17 #include "gen/dvalue.h" | 17 #include "gen/dvalue.h" |
18 | 18 |
19 #include "ir/irstruct.h" | |
20 | |
19 ////////////////////////////////////////////////////////////////////////////////////////// | 21 ////////////////////////////////////////////////////////////////////////////////////////// |
20 | 22 |
21 static void LLVM_AddBaseClassData(BaseClasses* bcs) | 23 static void LLVM_AddBaseClassData(BaseClasses* bcs) |
22 { | 24 { |
23 // add base class data members first | 25 // add base class data members first |
24 for (int j=0; j<bcs->dim; j++) | 26 for (int j=0; j<bcs->dim; j++) |
25 { | 27 { |
26 BaseClass* bc = (BaseClass*)(bcs->data[j]); | 28 BaseClass* bc = (BaseClass*)(bcs->data[j]); |
27 assert(bc); | |
28 if (bc->base->isInterfaceDeclaration()) | 29 if (bc->base->isInterfaceDeclaration()) |
29 continue; // interfaces only has methods | 30 continue; // interfaces only have methods |
30 | 31 |
31 LLVM_AddBaseClassData(&bc->base->baseclasses); | 32 LLVM_AddBaseClassData(&bc->base->baseclasses); |
32 | 33 |
33 Logger::println("Adding base class members of %s", bc->base->toChars()); | 34 Logger::println("Adding base class members of %s", bc->base->toChars()); |
34 LOG_SCOPE; | 35 LOG_SCOPE; |
36 Array* arr = &bc->base->fields; | 37 Array* arr = &bc->base->fields; |
37 for (int k=0; k < arr->dim; k++) { | 38 for (int k=0; k < arr->dim; k++) { |
38 VarDeclaration* v = (VarDeclaration*)(arr->data[k]); | 39 VarDeclaration* v = (VarDeclaration*)(arr->data[k]); |
39 v->toObjFile(); | 40 v->toObjFile(); |
40 } | 41 } |
41 | |
42 /*for (int k=0; k < bc->base->members->dim; k++) { | |
43 Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]); | |
44 if (dsym->isVarDeclaration()) | |
45 { | |
46 dsym->toObjFile(); | |
47 } | |
48 }*/ | |
49 } | 42 } |
50 } | 43 } |
51 | 44 |
52 ////////////////////////////////////////////////////////////////////////////////////////// | 45 ////////////////////////////////////////////////////////////////////////////////////////// |
53 | 46 |
61 | 54 |
62 // get the TypeClass | 55 // get the TypeClass |
63 assert(cd->type->ty == Tclass); | 56 assert(cd->type->ty == Tclass); |
64 TypeClass* ts = (TypeClass*)cd->type; | 57 TypeClass* ts = (TypeClass*)cd->type; |
65 | 58 |
66 // make sure the IRStruct is created | 59 // make sure the IrStruct is created |
67 IRStruct* irstruct = cd->llvmIRStruct; | 60 IrStruct* irstruct = cd->llvmIrStruct; |
68 if (!irstruct) { | 61 if (!irstruct) { |
69 irstruct = new IRStruct(ts); | 62 irstruct = new IrStruct(ts); |
70 cd->llvmIRStruct = irstruct; | 63 cd->llvmIrStruct = irstruct; |
71 } | 64 } |
72 | 65 |
73 // resolve the base class | 66 // resolve the base class |
74 if (cd->baseClass) { | 67 if (cd->baseClass) { |
75 DtoResolveClass(cd->baseClass); | 68 DtoResolveClass(cd->baseClass); |
76 } | 69 } |
77 | 70 |
78 // resolve interfaces | 71 // resolve interface vtables |
79 if (cd->vtblInterfaces) { | 72 if (cd->vtblInterfaces) { |
80 for (int i=0; i < cd->vtblInterfaces->dim; i++) { | 73 for (int i=0; i < cd->vtblInterfaces->dim; i++) { |
81 BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i]; | 74 BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i]; |
82 ClassDeclaration *id = b->base; | 75 ClassDeclaration *id = b->base; |
83 DtoResolveClass(id); | 76 DtoResolveClass(id); |
109 TypeClass* itc = (TypeClass*)id->type; | 102 TypeClass* itc = (TypeClass*)id->type; |
110 const llvm::Type* ivtblTy = getPtrToType(itc->llvmVtblType->get()); | 103 const llvm::Type* ivtblTy = getPtrToType(itc->llvmVtblType->get()); |
111 fieldtypes.push_back(ivtblTy); | 104 fieldtypes.push_back(ivtblTy); |
112 | 105 |
113 // add this interface to the map | 106 // add this interface to the map |
114 IRInterface* iri = new IRInterface(b, isaStruct(itc->llvmVtblType->get())); | 107 IrInterface* iri = new IrInterface(b, isaStruct(itc->llvmVtblType->get())); |
115 irstruct->interfaces.insert(std::make_pair(id, iri)); | 108 irstruct->interfaces.insert(std::make_pair(id, iri)); |
116 } | 109 } |
117 | 110 |
118 // base classes first | 111 // base classes first |
119 LLVM_AddBaseClassData(&cd->baseclasses); | 112 LLVM_AddBaseClassData(&cd->baseclasses); |
138 unsigned lastoffset = (unsigned)-1; | 131 unsigned lastoffset = (unsigned)-1; |
139 const llvm::Type* fieldtype = NULL; | 132 const llvm::Type* fieldtype = NULL; |
140 VarDeclaration* fieldinit = NULL; | 133 VarDeclaration* fieldinit = NULL; |
141 size_t fieldpad = 0; | 134 size_t fieldpad = 0; |
142 int idx = 0; | 135 int idx = 0; |
143 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { | 136 for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { |
144 // first iteration | 137 // first iteration |
145 if (lastoffset == (unsigned)-1) { | 138 if (lastoffset == (unsigned)-1) { |
146 lastoffset = i->first; | 139 lastoffset = i->first; |
147 fieldtype = i->second.type; | 140 fieldtype = i->second.type; |
148 fieldinit = i->second.var; | 141 fieldinit = i->second.var; |
149 prevsize = getABITypeSize(fieldtype); | 142 prevsize = getABITypeSize(fieldtype); |
150 i->second.var->llvmFieldIndex = idx; | 143 i->second.var->irField->index = idx; |
151 } | 144 } |
152 // colliding offset? | 145 // colliding offset? |
153 else if (lastoffset == i->first) { | 146 else if (lastoffset == i->first) { |
154 size_t s = getABITypeSize(i->second.type); | 147 size_t s = getABITypeSize(i->second.type); |
155 if (s > prevsize) { | 148 if (s > prevsize) { |
156 fieldpad += s - prevsize; | 149 fieldpad += s - prevsize; |
157 prevsize = s; | 150 prevsize = s; |
158 } | 151 } |
159 cd->llvmHasUnions = true; | 152 cd->llvmHasUnions = true; |
160 i->second.var->llvmFieldIndex = idx; | 153 i->second.var->irField->index = idx; |
161 } | 154 } |
162 // intersecting offset? | 155 // intersecting offset? |
163 else if (i->first < (lastoffset + prevsize)) { | 156 else if (i->first < (lastoffset + prevsize)) { |
164 size_t s = getABITypeSize(i->second.type); | 157 size_t s = getABITypeSize(i->second.type); |
165 assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size | 158 assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size |
166 cd->llvmHasUnions = true; | 159 cd->llvmHasUnions = true; |
167 i->second.var->llvmFieldIndex = idx; | 160 i->second.var->irField->index = idx; |
168 i->second.var->llvmFieldIndexOffset = (i->first - lastoffset) / s; | 161 i->second.var->irField->indexOffset = (i->first - lastoffset) / s; |
169 } | 162 } |
170 // fresh offset | 163 // fresh offset |
171 else { | 164 else { |
172 // commit the field | 165 // commit the field |
173 fieldtypes.push_back(fieldtype); | 166 fieldtypes.push_back(fieldtype); |
183 // start new | 176 // start new |
184 lastoffset = i->first; | 177 lastoffset = i->first; |
185 fieldtype = i->second.type; | 178 fieldtype = i->second.type; |
186 fieldinit = i->second.var; | 179 fieldinit = i->second.var; |
187 prevsize = getABITypeSize(fieldtype); | 180 prevsize = getABITypeSize(fieldtype); |
188 i->second.var->llvmFieldIndex = idx; | 181 i->second.var->irField->index = idx; |
189 fieldpad = 0; | 182 fieldpad = 0; |
190 } | 183 } |
191 } | 184 } |
192 fieldtypes.push_back(fieldtype); | 185 fieldtypes.push_back(fieldtype); |
193 irstruct->defaultFields.push_back(fieldinit); | 186 irstruct->defaultFields.push_back(fieldinit); |
197 } | 190 } |
198 } | 191 } |
199 | 192 |
200 /* | 193 /* |
201 // add field types | 194 // add field types |
202 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { | 195 for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { |
203 fieldtypes.push_back(i->second.type); | 196 fieldtypes.push_back(i->second.type); |
204 } | 197 } |
205 */ | 198 */ |
206 | 199 |
207 const llvm::StructType* structtype = llvm::StructType::get(fieldtypes); | 200 const llvm::StructType* structtype = llvm::StructType::get(fieldtypes); |
305 LOG_SCOPE; | 298 LOG_SCOPE; |
306 | 299 |
307 assert(cd->type->ty == Tclass); | 300 assert(cd->type->ty == Tclass); |
308 TypeClass* ts = (TypeClass*)cd->type; | 301 TypeClass* ts = (TypeClass*)cd->type; |
309 | 302 |
310 assert(cd->llvmIRStruct); | 303 assert(cd->llvmIrStruct); |
311 IRStruct* irstruct = cd->llvmIRStruct; | 304 IrStruct* irstruct = cd->llvmIrStruct; |
312 | 305 |
313 gIR->structs.push_back(irstruct); | 306 gIR->structs.push_back(irstruct); |
314 gIR->classes.push_back(cd); | 307 gIR->classes.push_back(cd); |
315 | 308 |
316 bool needs_definition = false; | 309 bool needs_definition = false; |
317 if (cd->getModule() == gIR->dmodule) { | 310 if (cd->getModule() == gIR->dmodule) { |
318 needs_definition = true; | 311 needs_definition = true; |
319 } | 312 } |
320 | 313 |
321 // interface vtables are emitted by the class implementing them | 314 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; |
322 // also, interfaces have no static initializer | 315 |
323 // also, abstract classes have no vtable | 316 // interfaces have no static initializer |
317 // same goes for abstract classes | |
324 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { | 318 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { |
325 // vtable | 319 // vtable |
326 std::string varname("_D"); | 320 std::string varname("_D"); |
327 varname.append(cd->mangle()); | 321 varname.append(cd->mangle()); |
328 varname.append("6__vtblZ"); | 322 varname.append("6__vtblZ"); |
329 | 323 |
330 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; | |
331 | |
332 const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get()); | 324 const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get()); |
333 cd->llvmVtbl = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module); | 325 cd->llvmVtbl = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module); |
334 | 326 } |
335 // build interface info type | 327 |
336 std::vector<const llvm::Type*> types; | 328 // get interface info type |
337 // ClassInfo classinfo | 329 const llvm::StructType* infoTy = DtoInterfaceInfoType(); |
338 ClassDeclaration* cd2 = ClassDeclaration::classinfo; | 330 |
339 DtoResolveClass(cd2); | 331 // interface info array |
340 types.push_back(getPtrToType(cd2->type->llvmType->get())); | 332 if (cd->vtblInterfaces->dim > 0) { |
341 // void*[] vtbl | 333 // symbol name |
342 std::vector<const llvm::Type*> vtbltypes; | 334 std::string nam = "_D"; |
343 vtbltypes.push_back(DtoSize_t()); | 335 nam.append(cd->mangle()); |
344 const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); | 336 nam.append("16__interfaceInfosZ"); |
345 vtbltypes.push_back(byteptrptrty); | 337 // resolve array type |
346 types.push_back(llvm::StructType::get(vtbltypes)); | 338 const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, cd->vtblInterfaces->dim); |
347 // int offset | 339 // declare global |
348 types.push_back(llvm::Type::Int32Ty); | 340 irstruct->interfaceInfosTy = arrTy; |
349 // create type | 341 irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, _linkage, NULL, nam, gIR->module); |
350 const llvm::StructType* infoTy = llvm::StructType::get(types); | 342 } |
351 | 343 |
352 // interface info array | 344 // interfaces have no static initializer |
353 if (cd->vtblInterfaces->dim > 0) { | 345 // same goes for abstract classes |
354 // symbol name | 346 if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { |
355 std::string nam = "_D"; | |
356 nam.append(cd->mangle()); | |
357 nam.append("16__interfaceInfosZ"); | |
358 // resolve array type | |
359 const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, cd->vtblInterfaces->dim); | |
360 // declare global | |
361 irstruct->interfaceInfosTy = arrTy; | |
362 irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, _linkage, NULL, nam, gIR->module); | |
363 } | |
364 | |
365 // interface vtables | 347 // interface vtables |
366 unsigned idx = 0; | 348 unsigned idx = 0; |
367 for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) | 349 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) |
368 { | 350 { |
369 ClassDeclaration* id = i->first; | 351 ClassDeclaration* id = i->first; |
370 IRInterface* iri = i->second; | 352 IrInterface* iri = i->second; |
371 | 353 |
372 std::string nam("_D"); | 354 std::string nam("_D"); |
373 nam.append(cd->mangle()); | 355 nam.append(cd->mangle()); |
374 nam.append("11__interface"); | 356 nam.append("11__interface"); |
375 nam.append(id->mangle()); | 357 nam.append(id->mangle()); |
376 nam.append("6__vtblZ"); | 358 nam.append("6__vtblZ"); |
377 | 359 |
378 assert(iri->vtblTy); | 360 assert(iri->vtblTy); |
379 iri->vtbl = new llvm::GlobalVariable(iri->vtblTy, true, _linkage, 0, nam, gIR->module); | 361 iri->vtbl = new llvm::GlobalVariable(iri->vtblTy, true, _linkage, 0, nam, gIR->module); |
380 iri->infoTy = infoTy; | |
381 llvm::Constant* idxs[2] = {DtoConstUint(0), DtoConstUint(idx)}; | 362 llvm::Constant* idxs[2] = {DtoConstUint(0), DtoConstUint(idx)}; |
382 iri->info = llvm::ConstantExpr::getGetElementPtr(irstruct->interfaceInfos, idxs, 2); | 363 iri->info = llvm::ConstantExpr::getGetElementPtr(irstruct->interfaceInfos, idxs, 2); |
383 idx++; | 364 idx++; |
384 } | 365 } |
385 | 366 |
418 return; // nothing to do | 399 return; // nothing to do |
419 | 400 |
420 Logger::println("DtoConstInitClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); | 401 Logger::println("DtoConstInitClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); |
421 LOG_SCOPE; | 402 LOG_SCOPE; |
422 | 403 |
423 IRStruct* irstruct = cd->llvmIRStruct; | 404 IrStruct* irstruct = cd->llvmIrStruct; |
424 gIR->structs.push_back(irstruct); | 405 gIR->structs.push_back(irstruct); |
425 gIR->classes.push_back(cd); | 406 gIR->classes.push_back(cd); |
426 | 407 |
427 // get the struct (class) type | 408 // get the struct (class) type |
428 assert(cd->type->ty == Tclass); | 409 assert(cd->type->ty == Tclass); |
429 TypeClass* ts = (TypeClass*)cd->type; | 410 TypeClass* ts = (TypeClass*)cd->type; |
430 const llvm::StructType* structtype = isaStruct(ts->llvmType->get()); | 411 const llvm::StructType* structtype = isaStruct(ts->llvmType->get()); |
431 const llvm::StructType* vtbltype = isaStruct(ts->llvmVtblType->get()); | 412 const llvm::StructType* vtbltype = isaStruct(ts->llvmVtblType->get()); |
432 | 413 |
433 // make sure each offset knows its default initializer | 414 // make sure each offset knows its default initializer |
434 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) | 415 for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) |
435 { | 416 { |
436 IRStruct::Offset* so = &i->second; | 417 IrStruct::Offset* so = &i->second; |
437 llvm::Constant* finit = DtoConstFieldInitializer(so->var->type, so->var->init); | 418 llvm::Constant* finit = DtoConstFieldInitializer(so->var->type, so->var->init); |
438 so->init = finit; | 419 so->init = finit; |
439 so->var->llvmConstInit = finit; | 420 so->var->irField->constInit = finit; |
440 } | 421 } |
441 | 422 |
442 // fill out fieldtypes/inits | 423 // fill out fieldtypes/inits |
443 std::vector<llvm::Constant*> fieldinits; | 424 std::vector<llvm::Constant*> fieldinits; |
444 | 425 |
463 fieldinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty))); | 444 fieldinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty))); |
464 | 445 |
465 size_t dataoffset = 2; | 446 size_t dataoffset = 2; |
466 | 447 |
467 // next comes interface vtables | 448 // next comes interface vtables |
468 for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) | 449 const llvm::StructType* infoTy = DtoInterfaceInfoType(); |
469 { | 450 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) |
470 IRInterface* iri = i->second; | 451 { |
452 IrInterface* iri = i->second; | |
453 iri->infoTy = infoTy; | |
471 if (cd->isAbstract()) | 454 if (cd->isAbstract()) |
472 { | 455 { |
473 fieldinits.push_back(llvm::Constant::getNullValue(iri->vtblTy)); | 456 fieldinits.push_back(llvm::Constant::getNullValue(iri->vtblTy)); |
474 } | 457 } |
475 else | 458 else |
480 } | 463 } |
481 } | 464 } |
482 | 465 |
483 /* | 466 /* |
484 // rest | 467 // rest |
485 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { | 468 for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { |
486 Logger::println("adding fieldinit for: %s", i->second.var->toChars()); | 469 Logger::println("adding fieldinit for: %s", i->second.var->toChars()); |
487 fieldinits.push_back(i->second.init); | 470 fieldinits.push_back(i->second.init); |
488 } | 471 } |
489 */ | 472 */ |
490 | 473 |
491 // go through the field inits and build the default initializer | 474 // go through the field inits and build the default initializer |
492 size_t nfi = irstruct->defaultFields.size(); | 475 size_t nfi = irstruct->defaultFields.size(); |
493 for (size_t i=0; i<nfi; ++i) { | 476 for (size_t i=0; i<nfi; ++i) { |
494 llvm::Constant* c; | 477 llvm::Constant* c; |
495 if (irstruct->defaultFields[i] != NULL) { | 478 if (irstruct->defaultFields[i] != NULL) { |
496 c = irstruct->defaultFields[i]->llvmConstInit; | 479 c = irstruct->defaultFields[i]->irField->constInit; |
497 assert(c); | 480 assert(c); |
498 } | 481 } |
499 else { | 482 else { |
500 const llvm::ArrayType* arrty = isaArray(structtype->getElementType(i+dataoffset)); | 483 const llvm::ArrayType* arrty = isaArray(structtype->getElementType(i+dataoffset)); |
501 std::vector<llvm::Constant*> vals(arrty->getNumElements(), llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false)); | 484 std::vector<llvm::Constant*> vals(arrty->getNumElements(), llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false)); |
533 assert(dsym); | 516 assert(dsym); |
534 //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; | 517 //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; |
535 | 518 |
536 if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { | 519 if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { |
537 DtoForceDeclareDsymbol(fd); | 520 DtoForceDeclareDsymbol(fd); |
538 assert(fd->llvmValue); | 521 assert(fd->irFunc->func); |
539 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue); | 522 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->irFunc->func); |
540 // cast if necessary (overridden method) | 523 // cast if necessary (overridden method) |
541 if (c->getType() != vtbltype->getElementType(k)) | 524 if (c->getType() != vtbltype->getElementType(k)) |
542 c = llvm::ConstantExpr::getBitCast(c, vtbltype->getElementType(k)); | 525 c = llvm::ConstantExpr::getBitCast(c, vtbltype->getElementType(k)); |
543 sinits.push_back(c); | 526 sinits.push_back(c); |
544 } | 527 } |
566 cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit); | 549 cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit); |
567 | 550 |
568 // create interface vtable const initalizers | 551 // create interface vtable const initalizers |
569 int idx = 2; | 552 int idx = 2; |
570 int idxScale = PTRSIZE; | 553 int idxScale = PTRSIZE; |
571 for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) | 554 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) |
572 { | 555 { |
573 ClassDeclaration* id = i->first; | 556 ClassDeclaration* id = i->first; |
574 assert(id->type->ty == Tclass); | 557 assert(id->type->ty == Tclass); |
575 TypeClass* its = (TypeClass*)id->type; | 558 TypeClass* its = (TypeClass*)id->type; |
576 | 559 |
577 IRInterface* iri = i->second; | 560 IrInterface* iri = i->second; |
578 BaseClass* b = iri->base; | 561 BaseClass* b = iri->base; |
579 | 562 |
580 const llvm::StructType* ivtbl_ty = isaStruct(its->llvmVtblType->get()); | 563 const llvm::StructType* ivtbl_ty = isaStruct(its->llvmVtblType->get()); |
581 | 564 |
582 // generate interface info initializer | 565 // generate interface info initializer |
583 std::vector<llvm::Constant*> infoInits; | 566 std::vector<llvm::Constant*> infoInits; |
567 | |
584 // classinfo | 568 // classinfo |
585 assert(id->llvmClass); | 569 assert(id->llvmClass); |
586 llvm::Constant* c = id->llvmClass; | 570 llvm::Constant* c = id->llvmClass; |
587 infoInits.push_back(c); | 571 infoInits.push_back(c); |
572 | |
588 // vtbl | 573 // vtbl |
589 const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); | 574 const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); |
590 c = llvm::ConstantExpr::getBitCast(iri->vtbl, byteptrptrty); | 575 c = llvm::ConstantExpr::getBitCast(iri->vtbl, byteptrptrty); |
591 c = DtoConstSlice(DtoConstSize_t(b->vtbl.dim), c); | 576 c = DtoConstSlice(DtoConstSize_t(b->vtbl.dim), c); |
592 infoInits.push_back(c); | 577 infoInits.push_back(c); |
578 | |
593 // offset | 579 // offset |
594 infoInits.push_back(DtoConstInt(idx*idxScale)); | 580 infoInits.push_back(DtoConstInt(idx*idxScale)); |
581 | |
595 // create interface info initializer constant | 582 // create interface info initializer constant |
596 iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits)); | 583 iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits)); |
597 | 584 |
598 // generate vtable initializer | 585 // generate vtable initializer |
599 std::vector<llvm::Constant*> iinits; | 586 std::vector<llvm::Constant*> iinits; |
606 Logger::println("interface vtbl const init nr. %d", k); | 593 Logger::println("interface vtbl const init nr. %d", k); |
607 Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k]; | 594 Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k]; |
608 FuncDeclaration* fd = dsym->isFuncDeclaration(); | 595 FuncDeclaration* fd = dsym->isFuncDeclaration(); |
609 assert(fd); | 596 assert(fd); |
610 DtoForceDeclareDsymbol(fd); | 597 DtoForceDeclareDsymbol(fd); |
611 assert(fd->llvmValue); | 598 assert(fd->irFunc->func); |
612 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue); | 599 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->irFunc->func); |
600 | |
613 // we have to bitcast, as the type created in ResolveClass expects a different this type | 601 // we have to bitcast, as the type created in ResolveClass expects a different this type |
614 c = llvm::ConstantExpr::getBitCast(c, iri->vtblTy->getContainedType(k)); | 602 c = llvm::ConstantExpr::getBitCast(c, iri->vtblTy->getContainedType(k)); |
615 iinits.push_back(c); | 603 iinits.push_back(c); |
616 } | 604 } |
617 | 605 |
627 llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits); | 615 llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits); |
628 iri->vtblInit = llvm::cast<llvm::ConstantStruct>(civtblInit); | 616 iri->vtblInit = llvm::cast<llvm::ConstantStruct>(civtblInit); |
629 | 617 |
630 idx++; | 618 idx++; |
631 } | 619 } |
632 } // !abstract | 620 } |
621 // we always generate interfaceinfos as best we can | |
622 else | |
623 { | |
624 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) | |
625 { | |
626 ClassDeclaration* id = i->first; | |
627 assert(id->type->ty == Tclass); | |
628 TypeClass* its = (TypeClass*)id->type; | |
629 | |
630 IrInterface* iri = i->second; | |
631 BaseClass* b = iri->base; | |
632 | |
633 // generate interface info initializer | |
634 std::vector<llvm::Constant*> infoInits; | |
635 | |
636 // classinfo | |
637 assert(id->llvmClass); | |
638 llvm::Constant* c = id->llvmClass; | |
639 infoInits.push_back(c); | |
640 | |
641 // vtbl | |
642 const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); | |
643 c = DtoConstSlice(DtoConstSize_t(0), getNullPtr(byteptrptrty)); | |
644 infoInits.push_back(c); | |
645 | |
646 // offset | |
647 infoInits.push_back(DtoConstInt(0)); | |
648 | |
649 // create interface info initializer constant | |
650 iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits)); | |
651 } | |
652 } | |
633 | 653 |
634 gIR->classes.pop_back(); | 654 gIR->classes.pop_back(); |
635 gIR->structs.pop_back(); | 655 gIR->structs.pop_back(); |
636 } | 656 } |
637 | 657 |
656 { | 676 { |
657 cd->llvmInit->setInitializer(cd->llvmConstInit); | 677 cd->llvmInit->setInitializer(cd->llvmConstInit); |
658 cd->llvmVtbl->setInitializer(cd->llvmConstVtbl); | 678 cd->llvmVtbl->setInitializer(cd->llvmConstVtbl); |
659 | 679 |
660 // initialize interface vtables | 680 // initialize interface vtables |
661 IRStruct* irstruct = cd->llvmIRStruct; | 681 IrStruct* irstruct = cd->llvmIrStruct; |
662 std::vector<llvm::Constant*> infoInits; | 682 std::vector<llvm::Constant*> infoInits; |
663 for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) | 683 for (IrStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) |
664 { | 684 { |
665 IRInterface* iri = i->second; | 685 IrInterface* iri = i->second; |
666 iri->vtbl->setInitializer(iri->vtblInit); | 686 iri->vtbl->setInitializer(iri->vtblInit); |
667 infoInits.push_back(iri->infoInit); | 687 infoInits.push_back(iri->infoInit); |
668 } | 688 } |
669 // initialize interface info array | 689 // initialize interface info array |
670 if (!infoInits.empty()) | 690 if (!infoInits.empty()) |
709 { | 729 { |
710 Logger::println("Resolving outer class"); | 730 Logger::println("Resolving outer class"); |
711 LOG_SCOPE; | 731 LOG_SCOPE; |
712 DValue* thisval = newexp->thisexp->toElem(gIR); | 732 DValue* thisval = newexp->thisexp->toElem(gIR); |
713 size_t idx = 2; | 733 size_t idx = 2; |
714 idx += tc->sym->llvmIRStruct->interfaces.size(); | 734 idx += tc->sym->llvmIrStruct->interfaces.size(); |
715 llvm::Value* dst = thisval->getRVal(); | 735 llvm::Value* dst = thisval->getRVal(); |
716 llvm::Value* src = DtoGEPi(mem,0,idx,"tmp"); | 736 llvm::Value* src = DtoGEPi(mem,0,idx,"tmp"); |
717 Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n'; | 737 Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n'; |
718 DtoStore(dst, src); | 738 DtoStore(dst, src); |
719 } | 739 } |
721 else if (tc->sym->isNested()) | 741 else if (tc->sym->isNested()) |
722 { | 742 { |
723 Logger::println("Resolving nested context"); | 743 Logger::println("Resolving nested context"); |
724 LOG_SCOPE; | 744 LOG_SCOPE; |
725 size_t idx = 2; | 745 size_t idx = 2; |
726 idx += tc->sym->llvmIRStruct->interfaces.size(); | 746 idx += tc->sym->llvmIrStruct->interfaces.size(); |
727 llvm::Value* nest = gIR->func()->decl->llvmNested; | 747 llvm::Value* nest = gIR->func()->decl->irFunc->nestedVar; |
728 if (!nest) | 748 if (!nest) |
729 nest = gIR->func()->decl->llvmThisVar; | 749 nest = gIR->func()->decl->irFunc->thisVar; |
730 assert(nest); | 750 assert(nest); |
731 llvm::Value* gep = DtoGEPi(mem,0,idx,"tmp"); | 751 llvm::Value* gep = DtoGEPi(mem,0,idx,"tmp"); |
732 nest = DtoBitCast(nest, gep->getType()->getContainedType(0)); | 752 nest = DtoBitCast(nest, gep->getType()->getContainedType(0)); |
733 DtoStore(nest, gep); | 753 DtoStore(nest, gep); |
734 } | 754 } |
790 Logger::println("Calling constructor"); | 810 Logger::println("Calling constructor"); |
791 LOG_SCOPE; | 811 LOG_SCOPE; |
792 | 812 |
793 assert(ctor); | 813 assert(ctor); |
794 DtoForceDeclareDsymbol(ctor); | 814 DtoForceDeclareDsymbol(ctor); |
795 llvm::Function* fn = llvm::cast<llvm::Function>(ctor->llvmValue); | 815 llvm::Function* fn = ctor->irFunc->func; |
796 TypeFunction* tf = (TypeFunction*)DtoDType(ctor->type); | 816 TypeFunction* tf = (TypeFunction*)DtoDType(ctor->type); |
797 | 817 |
798 std::vector<llvm::Value*> ctorargs; | 818 std::vector<llvm::Value*> ctorargs; |
799 ctorargs.push_back(mem); | 819 ctorargs.push_back(mem); |
800 for (size_t i=0; i<arguments->dim; ++i) | 820 for (size_t i=0; i<arguments->dim; ++i) |
820 { | 840 { |
821 Array* arr = &tc->sym->dtors; | 841 Array* arr = &tc->sym->dtors; |
822 for (size_t i=0; i<arr->dim; i++) | 842 for (size_t i=0; i<arr->dim; i++) |
823 { | 843 { |
824 FuncDeclaration* fd = (FuncDeclaration*)arr->data[i]; | 844 FuncDeclaration* fd = (FuncDeclaration*)arr->data[i]; |
825 assert(fd->llvmValue); | 845 assert(fd->irFunc->func); |
826 new llvm::CallInst(fd->llvmValue, instance, "", gIR->scopebb()); | 846 new llvm::CallInst(fd->irFunc->func, instance, "", gIR->scopebb()); |
827 } | 847 } |
828 } | 848 } |
829 | 849 |
830 ////////////////////////////////////////////////////////////////////////////////////////// | 850 ////////////////////////////////////////////////////////////////////////////////////////// |
831 | 851 |
1029 ptr = gIR->ir->CreateBitCast(ptr, st, "tmp"); | 1049 ptr = gIR->ir->CreateBitCast(ptr, st, "tmp"); |
1030 } | 1050 } |
1031 | 1051 |
1032 unsigned dataoffset = 2 + cd->vtblInterfaces->dim; | 1052 unsigned dataoffset = 2 + cd->vtblInterfaces->dim; |
1033 | 1053 |
1034 IRStruct* irstruct = cd->llvmIRStruct; | 1054 IrStruct* irstruct = cd->llvmIrStruct; |
1035 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { | 1055 for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { |
1036 //for (unsigned i=0; i<cd->fields.dim; ++i) { | 1056 //for (unsigned i=0; i<cd->fields.dim; ++i) { |
1037 //VarDeclaration* vd = (VarDeclaration*)cd->fields.data[i]; | 1057 //VarDeclaration* vd = (VarDeclaration*)cd->fields.data[i]; |
1038 VarDeclaration* vd = i->second.var; | 1058 VarDeclaration* vd = i->second.var; |
1039 assert(vd); | 1059 assert(vd); |
1040 Type* vdtype = DtoDType(vd->type); | 1060 Type* vdtype = DtoDType(vd->type); |
1041 Logger::println("found %u type %s", vd->offset, vdtype->toChars()); | 1061 Logger::println("found %u type %s", vd->offset, vdtype->toChars()); |
1042 assert(vd->llvmFieldIndex >= 0); | 1062 assert(vd->irField->index >= 0); |
1043 if (os == vd->offset && vdtype == t) { | 1063 if (os == vd->offset && vdtype == t) { |
1044 idxs.push_back(vd->llvmFieldIndex + dataoffset); | 1064 idxs.push_back(vd->irField->index + dataoffset); |
1045 Logger::cout() << "indexing: " << *ptr << '\n'; | 1065 Logger::cout() << "indexing: " << *ptr << '\n'; |
1046 ptr = DtoGEP(ptr, idxs, "tmp"); | 1066 ptr = DtoGEP(ptr, idxs, "tmp"); |
1047 if (ptr->getType() != llt) | 1067 if (ptr->getType() != llt) |
1048 ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); | 1068 ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); |
1049 Logger::cout() << "indexing: " << *ptr << '\n'; | 1069 Logger::cout() << "indexing: " << *ptr << '\n'; |
1050 if (vd->llvmFieldIndexOffset) | 1070 if (vd->irField->indexOffset) |
1051 ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb()); | 1071 ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->irField->indexOffset), "tmp", gIR->scopebb()); |
1052 Logger::cout() << "indexing: " << *ptr << '\n'; | 1072 Logger::cout() << "indexing: " << *ptr << '\n'; |
1053 return ptr; | 1073 return ptr; |
1054 } | 1074 } |
1055 else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) { | 1075 else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) { |
1056 TypeStruct* ts = (TypeStruct*)vdtype; | 1076 TypeStruct* ts = (TypeStruct*)vdtype; |
1057 StructDeclaration* ssd = ts->sym; | 1077 StructDeclaration* ssd = ts->sym; |
1058 idxs.push_back(vd->llvmFieldIndex + dataoffset); | 1078 idxs.push_back(vd->irField->index + dataoffset); |
1059 if (vd->llvmFieldIndexOffset) { | 1079 if (vd->irField->indexOffset) { |
1060 Logger::println("has union field offset"); | 1080 Logger::println("has union field offset"); |
1061 ptr = DtoGEP(ptr, idxs, "tmp"); | 1081 ptr = DtoGEP(ptr, idxs, "tmp"); |
1062 if (ptr->getType() != llt) | 1082 if (ptr->getType() != llt) |
1063 ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); | 1083 ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); |
1064 ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb()); | 1084 ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->irField->indexOffset), "tmp", gIR->scopebb()); |
1065 std::vector<unsigned> tmp; | 1085 std::vector<unsigned> tmp; |
1066 return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp); | 1086 return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp); |
1067 } | 1087 } |
1068 else { | 1088 else { |
1069 const llvm::Type* sty = getPtrToType(DtoType(vd->type)); | 1089 const llvm::Type* sty = getPtrToType(DtoType(vd->type)); |
1151 inits.push_back(DtoConstSize_t(offset)); | 1171 inits.push_back(DtoConstSize_t(offset)); |
1152 | 1172 |
1153 vd->type->getTypeInfo(NULL); | 1173 vd->type->getTypeInfo(NULL); |
1154 assert(vd->type->vtinfo); | 1174 assert(vd->type->vtinfo); |
1155 DtoForceDeclareDsymbol(vd->type->vtinfo); | 1175 DtoForceDeclareDsymbol(vd->type->vtinfo); |
1156 llvm::Constant* c = isaConstant(vd->type->vtinfo->llvmValue); | 1176 llvm::Constant* c = isaConstant(vd->type->vtinfo->getIrValue()); |
1157 | 1177 |
1158 const llvm::Type* tiTy = getPtrToType(Type::typeinfo->type->llvmType->get()); | 1178 const llvm::Type* tiTy = getPtrToType(Type::typeinfo->type->llvmType->get()); |
1159 //Logger::cout() << "tiTy = " << *tiTy << '\n'; | 1179 //Logger::cout() << "tiTy = " << *tiTy << '\n'; |
1160 | 1180 |
1161 types.push_back(tiTy); | 1181 types.push_back(tiTy); |
1228 return llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)); | 1248 return llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)); |
1229 } | 1249 } |
1230 else if (cd->dtors.dim == 1) { | 1250 else if (cd->dtors.dim == 1) { |
1231 DtorDeclaration *d = (DtorDeclaration *)cd->dtors.data[0]; | 1251 DtorDeclaration *d = (DtorDeclaration *)cd->dtors.data[0]; |
1232 DtoForceDeclareDsymbol(d); | 1252 DtoForceDeclareDsymbol(d); |
1233 assert(d->llvmValue); | 1253 assert(d->irFunc->func); |
1234 return llvm::ConstantExpr::getBitCast(isaConstant(d->llvmValue), getPtrToType(llvm::Type::Int8Ty)); | 1254 return llvm::ConstantExpr::getBitCast(isaConstant(d->irFunc->func), getPtrToType(llvm::Type::Int8Ty)); |
1235 } | 1255 } |
1236 | 1256 |
1237 std::string gname("_D"); | 1257 std::string gname("_D"); |
1238 gname.append(cd->mangle()); | 1258 gname.append(cd->mangle()); |
1239 gname.append("12__destructorMFZv"); | 1259 gname.append("12__destructorMFZv"); |
1247 | 1267 |
1248 for (size_t i = 0; i < cd->dtors.dim; i++) | 1268 for (size_t i = 0; i < cd->dtors.dim; i++) |
1249 { | 1269 { |
1250 DtorDeclaration *d = (DtorDeclaration *)cd->dtors.data[i]; | 1270 DtorDeclaration *d = (DtorDeclaration *)cd->dtors.data[i]; |
1251 DtoForceDeclareDsymbol(d); | 1271 DtoForceDeclareDsymbol(d); |
1252 assert(d->llvmValue); | 1272 assert(d->irFunc->func); |
1253 builder.CreateCall(d->llvmValue, thisptr); | 1273 builder.CreateCall(d->irFunc->func, thisptr); |
1254 } | 1274 } |
1255 builder.CreateRetVoid(); | 1275 builder.CreateRetVoid(); |
1256 | 1276 |
1257 return llvm::ConstantExpr::getBitCast(func, getPtrToType(llvm::Type::Int8Ty)); | 1277 return llvm::ConstantExpr::getBitCast(func, getPtrToType(llvm::Type::Int8Ty)); |
1258 } | 1278 } |
1378 c = DtoConstSlice(DtoConstSize_t(vtblsz), c); | 1398 c = DtoConstSlice(DtoConstSize_t(vtblsz), c); |
1379 } | 1399 } |
1380 inits.push_back(c); | 1400 inits.push_back(c); |
1381 | 1401 |
1382 // interfaces array | 1402 // interfaces array |
1383 IRStruct* irstruct = cd->llvmIRStruct; | 1403 IrStruct* irstruct = cd->llvmIrStruct; |
1384 if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos || cd->isAbstract()) { | 1404 if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos || cd->isAbstract()) { |
1385 c = cinfo->llvmConstInit->getOperand(5); | 1405 c = cinfo->llvmConstInit->getOperand(5); |
1386 } | 1406 } |
1387 else { | 1407 else { |
1388 const llvm::Type* t = cinfo->llvmConstInit->getOperand(5)->getType()->getContainedType(1); | 1408 const llvm::Type* t = cinfo->llvmConstInit->getOperand(5)->getType()->getContainedType(1); |
1444 inits.push_back(c); | 1464 inits.push_back(c); |
1445 | 1465 |
1446 // default constructor | 1466 // default constructor |
1447 if (cd->defaultCtor && !cd->isInterfaceDeclaration() && !cd->isAbstract()) { | 1467 if (cd->defaultCtor && !cd->isInterfaceDeclaration() && !cd->isAbstract()) { |
1448 DtoForceDeclareDsymbol(cd->defaultCtor); | 1468 DtoForceDeclareDsymbol(cd->defaultCtor); |
1449 c = isaConstant(cd->defaultCtor->llvmValue); | 1469 c = isaConstant(cd->defaultCtor->irFunc->func); |
1450 const llvm::Type* toTy = cinfo->llvmConstInit->getOperand(12)->getType(); | 1470 const llvm::Type* toTy = cinfo->llvmConstInit->getOperand(12)->getType(); |
1451 c = llvm::ConstantExpr::getBitCast(c, toTy); | 1471 c = llvm::ConstantExpr::getBitCast(c, toTy); |
1452 } | 1472 } |
1453 else { | 1473 else { |
1454 c = cinfo->llvmConstInit->getOperand(12); | 1474 c = cinfo->llvmConstInit->getOperand(12); |