fliush
[m6w6/ext-psi] / src / validator.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/param.h>
5 #include <dlfcn.h>
6
7 #include <jit/jit.h>
8
9 #include "validator.h"
10
11 PSI_Validator *PSI_ValidatorInit(PSI_Validator *V, PSI_Parser *P)
12 {
13 if (!V) {
14 V = malloc(sizeof(*V));
15 }
16 memset(V, 0, sizeof(*V));
17
18 PSI_DataExchange((PSI_Data *) V, (PSI_Data *) P);
19
20 return V;
21 }
22
23 void PSI_ValidatorDtor(PSI_Validator *V)
24 {
25 PSI_DataDtor((PSI_Data *) V);
26 memset(V, 0, sizeof(*V));
27 }
28
29 void PSI_ValidatorFree(PSI_Validator **V)
30 {
31 if (*V) {
32 PSI_ValidatorDtor(*V);
33 free(*V);
34 *V = NULL;
35 }
36 }
37
38 static int validate_lib(PSI_Validator *V) {
39 char lib[MAXPATHLEN];
40 const char *ptr = V->lib;
41 size_t len;
42
43 if (!ptr) {
44 /* FIXME: assume stdlib */
45 return 1;
46 } else if (!strchr(ptr, '/')) {
47 #ifdef DARWIN
48 len = snprintf(lib, MAXPATHLEN, "lib%s.dylib", ptr);
49 #else
50 len = snprintf(lib, MAXPATHLEN, "lib%s.so", ptr);
51 #endif
52 if (MAXPATHLEN == len) {
53 V->error(PSI_WARNING, "Library name too long: '%s'", ptr);
54 }
55 lib[len] = 0;
56 ptr = lib;
57 }
58 if (!(V->dlopened = dlopen(ptr, RTLD_LAZY|RTLD_LOCAL))) {
59 V->error(PSI_WARNING, "Could not open library '%s': %s.", V->lib, dlerror());
60 return 0;
61 }
62 return 1;
63 }
64
65 static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) {
66 size_t i;
67
68 if (type->real) {
69 return 1;
70 }
71 for (i = 0; i < defs->count; ++i) {
72 if (!strcmp(defs->list[i]->alias, type->name)) {
73 type->real = defs->list[i]->type;
74 return 1;
75 }
76 }
77 return 0;
78 }
79 static inline int locate_decl_type_struct(decl_structs *structs, decl_type *type) {
80 size_t i;
81
82 if (type->strct) {
83 return 1;
84 }
85 for (i = 0; i < structs->count; ++i) {
86 if (!strcmp(structs->list[i]->name, type->name)) {
87 type->strct = structs->list[i];
88 return 1;
89 }
90 }
91 return 0;
92 }
93 static inline int validate_decl_type(PSI_Validator *V, decl_arg *arg, decl_type *type) {
94 switch (type->type) {
95 case PSI_T_NAME:
96 if (!V->defs || !locate_decl_type_alias(V->defs, type)) {
97 V->error(PSI_WARNING, "Cannot use '%s' as type for '%s';"
98 " Use 'typedef <type> <alias>;' statement",
99 type->name, arg->var->name);
100 return 0;
101 }
102 return validate_decl_type(V, arg, type->real);
103 case PSI_T_STRUCT:
104 if (!V->structs || !locate_decl_type_struct(V->structs, type)) {
105 V->error(PSI_WARNING, "Cannot use '%s' as type for '%s';"
106 " Use 'typedef struct <name> <alias>;' statement",
107 type->name, arg->var->name);
108 return 0;
109 }
110 break;
111 }
112 return 1;
113 }
114 static inline int validate_typedef(PSI_Validator *V, decl_typedef *def) {
115 /* FIXME: check def->alias */
116 if (def->type->type == PSI_T_NAME) {
117 V->error(PSI_WARNING, "Type '%s' cannot be aliased to '%s'",
118 def->type->name, def->alias);
119 return 0;
120 }
121 return 1;
122 }
123 static inline int validate_typedefs(PSI_Validator *V) {
124 size_t i;
125
126 for (i = 0; i < V->defs->count; ++i) {
127 if (!validate_typedef(V, V->defs->list[i])) {
128 return 0;
129 }
130 }
131
132 return 1;
133 }
134 static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *func)
135 {
136 if (!strcmp(func->var->name, "dlsym")) {
137 V->error(PSI_WARNING, "Cannot dlsym dlsym (sic!)");
138 return 0;
139 }
140
141 if (!validate_decl_type(V, func, func->type)) {
142 return 0;
143 }
144
145 decl->dlptr = dlsym(V->dlopened ?: RTLD_NEXT, func->var->name);
146 if (!decl->dlptr) {
147 V->error(PSI_WARNING, "Failed to located symbol '%s': %s",
148 func->var->name, dlerror());
149 }
150 return 1;
151 }
152 static const char * const abi_ccs[] = {
153 "default", /* \ */
154 "extern", /* > - all the same */
155 "cdecl", /* / */
156 "stdcall",
157 "fastcall",
158 };
159 static inline int validate_decl_abi(PSI_Validator *V, decl_abi *abi) {
160 size_t i;
161
162 for (i = 0; i < sizeof(abi_ccs)/sizeof(char*); ++ i) {
163 if (strcasecmp(abi->convention, abi_ccs[i])) {
164 return 1;
165 }
166 }
167 V->error(PSI_WARNING, "Invalid calling convention: '%s'", abi->convention);
168 return 0;
169 }
170 static inline int validate_decl_arg(PSI_Validator *V, decl_arg *arg) {
171 if (!validate_decl_type(V, arg, arg->type)) {
172 return 0;
173 }
174 return 1;
175 }
176 static inline int validate_decl_args(PSI_Validator *V, decl_args *args) {
177 size_t i;
178
179 for (i = 0; i < args->count; ++i) {
180 if (!validate_decl_arg(V, args->args[i])) {
181 return 0;
182 }
183 }
184 return 1;
185 }
186 static inline int validate_decl(PSI_Validator *V, decl *decl) {
187 if (!validate_decl_abi(V, decl->abi)) {
188 return 0;
189 }
190 if (!validate_decl_func(V, decl, decl->func)) {
191 return 0;
192 }
193 if (decl->args && !validate_decl_args(V, decl->args)) {
194 return 0;
195 }
196 return 1;
197 }
198 static inline int validate_decls(PSI_Validator *V) {
199 size_t i;
200
201 for (i = 0; i < V->decls->count; ++i) {
202 if (!validate_decl(V, V->decls->list[i])) {
203 return 0;
204 }
205 }
206 return 1;
207 }
208 static inline int validate_struct(PSI_Validator *V, decl_struct *s) {
209 size_t i;
210
211 if (!validate_decl_args(V, s->args)) {
212 return 0;
213 }
214
215 s->layout = calloc(s->args->count, sizeof(*s->layout));
216 for (i = 0; i < s->args->count; ++i) {
217 decl_type *t = real_decl_type(s->args->args[i]->type);
218
219 if (i) {
220 decl_struct_layout *l = &s->layout[i-1];
221 s->layout[i].pos = psi_t_align(t->type, l->pos + l->size);
222 } else {
223 s->layout[i].pos = 0;
224 }
225 s->layout[i].len = psi_t_size(t->type);
226 }
227 return 1;
228 }
229 static inline int validate_structs(PSI_Validator *V) {
230 size_t i;
231
232 for (i = 0; i < V->structs->count; ++i) {
233 if (!validate_struct(V->structs->list[i])) {
234 return 0;
235 }
236 }
237 return 1;
238 }
239
240 static inline int validate_impl_type(PSI_Validator *V, impl *impl, impl_type *type) {
241 /* FIXME */
242 return 1;
243 }
244 static inline int validate_impl_arg(PSI_Validator *V, impl *impl, impl_arg *arg) {
245 return 1;
246 }
247 static inline int validate_impl_args(PSI_Validator *V, impl *impl, impl_args *args) {
248 size_t i;
249
250 for (i = 0; i < args->count; ++i) {
251 if (!validate_impl_arg(V, impl, args->args[i])) {
252 return 0;
253 }
254 }
255 return 1;
256 }
257 static inline int validate_impl_func(PSI_Validator *V, impl *impl, impl_func *func) {
258 /* FIXME: does name need any validation? */
259 if (!validate_impl_type(V, impl, func->return_type)) {
260 return 0;
261 }
262 if (func->args && !validate_impl_args(V, impl, func->args)) {
263 return 0;
264 }
265 return 1;
266 }
267 static inline decl *locate_impl_decl(decls *decls, return_stmt *ret) {
268 size_t i;
269
270 for (i = 0; i < decls->count; ++i) {
271 if (!strcmp(decls->list[i]->func->var->name, ret->decl->name)) {
272 return decls->list[i];
273 }
274 }
275 return NULL;
276 }
277
278 static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts *stmts) {
279 /* okay,
280 * - we must have exactly one ret stmt delcaring the native func to call and which type cast to apply
281 * - we can have multiple let stmts; every arg of the ret stmts var (the function to call) must have one
282 * - we can have any count of set stmts; processing out vars
283 * - we can have any count of free stmts; freeing any out vars
284 */
285 size_t i, j, k;
286 return_stmt *ret;
287 decl *decl;
288
289 if (!stmts) {
290 V->error(PSI_WARNING, "Missing body for implementation %s!",
291 impl->func->name);
292 return 0;
293 }
294 if (stmts->ret.count != 1) {
295 if (stmts->ret.count > 1) {
296 V->error(PSI_WARNING, "Too many `ret` statements for implmentation %s;"
297 "found %zu, exactly one is needed",
298 impl->func->name, stmts->ret.count);
299 } else {
300 V->error(PSI_WARNING, "Missing `ret` statement for implementation %s",
301 impl->func->name);
302 }
303 return 0;
304 }
305
306 ret = stmts->ret.list[0];
307 decl = locate_impl_decl(V->decls, ret);
308 if (!decl) {
309 V->error(PSI_WARNING, "Missing declaration for implementation %s",
310 impl->func->name);
311 return 0;
312 }
313
314 /* check that we have a let stmt for every decl arg */
315 for (i = 0; i < decl->args->count; ++i) {
316 decl_arg *darg = decl->args->args[i];
317 int check = 0;
318
319 for (j = 0; j < stmts->let.count; ++j) {
320 let_stmt *let = stmts->let.list[j];
321
322 if (!strcmp(let->var->name, darg->var->name)) {
323 darg->let = let;
324 check = 1;
325 break;
326 }
327 }
328 if (!check) {
329 V->error(PSI_WARNING, "Missing `let` statement for arg '%s %.*s%s'"
330 "of declaration '%s' for implementation '%s'",
331 darg->type->name, (int) darg->var->pointer_level, "*****",
332 darg->var->name, decl->func->var->name, impl->func->name);
333 return 0;
334 }
335 }
336 /* check that the let_value references a known variable or NULL */
337 for (i = 0; i < stmts->let.count; ++i) {
338 let_stmt *let = stmts->let.list[i];
339 int check = 0;
340
341 if (let->val && let->val->var) {
342 for (j = 0; j < impl->func->args->count; ++j) {
343 impl_arg *iarg = impl->func->args->args[j];
344
345 if (!strcmp(let->val->var->name, iarg->var->name)) {
346 let->arg = iarg;
347 check = 1;
348 break;
349 }
350 }
351 if (!check) {
352 V->error(PSI_WARNING, "Unknown value '$%s' of `let` statement"
353 " for variable '%s' of implementation '%s'",
354 let->val->var->name, let->var->name, impl->func->name);
355 return 0;
356 }
357 }
358 }
359 /* check that set stmts reference known variables */
360 for (i = 0; i < stmts->set.count; ++i) {
361 set_stmt *set = stmts->set.list[i];
362 int check = 0;
363
364 for (j = 0; j < impl->func->args->count; ++j) {
365 impl_arg *iarg = impl->func->args->args[j];
366
367 if (!strcmp(set->var->name, iarg->var->name)) {
368 set->arg = iarg;
369 check = 1;
370 break;
371 }
372 }
373 if (!check) {
374 V->error(PSI_WARNING, "Unknown variable '$%s' of `set` statement"
375 " of implementation '%s'",
376 set->var->name, impl->func->name);
377 return 0;
378 }
379
380 for (j = 0; j < set->val->vars->count; ++j) {
381 decl_var *set_var = set->val->vars->vars[j];
382
383 check = 0;
384 for (k = 0; k < decl->args->count; ++k) {
385 decl_arg *set_arg = decl->args->args[k];
386
387 if (!strcmp(set_var->name, set_arg->var->name)) {
388 check = 1;
389 set_var->arg = set_arg;
390 break;
391 }
392 }
393
394 if (!check) {
395 V->error(PSI_WARNING, "Unknown value '%s' of `set` statement"
396 " for variable '$%s' of implementation '%s'",
397 set_var->name, set->arg->var->name, impl->func->name);
398 return 0;
399 }
400 }
401 }
402 /* check free stmts */
403 for (i = 0; i < stmts->fre.count; ++i) {
404 free_stmt *fre = stmts->fre.list[i];
405
406 for (j = 0; j < fre->vars->count; ++j) {
407 decl_var *free_var = fre->vars->vars[j];
408 int check = 0;
409
410 if (!strcmp(free_var->name, decl->func->var->name)) {
411 continue;
412 }
413 for (k = 0; k < decl->args->count; ++k) {
414 decl_arg *free_arg = decl->args->args[k];
415
416 if (!strcmp(free_var->name, free_arg->var->name)) {
417 check = 1;
418 free_var->arg = free_arg;
419 break;
420 }
421 }
422
423 if (!check) {
424 V->error(PSI_WARNING, "Unknown variable '%s' of `free` statement"
425 " of implementation '%s'",
426 free_var->name, impl->func->name);
427 return 0;
428 }
429 }
430 }
431
432 impl->decl = decl;
433
434 return 1;
435 }
436
437 static inline int validate_impl(PSI_Validator *V, impl *impl) {
438 if (!validate_impl_func(V, impl, impl->func)) {
439 return 0;
440 }
441 if (!validate_impl_stmts(V, impl, impl->stmts)) {
442 return 0;
443 }
444 return 1;
445 }
446 static inline int validate_impls(PSI_Validator *V) {
447 size_t i;
448
449 for (i = 0; i < V->impls->count; ++i) {
450 if (!validate_impl(V, V->impls->list[i])) {
451 return 0;
452 }
453 }
454 return 1;
455 }
456
457 int PSI_ValidatorValidate(PSI_Validator *V)
458 {
459 if (!validate_lib(V)) {
460 return 0;
461 }
462 if (V->defs && !validate_typedefs(V)) {
463 return 0;
464 }
465 if (V->structs && !validate_structs(V)) {
466 return 0;
467 }
468 if (V->decls && !validate_decls(V)) {
469 return 0;
470 }
471 if (!V->impls || !validate_impls(V)) {
472 return 0;
473 }
474 return 1;
475 }