Skip to content

Commit 88e6eaf

Browse files
add support for enum, struct, tuple in llbc backend (#3721)
This pull request added some more features to Stable-mir to Ullbc translation: 1. Added support for translation of enum, struct, tuple and the projection associated with them. 2. Edited 3 Binops translation. 3. Added 4 simple tests for enum, struct, tuple and the projection . 4. If you had to perform any manual test, please describe them. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.
1 parent 3368a7f commit 88e6eaf

File tree

11 files changed

+1108
-200
lines changed

11 files changed

+1108
-200
lines changed

kani-compiler/src/codegen_aeneas_llbc/mir_to_ullbc/mod.rs

Lines changed: 766 additions & 200 deletions
Large diffs are not rendered by default.

tests/expected/llbc/enum/expected

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
enum test::MyEnum =
2+
| A(0: i32)
3+
| B()
4+
5+
6+
fn test::enum_match(@1: @Adt0) -> i32
7+
{
8+
let @0: i32; // return
9+
let e@1: @Adt0; // arg #1
10+
let i@2: i32; // local
11+
12+
match e@1 {
13+
0 => {
14+
i@2 := copy ((e@1 as variant @0).0)
15+
@0 := copy (i@2)
16+
drop i@2
17+
},
18+
1 => {
19+
@0 := const (0 : i32)
20+
},
21+
}
22+
return
23+
}
24+
25+
fn test::main()
26+
{
27+
let @0: (); // return
28+
let e@1: @Adt0; // local
29+
let i@2: i32; // local
30+
31+
e@1 := test::MyEnum::A { 0: const (1 : i32) }
32+
i@2 := @Fun0(move (e@1))
33+
drop i@2
34+
@0 := ()
35+
return
36+
}

tests/expected/llbc/enum/test.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
// kani-flags: -Zlean --print-llbc
4+
5+
//! This test checks that Kani's LLBC backend handles simple enum
6+
7+
enum MyEnum {
8+
A(i32),
9+
B,
10+
}
11+
12+
fn enum_match(e: MyEnum) -> i32 {
13+
match e {
14+
MyEnum::A(i) => i,
15+
MyEnum::B => 0,
16+
}
17+
}
18+
19+
#[kani::proof]
20+
fn main() {
21+
let e = MyEnum::A(1);
22+
let i = enum_match(e);
23+
}

tests/expected/llbc/generic/expected

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
enum core::option::Option<T> =
2+
| None()
3+
| Some(0: T)
4+
5+
6+
fn test::add_opt(@1: @Adt0<i32>, @2: @Adt0<i32>) -> @Adt0<i32>
7+
{
8+
let @0: @Adt0<i32>; // return
9+
let x@1: @Adt0<i32>; // arg #1
10+
let y@2: @Adt0<i32>; // arg #2
11+
let u@3: i32; // local
12+
let v@4: i32; // local
13+
let @5: i32; // anonymous local
14+
15+
match x@1 {
16+
1 => {
17+
u@3 := copy ((x@1 as variant @1).0)
18+
match y@2 {
19+
1 => {
20+
v@4 := copy ((y@2 as variant @1).0)
21+
@5 := copy (u@3) + copy (v@4)
22+
@0 := core::option::Option::Some { 0: move (@5) }
23+
drop @5
24+
},
25+
0 => {
26+
@0 := core::option::Option::None { }
27+
},
28+
}
29+
},
30+
0 => {
31+
@0 := core::option::Option::None { }
32+
},
33+
}
34+
return
35+
}
36+
37+
fn test::main()
38+
{
39+
let @0: (); // return
40+
let e@1: @Adt0<i32>; // local
41+
let @2: @Adt0<i32>; // anonymous local
42+
let @3: @Adt0<i32>; // anonymous local
43+
44+
@2 := core::option::Option::Some { 0: const (1 : i32) }
45+
@3 := core::option::Option::Some { 0: const (2 : i32) }
46+
e@1 := @Fun0(move (@2), move (@3))
47+
drop @3
48+
drop @2
49+
drop e@1
50+
@0 := ()
51+
return
52+
}

tests/expected/llbc/generic/test.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
// kani-flags: -Zlean --print-llbc
4+
5+
//! This test checks that Kani's LLBC backend handles simple generic args for option
6+
7+
fn add_opt(x: Option<i32>, y: Option<i32>) -> Option<i32> {
8+
match x {
9+
Some(u) => match y {
10+
Some(v) => Some(u + v),
11+
_ => None,
12+
},
13+
_ => None,
14+
}
15+
}
16+
17+
#[kani::proof]
18+
fn main() {
19+
let e = add_opt(Some(1), Some(2));
20+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
struct test::MyStruct =
2+
{
3+
a: i32,
4+
b: i32,
5+
}
6+
7+
enum test::MyEnum0 =
8+
| A(0: @Adt1, 1: i32)
9+
| B()
10+
11+
12+
enum test::MyEnum =
13+
| A(0: @Adt1, 1: @Adt2)
14+
| B(0: (i32, i32))
15+
16+
17+
fn test::enum_match(@1: @Adt0) -> i32
18+
{
19+
let @0: i32; // return
20+
let e@1: @Adt0; // arg #1
21+
let s@2: @Adt1; // local
22+
let e0@3: @Adt2; // local
23+
let s1@4: @Adt1; // local
24+
let b@5: i32; // local
25+
let @6: i32; // anonymous local
26+
let @7: i32; // anonymous local
27+
let @8: i32; // anonymous local
28+
let a@9: i32; // local
29+
let b@10: i32; // local
30+
31+
match e@1 {
32+
0 => {
33+
s@2 := move ((e@1 as variant @0).0)
34+
e0@3 := move ((e@1 as variant @0).1)
35+
match e0@3 {
36+
0 => {
37+
s1@4 := move ((e0@3 as variant @0).0)
38+
b@5 := copy ((e0@3 as variant @0).1)
39+
@6 := copy ((s1@4).a)
40+
@0 := copy (@6) + copy (b@5)
41+
drop @6
42+
drop s1@4
43+
drop e0@3
44+
drop s@2
45+
},
46+
1 => {
47+
@7 := copy ((s@2).a)
48+
@8 := copy ((s@2).b)
49+
@0 := copy (@7) + copy (@8)
50+
drop @8
51+
drop @7
52+
drop e0@3
53+
drop s@2
54+
},
55+
}
56+
},
57+
1 => {
58+
a@9 := copy (((e@1 as variant @1).0).0)
59+
b@10 := copy (((e@1 as variant @1).0).1)
60+
@0 := copy (a@9) + copy (b@10)
61+
},
62+
}
63+
return
64+
}
65+
66+
fn test::main()
67+
{
68+
let @0: (); // return
69+
let s@1: @Adt1; // local
70+
let s0@2: @Adt1; // local
71+
let e@3: @Adt0; // local
72+
let @4: @Adt2; // anonymous local
73+
let i@5: i32; // local
74+
75+
s@1 := @Adt1 { a: const (1 : i32), b: const (2 : i32) }
76+
s0@2 := @Adt1 { a: const (1 : i32), b: const (2 : i32) }
77+
@4 := test::MyEnum0::A { 0: move (s0@2), 1: const (1 : i32) }
78+
e@3 := test::MyEnum::A { 0: move (s@1), 1: move (@4) }
79+
drop @4
80+
i@5 := @Fun0(move (e@3))
81+
drop i@5
82+
@0 := ()
83+
return
84+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
// kani-flags: -Zlean --print-llbc
4+
5+
//! This test checks that Kani's LLBC backend handles simple projection
6+
7+
struct MyStruct {
8+
a: i32,
9+
b: i32,
10+
}
11+
12+
enum MyEnum0 {
13+
A(MyStruct, i32),
14+
B,
15+
}
16+
17+
enum MyEnum {
18+
A(MyStruct, MyEnum0),
19+
B((i32, i32)),
20+
}
21+
22+
fn enum_match(e: MyEnum) -> i32 {
23+
match e {
24+
MyEnum::A(s, e0) => match e0 {
25+
MyEnum0::A(s1, b) => s1.a + b,
26+
MyEnum0::B => s.a + s.b,
27+
},
28+
MyEnum::B((a, b)) => a + b,
29+
}
30+
}
31+
32+
#[kani::proof]
33+
fn main() {
34+
let s = MyStruct { a: 1, b: 2 };
35+
let s0 = MyStruct { a: 1, b: 2 };
36+
let e = MyEnum::A(s, MyEnum0::A(s0, 1));
37+
let i = enum_match(e);
38+
}

tests/expected/llbc/struct/expected

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
struct test::MyStruct =
2+
{
3+
a: i32,
4+
b: bool,
5+
}
6+
7+
fn test::struct_project(@1: @Adt0) -> i32
8+
{
9+
let @0: i32; // return
10+
let s@1: @Adt0; // arg #1
11+
12+
@0 := copy ((s@1).a)
13+
return
14+
}
15+
16+
fn test::main()
17+
{
18+
let @0: (); // return
19+
let s@1: @Adt0; // local
20+
let a@2: i32; // local
21+
22+
s@1 := @Adt0 { a: const (1 : i32), b: const (true) }
23+
a@2 := @Fun1(move (s@1))
24+
drop a@2
25+
@0 := ()
26+
return
27+
}

tests/expected/llbc/struct/test.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
// kani-flags: -Zlean --print-llbc
4+
5+
//! This test checks that Kani's LLBC backend handles simple struct
6+
7+
struct MyStruct {
8+
a: i32,
9+
b: bool,
10+
}
11+
12+
fn struct_project(s: MyStruct) -> i32 {
13+
s.a
14+
}
15+
16+
#[kani::proof]
17+
fn main() {
18+
let s = MyStruct { a: 1, b: true };
19+
let a = struct_project(s);
20+
}

tests/expected/llbc/tuple/expected

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
fn test::tuple_add(@1: (i32, i32)) -> i32
2+
{
3+
let @0: i32; // return
4+
let t@1: (i32, i32); // arg #1
5+
let @2: i32; // anonymous local
6+
let @3: i32; // anonymous local
7+
8+
@2 := copy ((t@1).0)
9+
@3 := copy ((t@1).1)
10+
@0 := copy (@2) + copy (@3)
11+
drop @3
12+
drop @2
13+
return
14+
}
15+
16+
fn test::main()
17+
{
18+
let @0: (); // return
19+
let s@1: i32; // local
20+
let @2: (i32, i32); // anonymous local
21+
22+
@2 := (const (1 : i32), const (2 : i32))
23+
s@1 := @Fun1(move (@2))
24+
drop @2
25+
drop s@1
26+
@0 := ()
27+
return
28+
}

0 commit comments

Comments
 (0)