Skip to content
This repository was archived by the owner on May 4, 2024. It is now read-only.

Commit 9ebe397

Browse files
rahxephon89meng-xu-cs
authored andcommitted
revise spec (#908)
1 parent ccdeb69 commit 9ebe397

File tree

2 files changed

+98
-27
lines changed

2 files changed

+98
-27
lines changed

language/move-prover/boogie-backend/src/bytecode_translator.rs

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,7 @@ impl<'env> FunctionTranslator<'env> {
810810
mem_inst_seen.insert(memory);
811811
}
812812
}
813-
813+
let mut dup: Vec<String> = vec![];
814814
// Declare temporaries for debug tracing and other purposes.
815815
for (_, (ty, ref bv_flag, cnt)) in self.compute_needed_temps() {
816816
for i in 0..cnt {
@@ -819,12 +819,12 @@ impl<'env> FunctionTranslator<'env> {
819819
} else {
820820
boogie_type
821821
};
822-
emitln!(
823-
writer,
824-
"var {}: {};",
825-
boogie_temp_from_suffix(env, &boogie_type_suffix_bv(env, &ty, *bv_flag), i),
826-
bv_type(env, &ty)
827-
);
822+
let temp_name =
823+
boogie_temp_from_suffix(env, &boogie_type_suffix_bv(env, &ty, *bv_flag), i);
824+
if !dup.contains(&temp_name) {
825+
emitln!(writer, "var {}: {};", temp_name.clone(), bv_type(env, &ty));
826+
dup.push(temp_name);
827+
}
828828
}
829829
}
830830

@@ -2181,7 +2181,13 @@ impl<'env> FunctionTranslator<'env> {
21812181
self.track_return(*i, srcs[0], bv_flag);
21822182
}
21832183
TraceAbort => self.track_abort(&str_local(srcs[0])),
2184-
TraceExp(kind, node_id) => self.track_exp(*kind, *node_id, srcs[0]),
2184+
TraceExp(kind, node_id) => {
2185+
let bv_flag = *global_state
2186+
.get_temp_index_oper(mid, fid, srcs[0], baseline_flag)
2187+
.unwrap()
2188+
== Bitwise;
2189+
self.track_exp(*kind, *node_id, srcs[0], bv_flag)
2190+
}
21852191
EmitEvent => {
21862192
let msg = srcs[0];
21872193
let handle = srcs[1];
@@ -2484,22 +2490,12 @@ impl<'env> FunctionTranslator<'env> {
24842490
);
24852491
}
24862492

