1 /** 2 * Compiler implementation of the 3 * $(LINK2 http://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved 6 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 7 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 8 * Source: $(DMDSRC _typeinf.d) 9 */ 10 11 module ddmd.typinf; 12 13 import ddmd.declaration; 14 import ddmd.dmodule; 15 import ddmd.dscope; 16 import ddmd.dstruct; 17 import ddmd.errors; 18 import ddmd.globals; 19 import ddmd.gluelayer; 20 import ddmd.mtype; 21 import ddmd.visitor; 22 23 /**************************************************** 24 * Get the exact TypeInfo. 25 */ 26 extern (C++) void genTypeInfo(Type torig, Scope* sc) 27 { 28 //printf("Type::genTypeInfo() %p, %s\n", this, toChars()); 29 if (!Type.dtypeinfo) 30 { 31 torig.error(Loc(), "TypeInfo not found. object.d may be incorrectly installed or corrupt, compile with -v switch"); 32 fatal(); 33 } 34 35 Type t = torig.merge2(); // do this since not all Type's are merge'd 36 if (!t.vtinfo) 37 { 38 if (t.isShared()) // does both 'shared' and 'shared const' 39 t.vtinfo = TypeInfoSharedDeclaration.create(t); 40 else if (t.isConst()) 41 t.vtinfo = TypeInfoConstDeclaration.create(t); 42 else if (t.isImmutable()) 43 t.vtinfo = TypeInfoInvariantDeclaration.create(t); 44 else if (t.isWild()) 45 t.vtinfo = TypeInfoWildDeclaration.create(t); 46 else 47 t.vtinfo = getTypeInfoDeclaration(t); 48 assert(t.vtinfo); 49 50 /* If this has a custom implementation in std/typeinfo, then 51 * do not generate a COMDAT for it. 52 */ 53 if (!builtinTypeInfo(t)) 54 { 55 // Generate COMDAT 56 if (sc) // if in semantic() pass 57 { 58 // Find module that will go all the way to an object file 59 Module m = sc._module.importedFrom; 60 m.members.push(t.vtinfo); 61 } 62 else // if in obj generation pass 63 { 64 toObjFile(t.vtinfo, global.params.multiobj); 65 } 66 } 67 } 68 if (!torig.vtinfo) 69 torig.vtinfo = t.vtinfo; // Types aren't merged, but we can share the vtinfo's 70 assert(torig.vtinfo); 71 } 72 73 extern (C++) Type getTypeInfoType(Type t, Scope* sc) 74 { 75 assert(t.ty != Terror); 76 genTypeInfo(t, sc); 77 return t.vtinfo.type; 78 } 79 80 extern (C++) TypeInfoDeclaration getTypeInfoDeclaration(Type t) 81 { 82 //printf("Type::getTypeInfoDeclaration() %s\n", t->toChars()); 83 switch (t.ty) 84 { 85 case Tpointer: 86 return TypeInfoPointerDeclaration.create(t); 87 case Tarray: 88 return TypeInfoArrayDeclaration.create(t); 89 case Tsarray: 90 return TypeInfoStaticArrayDeclaration.create(t); 91 case Taarray: 92 return TypeInfoAssociativeArrayDeclaration.create(t); 93 case Tstruct: 94 return TypeInfoStructDeclaration.create(t); 95 case Tvector: 96 return TypeInfoVectorDeclaration.create(t); 97 case Tenum: 98 return TypeInfoEnumDeclaration.create(t); 99 case Tfunction: 100 return TypeInfoFunctionDeclaration.create(t); 101 case Tdelegate: 102 return TypeInfoDelegateDeclaration.create(t); 103 case Ttuple: 104 return TypeInfoTupleDeclaration.create(t); 105 case Tclass: 106 if ((cast(TypeClass)t).sym.isInterfaceDeclaration()) 107 return TypeInfoInterfaceDeclaration.create(t); 108 else 109 return TypeInfoClassDeclaration.create(t); 110 111 default: 112 return TypeInfoDeclaration.create(t); 113 } 114 } 115 116 extern (C++) bool isSpeculativeType(Type t) 117 { 118 extern (C++) final class SpeculativeTypeVisitor : Visitor 119 { 120 alias visit = super.visit; 121 public: 122 bool result; 123 124 extern (D) this() 125 { 126 } 127 128 override void visit(Type t) 129 { 130 Type tb = t.toBasetype(); 131 if (tb != t) 132 tb.accept(this); 133 } 134 135 override void visit(TypeNext t) 136 { 137 if (t.next) 138 t.next.accept(this); 139 } 140 141 override void visit(TypeBasic t) 142 { 143 } 144 145 override void visit(TypeVector t) 146 { 147 t.basetype.accept(this); 148 } 149 150 override void visit(TypeAArray t) 151 { 152 t.index.accept(this); 153 visit(cast(TypeNext)t); 154 } 155 156 override void visit(TypeFunction t) 157 { 158 visit(cast(TypeNext)t); 159 // Currently TypeInfo_Function doesn't store parameter types. 160 } 161 162 override void visit(TypeStruct t) 163 { 164 StructDeclaration sd = t.sym; 165 if (auto ti = sd.isInstantiated()) 166 { 167 if (!ti.needsCodegen()) 168 { 169 if (ti.minst || sd.requestTypeInfo) 170 return; 171 172 /* Bugzilla 14425: TypeInfo_Struct would refer the members of 173 * struct (e.g. opEquals via xopEquals field), so if it's instantiated 174 * in speculative context, TypeInfo creation should also be 175 * stopped to avoid 'unresolved symbol' linker errors. 176 */ 177 /* When -debug/-unittest is specified, all of non-root instances are 178 * automatically changed to speculative, and here is always reached 179 * from those instantiated non-root structs. 180 * Therefore, if the TypeInfo is not auctually requested, 181 * we have to elide its codegen. 182 */ 183 result |= true; 184 return; 185 } 186 } 187 else 188 { 189 //assert(!sd.inNonRoot() || sd.requestTypeInfo); // valid? 190 } 191 } 192 193 override void visit(TypeClass t) 194 { 195 } 196 197 override void visit(TypeTuple t) 198 { 199 if (t.arguments) 200 { 201 for (size_t i = 0; i < t.arguments.dim; i++) 202 { 203 Type tprm = (*t.arguments)[i].type; 204 if (tprm) 205 tprm.accept(this); 206 if (result) 207 return; 208 } 209 } 210 } 211 } 212 213 scope SpeculativeTypeVisitor v = new SpeculativeTypeVisitor(); 214 t.accept(v); 215 return v.result; 216 } 217 218 /* ========================================================================= */ 219 220 /* These decide if there's an instance for them already in std.typeinfo, 221 * because then the compiler doesn't need to build one. 222 */ 223 extern (C++) static bool builtinTypeInfo(Type t) 224 { 225 if (t.isTypeBasic() || t.ty == Tclass || t.ty == Tnull) 226 return !t.mod; 227 if (t.ty == Tarray) 228 { 229 Type next = t.nextOf(); 230 // strings are so common, make them builtin 231 return !t.mod && 232 (next.isTypeBasic() !is null && !next.mod || 233 next.ty == Tchar && next.mod == MODimmutable || 234 next.ty == Tchar && next.mod == MODconst); 235 } 236 return false; 237 }