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.
20 #include "smatch_slist.h"
21 #include "smatch_extra.h"
23 __ALLOCATOR(sval_t
, "svals", sval
);
25 sval_t
*sval_alloc(sval_t sval
)
29 ret
= __alloc_sval(0);
34 sval_t
*sval_alloc_permanent(sval_t sval
)
38 ret
= malloc(sizeof(*ret
));
43 sval_t
sval_blank(struct expression
*expr
)
47 ret
.type
= get_type(expr
);
49 ret
.type
= &llong_ctype
;
50 ret
.value
= 123456789;
55 sval_t
sval_from_val(struct expression
*expr
, long long val
)
59 ret
= sval_blank(expr
);
61 ret
= sval_cast(ret
, expr
);
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
)
80 return sval
.type
->bit_size
;
84 * Casts the values and then does a compare. Returns -1 if one is smaller, 0 if
85 * they are the same and 1 if two is larger.
87 int sval_cmp(sval_t one
, sval_t two
)
89 if (one
.value
< two
.value
)
91 if (one
.value
== two
.value
)
96 int sval_cmp_val(sval_t one
, long long val
)
100 if (one
.value
== val
)
105 sval_t
sval_cast(sval_t sval
, struct expression
*expr
)
109 ret
= sval_blank(expr
);
110 switch (sval_bits(ret
)) {
112 if (sval_unsigned(ret
))
113 ret
.value
= (long long)(unsigned char)sval
.value
;
115 ret
.value
= (long long)(char)sval
.value
;
118 if (sval_unsigned(ret
))
119 ret
.value
= (long long)(unsigned short)sval
.value
;
121 ret
.value
= (long long)(short)sval
.value
;
124 if (sval_unsigned(ret
))
125 ret
.value
= (long long)(unsigned int)sval
.value
;
127 ret
.value
= (long long)(int)sval
.value
;
130 ret
.value
= sval
.value
;
136 sval_t
sval_preop(sval_t sval
, int op
)
140 sval
.value
= !sval
.value
;
143 sval
.value
= ~sval
.value
;
144 /* fixme: should probably cast this here */
147 sval
.value
= -sval
.value
;
153 sval_t
sval_binop(sval_t left
, int op
, sval_t right
)
157 /* fixme: these need to have proper type promotions */
158 ret
.type
= left
.type
;
161 ret
.value
= left
.value
* right
.value
;
164 if (right
.value
== 0) {
165 sm_msg("internal error: %s: divide by zero", __func__
);
166 ret
.value
= 123456789;
168 ret
.value
= left
.value
/ right
.value
;
172 ret
.value
= left
.value
+ right
.value
;
175 ret
.value
= left
.value
- right
.value
;
178 if (right
.value
== 0) {
179 sm_msg("internal error: %s: MOD by zero", __func__
);
180 ret
.value
= 123456789;
182 ret
.value
= left
.value
% right
.value
;
186 ret
.value
= left
.value
| right
.value
;
189 ret
.value
= left
.value
& right
.value
;
191 case SPECIAL_RIGHTSHIFT
:
192 ret
.value
= left
.value
>> right
.value
;
194 case SPECIAL_LEFTSHIFT
:
195 ret
.value
= left
.value
<< right
.value
;
198 ret
.value
= left
.value
^ right
.value
;
201 sm_msg("internal error: %s: unhandled binop %s", __func__
,
208 const char *sval_to_str(sval_t sval
)
212 if (sval_unsigned(sval
) && sval
.value
== ULLONG_MAX
)
214 if (sval
.value
== LLONG_MAX
)
216 if (sval_unsigned(sval
) && sval
.value
== UINT_MAX
)
218 if (sval
.value
== INT_MAX
)
220 if (sval_unsigned(sval
) && sval
.value
== USHRT_MAX
)
223 if ((sval
.type
== &sshort_ctype
|| sval
.type
== &short_ctype
) && sval
.value
== SHRT_MIN
)
225 if ((sval
.type
== &sint_ctype
|| sval
.type
== &int_ctype
) && sval
.value
== INT_MIN
)
227 if (sval_signed(sval
) && sval
.value
== LLONG_MIN
)
230 if (sval_unsigned(sval
))
231 snprintf(buf
, sizeof(buf
), "%llu", sval
.value
);
232 else if (sval
.value
< 0)
233 snprintf(buf
, sizeof(buf
), "(%lld)", sval
.value
);
235 snprintf(buf
, sizeof(buf
), "%lld", sval
.value
);
241 * This function is for compatibility. Eventually everything will use svals
242 * and we can get rid of whole_range.max.
244 long long sval_to_ll(sval_t sval
)
246 if (sval_unsigned(sval
) && sval
.value
== ULLONG_MAX
)
247 return whole_range
.max
;
251 static void free_svals(struct symbol
*sym
)
256 void register_sval(int my_id
)
258 add_hook(&free_svals
, END_FUNC_HOOK
);