1 -----------------------------------------------------------------------------
5 -- (c) The University of Glasgow 2004-2006
7 -----------------------------------------------------------------------------
10 CmmStmts, noStmts, oneStmt, mkStmts, plusStmts, stmtList,
13 primRepCmmType, primRepForeignHint,
14 typeCmmType, typeForeignHint,
16 isTrivialCmmExpr, hasNoGlobalRegs,
18 cmmRegOff, cmmLabelOff, cmmOffset, cmmOffsetLit, cmmIndex,
19 cmmOffsetExpr, cmmIndexExpr, cmmLoadIndex,
25 maybeAssignTemp, loadArgsIntoTemps
28 #include "HsVersions.h"
30 import TyCon ( PrimRep(..) )
31 import Type ( Type, typePrimRep )
39 ---------------------------------------------------
43 ---------------------------------------------------
45 primRepCmmType :: PrimRep -> CmmType
46 primRepCmmType VoidRep = panic "primRepCmmType:VoidRep"
47 primRepCmmType PtrRep = gcWord
48 primRepCmmType IntRep = bWord
49 primRepCmmType WordRep = bWord
50 primRepCmmType Int64Rep = b64
51 primRepCmmType Word64Rep = b64
52 primRepCmmType AddrRep = bWord
53 primRepCmmType FloatRep = f32
54 primRepCmmType DoubleRep = f64
56 typeCmmType :: Type -> CmmType
57 typeCmmType ty = primRepCmmType (typePrimRep ty)
59 primRepForeignHint :: PrimRep -> ForeignHint
60 primRepForeignHint VoidRep = panic "primRepForeignHint:VoidRep"
61 primRepForeignHint PtrRep = AddrHint
62 primRepForeignHint IntRep = SignedHint
63 primRepForeignHint WordRep = NoHint
64 primRepForeignHint Int64Rep = SignedHint
65 primRepForeignHint Word64Rep = NoHint
66 primRepForeignHint AddrRep = AddrHint -- NB! AddrHint, but NonPtrArg
67 primRepForeignHint FloatRep = NoHint
68 primRepForeignHint DoubleRep = NoHint
70 typeForeignHint :: Type -> ForeignHint
71 typeForeignHint = primRepForeignHint . typePrimRep
74 ---------------------------------------------------
78 ---------------------------------------------------
80 type CmmStmts = OrdList CmmStmt
85 oneStmt :: CmmStmt -> CmmStmts
88 mkStmts :: [CmmStmt] -> CmmStmts
91 plusStmts :: CmmStmts -> CmmStmts -> CmmStmts
94 stmtList :: CmmStmts -> [CmmStmt]
98 ---------------------------------------------------
102 ---------------------------------------------------
104 isNopStmt :: CmmStmt -> Bool
105 -- If isNopStmt returns True, the stmt is definitely a no-op;
106 -- but it might be a no-op even if isNopStmt returns False
107 isNopStmt CmmNop = True
108 isNopStmt (CmmAssign r e) = cheapEqReg r e
109 isNopStmt (CmmStore e1 (CmmLoad e2 _)) = cheapEqExpr e1 e2
112 cheapEqExpr :: CmmExpr -> CmmExpr -> Bool
113 cheapEqExpr (CmmReg r) e = cheapEqReg r e
114 cheapEqExpr (CmmRegOff r 0) e = cheapEqReg r e
115 cheapEqExpr (CmmRegOff r n) (CmmRegOff r' n') = r==r' && n==n'
116 cheapEqExpr _ _ = False
118 cheapEqReg :: CmmReg -> CmmExpr -> Bool
119 cheapEqReg r (CmmReg r') = r==r'
120 cheapEqReg r (CmmRegOff r' 0) = r==r'
121 cheapEqReg _ _ = False
123 ---------------------------------------------------
127 ---------------------------------------------------
129 isTrivialCmmExpr :: CmmExpr -> Bool
130 isTrivialCmmExpr (CmmLoad _ _) = False
131 isTrivialCmmExpr (CmmMachOp _ _) = False
132 isTrivialCmmExpr (CmmLit _) = True
133 isTrivialCmmExpr (CmmReg _) = True
134 isTrivialCmmExpr (CmmRegOff _ _) = True
135 isTrivialCmmExpr (CmmStackSlot _ _) = panic "isTrivialCmmExpr CmmStackSlot"
137 hasNoGlobalRegs :: CmmExpr -> Bool
138 hasNoGlobalRegs (CmmLoad e _) = hasNoGlobalRegs e
139 hasNoGlobalRegs (CmmMachOp _ es) = all hasNoGlobalRegs es
140 hasNoGlobalRegs (CmmLit _) = True
141 hasNoGlobalRegs (CmmReg (CmmLocal _)) = True
142 hasNoGlobalRegs (CmmRegOff (CmmLocal _) _) = True
143 hasNoGlobalRegs _ = False
145 ---------------------------------------------------
147 -- Expr Construction helpers
149 ---------------------------------------------------
151 cmmOffsetExpr :: CmmExpr -> CmmExpr -> CmmExpr
152 -- assumes base and offset have the same CmmType
153 cmmOffsetExpr e (CmmLit (CmmInt n _)) = cmmOffset e (fromInteger n)
154 cmmOffsetExpr e byte_off = CmmMachOp (MO_Add (cmmExprWidth e)) [e, byte_off]
156 -- NB. Do *not* inspect the value of the offset in these smart constructors!!!
157 -- because the offset is sometimes involved in a loop in the code generator
158 -- (we don't know the real Hp offset until we've generated code for the entire
159 -- basic block, for example). So we cannot eliminate zero offsets at this
160 -- stage; they're eliminated later instead (either during printing or
161 -- a later optimisation step on Cmm).
163 cmmOffset :: CmmExpr -> Int -> CmmExpr
165 cmmOffset (CmmReg reg) byte_off = cmmRegOff reg byte_off
166 cmmOffset (CmmRegOff reg m) byte_off = cmmRegOff reg (m+byte_off)
167 cmmOffset (CmmLit lit) byte_off = CmmLit (cmmOffsetLit lit byte_off)
168 cmmOffset (CmmMachOp (MO_Add rep) [expr, CmmLit (CmmInt byte_off1 _rep)]) byte_off2
169 = CmmMachOp (MO_Add rep)
170 [expr, CmmLit (CmmInt (byte_off1 + toInteger byte_off2) rep)]
171 cmmOffset expr byte_off
172 = CmmMachOp (MO_Add width) [expr, CmmLit (CmmInt (toInteger byte_off) width)]
174 width = cmmExprWidth expr
176 -- Smart constructor for CmmRegOff. Same caveats as cmmOffset above.
177 cmmRegOff :: CmmReg -> Int -> CmmExpr
178 cmmRegOff reg byte_off = CmmRegOff reg byte_off
180 cmmOffsetLit :: CmmLit -> Int -> CmmLit
181 cmmOffsetLit (CmmLabel l) byte_off = cmmLabelOff l byte_off
182 cmmOffsetLit (CmmLabelOff l m) byte_off = cmmLabelOff l (m+byte_off)
183 cmmOffsetLit (CmmInt m rep) byte_off = CmmInt (m + fromIntegral byte_off) rep
184 cmmOffsetLit _ byte_off = pprPanic "cmmOffsetLit" (ppr byte_off)
186 cmmLabelOff :: CLabel -> Int -> CmmLit
187 -- Smart constructor for CmmLabelOff
188 cmmLabelOff lbl 0 = CmmLabel lbl
189 cmmLabelOff lbl byte_off = CmmLabelOff lbl byte_off
191 -- | Useful for creating an index into an array, with a staticaly known offset.
192 -- The type is the element type; used for making the multiplier
193 cmmIndex :: Width -- Width w
194 -> CmmExpr -- Address of vector of items of width w
195 -> Int -- Which element of the vector (0 based)
196 -> CmmExpr -- Address of i'th element
197 cmmIndex width base idx = cmmOffset base (idx * widthInBytes width)
199 -- | Useful for creating an index into an array, with an unknown offset.
200 cmmIndexExpr :: Width -- Width w
201 -> CmmExpr -- Address of vector of items of width w
202 -> CmmExpr -- Which element of the vector (0 based)
203 -> CmmExpr -- Address of i'th element
204 cmmIndexExpr width base (CmmLit (CmmInt n _)) = cmmIndex width base (fromInteger n)
205 cmmIndexExpr width base idx =
206 cmmOffsetExpr base byte_off
208 idx_w = cmmExprWidth idx
209 byte_off = CmmMachOp (MO_Shl idx_w) [idx, CmmLit (mkIntCLit (widthInLog width))]
211 cmmLoadIndex :: CmmType -> CmmExpr -> Int -> CmmExpr
212 cmmLoadIndex ty expr ix = CmmLoad (cmmIndex (typeWidth ty) expr ix) ty
214 ---------------------------------------------------
216 -- Literal construction functions
218 ---------------------------------------------------
220 mkIntCLit :: Int -> CmmLit
221 mkIntCLit i = CmmInt (toInteger i) wordWidth
224 zeroCLit = CmmInt 0 wordWidth
226 mkLblExpr :: CLabel -> CmmExpr
227 mkLblExpr lbl = CmmLit (CmmLabel lbl)
229 ---------------------------------------------------
231 -- Helpers for foreign call arguments
233 ---------------------------------------------------
235 loadArgsIntoTemps :: [Unique]
237 -> ([Unique], [CmmStmt], HintedCmmActuals)
238 loadArgsIntoTemps uniques [] = (uniques, [], [])
239 loadArgsIntoTemps uniques ((CmmHinted e hint):args) =
241 new_stmts ++ remaining_stmts,
242 (CmmHinted new_e hint) : remaining_e)
244 (uniques', new_stmts, new_e) = maybeAssignTemp uniques e
245 (uniques'', remaining_stmts, remaining_e) =
246 loadArgsIntoTemps uniques' args
249 maybeAssignTemp :: [Unique] -> CmmExpr -> ([Unique], [CmmStmt], CmmExpr)
250 maybeAssignTemp uniques e
251 | hasNoGlobalRegs e = (uniques, [], e)
252 | otherwise = (tail uniques, [CmmAssign local e], CmmReg local)
253 where local = CmmLocal (LocalReg (head uniques) (cmmExprType e))