Consider

  struct s { long a : 33; };
  long bar(struct s *x) { return (x->a << 16) >> 16; }
  extern void abort(void);
  int main()
  {
    struct s a = { 1u << 31 };

    if (bar(&a) != 0)
      abort ();
    return 0;
  }

where we currently (rightfully so, IMHO) abort.

There are several problems with how we reach to that conclusion.  First
of all, a long bitfield is a GCC extension.  This extension does not
document integer promotion rules for such bitfields, and we indeed do
_not_ perform promotion to long for the argument of the shifts, but
the gimplifier is handed:

  return (long int) ((x->a << 16) >> 16);

which leads to a GIMPLE intermediate language representation with
registers/temporaries of width 31:

  long int D.1546;
  <unnamed-signed:33> D.1547;
  <unnamed-signed:33> D.1548;
  <unnamed-signed:33> D.1549;

  D.1547 = x->a;
  D.1548 = D.1547 << 16;
  D.1549 = D.1548 >> 16;
  D.1546 = (long int) D.1549;
  return D.1546;

where this ILs only sane semantics do NOT match the runtime behavior
of the program (IMHO the only sane semantics is to truncate the
value after D.1548 = D.1547 << 16).

Now we go further and expand is handed basically the original IL again
if you run TER, or the above if not.  But as we do not have modes
for registers that have such irregular precision, simply DImode is
used for all the temporaries and no bitfield reduction operations
are emitted, making the runtime behavior as expected.

So, to conclude, the runtime behavior does neither match the C99
standard (which doesn't specify integer promotions for types that
do not fit in int, but also leaves bitfields of types with rank
bigger than int as implementation defined), nor the only sane
semantics of the tree-ssa IL.

As a solution I propose to

 - document how integral promotion is performed on the implementation
   defined bitfields we allow as a GNU extension.  (4.9, "Integer
   promotion rules are extended for non-standard bit-field types to
   promote to the smallest integer type that can represent all values
   of the bit-field type.")

 - actually perform these integral promotions

 - disallow GIMPLE registers whose precision does not match the
   precision of the underlying mode.  Note that this requires
   BIT_FIELD_REF to allow a resulting type that does not match the
   type of the first operand (but possibly only the same mode).
   [alternatively only disallow arithmetics on such registers]


This all will possibly help to solve PRs 33819 and 33887.

Any thoughts?

Would any of the C frontend maintainers please try to formulate
standards-proof documentation for 4.9?

Thanks,
Richard.

Reply via email to