Mercurial > projects > ldc
diff druntime/src/compiler/ldc/cast_.d @ 1458:e0b2d67cfe7c
Added druntime (this should be removed once it works).
author | Robert Clipsham <robert@octarineparrot.com> |
---|---|
date | Tue, 02 Jun 2009 17:43:06 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/druntime/src/compiler/ldc/cast_.d Tue Jun 02 17:43:06 2009 +0100 @@ -0,0 +1,169 @@ +/** + * Implementation of array assignment support routines. + * + * Copyright: Copyright Digital Mars 2004 - 2009. + * License: <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>. + * Authors: Walter Bright, Sean Kelly + * + * Copyright Digital Mars 2004 - 2009. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ +module rt.cast_; + +extern (C): + +/****************************************** + * Given a pointer: + * If it is an Object, return that Object. + * If it is an interface, return the Object implementing the interface. + * If it is null, return null. + * Else, undefined crash + */ + +Object _d_toObject(void* p) +{ Object o; + + if (p) + { + o = cast(Object)p; + ClassInfo oc = o.classinfo; + Interface *pi = **cast(Interface ***)p; + + /* Interface.offset lines up with ClassInfo.name.ptr, + * so we rely on pointers never being less than 64K, + * and Objects never being greater. + */ + if (pi.offset < 0x10000) + { + //printf("\tpi.offset = %d\n", pi.offset); + o = cast(Object)(p - pi.offset); + } + } + return o; +} + + +/************************************* + * Attempts to cast Object o to class c. + * Returns o if successful, null if not. + */ + +Object _d_interface_cast(void* p, ClassInfo c) +{ Object o; + + //printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name); + if (p) + { + Interface *pi = **cast(Interface ***)p; + + //printf("\tpi.offset = %d\n", pi.offset); + o = cast(Object)(p - pi.offset); + return _d_dynamic_cast(o, c); + } + return o; +} + +Object _d_dynamic_cast(Object o, ClassInfo c) +{ ClassInfo oc; + size_t offset = 0; + + //printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name); + + if (o) + { + oc = o.classinfo; + if (_d_isbaseof2(oc, c, offset)) + { + //printf("\toffset = %d\n", offset); + o = cast(Object)(cast(void*)o + offset); + } + else + o = null; + } + //printf("\tresult = %p\n", o); + return o; +} + +int _d_isbaseof2(ClassInfo oc, ClassInfo c, inout size_t offset) +{ int i; + + if (oc is c) + return 1; + do + { + if (oc.base is c) + return 1; + for (i = 0; i < oc.interfaces.length; i++) + { + ClassInfo ic; + + ic = oc.interfaces[i].classinfo; + if (ic is c) + { offset = oc.interfaces[i].offset; + return 1; + } + } + for (i = 0; i < oc.interfaces.length; i++) + { + ClassInfo ic; + + ic = oc.interfaces[i].classinfo; + if (_d_isbaseof2(ic, c, offset)) + { offset = oc.interfaces[i].offset; + return 1; + } + } + oc = oc.base; + } while (oc); + return 0; +} + +int _d_isbaseof(ClassInfo oc, ClassInfo c) +{ int i; + + if (oc is c) + return 1; + do + { + if (oc.base is c) + return 1; + for (i = 0; i < oc.interfaces.length; i++) + { + ClassInfo ic; + + ic = oc.interfaces[i].classinfo; + if (ic is c || _d_isbaseof(ic, c)) + return 1; + } + oc = oc.base; + } while (oc); + return 0; +} + +/********************************* + * Find the vtbl[] associated with Interface ic. + */ + +void *_d_interface_vtbl(ClassInfo ic, Object o) +{ int i; + ClassInfo oc; + + //printf("__d_interface_vtbl(o = %p, ic = %p)\n", o, ic); + + assert(o); + + oc = o.classinfo; + for (i = 0; i < oc.interfaces.length; i++) + { + ClassInfo oic; + + oic = oc.interfaces[i].classinfo; + if (oic is ic) + { + return cast(void *)oc.interfaces[i].vtbl; + } + } + assert(0); +}