aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBernhard Schommer <bernhardschommer@gmail.com>2017-01-24 10:29:30 +0100
committerBernhard Schommer <bernhardschommer@gmail.com>2017-01-24 10:29:30 +0100
commitd60b593c8b1d19a4adfdadaeeaa93aa10b9dba53 (patch)
tree838eef3aa4f09efd467971a51e6c76d49ebb8a59
parent47e818992372c1480b1052b64728a33d758637cf (diff)
downloadcompcert-kvx-d60b593c8b1d19a4adfdadaeeaa93aa10b9dba53.tar.gz
compcert-kvx-d60b593c8b1d19a4adfdadaeeaa93aa10b9dba53.zip
New version to support designators.
The c standard allows member designators for offsetof. The current implementation works by recursively combining the offset of each of the member designators. For array access the size of the subtypes is multiplied by the index and for members the offset of the member is calculated. Bug 20765
-rw-r--r--cparser/Cabs.v2
-rw-r--r--cparser/Cutil.ml13
-rw-r--r--cparser/Cutil.mli2
-rw-r--r--cparser/Elab.ml41
-rw-r--r--cparser/Env.ml2
-rw-r--r--cparser/Parser.vy4
-rw-r--r--cparser/pre_parser.mly2
-rw-r--r--runtime/include/stddef.h2
8 files changed, 46 insertions, 22 deletions
diff --git a/cparser/Cabs.v b/cparser/Cabs.v
index 355c748e..b3e4ffda 100644
--- a/cparser/Cabs.v
+++ b/cparser/Cabs.v
@@ -142,7 +142,7 @@ with expression :=
(* Non-standard *)
| EXPR_ALIGNOF : expression -> expression
| TYPE_ALIGNOF : (list spec_elem * decl_type) -> expression
- | BUILTIN_OFFSETOF : (list spec_elem * decl_type) -> string -> expression
+ | BUILTIN_OFFSETOF : (list spec_elem * decl_type) -> list initwhat -> expression
with constant :=
(* The string is the textual representation of the constant in
diff --git a/cparser/Cutil.ml b/cparser/Cutil.ml
index 30f7294b..f55c1703 100644
--- a/cparser/Cutil.ml
+++ b/cparser/Cutil.ml
@@ -534,26 +534,23 @@ let sizeof_struct env members =
in sizeof_rec 0 members
(* Compute the offset of a struct member *)
-let offsetof env ty fields =
+let offsetof env ty field =
let rec sub acc name = function
| [] -> List.rev acc
| m::rem -> if m.fld_name = name then
List.rev acc
else
sub (m::acc) name rem in
- let offset (ofs,ty) field =
- match unroll env ty with
+ match unroll env ty with
| TStruct (id,_) ->
let str = Env.find_struct env id in
let pre = sub [] field.fld_name str.ci_members in
begin match sizeof_struct env pre ,alignof env field.fld_typ with
| Some s, Some a ->
- (ofs + align s a),field.fld_typ
+ align s a
| _ -> assert false end
- | _ -> ofs,field.fld_typ
- in
- let fields = List.rev fields in
- fst (List.fold_left offset (0,ty) fields)
+ | TUnion _ -> 0
+ | _ -> assert false
(* Simplified version to compute offsets on structs without bitfields *)
let struct_layout env members =
diff --git a/cparser/Cutil.mli b/cparser/Cutil.mli
index c5a074c5..a849d1fe 100644
--- a/cparser/Cutil.mli
+++ b/cparser/Cutil.mli
@@ -112,7 +112,7 @@ val composite_info_def:
val struct_layout:
Env.t -> field list -> (string * int) list
val offsetof:
- Env.t -> typ -> field list -> int
+ Env.t -> typ -> field -> int
(* Compute the offset of a struct member *)
(* Type classification functions *)
diff --git a/cparser/Elab.ml b/cparser/Elab.ml
index 6256bf1f..68dd1b76 100644
--- a/cparser/Elab.ml
+++ b/cparser/Elab.ml
@@ -1646,14 +1646,39 @@ let elab_expr vararg loc env a =
let (ty,env) = elab_type loc env spec dcl in
if Cutil.incomplete_type env ty then
error "offsetof of incomplete type %a" (print_typ env) ty;
- let fld = match unroll env ty with
- | TStruct(id,_) ->(wrap Env.find_struct_member loc env (id,mem))
- | TUnion (id,_)->(wrap Env.find_union_member loc env (id,mem))
- | _ ->
- error "request offsetof for member '%s' in something not a structure" mem in
- if List.exists (fun fld -> fld.fld_bitfield <> None) fld then
- error "cannot compute the offset of bitfield '%s" mem;
- let offset = Cutil.offsetof env ty fld in
+ let members env ty mem =
+ match ty with
+ | TStruct (id,_) -> wrap Env.find_struct_member loc env (id,mem)
+ | TUnion (id,_) -> wrap Env.find_union_member loc env (id,mem)
+ | _ -> error "request for member '%s' in something not a structure or union" mem in
+ let rec offset_of_list acc env ty = function
+ | [] -> acc,ty
+ | fld::rest -> let off = Cutil.offsetof env ty fld in
+ offset_of_list (acc+off) env fld.fld_typ rest in
+ let offset_of_member (env,off_accu,ty) mem =
+ match mem,unroll env ty with
+ | INFIELD_INIT mem,ty ->
+ let flds = members env ty mem in
+ let flds = List.rev flds in
+ let off,ty = offset_of_list 0 env ty flds in
+ env,off_accu + off,ty
+ | ATINDEX_INIT e,TArray (sub_ty,b,_) ->
+ let e,env = elab env e in
+ let e =
+ begin match Ceval.integer_expr env e,b with
+ | None,_ ->
+ error "array element designator for is not an integer constant expression"
+ | Some n,Some b -> if n >= b then
+ error "array index %Ld exceeds array bounds" n;
+ n
+ | Some n,None -> assert false
+ end in
+ let size = match sizeof env sub_ty with
+ | None -> assert false (* We expect only complete types *)
+ | Some s -> s in
+ env,off_accu + size * (Int64.to_int e),sub_ty
+ | ATINDEX_INIT _,_ -> error "subscripted value is not an array" in
+ let env,offset,_ = List.fold_left offset_of_member (env,0,ty) mem in
let offsetof_const = EConst (CInt(Int64.of_int offset,size_t_ikind (),"")) in
{ edesc = offsetof_const; etyp = TInt(size_t_ikind(), []) },env
diff --git a/cparser/Env.ml b/cparser/Env.ml
index 5fa4571a..27d17a93 100644
--- a/cparser/Env.ml
+++ b/cparser/Env.ml
@@ -220,6 +220,8 @@ let find_union_member env (id, m) =
with Not_found ->
raise(Error(No_member(id.name, "union", m)))
+
+
let find_typedef env id =
try
IdentMap.find id env.env_typedef
diff --git a/cparser/Parser.vy b/cparser/Parser.vy
index fb0b7444..f6bd6a7e 100644
--- a/cparser/Parser.vy
+++ b/cparser/Parser.vy
@@ -145,8 +145,8 @@ postfix_expression:
{ (CAST typ (COMPOUND_INIT (rev' init)), loc) }
| loc = LPAREN typ = type_name RPAREN LBRACE init = initializer_list COMMA RBRACE
{ (CAST typ (COMPOUND_INIT (rev' init)), loc) }
-| loc = BUILTIN_OFFSETOF LPAREN typ = type_name COMMA mem = OTHER_NAME RPAREN
- { (BUILTIN_OFFSETOF typ (fst mem), loc) }
+| loc = BUILTIN_OFFSETOF LPAREN typ = type_name COMMA mem = designator_list RPAREN
+ { (BUILTIN_OFFSETOF typ (rev mem), loc) }
(* Semantic value is in reverse order. *)
argument_expression_list:
diff --git a/cparser/pre_parser.mly b/cparser/pre_parser.mly
index 1c917b23..dc9c5319 100644
--- a/cparser/pre_parser.mly
+++ b/cparser/pre_parser.mly
@@ -254,7 +254,7 @@ postfix_expression:
| postfix_expression LBRACK expression RBRACK
| postfix_expression LPAREN argument_expression_list? RPAREN
| BUILTIN_VA_ARG LPAREN assignment_expression COMMA type_name RPAREN
-| BUILTIN_OFFSETOF LPAREN type_name COMMA other_identifier RPAREN
+| BUILTIN_OFFSETOF LPAREN type_name COMMA designator_list RPAREN
| postfix_expression DOT other_identifier
| postfix_expression PTR other_identifier
| postfix_expression INC
diff --git a/runtime/include/stddef.h b/runtime/include/stddef.h
index 452497c3..958720a1 100644
--- a/runtime/include/stddef.h
+++ b/runtime/include/stddef.h
@@ -114,7 +114,7 @@ typedef signed int wchar_t;
#endif
#if defined(_STDDEF_H) && !defined(offsetof)
-#define offsetof(ty,member) (__builtin_offsetof(ty,member))
+#define offsetof(ty,member) (__builtin_offsetof(ty,.member))
#endif
#endif