summaryrefslogtreecommitdiff
path: root/Lower.hs
blob: 46aaad503f64f5fe8eb26dca3d5279025c2f438d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
{-# LANGUAGE TupleSections #-}
module Lower(lowerIR) where

import AST (Name)
import Data.List
import qualified Data.Map.Strict as Map
import Intermediate


-- Not yet regalloc'd
data AsmProgram' = AsmProgram' [(Label, [AsmInstr'])]

data AsmInstr'
    = Li Ref Int
    | Mv Ref Ref
    | Arith Arith Ref Ref Ref
    | Not Ref Ref
    | Call Ref Label
    | Jcc CCond Ref Label
    | JccR CCond Ref Ref
    | Load Int Ref Ref
    | Store Int Ref Ref

newtype Label = Label String

data Arith = Add | Sub | Mul | Div | Lt | Lte | And | Or | Xor | Sll | Slr | Sar

data CCond = CCZ | CCNZ

type GFDMap = Map.Map Name GlobFuncDef

type BId = Int


-- Calling convention:
-- Upon function entry, the stack should look as follows:
-- - Closure item 1
-- - Closure item 2
-- ...
-- - Closure item N
-- - Argument 1
-- - Arugment 2
-- ...
-- - Argument M
-- - Link register [pushed by callee]


lowerIR :: IRProgram -> AsmProgram'
lowerIR (IRProgram bbs gfds datatbl) =
    let argcmap = floodArgCount gfds bbs
    in AsmProgram' [(Label ("BB" ++ show bid), lowerBB bb gfds argcmap)
                   | bb@(BB bid _ _) <- bbs]

lowerBB :: BB -> GFDMap -> Map.Map BId Int -> [AsmInstr']
lowerBB (BB bid inss term) gfds argcmap = concatMap (\ins -> lowerIns ins gfds argcmap) inss

lowerIns :: Instruction -> GFDMap -> Map.Map BId Int -> [AsmInstr']
lowerIns (dest, instruction) gfds argcmap = case instruction of
    IAssign src -> [Mv dest src]
    IParam idx  ->  undefined

floodArgCount :: GFDMap -> [BB] -> Map.Map BId Int
floodArgCount gfds bbs = go Map.empty [(bid, n) | GlobFuncDef bid n _ <- Map.elems gfds]
  where
    bbMap :: Map.Map Int BB
    bbMap = Map.fromList [(bid, bb) | bb@(BB bid _ _) <- bbs]

    go :: Map.Map BId Int -> [(Int, Int)] -> Map.Map BId Int
    go result frontier =
        let result' = foldl' (\mp (bid, n) -> Map.insert bid n mp) result frontier
            frontier' = concat [map (,n) (nexts bid \\ Map.keys result')
                               | (bid, n) <- frontier]
        in go result' frontier'

    nexts :: BId -> [BId]
    nexts bid = case let BB _ _ term = bbMap Map.! bid in term of
        IBr _ a b -> [a, b]
        IJmp a    -> [a]
        IRet _    -> []
        IExit     -> []
        IUnknown  -> []