comparison gen/classes.cpp @ 113:27b9f749d9fe trunk

[svn r117] Initial working implementation of interfaces. Groundwork for all the different types of class/interface casts laid out.
author lindquist
date Sat, 24 Nov 2007 06:33:00 +0100
parents 368547b1cbe6
children 5880c12dba83
comparison
equal deleted inserted replaced
112:368547b1cbe6 113:27b9f749d9fe
1 #include <sstream>
1 #include "gen/llvm.h" 2 #include "gen/llvm.h"
2 3
3 #include "mtype.h" 4 #include "mtype.h"
4 #include "aggregate.h" 5 #include "aggregate.h"
5 #include "init.h" 6 #include "init.h"
9 #include "gen/tollvm.h" 10 #include "gen/tollvm.h"
10 #include "gen/arrays.h" 11 #include "gen/arrays.h"
11 #include "gen/logger.h" 12 #include "gen/logger.h"
12 #include "gen/classes.h" 13 #include "gen/classes.h"
13 #include "gen/functions.h" 14 #include "gen/functions.h"
15 #include "gen/runtime.h"
16 #include "gen/dvalue.h"
14 17
15 ////////////////////////////////////////////////////////////////////////////////////////// 18 //////////////////////////////////////////////////////////////////////////////////////////
16 19
17 static void LLVM_AddBaseClassData(BaseClasses* bcs) 20 static void LLVM_AddBaseClassData(BaseClasses* bcs)
18 { 21 {
19 // add base class data members first 22 // add base class data members first
20 for (int j=0; j<bcs->dim; j++) 23 for (int j=0; j<bcs->dim; j++)
21 { 24 {
22 BaseClass* bc = (BaseClass*)(bcs->data[j]); 25 BaseClass* bc = (BaseClass*)(bcs->data[j]);
23 assert(bc); 26 assert(bc);
27 if (bc->base->isInterfaceDeclaration())
28 continue; // interfaces only has methods
29
30 LLVM_AddBaseClassData(&bc->base->baseclasses);
31
24 Logger::println("Adding base class members of %s", bc->base->toChars()); 32 Logger::println("Adding base class members of %s", bc->base->toChars());
25 LOG_SCOPE; 33 LOG_SCOPE;
26 34
27 LLVM_AddBaseClassData(&bc->base->baseclasses);
28 for (int k=0; k < bc->base->members->dim; k++) { 35 for (int k=0; k < bc->base->members->dim; k++) {
29 Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]); 36 Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]);
30 if (dsym->isVarDeclaration()) 37 if (dsym->isVarDeclaration())
31 { 38 {
32 dsym->toObjFile(); 39 dsym->toObjFile();
44 51
45 // first resolve the base class 52 // first resolve the base class
46 if (cd->baseClass) { 53 if (cd->baseClass) {
47 DtoResolveClass(cd->baseClass); 54 DtoResolveClass(cd->baseClass);
48 } 55 }
49 // resolve typeinfo 56
50 //DtoResolveClass(ClassDeclaration::typeinfo); 57 // resolve interfaces
51 // resolve classinfo 58 if (cd->vtblInterfaces) {
52 //DtoResolveClass(ClassDeclaration::classinfo); 59 for (int i=0; i < cd->vtblInterfaces->dim; i++) {
60 BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i];
61 ClassDeclaration *id = b->base;
62 DtoResolveClass(id);
63 // Fill in vtbl[]
64 b->fillVtbl(cd, &b->vtbl, 1);
65 }
66 }
53 67
54 Logger::println("DtoResolveClass(%s)", cd->toPrettyChars()); 68 Logger::println("DtoResolveClass(%s)", cd->toPrettyChars());
55 LOG_SCOPE; 69 LOG_SCOPE;
56 70
57 assert(cd->type->ty == Tclass); 71 assert(cd->type->ty == Tclass);
68 ts->llvmVtblType = new llvm::PATypeHolder(llvm::OpaqueType::get()); 82 ts->llvmVtblType = new llvm::PATypeHolder(llvm::OpaqueType::get());
69 const llvm::Type* vtabty = llvm::PointerType::get(ts->llvmVtblType->get()); 83 const llvm::Type* vtabty = llvm::PointerType::get(ts->llvmVtblType->get());
70 84
71 std::vector<const llvm::Type*> fieldtypes; 85 std::vector<const llvm::Type*> fieldtypes;
72 fieldtypes.push_back(vtabty); 86 fieldtypes.push_back(vtabty);
87
88 // add interface vtables
89 if (cd->vtblInterfaces)
90 for (size_t i = 0; i < cd->vtblInterfaces->dim; i++)
91 {
92 BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i];
93 ClassDeclaration *id = b->base;
94 assert(id->type->ty == Tclass);
95 TypeClass* itc = (TypeClass*)id->type;
96 const llvm::Type* ivtblTy = llvm::PointerType::get(itc->llvmVtblType->get());
97 fieldtypes.push_back(ivtblTy);
98
99 // add this interface to the map
100 IRInterface* iri = new IRInterface(b, isaStruct(itc->llvmVtblType->get()));
101 irstruct->interfaces.insert(std::make_pair(id, iri));
102 }
73 103
74 // base classes first 104 // base classes first
75 LLVM_AddBaseClassData(&cd->baseclasses); 105 LLVM_AddBaseClassData(&cd->baseclasses);
76 106
77 // then add own members 107 // then add own members
96 if (!ts->llvmType) 126 if (!ts->llvmType)
97 ts->llvmType = new llvm::PATypeHolder(structtype); 127 ts->llvmType = new llvm::PATypeHolder(structtype);
98 else 128 else
99 *ts->llvmType = structtype; 129 *ts->llvmType = structtype;
100 130
101 bool needs_definition = false;
102 if (cd->parent->isModule()) { 131 if (cd->parent->isModule()) {
103 gIR->module->addTypeName(cd->mangle(), ts->llvmType->get()); 132 gIR->module->addTypeName(cd->mangle(), ts->llvmType->get());
104 needs_definition = (cd->getModule() == gIR->dmodule);
105 } 133 }
106 else { 134 else {
107 assert(0 && "class parent is not a module"); 135 assert(0 && "class parent is not a module");
108 } 136 }
109 137
110 // generate vtable 138 // build interface info type
139 std::vector<const llvm::Type*> infoTypes;
140 // ClassInfo classinfo
141 ClassDeclaration* cinfod = ClassDeclaration::classinfo;
142 DtoResolveClass(cinfod);
143 infoTypes.push_back(llvm::PointerType::get(cinfod->type->llvmType->get()));
144 // void*[] vtbl
145 std::vector<const llvm::Type*> infoVtbltypes;
146 infoVtbltypes.push_back(DtoSize_t());
147 const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
148 infoVtbltypes.push_back(byteptrptrty);
149 infoTypes.push_back(llvm::StructType::get(infoVtbltypes));
150 // int offset
151 infoTypes.push_back(llvm::Type::Int32Ty);
152 // create type
153 const llvm::StructType* infoTy = llvm::StructType::get(infoTypes);
154
155 // create vtable type
111 llvm::GlobalVariable* svtblVar = 0; 156 llvm::GlobalVariable* svtblVar = 0;
112 std::vector<const llvm::Type*> sinits_ty; 157 std::vector<const llvm::Type*> sinits_ty;
113 158
114 for (int k=0; k < cd->vtbl.dim; k++) 159 for (int k=0; k < cd->vtbl.dim; k++)
115 { 160 {
122 assert(fd->type->ty == Tfunction); 167 assert(fd->type->ty == Tfunction);
123 TypeFunction* tf = (TypeFunction*)fd->type; 168 TypeFunction* tf = (TypeFunction*)fd->type;
124 const llvm::Type* fpty = llvm::PointerType::get(tf->llvmType->get()); 169 const llvm::Type* fpty = llvm::PointerType::get(tf->llvmType->get());
125 sinits_ty.push_back(fpty); 170 sinits_ty.push_back(fpty);
126 } 171 }
127 else if (ClassDeclaration* cd = dsym->isClassDeclaration()) { 172 else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) {
128 //Logger::println("*** ClassDeclaration in vtable: %s", cd->toChars()); 173 Logger::println("*** ClassDeclaration in vtable: %s", cd2->toChars());
129 const llvm::Type* cinfoty; 174 const llvm::Type* cinfoty;
130 if (cd != ClassDeclaration::classinfo) { 175 if (cd->isInterfaceDeclaration()) {
131 cd = ClassDeclaration::classinfo; 176 cinfoty = infoTy;
132 DtoResolveClass(cd); 177 }
133 cinfoty = cd->type->llvmType->get(); 178 else if (cd != cinfod) {
179 DtoResolveClass(cinfod);
180 cinfoty = cinfod->type->llvmType->get();
134 } 181 }
135 else { 182 else {
183 // this is the ClassInfo class, the type is this type
136 cinfoty = ts->llvmType->get(); 184 cinfoty = ts->llvmType->get();
137 } 185 }
138 const llvm::Type* cty = llvm::PointerType::get(cd->type->llvmType->get()); 186 const llvm::Type* cty = llvm::PointerType::get(cinfoty);
139 sinits_ty.push_back(cty); 187 sinits_ty.push_back(cty);
140 } 188 }
141 else 189 else
142 assert(0); 190 assert(0);
143 } 191 }
180 bool needs_definition = false; 228 bool needs_definition = false;
181 if (cd->parent->isModule()) { 229 if (cd->parent->isModule()) {
182 needs_definition = (cd->getModule() == gIR->dmodule); 230 needs_definition = (cd->getModule() == gIR->dmodule);
183 } 231 }
184 232
185 // vtable 233 // interface vtables are emitted by the class implementing them
186 std::string varname("_D"); 234 // also interfaces have no static initializer
187 varname.append(cd->mangle()); 235 if (!cd->isInterfaceDeclaration()) {
188 varname.append("6__vtblZ"); 236 // vtable
189 237 std::string varname("_D");
190 std::string styname(cd->mangle()); 238 varname.append(cd->mangle());
191 styname.append("__vtblTy"); 239 varname.append("6__vtblZ");
192 240
193 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; 241 llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
194 242
195 const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get()); 243 const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get());
196 cd->llvmVtbl = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module); 244 cd->llvmVtbl = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module);
197 245
198 // init 246 // build interface info type
199 std::string initname("_D"); 247 std::vector<const llvm::Type*> types;
200 initname.append(cd->mangle()); 248 // ClassInfo classinfo
201 initname.append("6__initZ"); 249 ClassDeclaration* cd2 = ClassDeclaration::classinfo;
202 250 DtoResolveClass(cd2);
203 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module); 251 types.push_back(llvm::PointerType::get(cd2->type->llvmType->get()));
204 ts->llvmInit = initvar; 252 // void*[] vtbl
253 std::vector<const llvm::Type*> vtbltypes;
254 vtbltypes.push_back(DtoSize_t());
255 const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
256 vtbltypes.push_back(byteptrptrty);
257 types.push_back(llvm::StructType::get(vtbltypes));
258 // int offset
259 types.push_back(llvm::Type::Int32Ty);
260 // create type
261 const llvm::StructType* infoTy = llvm::StructType::get(types);
262
263 // interface info array
264 if (needs_definition && cd->vtblInterfaces->dim > 0) {
265 // symbol name
266 std::string nam = "_D";
267 nam.append(cd->mangle());
268 nam.append("16__interfaceInfosZ");
269 // resolve array type
270 const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, cd->vtblInterfaces->dim);
271 // declare global
272 irstruct->interfaceInfosTy = arrTy;
273 irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, llvm::GlobalValue::InternalLinkage, 0, nam, gIR->module);
274 }
275
276 // interface vtables
277 unsigned idx = 0;
278 for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
279 {
280 ClassDeclaration* id = i->first;
281 IRInterface* iri = i->second;
282
283 std::string nam("_D");
284 nam.append(cd->mangle());
285 nam.append("11__interface");
286 nam.append(id->mangle());
287 nam.append("6__vtblZ");
288
289 assert(iri->vtblTy);
290 iri->vtbl = new llvm::GlobalVariable(iri->vtblTy, true, _linkage, 0, nam, gIR->module);
291 iri->infoTy = infoTy;
292 llvm::Constant* idxs[2] = {DtoConstUint(0), DtoConstUint(idx)};
293 iri->info = llvm::ConstantExpr::getGetElementPtr(irstruct->interfaceInfos, idxs, 2);
294 idx++;
295 }
296
297 // init
298 std::string initname("_D");
299 initname.append(cd->mangle());
300 initname.append("6__initZ");
301
302 llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module);
303 ts->llvmInit = initvar;
304 }
205 305
206 gIR->classes.pop_back(); 306 gIR->classes.pop_back();
207 gIR->structs.pop_back(); 307 gIR->structs.pop_back();
208 308
209 gIR->constInitList.push_back(cd); 309 gIR->constInitList.push_back(cd);
222 322
223 void DtoConstInitClass(ClassDeclaration* cd) 323 void DtoConstInitClass(ClassDeclaration* cd)
224 { 324 {
225 if (cd->llvmInitialized) return; 325 if (cd->llvmInitialized) return;
226 cd->llvmInitialized = true; 326 cd->llvmInitialized = true;
327
328 if (cd->isInterfaceDeclaration())
329 return; // nothing to do
227 330
228 Logger::println("DtoConstInitClass(%s)", cd->toPrettyChars()); 331 Logger::println("DtoConstInitClass(%s)", cd->toPrettyChars());
229 LOG_SCOPE; 332 LOG_SCOPE;
230 333
231 IRStruct* irstruct = cd->llvmIRStruct; 334 IRStruct* irstruct = cd->llvmIRStruct;
246 349
247 // first field is always the vtable 350 // first field is always the vtable
248 assert(cd->llvmVtbl != 0); 351 assert(cd->llvmVtbl != 0);
249 fieldinits.push_back(cd->llvmVtbl); 352 fieldinits.push_back(cd->llvmVtbl);
250 353
354 // next comes interface vtables
355 for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
356 {
357 IRInterface* iri = i->second;
358 assert(iri->vtbl);
359 fieldinits.push_back(iri->vtbl);
360 }
361
251 // rest 362 // rest
252 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { 363 for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
253 Logger::println("adding fieldinit for: %s", i->second.var->toChars()); 364 Logger::println("adding fieldinit for: %s", i->second.var->toChars());
254 fieldinits.push_back(i->second.init); 365 fieldinits.push_back(i->second.init);
255 } 366 }
258 assert(cd->type->ty == Tclass); 369 assert(cd->type->ty == Tclass);
259 TypeClass* ts = (TypeClass*)cd->type; 370 TypeClass* ts = (TypeClass*)cd->type;
260 const llvm::StructType* structtype = isaStruct(ts->llvmType->get()); 371 const llvm::StructType* structtype = isaStruct(ts->llvmType->get());
261 372
262 // generate initializer 373 // generate initializer
263 /*Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n'; 374 #if 0
375 Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n';
264 376
265 for(size_t i=0; i<structtype->getNumElements(); ++i) { 377 for(size_t i=0; i<structtype->getNumElements(); ++i) {
266 Logger::cout() << "s#" << i << " = " << *structtype->getElementType(i) << '\n'; 378 Logger::cout() << "s#" << i << " = " << *structtype->getElementType(i) << '\n';
267 } 379 }
268 380
269 for(size_t i=0; i<fieldinits.size(); ++i) { 381 for(size_t i=0; i<fieldinits.size(); ++i) {
270 Logger::cout() << "i#" << i << " = " << *fieldinits[i]->getType() << '\n'; 382 Logger::cout() << "i#" << i << " = " << *fieldinits[i]->getType() << '\n';
271 }*/ 383 }
384 #endif
272 385
273 llvm::Constant* _init = llvm::ConstantStruct::get(structtype, fieldinits); 386 llvm::Constant* _init = llvm::ConstantStruct::get(structtype, fieldinits);
274 assert(_init); 387 assert(_init);
275 cd->llvmInitZ = _init; 388 cd->llvmInitZ = _init;
276 389
298 assert(0); 411 assert(0);
299 } 412 }
300 413
301 const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get()); 414 const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get());
302 415
303 /*for (size_t i=0; i< sinits.size(); ++i) 416 #if 0
417 for (size_t i=0; i< sinits.size(); ++i)
304 { 418 {
305 Logger::cout() << "field[" << i << "] = " << *svtbl_ty->getElementType(i) << '\n'; 419 Logger::cout() << "field[" << i << "] = " << *svtbl_ty->getElementType(i) << '\n';
306 Logger::cout() << "init [" << i << "] = " << *sinits[i]->getType() << '\n'; 420 Logger::cout() << "init [" << i << "] = " << *sinits[i]->getType() << '\n';
307 assert(svtbl_ty->getElementType(i) == sinits[i]->getType()); 421 assert(svtbl_ty->getElementType(i) == sinits[i]->getType());
308 }*/ 422 }
423 #endif
309 424
310 llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits); 425 llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits);
311 cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit); 426 cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit);
427
428 // create interface vtable const initalizers
429 int idx = 1;
430 int idxScale = (global.params.is64bit) ? 8 : 4;
431 for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
432 {
433 ClassDeclaration* id = i->first;
434 assert(id->type->ty == Tclass);
435 TypeClass* its = (TypeClass*)id->type;
436
437 IRInterface* iri = i->second;
438 BaseClass* b = iri->base;
439
440 const llvm::StructType* ivtbl_ty = isaStruct(its->llvmVtblType->get());
441
442 // generate interface info initializer
443 std::vector<llvm::Constant*> infoInits;
444 // classinfo
445 assert(id->llvmClass);
446 llvm::Constant* c = id->llvmClass;
447 infoInits.push_back(c);
448 // vtbl
449 const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
450 c = llvm::ConstantExpr::getBitCast(iri->vtbl, byteptrptrty);
451 c = DtoConstSlice(DtoConstSize_t(b->vtbl.dim), c);
452 infoInits.push_back(c);
453 // offset
454 infoInits.push_back(DtoConstInt(idx*idxScale));
455 // create interface info initializer constant
456 iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits));
457
458 // generate vtable initializer
459 std::vector<llvm::Constant*> iinits;
460
461 // add interface info
462 iinits.push_back(iri->info);
463
464 for (int k=1; k < b->vtbl.dim; k++)
465 {
466 Logger::println("interface vtbl const init nr. %d", k);
467 Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k];
468 FuncDeclaration* fd = dsym->isFuncDeclaration();
469 assert(fd);
470 DtoForceDeclareDsymbol(fd);
471 assert(fd->llvmValue);
472 llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
473 // we have to bitcast, as the type created in ResolveClass expects a different this type
474 c = llvm::ConstantExpr::getBitCast(c, iri->vtblTy->getContainedType(k));
475 iinits.push_back(c);
476 }
477
478 #if 1
479 for (size_t x=0; x< iinits.size(); ++x)
480 {
481 Logger::cout() << "field[" << x << "] = " << *ivtbl_ty->getElementType(x) << "\n\n";
482 Logger::cout() << "init [" << x << "] = " << *iinits[x] << "\n\n";
483 assert(ivtbl_ty->getElementType(x) == iinits[x]->getType());
484 }
485 #endif
486
487 llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits);
488 iri->vtblInit = llvm::cast<llvm::ConstantStruct>(civtblInit);
489
490 idx++;
491 }
312 492
313 gIR->classes.pop_back(); 493 gIR->classes.pop_back();
314 gIR->structs.pop_back(); 494 gIR->structs.pop_back();
315 } 495 }
316 496
328 assert(cd->type->ty == Tclass); 508 assert(cd->type->ty == Tclass);
329 TypeClass* ts = (TypeClass*)cd->type; 509 TypeClass* ts = (TypeClass*)cd->type;
330 510
331 bool def = false; 511 bool def = false;
332 if (cd->parent->isModule() && cd->getModule() == gIR->dmodule) { 512 if (cd->parent->isModule() && cd->getModule() == gIR->dmodule) {
333 ts->llvmInit->setInitializer(cd->llvmInitZ); 513 // interfaces don't have initializers
334 cd->llvmVtbl->setInitializer(cd->llvmConstVtbl); 514 if (!cd->isInterfaceDeclaration()) {
515 ts->llvmInit->setInitializer(cd->llvmInitZ);
516 cd->llvmVtbl->setInitializer(cd->llvmConstVtbl);
517
518 // initialize interface vtables
519 IRStruct* irstruct = cd->llvmIRStruct;
520 std::vector<llvm::Constant*> infoInits;
521 for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
522 {
523 IRInterface* iri = i->second;
524 iri->vtbl->setInitializer(iri->vtblInit);
525 infoInits.push_back(iri->infoInit);
526 }
527 // initialize interface info array
528 if (!infoInits.empty()) {
529 llvm::Constant* arrInit = llvm::ConstantArray::get(irstruct->interfaceInfosTy, infoInits);
530 irstruct->interfaceInfos->setInitializer(arrInit);
531 }
532 }
335 def = true; 533 def = true;
336 } 534 }
337 535
338 // generate classinfo 536 // generate classinfo
339 if (def) DtoDefineClassInfo(cd); 537 if (def) DtoDefineClassInfo(cd);
392 } 590 }
393 } 591 }
394 592
395 ////////////////////////////////////////////////////////////////////////////////////////// 593 //////////////////////////////////////////////////////////////////////////////////////////
396 594
595 DValue* DtoCastObjectToInterface(DValue* val, Type* _to)
596 {
597 // call:
598 // Object _d_dynamic_cast(Object o, ClassInfo c)
599
600 llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_dynamic_cast");
601 const llvm::FunctionType* funcTy = func->getFunctionType();
602
603 std::vector<llvm::Value*> args;
604
605 // Object o
606 llvm::Value* tmp = val->getRVal();
607 tmp = DtoBitCast(tmp, funcTy->getParamType(0));
608 args.push_back(tmp);
609
610 // ClassInfo c
611 TypeClass* to = (TypeClass*)DtoDType(_to);
612 DtoForceDeclareDsymbol(to->sym);
613 assert(to->sym->llvmClass);
614 args.push_back(to->sym->llvmClass);
615
616 // call it
617 llvm::Value* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "tmp");
618 ret = DtoBitCast(ret, DtoType(_to));
619 return new DImValue(_to, ret);
620 }
621
622 //////////////////////////////////////////////////////////////////////////////////////////
623
624 DValue* DtoCastInterfaceToObject(DValue* val)
625 {
626 // call:
627 // Object _d_toObject(void* p)
628
629 llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_toObject");
630 const llvm::FunctionType* funcTy = func->getFunctionType();
631
632 // void* p
633 llvm::Value* tmp = val->getRVal();
634 tmp = DtoBitCast(tmp, funcTy->getParamType(0));
635
636 // call it
637 llvm::Value* ret = gIR->ir->CreateCall(func, tmp, "tmp");
638 return new DImValue(ClassDeclaration::object->type, ret);
639 }
640
641 //////////////////////////////////////////////////////////////////////////////////////////
642
397 void DtoDeclareClassInfo(ClassDeclaration* cd) 643 void DtoDeclareClassInfo(ClassDeclaration* cd)
398 { 644 {
399 if (cd->llvmClassDeclared) return; 645 if (cd->llvmClassDeclared) return;
400 cd->llvmClassDeclared = true; 646 cd->llvmClassDeclared = true;
401 647
405 ClassDeclaration* cinfo = ClassDeclaration::classinfo; 651 ClassDeclaration* cinfo = ClassDeclaration::classinfo;
406 DtoResolveClass(cinfo); 652 DtoResolveClass(cinfo);
407 653
408 std::string gname("_D"); 654 std::string gname("_D");
409 gname.append(cd->mangle()); 655 gname.append(cd->mangle());
410 gname.append("7__ClassZ"); 656 if (!cd->isInterfaceDeclaration())
657 gname.append("7__ClassZ");
658 else
659 gname.append("11__InterfaceZ");
411 660
412 const llvm::Type* st = cinfo->type->llvmType->get(); 661 const llvm::Type* st = cinfo->type->llvmType->get();
413 662
414 cd->llvmClass = new llvm::GlobalVariable(st, true, llvm::GlobalValue::ExternalLinkage, NULL, gname, gIR->module); 663 cd->llvmClass = new llvm::GlobalVariable(st, true, llvm::GlobalValue::ExternalLinkage, NULL, gname, gIR->module);
415 } 664 }
536 return llvm::ConstantExpr::getBitCast(func, llvm::PointerType::get(llvm::Type::Int8Ty)); 785 return llvm::ConstantExpr::getBitCast(func, llvm::PointerType::get(llvm::Type::Int8Ty));
537 } 786 }
538 787
539 static uint build_classinfo_flags(ClassDeclaration* cd) 788 static uint build_classinfo_flags(ClassDeclaration* cd)
540 { 789 {
790 // adapted from original dmd code
541 uint flags = 0; 791 uint flags = 0;
542 //flags |= isCOMclass(); // IUnknown 792 //flags |= isCOMclass(); // IUnknown
543 bool hasOffTi = false; 793 bool hasOffTi = false;
544 if (cd->ctor) flags |= 8; 794 if (cd->ctor) flags |= 8;
545 for (ClassDeclaration *cd2 = cd; cd2; cd2 = cd2->baseClass) 795 for (ClassDeclaration *cd2 = cd; cd2; cd2 = cd2->baseClass)
589 Logger::println("DtoDefineClassInfo(%s)", cd->toChars()); 839 Logger::println("DtoDefineClassInfo(%s)", cd->toChars());
590 LOG_SCOPE; 840 LOG_SCOPE;
591 841
592 assert(cd->type->ty == Tclass); 842 assert(cd->type->ty == Tclass);
593 assert(cd->llvmClass); 843 assert(cd->llvmClass);
594 assert(cd->llvmInitZ);
595 assert(cd->llvmVtbl);
596 assert(cd->llvmConstVtbl);
597 844
598 TypeClass* cdty = (TypeClass*)cd->type; 845 TypeClass* cdty = (TypeClass*)cd->type;
599 assert(cdty->llvmInit); 846 if (!cd->isInterfaceDeclaration()) {
847 assert(cd->llvmInitZ);
848 assert(cd->llvmVtbl);
849 assert(cd->llvmConstVtbl);
850 assert(cdty->llvmInit);
851 }
600 852
601 // holds the list of initializers for llvm 853 // holds the list of initializers for llvm
602 std::vector<llvm::Constant*> inits; 854 std::vector<llvm::Constant*> inits;
603 855
604 ClassDeclaration* cinfo = ClassDeclaration::classinfo; 856 ClassDeclaration* cinfo = ClassDeclaration::classinfo;
615 // monitor 867 // monitor
616 // TODO no monitors yet 868 // TODO no monitors yet
617 869
618 // byte[] init 870 // byte[] init
619 const llvm::Type* byteptrty = llvm::PointerType::get(llvm::Type::Int8Ty); 871 const llvm::Type* byteptrty = llvm::PointerType::get(llvm::Type::Int8Ty);
620 c = llvm::ConstantExpr::getBitCast(cdty->llvmInit, byteptrty); 872 if (cd->isInterfaceDeclaration()) {
621 assert(!cd->llvmInitZ->getType()->isAbstract()); 873 c = cinfo->llvmInitZ->getOperand(1);
622 size_t initsz = gTargetData->getTypeSize(cd->llvmInitZ->getType()); 874 }
623 c = DtoConstSlice(DtoConstSize_t(initsz), c); 875 else {
876 c = llvm::ConstantExpr::getBitCast(cdty->llvmInit, byteptrty);
877 assert(!cd->llvmInitZ->getType()->isAbstract());
878 size_t initsz = gTargetData->getTypeSize(cd->llvmInitZ->getType());
879 c = DtoConstSlice(DtoConstSize_t(initsz), c);
880 }
624 inits.push_back(c); 881 inits.push_back(c);
625 882
626 // class name 883 // class name
627 // from dmd 884 // from dmd
628 char *name = cd->ident->toChars(); 885 char *name = cd->ident->toChars();
634 } 891 }
635 c = DtoConstString(name); 892 c = DtoConstString(name);
636 inits.push_back(c); 893 inits.push_back(c);
637 894
638 // vtbl array 895 // vtbl array
639 const llvm::Type* byteptrptrty = llvm::PointerType::get(byteptrty); 896 if (cd->isInterfaceDeclaration()) {
640 assert(!cd->llvmVtbl->getType()->isAbstract()); 897 c = cinfo->llvmInitZ->getOperand(3);
641 c = llvm::ConstantExpr::getBitCast(cd->llvmVtbl, byteptrptrty); 898 }
642 assert(!cd->llvmConstVtbl->getType()->isAbstract()); 899 else {
643 size_t vtblsz = gTargetData->getTypeSize(cd->llvmConstVtbl->getType()); 900 const llvm::Type* byteptrptrty = llvm::PointerType::get(byteptrty);
644 c = DtoConstSlice(DtoConstSize_t(vtblsz), c); 901 assert(!cd->llvmVtbl->getType()->isAbstract());
902 c = llvm::ConstantExpr::getBitCast(cd->llvmVtbl, byteptrptrty);
903 assert(!cd->llvmConstVtbl->getType()->isAbstract());
904 size_t vtblsz = cd->llvmConstVtbl->getType()->getNumElements();
905 c = DtoConstSlice(DtoConstSize_t(vtblsz), c);
906 }
645 inits.push_back(c); 907 inits.push_back(c);
646 908
647 // interfaces array 909 // interfaces array
648 // TODO 910 IRStruct* irstruct = cd->llvmIRStruct;
649 c = cinfo->llvmInitZ->getOperand(4); 911 if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos) {
912 c = cinfo->llvmInitZ->getOperand(4);
913 }
914 else {
915 const llvm::Type* t = cinfo->llvmInitZ->getOperand(4)->getType()->getContainedType(1);
916 c = llvm::ConstantExpr::getBitCast(irstruct->interfaceInfos, t);
917 size_t iisz = irstruct->interfaceInfosTy->getNumElements();
918 c = DtoConstSlice(DtoConstSize_t(iisz), c);
919 }
650 inits.push_back(c); 920 inits.push_back(c);
651 921
652 // base classinfo 922 // base classinfo
653 if (cd->baseClass) { 923 if (cd->baseClass && !cd->isInterfaceDeclaration()) {
654 DtoDeclareClassInfo(cd->baseClass); 924 DtoDeclareClassInfo(cd->baseClass);
655 c = cd->baseClass->llvmClass; 925 c = cd->baseClass->llvmClass;
656 assert(c); 926 assert(c);
657 inits.push_back(c); 927 inits.push_back(c);
658 } 928 }
661 c = cinfo->llvmInitZ->getOperand(5); 931 c = cinfo->llvmInitZ->getOperand(5);
662 inits.push_back(c); 932 inits.push_back(c);
663 } 933 }
664 934
665 // destructor 935 // destructor
666 c = build_class_dtor(cd); 936 if (cd->isInterfaceDeclaration()) {
937 c = cinfo->llvmInitZ->getOperand(6);
938 }
939 else {
940 c = build_class_dtor(cd);
941 }
667 inits.push_back(c); 942 inits.push_back(c);
668 943
669 // invariant 944 // invariant
670 // TODO 945 // TODO
671 c = cinfo->llvmInitZ->getOperand(7); 946 c = cinfo->llvmInitZ->getOperand(7);
672 inits.push_back(c); 947 inits.push_back(c);
673 948
674 // uint flags, adapted from original dmd code 949 // uint flags
675 uint flags = build_classinfo_flags(cd); 950 if (cd->isInterfaceDeclaration()) {
676 c = DtoConstUint(flags); 951 c = cinfo->llvmInitZ->getOperand(8);
952 }
953 else {
954 uint flags = build_classinfo_flags(cd);
955 c = DtoConstUint(flags);
956 }
677 inits.push_back(c); 957 inits.push_back(c);
678 958
679 // allocator 959 // allocator
680 // TODO 960 // TODO
681 c = cinfo->llvmInitZ->getOperand(9); 961 c = cinfo->llvmInitZ->getOperand(9);
682 inits.push_back(c); 962 inits.push_back(c);
683 963
684 // offset typeinfo 964 // offset typeinfo
685 c = build_offti_array(cd, cinfo->llvmInitZ->getOperand(10)); 965 if (cd->isInterfaceDeclaration()) {
966 c = cinfo->llvmInitZ->getOperand(10);
967 }
968 else {
969 c = build_offti_array(cd, cinfo->llvmInitZ->getOperand(10));
970 }
686 inits.push_back(c); 971 inits.push_back(c);
687 972
688 // default constructor 973 // default constructor
689 if (cd->defaultCtor) { 974 if (cd->defaultCtor && !cd->isInterfaceDeclaration()) {
690 DtoForceDeclareDsymbol(cd->defaultCtor); 975 DtoForceDeclareDsymbol(cd->defaultCtor);
691 c = isaConstant(cd->defaultCtor->llvmValue); 976 c = isaConstant(cd->defaultCtor->llvmValue);
692 //const llvm::Type* toTy = cinfo->llvmInitZ->getOperand(11)->getType(); 977 //const llvm::Type* toTy = cinfo->llvmInitZ->getOperand(11)->getType();
693 c = llvm::ConstantExpr::getBitCast(c, llvm::PointerType::get(llvm::Type::Int8Ty)); // toTy); 978 c = llvm::ConstantExpr::getBitCast(c, llvm::PointerType::get(llvm::Type::Int8Ty)); // toTy);
694 } 979 }