Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GHC plugin update #260

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions gibbon-compiler/src/Gibbon/Common.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ module Gibbon.Common
-- * Gibbon configuration
, Config(..), Input(..), Mode(..), Backend(..), defaultConfig
, RunConfig(..), getRunConfig, defaultRunConfig, getGibbonConfig
, isBench, isLibrary

-- * Misc helpers
, SSModality(..), (#), (!!!), fragileZip, fragileZip', sdoc, ndoc, abbrv
Expand Down Expand Up @@ -252,8 +253,17 @@ data Mode = ToParse -- ^ Parse and then stop
| RunMPL -- ^ Compile to SML & compile with MPL & run
| Bench Var -- ^ Benchmark a particular function applied to the packed data within an input file.
| BenchInput FilePath -- ^ Hardcode the input file to the benchmark in the C code.
| Library Var -- ^ Compile as a library, with its main entry point given.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the idea for the "entry point" field of the library mode, @ckoparkar ? I don't see it used anywhere. Also, what's an entry point to a library anyway? I thought "entry point" is only applicable to executables. I'm really bad at these things...

deriving (Show, Read, Eq, Ord)

isBench :: Mode -> Bool
isBench (Bench _) = True
isBench _ = False

isLibrary :: Mode -> Bool
isLibrary (Library _) = True
isLibrary _ = False

-- | Compilation backend used
data Backend = C | LLVM
deriving (Show,Read,Eq,Ord)
Expand Down
26 changes: 14 additions & 12 deletions gibbon-compiler/src/Gibbon/Compiler.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@

module Gibbon.Compiler
( -- * Compiler entrypoints
compile, compileCmd
compile, compileFromL0, compileCmd
-- * Configuration options and parsing
, Config (..), Mode(..), Input(..)
, configParser, configWithArgs, defaultConfig
-- * Some other helper fns
, compileAndRunExe
, getRTSBuildDir, compileRTS
)
where

Expand Down Expand Up @@ -163,7 +164,8 @@ configParser = Config <$> inputParser
flag' RunMPL (long "mpl-run" <> help "Emit SML, compile with MPL, and run") <|>
(Bench . toVar <$> strOption (short 'b' <> long "bench-fun" <> metavar "FUN" <>
help ("Generate code to benchmark a 1-argument FUN against a input packed file."++
" If --bench-input is provided, then the benchmark is run as well.")))
" If --bench-input is provided, then the benchmark is run as well."))) <|>
(Library <$> toVar <$> strOption (long "lib" <> metavar "FUN" <> help ("Compile as a library with its entry point given.")))

-- use C as the default backend
backendParser :: Parser Backend
Expand Down Expand Up @@ -210,7 +212,7 @@ data CompileState a = CompileState
-- | Compiler entrypoint, given a full configuration and a list of
-- files to process, do the thing.
compile :: Config -> FilePath -> IO ()
compile config@Config{mode,input,verbosity,backend,cfile} fp0 = do
compile config@Config{input,verbosity} fp0 = do
-- set the env var DEBUG, to verbosity, when > 1
setDebugEnvVar verbosity

Expand All @@ -219,6 +221,11 @@ compile config@Config{mode,input,verbosity,backend,cfile} fp0 = do
let fp1 = dir </> fp0
-- Parse the input file
((l0, cnt0), fp) <- parseInput config input fp1
compileFromL0 config cnt0 fp l0


compileFromL0 :: Config -> Int -> FilePath -> L0.Prog0 -> IO ()
compileFromL0 config@Config{mode,backend,cfile} cnt0 fp l0 = do
let config' = config { srcFile = Just fp }

let initTypeChecked :: L0.Prog0
Expand Down Expand Up @@ -271,8 +278,6 @@ compile config@Config{mode,input,verbosity,backend,cfile} fp0 = do
str <- case backend of
C -> codegenProg config' l4



