|
|
@ -9,13 +9,21 @@ open! IStd
|
|
|
|
module L = Logging
|
|
|
|
module L = Logging
|
|
|
|
|
|
|
|
|
|
|
|
let sourcefile =
|
|
|
|
let sourcefile =
|
|
|
|
let pid = Pid.to_int (Unix.getpid ()) in
|
|
|
|
(* Avoid side-effect when [sourcefile ()] is never called. *)
|
|
|
|
SourceFile.create (Printf.sprintf "SynthesizedToplProperty%d.java" pid)
|
|
|
|
let x =
|
|
|
|
|
|
|
|
lazy
|
|
|
|
|
|
|
|
(let pid = Pid.to_int (Unix.getpid ()) in
|
|
|
|
|
|
|
|
SourceFile.create (Printf.sprintf "SynthesizedToplProperty%d.java" pid))
|
|
|
|
|
|
|
|
in
|
|
|
|
|
|
|
|
fun () -> Lazy.force x
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let cfg =
|
|
|
|
|
|
|
|
let x = lazy (Cfg.create ()) in
|
|
|
|
|
|
|
|
fun () -> Lazy.force x
|
|
|
|
|
|
|
|
|
|
|
|
let cfg = Cfg.create ()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let sourcefile_location = Location.none sourcefile
|
|
|
|
let sourcefile_location () = Location.none (sourcefile ())
|
|
|
|
|
|
|
|
|
|
|
|
let type_of_paramtyp (_t : Typ.Procname.Parameter.t) : Typ.t = ToplUtils.any_type
|
|
|
|
let type_of_paramtyp (_t : Typ.Procname.Parameter.t) : Typ.t = ToplUtils.any_type
|
|
|
|
|
|
|
|
|
|
|
@ -50,11 +58,13 @@ let procedure proc_name (make_body : node_generator) : Procdesc.t =
|
|
|
|
let attr =
|
|
|
|
let attr =
|
|
|
|
let formals = formals_of_procname proc_name in
|
|
|
|
let formals = formals_of_procname proc_name in
|
|
|
|
let is_defined = true in
|
|
|
|
let is_defined = true in
|
|
|
|
let loc = sourcefile_location in
|
|
|
|
let loc = sourcefile_location () in
|
|
|
|
{(ProcAttributes.default sourcefile proc_name) with formals; is_defined; loc}
|
|
|
|
{(ProcAttributes.default (sourcefile ()) proc_name) with formals; is_defined; loc}
|
|
|
|
|
|
|
|
in
|
|
|
|
|
|
|
|
let proc_desc = Cfg.create_proc_desc (cfg ()) attr in
|
|
|
|
|
|
|
|
let create_node kind instrs =
|
|
|
|
|
|
|
|
Procdesc.create_node proc_desc (sourcefile_location ()) kind instrs
|
|
|
|
in
|
|
|
|
in
|
|
|
|
let proc_desc = Cfg.create_proc_desc cfg attr in
|
|
|
|
|
|
|
|
let create_node kind instrs = Procdesc.create_node proc_desc sourcefile_location kind instrs in
|
|
|
|
|
|
|
|
let exit_node = create_node Procdesc.Node.Exit_node [] in
|
|
|
|
let exit_node = create_node Procdesc.Node.Exit_node [] in
|
|
|
|
let set_succs node succs = Procdesc.node_set_succs_exn proc_desc node succs [exit_node] in
|
|
|
|
let set_succs node succs = Procdesc.node_set_succs_exn proc_desc node succs [exit_node] in
|
|
|
|
let {start_node= body_start; exit_node= body_exit} = make_body create_node set_succs in
|
|
|
|
let {start_node= body_start; exit_node= body_exit} = make_body create_node set_succs in
|
|
|
@ -109,7 +119,7 @@ let pure_exp e : Exp.t * Sil.instr list =
|
|
|
|
let pairs = List.map ~f:(fun e -> (e, Ident.create_fresh Ident.knormal)) es in
|
|
|
|
let pairs = List.map ~f:(fun e -> (e, Ident.create_fresh Ident.knormal)) es in
|
|
|
|
let subst = List.map ~f:(function e, id -> (e, Exp.Var id)) pairs in
|
|
|
|
let subst = List.map ~f:(function e, id -> (e, Exp.Var id)) pairs in
|
|
|
|
let e' = Sil.exp_replace_exp subst e in
|
|
|
|
let e' = Sil.exp_replace_exp subst e in
|
|
|
|
let mk_load (e, id) = Sil.Load (id, e, ToplUtils.any_type, sourcefile_location) in
|
|
|
|
let mk_load (e, id) = Sil.Load (id, e, ToplUtils.any_type, sourcefile_location ()) in
|
|
|
|
let loads = List.map ~f:mk_load pairs in
|
|
|
|
let loads = List.map ~f:mk_load pairs in
|
|
|
|
(e', loads)
|
|
|
|
(e', loads)
|
|
|
|
|
|
|
|
|
|
|
@ -130,13 +140,13 @@ let gen_if (cond : Exp.t) (true_branch : node_generator) (false_branch : node_ge
|
|
|
|
let cond, preamble = pure_exp cond in
|
|
|
|
let cond, preamble = pure_exp cond in
|
|
|
|
let prune_true =
|
|
|
|
let prune_true =
|
|
|
|
let node_type = Procdesc.Node.Prune_node (true, Sil.Ik_if, PruneNodeKind_MethodBody) in
|
|
|
|
let node_type = Procdesc.Node.Prune_node (true, Sil.Ik_if, PruneNodeKind_MethodBody) in
|
|
|
|
let instr = Sil.Prune (cond, sourcefile_location, true, Sil.Ik_if) in
|
|
|
|
let instr = Sil.Prune (cond, sourcefile_location (), true, Sil.Ik_if) in
|
|
|
|
create_node node_type (preamble @ [instr])
|
|
|
|
create_node node_type (preamble @ [instr])
|
|
|
|
in
|
|
|
|
in
|
|
|
|
let prune_false =
|
|
|
|
let prune_false =
|
|
|
|
let node_type = Procdesc.Node.Prune_node (false, Sil.Ik_if, PruneNodeKind_MethodBody) in
|
|
|
|
let node_type = Procdesc.Node.Prune_node (false, Sil.Ik_if, PruneNodeKind_MethodBody) in
|
|
|
|
let instr =
|
|
|
|
let instr =
|
|
|
|
Sil.Prune (Exp.UnOp (Unop.LNot, cond, None), sourcefile_location, false, Sil.Ik_if)
|
|
|
|
Sil.Prune (Exp.UnOp (Unop.LNot, cond, None), sourcefile_location (), false, Sil.Ik_if)
|
|
|
|
in
|
|
|
|
in
|
|
|
|
create_node node_type (preamble @ [instr])
|
|
|
|
create_node node_type (preamble @ [instr])
|
|
|
|
in
|
|
|
|
in
|
|
|
@ -156,19 +166,19 @@ let stmt_node instrs : node_generator =
|
|
|
|
|
|
|
|
|
|
|
|
let sil_assign lhs rhs =
|
|
|
|
let sil_assign lhs rhs =
|
|
|
|
let tempvar = Ident.create_fresh Ident.knormal in
|
|
|
|
let tempvar = Ident.create_fresh Ident.knormal in
|
|
|
|
[ Sil.Load (tempvar, rhs, ToplUtils.any_type, sourcefile_location)
|
|
|
|
[ Sil.Load (tempvar, rhs, ToplUtils.any_type, sourcefile_location ())
|
|
|
|
; Sil.Store (lhs, ToplUtils.any_type, Exp.Var tempvar, sourcefile_location) ]
|
|
|
|
; Sil.Store (lhs, ToplUtils.any_type, Exp.Var tempvar, sourcefile_location ()) ]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let assign lhs rhs : node_generator = stmt_node (sil_assign lhs rhs)
|
|
|
|
let assign lhs rhs : node_generator = stmt_node (sil_assign lhs rhs)
|
|
|
|
|
|
|
|
|
|
|
|
let simple_call function_name : node_generator =
|
|
|
|
let simple_call function_name : node_generator =
|
|
|
|
let ret_id = Ident.create_fresh Ident.knormal in
|
|
|
|
let ret_id = Ident.create_fresh Ident.knormal in
|
|
|
|
stmt_node [ToplUtils.topl_call ret_id Tvoid sourcefile_location function_name []]
|
|
|
|
stmt_node [ToplUtils.topl_call ret_id Tvoid (sourcefile_location ()) function_name []]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let gen_maybe_call ret_id : node_generator =
|
|
|
|
let gen_maybe_call ret_id : node_generator =
|
|
|
|
stmt_node [ToplUtils.topl_call ret_id (Tint IBool) sourcefile_location ToplName.maybe []]
|
|
|
|
stmt_node [ToplUtils.topl_call ret_id (Tint IBool) (sourcefile_location ()) ToplName.maybe []]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let arguments_count proc_name = List.length (Typ.Procname.get_parameters proc_name)
|
|
|
|
let arguments_count proc_name = List.length (Typ.Procname.get_parameters proc_name)
|
|
|
@ -240,7 +250,7 @@ let generate_execute_state automaton proc_name =
|
|
|
|
( ToplUtils.static_var ToplName.state
|
|
|
|
( ToplUtils.static_var ToplName.state
|
|
|
|
, Typ.mk (Tint IInt)
|
|
|
|
, Typ.mk (Tint IInt)
|
|
|
|
, Exp.int (IntLit.of_int transition.target)
|
|
|
|
, Exp.int (IntLit.of_int transition.target)
|
|
|
|
, sourcefile_location ) ]
|
|
|
|
, sourcefile_location () ) ]
|
|
|
|
:: step (ToplUtils.static_var ToplName.retval) transition.label.ToplAst.return
|
|
|
|
:: step (ToplUtils.static_var ToplName.retval) transition.label.ToplAst.return
|
|
|
|
:: Option.value_map ~default:[] ~f:(List.mapi ~f:arg_action)
|
|
|
|
:: Option.value_map ~default:[] ~f:(List.mapi ~f:arg_action)
|
|
|
|
transition.label.ToplAst.arguments
|
|
|
|
transition.label.ToplAst.arguments
|
|
|
@ -297,5 +307,5 @@ let maybe_synthesize_it automaton proc_name =
|
|
|
|
|
|
|
|
|
|
|
|
let generate automaton proc_name =
|
|
|
|
let generate automaton proc_name =
|
|
|
|
IList.force_until_first_some
|
|
|
|
IList.force_until_first_some
|
|
|
|
[ lazy (Typ.Procname.Hash.find_opt cfg proc_name)
|
|
|
|
[ lazy (Typ.Procname.Hash.find_opt (cfg ()) proc_name)
|
|
|
|
; lazy (maybe_synthesize_it automaton proc_name) ]
|
|
|
|
; lazy (maybe_synthesize_it automaton proc_name) ]
|
|
|
|