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];
let _poped = Stack.pop call_stack in
try
Computer.StmtStartData.find ret_id.sid
with Not_found ->
non_terminating
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.under_inputs_termination_no_depend
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 leaf functions"
| Definition (f, _) ->
compute_for_definition kf f