Fix scoped type variables for expression type signatures
[ghc-hetmet.git] / compiler / cmm / CmmUtils.hs
1 -----------------------------------------------------------------------------
2 --
3 -- Cmm utilities.
4 --
5 -- (c) The University of Glasgow 2004
6 --
7 -----------------------------------------------------------------------------
8
9 module CmmUtils( 
10         CmmStmts, noStmts, oneStmt, mkStmts, plusStmts, stmtList,
11         isNopStmt,
12
13         isTrivialCmmExpr, hasNoGlobalRegs,
14
15         cmmRegOff, cmmLabelOff, cmmOffset, cmmOffsetLit, cmmIndex,
16         cmmOffsetExpr, cmmIndexExpr, cmmLoadIndex,
17
18         mkIntCLit, zeroCLit,
19
20         mkLblExpr,
21   ) where
22
23 #include "HsVersions.h"
24
25 import CLabel           ( CLabel )
26 import Cmm
27 import MachOp
28 import OrdList
29 import Outputable
30
31 ---------------------------------------------------
32 --
33 --      CmmStmts
34 --
35 ---------------------------------------------------
36
37 type CmmStmts = OrdList CmmStmt
38
39 noStmts :: CmmStmts
40 noStmts = nilOL
41
42 oneStmt :: CmmStmt -> CmmStmts
43 oneStmt = unitOL
44
45 mkStmts :: [CmmStmt] -> CmmStmts
46 mkStmts = toOL
47
48 plusStmts :: CmmStmts -> CmmStmts -> CmmStmts
49 plusStmts = appOL
50
51 stmtList :: CmmStmts -> [CmmStmt]
52 stmtList = fromOL
53
54
55 ---------------------------------------------------
56 --
57 --      CmmStmt
58 --
59 ---------------------------------------------------
60
61 isNopStmt :: CmmStmt -> Bool
62 -- If isNopStmt returns True, the stmt is definitely a no-op;
63 -- but it might be a no-op even if isNopStmt returns False
64 isNopStmt CmmNop                       = True
65 isNopStmt (CmmAssign r e)              = cheapEqReg r e
66 isNopStmt (CmmStore e1 (CmmLoad e2 _)) = cheapEqExpr e1 e2
67 isNopStmt s                            = False
68
69 cheapEqExpr :: CmmExpr -> CmmExpr -> Bool
70 cheapEqExpr (CmmReg r)      e                 = cheapEqReg r e
71 cheapEqExpr (CmmRegOff r 0) e                 = cheapEqReg r e
72 cheapEqExpr (CmmRegOff r n) (CmmRegOff r' n') = r==r' && n==n'
73 cheapEqExpr e1              e2                = False
74
75 cheapEqReg :: CmmReg -> CmmExpr -> Bool
76 cheapEqReg r (CmmReg r')      = r==r'
77 cheapEqReg r (CmmRegOff r' 0) = r==r'
78 cheapEqReg r e                = False
79
80 ---------------------------------------------------
81 --
82 --      CmmExpr
83 --
84 ---------------------------------------------------
85
86 isTrivialCmmExpr :: CmmExpr -> Bool
87 isTrivialCmmExpr (CmmLoad _ _)   = False
88 isTrivialCmmExpr (CmmMachOp _ _) = False
89 isTrivialCmmExpr (CmmLit _)      = True
90 isTrivialCmmExpr (CmmReg _)      = True
91 isTrivialCmmExpr (CmmRegOff _ _) = True
92
93 hasNoGlobalRegs :: CmmExpr -> Bool
94 hasNoGlobalRegs (CmmLoad e _)              = hasNoGlobalRegs e
95 hasNoGlobalRegs (CmmMachOp _ es)           = all hasNoGlobalRegs es
96 hasNoGlobalRegs (CmmLit _)                 = True
97 hasNoGlobalRegs (CmmReg (CmmLocal _))      = True
98 hasNoGlobalRegs (CmmRegOff (CmmLocal _) _) = True
99 hasNoGlobalRegs _ = False
100
101 ---------------------------------------------------
102 --
103 --      Expr Construction helpers
104 --
105 ---------------------------------------------------
106
107 cmmOffsetExpr :: CmmExpr -> CmmExpr -> CmmExpr
108 -- assumes base and offset have the same MachRep
109 cmmOffsetExpr e (CmmLit (CmmInt n _)) = cmmOffset e (fromInteger n)
110 cmmOffsetExpr e byte_off = CmmMachOp (MO_Add (cmmExprRep e)) [e, byte_off]
111
112 -- NB. Do *not* inspect the value of the offset in these smart constructors!!!
113 --
114 -- because the offset is sometimes involved in a loop in the code generator
115 -- (we don't know the real Hp offset until we've generated code for the entire
116 -- basic block, for example).  So we cannot eliminate zero offsets at this
117 -- stage; they're eliminated later instead (either during printing or
118 -- a later optimisation step on Cmm).
119 --
120 cmmOffset :: CmmExpr -> Int -> CmmExpr
121 cmmOffset (CmmReg reg)      byte_off = cmmRegOff reg byte_off
122 cmmOffset (CmmRegOff reg m) byte_off = cmmRegOff reg (m+byte_off)
123 cmmOffset (CmmLit lit)      byte_off = CmmLit (cmmOffsetLit lit byte_off)
124 cmmOffset (CmmMachOp (MO_Add rep) [expr, CmmLit (CmmInt byte_off1 _rep)]) byte_off2
125   = CmmMachOp (MO_Add rep) 
126               [expr, CmmLit (CmmInt (byte_off1 + toInteger byte_off2) rep)]
127 cmmOffset expr byte_off
128   = CmmMachOp (MO_Add rep) [expr, CmmLit (CmmInt (toInteger byte_off) rep)]
129   where
130     rep = cmmExprRep expr
131
132 -- Smart constructor for CmmRegOff.  Same caveats as cmmOffset above.
133 cmmRegOff :: CmmReg -> Int -> CmmExpr
134 cmmRegOff reg byte_off = CmmRegOff reg byte_off
135
136 cmmOffsetLit :: CmmLit -> Int -> CmmLit
137 cmmOffsetLit (CmmLabel l)      byte_off = cmmLabelOff   l byte_off
138 cmmOffsetLit (CmmLabelOff l m) byte_off = cmmLabelOff   l (m+byte_off)
139 cmmOffsetLit (CmmInt m rep)    byte_off = CmmInt (m + fromIntegral byte_off) rep
140 cmmOffsetLit other             byte_off = pprPanic "cmmOffsetLit" (ppr byte_off)
141
142 cmmLabelOff :: CLabel -> Int -> CmmLit
143 -- Smart constructor for CmmLabelOff
144 cmmLabelOff lbl 0        = CmmLabel lbl
145 cmmLabelOff lbl byte_off = CmmLabelOff lbl byte_off
146
147 -- | Useful for creating an index into an array, with a staticaly known offset.
148 cmmIndex :: MachRep -> CmmExpr -> Int -> CmmExpr
149 cmmIndex rep base idx = cmmOffset base (idx * machRepByteWidth rep)
150
151 -- | Useful for creating an index into an array, with an unknown offset.
152 cmmIndexExpr :: MachRep -> CmmExpr -> CmmExpr -> CmmExpr
153 cmmIndexExpr rep base (CmmLit (CmmInt n _)) = cmmIndex rep base (fromInteger n)
154 cmmIndexExpr rep base idx =
155   cmmOffsetExpr base byte_off
156   where
157     idx_rep = cmmExprRep idx
158     byte_off = CmmMachOp (MO_Shl idx_rep) [
159                   idx, CmmLit (mkIntCLit (machRepLogWidth rep))]
160
161 cmmLoadIndex :: MachRep -> CmmExpr -> Int -> CmmExpr
162 cmmLoadIndex rep expr ix = CmmLoad (cmmIndex rep expr ix) rep
163
164 ---------------------------------------------------
165 --
166 --      Literal construction functions
167 --
168 ---------------------------------------------------
169
170 mkIntCLit :: Int -> CmmLit
171 mkIntCLit i = CmmInt (toInteger i) wordRep
172
173 zeroCLit :: CmmLit
174 zeroCLit = CmmInt 0 wordRep
175
176 mkLblExpr :: CLabel -> CmmExpr
177 mkLblExpr lbl = CmmLit (CmmLabel lbl)