Skip to content

Commit d9cd6c6

Browse files
committed
Implement '--timeout' and '--timeout-instr' options, only in 'owi run' for now
See #155
1 parent 2eccec1 commit d9cd6c6

File tree

17 files changed

+164
-39
lines changed

17 files changed

+164
-39
lines changed

src/ast/compile.ml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ module Text = struct
3838
let* m = until_optimize ~unsafe ~rac ~srac ~optimize m in
3939
Link.modul link_state ~name m
4040

41-
let until_interpret ~unsafe ~rac ~srac ~optimize ~name link_state m =
41+
let until_interpret ~unsafe ~timeout ~timeout_instr ~rac ~srac ~optimize ~name link_state m =
4242
let* m, link_state =
4343
until_link ~unsafe ~rac ~srac ~optimize ~name link_state m
4444
in
45-
let+ () = Interpret.Concrete.modul link_state.envs m in
45+
let+ () = Interpret.Concrete.modul ~timeout ~timeout_instr link_state.envs m in
4646
link_state
4747
end
4848

@@ -61,9 +61,9 @@ module Binary = struct
6161
let* m = until_optimize ~unsafe ~optimize m in
6262
Link.modul link_state ~name m
6363

64-
let until_interpret ~unsafe ~optimize ~name link_state m =
64+
let until_interpret ~unsafe ~timeout ~timeout_instr ~optimize ~name link_state m =
6565
let* m, link_state = until_link ~unsafe ~optimize ~name link_state m in
66-
let+ () = Interpret.Concrete.modul link_state.envs m in
66+
let+ () = Interpret.Concrete.modul ~timeout ~timeout_instr link_state.envs m in
6767
link_state
6868
end
6969

@@ -84,10 +84,10 @@ module Any = struct
8484
| Wasm m -> Binary.until_link ~unsafe ~optimize ~name link_state m
8585
| Wast _ | Ocaml _ -> assert false
8686

87-
let until_interpret ~unsafe ~rac ~srac ~optimize ~name link_state = function
87+
let until_interpret ~unsafe ~timeout ~timeout_instr ~rac ~srac ~optimize ~name link_state = function
8888
| Kind.Wat m ->
89-
Text.until_interpret ~unsafe ~rac ~srac ~optimize ~name link_state m
90-
| Wasm m -> Binary.until_interpret ~unsafe ~optimize ~name link_state m
89+
Text.until_interpret ~unsafe ~timeout ~timeout_instr ~rac ~srac ~optimize ~name link_state m
90+
| Wasm m -> Binary.until_interpret ~unsafe ~timeout ~timeout_instr ~optimize ~name link_state m
9191
| Wast _ | Ocaml _ -> assert false
9292
end
9393

@@ -114,11 +114,11 @@ module File = struct
114114
| Wasm m -> Binary.until_link ~unsafe ~optimize ~name link_state m
115115
| Wast _ | Ocaml _ -> assert false
116116

117-
let until_interpret ~unsafe ~rac ~srac ~optimize ~name link_state filename =
117+
let until_interpret ~unsafe ~timeout ~timeout_instr ~rac ~srac ~optimize ~name link_state filename =
118118
let* m = Parse.guess_from_file filename in
119119
match m with
120120
| Kind.Wat m ->
121-
Text.until_interpret ~unsafe ~rac ~srac ~optimize ~name link_state m
122-
| Wasm m -> Binary.until_interpret ~unsafe ~optimize ~name link_state m
121+
Text.until_interpret ~unsafe ~timeout ~timeout_instr ~rac ~srac ~optimize ~name link_state m
122+
| Wasm m -> Binary.until_interpret ~unsafe ~timeout ~timeout_instr ~optimize ~name link_state m
123123
| Wast _ | Ocaml _ -> assert false
124124
end

src/ast/compile.mli

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ module Any : sig
3636
link state *)
3737
val until_interpret :
3838
unsafe:bool
39+
-> timeout:float option
40+
-> timeout_instr:int option
3941
-> rac:bool
4042
-> srac:bool
4143
-> optimize:bool
@@ -73,6 +75,8 @@ module File : sig
7375
link state *)
7476
val until_interpret :
7577
unsafe:bool
78+
-> timeout:float option
79+
-> timeout_instr:int option
7680
-> rac:bool
7781
-> srac:bool
7882
-> optimize:bool
@@ -123,6 +127,8 @@ module Text : sig
123127
link state *)
124128
val until_interpret :
125129
unsafe:bool
130+
-> timeout:float option
131+
-> timeout_instr:int option
126132
-> rac:bool
127133
-> srac:bool
128134
-> optimize:bool
@@ -153,6 +159,8 @@ module Binary : sig
153159
link state *)
154160
val until_interpret :
155161
unsafe:bool
162+
-> timeout:float option
163+
-> timeout_instr:int option
156164
-> optimize:bool
157165
-> name:string option
158166
-> Concrete_extern_func.extern_func Link.state

