fix calling convention and arg types
[m6w6/ext-psi] / src / types / decl_type.c
1 /*******************************************************************************
2 Copyright (c) 2016, Michael Wallner <mike@php.net>.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *******************************************************************************/
25
26 #include "php_psi_stdinc.h"
27 #include "token.h"
28 #include "data.h"
29
30 #define PSI_STD_TYPES
31 #include "php_psi_posix.h"
32
33 struct psi_decl_type *psi_decl_type_init(token_t type, zend_string *name)
34 {
35 struct psi_decl_type *t = pecalloc(1, sizeof(*t), 1);
36 t->type = type;
37 t->name = zend_string_copy(name);
38 return t;
39 }
40
41 void psi_decl_type_free(struct psi_decl_type **type_ptr)
42 {
43 if (*type_ptr) {
44 struct psi_decl_type *type = *type_ptr;
45
46 *type_ptr = NULL;
47 psi_token_free(&type->token);
48 if (type->type == PSI_T_FUNCTION) {
49 psi_decl_free(&type->real.func);
50 }
51 zend_string_release(type->name);
52 free(type);
53 }
54 }
55
56 struct psi_decl_type *psi_decl_type_copy(struct psi_decl_type *src)
57 {
58 struct psi_decl_type *dst = pecalloc(1, sizeof(*dst), 1);
59
60 dst->type = src->type;
61 if (src->name) {
62 dst->name = zend_string_copy(src->name);
63 }
64 if (src->token) {
65 dst->token = psi_token_copy(src->token);
66 }
67 return dst;
68 }
69
70 struct psi_plist *psi_decl_type_get_args(struct psi_decl_type *dtyp,
71 struct psi_decl_type **real_typ_ptr)
72 {
73 struct psi_decl_type *var_typ;
74
75 var_typ = psi_decl_type_get_real(dtyp);
76 if (real_typ_ptr) {
77 *real_typ_ptr = var_typ;
78 }
79
80 switch (var_typ->type) {
81 case PSI_T_STRUCT:
82 return var_typ->real.strct->args;
83 case PSI_T_UNION:
84 return var_typ->real.unn->args;
85 default:
86 return NULL;
87 }
88 }
89
90 size_t psi_decl_type_get_size(struct psi_decl_type *dtyp,
91 struct psi_decl_type **real_typ_ptr)
92 {
93 struct psi_decl_type *var_typ;
94
95 var_typ = psi_decl_type_get_real(dtyp);
96 if (real_typ_ptr) {
97 *real_typ_ptr = var_typ;
98 }
99
100 switch (var_typ->type) {
101 case PSI_T_STRUCT:
102 return var_typ->real.strct ? var_typ->real.strct->size : 0;
103 case PSI_T_UNION:
104 return var_typ->real.unn ? var_typ->real.unn->size : 0;
105 default:
106 return psi_t_size(var_typ->type);
107 }
108 }
109
110 bool psi_decl_type_get_alias(struct psi_decl_type *type, struct psi_plist *defs)
111 {
112 size_t i = 0;
113 struct psi_std_type *stdtyp;
114 struct psi_decl_arg *def;
115
116 if (type->real.def) {
117 return true;
118 }
119 if (defs) {
120 while (psi_plist_get(defs, i++, &def)) {
121 if (zend_string_equals(def->var->name, type->name)) {
122 type->real.def = def;
123 return true;
124 }
125 }
126 }
127 for (stdtyp = &psi_std_types[0]; stdtyp->type_tag; ++stdtyp) {
128 if (!strcmp(type->name->val, stdtyp->alias ?: stdtyp->type_name)) {
129 type->type = stdtyp->type_tag;
130 return true;
131 }
132 }
133
134 return false;
135 }
136
137 bool psi_decl_type_get_struct(struct psi_decl_type *type, struct psi_plist *structs)
138 {
139 size_t i = 0;
140 struct psi_decl_struct *s;
141
142 if (type->real.strct) {
143 return true;
144 }
145 if (structs) {
146 while (psi_plist_get(structs, i++, &s)) {
147 if (zend_string_equals(s->name, type->name)) {
148 type->real.strct = s;
149 return true;
150 }
151 }
152 }
153 return false;
154 }
155
156 bool psi_decl_type_get_union(struct psi_decl_type *type, struct psi_plist *unions)
157 {
158 size_t i = 0;
159 struct psi_decl_union *u;
160
161 if (type->real.unn) {
162 return true;
163 }
164 if (unions) {
165 while (psi_plist_get(unions, i++, &u)) {
166 if (zend_string_equals(u->name, type->name)) {
167 type->real.unn = u;
168 return true;
169 }
170 }
171 }
172 return false;
173 }
174
175 bool psi_decl_type_get_enum(struct psi_decl_type *type, struct psi_plist *enums)
176 {
177 size_t i = 0;
178 struct psi_decl_enum *e;
179
180 if (type->real.enm) {
181 return true;
182 }
183 if (enums) {
184 while (psi_plist_get(enums, i++, &e)) {
185 if (zend_string_equals(e->name, type->name)) {
186 type->real.enm = e;
187 return true;
188 }
189 }
190 }
191 return false;
192 }
193
194 bool psi_decl_type_get_decl(struct psi_decl_type *type, struct psi_plist *decls)
195 {
196 size_t i = 0;
197 struct psi_decl *decl;
198
199 if (type->real.func) {
200 return true;
201 }
202 if (decls) {
203 while (psi_plist_get(decls, i++, &decl)) {
204 if (zend_string_equals(decl->func->var->name, type->name)) {
205 type->real.func = decl;
206 return true;
207 }
208 }
209 }
210 return false;
211 }
212
213 bool psi_decl_type_validate(struct psi_data *data, struct psi_decl_type *type,
214 struct psi_decl_arg *def, struct psi_validate_scope *scope)
215 {
216 if (psi_decl_type_is_weak(type)) {
217 if (!psi_decl_type_get_alias(type, data->types)) {
218 if (!psi_validate_scope_has_type(scope, type->name)) {
219 return false;
220 }
221 type->real.def = psi_validate_scope_get_type(scope, type->name);
222 }
223 if (type->real.def) {
224 if (!psi_decl_type_validate(data, type->real.def->type,
225 type->real.def, scope)) {
226 return false;
227 }
228 if (def) {
229 def->var->pointer_level += type->real.def->var->pointer_level;
230 }
231 }
232 return true;
233 }
234
235 switch (type->type) {
236 case PSI_T_STRUCT:
237 if (!psi_decl_type_get_struct(type, data->structs)) {
238 if (psi_validate_scope_has_struct(scope, type->name)) {
239 type->real.strct = psi_validate_scope_get_struct(scope, type->name);
240 } else if (def && def->var->pointer_level) {
241 return true;
242 } else {
243 data->error(data, type->token, PSI_WARNING,
244 "Unknown struct '%s'", type->name->val);
245 return false;
246 }
247 }
248 if (!psi_decl_struct_validate(data, type->real.strct, scope)) {
249 return false;
250 }
251 break;
252 case PSI_T_UNION:
253 if (!psi_decl_type_get_union(type, data->unions)) {
254 if (psi_validate_scope_has_union(scope, type->name)) {
255 type->real.unn = psi_validate_scope_get_union(scope, type->name);
256 } else if (def && def->var->pointer_level) {
257 return true;
258 } else {
259 data->error(data, type->token, PSI_WARNING,
260 "Unknown union '%s'", type->name->val);
261 return false;
262 }
263 }
264 if (!psi_decl_union_validate(data, type->real.unn, scope)) {
265 return false;
266 }
267 break;
268 case PSI_T_ENUM:
269 if (!psi_decl_type_get_enum(type, data->enums)) {
270 data->error(data, type->token, PSI_WARNING,
271 "Unknown enum '%s'", type->name->val);
272 return false;
273 }
274 break;
275 case PSI_T_FUNCTION:
276 if (!psi_decl_type_get_decl(type, data->decls)) {
277 data->error(data, type->token, PSI_WARNING,
278 "Unknown decl '%s'", type->name->val);
279 return false;
280 }
281 if (!psi_decl_validate_nodl(data, type->real.func, scope)) {
282 return false;
283 }
284 break;
285 default:
286 break;
287 }
288
289 return true;
290 }
291
292 void psi_decl_type_dump_args_with_layout(struct psi_dump *dump, struct psi_plist *args,
293 unsigned level)
294 {
295 size_t i = 0;
296
297 PSI_DUMP(dump, " {\n");
298 if (args) {
299 struct psi_decl_arg *sarg;
300
301 ++level;
302 while (psi_plist_get(args, i++, &sarg)) {
303 PSI_DUMP(dump, "%s", psi_t_indent(level));
304 psi_decl_arg_dump(dump, sarg, level);
305 if (sarg->layout) {
306 if (sarg->layout->bfw) {
307 PSI_DUMP(dump, ":%zu", sarg->layout->bfw->len);
308 }
309 PSI_DUMP(dump, "::(%zu, %zu);\n", sarg->layout->pos,
310 sarg->layout->len);
311 } else {
312 PSI_DUMP(dump, ";\n");
313 }
314 }
315 --level;
316 }
317 PSI_DUMP(dump, "%s", psi_t_indent(level));
318 PSI_DUMP(dump, "}");
319 }
320
321 void psi_decl_type_dump(struct psi_dump *dump, struct psi_decl_type *t, unsigned level)
322 {
323 switch (t->type) {
324 case PSI_T_POINTER:
325 PSI_DUMP(dump, "%s *", t->name->val);
326 return;
327
328 case PSI_T_ENUM:
329 if (psi_decl_type_is_anon(t->name, "enum")) {
330 psi_decl_enum_dump(dump, t->real.enm, level);
331 return;
332 }
333 PSI_DUMP(dump, "enum ");
334 break;
335
336 case PSI_T_STRUCT:
337 PSI_DUMP(dump, "struct ");
338 if (psi_decl_type_is_anon(t->name, "struct")) {
339 PSI_DUMP(dump, "/*::(%zu, %zu)*/", t->real.strct->align, t->real.strct->size);
340 psi_decl_type_dump_args_with_layout(dump, t->real.strct->args, level);
341 return;
342 }
343 break;
344
345 case PSI_T_UNION:
346 PSI_DUMP(dump, "union ");
347 if (psi_decl_type_is_anon(t->name, "union")) {
348 PSI_DUMP(dump, "/*::(%zu, %zu)*/", t->real.unn->align, t->real.unn->size);
349 psi_decl_type_dump_args_with_layout(dump, t->real.unn->args, level);
350 return;
351 }
352 break;
353
354 case PSI_T_FUNCTION:
355 psi_decl_type_dump(dump, t->real.func->func->type, level);
356 return;
357
358 default:
359 break;
360 }
361
362 PSI_DUMP(dump, "%s", t->name->val);
363 }
364
365 int psi_decl_type_is_weak(struct psi_decl_type *type)
366 {
367 switch (type->type) {
368 case PSI_T_CHAR:
369 case PSI_T_SHORT:
370 case PSI_T_INT:
371 case PSI_T_LONG:
372 case PSI_T_UNSIGNED:
373 case PSI_T_SIGNED:
374 case PSI_T_NAME:
375 return type->type;
376 default:
377 return 0;
378 }
379 }
380
381 struct psi_decl_type *psi_decl_type_get_real(struct psi_decl_type *type)
382 {
383 while (psi_decl_type_is_weak(type) && type->real.def) {
384 type = type->real.def->type;
385 }
386 return type;
387 }
388
389 size_t psi_decl_type_get_align(struct psi_decl_type *t)
390 {
391 struct psi_decl_type *real = psi_decl_type_get_real(t);
392 size_t align;
393
394 switch (real->type) {
395 case PSI_T_STRUCT:
396 align = psi_decl_struct_get_align(real->real.strct);
397 break;
398 case PSI_T_UNION:
399 align = psi_decl_union_get_align(real->real.unn);
400 break;
401 case PSI_T_ENUM:
402 default:
403 align = psi_t_alignment(real->type);
404 break;
405 }
406
407 return align;
408 }
409
410 size_t psi_decl_type_get_args_align(struct psi_plist *args)
411 {
412 size_t i = 0, maxalign = 0;
413 struct psi_decl_arg *darg;
414
415 while (psi_plist_get(args, i++, &darg)) {
416 size_t align = psi_decl_arg_get_align(darg);
417
418 if (align > maxalign) {
419 maxalign = align;
420 }
421 }
422
423 return maxalign;
424 }
425