sval: delete some unused data_range code
[smatch.git] / smatch_ranges.c
blob86dfdc0eee408215314c16bc341d99a5e66b4414
1 /*
2 * sparse/smatch_ranges.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include "parse.h"
11 #include "smatch.h"
12 #include "smatch_extra.h"
13 #include "smatch_slist.h"
15 ALLOCATOR(data_info, "smatch extra data");
16 ALLOCATOR(data_range, "data range");
17 ALLOCATOR(data_range_sval, "data range sval");
18 __DO_ALLOCATOR(struct data_range_sval, sizeof(struct data_range_sval), __alignof__(struct data_range_sval),
19 "permanent ranges sval", perm_data_range_sval);
21 struct data_range whole_range = {
22 .min = LLONG_MIN,
23 .max = LLONG_MAX,
26 char *show_ranges_sval(struct range_list_sval *list)
28 struct data_range_sval *tmp;
29 char full[256];
30 int i = 0;
32 full[0] = '\0';
33 full[255] = '\0';
34 FOR_EACH_PTR(list, tmp) {
35 if (i++)
36 strncat(full, ",", 254 - strlen(full));
37 if (sval_cmp(tmp->min, tmp->max) == 0) {
38 strncat(full, sval_to_str(tmp->min), 254 - strlen(full));
39 continue;
41 strncat(full, sval_to_str(tmp->min), 254 - strlen(full));
42 strncat(full, "-", 254 - strlen(full));
43 strncat(full, sval_to_str(tmp->max), 254 - strlen(full));
44 } END_FOR_EACH_PTR(tmp);
45 return alloc_sname(full);
48 void get_value_ranges_sval(char *value, struct range_list_sval **rl)
50 long long val1, val2;
51 char *start;
52 char *c;
54 *rl = NULL;
56 c = value;
57 while (*c) {
58 if (*c == '(')
59 c++;
60 start = c;
62 if (!strncmp(start, "max", 3)) {
63 val1 = LLONG_MAX;
64 c += 3;
65 } else if (!strncmp(start, "u64max", 6)) {
66 val1 = LLONG_MAX; // FIXME
67 c += 6;
68 } else if (!strncmp(start, "s64max", 6)) {
69 val1 = LLONG_MAX;
70 c += 6;
71 } else if (!strncmp(start, "u32max", 6)) {
72 val1 = UINT_MAX;
73 c += 6;
74 } else if (!strncmp(start, "s32max", 6)) {
75 val1 = INT_MAX;
76 c += 6;
77 } else if (!strncmp(start, "u16max", 6)) {
78 val1 = USHRT_MAX;
79 c += 6;
80 } else if (!strncmp(start, "s16max", 6)) {
81 val1 = SHRT_MAX;
82 c += 6;
83 } else if (!strncmp(start, "min", 3)) {
84 val1 = LLONG_MIN;
85 c += 3;
86 } else if (!strncmp(start, "s64min", 6)) {
87 val1 = LLONG_MIN;
88 c += 6;
89 } else if (!strncmp(start, "s32min", 6)) {
90 val1 = INT_MIN;
91 c += 6;
92 } else if (!strncmp(start, "s16min", 6)) {
93 val1 = SHRT_MIN;
94 c += 6;
95 } else {
96 while (*c && *c != ',' && *c != '-')
97 c++;
98 val1 = strtoll(start, &c, 10);
100 if (*c == ')')
101 c++;
102 if (!*c) {
103 add_range_sval(rl, ll_to_sval(val1), ll_to_sval(val1));
104 break;
106 if (*c == ',') {
107 add_range_sval(rl, ll_to_sval(val1), ll_to_sval(val1));
108 c++;
109 start = c;
110 continue;
112 c++; /* skip the dash in eg. 4-5 */
113 if (*c == '(')
114 c++;
115 start = c;
116 if (!strncmp(start, "max", 3)) {
117 val2 = LLONG_MAX;
118 c += 3;
119 } else {
121 while (*c && *c != ',' && *c != '-')
122 c++;
123 val2 = strtoll(start, &c, 10);
125 add_range_sval(rl, ll_to_sval(val1), ll_to_sval(val2));
126 if (!*c)
127 break;
128 if (*c == ')')
129 c++;
130 c++; /* skip the comma in eg: 4-5,7 */
134 int is_whole_range_rl_sval(struct range_list_sval *rl)
136 struct data_range_sval *drange;
138 if (ptr_list_empty(rl))
139 return 1;
140 drange = first_ptr_list((struct ptr_list *)rl);
141 if (sval_is_min(drange->min) && sval_is_max(drange->max))
142 return 1;
143 return 0;
146 sval_t rl_min_sval(struct range_list_sval *rl)
148 struct data_range_sval *drange;
149 sval_t ret;
151 ret.type = &llong_ctype;
152 ret.value = LLONG_MIN;
153 if (ptr_list_empty(rl))
154 return ret;
155 drange = first_ptr_list((struct ptr_list *)rl);
156 return drange->min;
159 sval_t rl_max_sval(struct range_list_sval *rl)
161 struct data_range_sval *drange;
162 sval_t ret;
164 ret.type = &llong_ctype;
165 ret.value = LLONG_MAX;
166 if (ptr_list_empty(rl))
167 return ret;
168 drange = last_ptr_list((struct ptr_list *)rl);
169 return drange->max;
172 static struct data_range_sval *alloc_range_helper_sval(sval_t min, sval_t max, int perm)
174 struct data_range_sval *ret;
176 if (sval_cmp(min, max) > 0) {
177 // sm_msg("debug invalid range %lld to %lld", min, max);
178 min.value = LLONG_MIN; /* fixme: need a way to represent unknown svals */
179 max.value = LLONG_MAX;
182 if (perm)
183 ret = __alloc_perm_data_range_sval(0);
184 else
185 ret = __alloc_data_range_sval(0);
186 ret->min = min;
187 ret->max = max;
188 return ret;
191 struct data_range_sval *alloc_range_sval(sval_t min, sval_t max)
193 return alloc_range_helper_sval(min, max, 0);
196 struct data_range_sval *alloc_range_perm_sval(sval_t min, sval_t max)
198 return alloc_range_helper_sval(min, max, 1);
201 struct range_list_sval *alloc_range_list_sval(sval_t min, sval_t max)
203 struct range_list_sval *rl = NULL;
205 add_range_sval(&rl, min, max);
206 return rl;
209 struct range_list_sval *whole_range_list_sval(void)
211 return alloc_range_list_sval(ll_to_sval(whole_range.min), ll_to_sval(whole_range.max));
214 void add_range_sval(struct range_list_sval **list, sval_t min, sval_t max)
216 struct data_range_sval *tmp = NULL;
217 struct data_range_sval *new = NULL;
218 int check_next = 0;
221 * FIXME: This has a problem merging a range_list like: min-0,3-max
222 * with a range like 1-2. You end up with min-2,3-max instead of
223 * just min-max.
225 FOR_EACH_PTR(*list, tmp) {
226 if (check_next) {
227 /* Sometimes we overlap with more than one range
228 so we have to delete or modify the next range. */
229 if (max.value + 1 == tmp->min.value) {
230 /* join 2 ranges here */
231 new->max = tmp->max;
232 DELETE_CURRENT_PTR(tmp);
233 return;
236 /* Doesn't overlap with the next one. */
237 if (sval_cmp(max, tmp->min) < 0)
238 return;
239 /* Partially overlaps with the next one. */
240 if (sval_cmp(max, tmp->max) < 0) {
241 tmp->min.value = max.value + 1;
242 return;
244 /* Completely overlaps with the next one. */
245 if (sval_cmp(max, tmp->max) >= 0) {
246 DELETE_CURRENT_PTR(tmp);
247 /* there could be more ranges to delete */
248 continue;
251 if (!sval_is_max(max) && max.value + 1 == tmp->min.value) {
252 /* join 2 ranges into a big range */
253 new = alloc_range_sval(min, tmp->max);
254 REPLACE_CURRENT_PTR(tmp, new);
255 return;
257 if (sval_cmp(max, tmp->min) < 0) { /* new range entirely below */
258 new = alloc_range_sval(min, max);
259 INSERT_CURRENT(new, tmp);
260 return;
262 if (sval_cmp(min, tmp->min) < 0) { /* new range partially below */
263 if (sval_cmp(max, tmp->max) < 0)
264 max = tmp->max;
265 else
266 check_next = 1;
267 new = alloc_range_sval(min, max);
268 REPLACE_CURRENT_PTR(tmp, new);
269 if (!check_next)
270 return;
271 continue;
273 if (sval_cmp(max, tmp->max) <= 0) /* new range already included */
274 return;
275 if (sval_cmp(min, tmp->max) <= 0) { /* new range partially above */
276 min = tmp->min;
277 new = alloc_range_sval(min, max);
278 REPLACE_CURRENT_PTR(tmp, new);
279 check_next = 1;
280 continue;
282 if (!sval_is_min(min) && min.value - 1 == tmp->max.value) {
283 /* join 2 ranges into a big range */
284 new = alloc_range_sval(tmp->min, max);
285 REPLACE_CURRENT_PTR(tmp, new);
286 check_next = 1;
287 continue;
289 /* the new range is entirely above the existing ranges */
290 } END_FOR_EACH_PTR(tmp);
291 if (check_next)
292 return;
293 new = alloc_range_sval(min, max);
294 add_ptr_list(list, new);
297 struct range_list_sval *clone_range_list_sval(struct range_list_sval *list)
299 struct data_range_sval *tmp;
300 struct range_list_sval *ret = NULL;
302 FOR_EACH_PTR(list, tmp) {
303 add_ptr_list(&ret, tmp);
304 } END_FOR_EACH_PTR(tmp);
305 return ret;
308 struct range_list_sval *clone_permanent_sval(struct range_list_sval *list)
310 struct data_range_sval *tmp;
311 struct data_range_sval *new;
312 struct range_list_sval *ret = NULL;
314 FOR_EACH_PTR(list, tmp) {
315 new = alloc_range_perm_sval(tmp->min, tmp->max);
316 add_ptr_list(&ret, new);
317 } END_FOR_EACH_PTR(tmp);
318 return ret;
321 struct range_list_sval *range_list_union_sval(struct range_list_sval *one, struct range_list_sval *two)
323 struct data_range_sval *tmp;
324 struct range_list_sval *ret = NULL;
326 FOR_EACH_PTR(one, tmp) {
327 add_range_sval(&ret, tmp->min, tmp->max);
328 } END_FOR_EACH_PTR(tmp);
329 FOR_EACH_PTR(two, tmp) {
330 add_range_sval(&ret, tmp->min, tmp->max);
331 } END_FOR_EACH_PTR(tmp);
332 return ret;
335 struct range_list_sval *remove_range_sval(struct range_list_sval *list, sval_t min, sval_t max)
337 struct data_range_sval *tmp;
338 struct range_list_sval *ret = NULL;
340 FOR_EACH_PTR(list, tmp) {
341 if (sval_cmp(tmp->max, min) < 0) {
342 add_range_sval(&ret, tmp->min, tmp->max);
343 continue;
345 if (sval_cmp(tmp->min, max) > 0) {
346 add_range_sval(&ret, tmp->min, tmp->max);
347 continue;
349 if (sval_cmp(tmp->min, min) >= 0 && sval_cmp(tmp->max, max) <= 0)
350 continue;
351 if (sval_cmp(tmp->min, min) >= 0) {
352 max.value++;
353 add_range_sval(&ret, max, tmp->max);
354 } else if (sval_cmp(tmp->max, max) <= 0) {
355 min.value--;
356 add_range_sval(&ret, tmp->min, min);
357 } else {
358 min.value--;
359 max.value++;
360 add_range_sval(&ret, tmp->min, min);
361 add_range_sval(&ret, max, tmp->max);
363 } END_FOR_EACH_PTR(tmp);
364 return ret;
367 int estate_get_single_value_sval(struct smatch_state *state, sval_t *sval)
369 sval_t min, max;
371 min = rl_min_sval(estate_ranges_sval(state));
372 max = rl_max_sval(estate_ranges_sval(state));
373 if (sval_cmp(min, max) != 0)
374 return 0;
375 *sval = min;
376 return 1;
379 int ranges_equiv_sval(struct data_range_sval *one, struct data_range_sval *two)
381 if (!one && !two)
382 return 1;
383 if (!one || !two)
384 return 0;
385 if (sval_cmp(one->min, two->min) != 0)
386 return 0;
387 if (sval_cmp(one->max, two->max) != 0)
388 return 0;
389 return 1;
392 int range_lists_equiv_sval(struct range_list_sval *one, struct range_list_sval *two)
394 struct data_range_sval *one_range;
395 struct data_range_sval *two_range;
397 PREPARE_PTR_LIST(one, one_range);
398 PREPARE_PTR_LIST(two, two_range);
399 for (;;) {
400 if (!one_range && !two_range)
401 return 1;
402 if (!ranges_equiv_sval(one_range, two_range))
403 return 0;
404 NEXT_PTR_LIST(one_range);
405 NEXT_PTR_LIST(two_range);
407 FINISH_PTR_LIST(two_range);
408 FINISH_PTR_LIST(one_range);
410 return 1;
413 int true_comparison_range_sval(struct data_range_sval *left, int comparison, struct data_range_sval *right)
415 switch (comparison) {
416 case '<':
417 case SPECIAL_UNSIGNED_LT:
418 if (sval_cmp(left->min, right->max) < 0)
419 return 1;
420 return 0;
421 case SPECIAL_UNSIGNED_LTE:
422 case SPECIAL_LTE:
423 if (sval_cmp(left->min, right->max) <= 0)
424 return 1;
425 return 0;
426 case SPECIAL_EQUAL:
427 if (sval_cmp(left->max, right->min) < 0)
428 return 0;
429 if (sval_cmp(left->min, right->max) > 0)
430 return 0;
431 return 1;
432 case SPECIAL_UNSIGNED_GTE:
433 case SPECIAL_GTE:
434 if (sval_cmp(left->max, right->min) >= 0)
435 return 1;
436 return 0;
437 case '>':
438 case SPECIAL_UNSIGNED_GT:
439 if (sval_cmp(left->max, right->min) > 0)
440 return 1;
441 return 0;
442 case SPECIAL_NOTEQUAL:
443 if (sval_cmp(left->min, left->max) != 0)
444 return 1;
445 if (sval_cmp(right->min, right->max) != 0)
446 return 1;
447 if (sval_cmp(left->min, right->min) != 0)
448 return 1;
449 return 0;
450 default:
451 sm_msg("unhandled comparison %d\n", comparison);
452 return 0;
454 return 0;
457 int true_comparison_range_lr_sval(int comparison, struct data_range_sval *var, struct data_range_sval *val, int left)
459 if (left)
460 return true_comparison_range_sval(var, comparison, val);
461 else
462 return true_comparison_range_sval(val, comparison, var);
465 static int false_comparison_range_sval(struct data_range_sval *left, int comparison, struct data_range_sval *right)
467 switch (comparison) {
468 case '<':
469 case SPECIAL_UNSIGNED_LT:
470 if (sval_cmp(left->max, right->min) >= 0)
471 return 1;
472 return 0;
473 case SPECIAL_UNSIGNED_LTE:
474 case SPECIAL_LTE:
475 if (sval_cmp(left->max, right->min) > 0)
476 return 1;
477 return 0;
478 case SPECIAL_EQUAL:
479 if (sval_cmp(left->min, left->max) != 0)
480 return 1;
481 if (sval_cmp(right->min, right->max) != 0)
482 return 1;
483 if (sval_cmp(left->min, right->min) != 0)
484 return 1;
485 return 0;
486 case SPECIAL_UNSIGNED_GTE:
487 case SPECIAL_GTE:
488 if (sval_cmp(left->min, right->max) < 0)
489 return 1;
490 return 0;
491 case '>':
492 case SPECIAL_UNSIGNED_GT:
493 if (sval_cmp(left->min, right->max) <= 0)
494 return 1;
495 return 0;
496 case SPECIAL_NOTEQUAL:
497 if (sval_cmp(left->max, right->min) < 0)
498 return 0;
499 if (sval_cmp(left->min, right->max) > 0)
500 return 0;
501 return 1;
502 default:
503 sm_msg("unhandled comparison %d\n", comparison);
504 return 0;
506 return 0;
509 int false_comparison_range_lr_sval(int comparison, struct data_range_sval *var, struct data_range_sval *val, int left)
511 if (left)
512 return false_comparison_range_sval(var, comparison, val);
513 else
514 return false_comparison_range_sval(val, comparison, var);
517 int possibly_true(struct expression *left, int comparison, struct expression *right)
519 struct range_list_sval *rl_left, *rl_right;
520 struct data_range_sval *tmp_left, *tmp_right;
522 if (!get_implied_range_list_sval(left, &rl_left))
523 return 1;
524 if (!get_implied_range_list_sval(right, &rl_right))
525 return 1;
527 FOR_EACH_PTR(rl_left, tmp_left) {
528 FOR_EACH_PTR(rl_right, tmp_right) {
529 if (true_comparison_range_sval(tmp_left, comparison, tmp_right))
530 return 1;
531 } END_FOR_EACH_PTR(tmp_right);
532 } END_FOR_EACH_PTR(tmp_left);
533 return 0;
536 int possibly_false(struct expression *left, int comparison, struct expression *right)
538 struct range_list_sval *rl_left, *rl_right;
539 struct data_range_sval *tmp_left, *tmp_right;
541 if (!get_implied_range_list_sval(left, &rl_left))
542 return 1;
543 if (!get_implied_range_list_sval(right, &rl_right))
544 return 1;
546 FOR_EACH_PTR(rl_left, tmp_left) {
547 FOR_EACH_PTR(rl_right, tmp_right) {
548 if (false_comparison_range_sval(tmp_left, comparison, tmp_right))
549 return 1;
550 } END_FOR_EACH_PTR(tmp_right);
551 } END_FOR_EACH_PTR(tmp_left);
552 return 0;
555 int possibly_true_range_lists_sval(struct range_list_sval *left_ranges, int comparison, struct range_list_sval *right_ranges)
557 struct data_range_sval *left_tmp, *right_tmp;
559 if (!left_ranges || !right_ranges)
560 return 1;
562 FOR_EACH_PTR(left_ranges, left_tmp) {
563 FOR_EACH_PTR(right_ranges, right_tmp) {
564 if (true_comparison_range_sval(left_tmp, comparison, right_tmp))
565 return 1;
566 } END_FOR_EACH_PTR(right_tmp);
567 } END_FOR_EACH_PTR(left_tmp);
568 return 0;
571 int possibly_false_range_lists_sval(struct range_list_sval *left_ranges, int comparison, struct range_list_sval *right_ranges)
573 struct data_range_sval *left_tmp, *right_tmp;
575 if (!left_ranges || !right_ranges)
576 return 1;
578 FOR_EACH_PTR(left_ranges, left_tmp) {
579 FOR_EACH_PTR(right_ranges, right_tmp) {
580 if (false_comparison_range_sval(left_tmp, comparison, right_tmp))
581 return 1;
582 } END_FOR_EACH_PTR(right_tmp);
583 } END_FOR_EACH_PTR(left_tmp);
584 return 0;
587 /* FIXME: the _rl here stands for right left so really it should be _lr */
588 int possibly_true_range_lists_rl_sval(int comparison, struct range_list_sval *a, struct range_list_sval *b, int left)
590 if (left)
591 return possibly_true_range_lists_sval(a, comparison, b);
592 else
593 return possibly_true_range_lists_sval(b, comparison, a);
596 int possibly_false_range_lists_rl_sval(int comparison, struct range_list_sval *a, struct range_list_sval *b, int left)
598 if (left)
599 return possibly_false_range_lists_sval(a, comparison, b);
600 else
601 return possibly_false_range_lists_sval(b, comparison, a);
604 void tack_on_sval(struct range_list_sval **list, struct data_range_sval *drange)
606 add_ptr_list(list, drange);
609 void push_range_list_sval(struct range_list_stack_sval **rl_stack, struct range_list_sval *rl)
611 add_ptr_list(rl_stack, rl);
614 struct range_list_sval *pop_range_list_sval(struct range_list_stack_sval **rl_stack)
616 struct range_list_sval *rl;
618 rl = last_ptr_list((struct ptr_list *)*rl_stack);
619 delete_ptr_list_last((struct ptr_list **)rl_stack);
620 return rl;
623 struct range_list_sval *top_range_list_sval(struct range_list_stack_sval *rl_stack)
625 struct range_list_sval *rl;
627 rl = last_ptr_list((struct ptr_list *)rl_stack);
628 return rl;
631 void filter_top_range_list_sval(struct range_list_stack_sval **rl_stack, sval_t sval)
633 struct range_list_sval *rl;
635 rl = pop_range_list_sval(rl_stack);
636 rl = remove_range_sval(rl, sval, sval);
637 push_range_list_sval(rl_stack, rl);
640 struct range_list_sval *cast_rl(struct range_list_sval *rl, struct symbol *type)
642 struct data_range_sval *tmp;
643 struct data_range_sval *new;
644 struct range_list_sval *ret = NULL;
645 sval_t sval;
647 if (!type)
648 return clone_range_list_sval(rl);
650 sval = sval_cast(rl_min_sval(rl), type);
651 if (sval_cmp(sval, rl_min_sval(rl)) != 0)
652 return alloc_range_list_sval(sval_type_min(type), sval_type_max(type));
653 sval = sval_cast(rl_min_sval(rl), type);
654 if (sval_cmp(sval, rl_min_sval(rl)) != 0)
655 return alloc_range_list_sval(sval_type_min(type), sval_type_max(type));
657 FOR_EACH_PTR(rl, tmp) {
658 new = alloc_range_sval(sval_cast(tmp->min, type), sval_cast(tmp->max, type));
659 add_ptr_list(&ret, new);
660 } END_FOR_EACH_PTR(tmp);
662 return ret;
665 void free_range_list_sval(struct range_list_sval **rlist)
667 __free_ptr_list((struct ptr_list **)rlist);
670 static void free_single_dinfo(struct data_info *dinfo)
672 if (dinfo->type == DATA_RANGE)
673 free_range_list_sval(&dinfo->value_ranges);
676 static void free_dinfos(struct allocation_blob *blob)
678 unsigned int size = sizeof(struct data_info);
679 unsigned int offset = 0;
681 while (offset < blob->offset) {
682 free_single_dinfo((struct data_info *)(blob->data + offset));
683 offset += size;
687 void free_data_info_allocs(void)
689 struct allocator_struct *desc = &data_info_allocator;
690 struct allocation_blob *blob = desc->blobs;
692 desc->blobs = NULL;
693 desc->allocations = 0;
694 desc->total_bytes = 0;
695 desc->useful_bytes = 0;
696 desc->freelist = NULL;
697 while (blob) {
698 struct allocation_blob *next = blob->next;
699 free_dinfos(blob);
700 blob_free(blob, desc->chunking);
701 blob = next;
703 clear_data_range_alloc();