Re: Building on Windows: the saga continues

Ian Lynagh <[email protected]>
Newsgroups gmane.comp.lang.haskell.cvs.ghc
Message-ID <[email protected]>
On Mon, Dec 17, 2012 at 02:01:28PM +0000, Simon Peyton-Jones wrote:
> | On Mon, Dec 17, 2012 at 09:21:44AM +0000, Simon Peyton-Jones wrote:
> | >
> | > o   There's a seg-fault
> | 
> | I can reproduce this. I'll look into it.
> 
> Great, thank you.
> 
> It turns out that simply
> 
> 	ghc-stage2 -debug
> or
> 	ghc-stage2 -prof
> 
> is enough to trigger the seg-fault.  Any "way" flag seems to do it. 

Unfortunately, I've run out of time to debug this for now. Here's what
I've got:

It seems that the commits

    0c4a9f38637dfc3bc8fd48e8ba6bf64da51b727b
    ecd967612877e1965ddebefe9b83acd837bb413a

introduced the problem, but I'm not sure whether they are the direct
cause or just happened to tickle a pre-existing bug. Attached is a
self-contained module that goes wrong:

$ inplace/bin/ghc-stage1 -debug --make test -O -fforce-recomp
$ ./test +RTS -DS; echo $?
cap 0: initialised
A
Segmentation fault/access violation in generated code
1

Works with 7.4.1:
$ ghc -debug --make test -O -fforce-recomp
$ ./test; echo $?
A
[WayDyn]
B
0

It's quite fragile, e.g. if I remove
    ghcMode               :: (),
from the DynFlags type then it succeeds.


Thanks
Ian

_______________________________________________
Cvs-ghc mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/cvs-ghc
test.hs (text/x-haskell, 9.2 KB)
module Main (main) where

import Data.IntSet (IntSet)
import qualified Data.IntSet as IntSet
import Data.List
import System.IO

main :: IO ()
main = do
    hSetBuffering stdout NoBuffering
    hSetBuffering stderr NoBuffering
    let dflags0 = DynFlags {
                      ways = [],
                      settings = Settings {
                          sTargetPlatform = Platform {
                              platformOS = OSMinGW32
                          }
                      }
                  }
        ((), dflags1) = runCmdLine processArgs dflags0
    putStrLn "A"
    print $ ways dflags1
    putStrLn "B"

data GeneralFlag
   = Opt_PIC
   | Opt_SccProfilingOn
   | Opt_Static

   deriving (Eq, Show, Enum)

data Language = Haskell98 | Haskell2010
   deriving Enum

data ExtensionFlag
   = Opt_ParallelArrays
   deriving Enum

data DynFlags = DynFlags {
  settings              :: Settings,
  extensions            :: [OnOff ExtensionFlag],
  extensionFlags        :: IntSet,
  ways                  :: [Way],
  buildTag              :: String,
  rtsBuildTag           :: String,
  packageFlags          :: [PackageFlag],
  generalFlags          :: IntSet,
  language              :: Maybe Language,
  ghcMode               :: (),
  ghcLink               :: (),
  hscTarget             :: (),
  hscOutName            :: (),
  extCoreName           :: (),
  verbosity             :: (),
  optLevel              :: (),
  simplPhases           :: (),
  maxSimplIterations    :: (),
  shouldDumpSimplPhase  :: (),
  ruleCheck             :: (),
  strictnessBefore      :: (),
  simplTickFactor       :: (),
  specConstrThreshold   :: (),
  specConstrCount       :: (),
  liberateCaseThreshold :: (),
  floatLamArgs          :: (),
  historySize           :: (),
  cmdlineHcIncludes     :: (),
  importPaths           :: (),
  mainFunIs             :: (),
  ctxtStkDepth          :: (),
  splitInfo             :: (),
  objectDir             :: (),
  dylibInstallName      :: (),
  hiDir                 :: (),
  stubDir               :: (),
  dumpDir               :: (),
  objectSuf             :: (),
  hcSuf                 :: (),
  hiSuf                 :: (),
  canGenerateDynamicToo :: (),
  dynObjectSuf          :: (),
  dynHiSuf              :: (),
  outputFile            :: (),
  outputHi              :: (),
  dynLibLoader          :: (),
  dumpPrefixForce       :: (),
  includePaths          :: (),
  libraryPaths          :: (),
  frameworkPaths        :: (),
  cmdlineFrameworks     :: (),
  rtsOpts               :: (),
  rtsOptsEnabled        :: (),
  hpcDir                :: (),
  depMakefile           :: (),
  depIncludePkgDeps     :: (),
  depSuffixes           :: (),
  extraPkgConfs         :: (),
  filesToClean          :: (),
  dirsToClean           :: (),
  filesToNotIntermelean :: (),
  generatedDumps        :: (),
  dumpFlags             :: (),
  warningFlags          :: (),
  safeHaskell           :: (),
  thOnLoc               :: (),
  newDerivOnLoc         :: (),
  pkgTrustOnLoc         :: (),
  warnSafeOnLoc         :: (),
  warnUnsafeOnLoc       :: (),
  ufCreationThreshold   :: (),
  ufUseThreshold        :: (),
  ufFunAppDiscount      :: (),
  ufDictDiscount        :: (),
  ufKeenessFactor       :: (),
  ufDearOp              :: (),
  maxWorkerArgs         :: (),
  ghciHistSize          :: (),
  haddockOptions        :: (),
  ghciScripts           :: (),
  pprUserLength         :: (),
  pprCols               :: (),
  traceLevel            :: (),
  profAuto              :: (),
  interactivePrint      :: (),
  llvmVersion           :: (),
  nextWrapperNum        :: ()
 }

