]> git.llucax.com Git - software/druntime.git/blob - src/compiler/dmd/cast_.d
First commit of the D Runtime Project. This includes a fully functional runtime...
[software/druntime.git] / src / compiler / dmd / cast_.d
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 for use with the D Runtime Project
26  */
27
28 module 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     size_t 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, inout size_t 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 }