let initial_state_only_globals =
let module S =
State_builder.Option_ref
(Cvalue.Model)
(struct
let name = "only_globals"
let dependencies =
[ Ast.self; Kernel.LibEntry.self; Kernel.MainFunction.self ]
let kind = `Internal
end)
in
function () ->
let compute () =
Value_parameters.debug ~level:2 "Computing globals values";
let state = ref Cvalue.Model.empty_map in
let update_state st' =
if not (Db.Value.is_reachable st')
then raise Initialization_failed
else state := st'
in
let complete_init ~last_bitsoffset ~abs_offset typ _l lval =
begin try
let size_to_add, offset =
bitsSizeOf typ - last_bitsoffset,
Ival.inject_singleton (Int.of_int abs_offset)
in
assert (size_to_add >= 0);
if size_to_add <> 0 then
let loc =
match lval with
| Var vinfo, _ ->
let base = Base.create_varinfo vinfo in
let size_to_add = (Int.of_int size_to_add) in
let offset, size =
match Base.validity base with
Base.Periodic (mn, _mx, p) when Int.ge size_to_add p ->
Ival.inject_singleton mn, p
| _ -> offset, size_to_add
in
let loc =
Location_Bits.inject base offset
in
let loc = make_loc loc (Int_Base.inject size) in
loc
| _ ->
Value_parameters.error ~current:true
"Whacky initializer ? Please report.";
assert false
in
let v =
if hasAttribute "volatile" (typeAttrs typ)
then V.top_int
else V.singleton_zero
in
update_state
(Cvalue.Model.add_binding
~with_alarms:CilE.warn_none_mode
~exact:true
!state
loc
v)
with Cil.SizeOfError _ ->
Value_parameters.result ~once:true ~current:true
"cannot provide a default initializer: size is unknown"
end
in
let rec eval_init lval init =
match init with
| SingleInit exp ->
let loc =
Eval_exprs.lval_to_loc ~with_alarms:CilE.warn_none_mode
Cvalue.Model.top lval
in
let exact = cardinal_zero_or_one loc in
assert
(if exact then true
else begin
Value_parameters.warning ~current:true
"In global initialisation, the location can not be represented. Aborting.";
false
end);
let value =
Eval_exprs.eval_expr ~with_alarms:(warn_all_quiet_mode ())
!state
exp
in
let v =
if hasAttribute "volatile" (typeAttrs (Cil.typeOfLval lval))
then V.top_int
else if not (Int_Base.equal
loc.Locations.size
(Int_Base.inject
(Int.of_int ((bitsSizeOf (typeOf exp))))))
then
Cvalue.V.cast ~with_alarms:CilE.warn_none_mode
~size:(Int_Base.project loc.Locations.size)
~signed:(signof_typeof_lval lval)
value
else value
in
update_state
(Cvalue.Model.add_binding
~with_alarms:CilE.warn_none_mode ~exact
!state loc v);
| CompoundInit (base_typ, l) ->
if not (hasAttribute "volatile" (typeAttrs base_typ))
then
let last_bitsoffset =
foldLeftCompound
~implicit:false
~doinit:
(fun off init typ (acc:int) ->
let o,w = bitsOffset base_typ off in
if acc<o
then begin
let vi, (base_off,_) =
(match lval with
| Var vinfo, abs_offset ->
vinfo,
(bitsOffset vinfo.vtype abs_offset)
| _ ->
Value_parameters.fatal "Whacky initializer?")
in
let loc_bits =
Location_Bits.inject
(Base.create_varinfo vi)
(Ival.inject_singleton (Int.of_int (base_off+acc)))
in
let loc_size = Int_Base.inject (Int.of_int (o-acc)) in
let loc = make_loc loc_bits loc_size in
update_state
(Cvalue.Model.add_binding_not_initialized
!state
loc)
end
else assert (acc=o);
if hasAttribute "volatile" (typeAttrs typ) then
warning_once_current
"global initialization of volatile value ignored"
else
eval_init (addOffsetLval off lval) init;
o+w)
~ct:base_typ
~initl:l
~acc:0
in
let base_off,_ =
(match lval with
| Var vinfo, abs_offset ->
bitsOffset vinfo.vtype abs_offset
| _ ->
Value_parameters.fatal "Whacky initializer?")
in
complete_init ~last_bitsoffset
~abs_offset:(base_off+last_bitsoffset)
base_typ
l
lval
else ()
in
Globals.Vars.iter_in_file_order
(fun varinfo init ->
if not varinfo.vlogic then begin
CurrentLoc.set varinfo.vdecl;
match init.init with
| None ->
if varinfo.vstorage = Extern
then
update_state (initialize_var_using_type varinfo !state)
else
complete_init ~last_bitsoffset:0 ~abs_offset:0
varinfo.vtype [] (Var varinfo,NoOffset)
| Some i ->
eval_init (Var varinfo,NoOffset) i
end);
let min_valid = Base.min_valid_absolute_address () in
let max_valid = Base.max_valid_absolute_address () in
if Int.le min_valid max_valid
then begin
let loc_bits =
Location_Bits.inject_ival
(Ival.inject_singleton min_valid)
in
let loc_size =
Int_Base.inject
(Int.length min_valid max_valid)
in
if true
then
update_state
(Cvalue.Model.add_binding
~with_alarms:CilE.warn_none_mode
~exact:true
!state
(make_loc loc_bits loc_size)
Cvalue.V.top_int)
else
update_state
(Cvalue.Model.add_binding_not_initialized
!state
(make_loc loc_bits loc_size))
end;
let result = !state in
result
in
S.memo
(fun () ->
try compute ()
with Initialization_failed -> Cvalue.Model.bottom)