LLVM -> error $ "Cannot execute through the LLVM backend. To build Gibbon with LLVM: "
++ "stack build --flag gibbon:llvm_enabled"

Expand All @@ -284,7 +289,7 @@ compile config@Config{mode,input,verbosity,backend,cfile} fp0 = do
writeFile outfile str

-- (Stage 3) Code written, now compile if warranted.
when (mode == ToExe || mode == RunExe || isBench mode ) $ do
when (mode == ToExe || mode == RunExe || isBench mode || isLibrary mode) $ do
compileAndRunExe config fp >>= putStr
return ()

Expand Down Expand Up @@ -423,6 +428,7 @@ compileAndRunExe cfg@Config{backend,arrayInput,benchInput,mode,cfile,exefile} fp
_ -> return ""
where outfile = getOutfile backend fp cfile
exe = getExeFile backend fp exefile
doto = replaceExtension fp ".o"
pointer = gopt Opt_Pointer (dynflags cfg)
links = if pointer
then " -lgc -lm "
Expand All @@ -432,13 +438,14 @@ compileAndRunExe cfg@Config{backend,arrayInput,benchInput,mode,cfile,exefile} fp
lib_dir <- getRTSBuildDir
let rts_o_path = lib_dir </> "gibbon_rts.o"
let compile_prog_cmd = compilationCmd backend cfg
++ " -o " ++ exe
++ (if isLibrary mode then (" -c -o " ++ doto) else (" -o " ++ exe))
++" -I" ++ lib_dir
++" -L" ++ lib_dir
++ " -Wl,-rpath=" ++ lib_dir ++ " "
++ outfile ++ " " ++ rts_o_path
++ links ++ " -lgibbon_rts_ng"

putStrLn compile_prog_cmd
execCmd
Nothing
compile_prog_cmd
Expand Down Expand Up @@ -536,11 +543,6 @@ compilationCmd C config = (cc config) ++" -std=gnu11 "
simpleWriteBarrier = gopt Opt_SimpleWriteBarrier dflags
lazyPromote = gopt Opt_NoEagerPromote dflags

-- |
isBench :: Mode -> Bool
isBench (Bench _) = True
isBench _ = False

