xref: /netbsd-src/external/gpl3/gcc.old/dist/libphobos/libdruntime/rt/cast_.d (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
1 /**
2  * Implementation of array assignment support routines.
3  *
4  * Copyright: Copyright Digital Mars 2004 - 2010.
5  * License:   $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
6  * Authors:   Walter Bright, Sean Kelly
7  */
8 
9 /*          Copyright Digital Mars 2004 - 2010.
10  * Distributed under the Boost Software License, Version 1.0.
11  *    (See accompanying file LICENSE or copy at
12  *          http://www.boost.org/LICENSE_1_0.txt)
13  */
14 module rt.cast_;
15 
16 extern (C):
17 
18 /******************************************
19  * Given a pointer:
20  *      If it is an Object, return that Object.
21  *      If it is an interface, return the Object implementing the interface.
22  *      If it is null, return null.
23  *      Else, undefined crash
24  */
_d_toObject(void * p)25 Object _d_toObject(void* p)
26 {
27     if (!p)
28         return null;
29 
30     Object o = cast(Object) p;
31     ClassInfo oc = typeid(o);
32     Interface* pi = **cast(Interface***) p;
33 
34     /* Interface.offset lines up with ClassInfo.name.ptr,
35      * so we rely on pointers never being less than 64K,
36      * and Objects never being greater.
37      */
38     if (pi.offset < 0x10000)
39     {
40         debug(cast_) printf("\tpi.offset = %d\n", pi.offset);
41         return cast(Object)(p - pi.offset);
42     }
43     return o;
44 }
45 
46 /*************************************
47  * Attempts to cast Object o to class c.
48  * Returns o if successful, null if not.
49  */
_d_interface_cast(void * p,ClassInfo c)50 void* _d_interface_cast(void* p, ClassInfo c)
51 {
52     debug(cast_) printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name);
53     if (!p)
54         return null;
55 
56     Interface* pi = **cast(Interface***) p;
57 
58     debug(cast_) printf("\tpi.offset = %d\n", pi.offset);
59     return _d_dynamic_cast(cast(Object)(p - pi.offset), c);
60 }
61 
_d_dynamic_cast(Object o,ClassInfo c)62 void* _d_dynamic_cast(Object o, ClassInfo c)
63 {
64     debug(cast_) printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name);
65 
66     void* res = null;
67     size_t offset = 0;
68     if (o && _d_isbaseof2(typeid(o), c, offset))
69     {
70         debug(cast_) printf("\toffset = %d\n", offset);
71         res = cast(void*) o + offset;
72     }
73     debug(cast_) printf("\tresult = %p\n", res);
74     return res;
75 }
76 
_d_isbaseof2(ClassInfo oc,ClassInfo c,ref size_t offset)77 int _d_isbaseof2(ClassInfo oc, ClassInfo c, ref size_t offset)
78 {
79     if (oc is c)
80         return true;
81 
82     do
83     {
84         if (oc.base is c)
85             return true;
86 
87         // Bugzilla 2013: Use depth-first search to calculate offset
88         // from the derived (oc) to the base (c).
89         foreach (iface; oc.interfaces)
90         {
91             if (iface.classinfo is c || _d_isbaseof2(iface.classinfo, c, offset))
92             {
93                 offset += iface.offset;
94                 return true;
95             }
96         }
97 
98         oc = oc.base;
99     } while (oc);
100 
101     return false;
102 }
103 
_d_isbaseof(ClassInfo oc,ClassInfo c)104 int _d_isbaseof(ClassInfo oc, ClassInfo c)
105 {
106     if (oc is c)
107         return true;
108 
109     do
110     {
111         if (oc.base is c)
112             return true;
113 
114         foreach (iface; oc.interfaces)
115         {
116             if (iface.classinfo is c || _d_isbaseof(iface.classinfo, c))
117                 return true;
118         }
119 
120         oc = oc.base;
121     } while (oc);
122 
123     return false;
124 }
125 
126 /*********************************
127  * Find the vtbl[] associated with Interface ic.
128  */
_d_interface_vtbl(ClassInfo ic,Object o)129 void* _d_interface_vtbl(ClassInfo ic, Object o)
130 {
131     debug(cast_) printf("__d_interface_vtbl(o = %p, ic = %p)\n", o, ic);
132 
133     assert(o);
134 
135     foreach (iface; typeid(o).interfaces)
136     {
137         if (iface.classinfo is ic)
138             return cast(void*) iface.vtbl;
139     }
140     assert(0);
141 }
142