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 //////////////////////////////////////////////////////////////////////////////