1 /++ 2 $(H1 Type Information) 3 4 Type Information implementation compatible with BetterC mode. 5 6 Copyright: 2020 Ilya Yaroshenko, Kaleidic Associates Advisory Limited, Symmetry Investments 7 Authors: Ilya Yaroshenko 8 9 Macros: 10 NDSLICE = $(REF_ALTTEXT $(TT $2), $2, mir, ndslice, $1)$(NBSP) 11 T2=$(TR $(TDNW $(LREF $1)) $(TD $+)) 12 +/ 13 module mir.type_info; 14 15 /++ 16 +/ 17 struct mir_type_info 18 { 19 /// 20 extern(C) 21 void function(void*) @safe pure nothrow @nogc destructor; 22 /++ 23 Note: Negative values are used for classes to indicate that 24 +/ 25 int size; 26 } 27 28 /++ 29 +/ 30 ref immutable(mir_type_info) mir_get_type_info(T)() @trusted 31 { 32 import std.traits: Unqual, hasElaborateDestructor; 33 34 static if (is(T == class)) 35 enum sizeof = __traits(classInstanceSize, T); 36 else 37 enum sizeof = T.sizeof; 38 39 static if (!is(T == Unqual!T)) 40 { 41 return mir_get_type_info!(Unqual!T); 42 } 43 else 44 static if (hasElaborateDestructor!T) 45 { 46 import std.traits: SetFunctionAttributes, functionAttributes; 47 alias fun = void function(void*) @safe pure nothrow @nogc; 48 extern(C) 49 static void destroy_impl(void* ptr) nothrow 50 { 51 static if (is(T == class)) 52 T inst() return @trusted 53 { 54 return cast(T)ptr; 55 } 56 else 57 ref T inst() return @trusted 58 { 59 return *cast(T*)ptr; 60 } 61 version(assert) 62 destroy!true(inst()); 63 else 64 destroy!false(inst()); 65 } 66 67 static immutable ti = mir_type_info(cast(SetFunctionAttributes!(fun, "C", functionAttributes!fun))&destroy_impl, sizeof); 68 return ti; 69 } 70 else 71 { 72 return .mir_get_type_info!sizeof; 73 } 74 } 75 76 /++ 77 +/ 78 ref immutable(mir_type_info) mir_get_type_info(uint sizeof)() 79 { 80 static immutable ti = mir_type_info(null, sizeof); 81 return ti; 82 } 83 84 package template hasDestructor(T) 85 { 86 import std.traits: Unqual; 87 88 static if (is(T == struct)) 89 { 90 static if (__traits(hasMember, Unqual!T, "__xdtor")) 91 enum hasDestructor = __traits(isSame, Unqual!T, __traits(parent, T.init.__xdtor)); 92 else 93 enum hasDestructor = false; 94 } 95 else 96 static if (is(T == class)) 97 { 98 enum hasDestructor = __traits(hasMember, Unqual!T, "__xdtor"); 99 } 100 else 101 { 102 enum hasDestructor = false; 103 } 104 } 105 106 package const(void)* mir_get_payload_ptr(T)() 107 { 108 import std.traits: Unqual; 109 110 static if (!is(T == Unqual!T)) 111 { 112 return mir_get_payload_ptr!(Unqual!T); 113 } 114 else 115 static if (is(T == class)) 116 { 117 return typeid(T).initializer.ptr; 118 } 119 else 120 static if (__traits(isZeroInit, T) || __traits(isFloating, T)) 121 { 122 return null; 123 } 124 else 125 { 126 static immutable payload = T.init; 127 return &payload; 128 } 129 }