alpha 0.99999 → 1.0
raw patch · 12 files changed
+108/−76 lines, 12 files
Files
- alpha.cabal +1/−1
- src/Alpha.hs +12/−11
- src/Compile.hs +6/−7
- src/Compile/Utils.hs +18/−12
- src/Context.hs +6/−3
- src/My/Control/Monad/RWTL.hs +1/−0
- src/My/Data/SetBy.hs +2/−1
- src/My/Data/Tree.hs +5/−4
- src/Options.hs +34/−15
- src/PCode/Builtin.hs +1/−1
- src/Specialize.hs +4/−4
- src/Specialize/X86_64.hs +18/−17
alpha.cabal view
@@ -1,5 +1,5 @@ name: alpha-version: 0.99999+version: 1.0 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
@@ -9,7 +9,7 @@ import qualified Data.ByteString as B import qualified Data.Map as M import qualified Data.Serialize as Ser-import Elf (writeElf)+import Elf (writeElf,entryAddress) import Foreign hiding (void) import My.Control.Monad import My.Control.Monad.State hiding ((<.>))@@ -36,26 +36,27 @@ PrintVersion -> printVersion Compile -> doCompile s -version = "0.99999"+formatEntry Elf64 = entryAddress+formatEntry (Raw n) = n++version = "1.0" printHelp = putStrLn helpMsg printVersion = putStrLn $ "Alpha version "++version newtype Str = Str String instance Show Str where show (Str s) = s -doTestOlder = return True -- for testing purposes, turn makefile-style file dependencies checks on or off- doCompile opts = case programs opts of [] -> interactive progs -> mapM_ compileProgram progs where+ entry = formatEntry $ outputFmt opts languageFile language = languageDir opts</>language<.>"l" findSource language = findM doesFileExist (concat [[base<.>"a",base] | dir <- sourceDirs opts , let base = dir</>language])- readProg s = let (a,':':b) = break (==':') s in (a,b) interactive = void $ compileFile "/dev/stdin"- compileProgram (readProg -> (language,root)) = withDefaultContext $ do+ compileProgram (language,root) = withDefaultContext entry $ do importLanguage compileLanguage (const $ return ()) language l <- doF languageF get rootSym <- stateF languageF $ internSym root@@ -64,12 +65,13 @@ top <- gets compTop contents <- B.concat $< sequence [withForeignPtr ptr $ \p -> unsafePackCStringLen (castPtr p,size) | ptr <- ptrs | size <- zipWith (-) (tail addrs++[top]) addrs]- writeElf root contents+ case outputFmt opts of+ Elf64 -> writeElf root contents+ Raw _ -> B.writeFile root contents compileLanguage force name = do let langFile = languageFile name source <- findSource name- skip <- return (not force) <&&> fileExist langFile- <&&> maybe (return True) (\s -> langFile `newerThan` s) source+ 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++"..."@@ -79,13 +81,12 @@ return lang return (not skip,l) - compileFile src = withDefaultContext $ (>> gets language) $ do+ 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 } where compileExpr expr = do- debug expr `seq` return () symExpr <- languageState $ envCast expr trExpr <- doTransform symExpr (code,imports) <- languageState $ compile [] Nothing trExpr
src/Compile.hs view
@@ -46,7 +46,7 @@ sequence_ [createEdge TimeDep n' n | (_,l) <- code, n' <- l] return (SymVal Value dest,(n:concatMap fst code,[n])) -compileBuiltin _ _ [] = nullCodeVal (IntVal 0)+compileBuiltin _ dest [] = compileValue dest (IntVal 0) compileBuiltin b dest args = compileBy (Op b) dest args compileCall = compileBuiltin BCall @@ -94,7 +94,11 @@ compile' Nothing arg *>>= \v -> makeBackBranch v alts compileAxiom XVerb dest [Group (name:args),expr] = do- (sym,code) <- compileBody args name expr+ bv@BindVar { bindSym = sym } <- bindFromSyntax name+ ret <- case bindSubs bv of+ [] -> newVar >>= \ret -> return bv { bindSym = ret }+ (h,_):_ -> return h + code <- compileExpr args (Just ret) expr lift $ modify $ exportSymVal sym (Verb code) compile' dest (Symbol sym) compileAxiom XVerb dest [Symbol s,Symbol a] = do@@ -122,11 +126,6 @@ (code,imps) <- lift $ compile args ret expr modifyF importsF (imps++) return code-compileBody args retBind body = do- bv <- bindFromSyntax retBind- ret <- newVar- code <- compileExpr args (Just bv { bindSym = ret }) body- return (bindSym bv,code) compileValue dest val = do c <- singleCode $< case dest of Just v -> createNode (Instr $ set v val)
src/Compile/Utils.hs view
@@ -2,28 +2,34 @@ module Compile.Utils where import Compile.State as CS-import qualified My.Data.Graph as G-import My.Prelude+import Data.Array+import Data.Function+import Data.Maybe+import qualified Data.Map as M+import qualified Data.Set as S import My.Control.Monad import My.Control.Monad.State+import qualified My.Data.Graph as G import My.Data.List import My.Data.Tree--import qualified Data.Map as M-import qualified Data.Set as S-import Data.Function-import Data.Maybe+import My.Prelude import PCode import Syntax - import Translate -import Debug.Trace+flattenable code = map (f . instr) code'+ where f (Branch v alts) = Branch v (map (a!) alts)+ f i = i+ (bounds,instr,nexts,_) = navigate code+ t = spanningTree 0 nexts ; code' = flatten t+ a = array bounds (zip code' [0..]) uniquify a r [] = uniquify a r [ret]-uniquify args ret code = flatten $< descendM uniq (M.fromList $ zip syms syms) $ spanningTree 0 nexts+uniquify args ret code = do+ ret <- descendM uniq (M.fromList $ zip syms syms) $ spanningTree 0 nexts+ return (flatten ret) where syms = concatMap bindSyms $ maybe id (:) ret args- (_,instr,nexts,_) = navigate code+ (_,instr,nexts,_) = navigate $ flattenable code uniq (instr -> Bind bv v) m = do news <- mapM (const $ state createSym) (bindSyms bv) let m' = foldr (uncurry M.insert) m (zip (bindSyms bv) news)@@ -32,7 +38,7 @@ localVal m (SymVal t s) | (t==Value || t==Address) && not (M.member s m) = SymVal GValue s localVal m v = v translateBy m s = fromMaybe s $ M.lookup s m- withLocals m (Op b v vs) = (Op b v (map (localVal m) vs),M.insert v v m)+ withLocals m (Op b v vs) = (Op b v (map (localVal m) vs),M.insertWith (flip const) v v m) withLocals m (Branch v a) = (Branch (localVal m v) a,m) withLocals m i = (i,m)
src/Context.hs view
@@ -76,6 +76,9 @@ foreign export ccall "createSym_" createSym_ :: IO ID foreign import ccall "&createSym_" createSym_ptr :: FunPtr (IO ID) createSym_ = stateF languageF createSym+foreign export ccall "numSym_" numSym_ :: Int -> IO ID+foreign import ccall "&numSym_" numSym_ptr :: FunPtr (Int -> IO ID)+numSym_ = stateF languageF . internSym . show foreign export ccall "allocate_" allocate_ :: Int -> IO (Ptr ()) foreign import ccall "&allocate_" allocate_ptr :: FunPtr (Int -> IO (Ptr ()))@@ -110,6 +113,7 @@ ("alpha/c@" , Right $ exportAlpha callStub1 compAddr_ptr), ("alpha/create-symbol" , Right $ exportAlpha callStub0 createSym_ptr),+ ("alpha/number-symbol" , Right $ exportAlpha callStub1 numSym_ptr), ("alpha/symbol-name" , Right $ exportAlpha callStub1 symName_ptr), ("alpha/name-symbol" , Right $ exportAlpha callStub1 nameSym_ptr), @@ -120,7 +124,6 @@ ("alpha/print-OK" , Right $ exportAlpha callStub0 printOK_ptr), ("alpha/print-num" , Right $ exportAlpha callStub1 printNum_ptr)- ] doTransform syn = gets transform >>= ($syn) . maybe return tr @@ -152,7 +155,7 @@ 1 -> do liftM (Symbol . ID) $ peek p' -initialContext = C lang jitA M.empty (fromIntegral entryAddress) Nothing+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 <- stateF fstF (internSym s)@@ -160,7 +163,7 @@ Left v -> modifyF fstF (setSymVal i v) Right p -> modifyF sndF (M.insert i p) -withDefaultContext = withState initialContext+withDefaultContext = withState . initialContext contextState sta = (runState sta $< readIORef contextRef) >>= \(a,s') -> writeIORef contextRef s' >> return a languageState = contextState . doF languageF
src/My/Control/Monad/RWTL.hs view
@@ -24,6 +24,7 @@ where (p',f'',a,w) = runRWTL tl r p f' (p'',f',b,w') = runRWTL (cc a) r p' f return a = RWTL (\r p f -> (p,f,a,mempty))+ -- the Monoid constraint is not necesary if you want to be precise, -- but the alternative to liftM would be extremely ugly instance Monoid w => Functor (RWTL r w p f) where
src/My/Data/SetBy.hs view
@@ -2,7 +2,7 @@ ,empty,fromList,fromAscList ,null ,toList,toAscList- ,insert,delete,member+ ,insert,delete,deleteMany,member ,findMin ,partition ,union) where@@ -35,6 +35,7 @@ insert e (SetBy cmp t) = SetBy cmp (AVL.push (cmp e) e t) delete e (SetBy cmp t) = SetBy cmp (fromMaybe t $ fmap snd $ AVL.tryPop (cmp e) t)+deleteMany l s = foldr delete s l member e (SetBy cmp t) = isJust $ AVL.tryRead t (cmp e) findMin (SetBy _ t) = AVL.assertReadL t
src/My/Data/Tree.hs view
@@ -8,10 +8,11 @@ import qualified Data.Set as S import Control.Monad.State -nubT t = evalState (unfoldTreeM unfold t) S.empty- where unfold (Node a subs) = do- modify (S.insert a) ; s <- get- return (a,[sub | sub <- subs, not (S.member (rootLabel sub) s)]) +nubT t = head $ evalState (nubNode t) S.empty+ where nubNode (Node a subs) = gets (S.member a) >>= \b -> if b then return [] else do+ modify (S.insert a)+ subs <- mapM nubNode subs+ return [Node a (concat subs)] iterateT seed f = unfoldTree (\a -> (a,f a)) seed branches (Node a []) = [[a]]
src/Options.hs view
@@ -1,4 +1,4 @@-module Options (Architecture(..),Action(..),Settings(..),helpMsg,getSettings) where+module Options (Architecture(..),Action(..),Settings(..),Format(..),helpMsg,getSettings) where import Specialize.Architecture import System.Console.GetOpt@@ -9,50 +9,69 @@ | SourceDir FilePath | Program FilePath | LanguageDir FilePath - | Architecture Architecture + | Architecture Architecture+ | Format Format deriving Show data Action = PrintHelp | PrintVersion | Compile deriving Show-+data Format = Elf64 | Raw Int+ deriving Show data Settings = Settings { action :: Action, sourceDirs :: [FilePath], languageDir :: FilePath,- programs :: [FilePath],- outputArch :: Architecture+ programs :: [(String,String)],+ outputArch :: Architecture,+ outputFmt :: Format } deriving Show +splitArg s = case break (==':') s of+ (a,':':b) -> a:splitArg b+ ("","") -> []+ (a,"") -> [a]+ options = - [Option ['h'] ["help"] (NoArg Help) + [Option ['h','?'] ["help"] (NoArg Help) "prints usage information" ,Option ['v'] ["version"] (NoArg Version) "prints Alpha's version information" ,sep- ,Option ['S'] ["source-dir"] (ReqArg SourceDir "DIR") - "adds DIR to the list of directories searched for sources"- ,Option ['L'] ["language-dir"] (ReqArg LanguageDir "DIR") - "casts all languages in DIR (default '.')"+ ,Option ['S'] ["source-dir"] (ReqArg SourceDir "<dir>") + "adds <dir> to the list of directories searched for source files"+ ,Option ['L'] ["language-dir"] (ReqArg LanguageDir "<dir>") + "writes and seeks all language files in <dir> (defaults to the current directory)" ,sep- ,Option ['a'] ["architecture"] (ReqArg (Architecture . str2arch) "ARCH") - $ "specializes for ARCH instead of the local architecture (ARCH is one of "++foldr glue "" (tails archNames)++")"+ ,Option ['a'] ["architecture"] (ReqArg (Architecture . str2arch) "<arch>") + $ "specializes for <arch> instead of the host architecture (<arch> can be one of "++foldr glue "" (tails archNames)++")"+ ,Option ['f'] ["format"] (ReqArg (Format . str2fmt) "<fmt>")+ $ "writes the output programs in the specified format (<fmt> can be one of elf64 or \n"+ ++"raw:<n> where <n> is the start address)" ] where str2arch s = fromMaybe (error $ "Invalid architecture name "++s) $ lookup s $ zip archNames architectures+ str2fmt s = case splitArg s of+ ["elf64"] -> Elf64+ ["raw",n] -> Raw (read n)+ _ -> error ("Invalid format argument "++show s) archNames = map archName architectures glue [a] _ = a glue [a,_] t = a++" or "++t glue (a:_) t = a++", "++t sep = Option [] [] undefined "-----------------"-helpMsg = usageInfo "Usage: Alpha <options> <files>" options+helpMsg = usageInfo "Usage: alpha (<option>|<language>:<symbol>)..." options -defaultSettings progs = Settings Compile ["."] "." progs hostArch+defaultSettings progs = Settings Compile ["."] "." (map readProg progs) hostArch Elf64+ where readProg p = case splitArg p of+ [l,s] -> (l,s)+ _ -> error $ "Ill-formed argument '"++p++"'. Should be of the form <language>:<symbol>" getSettings [] = Right $ defaultSettings [] getSettings args = case getOpt Permute options args of- (opts,mods,[]) -> Right $ foldl handleOpt (defaultSettings mods) opts+ (opts,progs,[]) -> Right $ foldl handleOpt (defaultSettings progs) opts (_,_,err) -> Left $ helpMsg ++ concatMap ("\n"++) err where handleOpt s Help = s { action = PrintHelp } handleOpt s Version = s { action = PrintVersion } handleOpt s (SourceDir d) = s { sourceDirs = d : sourceDirs s } handleOpt s (LanguageDir d) = s { languageDir = d } handleOpt s (Architecture a) = s { outputArch = a }+ handleOpt s (Format f) = s { outputFmt = f }
src/PCode/Builtin.hs view
@@ -8,7 +8,7 @@ | BSet | BSetSX deriving (Show,Eq) -isBinOp b = b/=BCall && b/=BSet && b/=BNot+isBinOp b = b`elem`[BCall,BSet,BSetSX,BNot] bNames = [(BAdd,"+"),(BMul,"*"),(BSub,"-"),(BDiv,"/"),(BMod,"%"), (BLowerThan,"<"),(BGreaterThan,">"),(BLowerEq,"<="),(BGreaterEq,">="),
src/Specialize.hs view
@@ -55,11 +55,11 @@ nextFuture i f = snd4 $ runInstr i undefined f (const Nothing) gens = array bounds $ zip (flatten codeTree) [0..] gens' = array bounds $ zip [0..] (flatten codeTree)- getPast g i | g >= gens!i = Just $ fst $ instrs!#i- | otherwise = Nothing+ getPast g i | g == maximum (filter (<=(gens!i)) $ map (gens!) $ prevs i) = Nothing+ | otherwise = Just $ fst $ instrs!i instrs = array bounds $ flatten $ descend desc past codeTree where desc i p = ((i,(p,c)),p')- where ~(p',_,_,c) = runInstr i p (snd $ futures!g!#i) (getPast g)+ where ~(p',_,_,c) = runInstr i p (snd $ futures!g!i) (getPast g) g = gens!i futures = fmap snd $ listArray bounds $ iterate nextFut (1,initial) where initial = execState (sequence_ [changeFuture i 0 (futureOf i) | i <- map last (branches codeTree)])@@ -68,7 +68,7 @@ | otherwise = emptyFuture nextFut (g,fa) = (g+1,fa') where fa' = execState (sequence_ [changeFuture i g newFut | i <- prevs instr, head (nexts i)==instr]) fa- instr = gens'!g ; newFut = Future $ registers $ fst (instrs!#instr)+ instr = gens'!g ; newFut = Future $ registers $ fst (instrs!instr) changeFuture i g f = puti i (g,f) >> mapM_ propagate (prevs i) propagate i = do let j = head (nexts i)
src/Specialize/X86_64.hs view
@@ -210,7 +210,7 @@ (Left r,Left r') -> rr dest r r' (Left r,Right v) -> ri dest r v (Right v,Left r) -> ir dest v r- (Right (s,n),Right (s',n')) -> movi dest (max s s',liftM2 ii n n')+ (Right (s,n),Right (s',n')) -> movi dest (min s s',liftM2 ii n n') argVal (IntVal n) = Right $ withSize n argVal (SymVal Size s) = Right $ withSize $ fromMaybe defSize $ M.lookup s (sizes ?info)@@ -315,31 +315,30 @@ $ mfilter (`SB.member` free) (BM.lookup s regs) argAlloc (_,Just r) = return (Left $ Right r) argNew = leftK (allocReg <|||> return)- modify $ \s -> foldr SB.delete s fixed+ modify $ SB.deleteMany fixed alls <- mapM argAlloc args- modify $ \s -> foldr SB.delete s [r | Left (Right r) <- alls]+ modify $ SB.deleteMany [r | Left (Right r) <- alls] allocs <- mapM argNew alls let assocs = filter (\(r,arg,_) -> not $ (myWorkIsDone r ||| const False) (argVal arg)) $ lefts [left (,arg,bind arg) all | all <- allocs | (arg,_) <- args]- bind arg = argValSym arg >>= binding+ where bind (SymVal t s) | t`elem`[Value,Address] = binding s+ bind _ = Nothing groups = classesBy ((==)`on`parent) assocs parent (_,_,b) = fmap fst b myWorkIsDone r s = BM.pairMember (s,r) regs loadGroup g = do base <- loadRoot (parent $ head g) mapM_ (load base) g- where load base (r,arg,b) = lift regInfo >>= \(regs,_) -> do- when (BM.memberR r regs) (storeRegs [r])- lift $ case argVal arg of- Right v -> movi r v- Left s -> case lookupRegIn regs s of- Just r' -> mov r r'- Nothing -> do- n <- maybe (stackAddr (varSize s) s) return $ fmap snd b- if symValType arg == Value- then ld r (base,fi n,fi (varSize s))- else lea r base (fi n)- lift $ associate r ((Just ||| const Nothing) $ argVal arg) + where load base (r,arg,b) = do+ storeRegs [r] ; lift $ do+ case argVal arg of+ Right v -> movi r v+ Left s -> regInfo >>= \(regs,_) -> case (lookupRegIn regs s,symValType arg) of+ (Just r',Value) -> mov r r'+ (_,t) -> maybe (stackAddr (varSize s) s) return (fmap snd b) >>= \n -> case t of+ Value -> ld r (base,fi n,fi (varSize s))+ Address -> lea r base (fi n)+ associate r $ (Just ||| const Nothing) (argVal arg) mapM_ loadGroup groups return allocs@@ -389,7 +388,9 @@ storeRegs [r | (s,r) <- BM.toList regs, not (isActive s), isJust (binding s)] lift $ modifyF registersF (BM.filter (const . isActive)) compile' (Branch v alts) = withFreeSet $ do- let alignPast i = listening $ maybe doNothing (preserve . alignWith . registers) (instrPast i)+ let alignPast i = listening $ maybe doNothing (\p -> preserve $ do+ lift $ putF frameF (frame p)+ alignWith $ registers p) (instrPast i) jmpc short long (BC ~(e,s,_)) (BC ~(e',s',_)) = BC (length long+4,length code,return $ B.pack code) where de = e'-e ; ds = s'-s code | de==0 = []