|
| 1 | +/////////////////////////////////////////////////////////////////////////////// |
| 2 | +// Exercise: Point Functional Correctness |
| 3 | +/////////////////////////////////////////////////////////////////////////////// |
| 4 | + |
| 5 | + |
| 6 | +include "../../common/helpers.saw"; |
| 7 | +import "Point.cry"; |
| 8 | + |
| 9 | +m <- llvm_load_module "point.bc"; |
| 10 | + |
| 11 | +/////////////////////////////////////////////////////////////////////////////// |
| 12 | +// Part 1: Simple Point Equality |
| 13 | +/////////////////////////////////////////////////////////////////////////////// |
| 14 | + |
| 15 | +// Convert the memory safety spec below into a functional correctness |
| 16 | +// specification. |
| 17 | + |
| 18 | +// You can specify the values in a struct by using llvm_struct_value: |
| 19 | +// llvm_struct_value [ <field_0>, <field_1>, ... <field_n> ]; |
| 20 | + |
| 21 | +let point_eq_spec = do { |
| 22 | + (p1, p1_ptr) <- ptr_to_fresh_readonly "p1" (llvm_struct "struct.point"); |
| 23 | + (p2, p2_ptr) <- ptr_to_fresh_readonly "p2" (llvm_struct "struct.point"); |
| 24 | + |
| 25 | + llvm_execute_func [p1_ptr, p2_ptr]; |
| 26 | + |
| 27 | + ret <- llvm_fresh_var "ret" (llvm_int 1); |
| 28 | + llvm_return (llvm_term ret); |
| 29 | +}; |
| 30 | + |
| 31 | +point_eq_ov <- llvm_verify m "point_eq" [] true point_eq_spec z3; |
| 32 | + |
| 33 | +/////////////////////////////////////////////////////////////////////////////// |
| 34 | +// Part 2: Point Allocation |
| 35 | +/////////////////////////////////////////////////////////////////////////////// |
| 36 | + |
| 37 | +// Convert the memory safety proofs below into functional correctness proofs. |
| 38 | + |
| 39 | +let point_new_spec = do { |
| 40 | + p_x <- llvm_fresh_var "p_x" (llvm_int 32); |
| 41 | + p_y <- llvm_fresh_var "p_y" (llvm_int 32); |
| 42 | + |
| 43 | + llvm_execute_func [ llvm_term p_x, llvm_term p_y ]; |
| 44 | + |
| 45 | + (ret, ret_ptr) <- ptr_to_fresh "ret" (llvm_struct "struct.point"); |
| 46 | + llvm_return ret_ptr; |
| 47 | +}; |
| 48 | + |
| 49 | +point_new_ov <- llvm_verify m "point_new" [] true point_new_spec z3; |
| 50 | + |
| 51 | +let point_copy_spec = do { |
| 52 | + (p, p_ptr) <- ptr_to_fresh_readonly "p" (llvm_struct "struct.point"); |
| 53 | + |
| 54 | + llvm_execute_func [p_ptr]; |
| 55 | + |
| 56 | + (ret, ret_ptr) <- ptr_to_fresh "ret" (llvm_struct "struct.point"); |
| 57 | + llvm_return ret_ptr; |
| 58 | +}; |
| 59 | + |
| 60 | +point_copy_ov <- llvm_verify m "point_copy" [point_new_ov] true point_copy_spec z3; |
| 61 | + |
| 62 | +/////////////////////////////////////////////////////////////////////////////// |
| 63 | +// Part 3: Point Addition |
| 64 | +/////////////////////////////////////////////////////////////////////////////// |
| 65 | + |
| 66 | +// Convert the memory safety proof below into a proof that the C `point_add` |
| 67 | +// function is equivalent to the Cryptol `point_add` function in Point.cry. |
| 68 | + |
| 69 | +let point_add_spec = do { |
| 70 | + llvm_alloc_global "ZERO"; |
| 71 | + zero_global <- llvm_fresh_var "zero_global" (llvm_struct "struct.point"); |
| 72 | + llvm_points_to (llvm_global "ZERO") (llvm_term zero_global); |
| 73 | + |
| 74 | + (p1, p1_ptr) <- ptr_to_fresh_readonly "p1" (llvm_struct "struct.point"); |
| 75 | + (p2, p2_ptr) <- ptr_to_fresh_readonly "p2" (llvm_struct "struct.point"); |
| 76 | + |
| 77 | + llvm_execute_func [p1_ptr, p2_ptr]; |
| 78 | + |
| 79 | + (ret, ret_ptr) <- ptr_to_fresh "ret" (llvm_struct "struct.point"); |
| 80 | + llvm_return ret_ptr; |
| 81 | +}; |
| 82 | + |
| 83 | +llvm_verify m "point_add" |
| 84 | + [point_new_ov, point_copy_ov, point_eq_ov] |
| 85 | + true |
| 86 | + point_add_spec |
| 87 | + z3; |
0 commit comments