alpha 0.9.8 → 0.9.9
raw patch · 20 files changed
+367/−136 lines, 20 filesdep +relation
Dependencies added: relation
Files
- alpha.cabal +3/−3
- src/Alpha.hs +3/−3
- src/Compile.hs +20/−18
- src/Compile/State.hs +2/−2
- src/Context/Language.hs +39/−39
- src/Context/Types.hs +10/−10
- src/ID.hs +6/−8
- src/My/Control/Monad/TimeLine.hs +0/−1
- src/My/Data/Either.hs +7/−0
- src/My/Data/List.hs +4/−1
- src/My/Data/Tree.hs +10/−1
- src/PCode/Instruction.hs +13/−3
- src/PCode/Value.hs +9/−9
- src/Serialize.hs +2/−2
- src/Specialize.hs +110/−6
- src/Specialize/Architecture.hs +4/−7
- src/Specialize/Types.hs +26/−16
- src/Specialize/X86.hs +0/−4
- src/Specialize/X86_64.hs +96/−0
- src/Translate.hs +3/−3
alpha.cabal view
@@ -1,5 +1,5 @@ name: alpha-version: 0.9.8+version: 0.9.9 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@@ -20,8 +20,8 @@ location: git://github.com/lih/Alpha.git executable alpha- build-depends: base<=4.6.0.0, unix, containers, array, mtl, bytestring, bimap, ghc-prim, directory, filepath, cereal, parsec, transformers, bindings-posix+ build-depends: base<=4.6.0.0, unix, containers, array, mtl, bytestring, bimap, ghc-prim, directory, filepath, cereal, parsec, transformers, bindings-posix, relation main-is: Alpha.hs- other-modules: Alpha, Compile, Compile.State, Compile.Utils, Context, Context.Language, Context.Types, Elf, ID, My.Control.Monad, My.Control.Monad.State, My.Control.Monad.TimeLine, My.Data.Graph, My.Data.List, My.Data.Tree, My.Prelude, Options, PCode, PCode.Builtin, PCode.Instruction, PCode.Value, Serialize, Specialize, Specialize.Architecture, Specialize.Types, Specialize.X86, Syntax, Syntax.Parse, Translate+ other-modules: Alpha, Compile, Compile.State, Compile.Utils, Context, Context.Language, Context.Types, Elf, ID, My.Control.Monad, My.Control.Monad.State, My.Control.Monad.TimeLine, My.Data.Either, My.Data.Graph, My.Data.List, My.Data.Tree, My.Prelude, Options, PCode, PCode.Builtin, PCode.Instruction, PCode.Value, Serialize, Specialize, Specialize.Architecture, Specialize.Types, Specialize.X86_64, Syntax, Syntax.Parse, Translate hs-source-dirs: src c-sources: src/writeElf.c
src/Alpha.hs view
@@ -74,19 +74,19 @@ createDirectoryIfMissing True (dropFileName langFile) B.writeFile langFile (Ser.encode lang) return lang- loadLanguage name = compileLanguage name >>= execCode . loadCode >> languageState get+ loadLanguage name = compileLanguage name >>= execCode . initializeL >> languageState get compileFile src = withDefaultContext $ (>> gets language) $ do str <- readFile src let sTree = concat $ parseAlpha src str code <- mapM compileExpr sTree- languageState $ modify $ \e -> exportLanguage $ e { loadCode = foldr concatCode [] code }+ languageState $ modify $ \e -> exportLanguage $ e { initializeL = foldr concatCode [] code } where compileExpr expr = print (fmap Str expr) >> do symExpr <- languageState $ envCast expr print symExpr trExpr <- doTransform symExpr (code,imports) <- languageState $ compile Nothing trExpr- mapM_ (importLanguage compileLanguage (execCode . loadCode)) imports+ mapM_ (importLanguage compileLanguage (execCode . initializeL)) imports execCode code return code
src/Compile.hs view
@@ -1,21 +1,19 @@ {-# LANGUAGE TupleSections, ParallelListComp, NoMonomorphismRestriction #-} module Compile(compile) where -import Debug.Trace--import My.Prelude+import Compile.State as CS+import Compile.Utils+import Context.Language+import Data.Either+import Data.Maybe+import ID+import My.Control.Monad+import My.Control.Monad.State import My.Data.Graph as G hiding (deleteEdge,deleteNode) import My.Data.List-import My.Control.Monad.State-import My.Control.Monad-import Data.Maybe-import Data.Either+import My.Prelude import PCode-import Context.Language import Syntax-import ID-import Compile.Utils-import Compile.State as CS compile dest expr = runStateT st defaultState >§ \(code,cs) -> (code,imports cs) where st = do@@ -47,7 +45,9 @@ sequence_ [createEdge TimeDep n' n | (_,l) <- code, n' <- l] return (SymVal Value dest,(n:concatMap fst code,[n])) -compileBuiltin = compileBy . Op+compileBuiltin = compileBy . simplify+ where simplify op dest [] = Op BSet dest [IntVal 0]+ simplify op dest vars = Op op dest vars compileCall = compileBuiltin BCall compileAxiom XAlter _ forms = do@@ -55,15 +55,17 @@ codes <- sequence [compile' (Just v) e | Symbol v <- vars | e <- exprs] let (starts,ends) = unzip $ map snd codes return (NullVal,(concat starts,concat ends))-compileAxiom XBind _ args = doBind args+compileAxiom XBind _ args = case args of+ [bVars] -> doBind bVars Nothing+ [bVars,expr] -> do+ v <- newVar + compile' (Just v) expr *>> doBind bVars (Just v) where - doBind' bVars compile = compile *>>= \v -> do + doBind bVars val = do bnd <- bindFromSyntax bVars- n <- createNode (Instr $ PCode.Bind bnd v)+ n <- createNode (Instr $ PCode.Bind bnd val) return (NullVal,singleCode n)- doBind [bVars] = doBind' bVars $ nullCode- doBind [bVars,expr] = doBind' bVars $ newVar >>= \v -> compile' (Just v) expr-+ compileAxiom XDo dest [] = nullCode compileAxiom XDo dest forms = do let cs = reverse $ zipWith compile' (dest:repeat Nothing) (reverse forms)
src/Compile/State.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE StandaloneDeriving, NoMonomorphismRestriction #-}+{-# LANGUAGE StandaloneDeriving, NoMonomorphismRestriction, ViewPatterns #-} module Compile.State( module Context, module My.Data.Graph,@@ -104,7 +104,7 @@ br <- createNode (BrPart val) let makeAlt n = createEdge (BranchAlt typ n) br case val of- IntVal i -> makeAlt 0 (if i+1<length alts then tail alts!!i else head alts)+ IntVal (fromIntegral -> i) -> makeAlt 0 (if i+1<length alts then tail alts!!i else head alts) _ -> sequence_ $ zipWith makeAlt [0..] alts return (NullVal,([br],[]))
src/Context/Language.hs view
@@ -23,28 +23,28 @@ showTable name showLine contents = (name++":"):map (" "++) (concatMap showLine contents) instance Show Language where show e = intercalate "\n" $ showTable "Context" id [- ["Max ID: "++show (maxID e)],- showTable "Symbols" (\(s,i) -> [s++" -> "++show i]) $ BM.toList (symMap e),- showTable "Aliases" (\(i,i') -> [show i++" -> "++show i']) $ M.toList (aliasMap e),- showTable "Equivs" (\(i,i') -> [show i++" -> "++show i']) $ M.toList (equivMap e),- showTable "Modules" (\(s,IDRange r) -> [s++" -> "++show r]) $ BM.toList (modMap e),- showTable "Values" (\(i,v) -> [show i++" -> "++show v]) $ M.toList (valMap e),- ["Exports: "++show (exports e)],- ["Load code: "++show (loadCode e)]]+ ["Max ID: "++show (maxIDL e)],+ showTable "Symbols" (\(s,i) -> [s++" -> "++show i]) $ BM.toList (symbolsL e),+ showTable "Aliases" (\(i,i') -> [show i++" -> "++show i']) $ M.toList (aliasesL e),+ showTable "Equivs" (\(i,i') -> [show i++" -> "++show i']) $ M.toList (equivsL e),+ showTable "Modules" (\(s,Range r) -> [s++" -> "++show r]) $ BM.toList (languagesL e),+ showTable "Values" (\(i,v) -> [show i++" -> "++show v]) $ M.toList (valuesL e),+ ["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 undefined+empty = Language (toEnum 0) BM.empty M.empty M.empty BM.empty M.empty S.empty [] -createSym e@(Language { maxID = m }) = (m,e { maxID = succ m })-setSymVal id v e = e { valMap = M.insert id v (valMap e) }-lookupSymName id e = BM.lookupR id (symMap e)-lookupSymVal id e = fromMaybe NoValue $ M.lookup id (valMap e) -lookupSymMod id e = BM.lookupR (singleRange id) (modMap e) -addExport id e = e { exports = S.insert id (exports e) }-getImports e = map fst $ BM.toList $ modMap e-isImport im e = BM.member im (modMap e)+createSym e@(Language { maxIDL = m }) = (m,e { maxIDL = succ m })+setSymVal id v e = e { valuesL = M.insert id v (valuesL e) }+lookupSymName id e = BM.lookupR id (symbolsL e)+lookupSymVal id e = fromMaybe NoValue $ M.lookup id (valuesL e) +lookupSymMod id e = BM.lookupR (singleRange id) (languagesL e) +addExport id e = e { exportsL = S.insert id (exportsL e) }+getImports e = map fst $ BM.toList $ languagesL e+isImport im e = BM.member im (languagesL e) exportSymVal id v = setSymVal id v . addExport id -internSym s e = runState (st $ BM.lookup s (symMap e)) e +internSym s e = runState (st $ BM.lookup s (symbolsL e)) e where st (Just id) = return id st _ = do i <- state createSym @@ -59,45 +59,45 @@ where merge imp = gets language >>= \l -> unless (imp`isImport`l) $ do l' <- getImport imp- mapM_ merge [imp | (imp,_) <- BM.toList (modMap l')]+ mapM_ merge [imp | (imp,_) <- BM.toList (languagesL l')] mergeLanguage l' loadImport l' mergeLanguage l' = doF languageF $ do- let Language { symMap = syms' , modMap = mods' , maxID = mi' } = l'+ let Language { symbolsL = syms' , languagesL = mods' , maxIDL = mi' } = l' mapM_ (state . internSym) $ BM.keys syms'- Language { maxID = mi, symMap = syms } <- get+ Language { maxIDL = mi, symbolsL = syms } <- get let aliases = [(i'+mi,fromJust $ BM.lookup s' syms) | (s',i') <- BM.toList syms'] modify $ \l -> l {- maxID = mi+mi',- aliasMap = aliasMap l `M.union` M.fromList aliases,- equivMap = equivMap l `M.union` M.fromList (map swap aliases)+ maxIDL = mi+mi',+ aliasesL = aliasesL l `M.union` M.fromList aliases,+ equivsL = equivsL l `M.union` M.fromList (map swap aliases) }- Language { aliasMap = al , modMap = mods } <- get+ Language { aliasesL = al , languagesL = mods } <- get let tr s = fromMaybe (tr' s) $ M.lookup (tr' s) al tr' s' = fromMaybe (s' + mi) $ do m <- lookupSymMod s' l'- IDRange (r,_) <- BM.lookup m mods- IDRange (r',_) <- BM.lookup m mods'+ Range (r,_) <- BM.lookup m mods+ Range (r',_) <- BM.lookup m mods' return $ s'-r'+r- newVals = M.mapKeys tr $ M.map (translate tr) $ valMap l'+ newVals = M.mapKeys tr $ M.map (translate tr) $ valuesL l' modify $ \l -> l {- modMap = BM.insert imp (IDRange (mi,mi+mi')) (modMap l),- valMap = M.unionWith (\_ a -> a) (valMap l) newVals,- exports = S.difference (exports l) (M.keysSet newVals) + languagesL = BM.insert imp (Range (mi,mi+mi')) (languagesL l),+ valuesL = M.unionWith (\_ a -> a) (valuesL l) newVals,+ exportsL = S.difference (exportsL l) (M.keysSet newVals) } exportLanguage e = e {- symMap = BM.filter exportNameP (symMap e),- valMap = vals',- aliasMap = M.empty,- equivMap = M.empty,- exports = S.empty,- loadCode = translate trans (loadCode e)+ symbolsL = BM.filter exportNameP (symbolsL e),+ valuesL = vals',+ aliasesL = M.empty,+ equivsL = M.empty,+ exportsL = S.empty,+ initializeL = translate trans (initializeL e) } where set2Map s = M.fromAscList (zip (S.toAscList s) (repeat undefined))- Language { exports = ex, equivMap = eqs } = e- vals' = M.map (translate trans) $ M.intersection (valMap e) (set2Map ex)+ Language { exportsL = ex, equivsL = eqs } = e+ vals' = M.map (translate trans) $ M.intersection (valuesL e) (set2Map ex) trans s = fromMaybe s $ M.lookup s eqs refs = S.fromList $ concatMap references $ M.elems vals' exportNameP _ s = (S.member s ex || S.member s refs)
src/Context/Types.hs view
@@ -24,17 +24,17 @@ deriving Show data Language = Language {- maxID :: ID,- symMap :: Bimap String ID,- aliasMap :: Map ID ID,- equivMap :: Map ID ID,- modMap :: Bimap String IDRange,- valMap :: Map ID Context.Types.Value,- exports :: Set ID,- loadCode :: [Instruction]+ maxIDL :: ID,+ symbolsL :: Bimap String ID,+ aliasesL :: Map ID ID,+ equivsL :: Map ID ID,+ languagesL :: Bimap String (Range ID),+ valuesL :: Map ID Context.Types.Value,+ exportsL :: Set ID,+ initializeL :: [Instruction] }-symsF = Field (symMap,\s ce -> ce { symMap = s })-valsF = Field (valMap,\v ce -> ce { valMap = v })+symsF = Field (symbolsL,\s ce -> ce { symbolsL = s })+valsF = Field (valuesL,\v ce -> ce { valuesL = v }) data Context = C { language :: Language,
src/ID.hs view
@@ -2,15 +2,14 @@ newtype ID = ID Int deriving (Ord,Eq)-newtype IDRange = IDRange (ID,ID)- deriving Show- -singleRange i = IDRange (i,i)+newtype Range a = Range (a,a) -instance Eq IDRange where+singleRange i = Range (i,i)++instance Ord a => Eq (Range a) where a == b = compare a b == EQ-instance Ord IDRange where- compare (IDRange (a,b)) (IDRange (a',b')) = +instance Ord a => Ord (Range a) where+ compare (Range (a,b)) (Range (a',b')) = if b<=a' then LT else if b'<=a then GT else EQ@@ -28,7 +27,6 @@ abs = undefined signum = undefined fromInteger n = ID $ fromInteger n- -- Copyright (c) 2012, Coiffier Marc <marc.coiffier@gmail.com> -- All rights reserved.
src/My/Control/Monad/TimeLine.hs view
@@ -25,7 +25,6 @@ mzero = lift $ mzero mplus a b = TimeLineT (\t -> runTimeLineT a t `mplus` runTimeLineT b t) - timeLine tl = TimeLineT (Identity . tl) runTimeLine tl x = runIdentity $ runTimeLineT tl x
+ src/My/Data/Either.hs view
@@ -0,0 +1,7 @@+module My.Data.Either (module Data.Either, fromLeft, fromRight, fromEither) where++import Data.Either++fromLeft = either id (error "fromLeft given a Right argument")+fromRight = either (error "fromRight given a Left argument") id+fromEither x = either (const x) id
src/My/Data/List.hs view
@@ -1,4 +1,4 @@-module My.Data.List(module Data.List,classesBy,nubOrd) where+module My.Data.List(module Data.List,classesBy,nubOrd,sums) where import Data.List @@ -8,6 +8,9 @@ classesBy :: (a -> a -> Bool) -> [a] -> [[a]] classesBy (==) [] = [] classesBy (==) (e:l) = let (x,t) = partition (e==) l in (e:x):classesBy (==) t++sums :: Num a => [a] -> [a]+sums = scanl (+) 0 -- Copyright (c) 2012, Coiffier Marc <marc.coiffier@gmail.com> -- All rights reserved.
src/My/Data/Tree.hs view
@@ -1,6 +1,7 @@ module My.Data.Tree(module Data.Tree ,nubT,iterateT- ,spanningTree) where+ ,spanningTree+ ,branches, nodeList) where import Data.Tree import Data.Set as S@@ -12,4 +13,12 @@ return (a,[sub | sub <- subs, not (S.member (rootLabel sub) s)]) iterateT seed f = unfoldTree (\a -> (a,f a)) seed +branches (Node a []) = [[a]]+branches (Node a (sub:subs)) = let (b:t) = branches sub in ((a:b):t++concatMap branches subs)+ spanningTree seed nexts = nubT $ iterateT seed nexts++nodeList n@(Node _ subs) = n:concatMap nodeList subs ++test = Node 1 [Node 2 [Node 3 [],Node 4 []],+ Node 5 [Node 6 [],Node 7 []]]
src/PCode/Instruction.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE ViewPatterns, ParallelListComp #-} module PCode.Instruction where import Control.Monad.State@@ -20,7 +20,7 @@ } data Instruction = Op Builtin ID [Value] | Branch Value [Addr]- | Bind BindVar Value+ | Bind BindVar (Maybe ID) | Noop data Code = Code [BindVar] [Instruction] BindVar deriving Show@@ -31,18 +31,28 @@ isBranch _ = False bindSyms bv = bindSym bv : concatMap bindSyms (map fst $ bindSubs bv)+bindNodes bv = bv:map fst (bindSubs bv) symBind s = BindVar s (0,1) 0 [] instrVals (Op _ _ vs) = vs-instrVals (Bind _ v) = [v]+instrVals (Bind _ v) = map (SymVal Value) $ maybeToList v instrVals (Branch v _) = [v] instrVals _ = [] instrVars (Op _ v _) = [v] instrVars (Bind v _) = bindSyms v instrVars _ = [] +flattenBind def = flatten + where sizeOf (bindSize -> (s,sr)) = s+sr*def+ flatten bv@(BindVar s _ p subs) = (s,0,sizeOf bv):concat [+ [(s,n+n0,sz) | (s,n,sz) <- flatten bv]+ | (bv,_) <- subs+ | n0 <- scanl (+) p [n*sizeOf bv | (bv,n) <- subs]]+ set v val = Op BSet v [val] call v f args = Op BCall v (f:args) ret = Branch NullVal []+isRet (Branch NullVal []) = True+isRet _ = False concatCode c1 [] = c1 concatCode c1 c2 = map (f g1) c1 ++ map (f g2) c2
src/PCode/Value.hs view
@@ -11,7 +11,7 @@ data ValType = Value | Address | Size | SymID deriving Eq data Value = SymVal ValType ID- | IntVal Int+ | IntVal Integer | NullVal varEqVal n (SymVal Value n') = n==n'@@ -19,14 +19,14 @@ readConstant s = let (a,b) = break (=='#') (filter (/='-') s) in eitherToMaybe $ parseInt 10 a >>= \r -> if null b then return r else parseInt r (tail b)--parseInt r s - | all isHexDigit s =- case find (>=r) digs of - Just d -> Left $ "digit '"++[intToDigit d]++"' too great for base "++show r++" (in numeral constant '"++s++"')" - Nothing -> Right $ sum $ zipWith (*) (reverse digs) $ iterate (*r) 1- | otherwise = Left $ "all digits must be alphanumeric characters (in constant '"++s++"')"- where digs = map digitToInt s+ where + parseInt r s + | all isHexDigit s =+ case find (>=r) digs of + Just d -> Left $ "digit '"++[intToDigit $ fromIntegral d]++"' too great for base "++show r++" (in numeral constant '"++s++"')" + Nothing -> Right $ sum $ zipWith (*) (reverse digs) $ iterate (*r) 1+ | otherwise = Left $ "all digits must be alphanumeric characters (in constant '"++s++"')"+ where digs = map (fromIntegral . digitToInt) s instance Show Value where show (SymVal t v) = prefix++show v
src/Serialize.hs view
@@ -20,7 +20,7 @@ deriving instance Generic C.Value deriving instance Generic Axiom deriving instance Generic ID-deriving instance Generic IDRange+deriving instance Generic (Range a) deriving instance Generic Language instance Serialize ValType@@ -32,7 +32,7 @@ instance Serialize C.Value instance Serialize Axiom instance Serialize ID-instance Serialize IDRange+instance Serialize a => Serialize (Range a) instance (Ord a,Ord b,Serialize a,Serialize b) => Serialize (Bimap a b) where get = BM.fromList $< get put = put . BM.toList
src/Specialize.hs view
@@ -1,17 +1,121 @@+{-# LANGUAGE RankNTypes, ParallelListComp, TupleSections #-} module Specialize(specialize) where -import PCode+import Data.Monoid+import Control.Arrow import Context.Types+import Control.Monad.Trans.Reader+import Data.Array+import Data.List+import Data.Maybe import Data.Word-import Specialize.Architecture+import Data.Ord+import qualified Data.ByteString as B+import qualified Data.Map as M+import qualified Data.Relation as R+import qualified Data.Set as S import ID-import Data.ByteString+import My.Control.Monad+import My.Control.Monad.State+import My.Control.Monad.TimeLine+import My.Data.Either+import My.Data.Tree+import PCode+import Specialize.Architecture+import Specialize.Architecture+import Specialize.Types +import System.IO.Unsafe+import My.Prelude+ retCode = ret where ret = [0xc3] exit = [0x31,0xdb ,0x31,0xc0, 0xff,0xc0- ,0xcd,0x80] + ,0xcd,0x80]+sums = scanl (+) 0 -specialize :: Monad m => Architecture -> (ID -> m Int) -> Code -> (Int,m ByteString)-specialize arch assoc (Code args code ret) = (Prelude.length retCode,return $ pack retCode)+specialize arch assoc (Code args code retVar) = foo+ where+ foo = (sum sizes,B.concat $< sequence codes)+ -- foo = (length retCode, return (B.pack retCode))+ (estimates,sizes,codes) = unzip3 [v | Right (_,v) <- elems instructions]+ (past,future) = archInitials arch args retVar+ (bounds,instr,nexts,prevs) = navigate code+ positions = listArray bounds [(e,s) | e <- sums estimates, s <- sums sizes]+ codeTree = spanningTree 0 nexts+ runInstr i (p,f) past = runTimeLine (runReaderT (compile $ instr i) ((infos!i) getPos)) (p,f)+ where compile = archCompileInstr arch+ getPos j = (e'-e,d'-d,past j)+ where (e,d) = positions!i ; (e',d') = positions!j++ treeArray next seed = ret+ where assocs = (0,seed):concatMap f (nodeList codeTree)+ ret = array bounds assocs+ f (Node i subs) = [(j,next j (ret!i) (instr j)) | Node j _ <- subs]++ instructions = execState (specializeTree past codeTree) initialArray+ where+ specializeTree p (Node i subs) = gets ((!i) >>> fromLeft) >>= \f -> do+ past <- gets (!)+ let newVal@(p',_,vals) = runInstr i (p,f) (either (const Nothing) (Just . fst) . past)+ modify (// [(i,Right (p,vals))])+ mapM_ (specializeTree p') subs+ initialArray = fmap Left init+ where init = array bounds (concatMap f $ branches codeTree)+ f br = (n,fut):[(i,snd3 $ runInstr j (undefined,init!j) (const Nothing)) | (i,j) <- zip br (tail br)]+ where n = last br ; fut = if null (nexts n) then future else emptyFuture++ infos = constA bounds (Info assoc) `applyA` bindingsA `applyA` activesA `applyA` clobbersA+ where parent i v = fmap fst $ M.lookup v (bindingsA!i)+ bindingsA = treeArray next M.empty+ where next _ bnd (Bind bv (Just id)) = foldl (\m (k,v) -> M.insert k v m) bnd+ [(s,(id,n)) | (s,n,_) <- flattenBind (archDefaultSize arch) bv]+ next _ bnd _ = bnd+ activesA = saturate fun prevs nexts init start+ where init = accumArray const S.empty bounds []+ start = concat [prevs i | i <- indices init, isRet (instr i)]+ fun i a = addActives (instr i) $ S.unions (map (a!) (nexts i))+ where addActives (Op _ v vs) s = (s S.\\ clobbers i v)+ <> S.unions [clobbers i s' | SymVal Value s <- vs+ , s' <- s:maybeToList (parent i s)]+ <> maybe S.empty (clobbers i) (parent i v)+ addActives (Branch (SymVal Value id) _) s = s <> clobbers i id+ addActives (Bind bv v) s = maybe id S.insert v $ s S.\\ S.fromList (bindSyms bv)+ addActives _ s = s+ clobbers i v = fromMaybe (S.singleton v) $ R.lookupRan v (clobbersA!i)+ clobbersA = treeArray next (foldl (next undefined) R.empty [Bind bv Nothing | bv <- retVar:args])+ where next i r (Bind bv v) = insertManyR r' assocs+ where r' = restrict r (S.fromList (bindSyms bv))+ assocs = [ass | bv <- bindNodes bv+ , s <- bindSyms bv+ , ass <- [(bindSym bv,s),(s,bindSym bv)]]+ ++[ass | v <- maybeToList v+ , ref <- S.toList $ references i v+ , s <- maybe [v] S.toList (R.lookupRan ref r')+ , ass <- [(s,ref),(ref,s)]]+ next _ r _ = r+ lookupRefs v r = fromMaybe (S.singleton (ID (-1))) $ R.lookupRan v r+ references i v = lookupRefs v (referencesA!i)+ referencesA = treeArray next R.empty+ where next i r (Op _ v vs) = insertManyR r' (map (v,) $ S.toList refs)+ where r' = S.delete v (R.dom r) R.<| r+ refs = S.fromList [s | SymVal Address s <- vs]+ <> S.unions [lookupRefs v r | SymVal Value s <- vs]+ next _ r (Bind bv _) = restrict r (S.fromList (bindSyms bv))+ next _ r _ = r++restrict r s = (R.dom r S.\\ s) R.<| r R.|> (R.ran r S.\\ s)++constA bs v = accumArray const v bs []+zipWithA f a b = array (bounds a) [(i,f x y) | (i,x) <- assocs a | y <- elems b]+applyA = zipWithA ($)+insertManyR = foldl (\r (a,b) -> R.insert a b r)++saturate fun nexts prevs init start = f init (array (bounds init) [(i,length $ prevs i) | i <- indices init]) start+ where f a d [] = a+ f a d (i:t) | newElt == a!i = f a d t+ | otherwise = f (a//[(i,newElt)]) d'' (foldr (insertBy (comparing (d''!))) (filter (/=i) t) (nexts i))+ where newElt = fun i a+ d' = d // [(i,length $ (prevs`asTypeOf`nexts) i)]+ d'' = d' // [(n,(d'!n)-1) | n <- nexts i]
src/Specialize/Architecture.hs view
@@ -1,21 +1,18 @@ module Specialize.Architecture(Architecture(..),arch_x86,arch_x86_64,arch_arm,hostArch,architectures) where import Specialize.Types-import PCode.Instruction-import My.Control.Monad.TimeLine-import Data.Ord-import Data.Word-import Data.Set as S+import Specialize.X86_64 instance Eq Architecture where a == a' = archName a == archName a' instance Show Architecture where show a = "#<Arch:"++archName a++">" +undef s = error $ "undefined ("++s++")"+ architectures = [hostArch,arch_x86,arch_x86_64,arch_arm]-nullArch = Arch undefined undefined undefined undefined undefined+nullArch = Arch undefined undefined (undef "initials") (undef "compile") arch_x86 = nullArch { archName = "x86", archDefaultSize = 4 }-arch_x86_64 = nullArch { archName = "x86_64", archDefaultSize = 8 } arch_arm = nullArch { archName = "arm", archDefaultSize = 4 } hostArch = arch_x86_64 { archName = "host" }
src/Specialize/Types.hs view
@@ -2,36 +2,46 @@ module Specialize.Types( module Data.Word, module My.Control.Monad.TimeLine, module PCode, module ID,- Register(..),Address(..), + Register(..), Architecture(..), - Past(..),Future(..),- Allocate(..)) where+ Info(..), Past(..),Future(..),+ stackF,bindingsF, emptyFuture) where +import Data.Relation import Data.ByteString import Data.Word import My.Control.Monad.TimeLine+import My.Control.Monad.State+import Control.Monad.Trans.Reader import PCode import ID import Data.Map import Data.Set type Register = Int-type Address = (Maybe ID,Int) data Architecture = Arch {- archName :: String,- archDefaultSize :: Int,- archInitialPast :: [BindVar] -> Past,- archCompileCase :: [Int] -> (Int -> ((Int,Int),Past)) -> AllocInstr,- archCompileBuiltin :: Builtin -> ID -> [Value] -> AllocInstr+ archName :: String,+ archDefaultSize :: Int,+ archInitials :: [BindVar] -> BindVar -> (Past,Future),+ archCompileInstr :: Instruction -> ReaderT Info (TimeLine Past Future) (Int,Int,IO ByteString) } data Past = Past { - addresses :: Map ID Address,- bindings :: Map ID Register,- clobber :: Map ID [ID],- stack :: [(Bool,Int)]+ registers :: Map ID Register,+ stackAddrs :: Map ID Int,+ stack :: [(Bool,Int)] } data Future = Future {- fregs :: Map ID Register+ fregisters :: Map ID Register }-type Allocate = TimeLine Past Future-type AllocInstr = Monad m => Allocate (Int,m ByteString)+data Info = Info {+ idValue :: ID -> IO Int,+ bindings :: Map ID (ID,Int),+ actives :: Set ID,+ clobbers :: Relation ID ID,+ branchPos :: Int -> (Int,Int,Maybe Past)+ }++stackF = Field (stack,\s p -> p { stack = s })+bindingsF = Field (bindings,\a p -> p { bindings = a })++emptyFuture = Future Data.Map.empty
− src/Specialize/X86.hs
@@ -1,4 +0,0 @@-module Specialize.X86 where--specializeInstr (Op b vs v) info = do-
+ src/Specialize/X86_64.hs view
@@ -0,0 +1,96 @@+{-# LANGUAGE RankNTypes, ViewPatterns #-}+module Specialize.X86_64(arch_x86_64) where++import Specialize.Types+import Control.Monad+import qualified Data.ByteString as B+import Data.Bits+import My.Data.List+import Data.Char+import Data.Maybe+import Data.Ord++import My.Prelude++defSize = 8+arch_x86_64 = Arch "x86_64" defSize defaults compile++fromFields fs = foldl1 xor (zipWith shiftL (map (fromIntegral . fst) fs) (scanl (+) 0 $ map snd fs))++showHex n = reverse $ map (intToDigit . fromIntegral . (`mod`16)) $ take 2 $ iterate (`div`16) (n :: Word8)+showCode = intercalate " " . map showHex++argBytes :: Int -> Int -> (Maybe Integer) -> ([Word8],[Word8])+argBytes = argBytesWide True+argBytesWide w r rm arg = (pre,suf)+ where pre = if rex/=0x40 then [rex] else []+ where rex = fromFields [(rm`shiftR`3,1),(0,1),(r`shiftR`3,1),(fromEnum w,1),(4,4)]+ suf = [fromFields [(rm.&.7,3),(r.&.7,3),(mode,2)]] ++ sib ++ index+ (mode,index) = maybe (3,[]) fun arg+ where fun n | n == 0 = if rm.&.7==5 then (1,[0]) else (0,[])+ | n <= 128 && n > -128 = (1,[fromIntegral n])+ | otherwise = (2,take 4 $ map (fromIntegral . (.&.255)) $ iterate (`shiftR`8) n)+ sib | mode/=3 && (rm.&.7 == 4) = [fromFields [(4,3),(4,3),(0,2)]]+ | otherwise = []++[rax,rbx,rsp,rbp,r8,r12] = [0,3,4,5,8,12] :: [Int]++op code d a b | d==b = op d a+ | otherwise = mov d a++op d b+ where op d a = pre++code++suf+ where (pre,suf) = argBytes d a Nothing+opi codes d a n = mov d a ++ pre++[code]++suf++imm+ where (code,r,imm) = codes (n :: Integer)+ (pre,suf) = argBytes r d Nothing+codeFun codes n = head [(code,r,take s chop) | (s,(code,r)) <- codes, s>=size]+ where size = length $ takeWhile (>0) divs+ chop = map (.&.255) divs+ divs = map fromIntegral $ iterate (`shiftR`8) n++mov d s | d==s = []+ | otherwise = pre++[0x8B]++suf+ where (pre,suf) = argBytes d s Nothing+movi d 0 = op [0x33] d d d+movi d n = pre++[code]++suf++imm+ where (code,r,imm) = codeFun [(4,(0xC7,0)),(8,(0xB8`xor`(fromIntegral d.&.7),0))] n+ (pre,suf) | code==0xC7 = argBytes 0 d Nothing+ | otherwise = (fst $ argBytes d 0 Nothing,[])+ld d (s,n,size) = load+ where szs = maximumBy (comparing weight) $ permutations [sz | sz <- [8,4,2,1], sz.&.size /= 0]+ where weight l = sum $ zipWith f l $ sums l+ where f s i = fromJust $ findIndex (\p -> m.&.p==0) $ iterate (`shiftR`1) s+ where m = s-((n+i)`mod`s)+ load = concat $ zipWith ld (reverse $ zip (sums szs) szs) (True:repeat False)+ ld (i,sz) fst = sh sz++code++suf+ where (pre,suf) = argBytesWide (sz==8) d s (Just (n+i))+ code = pre++fromJust (lookup sz [(8,[0x8b]),(4,[0x8b]),(2,[0x66,0x8b]),(1,[0x8a])])+ sh sz | fst||sz==8 = []+ | otherwise = shli d d (sz*8)++st (d,n,size) s = store+ where szs = maximumBy (comparing weight) $ permutations [sz | sz <- [8,4,2,1], sz.&.size /= 0]+ where weight l = sum $ zipWith f l $ sums l+ where f s i = fromJust $ findIndex (\p -> m.&.p==0) $ iterate (`shiftR`1) s+ where m = s-((n+i)`mod`s)+ store = concat $ reverse $ zipWith st (reverse $ zip (sums szs) szs) (True:repeat False)+ st (i,sz) lst = code++suf++sh sz+ where (pre,suf) = argBytesWide (sz==8) s d (Just (n+i))+ code = pre++fromJust (lookup sz [(8,[0x89]),(4,[0x89]),(2,[0x66,0x89]),(1,[0x88])])+ sh sz | lst = rori s s ((8-i)*8)+ | otherwise = rori s s (sz*8)++add = op [0x03]+sub = op [0x2B]+mul = op [0x0F,0xAF]+addi = opi $ codeFun [(1,(0x83,0)),(4,(0x81,0))]+subi = opi $ codeFun [(1,(0x83,5)),(4,(0x81,5))]+muli = opi $ codeFun [(1,(0x6B,0)),(8,(0x69,0))]+shli = opi $ codeFun [(1,(0xC1,4))]+shri = opi $ codeFun [(1,(0xC1,5))]+rori d s n | n==0||n==64 = []+ | otherwise = opi (codeFun [(1,(0xC1,1))]) d s n++(e,s,c) <++> (e',s',c') = (e+e',s+s',liftM2 B.append c c')++defaults args ret = undefined+compile = undefined
src/Translate.hs view
@@ -11,8 +11,8 @@ instance Translatable ID where translate = ($)-instance Translatable IDRange where- translate t (IDRange (a,b)) = IDRange (t a,t b)+instance Translatable a => Translatable (Range a) where+ translate t (Range (a,b)) = Range (translate t a,translate t b) instance Translatable e => Translatable [e] where translate tr l = map (translate tr) l instance Translatable C.Value where @@ -22,7 +22,7 @@ instance Translatable Instruction where translate tr (Op b v vs) = Op b (translate tr v) (translate tr vs) translate tr (Branch v as) = Branch (translate tr v) as- translate tr (Bind bv v) = Bind (translate tr bv) (translate tr v)+ translate tr (Bind bv v) = Bind (translate tr bv) (fmap (translate tr) v) translate tr Noop = Noop instance Translatable PCode.Value where translate tr (SymVal t id) = SymVal t (translate tr id)