Skip to content

Bad code generation for oversaturated keepAlive#

Consider the following example program.

{-# LANGUAGE MagicHash #-}

import GHC.Exts
import GHC.IO
import System.IO

main :: IO ()
main = do
  IO $ \s -> keepAlive# () s (\s' f -> unIO f s') (putStrLn "test")
  hFlush stdout

Semantically, evaluating keepAlive# v s act is supposed to be the same as evaluating act s except that v is kept alive. So this program should print "test" when run to completion. But it doesn't, unless interpreted: During CoreToStg, we generate a single StgOpApp with too many arguments and don't generate correct code from the resulting STG.

I believe this problem is what this comment in GHC.Builtin.PrimOps refers to:

-- Some PrimOps need not return a manifest primitive or algebraic value
-- (i.e. they might return a polymorphic value).  These PrimOps *must*
-- be out of line, or the code generator won't work.

(Today, keepAlive# is the only primop with a polymorphic-enough result to be used over-saturated without a type error that doesn't always throw an exception. I discovered this problem while experimenting with fromStrict# :: Strict# a -> a.)

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