-- | The debug level at which we start to call the interpreter on the program during compilation.
interpDbgLevel :: Int
interpDbgLevel = 5
Expand Down
9 changes: 6 additions & 3 deletions gibbon-compiler/src/Gibbon/Passes/Codegen.hs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ sortFns (Prog _ _ funs mtal) = foldl go S.empty allTails
-- | Compile a program to C code that has the side effect of the
-- "gibbon_main" expression in that program.
codegenProg :: Config -> Prog -> IO String
codegenProg cfg prg@(Prog info_tbl sym_tbl funs mtal) =
codegenProg cfg@Config{mode} prg@(Prog info_tbl sym_tbl funs mtal) =
return (hashIncludes ++ pretty 80 (stack (map ppr defs)))
where
init_fun_env = foldr (\fn acc -> M.insert (funName fn) (map snd (funArgs fn), funRetTy fn) acc) M.empty funs
Expand All @@ -200,9 +200,12 @@ codegenProg cfg prg@(Prog info_tbl sym_tbl funs mtal) =
(prots,funs') <- (unzip . concat) <$> mapM codegenFun funs
main_expr' <- main_expr
let struct_tys = uniqueDicts $ S.toList $ harvestStructTys prg
return ((L.nub $ makeStructs struct_tys) ++ prots ++
return ((L.nub $ makeStructs struct_tys) ++
prots ++
[gibTypesEnum, initInfoTable info_tbl, initSymTable sym_tbl] ++
funs' ++ [main_expr'])
funs' ++
if isLibrary mode then [] else [main_expr']
)

main_expr :: PassM C.Definition
main_expr = do
Expand Down
6 changes: 4 additions & 2 deletions gibbon-compiler/src/Gibbon/Passes/Simplifier.hs
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,10 @@ simplifyL1 p0 = do
p0' <- freshNames1 p0
p1 <- markRecFns p0'
p2 <- inlineFuns p1
p3 <- deadFunElim p2
pure p3
Config{mode} <- ask
if isLibrary mode
then pure p2
else deadFunElim p2

--------------------------------------------------------------------------------

Expand Down
5 changes: 4 additions & 1 deletion gibbon-compiler/src/Gibbon/Pretty.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{-# LANGUAGE ConstraintKinds #-}

module Gibbon.Pretty
( Pretty(..), PPStyle(..), HasPretty, render, pprintHsWithEnv, pprender ) where
( Pretty(..), PPStyle(..), HasPretty, render, pprintHsWithEnv, pprender, pprenderWithStyle ) where

import Prelude hiding ((<>))
import Text.PrettyPrint
Expand Down Expand Up @@ -41,6 +41,9 @@ class Pretty e where
pprender :: Pretty e => e -> String
pprender = render . pprint

pprenderWithStyle :: Pretty e => PPStyle -> e -> String
pprenderWithStyle sty e = render $ pprintWithStyle sty e

doublecolon :: Doc
doublecolon = colon <> colon

Expand Down
5 changes: 1 addition & 4 deletions gibbon-ghc-integration/cabal.project
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
packages: ../gibbon-compiler
plugin0
plugin1
gibbon-plugin
examples

with-compiler: ghc-9.4.3

package *
ghc-options: -fexpose-all-unfoldings
40 changes: 12 additions & 28 deletions gibbon-ghc-integration/examples/gibbon-examples.cabal
Original file line number Diff line number Diff line change
@@ -1,41 +1,25 @@
cabal-version: >=1.10
cabal-version: 2.0

name: gibbon-examples
version: 0.1.0.0
build-type: Simple

library
executable run-gibbon-examples
hs-source-dirs: src
exposed-modules: BinTree
build-depends: base == 4.17.*
, plugin0
, plugin1
main-is: Main.hs
other-modules: BinTree, Measure
build-depends: base
, inline-c
, binary
ghc-options: -Wall -Wcompat -fdefer-typed-holes
, deepseq, time, bytestring
, gibbon-plugin
ghc-options:
default-language: Haskell2010
ghc-options: -Wall -Wcompat
-O2
-fplugin=Gibbon.Plugin
-fplugin=Gibbon.Plugin1

"-optl-Wl,--allow-multiple-definition"
-- "-optl-Wl,--whole-archive"
-- "-optl-Wl,-Bstatic"
-- "-optl-Wl,-L/home/ckoparka/chai/tree-velocity/gibbon-ghc-integration/plugin1/cbits/"
-- "-optl-Wl,-ltest2"
-- "-optl-Wl,-Bdynamic"
-- "-optl-Wl,--no-whole-archive"

-dcore-lint
-ddump-simpl -dsuppress-all -ddump-to-file
"-optl-Wl,-rpath,/home/artem/data/Dev/gibbon/gibbon/gibbon-rts/build"


executable run-gibbon-examples
hs-source-dirs: app
default-language: Haskell2010
main-is: Main.hs
build-depends: base, gibbon-examples, binary, bytestring
ghc-options:
-- "-with-rtsopts=-T"
-- "-with-rtsopts=-s"
-dcore-lint
extra-libraries: gibbon_rts_ng
extra-lib-dirs: /home/artem/data/Dev/gibbon/gibbon/gibbon-rts/build
60 changes: 39 additions & 21 deletions gibbon-ghc-integration/examples/src/BinTree.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

module BinTree where

import Gibbon.Plugin ( PackedAnn(..) )
-- import Gibbon.Plugin0 ( PackedAnn(..) )
import Gibbon.Plugin ( liftPacked, Packed, PackedAnn(..) )
import Foreign
import Foreign.C.Types
import GHC.Generics
Expand All @@ -14,48 +15,63 @@ import qualified Language.C.Inline as C

--------------------------------------------------------------------------------

data Tree a = Leaf Int a
| Node Int (Tree a) (Tree a)
data Tree = Leaf Int
| Node Int Tree Tree
deriving (Generic)

instance Binary a => Binary (Tree a)
instance Binary Tree

{-# ANN mkTree_seq LiftPacked #-}
mkTree_seq :: Int -> Tree Bool
-- {-# ANN mkTree_seq LiftPacked #-}
mkTree_seq :: Int -> Tree
mkTree_seq i =
if i <= 0
then Leaf 1 True
then Leaf 1
else
let x = mkTree_seq (i-1)
y = mkTree_seq (i-1)
in Node i x y

{-# ANN sumTree_seq LiftPacked #-}
sumTree_seq :: Tree a -> Int
sumTree_seq foo =
case foo of
Leaf i _ -> i
-- {-# ANN sumTree_seq LiftPacked #-}
sumTree_seq :: Tree -> Int
sumTree_seq tr =
case tr of
Leaf i -> i
Node _ a b ->
let x = sumTree_seq a
y = sumTree_seq b
in x + y

{-# ANN bench1 LiftPacked #-}
bench1 :: Int -> Int
bench1 n = sumTree_seq (mkTree_seq n)

--------------------------------------------------------------------------------
{-# ANN liftbench1 LiftPacked #-}
liftbench1 :: Int -> Int
liftbench1 n = sumTree_seq (mkTree_seq n)


foreign import ccall "print_double"
c_print_double :: CDouble -> IO CInt
foreign import ccall unsafe "c_liftbench1"
cfastbench1 :: CInt -> IO CInt

fast_print_double :: Double -> IO Int
fast_print_double x = do
y <- c_print_double (realToFrac x)
fastbench1 :: Int -> IO Int
fastbench1 x = do
y <- cfastbench1 (fromIntegral x)
pure $ fromIntegral y

--------------------------------------------------------------------------------

-- foreign import ccall "print_double"
-- c_print_double :: CDouble -> IO CInt

-- fast_print_double :: Double -> IO Int
-- fast_print_double x = do
-- y <- c_print_double (realToFrac x)
-- pure $ fromIntegral y

--------------------------------------------------------------------------------


{-

C.include "<stdlib.h>"
C.include "<stdio.h>"
C.include "<stdint.h>"
Expand All @@ -67,5 +83,7 @@ foreign import ccall "print_double2"

fast_print_double2 :: Double -> IO Int
fast_print_double2 x = do
y <- c_print_double2 (realToFrac x)
pure $ fromIntegral y
y <- c_print_double2 (realToFrac x)
pure $ fromIntegral y

-}
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
{-# LANGUAGE BangPatterns #-}

module Main ( main ) where

import BinTree -- ( fast_print_double, fast_print_double2 )
import Measure

import Control.Exception
import Data.Binary
import Data.ByteString.Lazy ( unpack )
import Data.Word
Expand Down Expand Up @@ -33,10 +37,28 @@ instance Binary Exp where

main :: IO ()
main = do
{-
let expr = OpE (IntE 10) (IntE 11)
print (unpack (encode expr))
let tr = Node 10 (Leaf 10 10) (Leaf 20 20) :: Tree Int
let tr = Node 10 (Leaf 10) (Leaf 20)
print (unpack (encode tr))
-}
{-
_ <- fast_print_double 3.0
_ <- fast_print_double2 10.0
-}

-- !n <- evaluate $ bench1 10
-- print n
-- !fastn <- fastbench1 10
-- print fastn

let size = 25
let iters = 9
(res0, t0, t_all_0) <- bench bench1 size iters

(res1, t1, t_all_1) <- benchIO fastbench1 size iters

print (res0,t0)
print (res1,t1)
pure ()
Loading
Loading