Mercurial > projects > ldc
diff 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 |
line wrap: on
line diff
--- a/gen/classes.cpp Sat Nov 24 06:33:00 2007 +0100 +++ b/gen/classes.cpp Sun Nov 25 00:19:13 2007 +0100 @@ -60,7 +60,7 @@ BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i]; ClassDeclaration *id = b->base; DtoResolveClass(id); - // Fill in vtbl[] + // Fill in vtbl[] b->fillVtbl(cd, &b->vtbl, 1); } } @@ -128,11 +128,11 @@ else *ts->llvmType = structtype; - if (cd->parent->isModule()) { - gIR->module->addTypeName(cd->mangle(), ts->llvmType->get()); + if (cd->isNested()) { + assert(0 && "nested classes not implemented"); } else { - assert(0 && "class parent is not a module"); + gIR->module->addTypeName(cd->mangle(), ts->llvmType->get()); } // build interface info type @@ -592,11 +592,51 @@ ////////////////////////////////////////////////////////////////////////////////////////// -DValue* DtoCastObjectToInterface(DValue* val, Type* _to) +DValue* DtoCastClass(DValue* val, Type* _to) +{ + Type* to = DtoDType(_to); + if (to->ty == Tpointer) { + const llvm::Type* tolltype = DtoType(_to); + llvm::Value* rval = DtoBitCast(val->getRVal(), tolltype); + return new DImValue(_to, rval); + } + + assert(to->ty == Tclass); + TypeClass* tc = (TypeClass*)to; + + Type* from = DtoDType(val->getType()); + TypeClass* fc = (TypeClass*)from; + + if (tc->sym->isInterfaceDeclaration()) { + assert(!fc->sym->isInterfaceDeclaration()); + return DtoDynamicCastObject(val, _to); + } + else { + int poffset; + if (fc->sym->isInterfaceDeclaration()) { + return DtoCastInterfaceToObject(val, _to); + } + else if (tc->sym->isBaseOf(fc->sym,NULL)) { + const llvm::Type* tolltype = DtoType(_to); + llvm::Value* rval = DtoBitCast(val->getRVal(), tolltype); + return new DImValue(_to, rval); + } + else { + return DtoDynamicCastObject(val, _to); + } + } +} + +////////////////////////////////////////////////////////////////////////////////////////// + +DValue* DtoDynamicCastObject(DValue* val, Type* _to) { // call: // Object _d_dynamic_cast(Object o, ClassInfo c) + DtoForceDeclareDsymbol(ClassDeclaration::object); + DtoForceDeclareDsymbol(ClassDeclaration::classinfo); + llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_dynamic_cast"); const llvm::FunctionType* funcTy = func->getFunctionType(); @@ -606,22 +646,31 @@ llvm::Value* tmp = val->getRVal(); tmp = DtoBitCast(tmp, funcTy->getParamType(0)); args.push_back(tmp); + assert(funcTy->getParamType(0) == tmp->getType()); // ClassInfo c TypeClass* to = (TypeClass*)DtoDType(_to); DtoForceDeclareDsymbol(to->sym); assert(to->sym->llvmClass); - args.push_back(to->sym->llvmClass); + tmp = to->sym->llvmClass; + // unfortunately this is needed as the implementation of object differs somehow from the declaration + // this could happen in user code as well :/ + tmp = DtoBitCast(tmp, funcTy->getParamType(1)); + args.push_back(tmp); + assert(funcTy->getParamType(1) == tmp->getType()); // call it llvm::Value* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "tmp"); + + // cast return value ret = DtoBitCast(ret, DtoType(_to)); + return new DImValue(_to, ret); } ////////////////////////////////////////////////////////////////////////////////////////// -DValue* DtoCastInterfaceToObject(DValue* val) +DValue* DtoCastInterfaceToObject(DValue* val, Type* to) { // call: // Object _d_toObject(void* p) @@ -635,7 +684,14 @@ // call it llvm::Value* ret = gIR->ir->CreateCall(func, tmp, "tmp"); - return new DImValue(ClassDeclaration::object->type, ret); + + // cast return value + if (to != NULL) + ret = DtoBitCast(ret, DtoType(to)); + else + to = ClassDeclaration::object->type; + + return new DImValue(to, ret); } //////////////////////////////////////////////////////////////////////////////////////////