let select_lval_rw set mark ~rd ~wr ~scope ~eval kf ki_opt=
assert (Db.Value.is_computed ());
let zone_option ~for_writing lval_str =
if Datatype.String.Set.is_empty lval_str
then None
else
let zone =
Datatype.String.Set.fold
(fun lval_str acc ->
let lval_term = !Db.Properties.Interp.lval kf scope lval_str in
let lval = !Db.Properties.Interp.term_lval_to_lval ~result:None lval_term in
let loc = !Db.Value.lval_to_loc ~with_alarms:CilE.warn_none_mode (Kstmt eval) lval in
let zone = Locations.valid_enumerate_bits ~for_writing loc
in Locations.Zone.join zone acc)
lval_str Locations.Zone.bottom
in SlicingParameters.debug ~level:3
"select_lval_rw %a zone=%a"
Kernel_function.pretty kf
Locations.Zone.pretty zone;
Some zone
in
let zone_rd_opt = zone_option ~for_writing:false rd in
let zone_wr_opt = zone_option ~for_writing:true wr in
match zone_rd_opt, zone_wr_opt with
| None, None -> set
| (_, _) as zone_option_rw ->
let ac = ref set in
let select_rw_from_stmt kf ki =
let rd_zone_opt, wr_zone_opt = Kinstr.is_rw_zone zone_option_rw ki in
let select_zone ~before zone_opt =
match zone_opt with
| None -> !ac
| Some zone ->
SlicingParameters.debug ~level:3
"select_lval_rw sid=%d before=%b zone=%a"
ki.sid before Locations.Zone.pretty zone;
select_stmt_zone !ac mark zone ~before ki kf ;
in
ac := select_zone ~before:true rd_zone_opt ;
ac := select_zone ~before:false wr_zone_opt
in (match ki_opt with
| Some ki -> select_rw_from_stmt kf ki
| None ->
Globals.Functions.iter
(fun kf ->
if !Db.Value.is_called kf then
if not (!Db.Value.use_spec_instead_of_definition kf)
then
Kinstr.iter_from_func (select_rw_from_stmt kf) kf
else begin
let select_inter_zone fsel zone_opt zone =
match zone_opt with
| None -> ()
| Some zone_requested ->
if Locations.Zone.intersects zone_requested zone
then let inter = Locations.Zone.narrow zone_requested zone
in fsel inter
else () in
let select_wr outputs =
ac := select_entry_point_and_some_inputs_outputs !ac ~mark kf
~return:false ~outputs ~inputs:Locations.Zone.bottom
and select_rd inputs =
ac := select_entry_point_and_some_inputs_outputs !ac ~mark kf
~return:false ~inputs ~outputs:Locations.Zone.bottom
in
assert (!Db.Value.is_called kf) ;
select_inter_zone select_wr zone_wr_opt (!Db.Outputs.get_external kf) ;
select_inter_zone select_rd zone_rd_opt (!Db.Inputs.get_external kf)
end
));
!ac