CBMC
Loading...
Searching...
No Matches
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(object.id() == ID_index && to_index_expr(object).index() == 0)
55 {
56 // simplify expressions of the form &array[0]
57 return simplify_json_expr(to_index_expr(object).array());
58 }
59 }
60 else if(
61 src.id() == ID_member &&
62 id2string(to_member_expr(src).get_component_name()).find("@") !=
63 std::string::npos)
64 {
65 // simplify expressions of the form member_expr(object, @class_identifier)
66 return simplify_json_expr(to_member_expr(src).struct_op());
67 }
68
69 return src;
70}
71
78json_objectt json(const typet &type, const namespacet &ns, const irep_idt &mode)
79{
80 json_objectt result;
81
82 if(type.id() == ID_unsignedbv)
83 {
84 result["name"] = json_stringt("integer");
85 result["width"] =
86 json_numbert(std::to_string(to_unsignedbv_type(type).get_width()));
87 }
88 else if(type.id() == ID_signedbv)
89 {
90 result["name"] = json_stringt("integer");
91 result["width"] =
92 json_numbert(std::to_string(to_signedbv_type(type).get_width()));
93 }
94 else if(type.id() == ID_floatbv)
95 {
96 result["name"] = json_stringt("float");
97 result["width"] =
98 json_numbert(std::to_string(to_floatbv_type(type).get_width()));
99 }
100 else if(type.id() == ID_bv)
101 {
102 result["name"] = json_stringt("integer");
103 result["width"] =
104 json_numbert(std::to_string(to_bv_type(type).get_width()));
105 }
106 else if(type.id() == ID_c_bit_field)
107 {
108 result["name"] = json_stringt("integer");
109 result["width"] =
110 json_numbert(std::to_string(to_c_bit_field_type(type).get_width()));
111 }
112 else if(type.id() == ID_c_enum_tag)
113 {
114 // we return the underlying type
115 return json(
116 ns.follow_tag(to_c_enum_tag_type(type)).underlying_type(), ns, mode);
117 }
118 else if(type.id() == ID_fixedbv)
119 {
120 result["name"] = json_stringt("fixed");
121 result["width"] =
122 json_numbert(std::to_string(to_fixedbv_type(type).get_width()));
123 }
124 else if(type.id() == ID_pointer)
125 {
126 result["name"] = json_stringt("pointer");
127 result["subtype"] = json(to_pointer_type(type).base_type(), ns, mode);
128 }
129 else if(type.id() == ID_bool)
130 {
131 result["name"] = json_stringt("boolean");
132 }
133 else if(type.id() == ID_array)
134 {
135 result["name"] = json_stringt("array");
136 result["subtype"] = json(to_array_type(type).element_type(), ns, mode);
137 result["size"] = json(to_array_type(type).size(), ns, mode);
138 }
139 else if(type.id() == ID_vector)
140 {
141 result["name"] = json_stringt("vector");
142 result["subtype"] = json(to_vector_type(type).element_type(), ns, mode);
143 result["size"] = json(to_vector_type(type).size(), ns, mode);
144 }
145 else if(type.id() == ID_struct)
146 {
147 result["name"] = json_stringt("struct");
148 json_arrayt &members = result["members"].make_array();
149 const struct_typet::componentst &components =
150 to_struct_type(type).components();
151 for(const auto &component : components)
152 {
153 json_objectt e{{"name", json_stringt(component.get_name())},
154 {"type", json(component.type(), ns, mode)}};
155 members.push_back(std::move(e));
156 }
157 }
158 else if(type.id() == ID_struct_tag)
159 {
160 return json(ns.follow_tag(to_struct_tag_type(type)), ns, mode);
161 }
162 else if(type.id() == ID_union)
163 {
164 result["name"] = json_stringt("union");
165 json_arrayt &members = result["members"].make_array();
166 const union_typet::componentst &components =
167 to_union_type(type).components();
168 for(const auto &component : components)
169 {
170 json_objectt e{{"name", json_stringt(component.get_name())},
171 {"type", json(component.type(), ns, mode)}};
172 members.push_back(std::move(e));
173 }
174 }
175 else if(type.id() == ID_union_tag)
176 {
177 return json(ns.follow_tag(to_union_tag_type(type)), ns, mode);
178 }
179 else
180 result["name"] = json_stringt("unknown");
181
182 return result;
183}
184
185static std::string binary(const constant_exprt &src)
186{
187 std::size_t width;
188 if(src.type().id() == ID_c_enum)
189 width = to_bitvector_type(to_c_enum_type(src.type()).underlying_type())
190 .get_width();
191 else
192 width = to_bitvector_type(src.type()).get_width();
193 const auto int_val = bvrep2integer(src.get_value(), width, false);
194 return integer2binary(int_val, width);
195}
196
203json_objectt json(const exprt &expr, const namespacet &ns, const irep_idt &mode)
204{
205 json_objectt result;
206
207 if(expr.is_constant())
208 {
210
211 const typet &type = expr.type();
212
213 std::unique_ptr<languaget> lang;
214 if(mode != ID_unknown)
215 lang = std::unique_ptr<languaget>(get_language_from_mode(mode));
216 if(!lang)
217 lang = std::unique_ptr<languaget>(get_default_language());
218
219 const typet &underlying_type =
220 type.id() == ID_c_bit_field ? to_c_bit_field_type(type).underlying_type()
221 : type;
222
223 std::string type_string;
224 bool error = lang->from_type(underlying_type, type_string, ns);
225 CHECK_RETURN(!error);
226
227 std::string value_string;
228 lang->from_expr(expr, value_string, ns);
229
230 if(
231 type.id() == ID_unsignedbv || type.id() == ID_signedbv ||
232 type.id() == ID_c_bit_field || type.id() == ID_c_bool)
233 {
234 std::size_t width = to_bitvector_type(type).get_width();
235
236 result["name"] = json_stringt("integer");
237 result["binary"] = json_stringt(binary(constant_expr));
238 result["width"] = json_numbert(std::to_string(width));
239 result["type"] = json_stringt(type_string);
240 result["data"] = json_stringt(value_string);
241 }
242 else if(type.id() == ID_c_enum)
243 {
244 result["name"] = json_stringt("integer");
245 result["binary"] = json_stringt(binary(constant_expr));
246 result["width"] = json_numbert(std::to_string(
247 to_bitvector_type(to_c_enum_type(type).underlying_type()).get_width()));
248 result["type"] = json_stringt("enum");
249 result["data"] = json_stringt(value_string);
250 }
251 else if(type.id() == ID_c_enum_tag)
252 {
254 constant_expr.get_value(), ns.follow_tag(to_c_enum_tag_type(type)));
255 return json(tmp, ns, mode);
256 }
257 else if(type.id() == ID_bv)
258 {
259 result["name"] = json_stringt("bitvector");
260 result["binary"] = json_stringt(binary(constant_expr));
261 }
262 else if(type.id() == ID_fixedbv)
263 {
264 result["name"] = json_stringt("fixed");
265 result["width"] =
266 json_numbert(std::to_string(to_bitvector_type(type).get_width()));
267 result["binary"] = json_stringt(binary(constant_expr));
268 result["data"] = json_stringt(fixedbvt(constant_expr).to_ansi_c_string());
269 }
270 else if(type.id() == ID_floatbv)
271 {
272 result["name"] = json_stringt("float");
273 result["width"] =
274 json_numbert(std::to_string(to_bitvector_type(type).get_width()));
275 result["binary"] = json_stringt(binary(constant_expr));
276 result["data"] =
277 json_stringt(ieee_float_valuet(constant_expr).to_ansi_c_string());
278 }
279 else if(type.id() == ID_pointer)
280 {
281 result["name"] = json_stringt("pointer");
282 result["type"] = json_stringt(type_string);
283 if(constant_expr.get_value() == ID_NULL)
284 result["data"] = json_stringt(value_string);
285 }
286 else if(type.id() == ID_bool)
287 {
288 result["name"] = json_stringt("boolean");
289 result["binary"] = json_stringt(expr == true ? "1" : "0");
290 result["data"] = jsont::json_boolean(expr == true);
291 }
292 else if(type.id() == ID_string)
293 {
294 result["name"] = json_stringt("string");
295 result["data"] = json_stringt(constant_expr.get_value());
296 }
297 else
298 {
299 result["name"] = json_stringt("unknown");
300 }
301 }
302 else if(expr.id() == ID_annotated_pointer_constant)
303 {
306 exprt simpl_expr = simplify_json_expr(c.symbolic_pointer());
307
308 if(simpl_expr.id() == ID_symbol)
309 {
310 result["name"] = json_stringt("pointer");
311
312 const typet &type = expr.type();
313
314 std::unique_ptr<languaget> lang;
315 if(mode != ID_unknown)
316 lang = std::unique_ptr<languaget>(get_language_from_mode(mode));
317 if(!lang)
318 lang = std::unique_ptr<languaget>(get_default_language());
319
320 const typet &underlying_type =
321 type.id() == ID_c_bit_field
322 ? to_c_bit_field_type(type).underlying_type()
323 : type;
324
325 std::string type_string;
326 bool error = lang->from_type(underlying_type, type_string, ns);
327 CHECK_RETURN(!error);
328 result["type"] = json_stringt(type_string);
329
330 const irep_idt &ptr_id = to_symbol_expr(simpl_expr).get_identifier();
331 identifiert identifier(id2string(ptr_id));
333 !identifier.components.empty(),
334 "pointer identifier should have non-empty components");
335 result["data"] = json_stringt(identifier.components.back());
336 }
337 else if(simpl_expr.is_constant())
338 return json(simpl_expr, ns, mode);
339 else
340 result["name"] = json_stringt("unknown");
341 }
342 else if(expr.id() == ID_array)
343 {
344 result["name"] = json_stringt("array");
345 json_arrayt &elements = result["elements"].make_array();
346
347 std::size_t index = 0;
348
349 for(const auto &op : expr.operands())
350 {
351 json_objectt e{
352 {"index", json_numbert(std::to_string(index))},
353 {"value", json(op, ns, mode)}};
354 elements.push_back(std::move(e));
355 index++;
356 }
357 }
358 else if(expr.id() == ID_struct)
359 {
360 result["name"] = json_stringt("struct");
361
363 expr.type().id() == ID_struct_tag
365 : to_struct_type(expr.type());
366 const struct_typet::componentst &components = struct_type.components();
368 components.size() == expr.operands().size(),
369 "number of struct components should match with its type");
370
371 json_arrayt &members = result["members"].make_array();
372 for(std::size_t m = 0; m < expr.operands().size(); m++)
373 {
374 json_objectt e{
375 {"value", json(expr.operands()[m], ns, mode)},
376 {"name", json_stringt(components[m].get_name())}};
377 members.push_back(std::move(e));
378 }
379 }
380 else if(expr.id() == ID_union)
381 {
382 result["name"] = json_stringt("union");
383
384 const union_exprt &union_expr = to_union_expr(expr);
385 result["member"] =
386 json_objectt({{"value", json(union_expr.op(), ns, mode)},
387 {"name", json_stringt(union_expr.get_component_name())}});
388 }
389 else
390 result["name"] = json_stringt("unknown");
391
392 return result;
393}
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:3118
const irep_idt & get_value() const
Definition std_expr.h:3126
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:57
bool is_constant() const
Return whether the expression is a constant.
Definition expr.h:213
typet & type()
Return the type of the expression.
Definition expr.h:85
operandst & operands()
Definition expr.h:95
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:78
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:291
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:3064
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:3189
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
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