sval: update calls to get_implied_range_list()
[smatch.git] / smatch_sval.c
blob12aa2330e5e04b091a739c50ff74938da787f8ef
1 /*
2 * smatch/smatch_sval.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
9 * Basically the point of sval is that it can hold both ULLONG_MAX and
10 * LLONG_MIN. If it is an unsigned type then we use sval.uvalue or if it is
11 * signed we use sval.value.
13 * I considered just using one bit to store whether the value was signed vs
14 * unsigned but I think it might help to have the type information so we know
15 * how to do type promotion.
19 #include "smatch.h"
20 #include "smatch_slist.h"
21 #include "smatch_extra.h"
23 __ALLOCATOR(sval_t, "svals", sval);
25 sval_t *sval_alloc(sval_t sval)
27 sval_t *ret;
29 ret = __alloc_sval(0);
30 *ret = sval;
31 return ret;
34 sval_t *sval_alloc_permanent(sval_t sval)
36 sval_t *ret;
38 ret = malloc(sizeof(*ret));
39 *ret = sval;
40 return ret;
43 sval_t sval_blank(struct expression *expr)
45 sval_t ret;
47 ret.type = get_type(expr);
48 if (!ret.type)
49 ret.type = &llong_ctype;
50 ret.value = 123456789;
52 return ret;
55 sval_t sval_from_val(struct expression *expr, long long val)
57 sval_t ret;
59 ret = sval_blank(expr);
60 ret.value = val;
61 ret = sval_cast(ret, expr);
63 return ret;
66 int sval_unsigned(sval_t sval)
68 return type_unsigned(sval.type);
71 int sval_signed(sval_t sval)
73 return !type_unsigned(sval.type);
76 int sval_bits(sval_t sval)
78 if (!sval.type)
79 return 32;
80 return sval.type->bit_size;
83 int sval_is_min(sval_t sval)
85 sval_t min = sval_type_min(sval.type);
87 if (sval_unsigned(sval)) {
88 if (sval.uvalue == 0)
89 return 1;
90 return 0;
92 /* return true for less than min as well */
93 return (sval.value <= min.value);
96 int sval_is_max(sval_t sval)
98 sval_t max = sval_type_max(sval.type);
100 if (sval_unsigned(sval))
101 return (sval.uvalue >= max.value);
102 return (sval.value >= max.value);
105 static int sval_unsigned_big(sval_t sval)
107 if (sval_unsigned(sval) && sval_bits(sval) >= 32)
108 return 1;
109 return 0;
113 * Casts the values and then does a compare. Returns -1 if one is smaller, 0 if
114 * they are the same and 1 if two is larger.
116 int sval_cmp(sval_t one, sval_t two)
118 if (sval_unsigned_big(one) || sval_unsigned_big(two)) {
119 if (one.uvalue < two.uvalue)
120 return -1;
121 if (one.uvalue == two.uvalue)
122 return 0;
123 return 1;
125 /* fix me handle type promotion and unsigned values */
126 if (one.value < two.value)
127 return -1;
128 if (one.value == two.value)
129 return 0;
130 return 1;
133 int sval_cmp_val(sval_t one, long long val)
135 if (one.value < val)
136 return -1;
137 if (one.value == val)
138 return 0;
139 return 1;
142 sval_t sval_cast(sval_t sval, struct expression *expr)
144 sval_t ret;
146 ret = sval_blank(expr);
147 switch (sval_bits(ret)) {
148 case 8:
149 if (sval_unsigned(ret))
150 ret.value = (long long)(unsigned char)sval.value;
151 else
152 ret.value = (long long)(char)sval.value;
153 break;
154 case 16:
155 if (sval_unsigned(ret))
156 ret.value = (long long)(unsigned short)sval.value;
157 else
158 ret.value = (long long)(short)sval.value;
159 break;
160 case 32:
161 if (sval_unsigned(ret))
162 ret.value = (long long)(unsigned int)sval.value;
163 else
164 ret.value = (long long)(int)sval.value;
165 break;
166 default:
167 ret.value = sval.value;
169 return ret;
173 sval_t sval_preop(sval_t sval, int op)
175 switch (op) {
176 case '!':
177 sval.value = !sval.value;
178 break;
179 case '~':
180 sval.value = ~sval.value;
181 /* fixme: should probably cast this here */
182 break;
183 case '-':
184 sval.value = -sval.value;
185 break;
187 return sval;
190 sval_t sval_binop(sval_t left, int op, sval_t right)
192 sval_t ret;
194 /* fixme: these need to have proper type promotions */
195 ret.type = left.type;
196 switch (op) {
197 case '*':
198 ret.value = left.value * right.value;
199 break;
200 case '/':
201 if (right.value == 0) {
202 sm_msg("internal error: %s: divide by zero", __func__);
203 ret.value = 123456789;
204 } else {
205 ret.value = left.value / right.value;
207 break;
208 case '+':
209 ret.value = left.value + right.value;
210 break;
211 case '-':
212 ret.value = left.value - right.value;
213 break;
214 case '%':
215 if (right.value == 0) {
216 sm_msg("internal error: %s: MOD by zero", __func__);
217 ret.value = 123456789;
218 } else {
219 ret.value = left.value % right.value;
221 break;
222 case '|':
223 ret.value = left.value | right.value;
224 break;
225 case '&':
226 ret.value = left.value & right.value;
227 break;
228 case SPECIAL_RIGHTSHIFT:
229 ret.value = left.value >> right.value;
230 break;
231 case SPECIAL_LEFTSHIFT:
232 ret.value = left.value << right.value;
233 break;
234 case '^':
235 ret.value = left.value ^ right.value;
236 break;
237 default:
238 sm_msg("internal error: %s: unhandled binop %s", __func__,
239 show_special(op));
240 ret.value = 1234567;
242 return ret;
245 const char *sval_to_str(sval_t sval)
247 char buf[30];
249 if (sval_unsigned(sval) && sval.value == ULLONG_MAX)
250 return "u64max";
251 if (sval.value == LLONG_MAX)
252 return "max"; // FIXME: should be s64max
253 if (sval_unsigned(sval) && sval.value == UINT_MAX)
254 return "u32max";
255 if (sval.value == INT_MAX)
256 return "s32max";
257 if (sval_unsigned(sval) && sval.value == USHRT_MAX)
258 return "u16max";
260 if ((sval.type == &sshort_ctype || sval.type == &short_ctype) && sval.value == SHRT_MIN)
261 return "s16min";
262 if ((sval.type == &sint_ctype || sval.type == &int_ctype) && sval.value == INT_MIN)
263 return "s32min";
264 if (sval_signed(sval) && sval.value == LLONG_MIN)
265 return "min"; // FIXME: should be s64min
267 if (sval_unsigned(sval))
268 snprintf(buf, sizeof(buf), "%llu", sval.value);
269 else if (sval.value < 0)
270 snprintf(buf, sizeof(buf), "(%lld)", sval.value);
271 else
272 snprintf(buf, sizeof(buf), "%lld", sval.value);
274 return alloc_sname(buf);
278 * This function is for compatibility. Eventually everything will use svals
279 * and we can get rid of whole_range.max.
281 long long sval_to_ll(sval_t sval)
283 if (sval_unsigned(sval) && sval.value == ULLONG_MAX)
284 return whole_range.max;
285 return sval.value;
288 sval_t ll_to_sval(long long val)
290 sval_t ret;
292 ret.type = &llong_ctype;
293 ret.value = val;
294 return ret;
297 static void free_svals(struct symbol *sym)
299 clear_sval_alloc();
302 void register_sval(int my_id)
304 add_hook(&free_svals, END_FUNC_HOOK);