1 module lifetime.class_; 2 3 import lifetime.common; 4 5 extern(C) Object _d_newclass(const TypeInfo_Class ti) 6 { 7 auto buff = lwdrInternal_allocBytes(ti.m_init.length); 8 foreach(i; 0 .. ti.m_init.length) 9 buff[i] = ti.m_init[i]; 10 return cast(Object)buff.ptr; 11 } 12 13 extern(C) void _d_delclass(Object* o) 14 { 15 lwdrInternal_free(cast(void*)*o); 16 *o = null; 17 } 18 19 extern(C) Object _d_allocclass(TypeInfo_Class ti) 20 { 21 auto buff = lwdrInternal_allocBytes(ti.m_init.length); 22 foreach(i; 0 .. ti.m_init.length) 23 buff[i] = ti.m_init[i]; 24 return cast(Object)buff.ptr; 25 } 26 27 /****************************************** 28 * Given a pointer: 29 * If it is an Object, return that Object. 30 * If it is an interface, return the Object implementing the interface. 31 * If it is null, return null. 32 * Else, undefined crash 33 */ 34 extern(C) Object _d_toObject(return void* p) pure nothrow @nogc 35 { 36 if (!p) 37 return null; 38 39 Object o = cast(Object) p; 40 ClassInfo oc = typeid(o); 41 Interface* pi = **cast(Interface***) p; 42 43 /* Interface.offset lines up with ClassInfo.name.ptr, 44 * so we rely on pointers never being less than 64K, 45 * and Objects never being greater. 46 */ 47 if (pi.offset < 0x10000) 48 { 49 debug(cast_) printf("\tpi.offset = %d\n", pi.offset); 50 return cast(Object)(p - pi.offset); 51 } 52 return o; 53 } 54 55 /************************************* 56 * Attempts to cast Object o to class c. 57 * Returns o if successful, null if not. 58 */ 59 extern(C) void* _d_interface_cast(void* p, ClassInfo c) pure nothrow @nogc 60 { 61 debug(cast_) printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name); 62 if (!p) 63 return null; 64 65 Interface* pi = **cast(Interface***) p; 66 67 debug(cast_) printf("\tpi.offset = %d\n", pi.offset); 68 return _d_dynamic_cast(cast(Object)(p - pi.offset), c); 69 } 70 71 72 73 extern(C) void* _d_dynamic_cast(Object o, ClassInfo c) pure nothrow @nogc 74 { 75 debug(cast_) printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name); 76 77 void* res = null; 78 size_t offset = 0; 79 if (o && _d_isbaseof2(typeid(o), c, offset)) 80 { 81 debug(cast_) printf("\toffset = %d\n", offset); 82 res = cast(void*) o + offset; 83 } 84 debug(cast_) printf("\tresult = %p\n", res); 85 return res; 86 } 87 88 extern(C) int _d_isbaseof2(scope ClassInfo oc, scope const ClassInfo c, scope ref size_t offset) @safe pure nothrow @nogc 89 { 90 if (oc is c) 91 return true; 92 93 do 94 { 95 if (oc.base is c) 96 return true; 97 98 // Bugzilla 2013: Use depth-first search to calculate offset 99 // from the derived (oc) to the base (c). 100 foreach (iface; oc.interfaces) 101 { 102 if (iface.classinfo is c || _d_isbaseof2(iface.classinfo, c, offset)) 103 { 104 offset += iface.offset; 105 return true; 106 } 107 } 108 109 oc = oc.base; 110 } while (oc); 111 112 return false; 113 } 114 115 extern(C) int _d_isbaseof(scope ClassInfo oc, scope const ClassInfo c) @safe pure nothrow @nogc 116 { 117 if (oc is c) 118 return true; 119 120 do 121 { 122 if (oc.base is c) 123 return true; 124 125 foreach (iface; oc.interfaces) 126 { 127 if (iface.classinfo is c || _d_isbaseof(iface.classinfo, c)) 128 return true; 129 } 130 131 oc = oc.base; 132 } while (oc); 133 134 return false; 135 } 136 137 //extern(C) void __aeabi_read_tp() {}