NCG generates invalid code for sized-types
While debugging !4717 (merged) I've found [1] that the native code generator doesn't correctly handle sized types (Int8#, etc.).
I've finally managed to make a reproducer:
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
module Main where
import GHC.Exts
import GHC.Types
import GHC.Num
data T = T Word8#
instance Num T where
fromInteger i = T (wordToWord8# (integerToWord# i))
instance Eq T where
(==) (T a) (T b) = isTrue# (a `eqWord8#` b)
(/=) (T a) (T b) = isTrue# (a `neWord8#` b)
main :: IO ()
main = do
let !addr = "\0\1\2\3\4\5\6\7\8"#
w8 <- IO (\s -> case readWord8OffAddr# (plusAddr# addr 5#) 0# s of
(# s', w8 #) -> (# s', T w8 #))
-- w8 must be small enough for one of the branch to be taken.
-- we need several alternatives for a jump table to be used
print $ case w8 of
0 -> 1000
1 -> 1001
2 -> 1002
3 -> 1003
4 -> 1004
5 -> 1005
6 -> 1006
_ -> 1010
❯ ~/projects/ghc/master/_build/stage1/bin/ghc Bug.hs -O2
❯ ./Bug
[1] 469926 segmentation fault (core dumped) ./Bug
The issue is that we have some Cmm switch on a I8 value:
_s25A::I8 = I8[R1 + 16];
if (_s25A::I8 < 7 :: W8) goto u27E; else goto c26z;
u27E: // global
switch [0 .. 6] _s25A::I8 {
case 0 : goto c26A;
case 1 : goto c26B;
case 2 : goto c26C;
case 3 : goto c26D;
case 4 : goto c26E;
case 5 : goto c26F;
case 6 : goto c26G;
}
That is compiled into the following x86 assembly:
_blk_c27D:
movb 16(%rbx),%al ; set AL
cmpb $7,%al
jae _blk_c26z
_blk_u27E:
jmp *_blk_n27M(,%rax,8) ; use RAX which higher part is garbage
This example only fails on HEAD, not on 9.2. 9.2 doesn't generate a jump table (probably because it lacks eb1a86bb) so this reproducer can't succeed in failing. But the bug may still be there.