aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Leroy <xavier.leroy@inria.fr>2015-07-08 10:16:53 +0200
committerXavier Leroy <xavier.leroy@inria.fr>2015-07-08 10:16:53 +0200
commit2b1c0aa69adafac185dd6c4e460d83517bcc8884 (patch)
tree00efb84c95bb3c75286dc0085e9c38b6cf5a25be
parent24a08b236f6334f5c01e423fb564892e070b4bff (diff)
downloadcompcert-2b1c0aa69adafac185dd6c4e460d83517bcc8884.tar.gz
compcert-2b1c0aa69adafac185dd6c4e460d83517bcc8884.zip
Fix issue with bit fields of type _Bool
cparser/Bitfields.ml: when assigning to a bit field of type _Bool, the right-hand side must be normalized to 0 or 1 via a cast to _Bool. test/regression/bitfields{1,9}.c: add corresponding test cases.
-rw-r--r--cparser/Bitfields.ml28
-rw-r--r--test/regression/Results/bitfields96
-rw-r--r--test/regression/bitfields1.c4
-rw-r--r--test/regression/bitfields9.c14
4 files changed, 34 insertions, 18 deletions
diff --git a/cparser/Bitfields.ml b/cparser/Bitfields.ml
index 570572fa..6569bb4c 100644
--- a/cparser/Bitfields.ml
+++ b/cparser/Bitfields.ml
@@ -31,7 +31,8 @@ type bitfield_info =
bf_pos: int; (* start bit *)
bf_size: int; (* size in bit *)
bf_signed: bool; (* is field signed or unsigned? *)
- bf_signed_res: bool (* is result of extracting field signed or unsigned? *)
+ bf_signed_res: bool; (* is result of extracting field signed or unsigned? *)
+ bf_bool: bool (* does field have type _Bool? *)
}
(* invariants:
@@ -100,7 +101,13 @@ let pack_bitfields env sid ml =
match unroll env (type_of_member env m) with
| TInt(ik, _) -> is_signed_ikind ik
| _ -> assert false (* should never happen, checked in Elab *) in
- pack ((m.fld_name, pos, n, signed, signed2) :: accu) (pos + n) ms
+ let is_bool =
+ match unroll env m.fld_typ with
+ | TInt(IBool, _) -> true
+ | _ -> false in
+
+ pack ((m.fld_name, pos, n, signed, signed2, is_bool) :: accu)
+ (pos + n) ms
end
in pack [] 0 ml
@@ -121,7 +128,7 @@ let rec transf_members env id count = function
let carrier_typ = TInt(carrier_ikind, []) in
(* Enter each field with its bit position, size, signedness *)
List.iter
- (fun (name, pos, sz, signed, signed2) ->
+ (fun (name, pos, sz, signed, signed2, is_bool) ->
if name <> "" then begin
let pos' =
if !config.bitfields_msb_first
@@ -131,7 +138,8 @@ let rec transf_members env id count = function
(id, name)
{bf_carrier = carrier; bf_carrier_typ = carrier_typ;
bf_pos = pos'; bf_size = sz;
- bf_signed = signed; bf_signed_res = signed2}
+ bf_signed = signed; bf_signed_res = signed2;
+ bf_bool = is_bool}
end)
bitfields;
{ fld_name = carrier; fld_typ = carrier_typ; fld_bitfield = None}
@@ -208,13 +216,16 @@ unsigned int bitfield_insert(unsigned int x, int ofs, int sz, unsigned int y)
return (x & ~mask) | ((y << ofs) & mask);
}
+If the bitfield is of type _Bool, the new value (y above) must be converted
+to _Bool to normalize it to 0 or 1.
*)
let bitfield_assign env bf carrier newval =
let msk = insertion_mask bf in
let notmsk = {edesc = EUnop(Onot, msk); etyp = msk.etyp} in
let newval_casted =
- ecast (TInt(IUInt,[])) newval in
+ ecast (TInt(IUInt,[]))
+ (if bf.bf_bool then ecast (TInt(IBool,[])) newval else newval) in
let newval_shifted =
eshift env Oshl newval_casted (intconst (Int64.of_int bf.bf_pos) IUInt) in
let newval_masked = ebinint env Oand newval_shifted msk
@@ -230,17 +241,22 @@ unsigned int bitfield_init(int ofs, int sz, unsigned int y)
unsigned int mask = (1U << sz) - 1;
return (y & mask) << ofs;
}
+
+If the bitfield is of type _Bool, the new value (y above) must be converted
+to _Bool to normalize it to 0 or 1.
*)
let bitfield_initializer bf i =
match i with
| Init_single e ->
let m = Int64.pred (Int64.shift_left 1L bf.bf_size) in
+ let e_cast =
+ if bf.bf_bool then ecast (TInt(IBool,[])) e else e in
let e_mask =
{edesc = EConst(CInt(m, IUInt, sprintf "0x%LXU" m));
etyp = TInt(IUInt, [])} in
let e_and =
- {edesc = EBinop(Oand, e, e_mask, TInt(IUInt,[]));
+ {edesc = EBinop(Oand, e_cast, e_mask, TInt(IUInt,[]));
etyp = TInt(IUInt,[])} in
{edesc = EBinop(Oshl, e_and, intconst (Int64.of_int bf.bf_pos) IInt,
TInt(IUInt, []));
diff --git a/test/regression/Results/bitfields9 b/test/regression/Results/bitfields9
index ca74f1f4..a1d0e9fd 100644
--- a/test/regression/Results/bitfields9
+++ b/test/regression/Results/bitfields9
@@ -1,10 +1,10 @@
glob_s = { a = -12, b = 1 }
-glob_t = { c = 123, d = 0, e = -45 }
+glob_t = { c = 123, d = 1, e = -45 }
loc_s = { a = 11, b = 2 }
loc_t = { c = 11, d = 1, e = 2 }
compound_s = { a = 2, b = 3 }
-compound_t = { c = 2, d = 0, e = -11 }
+compound_t = { c = 2, d = 1, e = -11 }
loc_s = { a = 7, b = 2 }
loc_t = { c = 7, d = 1, e = 50 }
compound_s = { a = -14, b = 3 }
-compound_t = { c = 50, d = 0, e = -7 }
+compound_t = { c = 50, d = 1, e = -7 }
diff --git a/test/regression/bitfields1.c b/test/regression/bitfields1.c
index c6022dd1..5f6dfdd1 100644
--- a/test/regression/bitfields1.c
+++ b/test/regression/bitfields1.c
@@ -7,7 +7,7 @@ struct s {
struct t {
unsigned int c: 16;
- unsigned int d: 1;
+ _Bool d: 1;
short e: 8;
};
@@ -29,7 +29,7 @@ int main()
y.c = 12345;
y.d = 0;
y.e = 89;
- res = f(&x, &y, 1);
+ res = f(&x, &y, 2);
printf("x = {a = %d, b = %d }\n", x.a, x.b);
printf("y = {c = %d, d = %d, e = %d }\n", y.c, y.d, y.e);
diff --git a/test/regression/bitfields9.c b/test/regression/bitfields9.c
index b33c4064..be87057b 100644
--- a/test/regression/bitfields9.c
+++ b/test/regression/bitfields9.c
@@ -9,7 +9,7 @@ struct s {
struct t {
unsigned int c: 16;
- unsigned int d: 1;
+ _Bool d: 1;
short e: 8;
};
@@ -25,25 +25,25 @@ void print_t(char * msg, struct t p)
/* Global initialization */
struct s glob_s = { -12, 1 };
-struct t glob_t = { 123, 0, -45 };
+struct t glob_t = { 123, 2, -45 };
/* Local initialization */
-void f(int x, int y)
+void f(int x, int y, int z)
{
struct s loc_s = { x, y };
- struct t loc_t = { x, 1, y };
+ struct t loc_t = { x, z, y };
print_s("loc_s", loc_s);
print_t("loc_t", loc_t);
print_s("compound_s", (struct s) { y, x });
- print_t("compound_t", (struct t) { y, 0, -x });
+ print_t("compound_t", (struct t) { y, ~z, -x });
}
int main()
{
print_s("glob_s", glob_s);
print_t("glob_t", glob_t);
- f(11, 2);
- f(7, 50);
+ f(11, 2, 3);
+ f(7, 50, 2);
return 0;
}