comparison gen/classes.cpp @ 114:5880c12dba83 trunk

[svn r118] Fixed dynamic casts. Fixed a few interface bugs.
author lindquist
date Sun, 25 Nov 2007 00:19:13 +0100
parents 27b9f749d9fe
children 5ba6d286c941
comparison
equal deleted inserted replaced
113:27b9f749d9fe 114:5880c12dba83
126 if (!ts->llvmType) 126 if (!ts->llvmType)
127 ts->llvmType = new llvm::PATypeHolder(structtype); 127 ts->llvmType = new llvm::PATypeHolder(structtype);
128 else 128 else
129 *ts->llvmType = structtype; 129 *ts->llvmType = structtype;
130 130
131 if (cd->parent->isModule()) { 131 if (cd->isNested()) {
132 assert(0 && "nested classes not implemented");
133 }
134 else {
132 gIR->module->addTypeName(cd->mangle(), ts->llvmType->get()); 135 gIR->module->addTypeName(cd->mangle(), ts->llvmType->get());
133 }
134 else {
135 assert(0 && "class parent is not a module");
136 } 136 }
137 137
138 // build interface info type 138 // build interface info type
139 std::vector<const llvm::Type*> infoTypes; 139 std::vector<const llvm::Type*> infoTypes;
140 // ClassInfo classinfo 140 // ClassInfo classinfo
590 } 590 }
591 } 591 }
592 592
593 ////////////////////////////////////////////////////////////////////////////////////////// 593 //////////////////////////////////////////////////////////////////////////////////////////
594 594
595 DValue* DtoCastObjectToInterface(DValue* val, Type* _to) 595 DValue* DtoCastClass(DValue* val, Type* _to)
596 {
597 Type* to = DtoDType(_to);
598 if (to->ty == Tpointer) {
599 const llvm::Type* tolltype = DtoType(_to);
600 llvm::Value* rval = DtoBitCast(val->getRVal(), tolltype);
601 return new DImValue(_to, rval);
602 }
603
604 assert(to->ty == Tclass);
605 TypeClass* tc = (TypeClass*)to;
606
607 Type* from = DtoDType(val->getType());
608 TypeClass* fc = (TypeClass*)from;
609
610 if (tc->sym->isInterfaceDeclaration()) {
611 assert(!fc->sym->isInterfaceDeclaration());
612 return DtoDynamicCastObject(val, _to);
613 }
614 else {
615 int poffset;
616 if (fc->sym->isInterfaceDeclaration()) {
617 return DtoCastInterfaceToObject(val, _to);
618 }
619 else if (tc->sym->isBaseOf(fc->sym,NULL)) {
620 const llvm::Type* tolltype = DtoType(_to);
621 llvm::Value* rval = DtoBitCast(val->getRVal(), tolltype);
622 return new DImValue(_to, rval);
623 }
624 else {
625 return DtoDynamicCastObject(val, _to);
626 }
627 }
628 }
629
630 //////////////////////////////////////////////////////////////////////////////////////////
631
632 DValue* DtoDynamicCastObject(DValue* val, Type* _to)
596 { 633 {
597 // call: 634 // call:
598 // Object _d_dynamic_cast(Object o, ClassInfo c) 635 // Object _d_dynamic_cast(Object o, ClassInfo c)
636
637 DtoForceDeclareDsymbol(ClassDeclaration::object);
638 DtoForceDeclareDsymbol(ClassDeclaration::classinfo);
599 639
600 llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_dynamic_cast"); 640 llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_dynamic_cast");
601 const llvm::FunctionType* funcTy = func->getFunctionType(); 641 const llvm::FunctionType* funcTy = func->getFunctionType();
602 642
603 std::vector<llvm::Value*> args; 643 std::vector<llvm::Value*> args;
604 644
605 // Object o 645 // Object o
606 llvm::Value* tmp = val->getRVal(); 646 llvm::Value* tmp = val->getRVal();
607 tmp = DtoBitCast(tmp, funcTy->getParamType(0)); 647 tmp = DtoBitCast(tmp, funcTy->getParamType(0));
608 args.push_back(tmp); 648 args.push_back(tmp);
649 assert(funcTy->getParamType(0) == tmp->getType());
609 650
610 // ClassInfo c 651 // ClassInfo c
611 TypeClass* to = (TypeClass*)DtoDType(_to); 652 TypeClass* to = (TypeClass*)DtoDType(_to);
612 DtoForceDeclareDsymbol(to->sym); 653 DtoForceDeclareDsymbol(to->sym);
613 assert(to->sym->llvmClass); 654 assert(to->sym->llvmClass);
614 args.push_back(to->sym->llvmClass); 655 tmp = to->sym->llvmClass;
656 // unfortunately this is needed as the implementation of object differs somehow from the declaration
657 // this could happen in user code as well :/
658 tmp = DtoBitCast(tmp, funcTy->getParamType(1));
659 args.push_back(tmp);
660 assert(funcTy->getParamType(1) == tmp->getType());
615 661
616 // call it 662 // call it
617 llvm::Value* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "tmp"); 663 llvm::Value* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "tmp");
664
665 // cast return value
618 ret = DtoBitCast(ret, DtoType(_to)); 666 ret = DtoBitCast(ret, DtoType(_to));
667
619 return new DImValue(_to, ret); 668 return new DImValue(_to, ret);
620 } 669 }
621 670
622 ////////////////////////////////////////////////////////////////////////////////////////// 671 //////////////////////////////////////////////////////////////////////////////////////////
623 672
624 DValue* DtoCastInterfaceToObject(DValue* val) 673 DValue* DtoCastInterfaceToObject(DValue* val, Type* to)
625 { 674 {
626 // call: 675 // call:
627 // Object _d_toObject(void* p) 676 // Object _d_toObject(void* p)
628 677
629 llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_toObject"); 678 llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_toObject");
633 llvm::Value* tmp = val->getRVal(); 682 llvm::Value* tmp = val->getRVal();
634 tmp = DtoBitCast(tmp, funcTy->getParamType(0)); 683 tmp = DtoBitCast(tmp, funcTy->getParamType(0));
635 684
636 // call it 685 // call it
637 llvm::Value* ret = gIR->ir->CreateCall(func, tmp, "tmp"); 686 llvm::Value* ret = gIR->ir->CreateCall(func, tmp, "tmp");
638 return new DImValue(ClassDeclaration::object->type, ret); 687
688 // cast return value
689 if (to != NULL)
690 ret = DtoBitCast(ret, DtoType(to));
691 else
692 to = ClassDeclaration::object->type;
693
694 return new DImValue(to, ret);
639 } 695 }
640 696
641 ////////////////////////////////////////////////////////////////////////////////////////// 697 //////////////////////////////////////////////////////////////////////////////////////////
642 698
643 void DtoDeclareClassInfo(ClassDeclaration* cd) 699 void DtoDeclareClassInfo(ClassDeclaration* cd)