2487-
fn track_exp(&self, kind: TraceKind, node_id: NodeId, temp: TempIndex) {
2493+
fn track_exp(&self, kind: TraceKind, node_id: NodeId, temp: TempIndex, bv_flag: bool) {
24882494
let env = self.parent.env;
24892495
let writer = self.parent.writer;
24902496
let ty = self.get_local_type(temp);
2491-
let global_state = &self
2492-
.fun_target
2493-
.global_env()
2494-
.get_extension::<GlobalNumberOperationState>()
2495-
.expect("global number operation state");
24962497
let temp_str = if ty.is_reference() {
2497-
let new_temp = boogie_temp(
2498-
env,
2499-
ty.skip_reference(),
2500-
0,
2501-
global_state.get_node_num_oper(node_id) == Bitwise,
2502-
);
2498+
let new_temp = boogie_temp(env, ty.skip_reference(), 0, bv_flag);
25032499
emitln!(writer, "{} := $Dereference($t{});", new_temp, temp);
25042500
new_temp
25052501
} else {

language/move-prover/tests/sources/functional/bitwise_features.move

Lines changed: 82 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,46 @@ module TestFeatures {
2424

2525
spec contains {
2626
pragma bv=b"0";
27+
pragma opaque;
2728
aborts_if false;
2829
ensures result == ((feature / 8) < len(features) && spec_contains(features, feature));
2930
}
3031

32+
fun is_enabled(feature: u64): bool acquires Features {
33+
exists<Features>(@std) &&
34+
contains(&borrow_global<Features>(@std).features, feature)
35+
}
36+
37+
spec is_enabled {
38+
aborts_if false;
39+
pragma timeout = 120;
40+
ensures result == (
41+
exists<Features>(@std) // this one does not verify
42+
&& (((feature / 8) < len(global<Features>(@std).features)
43+
&& spec_contains(global<Features>(@std).features, feature)))
44+
);
45+
}
46+
3147
fun set(features: &mut vector<u8>, feature: u64, include: bool) {
48+
let old_n = vector::length(features); // ghost var
49+
let old_features = *features; // ghost var
50+
let n = old_n; // ghost var
51+
3252
let byte_index = feature / 8;
3353
let bit_mask = 1 << ((feature % 8) as u8);
34-
while (vector::length(features) <= byte_index) {
35-
let len = vector::length(features);
36-
vector::insert(features, 0, len)
54+
while({
55+
spec {
56+
invariant n == len(features);
57+
invariant n >= old_n;
58+
invariant byte_index < old_n ==> len(features) == old_n;
59+
invariant byte_index >= old_n ==> len(features) <= byte_index + 1;
60+
invariant forall i in 0..old_n: features[i] == old_features[i];
61+
invariant forall i in old_n..n: (features[i] as u8) == (0 as u8);
62+
};
63+
vector::length(features) <= byte_index
64+
}) {
65+
vector::push_back(features, 0);
66+
n = n + 1;
3767
};
3868
let entry = vector::borrow_mut(features, byte_index);
3969
if (include)
@@ -44,6 +74,7 @@ module TestFeatures {
4474

4575
spec set {
4676
pragma bv=b"0";
77+
pragma timeout = 120;
4778
aborts_if false;
4879
ensures feature / 8 < len(features);
4980
ensures include == spec_contains(features, feature);
@@ -92,14 +123,58 @@ module TestFeatures {
92123
aborts_if signer::address_of(framework) != @std;
93124
}
94125

95-
fun enable_feature_flags(feature: u64) acquires Features {
126+
public fun disable_feature_flags(disable: vector<u64>) acquires Features {
96127
let features = &mut borrow_global_mut<Features>(@std).features;
97-
set(features, feature, true);
128+
let i = 0;
129+
let n = vector::length(&disable);
130+
while ({
131+
spec {
132+
invariant i <= n;
133+
invariant forall j in 0..i: disable[j] / 8 < len(features) && !spec_contains(features, disable[j]);
134+
};
135+
i < n
136+
}) {
137+
set(features, *vector::borrow(&disable, i), false);
138+
spec {
139+
assert (disable[i] / 8 < len(features) && !spec_contains(features, disable[i]));
140+
};
141+
i = i + 1;
142+
};
143+
}
144+
145+
spec disable_feature_flags {
146+
pragma opaque;
147+
pragma timeout = 120;
148+
modifies global<Features>(@std);
149+
let post features = global<Features>(@std).features;
150+
ensures forall i in 0..len(disable): (disable[i] / 8 < len(features) && !spec_contains(features, disable[i]));
151+
}
152+
153+
public fun enable_feature_flags(enable: vector<u64>) acquires Features {
154+
let features = &mut borrow_global_mut<Features>(@std).features;
155+
let i = 0;
156+
let n = vector::length(&enable);
157+
while ({
158+
spec {
159+
invariant i <= n;
160+
invariant forall j in 0..i: enable[j] / 8 < len(features) && spec_contains(features, enable[j]);
161+
};
162+
i < n
163+
}) {
164+
set(features, *vector::borrow(&enable, i), true);
165+
spec {
166+
assert (enable[i] / 8 < len(features) && spec_contains(features, enable[i]));
167+
};
168+
i = i + 1;
169+
};
98170
}
99171

100172
spec enable_feature_flags {
101-
let post features = borrow_global<Features>(@std).features;
102-
ensures spec_contains(features, feature);
173+
pragma opaque;
174+
pragma timeout = 120;
175+
modifies global<Features>(@std);
176+
let post features = global<Features>(@std).features;
177+
ensures forall i in 0..len(enable): (enable[i] / 8 < len(features) && spec_contains(features, enable[i]));
103178
}
104179

105180
}

0 commit comments

Comments
 (0)