1 /* 2 * Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com 3 * Written by Walter Bright 4 * 5 * This software is provided 'as-is', without any express or implied 6 * warranty. In no event will the authors be held liable for any damages 7 * arising from the use of this software. 8 * 9 * Permission is granted to anyone to use this software for any purpose, 10 * including commercial applications, and to alter it and redistribute it 11 * freely, in both source and binary form, subject to the following 12 * restrictions: 13 * 14 * o The origin of this software must not be misrepresented; you must not 15 * claim that you wrote the original software. If you use this software 16 * in a product, an acknowledgment in the product documentation would be 17 * appreciated but is not required. 18 * o Altered source versions must be plainly marked as such, and must not 19 * be misrepresented as being the original software. 20 * o This notice may not be removed or altered from any source 21 * distribution. 22 */ 23 24 /* 25 * Modified by Sean Kelly <sean@f4.ca> for use with Tango. 26 */ 27 28 module rt.compiler.dmd.rt.cast_; 29 30 extern (C): 31 32 /****************************************** 33 * Given a pointer: 34 * If it is an Object, return that Object. 35 * If it is an interface, return the Object implementing the interface. 36 * If it is null, return null. 37 * Else, undefined crash 38 */ 39 40 Object _d_toObject(void* p) 41 { Object o; 42 43 if (p) 44 { 45 o = cast(Object)p; 46 ClassInfo oc = o.classinfo; 47 Interface *pi = **cast(Interface ***)p; 48 49 /* Interface.offset lines up with ClassInfo.name.ptr, 50 * so we rely on pointers never being less than 64K, 51 * and Objects never being greater. 52 */ 53 if (pi.offset < 0x10000) 54 { 55 //printf("\tpi.offset = %d\n", pi.offset); 56 o = cast(Object)(p - pi.offset); 57 } 58 } 59 return o; 60 } 61 62 63 /************************************* 64 * Attempts to cast Object o to class c. 65 * Returns o if successful, null if not. 66 */ 67 68 Object _d_interface_cast(void* p, ClassInfo c) 69 { Object o; 70 71 //printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name); 72 if (p) 73 { 74 Interface *pi = **cast(Interface ***)p; 75 76 //printf("\tpi.offset = %d\n", pi.offset); 77 o = cast(Object)(p - pi.offset); 78 return _d_dynamic_cast(o, c); 79 } 80 return o; 81 } 82 83 Object _d_dynamic_cast(Object o, ClassInfo c) 84 { ClassInfo oc; 85 uint offset = 0; 86 87 //printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name); 88 89 if (o) 90 { 91 oc = o.classinfo; 92 if (_d_isbaseof2(oc, c, offset)) 93 { 94 //printf("\toffset = %d\n", offset); 95 o = cast(Object)(cast(void*)o + offset); 96 } 97 else 98 o = null; 99 } 100 //printf("\tresult = %p\n", o); 101 return o; 102 } 103 104 int _d_isbaseof2(ClassInfo oc, ClassInfo c, ref uint offset) 105 { int i; 106 107 if (oc is c) 108 return 1; 109 do 110 { 111 if (oc.base is c) 112 return 1; 113 for (i = 0; i < oc.interfaces.length; i++) 114 { 115 ClassInfo ic; 116 117 ic = oc.interfaces[i].classinfo; 118 if (ic is c) 119 { offset = oc.interfaces[i].offset; 120 return 1; 121 } 122 } 123 for (i = 0; i < oc.interfaces.length; i++) 124 { 125 ClassInfo ic; 126 127 ic = oc.interfaces[i].classinfo; 128 if (_d_isbaseof2(ic, c, offset)) 129 { offset = oc.interfaces[i].offset; 130 return 1; 131 } 132 } 133 oc = oc.base; 134 } while (oc); 135 return 0; 136 } 137 138 int _d_isbaseof(ClassInfo oc, ClassInfo c) 139 { int i; 140 141 if (oc is c) 142 return 1; 143 do 144 { 145 if (oc.base is c) 146 return 1; 147 for (i = 0; i < oc.interfaces.length; i++) 148 { 149 ClassInfo ic; 150 151 ic = oc.interfaces[i].classinfo; 152 if (ic is c || _d_isbaseof(ic, c)) 153 return 1; 154 } 155 oc = oc.base; 156 } while (oc); 157 return 0; 158 } 159 160 /********************************* 161 * Find the vtbl[] associated with Interface ic. 162 */ 163 164 void *_d_interface_vtbl(ClassInfo ic, Object o) 165 { int i; 166 ClassInfo oc; 167 168 //printf("__d_interface_vtbl(o = %p, ic = %p)\n", o, ic); 169 170 assert(o); 171 172 oc = o.classinfo; 173 for (i = 0; i < oc.interfaces.length; i++) 174 { 175 ClassInfo oic; 176 177 oic = oc.interfaces[i].classinfo; 178 if (oic is ic) 179 { 180 return cast(void *)oc.interfaces[i].vtbl; 181 } 182 } 183 assert(0); 184 }