let compute_internal_using_cfg kf =
let compute_for_definition kf f =
try
let module Computer =
Computer
(struct let stmt_can_reach = Stmts_graph.stmt_can_reach kf end)
in
let module Compute = Dataflow.ForwardsDataFlow(Computer) in
Stack.iter
(fun g -> if kf == g then begin
Inout_parameters.warning ~current:true
"ignoring recursive call detected in function %s during [inout context] computation."
(Kernel_function.get_name kf);
raise Exit
end)
call_stack;
Stack.push kf call_stack;
let res_if_termination =
match f.sbody.bstmts with
[] -> assert false
| start :: _ ->
let ret_id = Kernel_function.find_return kf in
Computer.StmtStartData.add
start.sid
(Computer.computeFirstPredecessor
start
empty);
Compute.compute [start];
ignore (Stack.pop call_stack);
try
Computer.StmtStartData.find ret_id.sid
with Not_found -> bottom
in
{ Inout_type.over_inputs_if_termination = res_if_termination.over_inputs;
under_outputs_if_termination = res_if_termination.under_outputs ;
over_inputs =
let acc = Computer.non_terminating_callees_inputs
in
Computer.StmtStartData.iter
(fun _sid data -> acc := Zone.join data.over_inputs !acc);
!acc}
with Exit ->
{ Inout_type.over_inputs_if_termination = empty.over_inputs ;
under_outputs_if_termination = empty.under_outputs ;
over_inputs = empty.over_inputs
}
in
match kf.fundec with
| Declaration _ ->
invalid_arg
"compute_using_cfg cannot be called on library functions"
| Definition (f, _) ->
compute_for_definition kf f