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.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 5
    switch (mod)
44
    {
45 5
        case 0:
46 5
            return 0;
47

48 5
        case MODFlags.const_:
49 5
        case MODFlags.wild:
50 5
        case MODFlags.wildconst:
51 5
            return mTYconst;
52

53 5
        case MODFlags.shared_:
54 5
            return mTYshared;
55

56 5
        case MODFlags.shared_ | MODFlags.const_:
57 5
        case MODFlags.shared_ | MODFlags.wild:
58 5
        case MODFlags.shared_ | MODFlags.wildconst:
59 5
            return mTYshared | mTYconst;
60

61 5
        case MODFlags.immutable_:
62 5
            return mTYimmutable;
63

64 0
        default:
65 0
            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 5
    if (!t.ctype)
81
    {
82 5
        scope ToCtypeVisitor v = new ToCtypeVisitor();
83 5
        t.accept(v);
84
    }
85 5
    return t.ctype;
86
}
87

88
private extern (C++) final class ToCtypeVisitor : Visitor
89
{
90
    alias visit = Visitor.visit;
91
public:
92 5
    extern (D) this()
93
    {
94
    }
95

96
    override void visit(Type t)
97
    {
98 5
        t.ctype = type_fake(totym(t));
99 5
        t.ctype.Tcount++;
100
    }
101

102
    override void visit(TypeSArray t)
103
    {
104 5
        t.ctype = type_static_array(t.dim.toInteger(), Type_toCtype(t.next));
105
    }
106

107
    override void visit(TypeDArray t)
108
    {
109 5
        t.ctype = type_dyn_array(Type_toCtype(t.next));
110 5
        t.ctype.Tident = t.toPrettyChars(true);
111
    }
112

113
    override void visit(TypeAArray t)
114
    {
115 5
        t.ctype = type_assoc_array(Type_toCtype(t.index), Type_toCtype(t.next));
116 5
        t.ctype.Tident = t.toPrettyChars(true);
117
    }
118

119
    override void visit(TypePointer t)
120
    {
121
        //printf("TypePointer::toCtype() %s\n", t.toChars());
122 5
        t.ctype = type_pointer(Type_toCtype(t.next));
123
    }
124

125
    override void visit(TypeFunction t)
126
    {
127 5
        const nparams = t.parameterList.length;
128 5
        type*[10] tmp = void;
129 5
        type** ptypes = (nparams <= tmp.length)
130 5
                        ? tmp.ptr
131 5
                        : cast(type**)Mem.check(malloc((type*).sizeof * nparams));
132 5
        type*[] types = ptypes[0 .. nparams];
133

134 5
        foreach (i; 0 .. nparams)
135
        {
136 5
            Parameter p = t.parameterList[i];
137 5
            type* tp = Type_toCtype(p.type);
138 5
            if (p.isReference())
139 5
                tp = type_allocn(TYnref, tp);
140 5
            else if (p.storageClass & STC.lazy_)
141
            {
142
                // Mangle as delegate
143 5
                type* tf = type_function(TYnfunc, null, false, tp);
144 5
                tp = type_delegate(tf);
145
            }
146 5
            types[i] = tp;
147
        }
148 5
        t.ctype = type_function(totym(t), types, t.parameterList.varargs == VarArg.variadic, Type_toCtype(t.next));
149 5
        if (types.ptr != tmp.ptr)
150 5
            free(types.ptr);
151
    }
152

153
    override void visit(TypeDelegate t)
154
    {
155 5
        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 5
        if (t.mod == 0)
162
        {
163
            // Create a new backend type
164 5
            StructDeclaration sym = t.sym;
165 5
            auto arg1type = sym.argType(0);
166 5
            auto arg2type = sym.argType(1);
167 5
            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 5
            if (global.params.symdebug && !global.errors)
172
            {
173 5
                foreach (v; sym.fields)
174
                {
175 5
                    symbol_struct_addField(cast(Symbol*)t.ctype.Ttag, v.ident.toChars(), Type_toCtype(v.type), v.offset);
176
                }
177
            }
178

179 5
            if (global.params.symdebugref)
180 5
                toDebug(sym);
181

182 5
            return;
183
        }
184

185
        // Copy mutable version of backend type and add modifiers
186 5
        type* mctype = Type_toCtype(t.castMod(0));
187 5
        t.ctype = type_alloc(tybasic(mctype.Tty));
188 5
        t.ctype.Tcount++;
189 5
        if (t.ctype.Tty == TYstruct)
190
        {
191 5
            t.ctype.Ttag = mctype.Ttag; // structure tag name
192
        }
193 5
        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 5
        if (t.mod == 0)
201
        {
202 5
            EnumDeclaration sym = t.sym;
203 5
            auto symMemtype = sym.memtype;
204 5
            if (!symMemtype)
205
            {
206
                // https://issues.dlang.org/show_bug.cgi?id=13792
207 5
                t.ctype = Type_toCtype(Type.tvoid);
208
            }
209 5
            else if (sym.ident == Id.__c_long)
210
            {
211 2
                t.ctype = type_fake(totym(t));
212 2
                t.ctype.Tcount++;
213 2
                return;
214
            }
215 5
            else if (symMemtype.toBasetype().ty == Tint32)
216
            {
217 5
                t.ctype = type_enum(sym.toPrettyChars(true), Type_toCtype(symMemtype));
218
            }
219
            else
220
            {
221 5
                t.ctype = Type_toCtype(symMemtype);
222
            }
223

224 5
            if (global.params.symdebugref)
225 5
                toDebug(t.sym);
226

227 5
            return;
228
        }
229

230
        // Copy mutable version of backend type and add modifiers
231 5
        type* mctype = Type_toCtype(t.castMod(0));
232 5
        if (tybasic(mctype.Tty) == TYenum)
233
        {
234 5
            Classsym* s = mctype.Ttag;
235 5
            assert(s);
236 5
            t.ctype = type_allocn(TYenum, mctype.Tnext);
237 5
            t.ctype.Ttag = s; // enum tag name
238 5
            t.ctype.Tcount++;
239 5
            t.ctype.Tty |= modToTym(t.mod);
240
        }
241
        else
242 5
            t.ctype = mctype;
243

244
        //printf("t = %p, Tflags = x%x\n", t, t.Tflags);
245
    }
246

247
    override void visit(TypeClass t)
248
    {
249 5
        if (t.mod == 0)
250
        {
251
            //printf("TypeClass::toCtype() %s\n", toChars());
252 5
            type* tc = type_struct_class(t.sym.toPrettyChars(true), t.sym.alignsize, t.sym.structsize, null, null, false, true, true, false);
253 5
            t.ctype = type_pointer(tc);
254
            /* Add in fields of the class
255
             * (after setting ctype to avoid infinite recursion)
256
             */
257 5
            if (global.params.symdebug)
258
            {
259 5
                foreach (v; t.sym.fields)
260
                {
261 5
                    symbol_struct_addField(cast(Symbol*)tc.Ttag, v.ident.toChars(), Type_toCtype(v.type), v.offset);
262
                }
263
            }
264

265 5
            if (global.params.symdebugref)
266 5
                toDebug(t.sym);
267 5
            return;
268
        }
269

270
        // Copy mutable version of backend type and add modifiers
271 5
        type* mctype = Type_toCtype(t.castMod(0));
272 5
        t.ctype = type_allocn(tybasic(mctype.Tty), mctype.Tnext); // pointer to class instance
273 5
        t.ctype.Tcount++;
274 5
        t.ctype.Tty |= modToTym(t.mod);
275
    }
276
}

Read our documentation on viewing source code .

Loading