src/bin/owi.ml

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,24 @@ let srac =
180180
let doc = "symbolic runtime assertion checking mode" in
181181
Arg.(value & flag & info [ "srac" ] ~doc)
182182

183+
let timeout =
184+
let doc =
185+
"Stop execution after S seconds."
186+
in
187+
Arg.(
188+
value
189+
& opt (some float) None
190+
& info [ "timeout" ] ~doc ~docv:"S" )
191+
192+
let timeout_instr =
193+
let doc =
194+
"Stop execution after running I instructions."
195+
in
196+
Arg.(
197+
value
198+
& opt (some int) None
199+
& info [ "timeout-instr" ] ~doc ~docv:"I" )
200+
183201
let unsafe =
184202
let doc = "skip typechecking pass" in
185203
Arg.(value & flag & info [ "unsafe"; "u" ] ~doc)
@@ -249,8 +267,8 @@ let c_cmd =
249267
and+ with_breadcrumbs
250268
and+ entry_point in
251269
Cmd_c.cmd ~arch ~property ~testcomp ~workspace ~workers ~opt_lvl ~includes
252-
~files ~unsafe ~optimize ~no_stop_at_failure ~no_value
253-
~no_assert_failure_expression_printing ~deterministic_result_order
270+
~files ~unsafe ~optimize ~no_stop_at_failure
271+
~no_value ~no_assert_failure_expression_printing ~deterministic_result_order
254272
~fail_mode ~concolic ~eacsl ~solver ~model_format ~entry_point
255273
~invoke_with_symbols ~out_file ~model_out_file ~with_breadcrumbs
256274
(* owi cpp *)
@@ -438,11 +456,13 @@ let run_info =
438456

439457
let run_cmd =
440458
let+ unsafe
459+
and+ timeout
460+
and+ timeout_instr
441461
and+ rac
442462
and+ optimize
443463
and+ () = setup_log
444464
and+ files in
445-
Cmd_run.cmd ~unsafe ~rac ~optimize ~files
465+
Cmd_run.cmd ~unsafe ~timeout ~timeout_instr ~rac ~optimize ~files
446466

447467
(* owi rust *)
448468

src/cmd/cmd_conc.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ let run_modules_to_run (link_state : _ Link.state) modules_to_run =
5757
List.fold_left
5858
(fun (acc : unit Choice.t) to_run ->
5959
Choice.bind acc (fun () ->
60-
(Interpret.Concolic.modul link_state.envs) to_run ) )
60+
(Interpret.Concolic.modul ~timeout:None ~timeout_instr:None link_state.envs) to_run ) )
6161
(Choice.return ()) modules_to_run
6262

6363
type end_of_trace =

src/cmd/cmd_iso.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ let check_iso ~unsafe export_name export_type module1 module2 =
329329
in
330330
let m = Symbolic.convert_module_to_run m in
331331

332-
Interpret.Symbolic.modul link_state.envs m
332+
Interpret.Symbolic.modul ~timeout:None ~timeout_instr:None link_state.envs m
333333

334334
module String_set = Set.Make (String)
335335

src/cmd/cmd_replay.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ let run_file ~unsafe ~optimize ~entry_point ~invoke_with_symbols filename model
212212
let* m, link_state =
213213
Compile.Binary.until_link ~unsafe link_state ~optimize ~name:None m
214214
in
215-
let* () = Interpret.Concrete.modul link_state.envs m in
215+
let* () = Interpret.Concrete.modul ~timeout:None ~timeout_instr:None link_state.envs m in
216216
Ok ()
217217

218218
let cmd ~unsafe ~optimize ~replay_file ~source_file ~entry_point

src/cmd/cmd_run.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ let extern_module : Concrete_extern_func.extern_func Link.extern_module =
2222
let link_state =
2323
Link.extern_module Link.empty_state ~name:"symbolic" extern_module
2424

25-
let run_file ~unsafe ~rac ~optimize filename =
25+
let run_file ~unsafe ~timeout ~timeout_instr ~rac ~optimize filename =
2626
let name = None in
2727
let link_state = if rac then link_state else Link.empty_state in
2828
let+ (_ : _ Link.state) =
29-
Compile.File.until_interpret ~unsafe ~rac ~srac:false ~optimize ~name
29+
Compile.File.until_interpret ~unsafe ~timeout ~timeout_instr ~rac ~srac:false ~optimize ~name
3030
link_state filename
3131
in
3232
()
3333

