comparison runtime/internal/cast.d @ 443:44f08170f4ef

Removed tango from the repository and instead added a runtime dir with the files needed to patch and build tango from svn. Reworked the LLVMDC specific pragmas.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Fri, 01 Aug 2008 00:32:06 +0200
parents
children
comparison
equal deleted inserted replaced
442:76078c8ab5b9 443:44f08170f4ef
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 extern (C):
29
30 //debug = PRINTF;
31 debug(PRINTF) int printf(char*, ...);
32
33 /******************************************
34 * Given a pointer:
35 * If it is an Object, return that Object.
36 * If it is an interface, return the Object implementing the interface.
37 * If it is null, return null.
38 * Else, undefined crash
39 */
40
41 Object _d_toObject(void* p)
42 { Object o;
43 debug(PRINTF) printf("toObject(%p)\n", p);
44 if (p)
45 {
46 o = cast(Object)p;
47 debug(PRINTF) printf("o = %p\n", o);
48 debug(PRINTF) printf("o.vtbl = %p\n", *cast(void**)p);
49 ClassInfo oc = o.classinfo;
50 debug(PRINTF) printf("oc = %p\n", oc);
51 Interface *pi = **cast(Interface ***)p;
52 debug(PRINTF) printf("pi = %p\n", pi);
53
54 /* Interface.offset lines up with ClassInfo.name.ptr,
55 * so we rely on pointers never being less than 64K,
56 * and interface vtable offsets never being greater.
57 */
58 if (pi.offset < 0x10000)
59 {
60 debug(PRINTF) printf("\tpi.offset = %d\n", pi.offset);
61 o = cast(Object)(p - pi.offset);
62 }
63 }
64 debug(PRINTF) printf("toObject = %p\n", o);
65 return o;
66 }
67
68
69 /*************************************
70 * Attempts to cast Object o to class c.
71 * Returns o if successful, null if not.
72 */
73
74 Object _d_interface_cast(void* p, ClassInfo c)
75 { Object o;
76
77 debug(PRINTF) printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name.length, c.name.ptr);
78 if (p)
79 {
80 Interface *pi = **cast(Interface ***)p;
81
82 debug(PRINTF) printf("\tpi.offset = %d\n", pi.offset);
83 o = cast(Object)(p - pi.offset);
84 return _d_dynamic_cast(o, c);
85 }
86 debug(PRINTF) printf("_d_interface_cast = %p\n", o);
87 return o;
88 }
89
90 Object _d_dynamic_cast(Object o, ClassInfo c)
91 { ClassInfo oc;
92 size_t offset = 0;
93
94 debug(PRINTF) printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name.length, c.name.ptr);
95
96 if (o)
97 {
98 oc = o.classinfo;
99 if (_d_isbaseof2(oc, c, offset))
100 {
101 debug(PRINTF) printf("\toffset = %d\n", offset);
102 o = cast(Object)(cast(void*)o + offset);
103 }
104 else
105 o = null;
106 }
107 //printf("\tresult = %p\n", o);
108 debug(PRINTF) printf("_d_dynamic_cast = %p\n", o);
109 return o;
110 }
111
112 int _d_isbaseof2(ClassInfo oc, ClassInfo c, ref size_t offset)
113 { int i;
114
115 debug(PRINTF) printf("_d_isbaseof2(%.*s, %.*s, %ul)\n", oc.name.length, oc.name.ptr, c.name.length, c.name.ptr, offset);
116
117 if (oc is c)
118 return 1;
119 do
120 {
121 debug(PRINTF) printf("oc.interfaces.length = %ul\n", oc.interfaces.length);
122 if (oc.base is c)
123 return 1;
124 for (i = 0; i < oc.interfaces.length; i++)
125 {
126 ClassInfo ic;
127
128 ic = oc.interfaces[i].classinfo;
129 debug(PRINTF) printf("checking %.*s\n", ic.name.length, ic.name.ptr);
130 if (ic is c)
131 { offset = cast(size_t)oc.interfaces[i].offset;
132 return 1;
133 }
134 }
135 for (i = 0; i < oc.interfaces.length; i++)
136 {
137 ClassInfo ic;
138
139 ic = oc.interfaces[i].classinfo;
140 if (_d_isbaseof2(ic, c, offset))
141 { offset = cast(size_t)oc.interfaces[i].offset;
142 return 1;
143 }
144 }
145 oc = oc.base;
146 } while (oc);
147 return 0;
148 }
149
150 int _d_isbaseof(ClassInfo oc, ClassInfo c)
151 { int i;
152
153 if (oc is c)
154 return 1;
155 do
156 {
157 if (oc.base is c)
158 return 1;
159 for (i = 0; i < oc.interfaces.length; i++)
160 {
161 ClassInfo ic;
162
163 ic = oc.interfaces[i].classinfo;
164 if (ic is c || _d_isbaseof(ic, c))
165 return 1;
166 }
167 oc = oc.base;
168 } while (oc);
169 return 0;
170 }
171
172 /*********************************
173 * Find the vtbl[] associated with Interface ic.
174 */
175
176 void *_d_interface_vtbl(ClassInfo ic, Object o)
177 { int i;
178 ClassInfo oc;
179
180 //printf("__d_interface_vtbl(o = %p, ic = %p)\n", o, ic);
181
182 assert(o);
183
184 oc = o.classinfo;
185 for (i = 0; i < oc.interfaces.length; i++)
186 {
187 ClassInfo oic;
188
189 oic = oc.interfaces[i].classinfo;
190 if (oic is ic)
191 {
192 return cast(void *)oc.interfaces[i].vtbl;
193 }
194 }
195 assert(0);
196 }