diff options
author | Xavier Leroy <xavier.leroy@inria.fr> | 2018-08-17 10:35:59 +0200 |
---|---|---|
committer | Xavier Leroy <xavierleroy@users.noreply.github.com> | 2018-08-17 14:01:08 +0200 |
commit | 999bea31a252dae1b0709166cf3c9540bda9dbb0 (patch) | |
tree | 7f203b9f97dcd398807d19c0dbeec866b0a63e1f /cparser/Cutil.mli | |
parent | 11837beafc84f226878b4706a791e9c13301e01f (diff) | |
download | compcert-kvx-999bea31a252dae1b0709166cf3c9540bda9dbb0.tar.gz compcert-kvx-999bea31a252dae1b0709166cf3c9540bda9dbb0.zip |
Issue with packed structs and sizeof, alignof, offsetof in cparser/
CompCert has two implementations of sizeof, alignof and offsetof (byte offset of a struct field):
- the reference implementation, in Coq, from cfrontend/Ctypes.v
- the implementation used during elaboration, in OCaml, from cparser/Cutil.ml
The reference Coq implementation is used as much as possible, but sometimes during elaboration the size of a type must be computed (e.g. to compute array sizes), or the offset of a field (e.g. to evaluate __builtin_offsetof), in which case the OCaml implementation is used.
This causes issues with packed structs. Currently, the cparser/Cutil.ml functions ignore the "packed" attribute on structs. Their results disagree with the "true" sizes, alignments and offsets computed by the cfrontend/Ctypes.v functions after source-to-source transformation of packed structs as done in cparser/PackedStruct.ml. For example:
```
struct __packed__(1) s { char c; short s; int i; };
assert (__builtin_offsetof(struct s, i) == 3);
assert (sizeof(struct s) = sizeof(char[sizeof(struct s)]));
```
The two assertions fail. In the first assertion, __builtin_offsetof is elaborated to 4, because the packed attribute is ignored during elaboration. In the second assertion, the type `char[sizeof(struct s)]` is elaborated to `char[8]`, again because the packed attribute is ignored during elaboration, while the other `sizeof(struct s)` is computed as 7 after the source-to-source transformation of packed structs.
This commit changes the cparser/Cutil.ml functions so that they take the packed attribute into account when computing sizeof, alignof, offsetof, and struct_layout.
Related changes:
* cparser/Cutil: add `packing_parameters` function to extract packing info from attributes
* cparser/Cutil: refactor and share more code between sizeof_struct, offsetof, and struct_layout
* cparser/Elab: check the alignment parameters given in packed attributes. (The check was previously done in cparser/PackedStruct.ml but now it would come too late.)
* cparser/Elab: refactor the checking of alignment parameters between _Alignas, attribute((aligned)), __packed__, and attribute((packed)).
* cparser/PackedStructs: simplify the code, some functionality was moved to cparser/Cutil, other to cparser/Elab
* cfrontend/C2C: raise an "unsupported" error if a packed struct is defined and -fpacked-structs is not given. Before, the packed attribute would be silently ignored, but now doing so would cause inconsistencies between cfrontend/ and cparser/.
* test/regression/packedstruct1.c: add tests to compare the sizes and the offsets produced by the elaborator with those obtained after elaboration.
Diffstat (limited to 'cparser/Cutil.mli')
-rw-r--r-- | cparser/Cutil.mli | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/cparser/Cutil.mli b/cparser/Cutil.mli index fb875b0d..5ae5dcd7 100644 --- a/cparser/Cutil.mli +++ b/cparser/Cutil.mli @@ -36,6 +36,11 @@ val incl_attributes : attributes -> attributes -> bool val alignas_attribute : attributes -> int (* Extract the value of the [_Alignas] attributes, if any. Return 0 if none, a (positive) power of two alignment if some. *) +val packing_parameters : attributes -> int * int * bool + (* Extract the value of the [__packed__] attributes, if any. + Return a triple + (maximum field alignment, minimum struct alignment, byte swapping). + Alignments of 0 mean default alignment. *) val find_custom_attributes : string list -> attributes -> attr_arg list list (* Extract arguments of custom [Attr] attributes whose names appear in the given list of names. *) @@ -127,7 +132,7 @@ val composite_info_decl: val composite_info_def: Env.t -> struct_or_union -> attributes -> field list -> Env.composite_info val struct_layout: - Env.t -> field list -> (string * int) list + Env.t -> attributes -> field list -> (string * int) list val offsetof: Env.t -> typ -> field -> int (* Compute the offset of a struct member *) |