let compute_using_prototype kf ~state_with_formals =
match kf.fundec with
| Definition (_,_) -> assert false
| Declaration (_,vi,_,_) when Cil.hasAttribute "noreturn" vi.vattr ->
None, Relations_type.Model.bottom, Location_Bits.Top_Param.bottom
| Declaration (_spec,varinfo,_,_) ->
let return_type,_formals_type,_inline,_attr =
splitFunctionType (Kernel_function.get_type kf)
in
let behaviors = valid_behaviors kf state_with_formals in
let assigns = Ast_info.merge_assigns behaviors in
let returned_value, state_with_formals =
return_value return_type kf state_with_formals
in
let returned_value = ref returned_value in
let clobbered_set = ref Location_Bits.Top_Param.bottom in
let state =
match assigns with
| [] -> state_with_formals
| assigns ->
let treat_assign acc (out, ins) =
let input_contents =
try
List.fold_left
(fun acc term ->
let input_loc =
!Db.Properties.Interp.identified_term_zone_to_loc
state_with_formals
term
in
let r =
Relations_type.Model.find
~with_alarms:CilE.warn_none_mode
state_with_formals
input_loc
in
Cvalue_type.V.join acc r)
Cvalue_type.V.top_int
ins
with Invalid_argument "not an lvalue" ->
Value_parameters.result
~once:true ~current:true
"cannot interpret assigns in function %a"
Kernel_function.pretty_name kf;
Cvalue_type.V.top
in
let treat_output_loc loc acc =
remember_bases_with_locals
clobbered_set
loc
input_contents;
let bound =
Relations_type.Model.add_binding
~with_alarms:CilE.warn_none_mode
~exact:false acc loc input_contents
in
Relations_type.Model.join bound acc
in
try
let lvals_out =
try
match out with
| Location out ->
!Db.Properties.Interp.loc_to_lval out.it_content
| Nothing -> []
with
Invalid_argument "not an lvalue" as e ->
begin match out with
Location {it_content={term_node=
TLval (TMem {term_node=TBinOp((IndexPI|PlusPI) ,
t1,_o1)},
_o2)}} ->
let deref_lvals =
!Db.Properties.Interp.loc_to_lval t1
in
raise (Deref_lvals deref_lvals)
| _ -> raise e
end
in
List.fold_left
(fun acc lval ->
let loc =
lval_to_loc ~with_alarms:CilE.warn_none_mode
state_with_formals lval
in
treat_output_loc loc acc
)
acc
lvals_out
with
Invalid_argument "not an lvalue" ->
(match out with
Location out when
Logic_utils.is_result out.it_content ->
returned_value :=
Cvalue_type.V.join
(Cvalue_type.V.topify_arith_origin
input_contents)
!returned_value;
acc
| Location _ ->
Value_parameters.warning ~once:true ~current:true
"Can not interpret assigns in function %a; effects will be ignored"
Kernel_function.pretty_name kf; acc
| Nothing -> assert false )
| Deref_lvals deref_lvals ->
let deref_loc =
List.fold_left
(fun acc lv ->
Location_Bits.join
(lval_to_loc ~with_alarms:CilE.warn_none_mode
state_with_formals lv).loc
acc)
Location_Bits.bottom
deref_lvals
in
let deref_loc = Location_Bits.topify_arith_origin deref_loc
in
let loc_bytes =
Relations_type.Model.find ~with_alarms:CilE.warn_none_mode
state_with_formals
(make_loc deref_loc Int_Base.top)
in
let loc =
make_loc (loc_bytes_to_loc_bits loc_bytes) Int_Base.top
in
treat_output_loc loc acc
in
(List.fold_left treat_assign state_with_formals assigns)
in
(if isVoidType return_type then None else
let offsetmap =
V_Offsetmap.update_ival
~with_alarms:CilE.warn_none_mode
~validity:Base.All
~offsets:Ival.zero
~exact:true
~size:(Int.of_int (bitsSizeOf return_type))
V_Offsetmap.empty
(Cvalue_type.V_Or_Uninitialized.initialized !returned_value)
in
Some offsetmap),
(Relations_type.Model.filter_base
(fun base -> not (Base.is_formal_of_prototype base varinfo))
state),
!clobbered_set