let initial_state_only_globals =
  let module S =
    State_builder.Option_ref
      (Relations_type.Model)
      (struct
        let name = "only_globals"
        let dependencies =
          [ Ast.self; Parameters.LibEntry.self; Parameters.MainFunction.self ]
        let kind = `Internal
      end)
  in
  function () ->
    let compute ()  =
      Value_parameters.debug ~level:2 "Computing globals values";
      let state = ref Relations_type.Model.empty_map in
      let complete_init last_bitsoffset typ _l lval =
        (* Now process the non initialized bits defaulting to 0 *)
        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 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
(*                    Format.printf "loc for final zeroes %a@."
                      Locations.pretty loc; *)

                    loc
                | _ -> 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.top lval
            in
(*            Format.printf "loc:%a state before:%a@."
              Locations.pretty loc
              Relations_type.Model.pretty !state;  *)

            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.top
                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;
(*            Format.printf "state after:%a@."
              Relations_type.Model.pretty !state;  *)


        | 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 (* uninitialize the padding bits *)
                        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
(*                        Format.printf "loc:%a@." Locations.pretty loc; *)
                        state :=
                          Relations_type.Model.add_binding_unspecified
                            !state
                            loc
                      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 -> (* Default to zero init *)
                  if varinfo.vstorage = Extern
                  then
                    (* Must not assume zero when the storage is extern. *)
                    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);

      
      (** Bind the declared range for NULL to uninitialized *)

      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 (* TODO: command line option *)
          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
                (*          ~with_alarms:warn_none_mode
                            ~exact:true *)

                !state
                (make_loc loc_bits loc_size)
                (*          Cvalue_type.V.bottom *)
        end;
      let result = !state in
      result
    in
    S.memo compute