data Settings = Settings {
  sTargetPlatform        :: Platform
 }

targetPlatform :: DynFlags -> Platform
targetPlatform dflags = sTargetPlatform (settings dflags)

data PackageFlag
  = ExposePackage   String

data Way
  = WayThreaded
  | WayDebug
  | WayProf
  | WayEventLog
  | WayPar
  | WayGran
  | WayNDP
  | WayDyn
  deriving (Show, Eq, Ord)

wayGeneralFlags :: Platform -> Way -> [GeneralFlag]
wayGeneralFlags _ WayThreaded = []
wayGeneralFlags _ WayDebug = []
wayGeneralFlags platform WayDyn =
        case platformOS platform of
            OSMinGW32 -> [Opt_PIC]
            OSDarwin  -> [Opt_PIC]
            OSLinux   -> [Opt_PIC]
            _         -> []
wayGeneralFlags _ WayProf     = [Opt_SccProfilingOn]
wayGeneralFlags _ WayEventLog = []
wayGeneralFlags _ WayPar      = []
wayGeneralFlags _ WayGran     = []
wayGeneralFlags _ WayNDP      = []

wayExtras :: Platform -> Way -> DynFlags -> DynFlags
wayExtras _ WayThreaded dflags = dflags
wayExtras _ WayDebug    dflags = dflags
wayExtras _ WayDyn      dflags = dflags
wayExtras _ WayProf     dflags = dflags
wayExtras _ WayEventLog dflags = dflags
wayExtras _ WayPar      dflags = exposePackage' "concurrent" dflags
wayExtras _ WayGran     dflags = exposePackage' "concurrent" dflags
wayExtras _ WayNDP      dflags = setExtensionFlag' Opt_ParallelArrays dflags

data OnOff a = On a

flattenExtensionFlags :: Maybe Language -> [OnOff ExtensionFlag] -> IntSet
flattenExtensionFlags ml = foldr f defaultExtensionFlags
    where f (On flag)  flags = IntSet.insert (fromEnum flag) flags
          defaultExtensionFlags = IntSet.fromList (map fromEnum (languageExtensions ml))

languageExtensions :: Maybe Language -> [ExtensionFlag]
languageExtensions Nothing = []
languageExtensions (Just Haskell98) = []
languageExtensions (Just Haskell2010) = []

gopt_set :: DynFlags -> GeneralFlag -> DynFlags
gopt_set dfs f = dfs{ generalFlags = IntSet.insert (fromEnum f) (generalFlags dfs) }

gopt_unset :: DynFlags -> GeneralFlag -> DynFlags
gopt_unset dfs f = dfs{ generalFlags = IntSet.delete (fromEnum f) (generalFlags dfs) }

xopt_set :: DynFlags -> ExtensionFlag -> DynFlags
xopt_set dfs f
    = let onoffs = On f : extensions dfs
      in dfs { extensions = onoffs,
               extensionFlags = flattenExtensionFlags (language dfs) onoffs }

