
On Tue, 2008-03-11 at 16:25 -0700, Simon Marlow wrote:
Duncan Coutts wrote:
from: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/mage-1.0
perhapsPbecause it's a pointer import it gets treated differently?
I just tried this and couldn't reproduce the problem.
Maybe there's something else going on.. can you boil down the example at all?
I can reproduce the problem with the mage-1.0 tarball with the following changes: add -fvia-C to the ghc-options add include-dirs: src Inspecting Main.hc we find things like: _s2oT = *((P_)(W_)&stdscr); that is references to the stdscr pointer. I was trying to get a boiled down example. I started with src/Main and commented stuff out. By commenting out the call to clear_screen the error went away. That's because it's clear_screen from src/Curses.hsc that references stdscrp. I swear it's non-deterministic, even when removing the .hi files before each run. Here's the smallest I can get it: module Curses (screen_size) where import Foreign data WINDOW = WINDOW type WINDOWptr = Ptr WINDOW foreign import ccall unsafe "curses.h & stdscr" stdscrp :: Ptr WINDOWptr screen_size :: IO () screen_size = do stdscr <- peek stdscrp return () module Main (main) where import Curses main = print =<< screen_size And (re-)building using: $ rm Main.hi Curses.hi; ghc-6.8.2 --make -O2 -fvia-C -fffi Main.hs -keep-hc-files [1 of 2] Compiling Curses ( Curses.hs, Curses.o ) [2 of 2] Compiling Main ( Main.hs, Main.o ) In file included from /usr/lib64/ghc-6.8.2/include/Stg.h:150, from Main.hc:3:0: Main.hc: In function ‘Main_a_entry’: Main.hc:46:0: error: ‘stdscr’ undeclared (first use in this function) Main.hc:46:0: error: (Each undeclared identifier is reported only once Main.hc:46:0: error: for each function it appears in.) Inspecting Main.hc we see _sFH = *((P_)(W_)&stdscr); inside the Main_a_entry. The Curses.hc does #include "curses.h" as required. It's Main.hc that does not, despite using &stdscr. Seems that -O2 is not necessary, -O also elicits the failure. ghc --show-iface Curses.hi shows us these interesting exports: screen_size :: GHC.IOBase.IO () {- Arity: 1 HasNoCafRefs Strictness: L Unfolding: (Curses.a `cast` (sym ((GHC.IOBase.:CoIO) ()))) -} a :: GHC.Prim.State# GHC.Prim.RealWorld -> (# GHC.Prim.State# GHC.Prim.RealWorld, () #) {- Arity: 1 HasNoCafRefs Strictness: L Unfolding: (\ s :: GHC.Prim.State# GHC.Prim.RealWorld -> case @ (# GHC.Prim.State# GHC.Prim.RealWorld, () #) GHC.Prim.readAddrOffAddr# @ GHC.Prim.RealWorld __label "stdscr" 0 s of wild2 { (# s2, x #) -> (# s2, GHC.Base.() #) }) -} (re-indented to fit) The __label "stdscr" in a's unfolding is particularly interesting. That looks like the route by which "stdscr" escapes the Curses module and ends up in Main, outside of the scope of the header file. Duncan