Mercurial > projects > ldc
comparison ir/irclass.cpp @ 1230:e67c85d6e680
Completed interface implementation. Hopefully that's it for now..
author | Tomas Lindquist Olsen <tomas.l.olsen gmail.com> |
---|---|
date | Thu, 16 Apr 2009 13:18:56 +0200 |
parents | fafe7c8d6734 |
children | 212ec2d9d176 |
comparison
equal
deleted
inserted
replaced
1229:fafe7c8d6734 | 1230:e67c85d6e680 |
---|---|
89 const llvm::Type* InterfaceTy = DtoType(idx->type->next); | 89 const llvm::Type* InterfaceTy = DtoType(idx->type->next); |
90 | 90 |
91 // create Interface[N] | 91 // create Interface[N] |
92 const llvm::ArrayType* array_type = llvm::ArrayType::get( | 92 const llvm::ArrayType* array_type = llvm::ArrayType::get( |
93 InterfaceTy, | 93 InterfaceTy, |
94 cd->vtblInterfaces->dim); | 94 type->irtype->isClass()->getNumInterfaceVtbls()); |
95 | 95 |
96 // put it in a global | 96 // put it in a global |
97 std::string name("_D"); | 97 std::string name("_D"); |
98 name.append(cd->mangle()); | 98 name.append(cd->mangle()); |
99 name.append("16__interfaceInfosZ"); | 99 name.append("16__interfaceInfosZ"); |
220 if (base->vtblInterfaces) | 220 if (base->vtblInterfaces) |
221 { | 221 { |
222 // false when it's not okay to use functions from super classes | 222 // false when it's not okay to use functions from super classes |
223 bool newinsts = (base == aggrdecl->isClassDeclaration()); | 223 bool newinsts = (base == aggrdecl->isClassDeclaration()); |
224 | 224 |
225 size_t inter_idx = interfacesWithVtbls.size(); | |
226 | |
225 ArrayIter<BaseClass> it2(*base->vtblInterfaces); | 227 ArrayIter<BaseClass> it2(*base->vtblInterfaces); |
226 for (; !it2.done(); it2.next()) | 228 for (; !it2.done(); it2.next()) |
227 { | 229 { |
228 BaseClass* b = it2.get(); | 230 BaseClass* b = it2.get(); |
229 constants.push_back(getInterfaceVtbl(b, newinsts)); | 231 constants.push_back(getInterfaceVtbl(b, newinsts, inter_idx)); |
230 offset += PTRSIZE; | 232 offset += PTRSIZE; |
233 | |
234 // add to the interface list | |
235 interfacesWithVtbls.push_back(b); | |
236 inter_idx++; | |
231 } | 237 } |
232 } | 238 } |
233 | 239 |
234 // tail padding? | 240 // tail padding? |
235 if (offset < base->structsize) | 241 if (offset < base->structsize) |
277 return definit; | 283 return definit; |
278 } | 284 } |
279 | 285 |
280 ////////////////////////////////////////////////////////////////////////////// | 286 ////////////////////////////////////////////////////////////////////////////// |
281 | 287 |
282 llvm::GlobalVariable * IrStruct::getInterfaceVtbl(BaseClass * b, bool new_instance) | 288 llvm::GlobalVariable * IrStruct::getInterfaceVtbl(BaseClass * b, bool new_instance, size_t interfaces_index) |
283 { | 289 { |
284 ClassDeclaration* cd = aggrdecl->isClassDeclaration(); | 290 ClassGlobalMap::iterator it = interfaceVtblMap.find(b->base); |
285 assert(cd && "not a class aggregate"); | |
286 | |
287 ClassGlobalMap::iterator it = interfaceVtblMap.find(cd); | |
288 if (it != interfaceVtblMap.end()) | 291 if (it != interfaceVtblMap.end()) |
289 return it->second; | 292 return it->second; |
290 | 293 |
291 IF_LOG Logger::println("Building vtbl for implementation of interface %s in class %s", | 294 IF_LOG Logger::println("Building vtbl for implementation of interface %s in class %s", |
292 b->base->toPrettyChars(), aggrdecl->toPrettyChars()); | 295 b->base->toPrettyChars(), aggrdecl->toPrettyChars()); |
293 LOG_SCOPE; | 296 LOG_SCOPE; |
294 | 297 |
298 ClassDeclaration* cd = aggrdecl->isClassDeclaration(); | |
299 assert(cd && "not a class aggregate"); | |
300 | |
295 Array vtbl_array; | 301 Array vtbl_array; |
296 b->fillVtbl(cd, &vtbl_array, new_instance); | 302 b->fillVtbl(cd, &vtbl_array, new_instance); |
297 | 303 |
298 std::vector<llvm::Constant*> constants; | 304 std::vector<llvm::Constant*> constants; |
299 constants.reserve(vtbl_array.dim); | 305 constants.reserve(vtbl_array.dim); |
300 | 306 |
301 // start with the interface info | 307 // start with the interface info |
302 llvm::Constant* c = getNullValue(DtoType(Type::tvoid->pointerTo())); | 308 VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3); |
309 Type* first = interfaces_idx->type->next->pointerTo(); | |
310 | |
311 // index into the interfaces array | |
312 llvm::Constant* idxs[2] = { | |
313 DtoConstSize_t(0), | |
314 DtoConstSize_t(interfaces_index) | |
315 }; | |
316 | |
317 llvm::Constant* c = llvm::ConstantExpr::getGetElementPtr( | |
318 getInterfaceArraySymbol(), idxs, 2); | |
319 | |
303 constants.push_back(c); | 320 constants.push_back(c); |
304 | 321 |
305 // add virtual function pointers | 322 // add virtual function pointers |
306 size_t n = vtbl_array.dim; | 323 size_t n = vtbl_array.dim; |
307 for (size_t i = 1; i < n; i++) | 324 for (size_t i = 1; i < n; i++) |
340 vtbl_constant, | 357 vtbl_constant, |
341 mangle, | 358 mangle, |
342 gIR->module | 359 gIR->module |
343 ); | 360 ); |
344 | 361 |
362 // insert into the vtbl map | |
345 interfaceVtblMap.insert(std::make_pair(b->base, GV)); | 363 interfaceVtblMap.insert(std::make_pair(b->base, GV)); |
346 | 364 |
347 return GV; | 365 return GV; |
348 } | 366 } |
349 | 367 |
355 LOG_SCOPE; | 373 LOG_SCOPE; |
356 | 374 |
357 ClassDeclaration* cd = aggrdecl->isClassDeclaration(); | 375 ClassDeclaration* cd = aggrdecl->isClassDeclaration(); |
358 assert(cd); | 376 assert(cd); |
359 | 377 |
360 if (!cd->vtblInterfaces || cd->vtblInterfaces->dim == 0) | 378 size_t n = interfacesWithVtbls.size(); |
379 assert(type->irtype->isClass()->getNumInterfaceVtbls() == n && | |
380 "inconsistent number of interface vtables in this class"); | |
381 | |
382 if (n == 0) | |
361 { | 383 { |
362 VarDeclarationIter idx(ClassDeclaration::classinfo->fields, 3); | 384 VarDeclarationIter idx(ClassDeclaration::classinfo->fields, 3); |
363 return getNullValue(DtoType(idx->type)); | 385 return getNullValue(DtoType(idx->type)); |
364 } | 386 } |
365 | 387 |
379 const LLType* voidptrptr_type = DtoType( | 401 const LLType* voidptrptr_type = DtoType( |
380 Type::tvoid->pointerTo()->pointerTo()); | 402 Type::tvoid->pointerTo()->pointerTo()); |
381 | 403 |
382 const LLType* our_type = type->irtype->isClass()->getPA().get(); | 404 const LLType* our_type = type->irtype->isClass()->getPA().get(); |
383 | 405 |
384 ArrayIter<BaseClass> it(*cd->vtblInterfaces); | 406 for (size_t i = 0; i < n; ++i) |
385 while (it.more()) | 407 { |
386 { | 408 BaseClass* it = interfacesWithVtbls[i]; |
409 | |
387 IF_LOG Logger::println("Adding interface %s", it->base->toPrettyChars()); | 410 IF_LOG Logger::println("Adding interface %s", it->base->toPrettyChars()); |
388 | 411 |
389 IrStruct* irinter = it->base->ir.irStruct; | 412 IrStruct* irinter = it->base->ir.irStruct; |
390 assert(irinter && "interface has null IrStruct"); | 413 assert(irinter && "interface has null IrStruct"); |
391 IrTypeClass* itc = irinter->type->irtype->isClass(); | 414 IrTypeClass* itc = irinter->type->irtype->isClass(); |
407 | 430 |
408 // create Interface struct | 431 // create Interface struct |
409 LLConstant* inits[3] = { ci, vtb, off }; | 432 LLConstant* inits[3] = { ci, vtb, off }; |
410 LLConstant* entry = llvm::ConstantStruct::get(inits, 3); | 433 LLConstant* entry = llvm::ConstantStruct::get(inits, 3); |
411 constants.push_back(entry); | 434 constants.push_back(entry); |
412 | |
413 // next | |
414 it.next(); | |
415 } | 435 } |
416 | 436 |
417 // create Interface[N] | 437 // create Interface[N] |
418 const llvm::ArrayType* array_type = llvm::ArrayType::get( | 438 const llvm::ArrayType* array_type = llvm::ArrayType::get( |
419 constants[0]->getType(), | 439 constants[0]->getType(), |
420 cd->vtblInterfaces->dim); | 440 n); |
421 | 441 |
422 LLConstant* arr = llvm::ConstantArray::get( | 442 LLConstant* arr = llvm::ConstantArray::get( |
423 array_type, | 443 array_type, |
424 &constants[0], | 444 &constants[0], |
425 constants.size()); | 445 constants.size()); |
427 // apply the initializer | 447 // apply the initializer |
428 classInterfacesArray->setInitializer(arr); | 448 classInterfacesArray->setInitializer(arr); |
429 | 449 |
430 LLConstant* idxs[2] = { | 450 LLConstant* idxs[2] = { |
431 DtoConstSize_t(0), | 451 DtoConstSize_t(0), |
432 DtoConstSize_t(0) | 452 // only the interface explicitly implemented by this class |
453 // (not super classes) should show in ClassInfo | |
454 DtoConstSize_t(n - cd->vtblInterfaces->dim) | |
433 }; | 455 }; |
434 | 456 |
435 // return as a slice | 457 // return as a slice |
436 return DtoConstSlice( | 458 return DtoConstSlice( |
437 DtoConstSize_t(cd->vtblInterfaces->dim), | 459 DtoConstSize_t(n), |
438 llvm::ConstantExpr::getGetElementPtr(classInterfacesArray, idxs, 2)); | 460 llvm::ConstantExpr::getGetElementPtr(classInterfacesArray, idxs, 2)); |
439 } | 461 } |
440 | 462 |
441 ////////////////////////////////////////////////////////////////////////////// | 463 ////////////////////////////////////////////////////////////////////////////// |