708b36f1e950ab581121ac768c82b15dece6934f
[m6w6/ext-psi] / src / context_dump.c
1 #include "php.h"
2 #include "php_psi.h"
3
4 #include "libjit.h"
5 #include "libffi.h"
6
7 static inline void dump_decl_type(int fd, decl_type *t) {
8 const char *pre;
9
10 switch (t->type) {
11 case PSI_T_STRUCT:
12 pre = "struct ";
13 break;
14 default:
15 pre = "";
16 }
17 dprintf(fd, "%s%s", pre, t->name);
18 }
19
20 static inline void dump_decl_var(int fd, decl_var *v) {
21 dprintf(fd, "%.*s%s", v->pointer_level-!!v->array_size, "**********", v->name);
22 if (v->array_size) {
23 dprintf(fd, "[%u]", v->array_size);
24 }
25 }
26
27 static inline void dump_decl_arg(int fd, decl_arg *a) {
28 dump_decl_type(fd, a->type);
29 dprintf(fd, " ");
30 dump_decl_var(fd, a->var);
31 }
32
33 static inline void dump_level(int fd, unsigned level) {
34 dprintf(fd, "%.*s", level > 10 ? 10 : level, "\t\t\t\t\t\t\t\t\t\t");
35 }
36
37 static inline void dump_num_exp(int fd, num_exp *exp) {
38 while (exp) {
39 switch (exp->t) {
40 case PSI_T_NUMBER:
41 dprintf(fd, "%s", exp->u.numb);
42 break;
43 case PSI_T_NSNAME:
44 dprintf(fd, "%s", exp->u.cnst->name);
45 break;
46 case PSI_T_NAME:
47 dump_decl_var(fd, exp->u.dvar);
48 break;
49 case PSI_T_ENUM:
50 dprintf(fd, "%s", exp->u.enm->name);
51 break;
52 EMPTY_SWITCH_DEFAULT_CASE();
53 }
54 if (exp->operand) {
55 char op;
56
57 switch (exp->operator) {
58 case PSI_T_PLUS: op = '+'; break;
59 case PSI_T_MINUS: op = '-'; break;
60 case PSI_T_ASTERISK:op = '*'; break;
61 case PSI_T_SLASH: op = '/'; break;
62 EMPTY_SWITCH_DEFAULT_CASE();
63 }
64 dprintf(fd, " %c ", op);
65 }
66 exp = exp->operand;
67 }
68 }
69
70 static inline void dump_impl_set_value(int fd, set_value *set, unsigned level, int last) {
71 size_t i;
72
73 if (level > 1) {
74 /* only if not directly after `set ...` */
75 dump_level(fd, level);
76 }
77
78 if (set->func->type == PSI_T_ELLIPSIS) {
79 dprintf(fd, "%s(", set->outer.set->func->name);
80 } else {
81 dprintf(fd, "%s(", set->func->name);
82 }
83
84 for (i = 0; i < set->vars->count; ++i) {
85 decl_var *svar = set->vars->vars[i];
86 if (i) {
87 dprintf(fd, ", ");
88 }
89 dump_decl_var(fd, svar);
90 }
91
92 if (set->func->type == PSI_T_ELLIPSIS) {
93 dprintf(fd, ", ...");
94 }
95 if (set->num) {
96 dprintf(fd, ", ");
97 dump_num_exp(fd, set->num);
98 }
99 if (set->inner && set->func->type != PSI_T_ELLIPSIS) {
100 dprintf(fd, ",\n");
101 for (i = 0; i < set->count; ++i) {
102 dump_impl_set_value(fd, set->inner[i], level+1, i == (set->count - 1));
103 }
104 /* only if inner stmts, i.e. with new lines, were dumped */
105 dump_level(fd, level);
106 }
107 if (level > 1) {
108 dprintf(fd, ")%s\n", last ? "" : ",");
109 } else {
110 dprintf(fd, ");");
111 }
112 }
113
114 static inline void dump_typedef(int fd, decl_arg *tdef) {
115 dprintf(fd, "typedef ");
116 dump_decl_arg(fd, tdef);
117 /*
118 dump_decl_type(fd, tdef->type);
119 dprintf(fd, " %s%s;", tdef->type->type == PSI_T_POINTER ? "*":"",
120 tdef->alias);
121 */
122 }
123
124 static inline void dump_typedefs(int fd, decl_typedefs *defs) {
125 size_t i;
126
127 for (i = 0; i < defs->count; ++i) {
128 decl_arg *tdef = defs->list[i];
129
130 dump_typedef(fd, tdef);
131 dprintf(fd, "\n");
132 }
133 }
134
135 static inline void dump_struct(int fd, decl_struct *strct) {
136 size_t j;
137
138 dprintf(fd, "struct %s::(%zu)", strct->name, strct->size);
139 if (strct->args && strct->args->count) {
140 dprintf(fd, " {\n");
141 for (j = 0; j < strct->args->count; ++j) {
142 decl_arg *sarg = strct->args->args[j];
143
144 dprintf(fd, "\t");
145 dump_decl_arg(fd, sarg);
146 dprintf(fd, "::(%zu, %zu);\n", sarg->layout->pos, sarg->layout->len);
147 }
148 dprintf(fd, "}");
149 } else {
150 dprintf(fd, ";");
151 }
152 }
153
154 static inline void dump_structs(int fd, decl_structs *structs) {
155 size_t i;
156
157 for (i = 0; i < structs->count; ++i) {
158 decl_struct *strct = structs->list[i];
159
160 dump_struct(fd, strct);
161 dprintf(fd, "\n");
162 }
163 }
164
165 static inline void dump_enum(int fd, decl_enum *e) {
166 size_t j;
167
168 dprintf(fd, "enum %s {\n", e->name);
169 for (j = 0; j < e->items->count; ++j) {
170 decl_enum_item *i = e->items->list[j];
171
172 if (j) {
173 dprintf(fd, ",\n");
174 }
175 dprintf(fd, "\t%s", i->name);
176 if (i->num && i->num != &i->inc) {
177 dprintf(fd, " = ");
178 dump_num_exp(fd, i->num);
179 }
180 }
181 dprintf(fd, "\n}");
182 }
183
184 static inline void dump_enums(int fd, decl_enums *enums) {
185 size_t i;
186
187 for (i = 0; i < enums->count; ++i) {
188 decl_enum *e = enums->list[i];
189
190 dump_enum(fd, e);
191 dprintf(fd, "\n");
192 }
193 }
194 static inline void dump_constant(int fd, constant *cnst) {
195 dprintf(fd, "const %s %s = ", cnst->type->name, cnst->name);
196 if (cnst->val->type == PSI_T_QUOTED_STRING) {
197 dprintf(fd, "\"%s\";", cnst->val->text);
198 } else {
199 dprintf(fd, "%s;", cnst->val->text);
200 }
201 }
202
203 static inline void dump_constants(int fd, constants *consts) {
204 size_t i;
205
206 for (i = 0; i < consts->count; ++i) {
207 constant *cnst = consts->list[i];
208
209 dump_constant(fd, cnst);
210 dprintf(fd, "\n");
211 }
212 }
213
214 static inline void dump_decl(int fd, decl *decl) {
215 size_t j;
216
217 dprintf(fd, "%s ", decl->abi->convention);
218 dump_decl_arg(fd, decl->func);
219 dprintf(fd, "(");
220 if (decl->args) {
221 for (j = 0; j < decl->args->count; ++j) {
222 if (j) {
223 dprintf(fd, ", ");
224 }
225 dump_decl_arg(fd, decl->args->args[j]);
226 }
227 if (decl->args->varargs) {
228 dprintf(fd, ", ...");
229 }
230 }
231 dprintf(fd, ");");
232 }
233
234 static inline void dump_decls(int fd, decls *decls) {
235 size_t i;
236
237 for (i = 0; i < decls->count; ++i) {
238 decl *decl = decls->list[i];
239
240 dump_decl(fd, decl);
241 dprintf(fd, "\n");
242 }
243 }
244
245 static inline void dump_impl_func(int fd, impl_func *func) {
246 size_t j;
247
248 dprintf(fd, "function %s(", func->name);
249 if (func->args) {
250 for (j = 0; j < func->args->count; ++j) {
251 impl_arg *iarg = func->args->args[j];
252
253 dprintf(fd, "%s%s %s$%s",
254 j ? ", " : "",
255 iarg->type->name,
256 iarg->var->reference ? "&" : "",
257 iarg->var->name);
258 if (iarg->def) {
259 dprintf(fd, " = %s", iarg->def->text);
260 }
261 }
262 if (func->args->vararg.name) {
263 impl_arg *vararg = func->args->vararg.name;
264
265 dprintf(fd, ", %s %s...$%s",
266 vararg->type->name,
267 vararg->var->reference ? "&" : "",
268 vararg->var->name);
269 }
270 }
271 dprintf(fd, ") : %s%s",
272 func->return_reference ? "&":"",
273 func->return_type->name);
274 }
275
276 static inline void dump_impl_let_stmt(int fd, let_stmt *let) {
277 dprintf(fd, "\tlet %s", let->var->name);
278 if (let->val) {
279 dprintf(fd, " = %s", let->val->flags.one.is_reference ? "&" : "");
280 switch (let->val->kind) {
281 case PSI_LET_NULL:
282 dprintf(fd, "NULL");
283 break;
284 case PSI_LET_TMP:
285 dump_decl_var(fd, let->val->data.var);
286 break;
287 case PSI_LET_CALLOC:
288 dprintf(fd, "calloc(");
289 dump_num_exp(fd, let->val->data.alloc->nmemb);
290 dprintf(fd, ", ");
291 dump_num_exp(fd, let->val->data.alloc->size);
292 dprintf(fd, ")");
293 break;
294 case PSI_LET_FUNC:
295 dprintf(fd, "%s($%s)", let->val->data.func->name,
296 let->val->data.func->var->name);
297 break;
298 case PSI_LET_NUMEXP:
299 dump_num_exp(fd, let->val->data.num);
300 break;
301
302 EMPTY_SWITCH_DEFAULT_CASE();
303 }
304 dprintf(fd, ";");
305 }
306 }
307
308 static inline void dump_impl_return_stmt(int fd, return_stmt *ret) {
309 dprintf(fd, "\treturn ");
310 dump_impl_set_value(fd, ret->set, 1, 0);
311 }
312
313 static inline void dump_impl_set_stmt(int fd, set_stmt *set) {
314 dprintf(fd, "\tset $%s = ", set->var->name);
315 dump_impl_set_value(fd, set->val, 1, 0);
316 }
317
318 static inline void dump_impl_free_call(int fd, free_call *call) {
319 size_t l;
320
321 dprintf(fd, "%s(", call->func);
322 for (l = 0; l < call->vars->count; ++l) {
323 decl_var *fvar = call->vars->vars[l];
324
325 dump_decl_var(fd, fvar);
326 }
327 dprintf(fd, ");");
328 }
329
330 static inline void dump_impl_free_stmt(int fd, free_stmt *fre) {
331 size_t k;
332
333 dprintf(fd, "\tfree ");
334 for (k = 0; k < fre->calls->count; ++k) {
335 free_call *call = fre->calls->list[k];
336
337 if (k) {
338 dprintf(fd, ", ");
339 }
340 dump_impl_free_call(fd, call);
341 dprintf(fd, "\n");
342 }
343 }
344 static inline void dump_impl_stmts(int fd, impl_stmts *stmts) {
345 size_t j;
346
347 for (j = 0; j < stmts->let.count; ++j) {
348 let_stmt *let = stmts->let.list[j];
349 dump_impl_let_stmt(fd, let);
350 dprintf(fd, "\n");
351 }
352 for (j = 0; j < stmts->ret.count; ++j) {
353 return_stmt *ret = stmts->ret.list[j];
354 dump_impl_return_stmt(fd, ret);
355 dprintf(fd, "\n");
356 }
357 for (j = 0; j < stmts->set.count; ++j) {
358 set_stmt *set = stmts->set.list[j];
359
360 dump_impl_set_stmt(fd, set);
361 dprintf(fd, "\n");
362 }
363 for (j = 0; j < stmts->fre.count; ++j) {
364 free_stmt *fre = stmts->fre.list[j];
365
366 dump_impl_free_stmt(fd, fre);
367 dprintf(fd, "\n");
368 }
369 }
370
371 static inline void dump_impl(int fd, impl *impl) {
372
373 dump_impl_func(fd, impl->func);
374 dprintf(fd, " {\n");
375 if (impl->stmts) {
376 dump_impl_stmts(fd, impl->stmts);
377 }
378 dprintf(fd, "}");
379 }
380
381 static inline void dump_impls(int fd, impls *impls) {
382 size_t i;
383
384 for (i = 0; i < impls->count; ++i) {
385 impl *impl = impls->list[i];
386
387 dump_impl(fd, impl);
388 dprintf(fd, "\n");
389 }
390 }
391
392 void PSI_ContextDump(PSI_Context *C, int fd)
393 {
394 #ifdef HAVE_LIBJIT
395 if (C->ops == PSI_Libjit()) {
396 dprintf(fd, "// psi.engine=jit\n");
397 }
398 #endif
399 #ifdef HAVE_LIBFFI
400 if (C->ops == PSI_Libffi()) {
401 dprintf(fd, "// psi.engine=ffi\n");
402 }
403 #endif
404 dprintf(fd, "\n");
405
406 if (C->defs) {
407 dump_typedefs(fd, C->defs);
408 dprintf(fd, "\n");
409 }
410
411 if (C->structs) {
412 dump_structs(fd, C->structs);
413 dprintf(fd, "\n");
414 }
415 if (C->enums) {
416 dump_enums(fd, C->enums);
417 dprintf(fd, "\n");
418 }
419 if (C->consts) {
420 dump_constants(fd, C->consts);
421 dprintf(fd, "\n");
422 }
423 if (C->decls) {
424 dump_decls(fd, C->decls);
425 dprintf(fd, "\n");
426 }
427 if (C->impls) {
428 dump_impls(fd, C->impls);
429 dprintf(fd, "\n");
430 }
431 }