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