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 _toctype.d)
9  */
10 
11 module ddmd.toctype;
12 
13 import core.stdc.stdlib;
14 
15 import ddmd.backend.cc : Classsym, Symbol;
16 import ddmd.backend.ty;
17 import ddmd.backend.type;
18 
19 import ddmd.declaration;
20 import ddmd.dstruct;
21 import ddmd.globals;
22 import ddmd.id;
23 import ddmd.mtype;
24 import ddmd.visitor;
25 
26 extern extern (C++) uint totym(Type tx);
27 
28 extern (C++) final class ToCtypeVisitor : Visitor
29 {
30     alias visit = super.visit;
31 public:
32     extern (D) this()
33     {
34     }
35 
36     override void visit(Type t)
37     {
38         t.ctype = type_fake(totym(t));
39         t.ctype.Tcount++;
40     }
41 
42     override void visit(TypeSArray t)
43     {
44         t.ctype = type_static_array(t.dim.toInteger(), Type_toCtype(t.next));
45     }
46 
47     override void visit(TypeDArray t)
48     {
49         t.ctype = type_dyn_array(Type_toCtype(t.next));
50         t.ctype.Tident = t.toPrettyChars(true);
51     }
52 
53     override void visit(TypeAArray t)
54     {
55         t.ctype = type_assoc_array(Type_toCtype(t.index), Type_toCtype(t.next));
56     }
57 
58     override void visit(TypePointer t)
59     {
60         //printf("TypePointer::toCtype() %s\n", t->toChars());
61         t.ctype = type_pointer(Type_toCtype(t.next));
62     }
63 
64     override void visit(TypeFunction t)
65     {
66         size_t nparams = Parameter.dim(t.parameters);
67         type*[10] tmp;
68         type** ptypes = tmp.ptr;
69         if (nparams > 10)
70             ptypes = cast(type**)malloc((type*).sizeof * nparams);
71         for (size_t i = 0; i < nparams; i++)
72         {
73             Parameter p = Parameter.getNth(t.parameters, i);
74             type* tp = Type_toCtype(p.type);
75             if (p.storageClass & (STCout | STCref))
76                 tp = type_allocn(TYnref, tp);
77             else if (p.storageClass & STClazy)
78             {
79                 // Mangle as delegate
80                 type* tf = type_function(TYnfunc, null, 0, false, tp);
81                 tp = type_delegate(tf);
82             }
83             ptypes[i] = tp;
84         }
85         t.ctype = type_function(totym(t), ptypes, nparams, t.varargs == 1, Type_toCtype(t.next));
86         if (nparams > 10)
87             free(ptypes);
88     }
89 
90     override void visit(TypeDelegate t)
91     {
92         t.ctype = type_delegate(Type_toCtype(t.next));
93     }
94 
95     void addMod(Type t)
96     {
97         switch (t.mod)
98         {
99         case 0:
100             assert(0);
101         case MODconst:
102         case MODwild:
103         case MODwildconst:
104             t.ctype.Tty |= mTYconst;
105             break;
106         case MODshared:
107             t.ctype.Tty |= mTYshared;
108             break;
109         case MODshared | MODconst:
110         case MODshared | MODwild:
111         case MODshared | MODwildconst:
112             t.ctype.Tty |= mTYshared | mTYconst;
113             break;
114         case MODimmutable:
115             t.ctype.Tty |= mTYimmutable;
116             break;
117         default:
118             assert(0);
119         }
120     }
121 
122     override void visit(TypeStruct t)
123     {
124         //printf("TypeStruct::toCtype() '%s'\n", t->sym->toChars());
125         if (t.mod == 0)
126         {
127             // Create a new backend type
128             StructDeclaration sym = t.sym;
129             if (sym.ident == Id.__c_long_double)
130             {
131                 t.ctype = type_fake(TYdouble);
132                 t.ctype.Tcount++;
133                 return;
134             }
135             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);
136             /* Add in fields of the struct
137              * (after setting ctype to avoid infinite recursion)
138              */
139             if (global.params.symdebug)
140             {
141                 for (size_t i = 0; i < sym.fields.dim; i++)
142                 {
143                     VarDeclaration v = sym.fields[i];
144                     symbol_struct_addField(cast(Symbol*)t.ctype.Ttag, v.ident.toChars(), Type_toCtype(v.type), v.offset);
145                 }
146             }
147             return;
148         }
149 
150         // Copy mutable version of backend type and add modifiers
151         type* mctype = Type_toCtype(t.castMod(0));
152         t.ctype = type_alloc(tybasic(mctype.Tty));
153         t.ctype.Tcount++;
154         if (t.ctype.Tty == TYstruct)
155         {
156             t.ctype.Ttag = mctype.Ttag; // structure tag name
157         }
158         addMod(t);
159         //printf("t = %p, Tflags = x%x\n", ctype, ctype->Tflags);
160     }
161 
162     override void visit(TypeEnum t)
163     {
164         //printf("TypeEnum::toCtype() '%s'\n", t->sym->toChars());
165         if (t.mod == 0)
166         {
167             if (!t.sym.memtype)
168             {
169                 // Bugzilla 13792
170                 t.ctype = Type_toCtype(Type.tvoid);
171             }
172             else if (t.sym.memtype.toBasetype().ty == Tint32)
173             {
174                 t.ctype = type_enum(t.sym.toPrettyChars(true), Type_toCtype(t.sym.memtype));
175             }
176             else
177             {
178                 t.ctype = Type_toCtype(t.sym.memtype);
179             }
180             return;
181         }
182 
183         // Copy mutable version of backend type and add modifiers
184         type* mctype = Type_toCtype(t.castMod(0));
185         if (tybasic(mctype.Tty) == TYenum)
186         {
187             Classsym* s = mctype.Ttag;
188             assert(s);
189             t.ctype = type_alloc(TYenum);
190             t.ctype.Ttag = s; // enum tag name
191             t.ctype.Tcount++;
192             t.ctype.Tnext = mctype.Tnext;
193             t.ctype.Tnext.Tcount++;
194             addMod(t);
195         }
196         else
197             t.ctype = mctype;
198         //printf("t = %p, Tflags = x%x\n", t, t->Tflags);
199     }
200 
201     override void visit(TypeClass t)
202     {
203         //printf("TypeClass::toCtype() %s\n", toChars());
204         type* tc = type_struct_class(t.sym.toPrettyChars(true), t.sym.alignsize, t.sym.structsize, null, null, false, true, true);
205         t.ctype = type_pointer(tc);
206         /* Add in fields of the class
207          * (after setting ctype to avoid infinite recursion)
208          */
209         if (global.params.symdebug)
210         {
211             for (size_t i = 0; i < t.sym.fields.dim; i++)
212             {
213                 VarDeclaration v = t.sym.fields[i];
214                 symbol_struct_addField(cast(Symbol*)tc.Ttag, v.ident.toChars(), Type_toCtype(v.type), v.offset);
215             }
216         }
217     }
218 }
219 
220 extern (C++) type* Type_toCtype(Type t)
221 {
222     if (!t.ctype)
223     {
224         scope ToCtypeVisitor v = new ToCtypeVisitor();
225         t.accept(v);
226     }
227     return t.ctype;
228 }