I've compiled GHC from HEAD this morning, and it once again broke my OpenGL binding. After boiling down the example (see attached Foo.hs), it seems that either Storable itself, constant folding or the strictness analysis is buggy:
[EMAIL PROTECTED]:~> ./Foo *** main 1 *** main 2 Foo: Prelude.undefined I suspect that the "undefined" is the one in the default instance of peekElemOff, but that is just guessing. GHC even goes so far to optimize away the last putStrLn (see Foo.simpl). :-( Cheers, S.
import Foreign -- Strangely enough, this works if newtype is used... data Elem a = Elem a instance Storable a => Storable (Elem a) where sizeOf ~(Elem r) = 3 * sizeOf r alignment ~(Elem r) = alignment r peek ptr = do r <- peekElemOff (castPtr ptr) 0; return (Elem r) poke ptr (Elem r) = poke (castPtr ptr) r main :: IO () main = do putStrLn "*** main 1" allocaBytes 100 $ \buf -> do poke buf (Elem 12345) putStrLn "*** main 2" Elem x <- peekElemOff buf 0 print (x :: Int) putStrLn "*** main 3"
==================== Tidy Core ==================== Main.lvl :: [GHC.Base.Char] [GlobalId] [] Main.lvl = GHC.Base.unpackCString# "*** main 2" Main.lvl1 :: [GHC.Base.Char] [GlobalId] [] Main.lvl1 = GHC.Base.unpackCString# "*** main 1" Main.a :: GHC.Prim.State# GHC.Prim.RealWorld -> (# GHC.Prim.State# GHC.Prim.RealWorld, () #) [GlobalId] [Arity 1 Str: DmdType L] Main.a = \ (eta_aJN :: GHC.Prim.State# GHC.Prim.RealWorld) -> case ((GHC.IO.hPutStr GHC.Handle.stdout Main.lvl1) `cast` ((GHC.IOBase.:CoIO) () :: GHC.IOBase.IO () :=: GHC.Prim.State# GHC.Prim.RealWorld -> (# GHC.Prim.State# GHC.Prim.RealWorld, () #))) eta_aJN of wild_aFw { (# new_s_aFy, a98_aFz #) -> case GHC.IO.$whPutChar GHC.Handle.stdout '\n' new_s_aFy of wild1_aID { (# new_s1_aIF, a981_aIG #) -> case GHC.Prim.newPinnedByteArray# @ GHC.Prim.RealWorld 100 new_s1_aIF of wild2_aSC { (# s_aSE, mbarr#_aSF #) -> case GHC.Prim.unsafeFreezeByteArray# @ GHC.Prim.RealWorld mbarr#_aSF s_aSE of wild11_aSH { (# s1_aSJ, barr#_aSK #) -> case GHC.Prim.writeIntOffAddr# @ GHC.Prim.RealWorld (GHC.Prim.byteArrayContents# barr#_aSK) 0 12345 s1_aSJ of s2_aJd { __DEFAULT -> case ((GHC.IO.hPutStr GHC.Handle.stdout Main.lvl) `cast` ((GHC.IOBase.:CoIO) () :: GHC.IOBase.IO () :=: GHC.Prim.State# GHC.Prim.RealWorld -> (# GHC.Prim.State# GHC.Prim.RealWorld, () #))) s2_aJd of wild3_XGu { (# new_s2_XGx, a982_XGz #) -> case GHC.IO.$whPutChar GHC.Handle.stdout '\n' new_s2_XGx of wild4_XKC { (# new_s3_XKF, a983_XKH #) -> GHC.Err.undefined `cast` (CoUnsafe (forall a_az9. a_az9) (# GHC.Prim.State# GHC.Prim.RealWorld, () #) :: forall a_az9. a_az9 :=: (# GHC.Prim.State# GHC.Prim.RealWorld, () #)) } } } } } } } Main.poke :: GHC.Ptr.Ptr (Main.Elem GHC.Base.Int) -> Main.Elem GHC.Base.Int -> GHC.IOBase.IO () [GlobalId] [Arity 3 NoCafRefs Str: DmdType U(L)U(U(L))L] Main.poke = \ (ptr_abO :: GHC.Ptr.Ptr (Main.Elem GHC.Base.Int)) (ds_dxP :: Main.Elem GHC.Base.Int) -> (\ (eta_sJg :: GHC.Prim.State# GHC.Prim.RealWorld) -> case ds_dxP of wild_B1 { Main.Elem r_abP -> case ptr_abO of wild1_ay0 { GHC.Ptr.Ptr addr_ay2 -> case r_abP of wild2_aJ9 { GHC.Base.I# x_aJb -> case GHC.Prim.writeIntOffAddr# @ GHC.Prim.RealWorld addr_ay2 0 x_aJb eta_sJg of s2_aJd { __DEFAULT -> (# s2_aJd, GHC.Base.() #) } } } }) `cast` (sym ((GHC.IOBase.:CoIO) ()) :: GHC.Prim.State# GHC.Prim.RealWorld -> (# GHC.Prim.State# GHC.Prim.RealWorld, () #) :=: GHC.IOBase.IO ()) Main.peek :: GHC.Ptr.Ptr (Main.Elem GHC.Base.Int) -> GHC.IOBase.IO (Main.Elem GHC.Base.Int) [GlobalId] [Arity 2 NoCafRefs Str: DmdType U(L)L] Main.peek = \ (ptr_abK :: GHC.Ptr.Ptr (Main.Elem GHC.Base.Int)) -> (\ (s_aIC :: GHC.Prim.State# GHC.Prim.RealWorld) -> case ptr_abK of wild_ay0 { GHC.Ptr.Ptr addr_ay2 -> case GHC.Prim.readIntOffAddr# @ GHC.Prim.RealWorld addr_ay2 0 s_aIC of wild2_aIT { (# s2_aIV, x_aIW #) -> (# s2_aIV, (Main.Elem @ GHC.Base.Int (GHC.Base.I# x_aIW)) #) } }) `cast` (sym ((GHC.IOBase.:CoIO) (Main.Elem GHC.Base.Int)) :: GHC.Prim.State# GHC.Prim.RealWorld -> (# GHC.Prim.State# GHC.Prim.RealWorld, Main.Elem GHC.Base.Int #) :=: GHC.IOBase.IO (Main.Elem GHC.Base.Int)) Main.alignment :: Main.Elem GHC.Base.Int -> GHC.Base.Int [GlobalId] [Arity 1 NoCafRefs Str: DmdType U(A)m] Main.alignment = \ (ds_dxK :: Main.Elem GHC.Base.Int) -> case ds_dxK of wild_B1 { Main.Elem r_abI -> Foreign.Storable.lvl } Main.lvl2 :: GHC.Base.Int [GlobalId] [NoCafRefs] Main.lvl2 = GHC.Base.I# 24 Main.sizeOf :: Main.Elem GHC.Base.Int -> GHC.Base.Int [GlobalId] [Arity 1 NoCafRefs Str: DmdType U(A)m] Main.sizeOf = \ (ds_dxC :: Main.Elem GHC.Base.Int) -> case ds_dxC of wild_B1 { Main.Elem r_aa8 -> Main.lvl2 } Main.peekByteOff :: forall b_avX. GHC.Ptr.Ptr b_avX -> GHC.Base.Int -> GHC.IOBase.IO (Main.Elem GHC.Base.Int) [GlobalId] [Arity 3 NoCafRefs Str: DmdType U(L)U(L)L] Main.peekByteOff = \ (@ b_awy) (ptr_azz :: GHC.Ptr.Ptr b_awy) (off_azA :: GHC.Base.Int) -> (\ (s_aIC :: GHC.Prim.State# GHC.Prim.RealWorld) -> case ptr_azz of wild_aJl { GHC.Ptr.Ptr addr_aJn -> case off_azA of wild1_aJp { GHC.Base.I# d_aJr -> case GHC.Prim.readIntOffAddr# @ GHC.Prim.RealWorld (GHC.Prim.plusAddr# addr_aJn d_aJr) 0 s_aIC of wild2_aIT { (# s2_aIV, x_aIW #) -> (# s2_aIV, (Main.Elem @ GHC.Base.Int (GHC.Base.I# x_aIW)) #) } } }) `cast` (sym ((GHC.IOBase.:CoIO) (Main.Elem GHC.Base.Int)) :: GHC.Prim.State# GHC.Prim.RealWorld -> (# GHC.Prim.State# GHC.Prim.RealWorld, Main.Elem GHC.Base.Int #) :=: GHC.IOBase.IO (Main.Elem GHC.Base.Int)) Main.pokeByteOff :: forall b_avZ. GHC.Ptr.Ptr b_avZ -> GHC.Base.Int -> Main.Elem GHC.Base.Int -> GHC.IOBase.IO () [GlobalId] [Arity 2 NoCafRefs Str: DmdType LL] Main.pokeByteOff = \ (@ b_awE) (ptr_azh :: GHC.Ptr.Ptr b_awE) (off_azi :: GHC.Base.Int) -> let { ptr1_sW1 [Just D(L)] :: GHC.Ptr.Ptr (Main.Elem GHC.Base.Int) [Str: DmdType] ptr1_sW1 = GHC.Ptr.plusPtr @ b_awE @ (Main.Elem GHC.Base.Int) ptr_azh off_azi } in \ (ds_dxP :: Main.Elem GHC.Base.Int) -> (\ (eta_sJg :: GHC.Prim.State# GHC.Prim.RealWorld) -> case ds_dxP of wild_B1 { Main.Elem r_abP -> case ptr1_sW1 of wild1_ay0 { GHC.Ptr.Ptr addr_ay2 -> case r_abP of wild2_aJ9 { GHC.Base.I# x_aJb -> case GHC.Prim.writeIntOffAddr# @ GHC.Prim.RealWorld addr_ay2 0 x_aJb eta_sJg of s2_aJd { __DEFAULT -> (# s2_aJd, GHC.Base.() #) } } } }) `cast` (sym ((GHC.IOBase.:CoIO) ()) :: GHC.Prim.State# GHC.Prim.RealWorld -> (# GHC.Prim.State# GHC.Prim.RealWorld, () #) :=: GHC.IOBase.IO ()) Main.$dmpeekElemOff :: GHC.Ptr.Ptr (Main.Elem GHC.Base.Int) -> GHC.Base.Int -> GHC.IOBase.IO (Main.Elem GHC.Base.Int) [GlobalId] [Arity 3 Str: DmdType U(A)U(A)Ab] Main.$dmpeekElemOff = \ (ptr_ayD :: GHC.Ptr.Ptr (Main.Elem GHC.Base.Int)) (off_ayE :: GHC.Base.Int) -> (\ (eta_sJB :: GHC.Prim.State# GHC.Prim.RealWorld) -> case ptr_ayD of wild_aJl { GHC.Ptr.Ptr addr_aJn -> case off_ayE of wild1_ayQ { GHC.Base.I# x_ayS -> GHC.Err.undefined `cast` (CoUnsafe (forall a_az9. a_az9) (# GHC.Prim.State# GHC.Prim.RealWorld, Main.Elem GHC.Base.Int #) :: forall a_az9. a_az9 :=: (# GHC.Prim.State# GHC.Prim.RealWorld, Main.Elem GHC.Base.Int #)) } }) `cast` (sym ((GHC.IOBase.:CoIO) (Main.Elem GHC.Base.Int)) :: GHC.Prim.State# GHC.Prim.RealWorld -> (# GHC.Prim.State# GHC.Prim.RealWorld, Main.Elem GHC.Base.Int #) :=: GHC.IOBase.IO (Main.Elem GHC.Base.Int)) Main.$dmpokeElemOff :: GHC.Ptr.Ptr (Main.Elem GHC.Base.Int) -> GHC.Base.Int -> Main.Elem GHC.Base.Int -> GHC.IOBase.IO () [GlobalId] [Arity 4 NoCafRefs Str: DmdType U(L)U(L)U(U(L))L] Main.$dmpokeElemOff = \ (ptr_ayf :: GHC.Ptr.Ptr (Main.Elem GHC.Base.Int)) (off_ayg :: GHC.Base.Int) (val_ayh :: Main.Elem GHC.Base.Int) -> (\ (eta_sTo :: GHC.Prim.State# GHC.Prim.RealWorld) -> case val_ayh of wild_B1 { Main.Elem r_abP -> case ptr_ayf of wild1_aJl { GHC.Ptr.Ptr addr_aJn -> case off_ayg of wild2_ayt { GHC.Base.I# x_ayv -> case r_abP of wild21_aJ9 { GHC.Base.I# x1_aJb -> case GHC.Prim.writeIntOffAddr# @ GHC.Prim.RealWorld (GHC.Prim.plusAddr# addr_aJn (GHC.Prim.*# x_ayv 24)) 0 x1_aJb eta_sTo of s2_aJd { __DEFAULT -> (# s2_aJd, GHC.Base.() #) } } } } }) `cast` (sym ((GHC.IOBase.:CoIO) ()) :: GHC.Prim.State# GHC.Prim.RealWorld -> (# GHC.Prim.State# GHC.Prim.RealWorld, () #) :=: GHC.IOBase.IO ()) Main.$dStorable :: Foreign.Storable.Storable (Main.Elem GHC.Base.Int) [GlobalId] [Str: DmdType m] Main.$dStorable = Foreign.Storable.:DStorable @ (Main.Elem GHC.Base.Int) Main.sizeOf Main.alignment Main.$dmpeekElemOff Main.$dmpokeElemOff Main.peekByteOff Main.pokeByteOff Main.peek Main.poke Main.main :: GHC.IOBase.IO () [GlobalId] [Arity 1 Str: DmdType L] Main.main = Main.a `cast` (sym ((GHC.IOBase.:CoIO) ()) :: GHC.Prim.State# GHC.Prim.RealWorld -> (# GHC.Prim.State# GHC.Prim.RealWorld, () #) :=: GHC.IOBase.IO ()) Main.$f1 :: forall a_aa6. (Foreign.Storable.Storable a_aa6) => Foreign.Storable.Storable (Main.Elem a_aa6) [GlobalId] [Arity 1 Str: DmdType Lm] Main.$f1 = __inline_me (\ (@ a_aa6) ($dStorable1_avR :: Foreign.Storable.Storable a_aa6) -> let { sizeOf1_sHj :: Main.Elem a_aa6 -> GHC.Base.Int [Arity 1 Str: DmdType U(L)] sizeOf1_sHj = \ (ds_dxC :: Main.Elem a_aa6) -> case ds_dxC of wild_B1 { Main.Elem r_aa8 -> GHC.Num.* @ GHC.Base.Int GHC.Num.$f6 (GHC.Base.I# 3) (Foreign.Storable.sizeOf @ a_aa6 $dStorable1_avR r_aa8) } } in let { alignment1_sHk :: Main.Elem a_aa6 -> GHC.Base.Int [Arity 1 Str: DmdType U(L) {avR->U(ASAAAAAA)}] alignment1_sHk = \ (ds_dxK :: Main.Elem a_aa6) -> case ds_dxK of wild_B1 { Main.Elem r_abI -> Foreign.Storable.alignment @ a_aa6 $dStorable1_avR r_abI } } in let { peek1_sHl :: GHC.Ptr.Ptr (Main.Elem a_aa6) -> GHC.IOBase.IO (Main.Elem a_aa6) [Arity 1 Str: DmdType L] peek1_sHl = \ (ptr_abK :: GHC.Ptr.Ptr (Main.Elem a_aa6)) -> GHC.Base.>>= @ GHC.IOBase.IO GHC.IOBase.$f16 @ a_aa6 @ (Main.Elem a_aa6) (Foreign.Storable.peekElemOff @ a_aa6 $dStorable1_avR (GHC.Ptr.castPtr @ (Main.Elem a_aa6) @ a_aa6 ptr_abK) (GHC.Base.I# 0)) (\ (r_abM :: a_aa6) -> GHC.Base.return @ GHC.IOBase.IO GHC.IOBase.$f16 @ (Main.Elem a_aa6) (Main.Elem @ a_aa6 r_abM)) } in let { poke1_sHm :: GHC.Ptr.Ptr (Main.Elem a_aa6) -> Main.Elem a_aa6 -> GHC.IOBase.IO () [Arity 2 Str: DmdType LU(L) {avR->U(AAAAAAAS)}] poke1_sHm = \ (ptr_abO :: GHC.Ptr.Ptr (Main.Elem a_aa6)) (ds_dxP :: Main.Elem a_aa6) -> case ds_dxP of wild_B1 { Main.Elem r_abP -> Foreign.Storable.poke @ a_aa6 $dStorable1_avR (GHC.Ptr.castPtr @ (Main.Elem a_aa6) @ a_aa6 ptr_abO) r_abP } } in __letrec { $dStorable2_sHe :: Foreign.Storable.Storable (Main.Elem a_aa6) [Str: DmdType m] $dStorable2_sHe = Foreign.Storable.:DStorable @ (Main.Elem a_aa6) sizeOf1_sHj alignment1_sHk $dmpeekElemOff1_sHg $dmpokeElemOff1_sHf peekByteOff1_sHi pokeByteOff1_sHh peek1_sHl poke1_sHm; peekByteOff1_sHi :: forall b_avX. GHC.Ptr.Ptr b_avX -> GHC.Base.Int -> GHC.IOBase.IO (Main.Elem a_aa6) [Arity 2 Str: DmdType LL {sHe->U(AAAAAAC(S)A)}] peekByteOff1_sHi = \ (@ b_awy) -> Foreign.Storable.$dmpeekByteOff @ (Main.Elem a_aa6) $dStorable2_sHe @ b_awy; pokeByteOff1_sHh :: forall b_avZ. GHC.Ptr.Ptr b_avZ -> GHC.Base.Int -> Main.Elem a_aa6 -> GHC.IOBase.IO () [Arity 2 Str: DmdType LL {sHe->U(AAAAAAAC(S))}] pokeByteOff1_sHh = \ (@ b_awE) -> Foreign.Storable.$dmpokeByteOff @ (Main.Elem a_aa6) $dStorable2_sHe @ b_awE; $dmpeekElemOff1_sHg :: GHC.Ptr.Ptr (Main.Elem a_aa6) -> GHC.Base.Int -> GHC.IOBase.IO (Main.Elem a_aa6) [Arity 2 Str: DmdType LL {sHe->U(LAAAC(C(S))AAA)}] $dmpeekElemOff1_sHg = Foreign.Storable.$dmpeekElemOff @ (Main.Elem a_aa6) $dStorable2_sHe; $dmpokeElemOff1_sHf :: GHC.Ptr.Ptr (Main.Elem a_aa6) -> GHC.Base.Int -> Main.Elem a_aa6 -> GHC.IOBase.IO () [Arity 3 Str: DmdType LLL {sHe->U(LAAAAC(C(C(S)))AA)}] $dmpokeElemOff1_sHf = Foreign.Storable.$dmpokeElemOff @ (Main.Elem a_aa6) $dStorable2_sHe; } in $dStorable2_sHe) :Main.main :: GHC.IOBase.IO () [GlobalId] [Arity 1 Str: DmdType L] :Main.main = GHC.TopHandler.runMainIO @ () (Main.a `cast` (sym ((GHC.IOBase.:CoIO) ()) :: GHC.Prim.State# GHC.Prim.RealWorld -> (# GHC.Prim.State# GHC.Prim.RealWorld, () #) :=: GHC.IOBase.IO ())) ==================== Tidy Core Rules ==================== "SPEC Main.$f1" __forall {$dStorable1_XIk :: Foreign.Storable.Storable GHC.Base.Int} Main.$f1 @ GHC.Base.Int $dStorable1_XIk = Main.$dStorable