1 /** 2 * Convert a D type to a type the backend understands. 3 * 4 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved 5 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 6 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 7 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/toctype.d, _toctype.d) 8 * Documentation: https://dlang.org/phobos/dmd_toctype.html 9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/toctype.d 10 */ 11 12 module dmd.toctype; 13 14 import core.stdc.stdio; 15 import core.stdc.stdlib; 16 17 import dmd.backend.cc : Classsym, Symbol; 18 import dmd.backend.ty; 19 import dmd.backend.type; 20 21 import dmd.root.rmem; 22 23 import dmd.astenums; 24 import dmd.declaration; 25 import dmd.denum; 26 import dmd.dmdparams; 27 import dmd.dstruct; 28 import dmd.globals; 29 import dmd.glue; 30 import dmd.id; 31 import dmd.mtype; 32 import dmd.tocvdebug; 33 34 35 /******************* 36 * Determine backend tym bits corresponding to MOD 37 * Params: 38 * mod = mod bits 39 * Returns: 40 * corresponding tym_t bits 41 */ 42 tym_t modToTym(MOD mod) pure @safe 43 { 44 switch (mod) 45 { 46 case 0: 47 return 0; 48 49 case MODFlags.const_: 50 case MODFlags.wild: 51 case MODFlags.wildconst: 52 return mTYconst; 53 54 case MODFlags.shared_: 55 return mTYshared; 56 57 case MODFlags.shared_ | MODFlags.const_: 58 case MODFlags.shared_ | MODFlags.wild: 59 case MODFlags.shared_ | MODFlags.wildconst: 60 return mTYshared | mTYconst; 61 62 case MODFlags.immutable_: 63 return mTYimmutable; 64 65 default: 66 assert(0); 67 } 68 } 69 70 71 /************************************ 72 * Convert front end type `t` to backend type `t.ctype`. 73 * Memoize the result. 74 * Params: 75 * t = front end `Type` 76 * Returns: 77 * back end equivalent `type` 78 */ 79 extern (C++) type* Type_toCtype(Type t) 80 { 81 if (t.ctype) 82 return t.ctype; 83 84 static type* visit(Type t) 85 { 86 type* tr = type_fake(totym(t)); 87 tr.Tcount++; 88 return tr; 89 } 90 91 static type* visitSArray(TypeSArray t) 92 { 93 auto ta = type_static_array(t.dim.toInteger(), Type_toCtype(t.next)); 94 ta.Tty |= ta.Tnext.Tty & mTYconst; 95 return ta; 96 } 97 98 static type* visitDArray(TypeDArray t) 99 { 100 type* tr = type_dyn_array(Type_toCtype(t.next)); 101 tr.Tident = t.toPrettyChars(true); 102 return tr; 103 } 104 105 static type* visitAArray(TypeAArray t) 106 { 107 type* tr = type_assoc_array(Type_toCtype(t.index), Type_toCtype(t.next)); 108 tr.Tident = t.toPrettyChars(true); 109 return tr; 110 } 111 112 static type* visitPointer(TypePointer t) 113 { 114 //printf("TypePointer::toCtype() %s\n", t.toChars()); 115 return type_pointer(Type_toCtype(t.next)); 116 } 117 118 static type* visitFunction(TypeFunction t) 119 { 120 const nparams = t.parameterList.length; 121 import dmd.common.string : SmallBuffer; 122 type*[10] tmp = void; 123 auto sb = SmallBuffer!(type*)(nparams, tmp[]); 124 type*[] types = sb[]; 125 126 foreach (i; 0 .. nparams) 127 { 128 Parameter p = t.parameterList[i]; 129 type* tp = Type_toCtype(p.type); 130 if (p.isReference()) 131 tp = type_allocn(TYnref, tp); 132 else if (p.isLazy()) 133 { 134 // Mangle as delegate 135 type* tf = type_function(TYnfunc, null, false, tp); 136 tp = type_delegate(tf); 137 tp.Tident = t.toPrettyChars(true); 138 } 139 types[i] = tp; 140 } 141 return type_function(totym(t), types, t.parameterList.varargs == VarArg.variadic, Type_toCtype(t.next)); 142 } 143 144 static type* visitDelegate(TypeDelegate t) 145 { 146 type* tr = type_delegate(Type_toCtype(t.next)); 147 tr.Tident = t.toPrettyChars(true); 148 return tr; 149 } 150 151 static type* visitStruct(TypeStruct t) 152 { 153 //printf("TypeStruct::toCtype() '%s'\n", t.sym.toChars()); 154 if (t.mod == 0) 155 { 156 // Create a new backend type 157 StructDeclaration sym = t.sym; 158 auto arg1type = sym.argType(0); 159 auto arg2type = sym.argType(1); 160 t.ctype = type_struct_class(sym.toPrettyChars(true), sym.alignsize, sym.structsize, arg1type ? Type_toCtype(arg1type) : null, arg2type ? Type_toCtype(arg2type) : null, sym.isUnionDeclaration() !is null, false, sym.isPOD() != 0, sym.hasNoFields); 161 /* Add in fields of the struct 162 * (after setting ctype to avoid infinite recursion) 163 */ 164 if (driverParams.symdebug && !global.errors) 165 { 166 foreach (v; sym.fields) 167 { 168 if (auto bf = v.isBitFieldDeclaration()) 169 symbol_struct_addBitField(cast(Symbol*)t.ctype.Ttag, v.ident.toChars(), Type_toCtype(v.type), v.offset, bf.fieldWidth, bf.bitOffset); 170 else 171 symbol_struct_addField(cast(Symbol*)t.ctype.Ttag, v.ident.toChars(), Type_toCtype(v.type), v.offset); 172 } 173 } 174 else 175 { 176 foreach (v; sym.fields) 177 { 178 if (auto bf = v.isBitFieldDeclaration()) 179 { 180 symbol_struct_hasBitFields(cast(Symbol*)t.ctype.Ttag); 181 break; 182 } 183 } 184 } 185 186 if (driverParams.symdebugref) 187 toDebug(sym); 188 189 return t.ctype; 190 } 191 192 // Copy mutable version of backend type and add modifiers 193 type* mctype = Type_toCtype(t.castMod(0)); 194 type* tr = type_alloc(tybasic(mctype.Tty)); 195 tr.Tcount++; 196 if (tr.Tty == TYstruct) 197 { 198 tr.Ttag = mctype.Ttag; // structure tag name 199 } 200 tr.Tty |= modToTym(t.mod); 201 //printf("t = %p, Tflags = x%x\n", ctype, ctype.Tflags); 202 return tr; 203 } 204 205 static type* visitEnum(TypeEnum t) 206 { 207 //printf("TypeEnum::toCtype() '%s'\n", t.sym.toChars()); 208 if (t.mod == 0) 209 { 210 EnumDeclaration sym = t.sym; 211 auto symMemtype = sym.memtype; 212 if (!symMemtype) 213 { 214 // https://issues.dlang.org/show_bug.cgi?id=13792 215 t.ctype = Type_toCtype(Type.tvoid); 216 } 217 else if (sym.ident == Id.__c_long || 218 sym.ident == Id.__c_complex_float || 219 sym.ident == Id.__c_complex_double || 220 sym.ident == Id.__c_complex_real) 221 { 222 t.ctype = type_fake(totym(t)); 223 t.ctype.Tcount++; 224 return t.ctype; 225 } 226 else if (symMemtype.toBasetype().ty == Tint32) 227 { 228 t.ctype = type_enum(sym.toPrettyChars(true), Type_toCtype(symMemtype)); 229 } 230 else 231 { 232 t.ctype = Type_toCtype(symMemtype); 233 } 234 235 if (driverParams.symdebugref) 236 toDebug(t.sym); 237 238 return t.ctype; 239 } 240 241 // Copy mutable version of backend type and add modifiers 242 type* mctype = Type_toCtype(t.castMod(0)); 243 if (tybasic(mctype.Tty) == TYenum) 244 { 245 Classsym* s = mctype.Ttag; 246 assert(s); 247 type* tr = type_allocn(TYenum, mctype.Tnext); 248 tr.Ttag = s; // enum tag name 249 tr.Tcount++; 250 tr.Tty |= modToTym(t.mod); 251 return tr; 252 } 253 //printf("t = %p, Tflags = x%x\n", t, t.Tflags); 254 return mctype; 255 } 256 257 static type* visitClass(TypeClass t) 258 { 259 if (t.mod == 0) 260 { 261 //printf("TypeClass::toCtype() %s\n", toChars()); 262 type* tc = type_struct_class(t.sym.toPrettyChars(true), t.sym.alignsize, t.sym.structsize, null, null, false, true, true, false); 263 t.ctype = type_pointer(tc); 264 /* Add in fields of the class 265 * (after setting ctype to avoid infinite recursion) 266 */ 267 if (driverParams.symdebug) 268 { 269 foreach (v; t.sym.fields) 270 { 271 symbol_struct_addField(cast(Symbol*)tc.Ttag, v.ident.toChars(), Type_toCtype(v.type), v.offset); 272 } 273 if (auto bc = t.sym.baseClass) 274 { 275 auto ptr_to_basetype = Type_toCtype(bc.type); 276 assert(ptr_to_basetype .Tty == TYnptr); 277 symbol_struct_addBaseClass(cast(Symbol*)tc.Ttag, ptr_to_basetype.Tnext, 0); 278 } 279 } 280 281 if (driverParams.symdebugref) 282 toDebug(t.sym); 283 return t.ctype; 284 } 285 286 // Copy mutable version of backend type and add modifiers 287 type* mctype = Type_toCtype(t.castMod(0)); 288 type* tr = type_allocn(tybasic(mctype.Tty), mctype.Tnext); // pointer to class instance 289 tr.Tcount++; 290 tr.Tty |= modToTym(t.mod); 291 return tr; 292 } 293 294 type* tr; 295 switch (t.ty) 296 { 297 default: tr = visit (t); break; 298 case Tsarray: tr = visitSArray (t.isTypeSArray()); break; 299 case Tarray: tr = visitDArray (t.isTypeDArray()); break; 300 case Taarray: tr = visitAArray (t.isTypeAArray()); break; 301 case Tpointer: tr = visitPointer (t.isTypePointer()); break; 302 case Tfunction: tr = visitFunction(t.isTypeFunction()); break; 303 case Tdelegate: tr = visitDelegate(t.isTypeDelegate()); break; 304 case Tstruct: tr = visitStruct (t.isTypeStruct()); break; 305 case Tenum: tr = visitEnum (t.isTypeEnum()); break; 306 case Tclass: tr = visitClass (t.isTypeClass()); break; 307 } 308 309 t.ctype = tr; 310 return tr; 311 }