34-
let cmd ~unsafe ~rac ~optimize ~files =
35-
list_iter (run_file ~unsafe ~rac ~optimize) files
34+
let cmd ~unsafe ~timeout ~timeout_instr ~rac ~optimize ~files =
35+
list_iter (run_file ~unsafe ~timeout ~timeout_instr ~rac ~optimize) files

src/cmd/cmd_run.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
val cmd :
66
unsafe:bool
7+
-> timeout:float option
8+
-> timeout_instr:int option
79
-> rac:bool
810
-> optimize:bool
911
-> files:Fpath.t list

src/cmd/cmd_sym.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ let run_file ~entry_point ~unsafe ~rac ~srac ~optimize ~invoke_with_symbols _pc
3131
Compile.Binary.until_link ~unsafe ~optimize ~name:None link_state m
3232
in
3333
let m = Symbolic.convert_module_to_run m in
34-
Interpret.Symbolic.modul link_state.envs m
34+
Interpret.Symbolic.modul ~timeout:None ~timeout_instr:None link_state.envs m
3535

3636
let print_bug ~model_format ~labels ~model_out_file ~id ~no_value
3737
~no_stop_at_failure ~no_assert_failure_expression_printing ~breadcrumbs

src/interpret/interpret.ml

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,21 +1433,25 @@ module Make (P : Interpret_intf.P) :
14331433
m "unimplemented instruction: %a" (Types.pp_instr ~short:false) i );
14341434
assert false
14351435

1436-
let rec loop (state : State.exec_state) =
1436+
let rec loop ~heartbeat (state : State.exec_state) =
1437+
let* () =
1438+
match heartbeat with
1439+
| None -> Choice.return ()
1440+
| Some f -> f () in
14371441
match state.pc with
14381442
| instr :: pc -> begin
14391443
let* state = exec_instr instr { state with pc } in
14401444
match state with
1441-
| State.Continue state -> loop state
1445+
| State.Continue state -> loop ~heartbeat state
14421446
| State.Return res -> Choice.return res
14431447
end
14441448
| [] -> (
14451449
let* next_state = State.end_block state in
14461450
match next_state with
1447-
| State.Continue state -> loop state
1451+
| State.Continue state -> loop ~heartbeat state
14481452
| State.Return res -> Choice.return res )
14491453

1450-
let exec_expr envs env locals stack expr bt =
1454+
let exec_expr ~heartbeat envs env locals stack expr bt =
14511455
let state : State.exec_state =
14521456
let func_rt = match bt with None -> [] | Some rt -> rt in
14531457
{ stack
@@ -1461,12 +1465,40 @@ module Make (P : Interpret_intf.P) :
14611465
}
14621466
in
14631467

1464-
let+ state = loop state in
1468+
let+ state = loop ~heartbeat state in
14651469
state
14661470

