Skip to content

Commit a07c01c

Browse files
authored
Merge pull request #1538 from GaloisInc/T1493
saw-remote-api: Reach parity with SAWScript for global option settings
2 parents 7a5c82e + e8b082d commit a07c01c

File tree

12 files changed

+154
-6
lines changed

12 files changed

+154
-6
lines changed

saw-remote-api/CHANGELOG.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33

44
## 0.9.1 -- YYYY-MM-DD
55

6-
* NEW CHANGELOG ENTRIES SINCE 0.9.0 GO HERE
6+
* `SAW/set option`'s `"option"` parameter is now allowed to be `"What4 eval"`,
7+
which controls whether to enable or disable What4 translation for SAWCore
8+
expressions during Crucible symbolic execution.
79

810

911
## 0.9.0 -- 2021-11-19

saw-remote-api/docs/SAW.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ Parameter fields
515515

516516

517517
``option``
518-
The option to set and its accompanying value (i.e., true or false); one of the following:``lax arithmetic``, ``lax pointer ordering``, ``debug intrinsics``, ``SMT array memory model``, or ``What4 hash consing``
518+
The option to set and its accompanying value (i.e., true or false); one of the following:``lax arithmetic``, ``lax pointer ordering``, ``debug intrinsics``, ``SMT array memory model``, ``What4 hash consing``, or ``What4 eval``
519519

520520

521521

saw-remote-api/python/CHANGELOG.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22

33
## 0.9.1 -- YYYY-MM-DD
44

5-
* NEW CHANGELOG ENTRIES SINCE 0.9.0 GO HERE
5+
* Add a `set_option` command to `saw_client` that allows enabling and disabling
6+
global SAW options. For example, SAWScript's `enable_lax_pointer_ordering` is
7+
equivalent to `set_option(LaxPointerOrdering(), True)` in `saw-client.
8+
`LaxPointerOrdering`, as well as all other possible options, can be imported
9+
from the `saw_client.option` module.
610

711

812
## 0.9.0 -- 2021-11-19

saw-remote-api/python/saw_client/__init__.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from argo_client.connection import ServerConnection
1515
from . import llvm
1616
from . import exceptions
17+
from . import option
1718
from . import proofscript
1819

1920
__designated_connection = None # type: Optional[connection.SAWConnection]
@@ -357,7 +358,7 @@ def on_finish(self) -> None:
357358
def on_abort(self) -> None:
358359
print("🛑 Aborting proof script.", file=self.file)
359360

360-
361+
361362
def view(v: View) -> None:
362363
"""Add a view to the global list of views. Future verification results will
363364
be handed to this view, and its on_finish() handler will be called at
@@ -648,6 +649,12 @@ def prove(goal: cryptoltypes.CryptolJSON,
648649
pr.counterexample = None
649650
return pr
650651

652+
def set_option(option : option.SAWOption, value : bool) -> None:
653+
"""Set a boolean-valued SAW option."""
654+
global __designated_connection
655+
if __designated_connection is not None:
656+
__designated_connection.set_option(option=option,value=value)
657+
651658
@atexit.register
652659
def script_exit() -> None:
653660
global __designated_views

saw-remote-api/python/saw_client/commands.py

+13
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from cryptol import cryptoltypes
55
from . import exceptions
66
from .proofscript import *
7+
from .option import *
78

89
from typing import Any, List
910

@@ -199,3 +200,15 @@ def __init__(self, connection : argo.HasProtocolState) -> None:
199200
{},
200201
connection
201202
)
203+
204+
205+
class SAWSetOption(SAWCommand):
206+
def __init__(self, connection : argo.HasProtocolState,
207+
option : SAWOption, value : bool,
208+
timeout : Optional[float]) -> None:
209+
params = {'option': str(option),
210+
'value': value}
211+
super(SAWSetOption, self).__init__('SAW/set option', params, connection, timeout=timeout)
212+
213+
def process_result(self, _res : Any) -> Any:
214+
return None

saw-remote-api/python/saw_client/connection.py

+9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from argo_client.connection import ServerConnection, DynamicSocketProcess, HttpProcess, ManagedProcess
77
from argo_client.interaction import Interaction, Command
88
from .commands import *
9+
from .option import *
910
from typing import Optional, Union, Any, List, TextIO
1011

1112
# FIXME cryptol_path isn't always used...?
@@ -237,3 +238,11 @@ def prove(self,
237238
"""
238239
self.most_recent_result = Prove(self, goal, proof_script, timeout)
239240
return self.most_recent_result
241+
242+
def set_option(self,
243+
option : SAWOption,
244+
value : bool,
245+
timeout : Optional[float] = None) -> Command:
246+
"""Set a boolean-valued SAW option."""
247+
self.most_recent_result = SAWSetOption(self, option, value, timeout)
248+
return self.most_recent_result
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from abc import ABCMeta, abstractmethod
2+
from dataclasses import dataclass
3+
from typing import Any
4+
5+
class SAWOption(metaclass=ABCMeta):
6+
@abstractmethod
7+
def __str__(self) -> str: pass
8+
9+
10+
@dataclass
11+
class LaxArithmetic(SAWOption):
12+
def __str__(self) -> str:
13+
return "lax arithmetic"
14+
15+
16+
@dataclass
17+
class LaxPointerOrdering(SAWOption):
18+
def __str__(self) -> str:
19+
return "lax pointer ordering"
20+
21+
22+
@dataclass
23+
class DebugIntrinsics(SAWOption):
24+
def __str__(self) -> str:
25+
return "debug intrinsics"
26+
27+
28+
@dataclass
29+
class SMTArrayMemoryModel(SAWOption):
30+
def __str__(self) -> str:
31+
return "SMT array memory model"
32+
33+
34+
@dataclass
35+
class What4HashConsing(SAWOption):
36+
def __str__(self) -> str:
37+
return "What4 hash consing"
38+
39+
40+
@dataclass
41+
class What4Eval(SAWOption):
42+
def __str__(self) -> str:
43+
return "What4 eval"

saw-remote-api/python/tests/saw/test-files/Makefile

+4
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ all: $(BC_FILES)
55

66
%.bc: %.c
77
clang -g -c -emit-llvm -o $@ $<
8+
9+
# This test case crucially relies on the use of -O2.
10+
llvm_lax_pointer_ordering.bc: llvm_lax_pointer_ordering.c
11+
clang -O2 -g -c -emit-llvm -o $@ $<
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include <stdint.h>
2+
#include <stdlib.h>
3+
4+
const size_t LEN = 42;
5+
6+
void zip_with_add(uint64_t c[LEN], const uint64_t a[LEN], const uint64_t b[LEN]) {
7+
for (size_t i = 0; i < LEN; i++) {
8+
c[i] = a[i] + b[i];
9+
}
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from pathlib import Path
2+
import unittest
3+
from saw_client import *
4+
from saw_client.llvm import Contract, FreshVar, LLVMType, SetupVal, array_ty, cryptol, i64, void
5+
from saw_client.option import LaxPointerOrdering
6+
7+
8+
LEN = 42
9+
10+
11+
def ptr_to_fresh(c : Contract, ty : LLVMType, name : Optional[str] = None,
12+
read_only : bool = False) -> Tuple[FreshVar, SetupVal]:
13+
"""Add to ``Contract`` ``c`` an allocation of a pointer of type ``ty`` initialized to an unknown fresh value.
14+
If ``read_only == True`` then the allocated memory is immutable.
15+
16+
:returns A fresh variable bound to the pointers initial value and the newly allocated pointer. (The fresh
17+
variable will be assigned ``name`` if provided/available.)"""
18+
var = c.fresh_var(ty, name)
19+
ptr = c.alloc(ty, points_to = var, read_only = read_only)
20+
return (var, ptr)
21+
22+
23+
class ZipWithAddContract(Contract):
24+
def specification(self):
25+
array_t = array_ty(LEN, i64)
26+
c_ptr = self.alloc(array_t)
27+
(a, a_ptr) = ptr_to_fresh(self, name='a', ty=array_t, read_only=True)
28+
(b, b_ptr) = ptr_to_fresh(self, name='b', ty=array_t, read_only=True)
29+
30+
self.execute_func(c_ptr, a_ptr, b_ptr)
31+
32+
self.points_to(c_ptr, cryptol(f'zipWith`{{ {LEN} }} (+) {a.name()} {b.name()}'))
33+
self.returns(void)
34+
35+
36+
class LLVMPointerTest(unittest.TestCase):
37+
38+
def test_llvm_pointer(self):
39+
connect(reset_server=True)
40+
if __name__ == "__main__": view(LogResults())
41+
bcname = str(Path('tests','saw','test-files', 'llvm_lax_pointer_ordering.bc'))
42+
mod = llvm_load_module(bcname)
43+
44+
set_option(LaxPointerOrdering(), True)
45+
46+
result = llvm_verify(mod, 'zip_with_add', ZipWithAddContract())
47+
self.assertIs(result.is_success(), True)
48+
49+
50+
if __name__ == "__main__":
51+
unittest.main()

