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
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
|
import tritv::*;
type precond = t;
/* 2 means "this constraint may or may not be true after execution"
1 means "this constraint is definitely true after execution"
0 means "this constraint is definitely false after execution" */
type postcond = t;
/* 2 means "don't know about this constraint"
1 means "this constraint is definitely true before entry"
0 means "this constraint is definitely false on entry" */
type prestate = t;
/* similar to postcond */
type poststate = t;
/* 1 means "this variable is definitely initialized"
0 means "don't know whether this variable is
initialized" */
/*
This says: this expression requires the constraints whose value is 1 in
<pre> to be true, and given the precondition, it guarantees that the
constraints in <post> whose values are 1 are true, and that the constraints
in <post> whose values are 0 are false.
*/
/* named thus so as not to confuse with prestate and poststate */
type pre_and_post = {precondition: precond, postcondition: postcond};
/* FIXME: once it's implemented: (Issue #34) */
// : ((*.precondition).nbits == (*.postcondition).nbits);
type pre_and_post_state = {prestate: prestate, poststate: poststate};
type ts_ann = {conditions: pre_and_post, states: pre_and_post_state};
fn true_precond(num_vars: uint) -> precond { ret create_tritv(num_vars); }
fn true_postcond(num_vars: uint) -> postcond { ret true_precond(num_vars); }
fn empty_prestate(num_vars: uint) -> prestate { ret true_precond(num_vars); }
fn empty_poststate(num_vars: uint) -> poststate {
ret true_precond(num_vars);
}
fn false_postcond(num_vars: uint) -> postcond {
let rslt = create_tritv(num_vars);
tritv_set_all(rslt);
ret rslt;
}
fn empty_pre_post(num_vars: uint) -> pre_and_post {
ret {precondition: empty_prestate(num_vars),
postcondition: empty_poststate(num_vars)};
}
fn empty_states(num_vars: uint) -> pre_and_post_state {
ret {prestate: true_precond(num_vars),
poststate: true_postcond(num_vars)};
}
fn empty_ann(num_vars: uint) -> ts_ann {
ret {conditions: empty_pre_post(num_vars),
states: empty_states(num_vars)};
}
fn get_pre(&&p: pre_and_post) -> precond { ret p.precondition; }
fn get_post(&&p: pre_and_post) -> postcond { ret p.postcondition; }
fn difference(p1: precond, p2: precond) -> bool {
ret tritv_difference(p1, p2);
}
fn union(p1: precond, p2: precond) -> bool { ret tritv_union(p1, p2); }
fn intersect(p1: precond, p2: precond) -> bool {
ret tritv_intersect(p1, p2);
}
fn pps_len(p: pre_and_post) -> uint {
// gratuitous check
assert (p.precondition.nbits == p.postcondition.nbits);
ret p.precondition.nbits;
}
fn require(i: uint, p: pre_and_post) {
// sets the ith bit in p's pre
tritv_set(i, p.precondition, ttrue);
}
fn require_and_preserve(i: uint, p: pre_and_post) {
// sets the ith bit in p's pre and post
tritv_set(i, p.precondition, ttrue);
tritv_set(i, p.postcondition, ttrue);
}
fn set_in_postcond(i: uint, p: pre_and_post) -> bool {
// sets the ith bit in p's post
ret set_in_postcond_(i, p.postcondition);
}
fn set_in_postcond_(i: uint, p: postcond) -> bool {
let was_set = tritv_get(p, i);
tritv_set(i, p, ttrue);
ret was_set != ttrue;
}
fn set_in_poststate(i: uint, s: pre_and_post_state) -> bool {
// sets the ith bit in p's post
ret set_in_poststate_(i, s.poststate);
}
fn set_in_poststate_(i: uint, p: poststate) -> bool {
let was_set = tritv_get(p, i);
tritv_set(i, p, ttrue);
ret was_set != ttrue;
}
fn clear_in_poststate(i: uint, s: pre_and_post_state) -> bool {
// sets the ith bit in p's post
ret clear_in_poststate_(i, s.poststate);
}
fn clear_in_poststate_(i: uint, s: poststate) -> bool {
let was_set = tritv_get(s, i);
tritv_set(i, s, tfalse);
ret was_set != tfalse;
}
fn clear_in_prestate(i: uint, s: pre_and_post_state) -> bool {
// sets the ith bit in p's pre
ret clear_in_prestate_(i, s.prestate);
}
fn clear_in_prestate_(i: uint, s: prestate) -> bool {
let was_set = tritv_get(s, i);
tritv_set(i, s, tfalse);
ret was_set != tfalse;
}
fn clear_in_postcond(i: uint, s: pre_and_post) -> bool {
// sets the ith bit in p's post
let was_set = tritv_get(s.postcondition, i);
tritv_set(i, s.postcondition, tfalse);
ret was_set != tfalse;
}
// Sets all the bits in a's precondition to equal the
// corresponding bit in p's precondition.
fn set_precondition(a: ts_ann, p: precond) {
tritv_copy(a.conditions.precondition, p);
}
// Sets all the bits in a's postcondition to equal the
// corresponding bit in p's postcondition.
fn set_postcondition(a: ts_ann, p: postcond) {
tritv_copy(a.conditions.postcondition, p);
}
// Sets all the bits in a's prestate to equal the
// corresponding bit in p's prestate.
fn set_prestate(a: ts_ann, p: prestate) -> bool {
ret tritv_copy(a.states.prestate, p);
}
// Sets all the bits in a's postcondition to equal the
// corresponding bit in p's postcondition.
fn set_poststate(a: ts_ann, p: poststate) -> bool {
ret tritv_copy(a.states.poststate, p);
}
// Set all the bits in p that are set in new
fn extend_prestate(p: prestate, newv: poststate) -> bool {
ret tritv_union(p, newv);
}
// Set all the bits in p that are set in new
fn extend_poststate(p: poststate, newv: poststate) -> bool {
ret tritv_union(p, newv);
}
// Sets the given bit in p to "don't care"
fn relax_prestate(i: uint, p: prestate) -> bool {
let was_set = tritv_get(p, i);
tritv_set(i, p, dont_care);
ret was_set != dont_care;
}
// Clears the given bit in p
fn relax_poststate(i: uint, p: poststate) -> bool {
ret relax_prestate(i, p);
}
// Clears the given bit in p
fn relax_precond(i: uint, p: precond) { relax_prestate(i, p); }
// Sets all the bits in p to "don't care"
fn clear(p: precond) { tritv_clear(p); }
// Sets all the bits in p to true
fn set(p: precond) { tritv_set_all(p); }
fn ann_precond(a: ts_ann) -> precond { ret a.conditions.precondition; }
fn ann_prestate(a: ts_ann) -> prestate { ret a.states.prestate; }
fn ann_poststate(a: ts_ann) -> poststate { ret a.states.poststate; }
fn pp_clone(p: pre_and_post) -> pre_and_post {
ret {precondition: clone(p.precondition),
postcondition: clone(p.postcondition)};
}
fn clone(p: prestate) -> prestate { ret tritv_clone(p); }
// returns true if a implies b
// that is, returns true except if for some bits c and d,
// c = 1 and d = either 0 or "don't know"
fn implies(a: t, b: t) -> bool {
let tmp = tritv_clone(b);
tritv_difference(tmp, a);
ret tritv_doesntcare(tmp);
}
fn trit_str(t: trit) -> str {
alt t { dont_care { "?" } ttrue { "1" } tfalse { "0" } }
}
// FIXME (#2538): Would be nice to have unit tests for some of these
// operations, as a step towards formalizing them more rigorously.
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
|