diff --git a/src/cil.ml b/src/cil.ml index d1d3edc78..3c9ba7df1 100755 --- a/src/cil.ml +++ b/src/cil.ml @@ -2956,7 +2956,7 @@ let initGccBuiltins () : unit = try assert (sizeInBits mod 8 = 0); let sizeInBytes = sizeInBits / 8 in - let sizedIntType = TInt (intKindForSize sizeInBytes false, []) in + let sizedIntType = TInt (intKindForSize sizeInBytes true, []) in let name = Printf.sprintf "__builtin_bswap%d" sizeInBits in H.add h name (sizedIntType, [ sizedIntType ], false) with Not_found -> diff --git a/src/frontc/cabs2cil.ml b/src/frontc/cabs2cil.ml index fd6e239ce..02c58fe57 100644 --- a/src/frontc/cabs2cil.ml +++ b/src/frontc/cabs2cil.ml @@ -4752,6 +4752,24 @@ and doExp (asconst: bool) (* This expression is used as a constant *) prestype := intType | _ -> ignore (warn "Invalid call to builtin_types_compatible_p"); end + else if fv.vname = "__builtin_bswap16" && asconst && isEmpty (!prechunk ()) then (* to support pure switch cases in Linux kernel *) + begin + match !pargs with + | [ arg ] -> begin + piscall := false; + prestype := TInt (IUShort, []); (* TODO: lookup via machdep? *) + let arg = CastE (IntegerPromotion, intType, arg) in (* bitwise operators will promote uint16 to int *) (* TODO: consider machdep? *) + pres := + CastE (Internal, !prestype, (* force promoted int back to uint16 *) + BinOp (BOr, + BinOp (Shiftlt, arg, integer 8, intType), + BinOp (Shiftrt, arg, integer 8, intType), + intType) + ); + end + | _ -> + ignore (warn "Invalid call to builtin_bswap16"); + end end | _ -> () ); diff --git a/test/small1/builtin_bswap_const.c b/test/small1/builtin_bswap_const.c new file mode 100755 index 000000000..06d122743 --- /dev/null +++ b/test/small1/builtin_bswap_const.c @@ -0,0 +1,13 @@ +#include "testharness.h" + +int main (void) +{ + switch (1) { + case (__builtin_bswap16(256)): + break; + default: + E(1); + } + + SUCCESS; +} diff --git a/test/testcil.pl b/test/testcil.pl index 07ac32d9d..c813dde04 100644 --- a/test/testcil.pl +++ b/test/testcil.pl @@ -555,6 +555,7 @@ sub addToGroup { addTest("testrun/builtin4 "); addTest("test/builtin5 "); addTest("test/builtin6 "); +addTest("testrun/builtin_bswap_const "); addTest("test/sync-1 _GNUCC=1"); addTest("test/sync-2 _GNUCC=1"); addTest("test/sync-3 _GNUCC=1");