Skip to content

Commit 9a48bd2

Browse files
committed
Compute typestate properly for move
typestate now drops constraints correctly in the post-state of a move expression or a declaration whose op is a move. It doesn't yet drop constraints mentioning variables that get updated. To do this, I had to change typestate to use trit-vectors instead of bit-vectors, because for every constraint, there are three possible values: known-to-be-false (e.g. after x <- y, init(y) is known-to-be-false), known-to-be-true, and unknown. Before, we conflated known-to-be-false with unknown. But move requires them to be treated differently. Consider: (program a) (a1) x = 1; (a2) y <- x; (a3) log x; (program b) (b1) x = 1; (b2) y <- z; (b3) log x; With only two values, the postcondition of statement a2 for constraint init(x) is the same as that of b2: 0. But in (a2)'s postcondition, init(x) *must* be false, but in (b2)'s condition, it's just whatever it was in the postcondition of the preceding statement.
1 parent 7105cd1 commit 9a48bd2

File tree

10 files changed

+625
-219
lines changed

10 files changed

+625
-219
lines changed

src/comp/middle/tstate/ann.rs

Lines changed: 69 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,36 @@
11

22
import front::ast::ident;
33
import std::vec;
4-
import std::bitv;
4+
import tritv::*;
55

6+
type precond = t;
67

7-
/*
8-
This says: this expression requires the idents in <pre> to be initialized,
9-
and given the precondition, it guarantees that the idents in <post> are
10-
initialized.
11-
*/
12-
type precond = bitv::t;
8+
/* 2 means "this constraint may or may not be true after execution"
9+
1 means "this constraint is definitely true after execution"
10+
0 means "this constraint is definitely false after execution" */
11+
type postcond = t;
1312

1413

15-
/* 1 means "this variable must be initialized"
16-
0 means "don't care about this variable" */
17-
type postcond = bitv::t;
14+
/* 2 means "don't know about this constraint"
15+
1 means "this constraint is definitely true before entry"
16+
0 means "this constraint is definitely false on entry" */
17+
type prestate = t;
1818

1919

20-
/* 1 means "this variable is initialized"
21-
0 means "don't know about this variable */
22-
type prestate = bitv::t;
20+
/* similar to postcond */
21+
type poststate = t;
2322

2423

2524
/* 1 means "this variable is definitely initialized"
2625
0 means "don't know whether this variable is
2726
initialized" */
28-
type poststate = bitv::t;
29-
3027

31-
/* 1 means "this variable is definitely initialized"
32-
0 means "don't know whether this variable is
33-
initialized" */
28+
/*
29+
This says: this expression requires the constraints whose value is 1 in
30+
<pre> to be true, and given the precondition, it guarantees that the
31+
constraints in <post> whose values are 1 are true, and that the constraints
32+
in <post> whose values are 0 are false.
33+
*/
3434

3535
/* named thus so as not to confuse with prestate and poststate */
3636
type pre_and_post = @rec(precond precondition, postcond postcondition);
@@ -44,7 +44,7 @@ type pre_and_post_state = rec(prestate prestate, poststate poststate);
4444
type ts_ann = @rec(pre_and_post conditions, pre_and_post_state states);
4545

4646
fn true_precond(uint num_vars) -> precond {
47-
be bitv::create(num_vars, false);
47+
be create_tritv(num_vars);
4848
}
4949

5050
fn true_postcond(uint num_vars) -> postcond { be true_precond(num_vars); }
@@ -54,7 +54,9 @@ fn empty_prestate(uint num_vars) -> prestate { be true_precond(num_vars); }
5454
fn empty_poststate(uint num_vars) -> poststate { be true_precond(num_vars); }
5555

5656
fn false_postcond(uint num_vars) -> postcond {
57-
be bitv::create(num_vars, true);
57+
auto res = create_tritv(num_vars);
58+
tritv_set_all(res);
59+
ret res;
5860
}
5961

