Hi,

In GCC 4.7.2 in function.c, inside assign_parm_find_data_types there
is distinction between passed and nominal mode.

nominal_type = TREE_TYPE (parm);
passed_type = DECL_ARG_TYPE (parm);

Next data->passed_pointer is set to true if passed_type should pass by
reference.

Consider synthetic code:

double g ();
typedef union {
  struct {
    unsigned s:1, e:8, f:23;
  } u;
  float f;
} s;

f(x, n)
  float x;
{
  ((s *)&x)->u.e -= n;
  x = g((double)x, -n);
}

In this case, for argument x, nominal_type is <real_type float> and
passed_type is <real_type double>.

Now suppose some private backend, where single floats are passed in
registers and doubles in memory.

In this case data->passed_pointer will be set to true. But really it
is passed in memory. So next inside assign_parms, DECL_RTL field will
be set to register, and later inside expand_expr_addr_expr_1, this
will assert on gcc_assert (MEM_P (result));

Just rewriting f as:

f(float x, int n)
{
  ((s *)&x)->u.e -= n;
  x = g((double)x, -n);
}

corrects things -- now both nominal_type and passed_type are float.
But I really want to be able to compile old-style definitions also.

So question is -- why assign_parm_find_data_types prefers passed_type
to nominal_type in checking if things are passing by reference, and
what is preferable way to fix this case? Maybe there already exists
some bug? I can not reproduce this case on any existing backend, it
seems x86 and arm passes SF and DF uniformly, so I am writing here,
not in bugzilla.

---
With best regards, Konstantin

Reply via email to