aboutsummaryrefslogtreecommitdiffstats
path: root/cparser/Cutil.ml
diff options
context:
space:
mode:
authorBernhard Schommer <bernhardschommer@gmail.com>2017-01-20 10:55:26 +0100
committerBernhard Schommer <bernhardschommer@gmail.com>2017-01-20 10:55:26 +0100
commit55937c177f90ecf0dea40c318d2f8d52fa69b55d (patch)
tree493a207959cd64f6b3419dc109d246df35b01e54 /cparser/Cutil.ml
parentefaf1cf1c47370ab23db190fc4c2c1f3ad05323e (diff)
downloadcompcert-kvx-55937c177f90ecf0dea40c318d2f8d52fa69b55d.tar.gz
compcert-kvx-55937c177f90ecf0dea40c318d2f8d52fa69b55d.zip
Implement offsetof via builtin.
The implementation of offsetof as macro in the form ((size_t) &((ty*) NULL)->member) has the problem that it cannot be used everywhere were an integer constant expression is allowed, for example in initiliazers of global variables and there is also no check for the case that member is of bitifield type. The new implementation adds a builtin function for this which is replaced by an integer constant during elaboration. Bug 20765
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