6062
fn empty_pre_post(uint num_vars) -> pre_and_post {
@@ -77,12 +79,16 @@ fn get_pre(&pre_and_post p) -> precond { ret p.precondition; }
7779
fn get_post(&pre_and_post p) -> postcond { ret p.postcondition; }
7880

7981
fn difference(&precond p1, &precond p2) -> bool {
80-
be bitv::difference(p1, p2);
82+
ret tritv_difference(p1, p2);
8183
}
8284

83-
fn union(&precond p1, &precond p2) -> bool { be bitv::union(p1, p2); }
85+
fn union(&precond p1, &precond p2) -> bool {
86+
ret tritv_union(p1, p2);
87+
}
8488

85-
fn intersect(&precond p1, &precond p2) -> bool { be bitv::intersect(p1, p2); }
89+
fn intersect(&precond p1, &precond p2) -> bool {
90+
ret tritv_intersect(p1, p2);
91+
}
8692

8793
fn pps_len(&pre_and_post p) -> uint {
8894
// gratuitous check
@@ -93,86 +99,88 @@ fn pps_len(&pre_and_post p) -> uint {
9399

94100
fn require(uint i, &pre_and_post p) {
95101
// sets the ith bit in p's pre
96-
97-
bitv::set(p.precondition, i, true);
102+
tritv_set(i, p.precondition, ttrue);
98103
}
99104

100105
fn require_and_preserve(uint i, &pre_and_post p) {
101106
// sets the ith bit in p's pre and post
102-
103-
bitv::set(p.precondition, i, true);
104-
bitv::set(p.postcondition, i, true);
107+
tritv_set(i, p.precondition, ttrue);
108+
tritv_set(i, p.postcondition, ttrue);
105109
}
106110

107111
fn set_in_postcond(uint i, &pre_and_post p) -> bool {
108112
// sets the ith bit in p's post
109-
110-
auto was_set = bitv::get(p.postcondition, i);
111-
bitv::set(p.postcondition, i, true);
112-
ret !was_set;
113+
auto was_set = tritv_get(p.postcondition, i);
114+
tritv_set(i, p.postcondition, ttrue);
115+
ret was_set != ttrue;
113116
}
114117

115118
fn set_in_poststate(uint i, &pre_and_post_state s) -> bool {
116119
// sets the ith bit in p's post
117-
118-
auto was_set = bitv::get(s.poststate, i);
119-
bitv::set(s.poststate, i, true);
120-
ret !was_set;
120+
auto was_set = tritv_get(s.poststate, i);
121+
tritv_set(i, s.poststate, ttrue);
122+
ret was_set != ttrue;
121123
}
122124

123125
fn clear_in_poststate(uint i, &pre_and_post_state s) -> bool {
124126
// sets the ith bit in p's post
125-
126-
auto was_set = bitv::get(s.poststate, i);
127-
bitv::set(s.poststate, i, false);
128-
ret was_set;
127+
auto was_set = tritv_get(s.poststate, i);
128+
tritv_set(i, s.poststate, tfalse);
129+
ret was_set != tfalse;
129130
}
130131

132+
fn clear_in_postcond(uint i, &pre_and_post s) -> bool {
133+
// sets the ith bit in p's post
134+
auto was_set = tritv_get(s.postcondition, i);
135+
tritv_set(i, s.postcondition, tfalse);
136+
ret was_set != tfalse;
137+
}
131138

132139
// Sets all the bits in a's precondition to equal the
133140
// corresponding bit in p's precondition.
134141
fn set_precondition(ts_ann a, &precond p) {
135-
bitv::copy(a.conditions.precondition, p);
142+
tritv_copy(a.conditions.precondition, p);
136143
}
137144

138145

139146
// Sets all the bits in a's postcondition to equal the
140147
// corresponding bit in p's postcondition.
141148
fn set_postcondition(ts_ann a, &postcond p) {
142-
bitv::copy(a.conditions.postcondition, p);
149+
tritv_copy(a.conditions.postcondition, p);
143150
}
144151

145152

146153
// Sets all the bits in a's prestate to equal the
147154
// corresponding bit in p's prestate.
148155
fn set_prestate(ts_ann a, &prestate p) -> bool {
149-
ret bitv::copy(a.states.prestate, p);
156+
ret tritv_copy(a.states.prestate, p);
150157
}
151158

152159

153160
// Sets all the bits in a's postcondition to equal the
154161
// corresponding bit in p's postcondition.
155162
fn set_poststate(ts_ann a, &poststate p) -> bool {
156-
ret bitv::copy(a.states.poststate, p);
163+
ret tritv_copy(a.states.poststate, p);
157164
}
158165

159166

160167
// Set all the bits in p that are set in new
161168
fn extend_prestate(&prestate p, &poststate new) -> bool {
162-
ret bitv::union(p, new);
169+
ret tritv_union(p, new);
163170
}
164171

165172

166173
// Set all the bits in p that are set in new
167174
fn extend_poststate(&poststate p, &poststate new) -> bool {
168-
ret bitv::union(p, new);
175+
ret tritv_union(p, new);
169176
}
170177

171-
// Clears the given bit in p
178+
// Sets the given bit in p to "don't care"
179+
// FIXME: is this correct?
172180
fn relax_prestate(uint i, &prestate p) -> bool {
173-
auto was_set = bitv::get(p, i);
174-
bitv::set(p, i, false);
175-
ret was_set;
181+
auto was_set = tritv_get(p, i);
182+
tritv_set(i, p, dont_care);
183+
ret was_set != dont_care;
176184
}
177185

178186
// Clears the given bit in p
@@ -185,12 +193,11 @@ fn relax_precond(uint i, &precond p) {
185193
relax_prestate(i, p);
186194
}
187195

188-
// Clears all the bits in p
189-
fn clear(&precond p) { bitv::clear(p); }
190-
196+
// Sets all the bits in p to "don't care"
197+
fn clear(&precond p) { tritv_clear(p); }
191198

192-
// Sets all the bits in p
193-
fn set(&precond p) { bitv::set_all(p); }
199+
// Sets all the bits in p to true
200+
fn set(&precond p) { tritv_set_all(p); }
194201

195202
fn ann_precond(&ts_ann a) -> precond { ret a.conditions.precondition; }
196203

@@ -203,16 +210,17 @@ fn pp_clone(&pre_and_post p) -> pre_and_post {
203210
postcondition=clone(p.postcondition));
204211
}
205212

206-
fn clone(prestate p) -> prestate { ret bitv::clone(p); }
213+
fn clone(prestate p) -> prestate { ret tritv_clone(p); }
207214

208215

209216
// returns true if a implies b
210217
// that is, returns true except if for some bits c and d,
211-
// c = 1 and d = 0
212-
fn implies(bitv::t a, bitv::t b) -> bool {
213-
auto tmp = bitv::clone(b);
214-
bitv::difference(tmp, a);
215-
ret bitv::is_false(tmp);
218+
// c = 1 and d = either 0 or "don't know"
219+
// FIXME: is this correct?
220+
fn implies(t a, t b) -> bool {
221+
auto tmp = tritv_clone(b);
222+
tritv_difference(tmp, a);
223+
ret tritv_doesntcare(tmp);
216224
}
217225
//
218226
// Local Variables:

0 commit comments

Comments
 (0)