let initial_state_only_globals =
let module S =
Computation.OptionRef
(Relations_type.Model.Datatype)
(struct
let name = "only_globals"
let dependencies =
[ Ast.self; Parameters.LibEntry.self; Parameters.MainFunction.self ]
end)
in
function () ->
let compute () =
Value_parameters.debug ~level:2 "Computing globals values";
let state = ref Relations_type.Model.empty in
let complete_init last_bitsoffset typ _l lval =
begin try
let size_to_add, offset =
bitsSizeOf typ - last_bitsoffset,
Ival.inject_singleton (Int.of_int last_bitsoffset)
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 loc =
Location_Bits.inject base offset
in
make_loc
loc
(Int_Base.inject (Int.of_int size_to_add))
| _ -> error "Whacky initializer ? Please report.";
assert false
in
let v =
if hasAttribute "volatile" (typeAttrs typ)
then V.top_int
else V.singleton_zero
in
state :=
Relations_type.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 = lval_to_loc ~with_alarms:CilE.warn_none_mode Relations_type.Model.empty lval
in
let exact = cardinal_zero_or_one loc in
assert (if not exact then (Cil.warning "In global initialisation, the location can not be represented. Aborting@."; exit 1); true);
let value =
eval_expr ~with_alarms:(warn_all_quiet_mode ())
Relations_type.Model.empty
exp
in
let v =
if hasAttribute "volatile" (typeAttrs (Cil.typeOfLval lval))
then V.top_int
else value
in
state :=
Relations_type.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
state := Relations_type.Model.add_binding_unspecified
!state
(make_loc loc_bits loc_size)
end else assert (acc=o);
if hasAttribute "volatile" (typeAttrs typ) then
Value_parameters.warning ~current:true ~once:true
"global initialization of volatile value ignored"
else
eval_init (addOffsetLval off lval) init;
o+w)
~ct:base_typ
~initl:l
~acc:0 in
complete_init last_bitsoffset base_typ l lval
else ()
in
Globals.Vars.iter
(fun varinfo init ->
if not varinfo.vlogic then begin
CurrentLoc.set varinfo.vdecl;
match init.init with
| None
->
if varinfo.vstorage = Extern then
state := initialize_var_using_type varinfo !state
else complete_init 0 varinfo.vtype [] (Var varinfo,NoOffset)
| Some i ->
eval_init (Var varinfo,NoOffset) i
end);
if Int.le
(Base.min_valid_absolute_address ())
(Base.max_valid_absolute_address ())
then begin
let loc_bits = Location_Bits.inject_ival
(Ival.inject_singleton (Base.min_valid_absolute_address ()))
in
let loc_size =
Int_Base.inject
(Int.length
(Base.min_valid_absolute_address ())
(Base.max_valid_absolute_address ()))
in
if true
then
state :=
Relations_type.Model.add_binding
~with_alarms:CilE.warn_none_mode
~exact:true
!state
(make_loc loc_bits loc_size)
Cvalue_type.V.top_int
else
state :=
Relations_type.Model.add_binding_unspecified
!state
(make_loc loc_bits loc_size)
end;
let result = !state in
result
in
S.memo compute