saw-remote-api/src/SAWServer/SetOption.hs

+7-2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ setOption opt =
3939
updateRW rw { rwSMTArrayMemoryModel = enabled }
4040
EnableWhat4HashConsing enabled ->
4141
updateRW rw { rwWhat4HashConsing = enabled }
42+
EnableWhat4Eval enabled ->
43+
updateRW rw { rwWhat4Eval = enabled }
4244
ok
4345

4446
data SetOptionParams
@@ -47,6 +49,7 @@ data SetOptionParams
4749
| EnableDebugIntrinsics Bool
4850
| EnableSMTArrayMemoryModel Bool
4951
| EnableWhat4HashConsing Bool
52+
| EnableWhat4Eval Bool
5053

5154
parseOption :: Object -> String -> Parser SetOptionParams
5255
parseOption o name =
@@ -56,6 +59,7 @@ parseOption o name =
5659
"debug intrinsics" -> EnableDebugIntrinsics <$> o .: "value"
5760
"SMT array memory model" -> EnableSMTArrayMemoryModel <$> o .: "value"
5861
"What4 hash consing" -> EnableWhat4HashConsing <$> o .: "value"
62+
"What4 eval" -> EnableWhat4Eval <$> o .: "value"
5963
_ -> empty
6064

6165
instance FromJSON SetOptionParams where
@@ -70,8 +74,9 @@ instance Doc.DescribedMethod SetOptionParams OK where
7074
, Doc.Literal "lax arithmetic", Doc.Text ", "
7175
, Doc.Literal "lax pointer ordering", Doc.Text ", "
7276
, Doc.Literal "debug intrinsics", Doc.Text ", "
73-
, Doc.Literal "SMT array memory model", Doc.Text ", or "
74-
, Doc.Literal "What4 hash consing"
77+
, Doc.Literal "SMT array memory model", Doc.Text ", "
78+
, Doc.Literal "What4 hash consing", Doc.Text ", or "
79+
, Doc.Literal "What4 eval"
7580
])
7681
]
7782
resultFieldDescription = []

0 commit comments

Comments
 (0)