let doInstr stmt (i: instr) (_d: t) =
let kinstr = !current_stmt
in
let add_with_additional_var k j st =
let deps, looking_for =
!Value.lval_to_loc_with_deps
~with_alarms:CilE.warn_none_mode
~deps:j
kinstr
k
in
let new_inputs =
Zone.join st.over_inputs (Zone.diff deps st.under_outputs) in
let new_outputs =
if Locations.valid_cardinal_zero_or_one
~for_writing:true
looking_for
then
Zone.link
st.under_outputs
(Locations.valid_enumerate_bits ~for_writing:true looking_for)
else st.under_outputs
in
{ over_inputs = new_inputs;
under_outputs = new_outputs }
in
match i with
| Set (lv, exp, _) ->
Dataflow.Post
(fun state ->
let exp_inputs_deps =
!From.find_deps_no_transitivity stmt exp
in
add_with_additional_var
lv
exp_inputs_deps
state)
| Call (lvaloption,funcexp,argl,_) ->
Dataflow.Post
(fun state ->
let funcexp_inputs, called_vinfos =
resolv_func_vinfo
~with_alarms:CilE.warn_none_mode
~deps:Zone.bottom
kinstr
funcexp
in
let acc_funcexp_arg_inputs =
List.fold_right
(fun arg inputs ->
let arg_inputs = !From.find_deps_no_transitivity stmt arg
in Zone.join inputs arg_inputs)
argl
funcexp_inputs
in
let state =
catenate
state
{ over_inputs = acc_funcexp_arg_inputs ;
under_outputs = Zone.bottom;}
in
let for_functions =
Kernel_function.Hptset.fold
(fun called_vinfo acc ->
let { Inout_type.over_inputs_if_termination = called_inputs_term;
under_outputs_if_termination = called_outputs ;
over_inputs = called_inputs} =
!Db.Operational_inputs.get_external called_vinfo
in
non_terminating_callees_inputs :=
Zone.join
!non_terminating_callees_inputs
(Zone.diff called_inputs state.under_outputs);
let for_function =
{ over_inputs = called_inputs_term;
under_outputs = called_outputs }
in
join for_function acc)
called_vinfos
bottom
in
let result = catenate state for_functions in
let result =
(match lvaloption with
| None -> result
| Some lv ->
add_with_additional_var
lv
Zone.bottom
result)
in result
)
| _ -> Dataflow.Default