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