{-# LANGUAGE GADTs #-}
module CmmSwitch (
SwitchTargets,
mkSwitchTargets,
switchTargetsCases, switchTargetsDefault, switchTargetsRange, switchTargetsSigned,
mapSwitchTargets, switchTargetsToTable, switchTargetsFallThrough,
switchTargetsToList, eqSwitchTargetWith,
SwitchPlan(..),
targetSupportsSwitch,
createSwitchPlan,
) where
import GhcPrelude
import Outputable
import DynFlags
import Hoopl.Label (Label)
import Data.Maybe
import Data.List (groupBy)
import Data.Function (on)
import qualified Data.Map as M
maxJumpTableHole :: Integer
maxJumpTableHole :: Integer
maxJumpTableHole = 7
minJumpTableSize :: Int
minJumpTableSize :: Int
minJumpTableSize = 5
minJumpTableOffset :: Integer
minJumpTableOffset :: Integer
minJumpTableOffset = 2
data SwitchTargets =
SwitchTargets
Bool
(Integer, Integer)
(Maybe Label)
(M.Map Integer Label)
deriving (Int -> SwitchTargets -> ShowS
[SwitchTargets] -> ShowS
SwitchTargets -> String
(Int -> SwitchTargets -> ShowS)
-> (SwitchTargets -> String)
-> ([SwitchTargets] -> ShowS)
-> Show SwitchTargets
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SwitchTargets] -> ShowS
$cshowList :: [SwitchTargets] -> ShowS
show :: SwitchTargets -> String
$cshow :: SwitchTargets -> String
showsPrec :: Int -> SwitchTargets -> ShowS
$cshowsPrec :: Int -> SwitchTargets -> ShowS
Show, SwitchTargets -> SwitchTargets -> Bool
(SwitchTargets -> SwitchTargets -> Bool)
-> (SwitchTargets -> SwitchTargets -> Bool) -> Eq SwitchTargets
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SwitchTargets -> SwitchTargets -> Bool
$c/= :: SwitchTargets -> SwitchTargets -> Bool
== :: SwitchTargets -> SwitchTargets -> Bool
$c== :: SwitchTargets -> SwitchTargets -> Bool
Eq)
mkSwitchTargets :: Bool -> (Integer, Integer) -> Maybe Label -> M.Map Integer Label -> SwitchTargets
mkSwitchTargets :: Bool
-> (Integer, Integer)
-> Maybe Label
-> Map Integer Label
-> SwitchTargets
mkSwitchTargets signed :: Bool
signed range :: (Integer, Integer)
range@(lo :: Integer
lo,hi :: Integer
hi) mbdef :: Maybe Label
mbdef ids :: Map Integer Label
ids
= Bool
-> (Integer, Integer)
-> Maybe Label
-> Map Integer Label
-> SwitchTargets
SwitchTargets Bool
signed (Integer, Integer)
range Maybe Label
mbdef' Map Integer Label
ids'
where
ids' :: Map Integer Label
ids' = Map Integer Label -> Map Integer Label
dropDefault (Map Integer Label -> Map Integer Label)
-> Map Integer Label -> Map Integer Label
forall a b. (a -> b) -> a -> b
$ Map Integer Label -> Map Integer Label
restrict Map Integer Label
ids
mbdef' :: Maybe Label
mbdef' | Bool
defaultNeeded = Maybe Label
mbdef
| Bool
otherwise = Maybe Label
forall a. Maybe a
Nothing
restrict :: Map Integer Label -> Map Integer Label
restrict = (Integer, Integer) -> Map Integer Label -> Map Integer Label
forall b. (Integer, Integer) -> Map Integer b -> Map Integer b
restrictMap (Integer
lo,Integer
hi)
dropDefault :: Map Integer Label -> Map Integer Label
dropDefault | Just l :: Label
l <- Maybe Label
mbdef = (Label -> Bool) -> Map Integer Label -> Map Integer Label
forall a k. (a -> Bool) -> Map k a -> Map k a
M.filter (Label -> Label -> Bool
forall a. Eq a => a -> a -> Bool
/= Label
l)
| Bool
otherwise = Map Integer Label -> Map Integer Label
forall a. a -> a
id
defaultNeeded :: Bool
defaultNeeded = Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Map Integer Label -> Int
forall k a. Map k a -> Int
M.size Map Integer Label
ids') Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
/= Integer
hiInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
loInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+1
mapSwitchTargets :: (Label -> Label) -> SwitchTargets -> SwitchTargets
mapSwitchTargets :: (Label -> Label) -> SwitchTargets -> SwitchTargets
mapSwitchTargets f :: Label -> Label
f (SwitchTargets signed :: Bool
signed range :: (Integer, Integer)
range mbdef :: Maybe Label
mbdef branches :: Map Integer Label
branches)
= Bool
-> (Integer, Integer)
-> Maybe Label
-> Map Integer Label
-> SwitchTargets
SwitchTargets Bool
signed (Integer, Integer)
range ((Label -> Label) -> Maybe Label -> Maybe Label
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Label -> Label
f Maybe Label
mbdef) ((Label -> Label) -> Map Integer Label -> Map Integer Label
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Label -> Label
f Map Integer Label
branches)
switchTargetsCases :: SwitchTargets -> [(Integer, Label)]
switchTargetsCases :: SwitchTargets -> [(Integer, Label)]
switchTargetsCases (SwitchTargets _ _ _ branches :: Map Integer Label
branches) = Map Integer Label -> [(Integer, Label)]
forall k a. Map k a -> [(k, a)]
M.toList Map Integer Label
branches
switchTargetsDefault :: SwitchTargets -> Maybe Label
switchTargetsDefault :: SwitchTargets -> Maybe Label
switchTargetsDefault (SwitchTargets _ _ mbdef :: Maybe Label
mbdef _) = Maybe Label
mbdef
switchTargetsRange :: SwitchTargets -> (Integer, Integer)
switchTargetsRange :: SwitchTargets -> (Integer, Integer)
switchTargetsRange (SwitchTargets _ range :: (Integer, Integer)
range _ _) = (Integer, Integer)
range
switchTargetsSigned :: SwitchTargets -> Bool
switchTargetsSigned :: SwitchTargets -> Bool
switchTargetsSigned (SwitchTargets signed :: Bool
signed _ _ _) = Bool
signed
switchTargetsToTable :: SwitchTargets -> (Int, [Maybe Label])
switchTargetsToTable :: SwitchTargets -> (Int, [Maybe Label])
switchTargetsToTable (SwitchTargets _ (lo :: Integer
lo,hi :: Integer
hi) mbdef :: Maybe Label
mbdef branches :: Map Integer Label
branches)
= (Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (-Integer
start), [ Integer -> Maybe Label
labelFor Integer
i | Integer
i <- [Integer
start..Integer
hi] ])
where
labelFor :: Integer -> Maybe Label
labelFor i :: Integer
i = case Integer -> Map Integer Label -> Maybe Label
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Integer
i Map Integer Label
branches of Just l :: Label
l -> Label -> Maybe Label
forall a. a -> Maybe a
Just Label
l
Nothing -> Maybe Label
mbdef
start :: Integer
start | Integer
lo Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= 0 Bool -> Bool -> Bool
&& Integer
lo Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
minJumpTableOffset = 0
| Bool
otherwise = Integer
lo
switchTargetsToList :: SwitchTargets -> [Label]
switchTargetsToList :: SwitchTargets -> [Label]
switchTargetsToList (SwitchTargets _ _ mbdef :: Maybe Label
mbdef branches :: Map Integer Label
branches)
= Maybe Label -> [Label]
forall a. Maybe a -> [a]
maybeToList Maybe Label
mbdef [Label] -> [Label] -> [Label]
forall a. [a] -> [a] -> [a]
++ Map Integer Label -> [Label]
forall k a. Map k a -> [a]
M.elems Map Integer Label
branches
switchTargetsFallThrough :: SwitchTargets -> ([([Integer], Label)], Maybe Label)
switchTargetsFallThrough :: SwitchTargets -> ([([Integer], Label)], Maybe Label)
switchTargetsFallThrough (SwitchTargets _ _ mbdef :: Maybe Label
mbdef branches :: Map Integer Label
branches) = ([([Integer], Label)]
groups, Maybe Label
mbdef)
where
groups :: [([Integer], Label)]
groups = ([(Integer, Label)] -> ([Integer], Label))
-> [[(Integer, Label)]] -> [([Integer], Label)]
forall a b. (a -> b) -> [a] -> [b]
map (\xs :: [(Integer, Label)]
xs -> (((Integer, Label) -> Integer) -> [(Integer, Label)] -> [Integer]
forall a b. (a -> b) -> [a] -> [b]
map (Integer, Label) -> Integer
forall a b. (a, b) -> a
fst [(Integer, Label)]
xs, (Integer, Label) -> Label
forall a b. (a, b) -> b
snd ([(Integer, Label)] -> (Integer, Label)
forall a. [a] -> a
head [(Integer, Label)]
xs))) ([[(Integer, Label)]] -> [([Integer], Label)])
-> [[(Integer, Label)]] -> [([Integer], Label)]
forall a b. (a -> b) -> a -> b
$
((Integer, Label) -> (Integer, Label) -> Bool)
-> [(Integer, Label)] -> [[(Integer, Label)]]
forall a. (a -> a -> Bool) -> [a] -> [[a]]
groupBy (Label -> Label -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Label -> Label -> Bool)
-> ((Integer, Label) -> Label)
-> (Integer, Label)
-> (Integer, Label)
-> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` (Integer, Label) -> Label
forall a b. (a, b) -> b
snd) ([(Integer, Label)] -> [[(Integer, Label)]])
-> [(Integer, Label)] -> [[(Integer, Label)]]
forall a b. (a -> b) -> a -> b
$
Map Integer Label -> [(Integer, Label)]
forall k a. Map k a -> [(k, a)]
M.toList Map Integer Label
branches
eqSwitchTargetWith :: (Label -> Label -> Bool) -> SwitchTargets -> SwitchTargets -> Bool
eqSwitchTargetWith :: (Label -> Label -> Bool) -> SwitchTargets -> SwitchTargets -> Bool
eqSwitchTargetWith eq :: Label -> Label -> Bool
eq (SwitchTargets signed1 :: Bool
signed1 range1 :: (Integer, Integer)
range1 mbdef1 :: Maybe Label
mbdef1 ids1 :: Map Integer Label
ids1) (SwitchTargets signed2 :: Bool
signed2 range2 :: (Integer, Integer)
range2 mbdef2 :: Maybe Label
mbdef2 ids2 :: Map Integer Label
ids2) =
Bool
signed1 Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool
signed2 Bool -> Bool -> Bool
&& (Integer, Integer)
range1 (Integer, Integer) -> (Integer, Integer) -> Bool
forall a. Eq a => a -> a -> Bool
== (Integer, Integer)
range2 Bool -> Bool -> Bool
&& Maybe Label -> Maybe Label -> Bool
goMB Maybe Label
mbdef1 Maybe Label
mbdef2 Bool -> Bool -> Bool
&& [(Integer, Label)] -> [(Integer, Label)] -> Bool
goList (Map Integer Label -> [(Integer, Label)]
forall k a. Map k a -> [(k, a)]
M.toList Map Integer Label
ids1) (Map Integer Label -> [(Integer, Label)]
forall k a. Map k a -> [(k, a)]
M.toList Map Integer Label
ids2)
where
goMB :: Maybe Label -> Maybe Label -> Bool
goMB Nothing Nothing = Bool
True
goMB (Just l1 :: Label
l1) (Just l2 :: Label
l2) = Label
l1 Label -> Label -> Bool
`eq` Label
l2
goMB _ _ = Bool
False
goList :: [(Integer, Label)] -> [(Integer, Label)] -> Bool
goList [] [] = Bool
True
goList ((i1 :: Integer
i1,l1 :: Label
l1):ls1 :: [(Integer, Label)]
ls1) ((i2 :: Integer
i2,l2 :: Label
l2):ls2 :: [(Integer, Label)]
ls2) = Integer
i1 Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
i2 Bool -> Bool -> Bool
&& Label
l1 Label -> Label -> Bool
`eq` Label
l2 Bool -> Bool -> Bool
&& [(Integer, Label)] -> [(Integer, Label)] -> Bool
goList [(Integer, Label)]
ls1 [(Integer, Label)]
ls2
goList _ _ = Bool
False
data SwitchPlan
= Unconditionally Label
| IfEqual Integer Label SwitchPlan
| IfLT Bool Integer SwitchPlan SwitchPlan
| JumpTable SwitchTargets
deriving Int -> SwitchPlan -> ShowS
[SwitchPlan] -> ShowS
SwitchPlan -> String
(Int -> SwitchPlan -> ShowS)
-> (SwitchPlan -> String)
-> ([SwitchPlan] -> ShowS)
-> Show SwitchPlan
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SwitchPlan] -> ShowS
$cshowList :: [SwitchPlan] -> ShowS
show :: SwitchPlan -> String
$cshow :: SwitchPlan -> String
showsPrec :: Int -> SwitchPlan -> ShowS
$cshowsPrec :: Int -> SwitchPlan -> ShowS
Show
targetSupportsSwitch :: HscTarget -> Bool
targetSupportsSwitch :: HscTarget -> Bool
targetSupportsSwitch HscC = Bool
True
targetSupportsSwitch HscLlvm = Bool
True
targetSupportsSwitch _ = Bool
False
createSwitchPlan :: SwitchTargets -> SwitchPlan
createSwitchPlan :: SwitchTargets -> SwitchPlan
createSwitchPlan (SwitchTargets _signed :: Bool
_signed _range :: (Integer, Integer)
_range (Just defLabel :: Label
defLabel) m :: Map Integer Label
m)
| [(x :: Integer
x, l :: Label
l)] <- Map Integer Label -> [(Integer, Label)]
forall k a. Map k a -> [(k, a)]
M.toList Map Integer Label
m
= Integer -> Label -> SwitchPlan -> SwitchPlan
IfEqual Integer
x Label
l (Label -> SwitchPlan
Unconditionally Label
defLabel)
createSwitchPlan (SwitchTargets _signed :: Bool
_signed (lo :: Integer
lo,hi :: Integer
hi) Nothing m :: Map Integer Label
m)
| [(x1 :: Integer
x1, l1 :: Label
l1), (_x2 :: Integer
_x2,l2 :: Label
l2)] <- Map Integer Label -> [(Integer, Label)]
forall k a. Map k a -> [(k, a)]
M.toAscList Map Integer Label
m
, Integer
hi Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
lo Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== 1
= Integer -> Label -> SwitchPlan -> SwitchPlan
IfEqual Integer
x1 Label
l1 (Label -> SwitchPlan
Unconditionally Label
l2)
createSwitchPlan (SwitchTargets _signed :: Bool
_signed _range :: (Integer, Integer)
_range (Just defLabel :: Label
defLabel) m :: Map Integer Label
m)
| [(x1 :: Integer
x1, l1 :: Label
l1), (x2 :: Integer
x2,l2 :: Label
l2)] <- Map Integer Label -> [(Integer, Label)]
forall k a. Map k a -> [(k, a)]
M.toAscList Map Integer Label
m
= Integer -> Label -> SwitchPlan -> SwitchPlan
IfEqual Integer
x1 Label
l1 (Integer -> Label -> SwitchPlan -> SwitchPlan
IfEqual Integer
x2 Label
l2 (Label -> SwitchPlan
Unconditionally Label
defLabel))
createSwitchPlan (SwitchTargets signed :: Bool
signed range :: (Integer, Integer)
range mbdef :: Maybe Label
mbdef m :: Map Integer Label
m) =
SwitchPlan
plan
where
pieces :: [Map Integer Label]
pieces = (Map Integer Label -> [Map Integer Label])
-> [Map Integer Label] -> [Map Integer Label]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Map Integer Label -> [Map Integer Label]
forall a. Map Integer a -> [Map Integer a]
breakTooSmall ([Map Integer Label] -> [Map Integer Label])
-> [Map Integer Label] -> [Map Integer Label]
forall a b. (a -> b) -> a -> b
$ Integer -> Map Integer Label -> [Map Integer Label]
forall a. Integer -> Map Integer a -> [Map Integer a]
splitAtHoles Integer
maxJumpTableHole Map Integer Label
m
flatPlan :: FlatSwitchPlan
flatPlan = FlatSwitchPlan -> FlatSwitchPlan
findSingleValues (FlatSwitchPlan -> FlatSwitchPlan)
-> FlatSwitchPlan -> FlatSwitchPlan
forall a b. (a -> b) -> a -> b
$ Bool
-> Maybe Label
-> (Integer, Integer)
-> [Map Integer Label]
-> FlatSwitchPlan
mkFlatSwitchPlan Bool
signed Maybe Label
mbdef (Integer, Integer)
range [Map Integer Label]
pieces
plan :: SwitchPlan
plan = Bool -> FlatSwitchPlan -> SwitchPlan
buildTree Bool
signed (FlatSwitchPlan -> SwitchPlan) -> FlatSwitchPlan -> SwitchPlan
forall a b. (a -> b) -> a -> b
$ FlatSwitchPlan
flatPlan
splitAtHoles :: Integer -> M.Map Integer a -> [M.Map Integer a]
splitAtHoles :: Integer -> Map Integer a -> [Map Integer a]
splitAtHoles _ m :: Map Integer a
m | Map Integer a -> Bool
forall k a. Map k a -> Bool
M.null Map Integer a
m = []
splitAtHoles holeSize :: Integer
holeSize m :: Map Integer a
m = ((Integer, Integer) -> Map Integer a)
-> [(Integer, Integer)] -> [Map Integer a]
forall a b. (a -> b) -> [a] -> [b]
map (\range :: (Integer, Integer)
range -> (Integer, Integer) -> Map Integer a -> Map Integer a
forall b. (Integer, Integer) -> Map Integer b -> Map Integer b
restrictMap (Integer, Integer)
range Map Integer a
m) [(Integer, Integer)]
nonHoles
where
holes :: [(Integer, Integer)]
holes = ((Integer, Integer) -> Bool)
-> [(Integer, Integer)] -> [(Integer, Integer)]
forall a. (a -> Bool) -> [a] -> [a]
filter (\(l :: Integer
l,h :: Integer
h) -> Integer
h Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
l Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
holeSize) ([(Integer, Integer)] -> [(Integer, Integer)])
-> [(Integer, Integer)] -> [(Integer, Integer)]
forall a b. (a -> b) -> a -> b
$ [Integer] -> [Integer] -> [(Integer, Integer)]
forall a b. [a] -> [b] -> [(a, b)]
zip (Map Integer a -> [Integer]
forall k a. Map k a -> [k]
M.keys Map Integer a
m) ([Integer] -> [Integer]
forall a. [a] -> [a]
tail (Map Integer a -> [Integer]
forall k a. Map k a -> [k]
M.keys Map Integer a
m))
nonHoles :: [(Integer, Integer)]
nonHoles = Integer -> [(Integer, Integer)] -> Integer -> [(Integer, Integer)]
forall a. a -> [(a, a)] -> a -> [(a, a)]
reassocTuples Integer
lo [(Integer, Integer)]
holes Integer
hi
(lo :: Integer
lo,_) = Map Integer a -> (Integer, a)
forall k a. Map k a -> (k, a)
M.findMin Map Integer a
m
(hi :: Integer
hi,_) = Map Integer a -> (Integer, a)
forall k a. Map k a -> (k, a)
M.findMax Map Integer a
m
breakTooSmall :: M.Map Integer a -> [M.Map Integer a]
breakTooSmall :: Map Integer a -> [Map Integer a]
breakTooSmall m :: Map Integer a
m
| Map Integer a -> Int
forall k a. Map k a -> Int
M.size Map Integer a
m Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
minJumpTableSize = [Map Integer a
m]
| Bool
otherwise = [Integer -> a -> Map Integer a
forall k a. k -> a -> Map k a
M.singleton Integer
k a
v | (k :: Integer
k,v :: a
v) <- Map Integer a -> [(Integer, a)]
forall k a. Map k a -> [(k, a)]
M.toList Map Integer a
m]
type FlatSwitchPlan = SeparatedList Integer SwitchPlan
mkFlatSwitchPlan :: Bool -> Maybe Label -> (Integer, Integer) -> [M.Map Integer Label] -> FlatSwitchPlan
mkFlatSwitchPlan :: Bool
-> Maybe Label
-> (Integer, Integer)
-> [Map Integer Label]
-> FlatSwitchPlan
mkFlatSwitchPlan _ Nothing _ [] = String -> SDoc -> FlatSwitchPlan
forall a. HasCallStack => String -> SDoc -> a
pprPanic "mkFlatSwitchPlan with nothing left to do" SDoc
empty
mkFlatSwitchPlan signed :: Bool
signed Nothing _ (m :: Map Integer Label
m:ms :: [Map Integer Label]
ms)
= (Bool -> Maybe Label -> Map Integer Label -> SwitchPlan
mkLeafPlan Bool
signed Maybe Label
forall a. Maybe a
Nothing Map Integer Label
m , [ ((Integer, Label) -> Integer
forall a b. (a, b) -> a
fst (Map Integer Label -> (Integer, Label)
forall k a. Map k a -> (k, a)
M.findMin Map Integer Label
m'), Bool -> Maybe Label -> Map Integer Label -> SwitchPlan
mkLeafPlan Bool
signed Maybe Label
forall a. Maybe a
Nothing Map Integer Label
m') | Map Integer Label
m' <- [Map Integer Label]
ms ])
mkFlatSwitchPlan signed :: Bool
signed (Just l :: Label
l) r :: (Integer, Integer)
r ms :: [Map Integer Label]
ms = let ((_,p1 :: SwitchPlan
p1):ps :: [(Integer, SwitchPlan)]
ps) = (Integer, Integer)
-> [Map Integer Label] -> [(Integer, SwitchPlan)]
go (Integer, Integer)
r [Map Integer Label]
ms in (SwitchPlan
p1, [(Integer, SwitchPlan)]
ps)
where
go :: (Integer, Integer)
-> [Map Integer Label] -> [(Integer, SwitchPlan)]
go (lo :: Integer
lo,hi :: Integer
hi) []
| Integer
lo Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
hi = []
| Bool
otherwise = [(Integer
lo, Label -> SwitchPlan
Unconditionally Label
l)]
go (lo :: Integer
lo,hi :: Integer
hi) (m :: Map Integer Label
m:ms :: [Map Integer Label]
ms)
| Integer
lo Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
min
= (Integer
lo, Label -> SwitchPlan
Unconditionally Label
l) (Integer, SwitchPlan)
-> [(Integer, SwitchPlan)] -> [(Integer, SwitchPlan)]
forall a. a -> [a] -> [a]
: (Integer, Integer)
-> [Map Integer Label] -> [(Integer, SwitchPlan)]
go (Integer
min,Integer
hi) (Map Integer Label
mMap Integer Label -> [Map Integer Label] -> [Map Integer Label]
forall a. a -> [a] -> [a]
:[Map Integer Label]
ms)
| Integer
lo Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
min
= (Integer
lo, Bool -> Maybe Label -> Map Integer Label -> SwitchPlan
mkLeafPlan Bool
signed (Label -> Maybe Label
forall a. a -> Maybe a
Just Label
l) Map Integer Label
m) (Integer, SwitchPlan)
-> [(Integer, SwitchPlan)] -> [(Integer, SwitchPlan)]
forall a. a -> [a] -> [a]
: (Integer, Integer)
-> [Map Integer Label] -> [(Integer, SwitchPlan)]
go (Integer
maxInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+1,Integer
hi) [Map Integer Label]
ms
| Bool
otherwise
= String -> SDoc -> [(Integer, SwitchPlan)]
forall a. HasCallStack => String -> SDoc -> a
pprPanic "mkFlatSwitchPlan" (Integer -> SDoc
integer Integer
lo SDoc -> SDoc -> SDoc
<+> Integer -> SDoc
integer Integer
min)
where
min :: Integer
min = (Integer, Label) -> Integer
forall a b. (a, b) -> a
fst (Map Integer Label -> (Integer, Label)
forall k a. Map k a -> (k, a)
M.findMin Map Integer Label
m)
max :: Integer
max = (Integer, Label) -> Integer
forall a b. (a, b) -> a
fst (Map Integer Label -> (Integer, Label)
forall k a. Map k a -> (k, a)
M.findMax Map Integer Label
m)
mkLeafPlan :: Bool -> Maybe Label -> M.Map Integer Label -> SwitchPlan
mkLeafPlan :: Bool -> Maybe Label -> Map Integer Label -> SwitchPlan
mkLeafPlan signed :: Bool
signed mbdef :: Maybe Label
mbdef m :: Map Integer Label
m
| [(_,l :: Label
l)] <- Map Integer Label -> [(Integer, Label)]
forall k a. Map k a -> [(k, a)]
M.toList Map Integer Label
m
= Label -> SwitchPlan
Unconditionally Label
l
| Bool
otherwise
= SwitchTargets -> SwitchPlan
JumpTable (SwitchTargets -> SwitchPlan) -> SwitchTargets -> SwitchPlan
forall a b. (a -> b) -> a -> b
$ Bool
-> (Integer, Integer)
-> Maybe Label
-> Map Integer Label
-> SwitchTargets
mkSwitchTargets Bool
signed (Integer
min,Integer
max) Maybe Label
mbdef Map Integer Label
m
where
min :: Integer
min = (Integer, Label) -> Integer
forall a b. (a, b) -> a
fst (Map Integer Label -> (Integer, Label)
forall k a. Map k a -> (k, a)
M.findMin Map Integer Label
m)
max :: Integer
max = (Integer, Label) -> Integer
forall a b. (a, b) -> a
fst (Map Integer Label -> (Integer, Label)
forall k a. Map k a -> (k, a)
M.findMax Map Integer Label
m)
findSingleValues :: FlatSwitchPlan -> FlatSwitchPlan
findSingleValues :: FlatSwitchPlan -> FlatSwitchPlan
findSingleValues (Unconditionally l :: Label
l, (i :: Integer
i, Unconditionally l2 :: Label
l2) : (i' :: Integer
i', Unconditionally l3 :: Label
l3) : xs :: [(Integer, SwitchPlan)]
xs)
| Label
l Label -> Label -> Bool
forall a. Eq a => a -> a -> Bool
== Label
l3 Bool -> Bool -> Bool
&& Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ 1 Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
i'
= FlatSwitchPlan -> FlatSwitchPlan
findSingleValues (Integer -> Label -> SwitchPlan -> SwitchPlan
IfEqual Integer
i Label
l2 (Label -> SwitchPlan
Unconditionally Label
l), [(Integer, SwitchPlan)]
xs)
findSingleValues (p :: SwitchPlan
p, (i :: Integer
i,p' :: SwitchPlan
p'):xs :: [(Integer, SwitchPlan)]
xs)
= (SwitchPlan
p,Integer
i) (SwitchPlan, Integer) -> FlatSwitchPlan -> FlatSwitchPlan
forall a b. (a, b) -> SeparatedList b a -> SeparatedList b a
`consSL` FlatSwitchPlan -> FlatSwitchPlan
findSingleValues (SwitchPlan
p', [(Integer, SwitchPlan)]
xs)
findSingleValues (p :: SwitchPlan
p, [])
= (SwitchPlan
p, [])
buildTree :: Bool -> FlatSwitchPlan -> SwitchPlan
buildTree :: Bool -> FlatSwitchPlan -> SwitchPlan
buildTree _ (p :: SwitchPlan
p,[]) = SwitchPlan
p
buildTree signed :: Bool
signed sl :: FlatSwitchPlan
sl = Bool -> Integer -> SwitchPlan -> SwitchPlan -> SwitchPlan
IfLT Bool
signed Integer
m (Bool -> FlatSwitchPlan -> SwitchPlan
buildTree Bool
signed FlatSwitchPlan
sl1) (Bool -> FlatSwitchPlan -> SwitchPlan
buildTree Bool
signed FlatSwitchPlan
sl2)
where
(sl1 :: FlatSwitchPlan
sl1, m :: Integer
m, sl2 :: FlatSwitchPlan
sl2) = FlatSwitchPlan -> (FlatSwitchPlan, Integer, FlatSwitchPlan)
forall b a.
SeparatedList b a -> (SeparatedList b a, b, SeparatedList b a)
divideSL FlatSwitchPlan
sl
type SeparatedList b a = (a, [(b,a)])
consSL :: (a, b) -> SeparatedList b a -> SeparatedList b a
consSL :: (a, b) -> SeparatedList b a -> SeparatedList b a
consSL (a :: a
a, b :: b
b) (a' :: a
a', xs :: [(b, a)]
xs) = (a
a, (b
b,a
a')(b, a) -> [(b, a)] -> [(b, a)]
forall a. a -> [a] -> [a]
:[(b, a)]
xs)
divideSL :: SeparatedList b a -> (SeparatedList b a, b, SeparatedList b a)
divideSL :: SeparatedList b a -> (SeparatedList b a, b, SeparatedList b a)
divideSL (_,[]) = String -> (SeparatedList b a, b, SeparatedList b a)
forall a. HasCallStack => String -> a
error "divideSL: Singleton SeparatedList"
divideSL (p :: a
p,xs :: [(b, a)]
xs) = ((a
p, [(b, a)]
xs1), b
m, (a
p', [(b, a)]
xs2))
where
(xs1 :: [(b, a)]
xs1, (m :: b
m,p' :: a
p'):xs2 :: [(b, a)]
xs2) = Int -> [(b, a)] -> ([(b, a)], [(b, a)])
forall a. Int -> [a] -> ([a], [a])
splitAt ([(b, a)] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(b, a)]
xs Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` 2) [(b, a)]
xs
restrictMap :: (Integer,Integer) -> M.Map Integer b -> M.Map Integer b
restrictMap :: (Integer, Integer) -> Map Integer b -> Map Integer b
restrictMap (lo :: Integer
lo,hi :: Integer
hi) m :: Map Integer b
m = Map Integer b
mid
where (_, mid_hi :: Map Integer b
mid_hi) = Integer -> Map Integer b -> (Map Integer b, Map Integer b)
forall k a. Ord k => k -> Map k a -> (Map k a, Map k a)
M.split (Integer
loInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-1) Map Integer b
m
(mid :: Map Integer b
mid, _) = Integer -> Map Integer b -> (Map Integer b, Map Integer b)
forall k a. Ord k => k -> Map k a -> (Map k a, Map k a)
M.split (Integer
hiInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+1) Map Integer b
mid_hi
reassocTuples :: a -> [(a,a)] -> a -> [(a,a)]
reassocTuples :: a -> [(a, a)] -> a -> [(a, a)]
reassocTuples initial :: a
initial [] last :: a
last
= [(a
initial,a
last)]
reassocTuples initial :: a
initial ((a :: a
a,b :: a
b):tuples :: [(a, a)]
tuples) last :: a
last
= (a
initial,a
a) (a, a) -> [(a, a)] -> [(a, a)]
forall a. a -> [a] -> [a]
: a -> [(a, a)] -> a -> [(a, a)]
forall a. a -> [(a, a)] -> a -> [(a, a)]
reassocTuples a
b [(a, a)]
tuples a
last