1 /** 2 * Convert a D type to a type the backend understands. 3 * 4 * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved 5 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 6 * License: $(LINK2 http://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.declaration; 24 import dmd.denum; 25 import dmd.dstruct; 26 import dmd.globals; 27 import dmd.glue; 28 import dmd.id; 29 import dmd.mtype; 30 import dmd.tocvdebug; 31 import dmd.visitor; 32 33 34 /******************* 35 * Determine backend tym bits corresponding to MOD 36 * Params: 37 * mod = mod bits 38 * Returns: 39 * corresponding tym_t bits 40 */ 41 tym_t modToTym(MOD mod) pure 42 { 43 switch (mod) 44 { 45 case 0: 46 return 0; 47 48 case MODFlags.const_: 49 case MODFlags.wild: 50 case MODFlags.wildconst: 51 return mTYconst; 52 53 case MODFlags.shared_: 54 return mTYshared; 55 56 case MODFlags.shared_ | MODFlags.const_: 57 case MODFlags.shared_ | MODFlags.wild: 58 case MODFlags.shared_ | MODFlags.wildconst: 59 return mTYshared | mTYconst; 60 61 case MODFlags.immutable_: 62 return mTYimmutable; 63 64 default: 65 assert(0); 66 } 67 } 68 69 70 /************************************ 71 * Convert front end type `t` to backend type `t.ctype`. 72 * Memoize the result. 73 * Params: 74 * t = front end `Type` 75 * Returns: 76 * back end equivalent `type` 77 */ 78 extern (C++) type* Type_toCtype(Type t) 79 { 80 if (!t.ctype) 81 { 82 scope ToCtypeVisitor v = new ToCtypeVisitor(); 83 t.accept(v); 84 } 85 return t.ctype; 86 } 87 88 private extern (C++) final class ToCtypeVisitor : Visitor 89 { 90 alias visit = Visitor.visit; 91 public: 92 extern (D) this() 93 { 94 } 95 96 override void visit(Type t) 97 { 98 t.ctype = type_fake(totym(t)); 99 t.ctype.Tcount++; 100 } 101 102 override void visit(TypeSArray t) 103 { 104 t.ctype = type_static_array(t.dim.toInteger(), Type_toCtype(t.next)); 105 } 106 107 override void visit(TypeDArray t) 108 { 109 t.ctype = type_dyn_array(Type_toCtype(t.next)); 110 t.ctype.Tident = t.toPrettyChars(true); 111 } 112 113 override void visit(TypeAArray t) 114 { 115 t.ctype = type_assoc_array(Type_toCtype(t.index), Type_toCtype(t.next)); 116 t.ctype.Tident = t.toPrettyChars(true); 117 } 118 119 override void visit(TypePointer t) 120 { 121 //printf("TypePointer::toCtype() %s\n", t.toChars()); 122 t.ctype = type_pointer(Type_toCtype(t.next)); 123 } 124 125 override void visit(TypeFunction t) 126 { 127 const nparams = t.parameterList.length; 128 type*[10] tmp = void; 129 type** ptypes = (nparams <= tmp.length) 130 ? tmp.ptr 131 : cast(type**)Mem.check(malloc((type*).sizeof * nparams)); 132 type*[] types = ptypes[0 .. nparams]; 133 134 foreach (i; 0 .. nparams) 135 { 136 Parameter p = t.parameterList[i]; 137 type* tp = Type_toCtype(p.type); 138 if (p.isReference()) 139 tp = type_allocn(TYnref, tp); 140 else if (p.storageClass & STC.lazy_) 141 { 142 // Mangle as delegate 143 type* tf = type_function(TYnfunc, null, false, tp); 144 tp = type_delegate(tf); 145 } 146 types[i] = tp; 147 } 148 t.ctype = type_function(totym(t), types, t.parameterList.varargs == VarArg.variadic, Type_toCtype(t.next)); 149 if (types.ptr != tmp.ptr) 150 free(types.ptr); 151 } 152 153 override void visit(TypeDelegate t) 154 { 155 t.ctype = type_delegate(Type_toCtype(t.next)); 156 } 157 158 override void visit(TypeStruct t) 159 { 160 //printf("TypeStruct::toCtype() '%s'\n", t.sym.toChars()); 161 if (t.mod == 0) 162 { 163 // Create a new backend type 164 StructDeclaration sym = t.sym; 165 auto arg1type = sym.argType(0); 166 auto arg2type = sym.argType(1); 167 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); 168 /* Add in fields of the struct 169 * (after setting ctype to avoid infinite recursion) 170 */ 171 if (global.params.symdebug && !global.errors) 172 { 173 foreach (v; sym.fields) 174 { 175 symbol_struct_addField(cast(Symbol*)t.ctype.Ttag, v.ident.toChars(), Type_toCtype(v.type), v.offset); 176 } 177 } 178 179 if (global.params.symdebugref) 180 toDebug(sym); 181 182 return; 183 } 184 185 // Copy mutable version of backend type and add modifiers 186 type* mctype = Type_toCtype(t.castMod(0)); 187 t.ctype = type_alloc(tybasic(mctype.Tty)); 188 t.ctype.Tcount++; 189 if (t.ctype.Tty == TYstruct) 190 { 191 t.ctype.Ttag = mctype.Ttag; // structure tag name 192 } 193 t.ctype.Tty |= modToTym(t.mod); 194 //printf("t = %p, Tflags = x%x\n", ctype, ctype.Tflags); 195 } 196 197 override void visit(TypeEnum t) 198 { 199 //printf("TypeEnum::toCtype() '%s'\n", t.sym.toChars()); 200 if (t.mod == 0) 201 { 202 EnumDeclaration sym = t.sym; 203 auto symMemtype = sym.memtype; 204 if (!symMemtype) 205 { 206 // https://issues.dlang.org/show_bug.cgi?id=13792 207 t.ctype = Type_toCtype(Type.tvoid); 208 } 209 else if (sym.ident == Id.__c_long || 210 sym.ident == Id.__c_complex_float || 211 sym.ident == Id.__c_complex_double || 212 sym.ident == Id.__c_complex_real) 213 { 214 t.ctype = type_fake(totym(t)); 215 t.ctype.Tcount++; 216 return; 217 } 218 else if (symMemtype.toBasetype().ty == Tint32) 219 { 220 t.ctype = type_enum(sym.toPrettyChars(true), Type_toCtype(symMemtype)); 221 } 222 else 223 { 224 t.ctype = Type_toCtype(symMemtype); 225 } 226 227 if (global.params.symdebugref) 228 toDebug(t.sym); 229 230 return; 231 } 232 233 // Copy mutable version of backend type and add modifiers 234 type* mctype = Type_toCtype(t.castMod(0)); 235 if (tybasic(mctype.Tty) == TYenum) 236 { 237 Classsym* s = mctype.Ttag; 238 assert(s); 239 t.ctype = type_allocn(TYenum, mctype.Tnext); 240 t.ctype.Ttag = s; // enum tag name 241 t.ctype.Tcount++; 242 t.ctype.Tty |= modToTym(t.mod); 243 } 244 else 245 t.ctype = mctype; 246 247 //printf("t = %p, Tflags = x%x\n", t, t.Tflags); 248 } 249 250 override void visit(TypeClass t) 251 { 252 if (t.mod == 0) 253 { 254 //printf("TypeClass::toCtype() %s\n", toChars()); 255 type* tc = type_struct_class(t.sym.toPrettyChars(true), t.sym.alignsize, t.sym.structsize, null, null, false, true, true, false); 256 t.ctype = type_pointer(tc); 257 /* Add in fields of the class 258 * (after setting ctype to avoid infinite recursion) 259 */ 260 if (global.params.symdebug) 261 { 262 foreach (v; t.sym.fields) 263 { 264 symbol_struct_addField(cast(Symbol*)tc.Ttag, v.ident.toChars(), Type_toCtype(v.type), v.offset); 265 } 266 } 267 268 if (global.params.symdebugref) 269 toDebug(t.sym); 270 return; 271 } 272 273 // Copy mutable version of backend type and add modifiers 274 type* mctype = Type_toCtype(t.castMod(0)); 275 t.ctype = type_allocn(tybasic(mctype.Tty), mctype.Tnext); // pointer to class instance 276 t.ctype.Tcount++; 277 t.ctype.Tty |= modToTym(t.mod); 278 } 279 }