sval: extra: handle assignments better
[smatch.git] / smatch_sval.c
blob3881a9faf45f8b08c35c5feee3f5d86ce354d7de
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_type_val(struct symbol *type, long long val)
57 sval_t ret;
59 ret.type = type;
60 ret.value = val;
61 return ret;
64 sval_t sval_from_val(struct expression *expr, long long val)
66 sval_t ret;
68 ret = sval_blank(expr);
69 ret.value = val;
70 ret = sval_cast(get_type(expr), ret);
72 return ret;
75 int sval_unsigned(sval_t sval)
77 return type_unsigned(sval.type);
80 int sval_signed(sval_t sval)
82 return !type_unsigned(sval.type);
85 int sval_bits(sval_t sval)
87 if (!sval.type)
88 return 32;
89 return sval.type->bit_size;
92 int sval_positive_bits(sval_t sval)
94 if (!sval.type)
95 return 31;
96 if (sval_signed(sval))
97 return sval.type->bit_size - 1;
98 return sval.type->bit_size;
101 int sval_is_min(sval_t sval)
103 sval_t min = sval_type_min(sval.type);
105 if (sval_unsigned(sval)) {
106 if (sval.uvalue == 0)
107 return 1;
108 return 0;
110 /* return true for less than min as well */
111 return (sval.value <= min.value);
114 int sval_is_max(sval_t sval)
116 sval_t max = sval_type_max(sval.type);
118 if (sval_unsigned(sval))
119 return (sval.uvalue >= max.value);
120 return (sval.value >= max.value);
123 int sval_is_a_min(sval_t sval)
125 if (sval_signed(sval) && sval.value == SHRT_MIN)
126 return 1;
127 if (sval_signed(sval) && sval.value == INT_MIN)
128 return 1;
129 if (sval_signed(sval) && sval.value == LLONG_MIN)
130 return 1;
131 return 0;
134 int sval_is_a_max(sval_t sval)
136 if (sval.uvalue == SHRT_MAX)
137 return 1;
138 if (sval.uvalue == INT_MAX)
139 return 1;
140 if (sval.uvalue == LLONG_MAX)
141 return 1;
142 if (sval.uvalue == USHRT_MAX)
143 return 1;
144 if (sval.uvalue == UINT_MAX)
145 return 1;
146 if (sval_unsigned(sval) && sval.uvalue == ULLONG_MAX)
147 return 1;
148 return 0;
152 * Returns -1 if one is smaller, 0 if they are the same and 1 if two is larger.
154 int sval_cmp(sval_t one, sval_t two)
156 sval_t tmp;
158 tmp = one;
159 if (sval_positive_bits(two) > sval_positive_bits(one))
160 tmp = two;
161 if (sval_bits(tmp) >= 32 && sval_unsigned(tmp)) {
162 if (one.uvalue < two.uvalue)
163 return -1;
164 if (one.uvalue == two.uvalue)
165 return 0;
166 return 1;
168 /* fix me handle type promotion and unsigned values */
169 if (one.value < two.value)
170 return -1;
171 if (one.value == two.value)
172 return 0;
173 return 1;
176 int sval_cmp_t(struct symbol *type, sval_t one, sval_t two)
178 sval_t one_cast, two_cast;
180 one_cast = sval_cast(type, one);
181 two_cast = sval_cast(type, two);
182 return sval_cmp(one_cast, two_cast);
185 int sval_cmp_val(sval_t one, long long val)
187 if (one.value < val)
188 return -1;
189 if (one.value == val)
190 return 0;
191 return 1;
194 sval_t sval_cast(struct symbol *type, sval_t sval)
196 sval_t ret;
198 if (!type)
199 type = &llong_ctype;
201 ret.type = type;
202 switch (sval_bits(ret)) {
203 case 8:
204 if (sval_unsigned(ret))
205 ret.value = (long long)(unsigned char)sval.value;
206 else
207 ret.value = (long long)(char)sval.value;
208 break;
209 case 16:
210 if (sval_unsigned(ret))
211 ret.value = (long long)(unsigned short)sval.value;
212 else
213 ret.value = (long long)(short)sval.value;
214 break;
215 case 32:
216 if (sval_unsigned(ret))
217 ret.value = (long long)(unsigned int)sval.value;
218 else
219 ret.value = (long long)(int)sval.value;
220 break;
221 default:
222 ret.value = sval.value;
224 return ret;
228 sval_t sval_preop(sval_t sval, int op)
230 switch (op) {
231 case '!':
232 sval.value = !sval.value;
233 break;
234 case '~':
235 sval.value = ~sval.value;
236 /* fixme: should probably cast this here */
237 break;
238 case '-':
239 sval.value = -sval.value;
240 break;
242 return sval;
245 static sval_t sval_binop_unsigned(struct symbol *type, sval_t left, int op, sval_t right)
247 sval_t ret;
249 ret.type = type;
250 switch (op) {
251 case '*':
252 ret.uvalue = left.uvalue * right.uvalue;
253 break;
254 case '/':
255 if (right.uvalue == 0) {
256 sm_msg("debug: %s: divide by zero", __func__);
257 ret.uvalue = 123456789;
258 } else {
259 ret.uvalue = left.uvalue / right.uvalue;
261 break;
262 case '+':
263 ret.uvalue = left.uvalue + right.uvalue;
264 break;
265 case '-':
266 ret.uvalue = left.uvalue - right.uvalue;
267 break;
268 case '%':
269 if (right.uvalue == 0) {
270 sm_msg("internal error: %s: MOD by zero", __func__);
271 ret.uvalue = 123456789;
272 } else {
273 ret.uvalue = left.uvalue % right.uvalue;
275 break;
276 case '|':
277 ret.uvalue = left.uvalue | right.uvalue;
278 break;
279 case '&':
280 ret.uvalue = left.uvalue & right.uvalue;
281 break;
282 case SPECIAL_RIGHTSHIFT:
283 ret.uvalue = left.uvalue >> right.uvalue;
284 break;
285 case SPECIAL_LEFTSHIFT:
286 ret.uvalue = left.uvalue << right.uvalue;
287 break;
288 case '^':
289 ret.uvalue = left.uvalue ^ right.uvalue;
290 break;
291 default:
292 sm_msg("internal error: %s: unhandled binop %s", __func__,
293 show_special(op));
294 ret.uvalue = 1234567;
296 return ret;
300 static sval_t sval_binop_signed(struct symbol *type, sval_t left, int op, sval_t right)
302 sval_t ret;
304 ret.type = type;
305 switch (op) {
306 case '*':
307 ret.value = left.value * right.value;
308 break;
309 case '/':
310 if (right.value == 0) {
311 sm_msg("debug: %s: divide by zero", __func__);
312 ret.value = 123456789;
313 } else if (left.value == LLONG_MIN && right.value == -1) {
314 sm_msg("debug: %s: invalid divide LLONG_MIN/-1", __func__);
315 ret.value = 12345678;
316 } else {
317 ret.value = left.value / right.value;
319 break;
320 case '+':
321 ret.value = left.value + right.value;
322 break;
323 case '-':
324 ret.value = left.value - right.value;
325 break;
326 case '%':
327 if (right.value == 0) {
328 sm_msg("internal error: %s: MOD by zero", __func__);
329 ret.value = 123456789;
330 } else {
331 ret.value = left.value % right.value;
333 break;
334 case '|':
335 ret.value = left.value | right.value;
336 break;
337 case '&':
338 ret.value = left.value & right.value;
339 break;
340 case SPECIAL_RIGHTSHIFT:
341 ret.value = left.value >> right.value;
342 break;
343 case SPECIAL_LEFTSHIFT:
344 ret.value = left.value << right.value;
345 break;
346 case '^':
347 ret.value = left.value ^ right.value;
348 break;
349 default:
350 sm_msg("internal error: %s: unhandled binop %s", __func__,
351 show_special(op));
352 ret.value = 1234567;
354 return ret;
357 sval_t sval_binop(sval_t left, int op, sval_t right)
359 struct symbol *type;
360 sval_t ret;
362 type = left.type;
363 if (sval_positive_bits(right) > sval_positive_bits(left))
364 type = right.type;
365 if (type_positive_bits(type) < 31)
366 type = &int_ctype;
368 if (type_unsigned(type))
369 ret = sval_binop_unsigned(type, left, op, right);
370 else
371 ret = sval_binop_signed(type, left, op, right);
372 return ret;
375 const char *sval_to_str(sval_t sval)
377 char buf[30];
379 if (sval_unsigned(sval) && sval.value == ULLONG_MAX)
380 return "u64max";
381 if (sval.value == LLONG_MAX)
382 return "s64max";
383 if (sval_unsigned(sval) && sval.value == UINT_MAX)
384 return "u32max";
385 if (sval.value == INT_MAX)
386 return "s32max";
387 if (sval_unsigned(sval) && sval.value == USHRT_MAX)
388 return "u16max";
390 if (sval_signed(sval) && sval.value == SHRT_MIN)
391 return "s16min";
392 if (sval_signed(sval) && sval.value == INT_MIN)
393 return "s32min";
394 if (sval_signed(sval) && sval.value == LLONG_MIN)
395 return "s64min";
397 if (sval_unsigned(sval))
398 snprintf(buf, sizeof(buf), "%llu", sval.value);
399 else if (sval.value < 0)
400 snprintf(buf, sizeof(buf), "(%lld)", sval.value);
401 else
402 snprintf(buf, sizeof(buf), "%lld", sval.value);
404 return alloc_sname(buf);
407 const char *sval_to_numstr(sval_t sval)
409 char buf[30];
411 if (sval_unsigned(sval))
412 snprintf(buf, sizeof(buf), "%llu", sval.value);
413 else if (sval.value < 0)
414 snprintf(buf, sizeof(buf), "(%lld)", sval.value);
415 else
416 snprintf(buf, sizeof(buf), "%lld", sval.value);
418 return alloc_sname(buf);
421 sval_t ll_to_sval(long long val)
423 sval_t ret;
425 ret.type = &llong_ctype;
426 ret.value = val;
427 return ret;
430 static void free_svals(struct symbol *sym)
432 clear_sval_alloc();
435 void register_sval(int my_id)
437 add_hook(&free_svals, END_FUNC_HOOK);