Skip to content

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.

[1] !4717 (comment 355874)

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information