2 * sparse/smatch_extra_helper.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
12 #include "smatch_extra.h"
13 #include "smatch_slist.h"
15 ALLOCATOR(data_info
, "smatch extra data");
16 ALLOCATOR(data_range
, "data range");
17 __DO_ALLOCATOR(struct data_range
, sizeof(struct data_range
), __alignof__(struct data_range
),
18 "permanent ranges", perm_data_range
);
20 static char *show_num(long long num
)
22 static char buff
[256];
24 if (num
== whole_range
.min
) {
25 snprintf(buff
, 255, "min");
26 } else if (num
== whole_range
.max
) {
27 snprintf(buff
, 255, "max");
29 snprintf(buff
, 255, "(%lld)", num
);
31 snprintf(buff
, 255, "%lld", num
);
37 char *show_ranges(struct range_list
*list
)
39 struct data_range
*tmp
;
45 FOR_EACH_PTR(list
, tmp
) {
47 strncat(full
, ",", 254 - strlen(full
));
48 if (tmp
->min
== tmp
->max
) {
49 strncat(full
, show_num(tmp
->min
), 254 - strlen(full
));
52 strncat(full
, show_num(tmp
->min
), 254 - strlen(full
));
53 strncat(full
, "-", 254 - strlen(full
));
54 strncat(full
, show_num(tmp
->max
), 254 - strlen(full
));
55 } END_FOR_EACH_PTR(tmp
);
56 return alloc_sname(full
);
59 static struct data_range range_zero
= {
64 static struct data_range range_one
= {
69 struct data_range
*alloc_range(long long min
, long long max
)
71 struct data_range
*ret
;
74 printf("Error invalid range %lld to %lld\n", min
, max
);
76 if (min
== whole_range
.min
&& max
== whole_range
.max
)
78 if (min
== 0 && max
== 0)
80 if (min
== 1 && max
== 1)
82 ret
= __alloc_data_range(0);
88 struct data_range
*alloc_range_perm(long long min
, long long max
)
90 struct data_range
*ret
;
93 printf("Error invalid range %lld to %lld\n", min
, max
);
95 if (min
== whole_range
.min
&& max
== whole_range
.max
)
97 if (min
== 0 && max
== 0)
99 if (min
== 1 && max
== 1)
101 ret
= __alloc_perm_data_range(0);
107 struct data_info
*alloc_dinfo_range(long long min
, long long max
)
109 struct data_info
*ret
;
111 ret
= __alloc_data_info(0);
112 ret
->type
= DATA_RANGE
;
114 ret
->value_ranges
= NULL
;
115 add_range(&ret
->value_ranges
, min
, max
);
119 void add_range(struct range_list
**list
, long long min
, long long max
)
121 struct data_range
*tmp
= NULL
;
122 struct data_range
*new;
124 FOR_EACH_PTR(*list
, tmp
) {
125 if (max
!= whole_range
.max
&& max
+ 1 == tmp
->min
) {
126 /* join 2 ranges into a big range */
127 new = alloc_range(min
, tmp
->max
);
128 REPLACE_CURRENT_PTR(tmp
, new);
131 if (max
< tmp
->min
) { /* new range entirely below */
132 new = alloc_range(min
, max
);
133 INSERT_CURRENT(new, tmp
);
136 if (min
< tmp
->min
) { /* new range partially below */
139 new = alloc_range(min
, max
);
140 REPLACE_CURRENT_PTR(tmp
, new);
143 if (max
<= tmp
->max
) /* new range already included */
145 if (min
<= tmp
->max
) { /* new range partially above */
147 new = alloc_range(min
, max
);
148 REPLACE_CURRENT_PTR(tmp
, new);
151 if (min
!= whole_range
.min
&& min
- 1 == tmp
->max
) {
152 /* join 2 ranges into a big range */
153 new = alloc_range(tmp
->min
, max
);
154 REPLACE_CURRENT_PTR(tmp
, new);
157 } END_FOR_EACH_PTR(tmp
);
158 new = alloc_range(min
, max
);
159 add_ptr_list(list
, new);
162 struct range_list
*clone_range_list(struct range_list
*list
)
164 struct data_range
*tmp
;
165 struct range_list
*ret
= NULL
;
167 FOR_EACH_PTR(list
, tmp
) {
168 add_ptr_list(&ret
, tmp
);
169 } END_FOR_EACH_PTR(tmp
);
173 struct range_list
*range_list_union(struct range_list
*one
, struct range_list
*two
)
175 struct data_range
*tmp
;
176 struct range_list
*ret
= NULL
;
178 if (!one
|| !two
) /*having nothing in a list means everything is in */
181 FOR_EACH_PTR(one
, tmp
) {
182 add_range(&ret
, tmp
->min
, tmp
->max
);
183 } END_FOR_EACH_PTR(tmp
);
184 FOR_EACH_PTR(two
, tmp
) {
185 add_range(&ret
, tmp
->min
, tmp
->max
);
186 } END_FOR_EACH_PTR(tmp
);
190 struct range_list
*remove_range(struct range_list
*list
, long long min
, long long max
)
192 struct data_range
*tmp
;
193 struct range_list
*ret
= NULL
;
195 FOR_EACH_PTR(list
, tmp
) {
196 if (tmp
->max
< min
) {
197 add_range(&ret
, tmp
->min
, tmp
->max
);
200 if (tmp
->min
> max
) {
201 add_range(&ret
, tmp
->min
, tmp
->max
);
204 if (tmp
->min
>= min
&& tmp
->max
<= max
)
206 if (tmp
->min
>= min
) {
207 add_range(&ret
, max
+ 1, tmp
->max
);
208 } else if (tmp
->max
<= max
) {
209 add_range(&ret
, tmp
->min
, min
- 1);
211 add_range(&ret
, tmp
->min
, min
- 1);
212 add_range(&ret
, max
+ 1, tmp
->max
);
214 } END_FOR_EACH_PTR(tmp
);
218 long long get_dinfo_min(struct data_info
*dinfo
)
220 struct data_range
*drange
;
222 if (!dinfo
|| !dinfo
->value_ranges
)
223 return whole_range
.min
;
224 drange
= first_ptr_list((struct ptr_list
*)dinfo
->value_ranges
);
228 long long get_dinfo_max(struct data_info
*dinfo
)
230 struct data_range
*drange
;
232 if (!dinfo
|| !dinfo
->value_ranges
)
233 return whole_range
.max
;
234 drange
= first_ptr_list((struct ptr_list
*)dinfo
->value_ranges
);
238 int is_whole_range(struct range_list
*ranges
)
240 struct data_range
*drange
;
245 drange
= first_ptr_list((struct ptr_list
*)ranges
);
246 if (drange
->min
== whole_range
.min
&& drange
->max
== whole_range
.max
)
252 * if it can be only one value return that, else return UNDEFINED
254 long long get_single_value_from_range(struct data_info
*dinfo
)
256 struct data_range
*tmp
;
258 long long ret
= UNDEFINED
;
260 if (dinfo
->type
!= DATA_RANGE
)
263 FOR_EACH_PTR(dinfo
->value_ranges
, tmp
) {
265 if (tmp
->min
!= tmp
->max
)
271 } END_FOR_EACH_PTR(tmp
);
275 int true_comparison_range(struct data_range
*left
, int comparison
, struct data_range
*right
)
279 case SPECIAL_UNSIGNED_LT
:
280 if (left
->min
< right
->max
)
283 case SPECIAL_UNSIGNED_LTE
:
285 if (left
->min
<= right
->max
)
289 if (left
->max
< right
->min
)
291 if (left
->min
> right
->max
)
294 case SPECIAL_UNSIGNED_GTE
:
296 if (left
->max
>= right
->min
)
300 case SPECIAL_UNSIGNED_GT
:
301 if (left
->max
> right
->min
)
304 case SPECIAL_NOTEQUAL
:
305 if (left
->min
!= left
->max
)
307 if (right
->min
!= right
->max
)
309 if (left
->min
!= right
->min
)
313 smatch_msg("unhandled comparison %d\n", comparison
);
319 int true_comparison_range_lr(int comparison
, struct data_range
*var
, struct data_range
*val
, int left
)
322 return true_comparison_range(var
, comparison
, val
);
324 return true_comparison_range(val
, comparison
, var
);
327 static int false_comparison_range(struct data_range
*left
, int comparison
, struct data_range
*right
)
331 case SPECIAL_UNSIGNED_LT
:
332 if (left
->max
>= right
->min
)
335 case SPECIAL_UNSIGNED_LTE
:
337 if (left
->max
> right
->min
)
341 if (left
->min
!= left
->max
)
343 if (right
->min
!= right
->max
)
345 if (left
->min
!= right
->min
)
348 case SPECIAL_UNSIGNED_GTE
:
350 if (left
->min
< right
->max
)
354 case SPECIAL_UNSIGNED_GT
:
355 if (left
->min
<= right
->max
)
358 case SPECIAL_NOTEQUAL
:
359 if (left
->max
< right
->min
)
361 if (left
->min
> right
->max
)
365 smatch_msg("unhandled comparison %d\n", comparison
);
371 int false_comparison_range_lr(int comparison
, struct data_range
*var
, struct data_range
*val
, int left
)
374 return false_comparison_range(var
, comparison
, val
);
376 return false_comparison_range(val
, comparison
, var
);
381 int possibly_true(int comparison
, struct data_info
*dinfo
, int num
, int left
)
383 struct data_range
*tmp
;
385 struct data_range drange
;
390 FOR_EACH_PTR(dinfo
->value_ranges
, tmp
) {
392 ret
= true_comparison_range(tmp
, comparison
, &drange
);
394 ret
= true_comparison_range(&drange
, comparison
, tmp
);
397 } END_FOR_EACH_PTR(tmp
);
401 int possibly_false(int comparison
, struct data_info
*dinfo
, int num
, int left
)
403 struct data_range
*tmp
;
405 struct data_range drange
;
410 FOR_EACH_PTR(dinfo
->value_ranges
, tmp
) {
412 ret
= false_comparison_range(tmp
, comparison
, &drange
);
414 ret
= false_comparison_range(&drange
, comparison
, tmp
);
417 } END_FOR_EACH_PTR(tmp
);
421 void tack_on(struct range_list
**list
, struct data_range
*drange
)
423 add_ptr_list(list
, drange
);
426 int in_list_exact(struct range_list
*list
, struct data_range
*drange
)
428 struct data_range
*tmp
;
430 FOR_EACH_PTR(list
, tmp
) {
431 if (tmp
->min
== drange
->min
&& tmp
->max
== drange
->max
)
433 } END_FOR_EACH_PTR(tmp
);
438 static void free_single_dinfo(struct data_info
*dinfo
)
440 if (dinfo
->type
== DATA_RANGE
)
441 __free_ptr_list((struct ptr_list
**)&dinfo
->value_ranges
);
444 static void free_dinfos(struct allocation_blob
*blob
)
446 unsigned int size
= sizeof(struct data_info
);
447 unsigned int offset
= 0;
449 while (offset
< blob
->offset
) {
450 free_single_dinfo((struct data_info
*)(blob
->data
+ offset
));
455 void free_data_info_allocs(void)
457 struct allocator_struct
*desc
= &data_info_allocator
;
458 struct allocation_blob
*blob
= desc
->blobs
;
461 desc
->allocations
= 0;
462 desc
->total_bytes
= 0;
463 desc
->useful_bytes
= 0;
464 desc
->freelist
= NULL
;
466 struct allocation_blob
*next
= blob
->next
;
468 blob_free(blob
, desc
->chunking
);
471 clear_data_range_alloc();