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 
18 
19 bvt map_bv(const endianness_mapt &map, const bvt &src)
20 {
21  PRECONDITION(map.number_of_bits() == src.size());
22  bvt result;
23  result.reserve(src.size());
24 
25  for(std::size_t i=0; i<src.size(); i++)
26  {
27  const size_t mapped_index = map.map_bit(i);
28  CHECK_RETURN(mapped_index < src.size());
29  result.push_back(src[mapped_index]);
30  }
31 
32  return result;
33 }
34 
36 {
37  // array logic does not handle byte operators, thus lower when operating on
38  // unbounded arrays
39  if(is_unbounded_array(expr.op().type()))
40  {
41  return convert_bv(lower_byte_extract(expr, ns));
42  }
43 
44  const std::size_t width = boolbv_width(expr.type());
45 
46  // special treatment for bit-fields and big-endian:
47  // we need byte granularity
48  #if 0
49  if(expr.id()==ID_byte_extract_big_endian &&
50  expr.type().id()==ID_c_bit_field &&
51  (width%8)!=0)
52  {
53  byte_extract_exprt tmp=expr;
54  // round up
55  to_c_bit_field_type(tmp.type()).set_width(width+8-width%8);
56  convert_byte_extract(tmp, bv);
57  bv.resize(width); // chop down
58  return;
59  }
60  #endif
61 
62  // see if the byte number is constant and within bounds, else work from the
63  // root object
64  const auto op_bytes_opt = pointer_offset_size(expr.op().type(), ns);
65  auto index = numeric_cast<mp_integer>(expr.offset());
66 
67  if(
68  (!index.has_value() || !op_bytes_opt.has_value() ||
69  *index < 0 || *index >= *op_bytes_opt) &&
70  (expr.op().id() == ID_member ||
71  expr.op().id() == ID_index ||
72  expr.op().id() == ID_byte_extract_big_endian ||
73  expr.op().id() == ID_byte_extract_little_endian))
74  {
76  o.build(expr.op(), ns);
77  CHECK_RETURN(o.offset().id() != ID_unknown);
78 
79  o.offset() =
81 
83  expr.id(),
84  o.root_object(),
85  plus_exprt(o.offset(), expr.offset()),
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  unsigned byte_width=8;
108 
109  if(index.has_value())
110  {
111  const mp_integer offset = *index * byte_width;
112 
113  for(std::size_t i=0; i<width; i++)
114  // out of bounds?
115  if(offset + i < 0 || offset + i >= op_bv.size())
116  bv[i]=prop.new_variable();
117  else
118  bv[i] = op_bv[numeric_cast_v<std::size_t>(offset + i)];
119  }
120  else
121  {
122  std::size_t bytes=op_bv.size()/byte_width;
123 
124  if(prop.has_set_to())
125  {
126  // free variables
127  bv = prop.new_variables(width);
128 
129  // add implications
130 
131  // type of index operand
132  const typet &constant_type = expr.offset().type();
133 
134  bvt equal_bv;
135  equal_bv.resize(width);
136 
137  for(std::size_t i=0; i<bytes; i++)
138  {
139  std::size_t offset=i*byte_width;
140 
141  for(std::size_t j=0; j<width; j++)
142  if(offset+j<op_bv.size())
143  equal_bv[j]=prop.lequal(bv[j], op_bv[offset+j]);
144  else
145  equal_bv[j]=const_literal(true);
146 
148  convert(equal_exprt(expr.offset(), from_integer(i, constant_type))),
149  prop.land(equal_bv)));
150  }
151  }
152  else
153  {
154  // type of index operand
155  const typet &constant_type = expr.offset().type();
156 
157  for(std::size_t i=0; i<bytes; i++)
158  {
159  literalt e =
160  convert(equal_exprt(expr.offset(), from_integer(i, constant_type)));
161 
162  std::size_t offset=i*byte_width;
163 
164  for(std::size_t j=0; j<width; j++)
165  {
166  literalt l;
167 
168  if(offset+j<op_bv.size())
169  l=op_bv[offset+j];
170  else
171  l=const_literal(false);
172 
173  if(i==0)
174  bv[j]=l;
175  else
176  bv[j]=prop.lselect(e, l, bv[j]);
177  }
178  }
179  }
180  }
181 
182  // shuffle the result
183  bv=map_bv(result_map, bv);
184 
185  return bv;
186 }
map_bv
bvt map_bv(const endianness_mapt &map, const bvt &src)
Definition: boolbv_byte_extract.cpp:19
pointer_offset_size.h
typecast_exprt::conditional_cast
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2025
mp_integer
BigInt mp_integer
Definition: smt_terms.h:17
arith_tools.h
object_descriptor_exprt::build
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...
Definition: pointer_expr.cpp:107
propt::new_variables
virtual bvt new_variables(std::size_t width)
generates a bitvector of given width with new variables
Definition: prop.cpp:20
boolbvt::is_unbounded_array
bool is_unbounded_array(const typet &type) const override
Definition: boolbv.cpp:518
CHECK_RETURN
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
typet
The type of an expression, extends irept.
Definition: type.h:28
bvt
std::vector< literalt > bvt
Definition: literal.h:201
object_descriptor_exprt
Split an expression into a base object and a (byte) offset.
Definition: pointer_expr.h:166
plus_exprt
The plus expression Associativity is not specified.
Definition: std_expr.h:946
lower_byte_extract
exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
rewrite byte extraction from an array to byte extraction from a concatenation of array index expressi...
Definition: byte_operators.cpp:1099
propt::new_variable
virtual literalt new_variable()=0
exprt
Base class for all expressions.
Definition: expr.h:55
propt::l_set_to_true
void l_set_to_true(literalt a)
Definition: prop.h:50
propt::land
virtual literalt land(literalt a, literalt b)=0
equal_exprt
Equality.
Definition: std_expr.h:1305
object_descriptor_exprt::root_object
static const exprt & root_object(const exprt &expr)
Definition: pointer_expr.cpp:168
expr_lowering.h
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
boolbvt::convert_byte_extract
virtual bvt convert_byte_extract(const byte_extract_exprt &expr)
Definition: boolbv_byte_extract.cpp:35
byte_operators.h
Expression classes for byte-level operators.
endianness_mapt::number_of_bits
size_t number_of_bits() const
Definition: endianness_map.h:55
propt::limplies
virtual literalt limplies(literalt a, literalt b)=0
boolbvt::boolbv_width
virtual std::size_t boolbv_width(const typet &type) const
Definition: boolbv.h:102
byte_extract_exprt::op
exprt & op()
Definition: byte_operators.h:43
boolbvt::convert_bv
virtual const bvt & convert_bv(const exprt &expr, const optionalt< 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
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
arrayst::ns
const namespacet & ns
Definition: arrays.h:56
endianness_mapt::map_bit
size_t map_bit(size_t bit) const
Definition: endianness_map.h:47
pointer_expr.h
const_literal
literalt const_literal(bool value)
Definition: literal.h:188
irept::id
const irep_idt & id() const
Definition: irep.h:396
bitvector_typet::set_width
void set_width(std::size_t width)
Definition: std_types.h:881
prop_conv_solvert::convert
literalt convert(const exprt &expr) override
Convert a Boolean expression and return the corresponding literal.
Definition: prop_conv_solver.cpp:156
byte_extract_exprt::offset
exprt & offset()
Definition: byte_operators.h:44
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
propt::lequal
virtual literalt lequal(literalt a, literalt b)=0
pointer_offset_size
optionalt< mp_integer > pointer_offset_size(const typet &type, const namespacet &ns)
Compute the size of a type in bytes, rounding up to full bytes.
Definition: pointer_offset_size.cpp:90
from_integer
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Definition: arith_tools.cpp:100
literalt
Definition: literal.h:25
byte_extract_exprt
Expression of type type extracted from some object op starting at position offset (given in number of...
Definition: byte_operators.h:28
propt::has_set_to
virtual bool has_set_to() const
Definition: prop.h:79
endianness_mapt
Maps a big-endian offset to a little-endian offset.
Definition: endianness_map.h:30
boolbv.h
boolbvt::endianness_map
virtual endianness_mapt endianness_map(const typet &type, bool little_endian) const
Definition: boolbv.h:108
std_expr.h
propt::lselect
virtual literalt lselect(literalt a, literalt b, literalt c)=0
prop_conv_solvert::prop
propt & prop
Definition: prop_conv_solver.h:130
object_descriptor_exprt::offset
exprt & offset()
Definition: pointer_expr.h:209