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