flagsAll :: [Flag (CmdLineP DynFlags)]
flagsAll = [
    Flag "-prof"           (NoArg (addWay WayProf))
  , Flag "-dynamic"        (NoArg (do unSetGeneralFlag Opt_Static
                                      addWay WayDyn))
 ]

type DynP = EwM (CmdLineP DynFlags)

upd :: (DynFlags -> DynFlags) -> DynP ()
upd f = liftEwM (do dflags <- getCmdLineState
                    putCmdLineState $ f dflags)

addWay :: Way -> DynP ()
addWay w = upd (addWay' w)

addWay' :: Way -> DynFlags -> DynFlags
addWay' w dflags0 = let platform = targetPlatform dflags0
                        dflags1 = dflags0 { ways = w : ways dflags0 }
                        dflags2 = wayExtras platform w dflags1
                        dflags3 = foldr setGeneralFlag' dflags2 (wayGeneralFlags platform w)
                    in dflags3

unSetGeneralFlag :: GeneralFlag -> DynP ()
unSetGeneralFlag f = upd (unSetGeneralFlag' f)

setGeneralFlag' :: GeneralFlag -> DynFlags -> DynFlags
setGeneralFlag' f dflags = gopt_set dflags f
unSetGeneralFlag' :: GeneralFlag -> DynFlags -> DynFlags
unSetGeneralFlag' f dflags = gopt_unset dflags f


setExtensionFlag' :: ExtensionFlag -> DynFlags -> DynFlags
setExtensionFlag' f dflags = xopt_set dflags f

exposePackage' :: String -> DynFlags -> DynFlags
exposePackage' p dflags
    = dflags { packageFlags = ExposePackage p : packageFlags dflags }

data Platform
        = Platform {
              platformOS                       :: OS
          }
        deriving (Read, Show, Eq)

data OS
        = OSUnknown
        | OSLinux
        | OSDarwin
        | OSSolaris2
        | OSMinGW32
        | OSFreeBSD
        | OSDragonFly
        | OSOpenBSD
        | OSNetBSD
        | OSKFreeBSD
        | OSHaiku
        | OSOsf3
        deriving (Read, Show, Eq)

data Flag m = Flag
    {   flagName    :: String,   -- Flag, without the leading "-"
        flagOptKind :: OptKind m -- What to do if we see it
    }

data OptKind m                             -- Suppose the flag is -f
    = NoArg     (EwM m ())                 -- -f all by itself

newtype EwM m a = EwM { unEwM :: String -> m a }

instance Monad m => Monad (EwM m) where
    (EwM f) >>= k = EwM (\l -> do r <- f l
                                  unEwM (k r) l)
    return v = EwM (\_ -> return v)

setArg :: Monad m => String -> EwM m () -> EwM m ()
setArg l (EwM f) = EwM (\_ -> f l)

liftEwM :: Monad m => m a -> EwM m a
liftEwM action = EwM (\_ -> do { r <- action; return r })


newtype CmdLineP s a = CmdLineP { runCmdLine :: s -> (a, s) }

instance Monad (CmdLineP s) where
    m >>= k = CmdLineP $ \s ->
                  let (a, s') = runCmdLine m s
                  in runCmdLine (k a) s'

    return a = CmdLineP $ \s -> (a, s)

getCmdLineState :: CmdLineP s s
getCmdLineState   = CmdLineP $ \s -> (s,s)
putCmdLineState :: s -> CmdLineP s ()
putCmdLineState s = CmdLineP $ \_ -> ((),s)


processArgs :: CmdLineP DynFlags ()
processArgs = unEwM process (error "processArgs: no arg yet")
  where
    process =
        case findArg flagsAll "-dynamic" of
            Just (NoArg _) -> setArg "-dynamic" $ do unSetGeneralFlag Opt_Static
                                                     addWay WayDyn
            Nothing -> return ()

findArg :: [Flag m] -> String -> Maybe (OptKind m)
findArg spec arg =
    case
           [ optKind
           | flag <- spec,
             let optKind  = flagOptKind flag,
             Just _ <- [stripPrefix (flagName flag) arg] ]
    of
        []      -> Nothing
        (one:_) -> Just one
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.