ghc-core (empty) → 0.1
raw patch · 5 files changed
+275/−0 lines, 5 filesdep +basedep +directorydep +filepathsetup-changed
Dependencies added: base, directory, filepath, hscolour, pcre-light, process
Files
- LICENSE +30/−0
- README +2/−0
- Setup.lhs +3/−0
- ghc-core.cabal +34/−0
- ghc-core.hs +206/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2008 Don Stewart++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of his contributors+ may be used to endorse or promote products derived from this software+ without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ README view
@@ -0,0 +1,2 @@+A convenient command line wrapper over GHC to display GHC's optimised+Core and assembly output in a human readable manner.
+ Setup.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ ghc-core.cabal view
@@ -0,0 +1,34 @@+name: ghc-core+version: 0.1+license: BSD3+license-file: LICENSE+author: Don Stewart+maintainer: Don Stewart+homepage: http://code.haskell.org/~dons/code/ghc-core+category: Development+synopsis: Display GHC's core and assembly output in a pager+description: A convenient command line wrapper for GHC that displays+ GHC's optimised core and assembly output in a human+ readable, colourised manner, in a pager.+ .+ Usage: + .+ > ghc-core A.hs+ .+ > ghc-core -fvia-C -optc-O3 A.hs+ .+ Screenshot: <http://galois.com/~dons/images/ghc-core.png>+ .+build-type: Simple+cabal-version: >= 1.2++executable ghc-core+ build-depends: base,+ process,+ pcre-light,+ hscolour >= 1.9,+ directory,+ filepath+ main-is: ghc-core.hs+ ghc-options: -Wall+ extensions: PatternGuards
+ ghc-core.hs view
@@ -0,0 +1,206 @@+{-# LANGUAGE PatternGuards #-}+--------------------------------------------------------------------+-- |+-- Module : ghc-core+-- Copyright : (c) Galois, Inc. 2008+-- License : BSD3+--+-- Maintainer: Don Stewart <dons@galois.com>+-- Stability : provisional+-- Portability: Needs a few libraries from hackage.+--+--------------------------------------------------------------------+--+-- Inspect the optimised core and assembly produce by GHC.+--+-- Examples:+--+-- > ghc-core zipwith+--+-- > ghc-core -fvia-C zipwith +--++------------------------------------------------------------------------++import Control.Concurrent+import Control.Exception+import Control.Monad+import Data.List+import System.Cmd+import System.Directory+import System.Environment+import System.Exit+import System.FilePath+import System.IO+import System.Process+import Text.Printf+import qualified Control.Exception as C++import Text.Regex.PCRE.Light.Char8++import Language.Haskell.HsColour+import Language.Haskell.HsColour.Colourise++------------------------------------------------------------------------++-- default hscolours+defaultColourPrefs :: ColourPrefs+defaultColourPrefs = ColourPrefs+ { keyword = [Foreground Green,Underscore]+ , keyglyph = [Foreground Red]+ , layout = [Foreground Cyan]+ , comment = [Foreground Blue]+ , conid = [Normal]+ , varid = [Normal]+ , conop = [Foreground Red,Bold]+ , varop = [Foreground Cyan]+ , string = [Foreground Magenta]+ , char = [Foreground Magenta]+ , number = [Foreground Magenta]+ , cpp = [Foreground Magenta,Dim]+ , selection = [Bold, Foreground Magenta]+ , variantselection = [Dim, Foreground Red, Underscore]+ , definition = [Foreground Blue]+ }++------------------------------------------------------------------------++main :: IO ()+main = do+ args <- getArgs++ mv <- getEnvMaybe "PAGER"+ let less = case mv of Just s -> s ; _ -> "less"++ strs' <- polish `fmap` compileWithCore args+ (strs,tmps) <- do+ x <- readProcess "sh" ["-c","ls /tmp/ghc*/*.s | head -1"] []+ case x of+ Left _ -> return (strs', Nothing)+ Right s -> if "-fvia-C" `elem` args+ then do asm <- readFile (init s)+ return ((strs' ++ asm), Just $ takeDirectory s)+ else return (strs', Just $ takeDirectory s)++ let nice = hscolour TTY defaultColourPrefs False True False strs++ bracket+ (openTempFile "/tmp" "ghc-core-XXXX.hcr")+ (\(f,h) -> do hClose h+ removeFile f+ case tmps of+ Just g -> system ("rm -rf " ++ g) >> return ()+ _ -> return ()+ )+ (\(f,h) -> do+ hPutStrLn h nice >> hFlush h+ e <- system $ less ++ " -r " ++ f+ exitWith e)++-- +-- Clean up the output with some regular expressions. +-- +polish :: String -> String+polish = unlines . dups . map polish' . lines+ where+ polish' [] = []+ polish' s+ | Just [_,a,b] <- match name s [] = polish' (a ++ b)+ | Just [_,a,b] <- match local s [] = polish' (a ++ b)+ | Just _ <- match core s [] = "------------------------------- Core -----------------------------------"+ | Just _ <- match asm s [] = "------------------------------- Assembly -------------------------------"++ | Just _ <- match junk s [] = []+ | Just _ <- match junk2 s [] = []+ | Just _ <- match junk3 s [] = []+ | Just _ <- match junk4 s [] = []+ | Just _ <- match junk5 s [] = []+ | Just _ <- match junk6 s [] = []+ | Just _ <- match junk7 s [] = []++ | otherwise = s++ -- simplify some qualified names+ name = compile+ "^(.*)GHC\\.[^\\.]*\\.(.*)$"+ [ungreedy]++ local = compile+ "^(.*)Main\\.(.*)$"+ [ungreedy]++ -- remove boring things+ core = compile "Tidy Core" [ungreedy]+ asm = compile "Asm code" [ungreedy]++ junk = compile "^.GlobalId" []+ junk2 = compile "^.Arity .*" []+ junk3 = compile "^Rec {|^end Rec" []+ junk4 = compile "DmdType" []+ junk5 = compile "NoCafRefs" []+ junk6 = compile "^\\[\\]$" []+ junk7 = compile "==========" []++ -- remove duplicate blank lines+ dups [] = []+ dups ([]:[]:xs) = dups ([]:xs)+ dups (x:xs) = x : dups xs++------------------------------------------------------------------------++compileWithCore :: [String] -> IO String+compileWithCore opts = do+ let ghc = "ghc"+ args = words "-O2 -keep-tmp-files -ddump-simpl -ddump-asm -ddump-simpl-stats -no-recomp --make"++ x <- readProcess ghc (opts ++ args) []+ case x of+ Left (err,str,std) -> do+ mapM_ putStrLn (lines str)+ mapM_ putStrLn (lines std)+ printf "GHC failed to compile %s\n" (show err)+ exitWith (ExitFailure 1) -- fatal++ Right str -> return str++------------------------------------------------------------------------++--+-- Strict process reading +--+readProcess :: FilePath -- ^ command to run+ -> [String] -- ^ any arguments+ -> String -- ^ standard input+ -> IO (Either (ExitCode,String,String) String) -- ^ either the stdout, or an exitcode and any output++readProcess cmd args input = C.handle (return . handler) $ do+ (inh,outh,errh,pid) <- runInteractiveProcess cmd args Nothing Nothing++ output <- hGetContents outh+ outMVar <- newEmptyMVar+ forkIO $ (C.evaluate (length output) >> putMVar outMVar ())++ errput <- hGetContents errh+ errMVar <- newEmptyMVar+ forkIO $ (C.evaluate (length errput) >> putMVar errMVar ())++ when (not (null input)) $ hPutStr inh input+ takeMVar outMVar+ takeMVar errMVar+ ex <- C.catch (waitForProcess pid) (\_e -> return ExitSuccess)+ hClose outh+ hClose inh -- done with stdin+ hClose errh -- ignore stderr++ return $ case ex of+ ExitSuccess -> Right output+ ExitFailure _ -> Left (ex, errput, output)++ where+ handler (C.ExitException e) = Left (e,"","")+ handler e = Left (ExitFailure 1, show e, "")+++-- Safe wrapper for getEnv+getEnvMaybe :: String -> IO (Maybe String)+getEnvMaybe name = handle (const $ return Nothing) (Just `fmap` getEnv name)