alpha 1.0.5 → 1.0.7
raw patch · 13 files changed
+279/−293 lines, 13 files
Files
- alpha.cabal +1/−1
- src/Alpha.hs +248/−66
- src/Compile.hs +1/−1
- src/Compile/State.hs +2/−6
- src/Context.hs +2/−200
- src/Context/Language.hs +5/−4
- src/Context/Types.hs +2/−0
- src/Format.hs +3/−3
- src/PCode/Instruction.hs +1/−1
- src/PCode/Value.hs +1/−1
- src/Specialize.hs +5/−5
- src/Specialize/Types.hs +2/−1
- src/Specialize/X86_64.hs +6/−4
alpha.cabal view
@@ -1,5 +1,5 @@ name: alpha-version: 1.0.5+version: 1.0.7 synopsis: A compiler for the Alpha language description: Alpha is a programming language that aims at being very simple and low-level, so as to be efficient, while at the same time
src/Alpha.hs view
@@ -1,98 +1,280 @@-{-# LANGUAGE ViewPatterns, NoMonomorphismRestriction, ParallelListComp, TupleSections #-}+{-# LANGUAGE ViewPatterns, ImplicitParams, NoMonomorphismRestriction, ParallelListComp, TupleSections, CPP, ForeignFunctionInterface, MultiParamTypeClasses, RankNTypes #-}+import Bindings.Posix.Sys.Mman+import Bindings.Posix.Unistd import Compile-import Context+import Context as C+import Control.Category ((>>>))+import Data.ByteString.Internal import Data.ByteString.Unsafe+import Data.Functor.Identity+import Data.IORef import Data.List import Data.Maybe import Data.Ord import Data.Version-import qualified Data.Bimap as BM-import qualified Data.ByteString as B-import qualified Data.Map as M-import qualified Data.Serialize as Ser+import Foreign hiding (unsafePerformIO,unsafeForeignPtrToPtr,void)+import Foreign.C+import Foreign.ForeignPtr.Unsafe import Format-import Foreign hiding (void)+import ID import My.Control.Monad-import My.Control.Monad.State hiding ((<.>))+import My.Control.Monad.State import My.Prelude import Options-import Paths_alpha (version) import PCode+import Paths_alpha (version) import Serialize import Specialize+import Specialize.Architecture import Syntax import Syntax.Parse-import System.IO import System.Directory import System.Environment as SE import System.FilePath+import System.IO+import System.IO.Unsafe (unsafePerformIO) import System.Posix.Files+import qualified Data.Bimap as BM+import qualified Data.ByteString as B+import qualified Data.Map as M+import qualified Data.Serialize as Ser +newtype Str = Str String+instance Show Str where show (Str s) = s++withSettings :: ((?settings :: Settings) => IO a) -> IO a+withSettings m = gets settings >>= \s -> let ?settings = s in m+ main = do args <- getArgs case getSettings args of- Right s -> execute s+ Right s -> do+ put (C s undefined undefined undefined undefined undefined)+ withSettings $ case (action ?settings,programs ?settings) of+ (PrintHelp,_) -> printHelp+ (PrintVersion,_) -> printVersion+ (Compile,[]) -> interactive+ (Compile,progs) -> mapM_ compileProgram progs Left err -> fail err -execute s = case action s of- PrintHelp -> printHelp- PrintVersion -> printVersion- Compile -> doCompile s- printHelp = putStrLn helpMsg printVersion = putStrLn $ "Alpha version "++showVersion version -newtype Str = Str String-instance Show Str where show (Str s) = s+entry = formatEntry $ outputFmt ?settings+languageFile language = languageDir ?settings</>language<.>"l"+findSource language = findM doesFileExist [dir</>language<.>"a" | dir <- sourceDirs ?settings] -doCompile opts = case programs opts of- [] -> interactive- progs -> mapM_ compileProgram progs+interactive = withDefaultContext $ do+ putStrLn $ "Alpha, version "++showVersion version++". Type alpha/help() for help on Alpha invocation. ^D to exit."+ str <- getContents+ let sTree = concat $ parseAlpha "/dev/stdin" str+ mapM_ (\e -> compileExpr e >> putStr "> " >> hFlush stdout) (Group []:sTree)+ putStrLn "\rGoodbye !"+compileProgram (language,entryName) = withDefaultContext $ do+ importLanguage compileLanguage (const $ return ()) language+ l <- getting language_+ entrySym <- viewState language_ $ internSym entryName+ _ <- getAddressComp (outputArch ?settings) entrySym+ (addrs,ptrs) <- unzip $< sortBy (comparing fst) $< M.elems $< gets compAddresses+ top <- gets compTop+ contents <- B.concat $< sequence [withForeignPtr ptr $ \p -> unsafePackCStringLen (castPtr p,size)+ | ptr <- ptrs | size <- zipWith (-) (tail addrs++[top]) addrs]+ writeFormat (outputFmt ?settings) entryName contents+compileLanguage force name = do+ let langFile = languageFile name+ source <- findSource name+ skip <- return (not force) <&&> fileExist langFile <&&> maybe (return True) (langFile `newerThan`) source+ l <- if skip then either (\e -> error $ "Error reading language file "++langFile++": "++e)+ id $< Ser.decode $< B.readFile langFile else do+ putStrLn $ "Compiling language "++name++"..."+ lang <- compileFile $ fromMaybe (error $ "Couldn't find source file for language "++name) source+ createDirectoryIfMissing True (dropFileName langFile)+ B.writeFile langFile (Ser.encode lang)+ return lang+ return (not skip,l)+ where compileFile src = withDefaultContext $ (>> gets language) $ do+ str <- readFile src+ let sTree = concat $ parseAlpha src str+ init <- mapM compileExpr sTree+ languageState $ modify $ \e -> exportLanguage $ e { initializeL = init }+compileExpr expr = do+ symExpr <- languageState $ envCast expr+ trExpr <- doTransform symExpr+ (code,imports) <- languageState $ compile [] Nothing trExpr+ mapM_ (importLanguage compileLanguage (mapM_ execCode)) imports+ execCode code+ return code++foreign import ccall "mprotect" mprotect :: Ptr () -> CSize -> CInt -> IO CInt++foreign import ccall "dynamic" mkProc :: FunPtr (Ptr() -> IO ()) -> Ptr() -> IO ()+foreign import ccall "dynamic" mkFunSize :: FunPtr (Ptr() -> IO Int) -> Ptr() -> IO Int+foreign import ccall "dynamic" mkFunInit :: FunPtr (Ptr () -> Ptr() -> IO ()) -> Ptr() -> Ptr () -> IO ()+foreign import ccall "dynamic" mkFunTransform :: FunPtr (Ptr () -> Ptr() -> IO (Ptr ())) -> Ptr() -> Ptr () -> IO (Ptr ())++funPtrToInteger f = fromIntegral $ ptrToIntPtr $ castFunPtrToPtr f+exportAlpha stub ptr = unsafePerformIO $ do+ unsafeUseAsCStringLen (stub $ funPtrToInteger ptr) $ \(src,size) -> do+ ptr <- mallocForeignPtrBytes size+ withForeignPtr ptr $ \dst -> copyBytes (castPtr dst) src size+ return ptr+initialBindings = [(n,Left $ Builtin b) | (b,n) <- bNames] ++ [+ ("alter" ,Left $ Axiom XAlter),+ ("bind" ,Left $ Axiom XBind),++ ("choose" ,Left $ Axiom XChoose),+ ("<-" ,Left $ Axiom XRestart),+ ("->" ,Left $ Axiom XReturn),+ ("do" ,Left $ Axiom XDo),++ ("lang" ,Left $ Axiom XLang),+ ("verb" ,Left $ Axiom XVerb),+ ("noun" ,Left $ Axiom XNoun),++ ("id" ,Left $ Axiom XID),+ ("@" ,Left $ Axiom XAddr),+ ("#" ,Left $ Axiom XSize)] ++ [++ ("alpha/c@" , Right $ exportAlpha callStub1 alpha_compAddr), + ("alpha/create-symbol" , Right $ exportAlpha callStub0 alpha_createSym),+ ("alpha/number-symbol" , Right $ exportAlpha callStub1 alpha_numSym),+ ("alpha/symbol-name" , Right $ exportAlpha callStub1 alpha_symName),+ ("alpha/name-symbol" , Right $ exportAlpha callStub1 alpha_nameSym),++ ("alpha/set-transform" , Right $ exportAlpha callStub1 alpha_setTransform), + ("alpha/reload" , Right $ exportAlpha callStub0 alpha_reload), + + ("alpha/allocate" , Right $ exportAlpha callStub1 alpha_allocate), + ("alpha/free" , Right $ exportAlpha callStub1 alpha_free), + + ("alpha/list" , Right $ exportAlpha callStub0 alpha_printList),+ ("alpha/lang" , Right $ exportAlpha callStub0 alpha_printLang),+ ("alpha/help" , Right $ exportAlpha callStub0 alpha_printHelp),+ ("alpha/print-OK" , Right $ exportAlpha callStub0 alpha_printOK), + ("alpha/print-num" , Right $ exportAlpha callStub1 alpha_printNum)+ ]++#define str(x) #x+#define ALPHA_EXPORT(fun,t) foreign export ccall str(__alpha_##fun) __alpha_##fun :: t ; foreign import ccall str(&__alpha_##fun) alpha_##fun :: FunPtr (t) ; __alpha_##fun+ALPHA_EXPORT(setTransform,Ptr () -> IO ()) fun = modify $ \c -> c { transform = Just fun }+ALPHA_EXPORT(compAddr,ID -> IO Int) id = readIORef compAddrRef >>= ($id)++ALPHA_EXPORT(symName,ID -> IO (Ptr Word8)) sym = do+ n <- gets (lookupSymName sym . language)+ ret <- newArray0 0 (map c2w $ fromMaybe "" n)+ return ret+ALPHA_EXPORT(nameSym,Ptr Word8 -> IO ID) p = do+ l <- peekArray0 0 p+ viewState language_ (internSym $ map w2c l)+ALPHA_EXPORT(createSym,IO ID) = viewState language_ createSym+ALPHA_EXPORT(numSym,Int -> IO ID) = viewState language_ . internSym . show++ALPHA_EXPORT(allocate,Int -> IO (Ptr())) = mallocBytes+ALPHA_EXPORT(free,Ptr() -> IO ()) = free++ALPHA_EXPORT(printHelp,IO()) = printHelp+ALPHA_EXPORT(printOK,IO()) = putStrLn "OK"+ALPHA_EXPORT(printNum,Int -> IO()) n = print (intPtrToPtr $ fromIntegral n)+ALPHA_EXPORT(printList,IO()) = do+ syms <- getting (language_ >>> syms_)+ putStrLn $ intercalate " " (map fst $ BM.toList syms)+ALPHA_EXPORT(printLang,IO()) = getting language_ >>= print++ALPHA_EXPORT(reload,IO()) = withSettings $ do+ imports <- getting (language_ >>> f_ (languagesL >>> BM.toList >>> map fst)) + put initialContext+ mapM_ (importLanguage compileLanguage (mapM_ execCode)) imports++compAddrRef = unsafePerformIO $ newIORef (undefined :: ID -> IO Int)+contextRef = unsafePerformIO $ newIORef (error "Undefined context" :: Context)+instance MonadState Context IO where+ get = readIORef contextRef+ put = writeIORef contextRef++initialContext = C ?settings lang jitA M.empty (fromIntegral entry) Nothing+ where (lang,jitA) = execState (mapM_ st initialBindings) (C.emptyLanguage,M.empty)+ where st (s,v) = do+ i <- viewState fst_ (internSym s)+ case v of+ Left v -> modifying fst_ (setSymVal i v)+ Right p -> modifying snd_ (M.insert i p)++withDefaultContext = withState initialContext+contextState sta = (runState sta $< readIORef contextRef) >>= \(a,s') -> writeIORef contextRef s' >> return a+languageState = contextState . viewing language_++pageSize = fromIntegral $ unsafePerformIO $ c'sysconf c'_SC_PAGESIZE+enableExec p size = do+ let p' = alignPtr (p`plusPtr`(1-pageSize)) pageSize+ mprotect (castPtr p') (fromIntegral $ size+ p`minusPtr`p') (c'PROT_READ .|. c'PROT_WRITE .|. c'PROT_EXEC)+ +evalCode :: (FunPtr (Ptr() -> a) -> Ptr() -> a) -> ByteString -> Code -> (a -> IO b) -> IO b+evalCode wrap stub code f = do+ sym <- languageState $ state createSym >>= \s -> modify (setSymVal s (Verb code)) >> return s+ p <- getAddressJIT sym+ unsafeUseAsCString stub $ \stub -> f $ wrap (castPtrToFunPtr stub) (intPtrToPtr $ fromIntegral p)+ +execCode c = evalCode mkProc execStub c id++withRef ref val x = readIORef ref >>= \v -> writeIORef ref val >> x >>= \x -> writeIORef ref v >> return x+getAddress arch lookup register = withRef compAddrRef getAddr . getAddr where- entry = formatEntry $ outputFmt opts- languageFile language = languageDir opts</>language<.>"l"- findSource language = findM doesFileExist [file | dir <- sourceDirs opts- , let base = dir</>language- , file <- [base<.>"a",base]]+ getAddr sym = lookup sym >>= \val -> case val of+ Just a -> return a+ Nothing -> gets language >>= \lang -> (>> getAddr sym) $ case lookupSymVal sym lang of+ Verb c -> void $ do+ let (size,codem) = specialize arch (sym,getAddr) c+ ptr <- mallocForeignPtrBytes size+ register sym ptr size+ code <- codem+ withForeignPtr ptr $ \p -> do+ unsafeUseAsCStringLen code $ \(p',n) -> copyBytes p (castPtr p') n+ enableExec p size+ Noun size init -> do+ size <- evalCode mkFunSize execStub size id+ ptr <- mallocForeignPtrBytes size+ register sym ptr size+ withForeignPtr ptr $ \p -> evalCode mkFunInit initStub init ($castPtr p)+ _ -> fail $ "Couldn't find definition of symbol "++fromMaybe (show sym) (lookupSymName sym lang) - interactive = withDefaultContext entry $ do- putStrLn $ "Alpha, version "++showVersion version++". Type alpha/help() for help on Alpha invocation. ^D to exit."- str <- getContents- let sTree = concat $ parseAlpha "/dev/stdin" str- mapM_ (\e -> compileExpr e >> putStr "> " >> hFlush stdout) (Group []:sTree)- putStrLn "\rGoodbye !"- compileProgram (language,entryName) = withDefaultContext entry $ do- importLanguage compileLanguage (const $ return ()) language- l <- getting language_- entrySym <- viewState language_ $ internSym entryName- _ <- getAddressComp (outputArch opts) entrySym- (addrs,ptrs) <- unzip $< sortBy (comparing fst) $< M.elems $< gets compAddresses- top <- gets compTop- contents <- B.concat $< sequence [withForeignPtr ptr $ \p -> unsafePackCStringLen (castPtr p,size)- | ptr <- ptrs | size <- zipWith (-) (tail addrs++[top]) addrs]- writeFormat (outputFmt opts) entryName contents- compileLanguage force name = do- let langFile = languageFile name- source <- findSource name- skip <- return (not force) <&&> fileExist langFile <&&> maybe (return True) (langFile `newerThan`) source- l <- if skip then either (\e -> error $ "Error reading language file "++langFile++": "++e)- id $< Ser.decode $< B.readFile langFile else do- putStrLn $ "Compiling language "++name++"..."- lang <- compileFile $ fromMaybe (error $ "Couldn't find source file for language "++name) source- createDirectoryIfMissing True (dropFileName langFile)- B.writeFile langFile (Ser.encode lang)- return lang- return (not skip,l)- where compileFile src = withDefaultContext entry $ (>> gets language) $ do- str <- readFile src- let sTree = concat $ parseAlpha src str- init <- mapM compileExpr sTree- languageState $ modify $ \e -> exportLanguage $ e { initializeL = init }- compileExpr expr = do- symExpr <- languageState $ envCast expr- trExpr <- doTransform symExpr- (code,imports) <- languageState $ compile [] Nothing trExpr- mapM_ (importLanguage compileLanguage (mapM_ execCode . initializeL)) imports- execCode code- return code+getAddressJIT = getAddress arch_host lookup register+ where lookup id = do+ val <- M.lookup id $< gets jitAddresses+ return $ (fromIntegral . ptrToIntPtr . unsafeForeignPtrToPtr) $< val+ register id ptr size = modifying jitAddresses_ (M.insert id ptr)+getAddressComp arch = getAddress arch lookup register+ where lookup id = (fst$<) $< M.lookup id $< gets compAddresses+ register id ptr size = do+ n <- getting compTop_+ modifying compAddresses_ (M.insert id (n,ptr))+ modifying compTop_ (+size) +doTransform syn = gets transform >>= ($syn) . maybe return tr + where tr fun tree = do+ root <- allocTree tree+ new <- unsafeUseAsCString initStub $ \stub -> mkFunTransform (castPtrToFunPtr stub) fun root+ readTree new+ intS = sizeOf (undefined::Int) ; ptrS = sizeOf (undefined::Ptr())+ pok e p = poke (castPtr p) e >> return (p`plusPtr`sizeOf e)+ pik p = peek (castPtr p) >>= \e -> return (e,p`plusPtr`sizeOf e)+ allocTree (Group g) = do+ p <- mallocBytes (intS+intS+(length g*ptrS))+ p' <- pok (0::Int) p+ p'' <- pok (length g) p'+ mapM allocTree g >>= \l -> pokeArray (castPtr p'') l+ return p+ allocTree (Symbol (ID s)) = do+ p <- mallocBytes (intS+intS)+ p' <- pok (1::Int) p+ pok s p'+ return p+ readTree p = do+ (t,p') <- pik p+ case t :: Int of+ 0 -> do+ (s,p'') <- pik p'+ l <- peekArray s p''+ liftM Group $ mapM readTree l+ 1 -> do+ liftM (Symbol . ID) $ peek p'+
src/Compile.hs view
@@ -3,7 +3,7 @@ import Compile.State as CS import Compile.Utils-import Context.Language+import Context import Data.Either import Data.Maybe import ID
src/Compile/State.hs view
@@ -1,6 +1,5 @@ {-# LANGUAGE StandaloneDeriving, NoMonomorphismRestriction, ViewPatterns #-} module Compile.State(- module Context.Types, module My.Data.Graph, CompileState(..),BranchType(..),EdgeData(..),NodeData(..),CaseInfo(..), depGraph_,infoStack_,imports_,@@ -26,11 +25,8 @@ import My.Control.Monad import ID import My.Data.Graph hiding (deleteEdge,deleteNode,getContext,empty)-import Context.Types-import Context.Language as L-+import Context as C import qualified My.Data.Graph as G-import qualified Context as E import qualified Data.Map as M deriving instance Eq Instruction@@ -63,7 +59,7 @@ isBackEdge (_,BranchAlt Backward _) = True isBackEdge _ = False -getSymName = lift . gets . L.lookupSymName+getSymName = lift . gets . C.lookupSymName getSymVal s = lift $ getting (vals_ >>> f_ (M.lookup s)) newVar = lift $ state createSym
src/Context.hs view
@@ -1,203 +1,5 @@-{-# LANGUAGE ForeignFunctionInterface, NoMonomorphismRestriction, MultiParamTypeClasses, CPP #-} module Context(module Context.Types- ,module Lang- ,withDefaultContext- ,languageState- ,doTransform ,getAddressComp- ,execCode) where+ ,module Context.Language) where -import Bindings.Posix.Sys.Mman-import Bindings.Posix.Unistd-import Context.Language as Lang import Context.Types-import Control.Category ((>>>))-import Data.ByteString.Internal-import Data.ByteString.Unsafe-import Data.Functor.Identity-import Data.IORef-import Data.List-import Data.Maybe-import Foreign hiding (unsafePerformIO,unsafeForeignPtrToPtr,void)-import Foreign.C-import Foreign.ForeignPtr.Unsafe-import Format-import ID-import My.Control.Monad-import My.Control.Monad.State-import My.Prelude-import Options-import PCode-import Specialize-import Specialize.Architecture-import Syntax-import System.IO.Unsafe (unsafePerformIO)-import qualified Data.Bimap as BM-import qualified Data.ByteString as B-import qualified Data.Map as M--foreign import ccall "mprotect" mprotect :: Ptr () -> CSize -> CInt -> IO CInt--foreign import ccall "dynamic" mkProc :: FunPtr (Ptr() -> IO ()) -> Ptr() -> IO ()-foreign import ccall "dynamic" mkFunSize :: FunPtr (Ptr() -> IO Int) -> Ptr() -> IO Int-foreign import ccall "dynamic" mkFunInit :: FunPtr (Ptr () -> Ptr() -> IO ()) -> Ptr() -> Ptr () -> IO ()-foreign import ccall "dynamic" mkFunTransform :: FunPtr (Ptr () -> Ptr() -> IO (Ptr ())) -> Ptr() -> Ptr () -> IO (Ptr ())--funPtrToInteger f = fromIntegral $ ptrToIntPtr $ castFunPtrToPtr f-exportAlpha stub ptr = unsafePerformIO $ do- unsafeUseAsCStringLen (stub $ funPtrToInteger ptr) $ \(src,size) -> do- ptr <- mallocForeignPtrBytes size- withForeignPtr ptr $ \dst -> copyBytes (castPtr dst) src size- return ptr-initialBindings = [(n,Left $ Builtin b) | (b,n) <- bNames] ++ [- ("alter" ,Left $ Axiom XAlter),- ("bind" ,Left $ Axiom XBind),-- ("choose" ,Left $ Axiom XChoose),- ("<-" ,Left $ Axiom XRestart),- ("->" ,Left $ Axiom XReturn),- ("do" ,Left $ Axiom XDo),-- ("lang" ,Left $ Axiom XLang),- ("verb" ,Left $ Axiom XVerb),- ("noun" ,Left $ Axiom XNoun),-- ("id" ,Left $ Axiom XID),- ("@" ,Left $ Axiom XAddr),- ("#" ,Left $ Axiom XSize)] ++ [-- ("alpha/c@" , Right $ exportAlpha callStub1 alpha_compAddr), - ("alpha/create-symbol" , Right $ exportAlpha callStub0 alpha_createSym),- ("alpha/number-symbol" , Right $ exportAlpha callStub1 alpha_numSym),- ("alpha/symbol-name" , Right $ exportAlpha callStub1 alpha_symName),- ("alpha/name-symbol" , Right $ exportAlpha callStub1 alpha_nameSym),-- ("alpha/set-transform" , Right $ exportAlpha callStub1 alpha_setTransform), -- ("alpha/allocate" , Right $ exportAlpha callStub1 alpha_allocate), - ("alpha/free" , Right $ exportAlpha callStub1 alpha_free), - - ("alpha/list" , Right $ exportAlpha callStub0 alpha_printList),- ("alpha/lang" , Right $ exportAlpha callStub0 alpha_printLang),- ("alpha/help" , Right $ exportAlpha callStub0 alpha_printHelp),- ("alpha/print-OK" , Right $ exportAlpha callStub0 alpha_printOK), - ("alpha/print-num" , Right $ exportAlpha callStub1 alpha_printNum)- ]--#define str(x) #x-#define ALPHA_EXPORT(fun,t) foreign export ccall str(__alpha_##fun) __alpha_##fun :: t ; foreign import ccall str(&__alpha_##fun) alpha_##fun :: FunPtr (t) ; __alpha_##fun-ALPHA_EXPORT(setTransform,Ptr () -> IO ()) fun = modify $ \c -> c { transform = Just fun }-ALPHA_EXPORT(compAddr,ID -> IO Int) id = readIORef compAddrRef >>= ($id)--ALPHA_EXPORT(symName,ID -> IO (Ptr Word8)) sym = do- n <- gets (lookupSymName sym . language)- ret <- newArray0 0 (map c2w $ fromMaybe "" n)- return ret-ALPHA_EXPORT(nameSym,Ptr Word8 -> IO ID) p = do- l <- peekArray0 0 p- viewState language_ (internSym $ map w2c l)-ALPHA_EXPORT(createSym,IO ID) = viewState language_ createSym-ALPHA_EXPORT(numSym,Int -> IO ID) = viewState language_ . internSym . show--ALPHA_EXPORT(allocate,Int -> IO (Ptr())) = mallocBytes-ALPHA_EXPORT(free,Ptr() -> IO ()) = free--ALPHA_EXPORT(printHelp,IO()) = Prelude.putStrLn helpMsg-ALPHA_EXPORT(printOK,IO()) = Prelude.putStrLn "OK"-ALPHA_EXPORT(printNum,Int -> IO()) n = print (intPtrToPtr $ fromIntegral n)-ALPHA_EXPORT(printList,IO()) = do- syms <- getting (language_ >>> syms_)- putStrLn $ intercalate " " (map fst $ BM.toList syms)-ALPHA_EXPORT(printLang,IO()) = getting language_ >>= print--compAddrRef = unsafePerformIO $ newIORef (undefined :: ID -> IO Int)-contextRef = unsafePerformIO $ newIORef (error "Undefined context" :: Context)-instance MonadState Context IO where- get = readIORef contextRef- put = writeIORef contextRef--initialContext entry = C lang jitA M.empty (fromIntegral entry) Nothing- where (lang,jitA) = execState (mapM_ st initialBindings) (Lang.empty,M.empty)- where st (s,v) = do- i <- viewState fst_ (internSym s)- case v of- Left v -> modifying fst_ (setSymVal i v)- Right p -> modifying snd_ (M.insert i p)--withDefaultContext = withState . initialContext-contextState sta = (runState sta $< readIORef contextRef) >>= \(a,s') -> writeIORef contextRef s' >> return a-languageState = contextState . viewing language_--pageSize = fromIntegral $ unsafePerformIO $ c'sysconf c'_SC_PAGESIZE-enableExec p size = do- let p' = alignPtr (p`plusPtr`(1-pageSize)) pageSize- mprotect (castPtr p') (fromIntegral $ size+ p`minusPtr`p') (c'PROT_READ .|. c'PROT_WRITE .|. c'PROT_EXEC)- -evalCode :: (FunPtr (Ptr() -> a) -> Ptr() -> a) -> ByteString -> Code -> (a -> IO b) -> IO b-evalCode wrap stub code f = do- id <- languageState $ state createSym >>= \i -> modify (setSymVal i (Verb code)) >> return i- p <- getAddressJIT id- unsafeUseAsCString stub $ \stub -> f $ wrap (castPtrToFunPtr stub) (intPtrToPtr $ fromIntegral p) -execCode c = evalCode mkProc execStub c id--withRef ref val x = readIORef ref >>= \v -> writeIORef ref val >> x >>= \x -> writeIORef ref v >> return x-getAddress arch lookup register = withRef compAddrRef getAddr . getAddr- where- getAddr sym = lookup sym >>= \val -> case val of- Just a -> return a- Nothing -> gets language >>= \lang -> (>> getAddr sym) $ case lookupSymVal sym lang of- Verb c -> void $ do- let (size,codem) = specialize arch (sym,getAddr) c- ptr <- mallocForeignPtrBytes size- register sym ptr size- code <- codem- withForeignPtr ptr $ \p -> do- unsafeUseAsCStringLen code $ \(p',n) -> copyBytes p (castPtr p') n- enableExec p size- Noun size init -> do- size <- evalCode mkFunSize execStub size id- ptr <- mallocForeignPtrBytes size- register sym ptr size- withForeignPtr ptr $ \p -> evalCode mkFunInit initStub init ($castPtr p)- _ -> fail $ "Couldn't find definition of symbol "++fromMaybe (show sym) (lookupSymName sym lang)--getAddressJIT = getAddress arch_host lookup register- where lookup id = do- val <- M.lookup id $< gets jitAddresses- return $ (fromIntegral . ptrToIntPtr . unsafeForeignPtrToPtr) $< val- register id ptr size = modifying jitAddresses_ (M.insert id ptr)-getAddressComp arch = getAddress arch lookup register- where lookup id = (fst$<) $< M.lookup id $< gets compAddresses- register id ptr size = do- n <- getting compTop_- modifying compAddresses_ (M.insert id (n,ptr))- modifying compTop_ (+size)--doTransform syn = gets transform >>= ($syn) . maybe return tr - where tr fun tree = do- root <- allocTree tree- new <- unsafeUseAsCString initStub $ \stub -> mkFunTransform (castPtrToFunPtr stub) fun root- readTree new- intS = sizeOf (undefined::Int) ; ptrS = sizeOf (undefined::Ptr())- pok e p = poke (castPtr p) e >> return (p`plusPtr`sizeOf e)- pik p = peek (castPtr p) >>= \e -> return (e,p`plusPtr`sizeOf e)- allocTree (Group g) = do- p <- mallocBytes (intS+intS+(length g*ptrS))- p' <- pok (0::Int) p- p'' <- pok (length g) p'- mapM allocTree g >>= \l -> pokeArray (castPtr p'') l- return p- allocTree (Symbol (ID s)) = do- p <- mallocBytes (intS+intS)- p' <- pok (1::Int) p- pok s p'- return p- readTree p = do- (t,p') <- pik p- case t :: Int of- 0 -> do- (s,p'') <- pik p'- l <- peekArray s p''- liftM Group $ mapM readTree l- 1 -> do- liftM (Symbol . ID) $ peek p'- +import Context.Language
src/Context/Language.hs view
@@ -32,7 +32,7 @@ ["Exports: "++show (exportsL e)], ["Load code: "++show (initializeL e)]] -empty = Language (toEnum 0) BM.empty M.empty M.empty BM.empty M.empty S.empty []+emptyLanguage = Language (toEnum 0) BM.empty M.empty M.empty BM.empty M.empty S.empty [] createSym e@(Language { maxIDL = m }) = (m,e { maxIDL = succ m }) setSymVal id v e = e { valuesL = M.insert id v (valuesL e) }@@ -66,8 +66,8 @@ mapM merge [imp | (imp,_) <- BM.toList (languagesL l')] return l' else return l'- mergeLanguage imp l'- loadImport l'+ init <- mergeLanguage imp l'+ loadImport init return $ comp || recomp mergeLanguage imp l' = viewing language_ $ do let Language { symbolsL = syms' , languagesL = mods' , maxIDL = mi' } = l'@@ -80,7 +80,7 @@ aliasesL = aliasesL l `M.union` M.fromList aliases, equivsL = equivsL l `M.union` M.fromList (map swap aliases) }- Language { aliasesL = al , languagesL = mods } <- get+ Language { aliasesL = al , languagesL = mods, initializeL = init } <- get let tr s = fromMaybe (tr' s) $ M.lookup (tr' s) al tr' s' = fromMaybe (s' + mi) $ do m <- lookupSymMod s' l'@@ -93,6 +93,7 @@ valuesL = M.unionWith (\_ a -> a) (valuesL l) newVals, exportsL = exportsL l S.\\ M.keysSet newVals }+ return (translate tr init) exportLanguage l = l { symbolsL = BM.filter exportNameP (symbolsL l),
src/Context/Types.hs view
@@ -10,6 +10,7 @@ import ID import PCode import Syntax+import Options data Axiom = XAlter | XBind | XReturn | XRestart | XChoose | XDo@@ -38,6 +39,7 @@ vals_ = View (valuesL,\v ce -> ce { valuesL = v }) data Context = C {+ settings :: Settings, language :: Language, jitAddresses :: Map ID (ForeignPtr Word8), compAddresses :: Map ID (Int,ForeignPtr Word8),
src/Format.hs view
@@ -27,11 +27,11 @@ let (+) = unionFileModes setFileMode name (ownerExecuteMode + groupExecuteMode + otherExecuteMode + fileMode stat) -#define importFun(fun,t) foreign import ccall #fun fun :: t-#define importFmt(fmt) importFun(fmt##_entry,Int) ; importFun(fmt##_headerSize,Int) ; importFun(fmt##_headerCons,Int -> IO (Ptr CChar)) ; fmt = F #fmt fmt##_entry fmt##_headerSize fmt##_headerCons+#define IMPORT_FUN(fun,t) foreign import ccall #fun fun :: t+#define IMPORT_FORMAT(fmt) IMPORT_FUN(fmt##_entry,Int) ; IMPORT_FUN(fmt##_headerSize,Int) ; IMPORT_FUN(fmt##_headerCons,Int -> IO (Ptr CChar)) ; fmt = F #fmt fmt##_entry fmt##_headerSize fmt##_headerCons raw entry = F ("raw:"++show entry) entry 0 (const $ return nullPtr)-importFmt(elf64) ; importFmt(elf32) ; importFmt(exe)+IMPORT_FORMAT(elf64) ; IMPORT_FORMAT(elf32) ; IMPORT_FORMAT(exe) formats = [elf64,elf32,exe] #if x86_64_HOST_ARCH
src/PCode/Instruction.hs view
@@ -70,7 +70,7 @@ spanArray bs tree = array bs (assocs Nothing tree) where assocs p (Node a subs) = (a,(p,map rootLabel subs)):concatMap (assocs (Just a)) subs-codeRefs (Code args code ret) = [v | SymVal GValue v <- concatMap instrVals code]+codeRefs (Code args code ret) = [v | SymVal t v <- concatMap instrVals code, t == GValue || t==SymID] instance Show Instruction where show (Op BCall d (f:args)) = show d ++ " = " ++ show f ++ "(" ++ intercalate "," (map show args) ++ ")"
src/PCode/Value.hs view
@@ -31,7 +31,7 @@ instance Show Value where show (SymVal t v) = prefix++show v- where prefix = fromJust $ lookup t [(Value,""),(Address,"@"),(Size,"#"),(SymID,"$"),(GValue,"")]+ where prefix = fromJust $ lookup t [(Value,""),(Address,"@"),(Size,"#"),(SymID,"$"),(GValue,"g")] show (IntVal n) = show n show NullVal = "(null)"
src/Specialize.hs view
@@ -110,18 +110,18 @@ , s <- S.toList $ clobbers i ref , s' <- bindSyms bv] next i r (Op BCall d (_:args)) = insertManyA r assocs- where assocs = [a | ref <- d : argRefs i args+ where assocs = [a | ref <- S.toList (argsRefs i args) , v <- S.toList $ clobbers i ref , a <- [(v,worldID),(v,v)]] next _ r _ = r insertManyA r as = insertManyR r [a | (x,y) <- as, a <- [(x,y),(y,x)]] lookupRefs v r = ifEmpty (S.singleton worldID) $ R.lookupRan v r- argRefs i vs = S.toList $ S.fromList [s | SymVal Address s <- vs]+ argsRefs i vs = S.fromList [s | SymVal Address s <- vs] <> S.unions [references i s | SymVal Value s <- vs] references i v = lookupRefs v (referencesA!i)- referencesA = treeArray next $ insertManyR R.empty [(s,worldID) | arg <- args, s <- bindSyms arg]- where next i r (Op _ v vs) = insertManyR r' (map (v,) $ argRefs i vs)- where r' = foldr (uncurry R.delete) r [(v,v') | v' <- S.toList $ R.lookupRan v r]+ referencesA = treeArray next $ R.setDom worldID (S.fromList $ concatMap bindSyms args) R.empty+ where next i r (Op b v vs) = R.setRan v (argsRefs i vs <> world) r+ where world = if b==BCall then S.singleton worldID else S.empty next _ r _ = r ifEmpty def s | S.null s = def
src/Specialize/Types.hs view
@@ -2,7 +2,7 @@ module Specialize.Types(BinCode(..), isEmptyCode, binCodeData ,Architecture(..) ,Info(..)- ,Location(..), isFlags, regSyms, symLocs, symReg+ ,Location(..), isFlags, isRegister, regSyms, symLocs, symReg ,MemState(..), Future(..), emptyFuture ,frame_, locations_, flocations_) where @@ -82,6 +82,7 @@ regNum (Register r) = Just r regNum _ = Nothing isFlags (Flags _) = True ; isFlags _ = False+isRegister (Register _) = True; isRegister _ = False regSyms r locs = S.toList $ R.lookupDom (Register r) locs symLocs s locs = S.toList $ R.lookupRan s locs
src/Specialize/X86_64.hs view
@@ -107,7 +107,8 @@ return r loadRoot Nothing = return rsp -saveRegs rs = lift locInfo >>= \(locs,_) -> saveVars $ concatMap (flip regSyms locs) rs+saveRegs rs = lift locInfo >>= \(locs,_) -> saveVars $ nubOrd $ concatMap (flip regSyms locs) rs+storeRegs rs = lift locInfo >>= \(locs,_) -> storeVars $ nubOrd $ concatMap (flip regSyms locs) rs saveVars = saveVars' (\p s -> R.member s Memory (locations p) || S.size (R.lookupRan s (locations p)) > 1) storeVars = saveVars' (\p s -> R.member s Memory (locations p)) saveVars' isSaved vs = lift locInfo >>= \(locs,_) -> do@@ -302,20 +303,21 @@ Nothing -> return () modify (SB.delete rax)- let args' = [(arg,Just r) | (id,arg) <- argAssocs, Register r <- symLocs id locs]+ let args' = [(arg,Just r) | (sym,arg) <- argAssocs, Register r <- symLocs sym locs] (func:_,cload) <- listen $ loadArgs $ (fun,Nothing):args' readFuture $ do put (SB.empty compare)- (_,cstore) <- listen $ saveRegs allocRegs+ (_,cstore) <- listen $ storeRegs allocRegs top <- lift $ gets (frameTop . frame) (_,cstore') <- listen $ do lift $ mapM_ (storeBig top) argAssocs subri rsp rsp $ Left (fi top)- let pos = verbAddress >§ (+(snd (instrAddress thisInstr)+delta))+ let pos = verbAddress >§ \va -> va+snd (instrAddress thisInstr)+delta BC ~(_,delta,_) = cload <> cstore <> cstore' (call <|||> calli pos) func addri rsp rsp $ Left (fi top)+ lift $ modifying locations_ (R.filterRan (not . isRegister)) lift $ associateVR d rax compileOp b d [s]