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 =
        (* 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 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
(*                  Format.printf "loc for final zeroes %a@."
                      Locations.pretty loc; *)

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

            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 (* bit-field *)
                (* same sequence used for assignment to bit-fields in the code;
                   refactor *)

                  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);
(*          Format.printf "state after:%a@."
              Cvalue.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
                (*    Format.printf "acc:%d o:%d w:%d@." acc o w; *)
                    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; *)
                        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
          (*    Format.printf "last_bitsoffset:%d base_off:%d@\nstate after:%a@."
                last_bitsoffset
                base_off
                Cvalue.Model.pretty !state;  *)

              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 -> (* Default to zero init *)
                  if varinfo.vstorage = Extern
                  then
                    (* Must not assume zero when the storage is extern. *)
                    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);

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

      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 (* TODO: command line option *)
          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)