CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
json_expr.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Expressions in JSON
4
5Author: Peter Schrammel
6
7\*******************************************************************/
8
11
12#include "json_expr.h"
13
14#include <util/arith_tools.h>
15#include <util/c_types.h>
16#include <util/expr_util.h>
17#include <util/fixedbv.h>
18#include <util/identifier.h>
19#include <util/ieee_float.h>
20#include <util/invariant.h>
21#include <util/json.h>
22#include <util/namespace.h>
23#include <util/pointer_expr.h>
24#include <util/std_expr.h>
25
26#include <langapi/language.h>
27#include <langapi/mode.h>
28
29#include <memory>
30
31static exprt simplify_json_expr(const exprt &src)
32{
33 if(src.id() == ID_typecast)
34 {
35 return simplify_json_expr(to_typecast_expr(src).op());
36 }
37 else if(src.id() == ID_address_of)
38 {
39 const exprt &object = skip_typecast(to_address_of_expr(src).object());
40
41 if(object.id() == ID_symbol)
42 {
43 // simplify expressions of the form &symbol
44 return simplify_json_expr(object);
45 }
46 else if(
47 object.id() == ID_member &&
48 id2string(to_member_expr(object).get_component_name()).find("@") !=
49 std::string::npos)
50 {
51 // simplify expressions of the form &member(object, @class_identifier)
52 return simplify_json_expr(object);
53 }
54 else if(
55 object.id() == ID_index && to_index_expr(object).index().is_constant() &&
56 to_constant_expr(to_index_expr(object).index()).value_is_zero_string())
57 {
58 // simplify expressions of the form &array[0]
59 return simplify_json_expr(to_index_expr(object).array());
60 }
61 }
62 else if(
63 src.id() == ID_member &&
64 id2string(to_member_expr(src).get_component_name()).find("@") !=
65 std::string::npos)
66 {
67 // simplify expressions of the form member_expr(object, @class_identifier)
68 return simplify_json_expr(to_member_expr(src).struct_op());
69 }
70
71 return src;
72}
73
80json_objectt json(const typet &type, const namespacet &ns, const irep_idt &mode)
81{
82 json_objectt result;
83
84 if(type.id() == ID_unsignedbv)
85 {
86 result["name"] = json_stringt("integer");
87 result["width"] =
88 json_numbert(std::to_string(to_unsignedbv_type(type).get_width()));
89 }
90 else if(type.id() == ID_signedbv)
91 {
92 result["name"] = json_stringt("integer");
93 result["width"] =
94 json_numbert(std::to_string(to_signedbv_type(type).get_width()));
95 }
96 else if(type.id() == ID_floatbv)
97 {
98 result["name"] = json_stringt("float");
99 result["width"] =
100 json_numbert(std::to_string(to_floatbv_type(type).get_width()));
101 }
102 else if(type.id() == ID_bv)
103 {
104 result["name"] = json_stringt("integer");
105 result["width"] =
106 json_numbert(std::to_string(to_bv_type(type).get_width()));
107 }
108 else if(type.id() == ID_c_bit_field)
109 {
110 result["name"] = json_stringt("integer");
111 result["width"] =
112 json_numbert(std::to_string(to_c_bit_field_type(type).get_width()));
113 }
114 else if(type.id() == ID_c_enum_tag)
115 {
116 // we return the underlying type
117 return json(
118 ns.follow_tag(to_c_enum_tag_type(type)).underlying_type(), ns, mode);
119 }
120 else if(type.id() == ID_fixedbv)
121 {
122 result["name"] = json_stringt("fixed");
123 result["width"] =
124 json_numbert(std::to_string(to_fixedbv_type(type).get_width()));
125 }
126 else if(type.id() == ID_pointer)
127 {
128 result["name"] = json_stringt("pointer");
129 result["subtype"] = json(to_pointer_type(type).base_type(), ns, mode);
130 }
131 else if(type.id() == ID_bool)
132 {
133 result["name"] = json_stringt("boolean");
134 }
135 else if(type.id() == ID_array)
136 {
137 result["name"] = json_stringt("array");
138 result["subtype"] = json(to_array_type(type).element_type(), ns, mode);
139 result["size"] = json(to_array_type(type).size(), ns, mode);
140 }
141 else if(type.id() == ID_vector)
142 {
143 result["name"] = json_stringt("vector");
144 result["subtype"] = json(to_vector_type(type).element_type(), ns, mode);
145 result["size"] = json(to_vector_type(type).size(), ns, mode);
146 }
147 else if(type.id() == ID_struct)
148 {
149 result["name"] = json_stringt("struct");
150 json_arrayt &members = result["members"].make_array();
151 const struct_typet::componentst &components =
152 to_struct_type(type).components();
153 for(const auto &component : components)
154 {
155 json_objectt e{{"name", json_stringt(component.get_name())},
156 {"type", json(component.type(), ns, mode)}};
157 members.push_back(std::move(e));
158 }
159 }
160 else if(type.id() == ID_struct_tag)
161 {
162 return json(ns.follow_tag(to_struct_tag_type(type)), ns, mode);
163 }
164 else if(type.id() == ID_union)
165 {
166 result["name"] = json_stringt("union");
167 json_arrayt &members = result["members"].make_array();
168 const union_typet::componentst &components =
169 to_union_type(type).components();
170 for(const auto &component : components)
171 {
172 json_objectt e{{"name", json_stringt(component.get_name())},
173 {"type", json(component.type(), ns, mode)}};
174 members.push_back(std::move(e));
175 }
176 }
177 else if(type.id() == ID_union_tag)
178 {
179 return json(ns.follow_tag(to_union_tag_type(type)), ns, mode);
180 }
181 else
182 result["name"] = json_stringt("unknown");
183
184 return result;
185}
186
187static std::string binary(const constant_exprt &src)
188{
189 std::size_t width;
190 if(src.type().id() == ID_c_enum)
191 width = to_bitvector_type(to_c_enum_type(src.type()).underlying_type())
192 .get_width();
193 else
194 width = to_bitvector_type(src.type()).get_width();
195 const auto int_val = bvrep2integer(src.get_value(), width, false);
196 return integer2binary(int_val, width);
197}
198
205json_objectt json(const exprt &expr, const namespacet &ns, const irep_idt &mode)
206{
207 json_objectt result;
208
209 if(expr.is_constant())
210 {
212
213 const typet &type = expr.type();
214
215 std::unique_ptr<languaget> lang;
216 if(mode != ID_unknown)
217 lang = std::unique_ptr<languaget>(get_language_from_mode(mode));
218 if(!lang)
219 lang = std::unique_ptr<languaget>(get_default_language());
220
221 const typet &underlying_type =
222 type.id() == ID_c_bit_field ? to_c_bit_field_type(type).underlying_type()
223 : type;
224
225 std::string type_string;
226 bool error = lang->from_type(underlying_type, type_string, ns);
227 CHECK_RETURN(!error);
228
229 std::string value_string;
230 lang->from_expr(expr, value_string, ns);
231
232 if(
233 type.id() == ID_unsignedbv || type.id() == ID_signedbv ||
234 type.id() == ID_c_bit_field || type.id() == ID_c_bool)
235 {
236 std::size_t width = to_bitvector_type(type).get_width();
237
238 result["name"] = json_stringt("integer");
239 result["binary"] = json_stringt(binary(constant_expr));
240 result["width"] = json_numbert(std::to_string(width));
241 result["type"] = json_stringt(type_string);
242 result["data"] = json_stringt(value_string);
243 }
244 else if(type.id() == ID_c_enum)
245 {
246 result["name"] = json_stringt("integer");
247 result["binary"] = json_stringt(binary(constant_expr));
248 result["width"] = json_numbert(std::to_string(
249 to_bitvector_type(to_c_enum_type(type).underlying_type()).get_width()));
250 result["type"] = json_stringt("enum");
251 result["data"] = json_stringt(value_string);
252 }
253 else if(type.id() == ID_c_enum_tag)
254 {
256 constant_expr.get_value(), ns.follow_tag(to_c_enum_tag_type(type)));
257 return json(tmp, ns, mode);
258 }
259 else if(type.id() == ID_bv)
260 {
261 result["name"] = json_stringt("bitvector");
262 result["binary"] = json_stringt(binary(constant_expr));
263 }
264 else if(type.id() == ID_fixedbv)
265 {
266 result["name"] = json_stringt("fixed");
267 result["width"] =
268 json_numbert(std::to_string(to_bitvector_type(type).get_width()));
269 result["binary"] = json_stringt(binary(constant_expr));
270 result["data"] = json_stringt(fixedbvt(constant_expr).to_ansi_c_string());
271 }
272 else if(type.id() == ID_floatbv)
273 {
274 result["name"] = json_stringt("float");
275 result["width"] =
276 json_numbert(std::to_string(to_bitvector_type(type).get_width()));
277 result["binary"] = json_stringt(binary(constant_expr));
278 result["data"] =
279 json_stringt(ieee_float_valuet(constant_expr).to_ansi_c_string());
280 }
281 else if(type.id() == ID_pointer)
282 {
283 result["name"] = json_stringt("pointer");
284 result["type"] = json_stringt(type_string);
285 if(constant_expr.get_value() == ID_NULL)
286 result["data"] = json_stringt(value_string);
287 }
288 else if(type.id() == ID_bool)
289 {
290 result["name"] = json_stringt("boolean");
291 result["binary"] = json_stringt(expr.is_true() ? "1" : "0");
292 result["data"] = jsont::json_boolean(expr.is_true());
293 }
294 else if(type.id() == ID_string)
295 {
296 result["name"] = json_stringt("string");
297 result["data"] = json_stringt(constant_expr.get_value());
298 }
299 else
300 {
301 result["name"] = json_stringt("unknown");
302 }
303 }
304 else if(expr.id() == ID_annotated_pointer_constant)
305 {
308 exprt simpl_expr = simplify_json_expr(c.symbolic_pointer());
309
310 if(simpl_expr.id() == ID_symbol)
311 {
312 result["name"] = json_stringt("pointer");
313
314 const typet &type = expr.type();
315
316 std::unique_ptr<languaget> lang;
317 if(mode != ID_unknown)
318 lang = std::unique_ptr<languaget>(get_language_from_mode(mode));
319 if(!lang)
320 lang = std::unique_ptr<languaget>(get_default_language());
321
322 const typet &underlying_type =
323 type.id() == ID_c_bit_field
324 ? to_c_bit_field_type(type).underlying_type()
325 : type;
326
327 std::string type_string;
328 bool error = lang->from_type(underlying_type, type_string, ns);
329 CHECK_RETURN(!error);
330 result["type"] = json_stringt(type_string);
331
332 const irep_idt &ptr_id = to_symbol_expr(simpl_expr).get_identifier();
333 identifiert identifier(id2string(ptr_id));
335 !identifier.components.empty(),
336 "pointer identifier should have non-empty components");
337 result["data"] = json_stringt(identifier.components.back());
338 }
339 else if(simpl_expr.is_constant())
340 return json(simpl_expr, ns, mode);
341 else
342 result["name"] = json_stringt("unknown");
343 }
344 else if(expr.id() == ID_array)
345 {
346 result["name"] = json_stringt("array");
347 json_arrayt &elements = result["elements"].make_array();
348
349 std::size_t index = 0;
350
351 for(const auto &op : expr.operands())
352 {
353 json_objectt e{
354 {"index", json_numbert(std::to_string(index))},
355 {"value", json(op, ns, mode)}};
356 elements.push_back(std::move(e));
357 index++;
358 }
359 }
360 else if(expr.id() == ID_struct)
361 {
362 result["name"] = json_stringt("struct");
363
365 expr.type().id() == ID_struct_tag
367 : to_struct_type(expr.type());
368 const struct_typet::componentst &components = struct_type.components();
370 components.size() == expr.operands().size(),
371 "number of struct components should match with its type");
372
373 json_arrayt &members = result["members"].make_array();
374 for(std::size_t m = 0; m < expr.operands().size(); m++)
375 {
376 json_objectt e{
377 {"value", json(expr.operands()[m], ns, mode)},
378 {"name", json_stringt(components[m].get_name())}};
379 members.push_back(std::move(e));
380 }
381 }
382 else if(expr.id() == ID_union)
383 {
384 result["name"] = json_stringt("union");
385
386 const union_exprt &union_expr = to_union_expr(expr);
387 result["member"] =
388 json_objectt({{"value", json(union_expr.op(), ns, mode)},
389 {"name", json_stringt(union_expr.get_component_name())}});
390 }
391 else
392 result["name"] = json_stringt("unknown");
393
394 return result;
395}
mp_integer bvrep2integer(const irep_idt &src, std::size_t width, bool is_signed)
convert a bit-vector representation (possibly signed) to integer
const bv_typet & to_bv_type(const typet &type)
Cast a typet to a bv_typet.
const fixedbv_typet & to_fixedbv_type(const typet &type)
Cast a typet to a fixedbv_typet.
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
const unsignedbv_typet & to_unsignedbv_type(const typet &type)
Cast a typet to an unsignedbv_typet.
const signedbv_typet & to_signedbv_type(const typet &type)
Cast a typet to a signedbv_typet.
const c_bit_field_typet & to_c_bit_field_type(const typet &type)
Cast a typet to a c_bit_field_typet.
Definition c_types.h:80
const c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
Definition c_types.h:335
const c_enum_tag_typet & to_c_enum_tag_type(const typet &type)
Cast a typet to a c_enum_tag_typet.
Definition c_types.h:377
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition c_types.h:184
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition c_types.h:224
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Pointer-typed bitvector constant annotated with the pointer expression that the bitvector is the nume...
A constant literal expression.
Definition std_expr.h:3117
const irep_idt & get_value() const
Definition std_expr.h:3125
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
Base class for all expressions.
Definition expr.h:56
bool is_true() const
Return whether the expression is a constant representing true.
Definition expr.cpp:27
bool is_constant() const
Return whether the expression is a constant.
Definition expr.h:212
typet & type()
Return the type of the expression.
Definition expr.h:84
operandst & operands()
Definition expr.h:94
componentst components
Definition identifier.h:30
An IEEE 754 floating-point value, including specificiation.
Definition ieee_float.h:117
const irep_idt & id() const
Definition irep.h:388
jsont & push_back(const jsont &json)
Definition json.h:212
json_arrayt & make_array()
Definition json.h:418
static jsont json_boolean(bool value)
Definition json.h:97
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition namespace.cpp:49
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
Structure type, corresponds to C style structs.
Definition std_types.h:231
std::vector< componentt > componentst
Definition std_types.h:140
The type of an expression, extends irept.
Definition type.h:29
Union constructor from single element.
Definition std_expr.h:1770
const exprt & skip_typecast(const exprt &expr)
find the expression nested inside typecasts, if any
Deprecated expression utility functions.
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
static std::string binary(const constant_exprt &src)
static exprt simplify_json_expr(const exprt &src)
Definition json_expr.cpp:31
json_objectt json(const typet &type, const namespacet &ns, const irep_idt &mode)
Output a CBMC type in json.
Definition json_expr.cpp:80
Expressions in JSON.
Abstract interface to support a programming language.
std::unique_ptr< languaget > get_language_from_mode(const irep_idt &mode)
Get the language corresponding to the given mode.
Definition mode.cpp:51
std::unique_ptr< languaget > get_default_language()
Returns the default language.
Definition mode.cpp:139
const std::string integer2binary(const mp_integer &n, std::size_t width)
Definition mp_arith.cpp:64
API to expression classes for Pointers.
const annotated_pointer_constant_exprt & to_annotated_pointer_constant_expr(const exprt &expr)
Cast an exprt to an annotated_pointer_constant_exprt.
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
#define CHECK_RETURN(CONDITION)
Definition invariant.h:495
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition invariant.h:534
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition std_expr.cpp:97
API to expression classes.
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition std_expr.h:1538
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition std_expr.h:2107
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition std_expr.h:3063
const union_exprt & to_union_expr(const exprt &expr)
Cast an exprt to a union_exprt.
Definition std_expr.h:1816
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3172
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:272
const vector_typet & to_vector_type(const typet &type)
Cast a typet to a vector_typet.
Definition std_types.h:1116
bool is_constant(const typet &type)
This method tests, if the given typet is a constant.
Definition std_types.h:29
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition std_types.h:308
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition std_types.h:518
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition std_types.h:888