-
Notifications
You must be signed in to change notification settings - Fork 273
/
Copy pathbyte_operators.h
195 lines (162 loc) · 5.72 KB
/
byte_operators.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*******************************************************************\
Module:
Author: Daniel Kroening, [email protected]
\*******************************************************************/
#ifndef CPROVER_UTIL_BYTE_OPERATORS_H
#define CPROVER_UTIL_BYTE_OPERATORS_H
/*! \file util/byte_operators.h
* \brief Expression classes for byte-level operators
*
* \author Daniel Kroening <[email protected]>
* \date Sun Jul 31 21:54:44 BST 2011
*/
#include "invariant.h"
#include "std_expr.h"
/// Expression of type \c type extracted from some object \c op starting at
/// position \c offset (given in number of bytes).
/// The object can either be interpreted in big endian or little endian, which
/// is reflected by the \c id of the expression which is either
/// \c ID_byte_extract_big_endian or \c ID_byte_extract_little_endian
class byte_extract_exprt : public binary_exprt
{
public:
byte_extract_exprt(
irep_idt _id,
const exprt &_op,
const exprt &_offset,
std::size_t bits_per_byte,
const typet &_type)
: binary_exprt(_op, _id, _offset, _type)
{
INVARIANT(
_id == ID_byte_extract_little_endian || _id == ID_byte_extract_big_endian,
"byte_extract_exprt: Invalid ID");
set_bits_per_byte(bits_per_byte);
}
exprt &op() { return op0(); }
exprt &offset() { return op1(); }
const exprt &op() const { return op0(); }
const exprt &offset() const { return op1(); }
std::size_t get_bits_per_byte() const
{
return get_size_t(ID_bits_per_byte);
}
void set_bits_per_byte(std::size_t bits_per_byte)
{
set_size_t(ID_bits_per_byte, bits_per_byte);
}
};
template <>
inline bool can_cast_expr<byte_extract_exprt>(const exprt &base)
{
return base.id() == ID_byte_extract_little_endian ||
base.id() == ID_byte_extract_big_endian;
}
inline const byte_extract_exprt &to_byte_extract_expr(const exprt &expr)
{
PRECONDITION(expr.operands().size() == 2);
return static_cast<const byte_extract_exprt &>(expr);
}
inline byte_extract_exprt &to_byte_extract_expr(exprt &expr)
{
PRECONDITION(expr.operands().size() == 2);
return static_cast<byte_extract_exprt &>(expr);
}
inline void validate_expr(const byte_extract_exprt &value)
{
validate_operands(value, 2, "Byte extract must have two operands");
}
/// Expression corresponding to \c op() where the bytes starting at
/// position \c offset (given in number of bytes) have been updated with
/// \c value.
class byte_update_exprt : public ternary_exprt
{
public:
byte_update_exprt(
irep_idt _id,
const exprt &_op,
const exprt &_offset,
const exprt &_value,
std::size_t bits_per_byte)
: ternary_exprt(_id, _op, _offset, _value, _op.type())
{
INVARIANT(
_id == ID_byte_update_little_endian || _id == ID_byte_update_big_endian,
"byte_update_exprt: Invalid ID");
set_bits_per_byte(bits_per_byte);
}
void set_op(exprt e)
{
op0() = std::move(e);
}
void set_offset(exprt e)
{
op1() = std::move(e);
}
void set_value(exprt e)
{
op2() = std::move(e);
}
const exprt &op() const { return op0(); }
const exprt &offset() const { return op1(); }
const exprt &value() const { return op2(); }
std::size_t get_bits_per_byte() const
{
return get_size_t(ID_bits_per_byte);
}
void set_bits_per_byte(std::size_t bits_per_byte)
{
set_size_t(ID_bits_per_byte, bits_per_byte);
}
};
template <>
inline bool can_cast_expr<byte_update_exprt>(const exprt &base)
{
return base.id() == ID_byte_update_little_endian ||
base.id() == ID_byte_update_big_endian;
}
inline const byte_update_exprt &to_byte_update_expr(const exprt &expr)
{
PRECONDITION(expr.operands().size() == 3);
return static_cast<const byte_update_exprt &>(expr);
}
inline byte_update_exprt &to_byte_update_expr(exprt &expr)
{
PRECONDITION(expr.operands().size() == 3);
return static_cast<byte_update_exprt &>(expr);
}
/// Construct a byte_extract_exprt with endianness and byte width matching the
/// current configuration.
byte_extract_exprt
make_byte_extract(const exprt &_op, const exprt &_offset, const typet &_type);
/// Construct a byte_update_exprt with endianness and byte width matching the
/// current configuration.
byte_update_exprt
make_byte_update(const exprt &_op, const exprt &_offset, const exprt &_value);
/// Return true iff \p src or one of its operands contain a byte extract or byte
/// update expression.
bool has_byte_operator(const exprt &src);
/// Rewrite a byte extract expression to more fundamental operations.
/// \param src: Byte extract expression
/// \param ns: Namespace
/// \return Semantically equivalent expression such that the top-level
/// expression no longer is a \ref byte_extract_exprt or
/// \ref byte_update_exprt. Use \ref lower_byte_operators to also remove all
/// byte operators from any operands of \p src.
exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns);
/// Rewrite a byte update expression to more fundamental operations.
/// \param src: Byte update expression
/// \param ns: Namespace
/// \return Semantically equivalent expression such that the top-level
/// expression no longer is a \ref byte_extract_exprt or
/// \ref byte_update_exprt. Use \ref lower_byte_operators to also remove all
/// byte operators from any operands of \p src.
exprt lower_byte_update(const byte_update_exprt &src, const namespacet &ns);
/// Rewrite an expression possibly containing byte-extract or -update
/// expressions to more fundamental operations.
/// \param src: Input expression
/// \param ns: Namespace
/// \return Semantically equivalent expression that does not contain any \ref
/// byte_extract_exprt or \ref byte_update_exprt.
exprt lower_byte_operators(const exprt &src, const namespacet &ns);
#endif // CPROVER_UTIL_BYTE_OPERATORS_H