CBMC
boolbv_byte_extract.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module:
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
9 #include "boolbv.h"
10 
11 #include <util/arith_tools.h>
12 #include <util/byte_operators.h>
13 #include <util/pointer_expr.h>
15 #include <util/std_expr.h>
16 
17 bvt map_bv(const endianness_mapt &map, const bvt &src)
18 {
19  PRECONDITION(map.number_of_bits() == src.size());
20  bvt result;
21  result.reserve(src.size());
22 
23  for(std::size_t i=0; i<src.size(); i++)
24  {
25  const size_t mapped_index = map.map_bit(i);
26  CHECK_RETURN(mapped_index < src.size());
27  result.push_back(src[mapped_index]);
28  }
29 
30  return result;
31 }
32 
34 {
35  // array logic does not handle byte operators, thus lower when operating on
36  // unbounded arrays
37  if(is_unbounded_array(expr.op().type()))
38  {
39  return convert_bv(lower_byte_extract(expr, ns));
40  }
41 
42  const std::size_t width = boolbv_width(expr.type());
43 
44  // special treatment for bit-fields and big-endian:
45  // we need byte granularity
46  #if 0
47  if(expr.id()==ID_byte_extract_big_endian &&
48  expr.type().id()==ID_c_bit_field &&
49  (width%expr.get_bits_per_byte())!=0)
50  {
51  byte_extract_exprt tmp=expr;
52  // round up
54  width+expr.get_bits_per_byte()-width%expr.get_bits_per_byte());
55  convert_byte_extract(tmp, bv);
56  bv.resize(width); // chop down
57  return;
58  }
59  #endif
60 
61  // see if the byte number is constant and within bounds, else work from the
62  // root object
63  const auto op_bytes_opt = pointer_offset_size(expr.op().type(), ns);
64  auto index = numeric_cast<mp_integer>(expr.offset());
65 
66  if(
67  (!index.has_value() || !op_bytes_opt.has_value() ||
68  *index < 0 || *index >= *op_bytes_opt) &&
69  (expr.op().id() == ID_member ||
70  expr.op().id() == ID_index ||
71  expr.op().id() == ID_byte_extract_big_endian ||
72  expr.op().id() == ID_byte_extract_little_endian))
73  {
75  o.build(expr.op(), ns);
76  CHECK_RETURN(o.offset().id() != ID_unknown);
77 
78  o.offset() =
80 
82  expr.id(),
83  o.root_object(),
84  plus_exprt(o.offset(), expr.offset()),
85  expr.get_bits_per_byte(),
86  expr.type());
87 
88  return convert_bv(be);
89  }
90 
91  const exprt &op=expr.op();
93  expr.id() == ID_byte_extract_little_endian ||
94  expr.id() == ID_byte_extract_big_endian);
95  const bool little_endian = expr.id() == ID_byte_extract_little_endian;
96 
97  // first do op0
98  const endianness_mapt op_map = endianness_map(op.type(), little_endian);
99  const bvt op_bv=map_bv(op_map, convert_bv(op));
100 
101  // do result
102  endianness_mapt result_map = endianness_map(expr.type(), little_endian);
103  bvt bv;
104  bv.resize(width);
105 
106  // see if the byte number is constant
107  if(index.has_value())
108  {
109  const mp_integer offset = *index * expr.get_bits_per_byte();
110 
111  for(std::size_t i=0; i<width; i++)
112  // out of bounds?
113  if(offset + i < 0 || offset + i >= op_bv.size())
114  bv[i]=prop.new_variable();
115  else
116  bv[i] = op_bv[numeric_cast_v<std::size_t>(offset + i)];
117  }
118  else
119  {
120  std::size_t bytes = op_bv.size() / expr.get_bits_per_byte();
121 
122  if(prop.has_set_to())
123  {
124  // free variables
125  bv = prop.new_variables(width);
126 
127  // add implications
128 
129  // type of index operand
130  const typet &constant_type = expr.offset().type();
131 
132  bvt equal_bv;
133  equal_bv.resize(width);
134 
135  for(std::size_t i=0; i<bytes; i++)
136  {
137  std::size_t offset = i * expr.get_bits_per_byte();
138 
139  for(std::size_t j=0; j<width; j++)
140  if(offset+j<op_bv.size())
141  equal_bv[j]=prop.lequal(bv[j], op_bv[offset+j]);
142  else
143  equal_bv[j]=const_literal(true);
144 
146  convert(equal_exprt(expr.offset(), from_integer(i, constant_type))),
147  prop.land(equal_bv)));
148  }
149  }
150  else
151  {
152  // type of index operand
153  const typet &constant_type = expr.offset().type();
154 
155  for(std::size_t i=0; i<bytes; i++)
156  {
157  literalt e =
158  convert(equal_exprt(expr.offset(), from_integer(i, constant_type)));
159 
160  std::size_t offset = i * expr.get_bits_per_byte();
161 
162  for(std::size_t j=0; j<width; j++)
163  {
164  literalt l;
165 
166  if(offset+j<op_bv.size())
167  l=op_bv[offset+j];
168  else
169  l=const_literal(false);
170 
171  if(i==0)
172  bv[j]=l;
173  else
174  bv[j]=prop.lselect(e, l, bv[j]);
175  }
176  }
177  }
178  }
179 
180  // shuffle the result
181  bv=map_bv(result_map, bv);
182 
183  return bv;
184 }
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Definition: arith_tools.cpp:99
bvt map_bv(const endianness_mapt &map, const bvt &src)
Expression classes for byte-level operators.
exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
Rewrite a byte extract expression to more fundamental operations.
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 namespacet & ns
Definition: arrays.h:56
void set_width(std::size_t width)
Definition: std_types.h:932
virtual const bvt & convert_bv(const exprt &expr, const std::optional< std::size_t > expected_width={})
Convert expression to vector of literalts, using an internal cache to speed up conversion if availabl...
Definition: boolbv.cpp:39
virtual bvt convert_byte_extract(const byte_extract_exprt &expr)
bool is_unbounded_array(const typet &type) const override
Definition: boolbv.cpp:535
virtual endianness_mapt endianness_map(const typet &type, bool little_endian) const
Definition: boolbv.h:108
virtual std::size_t boolbv_width(const typet &type) const
Definition: boolbv.h:102
Expression of type type extracted from some object op starting at position offset (given in number of...
std::size_t get_bits_per_byte() const
Maps a big-endian offset to a little-endian offset.
size_t number_of_bits() const
size_t map_bit(size_t bit) const
Equality.
Definition: std_expr.h:1366
Base class for all expressions.
Definition: expr.h:56
typet & type()
Return the type of the expression.
Definition: expr.h:84
const irep_idt & id() const
Definition: irep.h:388
Split an expression into a base object and a (byte) offset.
Definition: pointer_expr.h:181
void build(const exprt &expr, const namespacet &ns)
Given an expression expr, attempt to find the underlying object it represents by skipping over type c...
static const exprt & root_object(const exprt &expr)
The plus expression Associativity is not specified.
Definition: std_expr.h:1002
literalt convert(const exprt &expr) override
Convert a Boolean expression and return the corresponding literal.
void l_set_to_true(literalt a)
Definition: prop.h:52
virtual literalt land(literalt a, literalt b)=0
virtual literalt limplies(literalt a, literalt b)=0
virtual literalt lselect(literalt a, literalt b, literalt c)=0
virtual bvt new_variables(std::size_t width)
generates a bitvector of given width with new variables
Definition: prop.cpp:30
virtual literalt new_variable()=0
virtual literalt lequal(literalt a, literalt b)=0
virtual bool has_set_to() const
Definition: prop.h:81
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2081
The type of an expression, extends irept.
Definition: type.h:29
std::vector< literalt > bvt
Definition: literal.h:201
literalt const_literal(bool value)
Definition: literal.h:188
API to expression classes for Pointers.
std::optional< mp_integer > pointer_offset_size(const typet &type, const namespacet &ns)
Compute the size of a type in bytes, rounding up to full bytes.
Pointer Logic.
BigInt mp_integer
Definition: smt_terms.h:17
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
API to expression classes.