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