let compute_using_prototype_for_state state kf =
let varinfo = Kernel_function.get_vi kf in
let behaviors = !Value.valid_behaviors kf state in
let assigns = Ast_info.merge_assigns behaviors in
let return_deps,deps =
match assigns with
WritesAny ->
Lmap_bitwise.From_Model.LOffset.empty,
Lmap_bitwise.From_Model.empty
| Writes assigns ->
let (rt_typ,_,_,_) = splitFunctionTypeVI varinfo in
let input_zone ins =
match ins with
FromAny -> Zone.top
| From l ->
(try
List.fold_left
(fun acc loc ->
Zone.join acc
(Locations.valid_enumerate_bits
~for_writing:false
(!Properties.Interp.loc_to_loc
~result:None
state
loc.it_content)))
Zone.bottom
l
with Invalid_argument "not an lvalue" ->
From_parameters.result ~once:true ~current:true
"Unable to extract precise FROM in %a"
Kernel_function.pretty kf;
Zone.top)
in
let treat_assign acc (out, ins) =
try
let output_loc =
!Properties.Interp.loc_to_loc ~result:None state
out.it_content
in
let output_zone =
Locations.valid_enumerate_bits ~for_writing:true
output_loc
in
Lmap_bitwise.From_Model.add_binding ~exact:true
acc output_zone (input_zone ins)
with Invalid_argument "not an lvalue" ->
From_parameters.result
~once:true ~current:true "Unable to extract assigns in %a"
Kernel_function.pretty kf;
acc
in
let treat_ret_assign acc (out,ins) =
try
let coffs =
!Properties.Interp.loc_to_offset ~result:None out.it_content
in
List.fold_left
(fun acc coff ->
let (base,width) = bitsOffset rt_typ coff in
Lmap_bitwise.From_Model.LOffset.add_iset
~exact:true
(Abstract_value.Int_Intervals.from_ival_size
(Ival.of_int base)
(Int_Base.inject (Int.of_int width)))
(input_zone ins) acc)
acc coffs
with Invalid_argument "not an lvalue" | SizeOfError _ ->
From_parameters.result ~once:true ~current:true
"Unable to extract a proper offset. Using FROM for the whole \\result";
Lmap_bitwise.From_Model.LOffset.add_iset ~exact:false
(Abstract_value.Int_Intervals.from_ival_size
(Ival.of_int 0) (Bit_utils.sizeof rt_typ))
(input_zone ins) acc
in
let return_assigns, other_assigns =
List.fold_left
(fun (ra,oa) (loc,_ as a) ->
if Logic_utils.is_result loc.it_content
then a::ra,oa else ra,a::oa)
([],[]) assigns
in
let return_assigns =
match return_assigns with
| [] when Cil.isVoidType rt_typ ->
Lmap_bitwise.From_Model.LOffset.empty
| [] ->
Lmap_bitwise.From_Model.LOffset.add_iset ~exact:true
(Abstract_value.Int_Intervals.from_ival_size
(Ival.of_int 0) (Bit_utils.sizeof rt_typ))
(input_zone FromAny)
Lmap_bitwise.From_Model.LOffset.empty
| _ ->
List.fold_left treat_ret_assign
Lmap_bitwise.From_Model.LOffset.empty return_assigns
in
return_assigns,
List.fold_left
treat_assign
Lmap_bitwise.From_Model.empty
other_assigns
in
{ deps_return = return_deps; Function_Froms.deps_table = deps }