CBMC
json_expr.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Expressions in JSON
4 
5 Author: 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 
31 static 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 
80 json_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"] =
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 
187 static std::string binary(const constant_exprt &src)
188 {
189  std::size_t width;
190  if(src.type().id() == ID_c_enum)
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 
205 json_objectt json(const exprt &expr, const namespacet &ns, const irep_idt &mode)
206 {
207  json_objectt result;
208 
209  if(expr.is_constant())
210  {
211  const constant_exprt &constant_expr = to_constant_expr(expr);
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  {
255  constant_exprt tmp(
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_floatt(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
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 
364  const typet &type = ns.follow(expr.type());
365 
366  // these are expected to have a struct type
367  if(type.id() == ID_struct)
368  {
369  const struct_typet &struct_type = to_struct_type(type);
370  const struct_typet::componentst &components = struct_type.components();
372  components.size() == expr.operands().size(),
373  "number of struct components should match with its type");
374 
375  json_arrayt &members = result["members"].make_array();
376  for(std::size_t m = 0; m < expr.operands().size(); m++)
377  {
378  json_objectt e{{"value", json(expr.operands()[m], ns, mode)},
379  {"name", json_stringt(components[m].get_name())}};
380  members.push_back(std::move(e));
381  }
382  }
383  }
384  else if(expr.id() == ID_union)
385  {
386  result["name"] = json_stringt("union");
387 
388  const union_exprt &union_expr = to_union_expr(expr);
389  result["member"] =
390  json_objectt({{"value", json(union_expr.op(), ns, mode)},
391  {"name", json_stringt(union_expr.get_component_name())}});
392  }
393  else
394  result["name"] = json_stringt("unknown");
395 
396  return result;
397 }
mp_integer bvrep2integer(const irep_idt &src, std::size_t width, bool is_signed)
convert a bit-vector representation (possibly signed) to integer
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
const signedbv_typet & to_signedbv_type(const typet &type)
Cast a typet to a signedbv_typet.
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
const fixedbv_typet & to_fixedbv_type(const typet &type)
Cast a typet to a fixedbv_typet.
const unsignedbv_typet & to_unsignedbv_type(const typet &type)
Cast a typet to an unsignedbv_typet.
const bv_typet & to_bv_type(const typet &type)
Cast a typet to a bv_typet.
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 union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition: c_types.h:224
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 union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition: c_types.h:184
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
Pointer-typed bitvector constant annotated with the pointer expression that the bitvector is the nume...
std::size_t get_width() const
Definition: std_types.h:920
const typet & underlying_type() const
Definition: c_types.h:30
const typet & underlying_type() const
Definition: c_types.h:307
A constant literal expression.
Definition: std_expr.h:2987
const irep_idt & get_value() const
Definition: std_expr.h:2995
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
typet & type()
Return the type of the expression.
Definition: expr.h:84
bool is_constant() const
Return whether the expression is a constant.
Definition: expr.h:212
operandst & operands()
Definition: expr.h:94
componentst components
Definition: identifier.h:30
const irep_idt & id() const
Definition: irep.h:384
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 typet & follow(const typet &) const
Resolve type symbol to the type it points to.
Definition: namespace.cpp:49
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition: namespace.cpp:63
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
Structure type, corresponds to C style structs.
Definition: std_types.h:231
const componentst & components() const
Definition: std_types.h:147
std::vector< componentt > componentst
Definition: std_types.h:140
const irep_idt & get_identifier() const
Definition: std_expr.h:160
The type of an expression, extends irept.
Definition: type.h:29
const exprt & op() const
Definition: std_expr.h:391
Union constructor from single element.
Definition: std_expr.h:1765
irep_idt get_component_name() const
Definition: std_expr.h:1773
const exprt & skip_typecast(const exprt &expr)
find the expression nested inside typecasts, if any
Definition: expr_util.cpp:219
Deprecated expression utility functions.
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
static std::string binary(const constant_exprt &src)
Definition: json_expr.cpp:187
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 pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: pointer_expr.h:93
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
Definition: pointer_expr.h:577
#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:80
API to expression classes.
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition: std_expr.h:3037
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:272
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition: std_expr.h:2102
const union_exprt & to_union_expr(const exprt &expr)
Cast an exprt to a union_exprt.
Definition: std_expr.h:1811
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition: std_expr.h:2933
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition: std_expr.h:1533
const vector_typet & to_vector_type(const typet &type)
Cast a typet to a vector_typet.
Definition: std_types.h:1104
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:308
bool is_constant(const typet &type)
This method tests, if the given typet is a constant.
Definition: std_types.h:29
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:888
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition: std_types.h:518
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.