module LinearScan
(
allocate
, BlockInfo(..)
, OpInfo(..)
, OpKind(..)
, VarId
, VarInfo(..)
, VarKind(..)
, PhysReg
) where
import Control.Monad.Trans.State
import qualified LinearScan.Blocks as LS
import qualified LinearScan.Main as LS
import qualified LinearScan.Morph as LS
import LinearScan.Blocks
( VarId
, VarKind(..)
, OpKind(..)
, PhysReg
)
data VarInfo = VarInfo
{ varId :: Either PhysReg VarId
, varKind :: VarKind
, regRequired :: Bool
}
deriving instance Eq VarKind
fromVarInfo :: VarInfo -> LS.VarInfo
fromVarInfo (VarInfo a b c) = LS.Build_VarInfo a b c
data OpInfo accType op1 op2 = OpInfo
{ opKind :: op1 -> OpKind
, opRefs :: op1 -> [VarInfo]
, moveOp :: PhysReg -> PhysReg -> State accType [op2]
, swapOp :: PhysReg -> PhysReg -> State accType [op2]
, saveOp :: PhysReg -> Maybe Int -> State accType [op2]
, restoreOp :: Maybe Int -> PhysReg -> State accType [op2]
, applyAllocs :: op1 -> [(Int, PhysReg)] -> [op2]
}
deriving instance Eq OpKind
deriving instance Show OpKind
fromOpInfo :: OpInfo accType op1 op2 -> LS.OpInfo accType op1 op2
fromOpInfo (OpInfo a b c d e f g) =
LS.Build_OpInfo a
(map fromVarInfo . b)
((runState .) . c)
((runState .) . d)
((runState .) . e)
((runState .) . f) g
data BlockInfo blk1 blk2 op1 op2 = BlockInfo
{ blockId :: blk1 -> Int
, blockSuccessors :: blk1 -> [Int]
, blockOps :: blk1 -> ([op1], [op1], [op1])
, setBlockOps :: blk1 -> [op2] -> [op2] -> [op2] -> blk2
}
fromBlockInfo :: BlockInfo blk1 blk2 op1 op2
-> LS.BlockInfo blk1 blk2 op1 op2
fromBlockInfo (BlockInfo a b c d) =
LS.Build_BlockInfo a b
(\blk -> let (x, y, z) = c blk in ((x, y), z)) d
allocate :: Int
-> BlockInfo blk1 blk2 op1 op2
-> OpInfo accType op1 op2
-> [blk1]
-> State accType (Either String [blk2])
allocate 0 _ _ _ = return $ Left "Cannot allocate with no registers"
allocate _ _ _ [] = return $ Left "No basic blocks were provided"
allocate maxReg (fromBlockInfo -> binfo) (fromOpInfo -> oinfo) blocks = do
eres <- gets (LS.linearScan maxReg binfo oinfo blocks)
case eres of
Left x -> return $ Left $ case x of
LS.ECannotSplitSingleton1 n ->
"Current interval is a singleton (err#1) (" ++ show n ++ ")"
LS.ECannotSplitSingleton2 n ->
"Current interval is a singleton (err#2) (" ++ show n ++ ")"
LS.ECannotSplitSingleton3 n ->
"Current interval is a singleton (err#3) (" ++ show n ++ ")"
LS.ECannotSplitSingleton4 n ->
"Current interval is a singleton (err#4) (" ++ show n ++ ")"
LS.ECannotSplitSingleton5 n ->
"Current interval is a singleton (err#5) (" ++ show n ++ ")"
LS.ECannotSplitSingleton6 n ->
"Current interval is a singleton (err#6) (" ++ show n ++ ")"
LS.ECannotSplitSingleton7 n ->
"Current interval is a singleton (err#7) (" ++ show n ++ ")"
LS.ENoIntervalsToSplit ->
"There are no intervals to split"
LS.ERegisterAlreadyAssigned n ->
"Register is already assigned (" ++ show n ++ ")"
LS.ERegisterAssignmentsOverlap n ->
"Register assignments overlap (" ++ show n ++ ")"
LS.EFuelExhausted -> "Fuel was exhausted"
LS.EUnexpectedNoMoreUnhandled ->
"The unexpected happened: no more unhandled intervals"
Right (z, acc) -> put acc >> return (Right z)