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