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.ForwardsDataFlow(Computer) in
Stack.iter
(fun g ->
if kf == g then begin
From_parameters.error
"ignoring recursive call detected in function %a during dependencies computations."
Kernel_function.pretty_name 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 = Kernel_function.find_return kf in
Computer.StmtStartData.add
start.sid
(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 =
Inthash.create (Computer.StmtStartData.length ())
in
Computer.StmtStartData.iter
(fun k record ->
Inthash.add states k record.deps_table);
Db.From.Record_From_Callbacks.apply (call_stack, states)
end;
let _poped = Stack.pop call_stack in
let last_from =
try
if Db.Value.is_reachable
(Values_To_Use.get_state (Kstmt ret_id))
then
Computer.externalize
ret_id
f
(Computer.StmtStartData.find ret_id.sid)
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 }