{-# LANGUAGE GADTs #-} module AsmTest where import Assembly import Compiler.Hoopl as Hoopl hiding ((<*>)) import Control.DeepSeq import Control.Exception import Control.Monad.Trans.State (evalStateT, gets) import Data.Foldable import qualified Data.Map as M import Data.Maybe (fromMaybe) import LinearScan import LinearScan.Hoopl import LinearScan.Hoopl.DSL import Normal () import Test.Hspec asmTestLiteral :: Int -> Program (Node IRVar) -> String -> Expectation asmTestLiteral regs program expected = do let eres = runSimpleUniqueMonad $ do x <- compile "entry" program uncurry runTest x case eres of Left err -> error $ "Allocation failed: " ++ err Right blks -> do let graph' = newGraph $!! blks let g = showGraph show graph' catch (g `shouldBe` expected) $ \e -> do let input = runSimpleUniqueMonad $ compile "entry" program putStrLn $ "---- Parsed ----\n" ++ showGraph show (fst input) putStrLn $ "---- Expecting ----\n" ++ expected putStrLn $ "---- Compiled ----\n" ++ g putStrLn "-------------------" throwIO (e :: SomeException) where runTest prog entry = go $ M.fromList $ zip (Prelude.map entryLabel blocks) [(0 :: Int)..] where GMany NothingO body NothingO = prog blocks = postorder_dfs_from body entry alloc = allocate regs (blockInfo getBlockId) opInfo $!! blocks where getBlockId :: Hoopl.Label -> Env Int getBlockId lbl = do bids <- gets envBlockIds return $ fromMaybe (error $ "Unable to find block at label " ++ show lbl) (M.lookup lbl bids) go blockIds = evalStateT alloc (newEnvState { envBlockIds = blockIds }) newBody = Data.Foldable.foldl' (flip addBlock) emptyBody newGraph xs = GMany NothingO (newBody xs) NothingO asmTest :: Int -> Program (Node IRVar) -> Program (Node (Assign VarId PhysReg)) -> Expectation asmTest regs program expected = asmTestLiteral regs program $ showGraph show $ fst $ runSimpleUniqueMonad $ compile "entry" expected