# 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:

- 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.
- 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.