aboutsummaryrefslogtreecommitdiffstats
path: root/cparser/Cutil.ml
diff options
context:
space:
mode:
Diffstat (limited to 'cparser/Cutil.ml')
-rw-r--r--cparser/Cutil.ml37
1 files changed, 37 insertions, 0 deletions
diff --git a/cparser/Cutil.ml b/cparser/Cutil.ml
index f5d5c425..66ea19e4 100644
--- a/cparser/Cutil.ml
+++ b/cparser/Cutil.ml
@@ -533,6 +533,43 @@ let sizeof_struct env members =
end
in sizeof_rec 0 members
+(* Compute the offset of a struct member *)
+let offsetof env ty fields =
+ let align_field ofs ty =
+ let a = match alignof env ty with
+ | Some a -> a
+ | None -> assert false in
+ align ofs a in
+ let rec offsetof_rec ofs field rest = function
+ | [] -> ofs
+ | m :: rem as ml ->
+ if m.fld_name = field.fld_name then begin
+ match rest with
+ | [] -> align_field ofs field.fld_typ
+ | _ -> lookup_field ofs field.fld_typ rest
+ end else if m.fld_bitfield = None then begin
+ match alignof env m.fld_typ, sizeof env m.fld_typ with
+ | Some a, Some s -> offsetof_rec (align ofs a + s) field rest rem
+ | _, _ -> assert false (* should never happen *)
+ end else begin
+ let (s, a, ml') = pack_bitfields ml in
+ let ofs = align ofs a + s in
+ offsetof_rec ofs field rest ml'
+ end
+ and lookup_field ofs ty = function
+ | [] -> align_field ofs ty
+ | fld::rest ->
+ begin match unroll env ty with
+ | TStruct (id,_) ->
+ let str = Env.find_struct env id in
+ offsetof_rec ofs fld rest str.ci_members
+ | TUnion (id,_) ->
+ lookup_field ofs fld.fld_typ rest
+ | _ -> assert false
+ end
+ in
+ lookup_field 0 ty (List.rev fields)
+
(* Simplified version to compute offsets on structs without bitfields *)
let struct_layout env members =
let rec struct_layout_rec mem ofs = function