sval: pass type information to extra_undefined()
[smatch.git] / smatch_sval.c
blob240462f905ec5f0f8b4056234e5fa636741026a4
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, get_type(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_positive_bits(sval_t sval)
85 if (!sval.type)
86 return 31;
87 if (sval_signed(sval))
88 return sval.type->bit_size - 1;
89 return sval.type->bit_size;
92 int sval_is_min(sval_t sval)
94 sval_t min = sval_type_min(sval.type);
96 if (sval_unsigned(sval)) {
97 if (sval.uvalue == 0)
98 return 1;
99 return 0;
101 /* return true for less than min as well */
102 return (sval.value <= min.value);
105 int sval_is_max(sval_t sval)
107 sval_t max = sval_type_max(sval.type);
109 if (sval_unsigned(sval))
110 return (sval.uvalue >= max.value);
111 return (sval.value >= max.value);
115 * Returns -1 if one is smaller, 0 if they are the same and 1 if two is larger.
117 int sval_cmp(sval_t one, sval_t two)
119 sval_t tmp;
121 tmp = one;
122 if (sval_positive_bits(two) > sval_positive_bits(one))
123 tmp = two;
124 if (sval_bits(tmp) >= 32 && sval_unsigned(tmp)) {
125 if (one.uvalue < two.uvalue)
126 return -1;
127 if (one.uvalue == two.uvalue)
128 return 0;
129 return 1;
131 /* fix me handle type promotion and unsigned values */
132 if (one.value < two.value)
133 return -1;
134 if (one.value == two.value)
135 return 0;
136 return 1;
139 int sval_cmp_t(struct symbol *type, sval_t one, sval_t two)
141 sval_t one_cast, two_cast;
143 one_cast = sval_cast(one, type);
144 two_cast = sval_cast(two, type);
145 return sval_cmp(one_cast, two_cast);
148 int sval_cmp_val(sval_t one, long long val)
150 if (one.value < val)
151 return -1;
152 if (one.value == val)
153 return 0;
154 return 1;
157 sval_t sval_cast(sval_t sval, struct symbol *type)
159 sval_t ret;
161 if (!type)
162 type = &llong_ctype;
164 ret.type = type;
165 switch (sval_bits(ret)) {
166 case 8:
167 if (sval_unsigned(ret))
168 ret.value = (long long)(unsigned char)sval.value;
169 else
170 ret.value = (long long)(char)sval.value;
171 break;
172 case 16:
173 if (sval_unsigned(ret))
174 ret.value = (long long)(unsigned short)sval.value;
175 else
176 ret.value = (long long)(short)sval.value;
177 break;
178 case 32:
179 if (sval_unsigned(ret))
180 ret.value = (long long)(unsigned int)sval.value;
181 else
182 ret.value = (long long)(int)sval.value;
183 break;
184 default:
185 ret.value = sval.value;
187 return ret;
191 sval_t sval_preop(sval_t sval, int op)
193 switch (op) {
194 case '!':
195 sval.value = !sval.value;
196 break;
197 case '~':
198 sval.value = ~sval.value;
199 /* fixme: should probably cast this here */
200 break;
201 case '-':
202 sval.value = -sval.value;
203 break;
205 return sval;
208 sval_t sval_binop(sval_t left, int op, sval_t right)
210 sval_t ret;
212 /* fixme: these need to have proper type promotions */
213 ret.type = left.type;
214 switch (op) {
215 case '*':
216 ret.value = left.value * right.value;
217 break;
218 case '/':
219 if (right.value == 0) {
220 sm_msg("internal error: %s: divide by zero", __func__);
221 ret.value = 123456789;
222 } else {
223 ret.value = left.value / right.value;
225 break;
226 case '+':
227 ret.value = left.value + right.value;
228 break;
229 case '-':
230 ret.value = left.value - right.value;
231 break;
232 case '%':
233 if (right.value == 0) {
234 sm_msg("internal error: %s: MOD by zero", __func__);
235 ret.value = 123456789;
236 } else {
237 ret.value = left.value % right.value;
239 break;
240 case '|':
241 ret.value = left.value | right.value;
242 break;
243 case '&':
244 ret.value = left.value & right.value;
245 break;
246 case SPECIAL_RIGHTSHIFT:
247 ret.value = left.value >> right.value;
248 break;
249 case SPECIAL_LEFTSHIFT:
250 ret.value = left.value << right.value;
251 break;
252 case '^':
253 ret.value = left.value ^ right.value;
254 break;
255 default:
256 sm_msg("internal error: %s: unhandled binop %s", __func__,
257 show_special(op));
258 ret.value = 1234567;
260 return ret;
263 const char *sval_to_str(sval_t sval)
265 char buf[30];
267 if (sval.value && sval_bits(sval) > 8 && sval_is_min(sval))
268 return "min";
269 if (sval_bits(sval) > 8 && sval_is_max(sval))
270 return "max";
272 if (sval_unsigned(sval) && sval.value == ULLONG_MAX)
273 return "u64max";
274 if (sval.value == LLONG_MAX)
275 return "max"; // FIXME: should be s64max
276 if (sval_unsigned(sval) && sval.value == UINT_MAX)
277 return "u32max";
278 if (sval.value == INT_MAX)
279 return "s32max";
280 if (sval_unsigned(sval) && sval.value == USHRT_MAX)
281 return "u16max";
283 if ((sval.type == &sshort_ctype || sval.type == &short_ctype) && sval.value == SHRT_MIN)
284 return "s16min";
285 if ((sval.type == &sint_ctype || sval.type == &int_ctype) && sval.value == INT_MIN)
286 return "s32min";
287 if (sval_signed(sval) && sval.value == LLONG_MIN)
288 return "min"; // FIXME: should be s64min
290 if (sval_unsigned(sval))
291 snprintf(buf, sizeof(buf), "%llu", sval.value);
292 else if (sval.value < 0)
293 snprintf(buf, sizeof(buf), "(%lld)", sval.value);
294 else
295 snprintf(buf, sizeof(buf), "%lld", sval.value);
297 return alloc_sname(buf);
300 const char *sval_to_numstr(sval_t sval)
302 char buf[30];
304 if (sval_unsigned(sval))
305 snprintf(buf, sizeof(buf), "%llu", sval.value);
306 else if (sval.value < 0)
307 snprintf(buf, sizeof(buf), "(%lld)", sval.value);
308 else
309 snprintf(buf, sizeof(buf), "%lld", sval.value);
311 return alloc_sname(buf);
314 sval_t ll_to_sval(long long val)
316 sval_t ret;
318 ret.type = &llong_ctype;
319 ret.value = val;
320 return ret;
323 static void free_svals(struct symbol *sym)
325 clear_sval_alloc();
328 void register_sval(int my_id)
330 add_hook(&free_svals, END_FUNC_HOOK);