1467-
let modul envs (modul : Module_to_run.t) : unit P.Choice.t =
1471+
let make_heartbeat ~timeout ~timeout_instr () =
1472+
match timeout, timeout_instr with
1473+
| None, None -> None
1474+
| Some _, _ | _, Some _ ->
1475+
Some (
1476+
let fuel = Atomic.make (
1477+
match timeout_instr with
1478+
| Some i -> i
1479+
| None -> max_int
1480+
) in
1481+
let start_time = Unix.gettimeofday () in
1482+
fun () ->
1483+
let fuel_left = Atomic.fetch_and_add fuel (-1) in
1484+
if fuel_left mod 1024 = 0 then begin
1485+
let at_timeout = match timeout with
1486+
| None -> false
1487+
| Some s -> Float.compare (Unix.gettimeofday () -. start_time) s > 0
1488+
in
1489+
let at_timeout_instr = match timeout_instr with
1490+
| None -> false
1491+
| Some _ -> fuel_left <= 0
1492+
in
1493+
if at_timeout || at_timeout_instr
1494+
then Choice.trap (`Msg "timeout")
1495+
else Choice.return ()
1496+
end else Choice.return ()
1497+
)
1498+
1499+
let modul ~timeout ~timeout_instr envs (modul : Module_to_run.t) : unit P.Choice.t =
1500+
let heartbeat = make_heartbeat ~timeout ~timeout_instr () in
14681501
Logs.info (fun m -> m "interpreting ...");
1469-
14701502
try
14711503
begin
14721504
let* () =
@@ -1475,7 +1507,7 @@ module Make (P : Interpret_intf.P) :
14751507
let* () = u in
14761508
let+ _end_stack =
14771509
let env = Module_to_run.env modul in
1478-
exec_expr envs env (State.Locals.of_list []) Stack.empty to_run
1510+
exec_expr ~heartbeat envs env (State.Locals.of_list []) Stack.empty to_run
14791511
None
14801512
in
14811513
() )
@@ -1508,7 +1540,7 @@ module Make (P : Interpret_intf.P) :
15081540
match state with
15091541
| State.Return res -> Choice.return res
15101542
| State.Continue state ->
1511-
let+ res = loop state in
1543+
let+ res = loop ~heartbeat:None state in
15121544
res
15131545
end
15141546
with Stack_overflow -> Choice.trap `Call_stack_exhausted

src/interpret/interpret.mli

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
module Concrete : sig
66
val modul :
7-
Concrete.Env.t Env_id.collection
7+
timeout:float option
8+
-> timeout_instr:int option
9+
-> Concrete.Env.t Env_id.collection
810
-> Concrete.Module_to_run.t
911
-> unit Concrete_choice.t
1012

@@ -44,21 +46,27 @@ end
4446

4547
module Symbolic : sig
4648
val modul :
47-
Symbolic.Env.t Env_id.collection
49+
timeout:float option
50+
-> timeout_instr:int option
51+
-> Symbolic.Env.t Env_id.collection
4852
-> Symbolic.Module_to_run.t
4953
-> unit Symbolic.Choice.t
5054
end
5155

5256
module Minimalist_symbolic : sig
5357
val modul :
54-
Minimalist_symbolic.Env.t Env_id.collection
58+
timeout:float option
59+
-> timeout_instr:int option
60+
-> Minimalist_symbolic.Env.t Env_id.collection
5561
-> Minimalist_symbolic.Module_to_run.t
5662
-> unit Minimalist_symbolic.Choice.t
5763
end
5864

5965
module Concolic : sig
6066
val modul :
61-
Concolic.Env.t Env_id.collection
67+
timeout:float option
68+
-> timeout_instr:int option
69+
-> Concolic.Env.t Env_id.collection
6270
-> Concolic.Module_to_run.t
6371
-> unit Concolic.Choice.t
6472
end

src/intf/interpret_intf.ml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,10 @@ module type S = sig
159159
type module_to_run
160160

161161
(** interpret a module *)
162-
val modul : env Env_id.collection -> module_to_run -> unit choice
162+
val modul :
163+
timeout:float option ->
164+
timeout_instr:int option ->
165+
env Env_id.collection -> module_to_run -> unit choice
163166

164167
type value
165168

src/script/script.ml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ let run ~no_exhaustion ~optimize script =
160160
Logs.info (fun m -> m "*** module");
161161
incr curr_module;
162162
let+ link_state =
163-
Compile.Text.until_interpret link_state ~unsafe ~rac:false ~srac:false
163+
Compile.Text.until_interpret ~timeout:None ~timeout_instr:None link_state ~unsafe ~rac:false ~srac:false
164164
~optimize ~name:None m
165165
in
166166
(* TODO: enable printing again! *)
@@ -170,7 +170,9 @@ let run ~no_exhaustion ~optimize script =
170170
incr curr_module;
171171
let* m = Parse.Text.Inline_module.from_string m in
172172
let+ link_state =
173-
Compile.Text.until_interpret link_state ~unsafe ~rac:false ~srac:false
173+
Compile.Text.until_interpret link_state
174+
~unsafe ~rac:false ~srac:false
175+
~timeout:None ~timeout_instr:None
174176
~optimize ~name:None m
175177
in
176178
link_state
@@ -180,7 +182,7 @@ let run ~no_exhaustion ~optimize script =
180182
let* m = Parse.Binary.Module.from_string m in
181183
let m = { m with id } in
182184
let+ link_state =
183-
Compile.Binary.until_interpret link_state ~unsafe ~optimize ~name:None
185+
Compile.Binary.until_interpret link_state ~timeout:None ~timeout_instr:None ~unsafe ~optimize ~name:None
184186
m
185187
in
186188
link_state
@@ -191,7 +193,7 @@ let run ~no_exhaustion ~optimize script =
191193
Compile.Text.until_link link_state ~unsafe ~rac:false ~srac:false
192194
~optimize ~name:None m
193195
in
194-
let got = Interpret.Concrete.modul link_state.envs m in
196+
let got = Interpret.Concrete.modul ~timeout:None ~timeout_instr:None link_state.envs m in
195197
let+ () = check_error_result expected got in
196198
link_state
197199
| Assert (Assert_malformed_binary (m, expected)) ->

test/run/dune

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
(cram
22
(deps
33
%{bin:owi}
4+
(file ./loop.wat)
5+
(file ./fibo.wat)
46
(file ./binary_loop.wasm)
57
(file ./overflow.wat)))

0 commit comments

Comments
 (0)