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 module rt.compiler.gdc.rt.cast_; 28 extern (C): 29 30 /****************************************** 31 * Given a pointer: 32 * If it is an Object, return that Object. 33 * If it is an interface, return the Object implementing the interface. 34 * If it is null, return null. 35 * Else, undefined crash 36 */ 37 38 Object _d_toObject(void* p) 39 { Object o; 40 41 if (p) 42 { 43 o = cast(Object)p; 44 ClassInfo oc = o.classinfo; 45 Interface *pi = **cast(Interface ***)p; 46 47 /* Interface.offset lines up with ClassInfo.name.ptr, 48 * so we rely on pointers never being less than 64K, 49 * and Objects never being greater. 50 */ 51 if (pi.offset < 0x10000) 52 { 53 //printf("\tpi.offset = %d\n", pi.offset); 54 o = cast(Object)(p - pi.offset); 55 } 56 } 57 return o; 58 } 59 60 61 /************************************* 62 * Attempts to cast Object o to class c. 63 * Returns o if successful, null if not. 64 */ 65 66 Object _d_interface_cast(void* p, ClassInfo c) 67 { Object o; 68 69 //printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name); 70 if (p) 71 { 72 Interface *pi = **cast(Interface ***)p; 73 74 //printf("\tpi.offset = %d\n", pi.offset); 75 o = cast(Object)(p - pi.offset); 76 return _d_dynamic_cast(o, c); 77 } 78 return o; 79 } 80 81 Object _d_dynamic_cast(Object o, ClassInfo c) 82 { ClassInfo oc; 83 size_t offset = 0; 84 85 //printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name); 86 87 if (o) 88 { 89 oc = o.classinfo; 90 if (_d_isbaseof2(oc, c, offset)) 91 { 92 //printf("\toffset = %d\n", offset); 93 o = cast(Object)(cast(void*)o + offset); 94 } 95 else 96 o = null; 97 } 98 //printf("\tresult = %p\n", o); 99 return o; 100 } 101 102 int _d_isbaseof2(ClassInfo oc, ClassInfo c, ref size_t offset) 103 { int i; 104 105 if (oc is c) 106 return 1; 107 do 108 { 109 if (oc.base is c) 110 return 1; 111 for (i = 0; i < oc.interfaces.length; i++) 112 { 113 ClassInfo ic; 114 115 ic = oc.interfaces[i].classinfo; 116 if (ic is c) 117 { offset = oc.interfaces[i].offset; 118 return 1; 119 } 120 } 121 for (i = 0; i < oc.interfaces.length; i++) 122 { 123 ClassInfo ic; 124 125 ic = oc.interfaces[i].classinfo; 126 if (_d_isbaseof2(ic, c, offset)) 127 { offset = oc.interfaces[i].offset; 128 return 1; 129 } 130 } 131 oc = oc.base; 132 } while (oc); 133 return 0; 134 } 135 136 int _d_isbaseof(ClassInfo oc, ClassInfo c) 137 { int i; 138 139 if (oc is c) 140 return 1; 141 do 142 { 143 if (oc.base is c) 144 return 1; 145 for (i = 0; i < oc.interfaces.length; i++) 146 { 147 ClassInfo ic; 148 149 ic = oc.interfaces[i].classinfo; 150 if (ic is c || _d_isbaseof(ic, c)) 151 return 1; 152 } 153 oc = oc.base; 154 } while (oc); 155 return 0; 156 } 157 158 /********************************* 159 * Find the vtbl[] associated with Interface ic. 160 */ 161 162 void *_d_interface_vtbl(ClassInfo ic, Object o) 163 { int i; 164 ClassInfo oc; 165 166 //printf("__d_interface_vtbl(o = %p, ic = %p)\n", o, ic); 167 168 assert(o); 169 170 oc = o.classinfo; 171 for (i = 0; i < oc.interfaces.length; i++) 172 { 173 ClassInfo oic; 174 175 oic = oc.interfaces[i].classinfo; 176 if (oic is ic) 177 { 178 return cast(void *)oc.interfaces[i].vtbl; 179 } 180 } 181 assert(0); 182 }