# nir: Fix undefined behaviour of shifts of negative values

A number of nir instructions in `src/compiler/nir/nir_opcodes.py` might use shift operators with a negative `lhs` value. This behavior, however, is undefined for left shifts, and implementation-defined for right shifts.

Section Section 6.5.7 "Bitwise shift operators" of the C99 n1124 spec states:

1. The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 * 2^E2 , reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 * 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
2. The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2^E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.

Which is different from what is described in Section 5.9 "Expressions" of the GLSL 4.40 (rev 9) spec:

The value of E1 << E2 is E1 (interpreted as a bit pattern) left-shifted by E2 bits.

The value of E1 >> E2 is E1 right-shifted by E2 bit positions. If E1 is a signed integer, the right-shift will extend the sign bit. If E1 is an unsigned integer, the right-shift will zero-extend.

For the left shift, the required behavior can be easily simulated by casting the `E1` value to unsigned before performing the shift, and then casting the result back to signed.

The right shift, that preserves the `MSB` bit, can be implemented as such:

``````((s ^ lhs) >> rhs) ^ s
where s is
0 if lhs >= 0 (all bits of s are 0)
-1 if lhs <  0 (all bits of s are 1)``````

`s` and `lhs` will always have the same `MSB`, so `s ^ lhs` will always have a `0` in `MSB`. This way, the implementation-defined behavior of the right shift shall be avoided. After performing the right shift, the original `MSB` of `lhs` can be retrieved by another `^`-comparation against `s`.

Also adding unit tests for all users of left and right shifts in `nir_opcodes.py`. With mesa built with `-Db_sanitize=undefined` (which is the case for Gitlab CI), the tests are expected to result in runtime errors without subsequent commits.