[Mesa-dev] [PATCH v3] glsl: fix some strict aliasing issues in exec_list

Neil Roberts neil at linux.intel.com
Thu Jul 2 06:58:04 PDT 2015


Davin McCall <davmac at davmac.org> writes:

> I actually had thought about this, but technically, you can only use
> unions for type aliasing if you perform all accesses (that are not to
> the 'active' member) through the union. All the list processing code
> that iterates through all the nodes including the tail sentinel would
> *technically* still have an aliasing problem, because it doesn't go
> through the exec_list structure at all (though in practice, I don't
> think it would ever manifest in as an issue in the compiled code).

I don't think it matters that the list iterating code doesn't use
exec_list. If something modifies the list pointers through an exec_node
then the compiler will know that that potentially aliases the pointers
in an exec_list because the pointers in exec_list are also wrapped in an
exec_node. With your patch there is no type aliasing at all and the
union modification doesn't alter that.

> Why must all accesses go through the union? Consider the case:
>
>      int someMethod(float *f, int *i) {
>          *f = 4.0;    // LINE A
>          int a = *i;   // LINE B
>          return a;
>      }
>
> If I had some union 'u' with { float ff; int ii; } then I could call
> the above method, even if it was in a different module, with:
>
>      someMethod(&u.ff, &u.ii).
>
> Now, that would mean that the compiler would not be allowed to
> re-order LINE A and LINE B. But as I said, someMethod might be in a
> different module, where the compiler does not know that 'i' and 'f'
> point to members of the same union. In that case it assumes that 'i'
> and 'f' don't alias. Compare that to:
>
>      int someMethod(union u *a, union u *b)
>      {
>          u->ff = 4.0;
>          int a = u->ii;
>          return a;
>      }
>
> In this version, accesses are through the union, and the compiler
> knows that they potentially alias.

I don't think this example is relevant in this case because all of the
relevant members of the union I suggested are the same type (struct
exec_node). There is no type aliasing.

Maybe a hypothetical problem with this sort of use could be if you had a
function like this:

struct exec_node *
some_method(struct exec_node *a,
            struct exec_node *b)
{
   a->prev = &something;
   b->next = &something_else;
   return a->prev;
}

If you called this with the head and tail sentinels then the compiler
won't know that a->prev and b->next alias each other so it might return
&something instead of &something_else. However in practice for this use
case the only part that is aliased is a NULL pointer that is never
written to so I don't think it would actually matter.

Regards,
- Neil


More information about the mesa-dev mailing list