let initialize_var_using_type varinfo state =
  CurrentLoc.set varinfo.vdecl;
  let initializing_formal = not varinfo.vglob in
  let rec add_offsetmap depth v name_desc name typ offset_orig typ_orig state =
    let typ = Cil.unrollType typ in
    let loc = loc_of_typoffset v typ_orig offset_orig in
    let must_initialize =
      initializing_formal ||
      (not (hasAttribute "const" (typeAttrs typ))) ||
        (Cvalue_type.V.equal
            (Relations_type.Model.find ~conflate_bottom:true ~with_alarms:CilE.warn_none_mode
                state loc)
            Cvalue_type.V.bottom)
    in
    if not must_initialize
      (* if we do not have an initializer for this const, we generate
         a formal constant *)

    then state else
      match typ with
      | TInt _ | TEnum (_, _)->
          Relations_type.Model.add_binding
            ~with_alarms:CilE.warn_none_mode
            ~exact:true
            state
            loc
            Cvalue_type.V.top_int
      | TFloat _ ->
          Relations_type.Model.add_binding
            ~with_alarms:CilE.warn_none_mode
            ~exact:true
            state
            loc
            Cvalue_type.V.top_float
      | TFun _ ->
          Relations_type.Model.add_binding
            ~with_alarms:CilE.warn_none_mode
            ~exact:true
            state
            loc
            (Cvalue_type.V.top_leaf_origin ())
      | TPtr (typ, _) as full_typ
          when depth <= Value_parameters.AutomaticContextMaxDepth.get () ->
          let attr = typeAttr full_typ in

          if not (isVoidType typ) && not (isFunctionType typ) then
            let i = match findAttribute "arraylen" attr with
            | [AInt i] -> i
            | _ -> Value_parameters.AutomaticContextMaxWidth.get ()
            in
            let pointed_typ =
              TArray(typ,Some (integer i),empty_size_cache (), [])
            in
            let hidden_var_name =
              Cabs2cil.fresh_global ("S_" ^ name)
            in
            let name_desc = "*"^name_desc in
            let hidden_base =
              create_hidden_base
                true
                ~hidden_var_name
                ~name_desc
                pointed_typ
            in
            let state = add_offsetmap
              (depth + 1)
              hidden_base
              name_desc
              hidden_var_name
              pointed_typ
              NoOffset
              pointed_typ
              state
            in
            let value = Cvalue_type.V.inject hidden_base (Ival.zero)
            in
            let value =
              if Value_parameters.AllocatedContextValid.get ()
              then value
              else Cvalue_type.V.join Cvalue_type.V.singleton_zero value
            in
            Relations_type.Model.add_binding
              ~with_alarms:CilE.warn_none_mode
              ~exact:true
              state
              loc
              value
          else
            let hidden_var_name =
              Cabs2cil.fresh_global ("S_" ^ name)
            in
            let name_desc = "*"^name_desc in
            let hidden_base =
              create_hidden_base
                false
                ~hidden_var_name
                ~name_desc
                typ
            in
            make_well hidden_base state loc

      | TArray (typ, len, _, _) ->
          begin try
            let size = lenOfArray len in
            let state = ref state in
            let treat_index (i : int) =
              let offset =
                addOffset
                  (Index (integer i, NoOffset))
                  offset_orig
              in
              let name = (string_of_int i) ^"_"^ name in
              let name_desc = name_desc ^ "[" ^ (string_of_int i) ^ "]" in
              state := (add_offsetmap depth v
                          name_desc name typ
                          offset typ_orig !state)
            in
            for i = 0 to pred size do
              treat_index i
            done;
            !state
          with LenOfArray ->
            Value_parameters.result ~once:true ~current:true
              "could not find a size for array";
            state
          end
      | TComp ({cstruct=true;} as compinfo, _, _) -> (* Struct *)
          let treat_field (next_offset,state) field =
            let new_offset = Field (field, NoOffsetin
            let offset =
              addOffset
                new_offset
                offset_orig
            in
            let field_offset,field_width = bitsOffset typ_orig offset in
            let state =
              if field_offset>next_offset then (* padding bits needs filling*)
                let loc = make_loc
                  (Location_Bits.inject v (Ival.of_int next_offset))
                  (Int_Base.inject (Int.of_int (field_offset-next_offset)))
                in
                Relations_type.Model.add_binding_unspecified
                  state
                  loc
              else state
            in
            field_offset+field_width,
            add_offsetmap
              depth
              v
              (name_desc ^ "." ^ field.fname)
              (field.fname^"_"^name)
              field.ftype
              offset
              typ_orig
              state
          in
          begin try
            let boff,bwidth = bitsOffset typ_orig offset_orig in
            let last_offset,state= List.fold_left
              treat_field
              (boff,state)
              compinfo.cfields
            in
            if last_offset<(boff+bwidth) then (* padding at end of struct*)
              let loc = make_loc
                (Location_Bits.inject v (Ival.of_int last_offset))
                (Int_Base.inject (Int.of_int (boff+bwidth-last_offset)))
              in
              Relations_type.Model.add_binding_unspecified
                state
                loc
            else state
          with Cil.SizeOfError _ -> state
          end
      | TComp ({cstruct=false}, _, _) when
          is_fully_arithmetic typ
          -> (* Union of arithmetic types *)
          Relations_type.Model.add_binding
            ~with_alarms:CilE.warn_none_mode
            ~exact:true
            state
            loc
            Cvalue_type.V.top_int

      | TPtr _ when Value_parameters.AllocatedContextValid.get () ->
          (* deep pointers map to NULL in this case *)
          Relations_type.Model.add_binding
            ~with_alarms:CilE.warn_none_mode
            ~exact:true
            state
            loc
            Cvalue_type.V.singleton_zero

      | TBuiltin_va_list _ | TComp _ | TVoid _  | TPtr  _ ->
          (* variable arguments or union with non-arithmetic type or deep pointers *)

          (* first create a new varid and offsetmap for the
             "hidden location" *)

          let hidden_var_name =
            Cabs2cil.fresh_global ("WELL_"^name)
          in
          let hidden_var =
            makeGlobalVar ~logic:true hidden_var_name charType
          in
          hidden_var.vdescr <- Some (name_desc^"_WELL");
          let hidden_base =
            Base.create_logic
              hidden_var
              (Base.Known (Int.zero,Bit_utils.max_bit_address ()))
          in
          make_well  hidden_base state loc
      | TNamed (_, _)  -> assert false
  in
  add_offsetmap
    0
    (Base.create_varinfo varinfo)
    varinfo.vname varinfo.vname varinfo.vtype NoOffset varinfo.vtype state