let compute_using_cfg kf =
match kf.fundec with
| Declaration _ -> assert false
| Definition (f,_) ->
try
let module Computer =
Computer
(struct
let stmt_can_reach = Stmts_graph.stmt_can_reach kf
let blocks_closed_by_edge = Kernel_function.blocks_closed_by_edge
end)
in
let module Compute = Dataflow.Forwards(Computer) in
Stack.iter
(fun g ->
if kf == g then begin
if Db.Value.ignored_recursive_call kf then
From_parameters.error
"during dependencies computations for %a, ignoring probable recursive"
Kernel_function.pretty kf;
raise Exit
end)
call_stack;
Stack.push kf call_stack;
let state =
{ Computer.empty_from with
deps_table =
Lmap_bitwise.From_Model.uninitialize_locals
f.slocals Computer.empty_from.deps_table }
in
match f.sbody.bstmts with
[] -> assert false
| start :: _ ->
let ret_id =
try Kernel_function.find_return kf
with Kernel_function.No_Statement -> assert false
in
Computer.StmtStartData.add
start
(Computer.computeFirstPredecessor
start
state);
Compute.compute [start];
if not (Db.From.Record_From_Callbacks.is_empty ())
then begin
From_parameters.feedback "Now calling From callbacks";
let states =
Stmt.Hashtbl.create (Computer.StmtStartData.length ())
in
Computer.StmtStartData.iter
(fun k record ->
Stmt.Hashtbl.add states k record.deps_table);
Db.From.Record_From_Callbacks.apply
(call_stack, states, Computer.callwise_states_with_formals)
end;
let _poped = Stack.pop call_stack in
let last_from =
try
if Db.Value.is_reachable
(Values_To_Use.get_stmt_state ret_id)
then
Computer.externalize
ret_id
kf
(Computer.StmtStartData.find ret_id)
else
raise Not_found
with Not_found -> begin
From_parameters.result ~current:true "Non terminating function (no dependencies)";
{ Function_Froms.deps_return =
Lmap_bitwise.From_Model.LOffset.empty;
deps_table = Computer.empty_from.deps_table }
end
in
last_from
with Exit ->
{ Function_Froms.deps_return = Lmap_bitwise.From_Model.LOffset.empty;
deps_table = Lmap_bitwise.From_Model.empty }