You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

299 lines
11 KiB

(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
(** Interval abstract domain *)
open Apron
let equal_apron_typ =
(* Apron.Texpr1.typ is a sum of nullary constructors *)
Poly.equal
(** Apron-managed map from variables to intervals *)
type t = Box.t Abstract1.t
let equal : t -> t -> bool = Poly.equal
let compare : t -> t -> int = Poly.compare
let man = lazy (Box.manager_alloc ())
let join l r = Abstract1.join (Lazy.force man) l r
let joinN = function
| [] -> Abstract1.bottom (Lazy.force man) (Environment.make [||] [||])
| x :: xs -> List.fold ~f:join xs x
let is_false x = Abstract1.is_bottom (Lazy.force man) x
let bindings (itv : t) =
let itv = Abstract1.minimize_environment (Lazy.force man) itv in
let box = Abstract1.to_box (Lazy.force man) itv in
let vars =
Environment.vars box.box1_env |> fun (i, r) -> Array.append i r
in
Array.combine_exn vars box.interval_array
let sexp_of_t (itv : t) =
let sexps =
Array.fold_right (bindings itv) [] ~f:(fun (v, i) acc ->
Sexp.List
[ Sexp.Atom (Var.to_string v)
; Sexp.Atom (Scalar.to_string i.inf)
; Sexp.Atom (Scalar.to_string i.sup) ]
:: acc )
in
Sexp.List sexps
let pp fs =
let pp_pair a_pp b_pp fs (a, b) =
Format.fprintf fs "@[(%a@,%a)@]" a_pp a b_pp b
in
bindings >> Array.pp "@," (pp_pair Var.print Interval.print) fs
let init _gs = Abstract1.top (Lazy.force man) (Environment.make [||] [||])
let apron_var_of_name = (fun nm -> "%" ^ nm) >> Apron.Var.of_string
let apron_var_of_reg = Llair.Reg.name >> apron_var_of_name
let rec apron_typ_of_llair_typ : Llair.Typ.t -> Texpr1.typ option = function
| Pointer {elt= _} -> apron_typ_of_llair_typ Llair.Typ.siz
| Integer {bits= _} -> Some Texpr1.Int
| Float {bits= 32; enc= `IEEE} -> Some Texpr1.Single
| Float {bits= 64; enc= `IEEE} -> Some Texpr1.Double
| Float {bits= 80; enc= `Extended} -> Some Texpr1.Extended
| Float {bits= 128; enc= `IEEE} -> Some Texpr1.Quad
| t ->
warn "No corresponding apron type for llair type %a " Llair.Typ.pp t
() ;
None
let rec apron_texpr_of_llair_exp exp q =
match (exp : Llair.Exp.t) with
| Reg {name} | Global {name} | Function {name} ->
Some (Texpr1.Var (apron_var_of_name name))
| Integer {data} -> Some (Texpr1.Cst (Coeff.s_of_int (Z.to_int data)))
| Float {data} -> (
match Float.of_string_exn data with
| f -> Some (Texpr1.Cst (Coeff.s_of_float f))
| exception Invalid_argument _ -> None )
| Ap1 (Signed {bits}, _, _) ->
let n = Int.shift_left 1 (bits - 1) in
Some (Texpr1.Cst (Coeff.i_of_int (-n) (n - 1)))
| Ap1 (Unsigned {bits}, _, _) ->
let n = Int.shift_left 1 (bits - 1) in
Some (Texpr1.Cst (Coeff.i_of_int 0 n))
| Ap1 (Convert {src}, dst, x) ->
let* src' = apron_typ_of_llair_typ src in
let* dst' = apron_typ_of_llair_typ dst in
let subtm = apron_texpr_of_llair_exp x q in
if equal_apron_typ src' dst' then subtm
else
let+ t = subtm in
Texpr1.Unop (Texpr1.Cast, t, dst', Texpr0.Rnd)
| Ap2 (op, typ, x, y) -> (
let* typ' = apron_typ_of_llair_typ typ in
let* x' = apron_texpr_of_llair_exp x q in
let* y' = apron_texpr_of_llair_exp y q in
(* abstract evaluation of boolean binary operation [te1 op te2] at [q]
by translation to [te1 - te2 op 0] and intersection with [q] *)
let bool_binop q op x' y' =
let env = Abstract1.env q in
let lhs = Texpr1.Binop (Texpr1.Sub, x', y', typ', Texpr0.Rnd) in
let tcons = Tcons1.make (Texpr1.of_expr env lhs) op in
let ea =
Tcons1.array_make env 1 $> fun ea -> Tcons1.array_set ea 0 tcons
in
(* if meet of q with tree constraint encoding of binop is: (bottom
-> binop definitely false); (unchanged from q -> binop definitely
true); (else -> binop may be true or false) *)
let meet = Abstract1.meet_tcons_array (Lazy.force man) q ea in
if is_false meet then Some (Texpr1.Cst (Coeff.s_of_int 0))
else if equal meet q then Some (Texpr1.Cst (Coeff.s_of_int (-1)))
else Some (Texpr1.Cst (Coeff.i_of_int (-1) 0))
in
let arith_bop op x' y' =
Some (Texpr1.Binop (op, x', y', typ', Texpr0.Rnd))
in
match op with
| Eq -> bool_binop q Tcons0.EQ x' y'
| Dq -> bool_binop q Tcons0.DISEQ x' y'
| Gt -> bool_binop q Tcons0.SUP x' y'
| Ge -> bool_binop q Tcons0.SUPEQ x' y'
| Lt -> bool_binop q Tcons0.SUP y' x'
| Le -> bool_binop q Tcons0.SUPEQ y' x'
| Ugt | Uge | Ult | Ule | Ord | Uno -> None
| Add -> arith_bop Texpr1.Add x' y'
| Sub -> arith_bop Texpr1.Sub x' y'
| Mul -> arith_bop Texpr1.Mul x' y'
| Div -> arith_bop Texpr1.Div x' y'
| Rem -> arith_bop Texpr1.Mod x' y'
| Udiv | Urem -> None
| And | Or | Xor | Shl | Lshr | Ashr | Update _ -> None )
| Label _
|Ap1 ((Splat | Select _), _, _)
|Ap3 (Conditional, _, _, _, _)
|ApN (Record, _, _) ->
None
let assign reg exp q =
[%Trace.call fun {pf} ->
pf "@ {%a}@\n%a := %a" pp q Llair.Reg.pp reg Llair.Exp.pp exp]
;
let lval = apron_var_of_reg reg in
( match apron_texpr_of_llair_exp exp q with
| Some e ->
let env = Abstract1.env q in
let new_env =
match
( Environment.mem_var env lval
, apron_typ_of_llair_typ (Llair.Reg.typ reg) )
with
| true, _ -> env
| false, Some Texpr1.Int -> Environment.add env [|lval|] [||]
| false, _ -> Environment.add env [||] [|lval|]
in
let man = Lazy.force man in
let q = Abstract1.change_environment man q new_env true in
Abstract1.assign_texpr man q lval (Texpr1.of_expr new_env e) None
| _ -> q )
|>
[%Trace.retn fun {pf} r -> pf "{%a}" pp r]
[sledge] Add concurrency analysis Summary: This diff changes the analysis exploration algorithm from considering only sequential executions to considering executions of the interleaving semantics. As part of this, symbolic states are changed so that each thread has its own registers, while all memory is shared between them. Currently only a simple threads interface is supported: they can be created with `thread_create(&thread_routine)`, they can exit by returning from `thread_routine`, and they can be joined with `thread_join`. Current simplifications include that newly created threads are already runnable, thread routines accept no arguments and return no result, and no failures are possible. The concurrent exploration algorithm gives preference to executions which have fewer context switches, thereby performing an incremental form of context-bounded analysis. A form of partial-order reduction is performed, where the symbolic states are joined across (prefixes of) executions with the same number of context switches which reach a point where the instruction pointers and call stacks of all threads are the same. This has the effect of "dagifying" the concurrent execution tree by merging points after e.g. threads perform actions that commute with each other. This is unlike traditional partial-order reduction in that it relies on the symbolic join to combine the results of commuting operations in a way that the following symbolic execution can take advantage of, rather than performing some up-front analysis to identify commuting operations and quotienting the space of executions. The current state of the symbolic join and execution is significantly suboptimal in this regard. Differential Revision: D29441149 fbshipit-source-id: cf801a6b1
3 years ago
let resolve_int _ _ _ = []
(** block if [e] is known to be false; skip otherwise *)
[sledge] Add concurrency analysis Summary: This diff changes the analysis exploration algorithm from considering only sequential executions to considering executions of the interleaving semantics. As part of this, symbolic states are changed so that each thread has its own registers, while all memory is shared between them. Currently only a simple threads interface is supported: they can be created with `thread_create(&thread_routine)`, they can exit by returning from `thread_routine`, and they can be joined with `thread_join`. Current simplifications include that newly created threads are already runnable, thread routines accept no arguments and return no result, and no failures are possible. The concurrent exploration algorithm gives preference to executions which have fewer context switches, thereby performing an incremental form of context-bounded analysis. A form of partial-order reduction is performed, where the symbolic states are joined across (prefixes of) executions with the same number of context switches which reach a point where the instruction pointers and call stacks of all threads are the same. This has the effect of "dagifying" the concurrent execution tree by merging points after e.g. threads perform actions that commute with each other. This is unlike traditional partial-order reduction in that it relies on the symbolic join to combine the results of commuting operations in a way that the following symbolic execution can take advantage of, rather than performing some up-front analysis to identify commuting operations and quotienting the space of executions. The current state of the symbolic join and execution is significantly suboptimal in this regard. Differential Revision: D29441149 fbshipit-source-id: cf801a6b1
3 years ago
let exec_assume _ q e =
match apron_texpr_of_llair_exp e q with
| Some e ->
let cond =
Abstract1.bound_texpr (Lazy.force man) q (Texpr1.of_expr q.env e)
in
if Interval.is_zero cond then None else Some q
| _ -> Some q
(** existentially quantify killed register [r] out of state [q] *)
[sledge] Add concurrency analysis Summary: This diff changes the analysis exploration algorithm from considering only sequential executions to considering executions of the interleaving semantics. As part of this, symbolic states are changed so that each thread has its own registers, while all memory is shared between them. Currently only a simple threads interface is supported: they can be created with `thread_create(&thread_routine)`, they can exit by returning from `thread_routine`, and they can be joined with `thread_join`. Current simplifications include that newly created threads are already runnable, thread routines accept no arguments and return no result, and no failures are possible. The concurrent exploration algorithm gives preference to executions which have fewer context switches, thereby performing an incremental form of context-bounded analysis. A form of partial-order reduction is performed, where the symbolic states are joined across (prefixes of) executions with the same number of context switches which reach a point where the instruction pointers and call stacks of all threads are the same. This has the effect of "dagifying" the concurrent execution tree by merging points after e.g. threads perform actions that commute with each other. This is unlike traditional partial-order reduction in that it relies on the symbolic join to combine the results of commuting operations in a way that the following symbolic execution can take advantage of, rather than performing some up-front analysis to identify commuting operations and quotienting the space of executions. The current state of the symbolic join and execution is significantly suboptimal in this regard. Differential Revision: D29441149 fbshipit-source-id: cf801a6b1
3 years ago
let exec_kill _ r q =
let apron_v = apron_var_of_reg r in
if Environment.mem_var (Abstract1.env q) apron_v then
Abstract1.forget_array (Lazy.force man) q [|apron_v|] false
else q
(** perform a series [move_vec] of reg:=exp moves at state [q] *)
[sledge] Add concurrency analysis Summary: This diff changes the analysis exploration algorithm from considering only sequential executions to considering executions of the interleaving semantics. As part of this, symbolic states are changed so that each thread has its own registers, while all memory is shared between them. Currently only a simple threads interface is supported: they can be created with `thread_create(&thread_routine)`, they can exit by returning from `thread_routine`, and they can be joined with `thread_join`. Current simplifications include that newly created threads are already runnable, thread routines accept no arguments and return no result, and no failures are possible. The concurrent exploration algorithm gives preference to executions which have fewer context switches, thereby performing an incremental form of context-bounded analysis. A form of partial-order reduction is performed, where the symbolic states are joined across (prefixes of) executions with the same number of context switches which reach a point where the instruction pointers and call stacks of all threads are the same. This has the effect of "dagifying" the concurrent execution tree by merging points after e.g. threads perform actions that commute with each other. This is unlike traditional partial-order reduction in that it relies on the symbolic join to combine the results of commuting operations in a way that the following symbolic execution can take advantage of, rather than performing some up-front analysis to identify commuting operations and quotienting the space of executions. The current state of the symbolic join and execution is significantly suboptimal in this regard. Differential Revision: D29441149 fbshipit-source-id: cf801a6b1
3 years ago
let exec_move _ move_vec q =
let defs, uses =
IArray.fold move_vec (Llair.Reg.Set.empty, Llair.Reg.Set.empty)
~f:(fun (r, e) (defs, uses) ->
( Llair.Reg.Set.add r defs
, Llair.Exp.fold_regs ~f:Llair.Reg.Set.add e uses ) )
in
if not (Llair.Reg.Set.disjoint defs uses) then
todo "overwritten variables in Domain_itv" () ;
IArray.fold ~f:(fun (r, e) q -> assign r e q) move_vec q
[sledge] Add concurrency analysis Summary: This diff changes the analysis exploration algorithm from considering only sequential executions to considering executions of the interleaving semantics. As part of this, symbolic states are changed so that each thread has its own registers, while all memory is shared between them. Currently only a simple threads interface is supported: they can be created with `thread_create(&thread_routine)`, they can exit by returning from `thread_routine`, and they can be joined with `thread_join`. Current simplifications include that newly created threads are already runnable, thread routines accept no arguments and return no result, and no failures are possible. The concurrent exploration algorithm gives preference to executions which have fewer context switches, thereby performing an incremental form of context-bounded analysis. A form of partial-order reduction is performed, where the symbolic states are joined across (prefixes of) executions with the same number of context switches which reach a point where the instruction pointers and call stacks of all threads are the same. This has the effect of "dagifying" the concurrent execution tree by merging points after e.g. threads perform actions that commute with each other. This is unlike traditional partial-order reduction in that it relies on the symbolic join to combine the results of commuting operations in a way that the following symbolic execution can take advantage of, rather than performing some up-front analysis to identify commuting operations and quotienting the space of executions. The current state of the symbolic join and execution is significantly suboptimal in this regard. Differential Revision: D29441149 fbshipit-source-id: cf801a6b1
3 years ago
let exec_inst tid i q =
match (i : Llair.inst) with
[sledge] Add concurrency analysis Summary: This diff changes the analysis exploration algorithm from considering only sequential executions to considering executions of the interleaving semantics. As part of this, symbolic states are changed so that each thread has its own registers, while all memory is shared between them. Currently only a simple threads interface is supported: they can be created with `thread_create(&thread_routine)`, they can exit by returning from `thread_routine`, and they can be joined with `thread_join`. Current simplifications include that newly created threads are already runnable, thread routines accept no arguments and return no result, and no failures are possible. The concurrent exploration algorithm gives preference to executions which have fewer context switches, thereby performing an incremental form of context-bounded analysis. A form of partial-order reduction is performed, where the symbolic states are joined across (prefixes of) executions with the same number of context switches which reach a point where the instruction pointers and call stacks of all threads are the same. This has the effect of "dagifying" the concurrent execution tree by merging points after e.g. threads perform actions that commute with each other. This is unlike traditional partial-order reduction in that it relies on the symbolic join to combine the results of commuting operations in a way that the following symbolic execution can take advantage of, rather than performing some up-front analysis to identify commuting operations and quotienting the space of executions. The current state of the symbolic join and execution is significantly suboptimal in this regard. Differential Revision: D29441149 fbshipit-source-id: cf801a6b1
3 years ago
| Move {reg_exps; loc= _} -> Ok (exec_move tid reg_exps q)
| Store {ptr; exp; len= _; loc= _} -> (
match Llair.Reg.of_exp ptr with
| Some reg -> Ok (assign reg exp q)
| None -> Ok q )
| Load {reg; ptr; len= _; loc= _} -> Ok (assign reg ptr q)
[sledge] Add concurrency analysis Summary: This diff changes the analysis exploration algorithm from considering only sequential executions to considering executions of the interleaving semantics. As part of this, symbolic states are changed so that each thread has its own registers, while all memory is shared between them. Currently only a simple threads interface is supported: they can be created with `thread_create(&thread_routine)`, they can exit by returning from `thread_routine`, and they can be joined with `thread_join`. Current simplifications include that newly created threads are already runnable, thread routines accept no arguments and return no result, and no failures are possible. The concurrent exploration algorithm gives preference to executions which have fewer context switches, thereby performing an incremental form of context-bounded analysis. A form of partial-order reduction is performed, where the symbolic states are joined across (prefixes of) executions with the same number of context switches which reach a point where the instruction pointers and call stacks of all threads are the same. This has the effect of "dagifying" the concurrent execution tree by merging points after e.g. threads perform actions that commute with each other. This is unlike traditional partial-order reduction in that it relies on the symbolic join to combine the results of commuting operations in a way that the following symbolic execution can take advantage of, rather than performing some up-front analysis to identify commuting operations and quotienting the space of executions. The current state of the symbolic join and execution is significantly suboptimal in this regard. Differential Revision: D29441149 fbshipit-source-id: cf801a6b1
3 years ago
| Nondet {reg= Some reg; msg= _; loc= _} -> Ok (exec_kill tid reg q)
| Nondet {reg= None; msg= _; loc= _} | Alloc _ | Free _ -> Ok q
[sledge] Add concurrency analysis Summary: This diff changes the analysis exploration algorithm from considering only sequential executions to considering executions of the interleaving semantics. As part of this, symbolic states are changed so that each thread has its own registers, while all memory is shared between them. Currently only a simple threads interface is supported: they can be created with `thread_create(&thread_routine)`, they can exit by returning from `thread_routine`, and they can be joined with `thread_join`. Current simplifications include that newly created threads are already runnable, thread routines accept no arguments and return no result, and no failures are possible. The concurrent exploration algorithm gives preference to executions which have fewer context switches, thereby performing an incremental form of context-bounded analysis. A form of partial-order reduction is performed, where the symbolic states are joined across (prefixes of) executions with the same number of context switches which reach a point where the instruction pointers and call stacks of all threads are the same. This has the effect of "dagifying" the concurrent execution tree by merging points after e.g. threads perform actions that commute with each other. This is unlike traditional partial-order reduction in that it relies on the symbolic join to combine the results of commuting operations in a way that the following symbolic execution can take advantage of, rather than performing some up-front analysis to identify commuting operations and quotienting the space of executions. The current state of the symbolic join and execution is significantly suboptimal in this regard. Differential Revision: D29441149 fbshipit-source-id: cf801a6b1
3 years ago
| Intrinsic {reg= Some reg; _} -> Ok (exec_kill tid reg q)
| Intrinsic {reg= None; _} -> Ok q
| Abort {loc} ->
Error
{ Alarm.kind= Abort
; loc
; pp_action= Fun.flip Llair.Inst.pp i
; pp_state= Fun.flip pp q }
[sledge] Add concurrency analysis Summary: This diff changes the analysis exploration algorithm from considering only sequential executions to considering executions of the interleaving semantics. As part of this, symbolic states are changed so that each thread has its own registers, while all memory is shared between them. Currently only a simple threads interface is supported: they can be created with `thread_create(&thread_routine)`, they can exit by returning from `thread_routine`, and they can be joined with `thread_join`. Current simplifications include that newly created threads are already runnable, thread routines accept no arguments and return no result, and no failures are possible. The concurrent exploration algorithm gives preference to executions which have fewer context switches, thereby performing an incremental form of context-bounded analysis. A form of partial-order reduction is performed, where the symbolic states are joined across (prefixes of) executions with the same number of context switches which reach a point where the instruction pointers and call stacks of all threads are the same. This has the effect of "dagifying" the concurrent execution tree by merging points after e.g. threads perform actions that commute with each other. This is unlike traditional partial-order reduction in that it relies on the symbolic join to combine the results of commuting operations in a way that the following symbolic execution can take advantage of, rather than performing some up-front analysis to identify commuting operations and quotienting the space of executions. The current state of the symbolic join and execution is significantly suboptimal in this regard. Differential Revision: D29441149 fbshipit-source-id: cf801a6b1
3 years ago
let enter_scope _ _ q = q
type from_call = {areturn: Llair.Reg.t option; caller_q: t}
[@@deriving sexp_of]
let recursion_beyond_bound = `prune
(** existentially quantify locals *)
[sledge] Add concurrency analysis Summary: This diff changes the analysis exploration algorithm from considering only sequential executions to considering executions of the interleaving semantics. As part of this, symbolic states are changed so that each thread has its own registers, while all memory is shared between them. Currently only a simple threads interface is supported: they can be created with `thread_create(&thread_routine)`, they can exit by returning from `thread_routine`, and they can be joined with `thread_join`. Current simplifications include that newly created threads are already runnable, thread routines accept no arguments and return no result, and no failures are possible. The concurrent exploration algorithm gives preference to executions which have fewer context switches, thereby performing an incremental form of context-bounded analysis. A form of partial-order reduction is performed, where the symbolic states are joined across (prefixes of) executions with the same number of context switches which reach a point where the instruction pointers and call stacks of all threads are the same. This has the effect of "dagifying" the concurrent execution tree by merging points after e.g. threads perform actions that commute with each other. This is unlike traditional partial-order reduction in that it relies on the symbolic join to combine the results of commuting operations in a way that the following symbolic execution can take advantage of, rather than performing some up-front analysis to identify commuting operations and quotienting the space of executions. The current state of the symbolic join and execution is significantly suboptimal in this regard. Differential Revision: D29441149 fbshipit-source-id: cf801a6b1
3 years ago
let post _ locals _ (q : t) =
let locals =
Llair.Reg.Set.fold locals [] ~f:(fun r a ->
let v = apron_var_of_reg r in
if Environment.mem_var q.env v then v :: a else a )
|> Array.of_list
in
Abstract1.forget_array (Lazy.force man) q locals false
(** drop caller-local variables, add returned value to caller state *)
[sledge] Add concurrency analysis Summary: This diff changes the analysis exploration algorithm from considering only sequential executions to considering executions of the interleaving semantics. As part of this, symbolic states are changed so that each thread has its own registers, while all memory is shared between them. Currently only a simple threads interface is supported: they can be created with `thread_create(&thread_routine)`, they can exit by returning from `thread_routine`, and they can be joined with `thread_join`. Current simplifications include that newly created threads are already runnable, thread routines accept no arguments and return no result, and no failures are possible. The concurrent exploration algorithm gives preference to executions which have fewer context switches, thereby performing an incremental form of context-bounded analysis. A form of partial-order reduction is performed, where the symbolic states are joined across (prefixes of) executions with the same number of context switches which reach a point where the instruction pointers and call stacks of all threads are the same. This has the effect of "dagifying" the concurrent execution tree by merging points after e.g. threads perform actions that commute with each other. This is unlike traditional partial-order reduction in that it relies on the symbolic join to combine the results of commuting operations in a way that the following symbolic execution can take advantage of, rather than performing some up-front analysis to identify commuting operations and quotienting the space of executions. The current state of the symbolic join and execution is significantly suboptimal in this regard. Differential Revision: D29441149 fbshipit-source-id: cf801a6b1
3 years ago
let retn tid _ freturn {areturn; caller_q} callee_q =
match (areturn, freturn) with
| Some aret, Some fret ->
let env_fret_only =
match apron_typ_of_llair_typ (Llair.Reg.typ fret) with
| None -> Environment.make [||] [||]
| Some Texpr1.Int -> Environment.make [|apron_var_of_reg fret|] [||]
| _ -> Environment.make [||] [|apron_var_of_reg fret|]
in
let env = Environment.lce env_fret_only (Abstract1.env caller_q) in
let man = Lazy.force man in
let callee_fret =
(* drop all callee vars, scope to (caller + freturn) env *)
Abstract1.change_environment man callee_q env_fret_only false
|> fun q -> Abstract1.change_environment man q env false
in
let caller_q = Abstract1.change_environment man caller_q env false in
let result = Abstract1.meet man callee_fret caller_q in
Abstract1.rename_array man result
[|apron_var_of_reg fret|]
[|apron_var_of_reg aret|]
[sledge] Add concurrency analysis Summary: This diff changes the analysis exploration algorithm from considering only sequential executions to considering executions of the interleaving semantics. As part of this, symbolic states are changed so that each thread has its own registers, while all memory is shared between them. Currently only a simple threads interface is supported: they can be created with `thread_create(&thread_routine)`, they can exit by returning from `thread_routine`, and they can be joined with `thread_join`. Current simplifications include that newly created threads are already runnable, thread routines accept no arguments and return no result, and no failures are possible. The concurrent exploration algorithm gives preference to executions which have fewer context switches, thereby performing an incremental form of context-bounded analysis. A form of partial-order reduction is performed, where the symbolic states are joined across (prefixes of) executions with the same number of context switches which reach a point where the instruction pointers and call stacks of all threads are the same. This has the effect of "dagifying" the concurrent execution tree by merging points after e.g. threads perform actions that commute with each other. This is unlike traditional partial-order reduction in that it relies on the symbolic join to combine the results of commuting operations in a way that the following symbolic execution can take advantage of, rather than performing some up-front analysis to identify commuting operations and quotienting the space of executions. The current state of the symbolic join and execution is significantly suboptimal in this regard. Differential Revision: D29441149 fbshipit-source-id: cf801a6b1
3 years ago
| Some aret, None -> exec_kill tid aret caller_q
| None, _ -> caller_q
(** map actuals to formals (via temporary registers), stash constraints on
caller-local variables. Note that this exploits the non-relational-ness
of Box to ignore all variables other than the formal/actual params/
returns; this will not be possible if extended to a relational domain *)
[sledge] Add concurrency analysis Summary: This diff changes the analysis exploration algorithm from considering only sequential executions to considering executions of the interleaving semantics. As part of this, symbolic states are changed so that each thread has its own registers, while all memory is shared between them. Currently only a simple threads interface is supported: they can be created with `thread_create(&thread_routine)`, they can exit by returning from `thread_routine`, and they can be joined with `thread_join`. Current simplifications include that newly created threads are already runnable, thread routines accept no arguments and return no result, and no failures are possible. The concurrent exploration algorithm gives preference to executions which have fewer context switches, thereby performing an incremental form of context-bounded analysis. A form of partial-order reduction is performed, where the symbolic states are joined across (prefixes of) executions with the same number of context switches which reach a point where the instruction pointers and call stacks of all threads are the same. This has the effect of "dagifying" the concurrent execution tree by merging points after e.g. threads perform actions that commute with each other. This is unlike traditional partial-order reduction in that it relies on the symbolic join to combine the results of commuting operations in a way that the following symbolic execution can take advantage of, rather than performing some up-front analysis to identify commuting operations and quotienting the space of executions. The current state of the symbolic join and execution is significantly suboptimal in this regard. Differential Revision: D29441149 fbshipit-source-id: cf801a6b1
3 years ago
let call ~summaries _ ~globals:_ ~actuals ~areturn ~formals ~freturn:_
~locals:_ q =
if summaries then
todo "Summaries not yet implemented for interval analysis" ()
else
let mangle r =
Llair.Reg.mk (Llair.Reg.typ r) 0 ("__tmp__" ^ Llair.Reg.name r)
in
let args = IArray.combine_exn formals actuals in
let q' =
IArray.fold ~f:(fun (f, a) q -> assign (mangle f) a q) args q
in
let callee_env =
IArray.fold formals ([], []) ~f:(fun f (is, fs) ->
match apron_typ_of_llair_typ (Llair.Reg.typ f) with
| None -> (is, fs)
| Some Texpr1.Int -> (apron_var_of_reg (mangle f) :: is, fs)
| _ -> (is, apron_var_of_reg (mangle f) :: fs) )
|> fun (is, fs) ->
Environment.make (Array.of_list is) (Array.of_list fs)
in
let man = Lazy.force man in
let q'' = Abstract1.change_environment man q' callee_env false in
let q''' =
Abstract1.rename_array man q''
(Array.map
~f:(mangle >> apron_var_of_reg)
(IArray.to_array formals))
(Array.map ~f:apron_var_of_reg (IArray.to_array formals))
in
(q''', {areturn; caller_q= q})
let dnf q = [q]
[sledge] Add concurrency analysis Summary: This diff changes the analysis exploration algorithm from considering only sequential executions to considering executions of the interleaving semantics. As part of this, symbolic states are changed so that each thread has its own registers, while all memory is shared between them. Currently only a simple threads interface is supported: they can be created with `thread_create(&thread_routine)`, they can exit by returning from `thread_routine`, and they can be joined with `thread_join`. Current simplifications include that newly created threads are already runnable, thread routines accept no arguments and return no result, and no failures are possible. The concurrent exploration algorithm gives preference to executions which have fewer context switches, thereby performing an incremental form of context-bounded analysis. A form of partial-order reduction is performed, where the symbolic states are joined across (prefixes of) executions with the same number of context switches which reach a point where the instruction pointers and call stacks of all threads are the same. This has the effect of "dagifying" the concurrent execution tree by merging points after e.g. threads perform actions that commute with each other. This is unlike traditional partial-order reduction in that it relies on the symbolic join to combine the results of commuting operations in a way that the following symbolic execution can take advantage of, rather than performing some up-front analysis to identify commuting operations and quotienting the space of executions. The current state of the symbolic join and execution is significantly suboptimal in this regard. Differential Revision: D29441149 fbshipit-source-id: cf801a6b1
3 years ago
let resolve_callee _ _ _ _ = []
type summary = t
let pp_summary = pp
let apply_summary _ _ = None
[sledge] Add concurrency analysis Summary: This diff changes the analysis exploration algorithm from considering only sequential executions to considering executions of the interleaving semantics. As part of this, symbolic states are changed so that each thread has its own registers, while all memory is shared between them. Currently only a simple threads interface is supported: they can be created with `thread_create(&thread_routine)`, they can exit by returning from `thread_routine`, and they can be joined with `thread_join`. Current simplifications include that newly created threads are already runnable, thread routines accept no arguments and return no result, and no failures are possible. The concurrent exploration algorithm gives preference to executions which have fewer context switches, thereby performing an incremental form of context-bounded analysis. A form of partial-order reduction is performed, where the symbolic states are joined across (prefixes of) executions with the same number of context switches which reach a point where the instruction pointers and call stacks of all threads are the same. This has the effect of "dagifying" the concurrent execution tree by merging points after e.g. threads perform actions that commute with each other. This is unlike traditional partial-order reduction in that it relies on the symbolic join to combine the results of commuting operations in a way that the following symbolic execution can take advantage of, rather than performing some up-front analysis to identify commuting operations and quotienting the space of executions. The current state of the symbolic join and execution is significantly suboptimal in this regard. Differential Revision: D29441149 fbshipit-source-id: cf801a6b1
3 years ago
let create_summary _ ~locals:_ ~formals:_ q = (q, q)