replace Cmm 'hint' with 'kind'
[ghc-hetmet.git] / compiler / codeGen / CgPrimOp.hs
1 {-# OPTIONS -w #-}
2 -- The above warning supression flag is a temporary kludge.
3 -- While working on this module you are encouraged to remove it and fix
4 -- any warnings in the module. See
5 --     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
6 -- for details
7
8 -----------------------------------------------------------------------------
9 --
10 -- Code generation for PrimOps.
11 --
12 -- (c) The University of Glasgow 2004-2006
13 --
14 -----------------------------------------------------------------------------
15
16 module CgPrimOp (
17    cgPrimOp
18  ) where
19
20 import ForeignCall
21 import ClosureInfo
22 import StgSyn
23 import CgForeignCall
24 import CgBindery
25 import CgMonad
26 import CgInfoTbls
27 import CgUtils
28 import Cmm
29 import CLabel
30 import CmmUtils
31 import MachOp
32 import PrimOp
33 import SMRep
34 import Constants
35 import Outputable
36 import FastString
37
38 -- ---------------------------------------------------------------------------
39 -- Code generation for PrimOps
40
41 cgPrimOp   :: CmmFormalsWithoutKinds    -- where to put the results
42            -> PrimOp            -- the op
43            -> [StgArg]          -- arguments
44            -> StgLiveVars       -- live vars, in case we need to save them
45            -> Code
46
47 cgPrimOp results op args live
48   = do arg_exprs <- getArgAmodes args
49        let non_void_args = [ e | (r,e) <- arg_exprs, nonVoidArg r ] 
50        emitPrimOp results op non_void_args live
51
52
53 emitPrimOp :: CmmFormalsWithoutKinds    -- where to put the results
54            -> PrimOp            -- the op
55            -> [CmmExpr]         -- arguments
56            -> StgLiveVars       -- live vars, in case we need to save them
57            -> Code
58
59 --  First we handle various awkward cases specially.  The remaining
60 -- easy cases are then handled by translateOp, defined below.
61
62 emitPrimOp [res_r,res_c] IntAddCOp [aa,bb] live
63 {- 
64    With some bit-twiddling, we can define int{Add,Sub}Czh portably in
65    C, and without needing any comparisons.  This may not be the
66    fastest way to do it - if you have better code, please send it! --SDM
67   
68    Return : r = a + b,  c = 0 if no overflow, 1 on overflow.
69   
70    We currently don't make use of the r value if c is != 0 (i.e. 
71    overflow), we just convert to big integers and try again.  This
72    could be improved by making r and c the correct values for
73    plugging into a new J#.  
74    
75    { r = ((I_)(a)) + ((I_)(b));                                 \
76      c = ((StgWord)(~(((I_)(a))^((I_)(b))) & (((I_)(a))^r)))    \
77          >> (BITS_IN (I_) - 1);                                 \
78    } 
79    Wading through the mass of bracketry, it seems to reduce to:
80    c = ( (~(a^b)) & (a^r) ) >>unsigned (BITS_IN(I_)-1)
81
82 -}
83    = stmtsC [
84         CmmAssign (CmmLocal res_r) (CmmMachOp mo_wordAdd [aa,bb]),
85         CmmAssign (CmmLocal res_c) $
86           CmmMachOp mo_wordUShr [
87                 CmmMachOp mo_wordAnd [
88                     CmmMachOp mo_wordNot [CmmMachOp mo_wordXor [aa,bb]],
89                     CmmMachOp mo_wordXor [aa, CmmReg (CmmLocal res_r)]
90                 ], 
91                 CmmLit (mkIntCLit (wORD_SIZE_IN_BITS - 1))
92           ]
93      ]
94
95
96 emitPrimOp [res_r,res_c] IntSubCOp [aa,bb] live
97 {- Similarly:
98    #define subIntCzh(r,c,a,b)                                   \
99    { r = ((I_)(a)) - ((I_)(b));                                 \
100      c = ((StgWord)((((I_)(a))^((I_)(b))) & (((I_)(a))^r)))     \
101          >> (BITS_IN (I_) - 1);                                 \
102    }
103
104    c =  ((a^b) & (a^r)) >>unsigned (BITS_IN(I_)-1)
105 -}
106    = stmtsC [
107         CmmAssign (CmmLocal res_r) (CmmMachOp mo_wordSub [aa,bb]),
108         CmmAssign (CmmLocal res_c) $
109           CmmMachOp mo_wordUShr [
110                 CmmMachOp mo_wordAnd [
111                     CmmMachOp mo_wordXor [aa,bb],
112                     CmmMachOp mo_wordXor [aa, CmmReg (CmmLocal res_r)]
113                 ], 
114                 CmmLit (mkIntCLit (wORD_SIZE_IN_BITS - 1))
115           ]
116      ]
117
118
119 emitPrimOp [res] ParOp [arg] live
120   = do
121         -- for now, just implement this in a C function
122         -- later, we might want to inline it.
123     vols <- getVolatileRegs live
124     emitForeignCall' PlayRisky
125         [CmmKinded res NoHint]
126         (CmmCallee newspark CCallConv) 
127         [   (CmmKinded (CmmReg (CmmGlobal BaseReg)) PtrHint)
128           , (CmmKinded arg PtrHint)  ] 
129         (Just vols)
130         NoC_SRT -- No SRT b/c we do PlayRisky
131         CmmMayReturn
132   where
133         newspark = CmmLit (CmmLabel (mkRtsCodeLabel (sLit "newSpark")))
134
135 emitPrimOp [res] ReadMutVarOp [mutv] live
136    = stmtC (CmmAssign (CmmLocal res) (cmmLoadIndexW mutv fixedHdrSize))
137
138 emitPrimOp [] WriteMutVarOp [mutv,var] live
139    = do
140         stmtC (CmmStore (cmmOffsetW mutv fixedHdrSize) var)
141         vols <- getVolatileRegs live
142         emitForeignCall' PlayRisky
143                 [{-no results-}]
144                 (CmmCallee (CmmLit (CmmLabel mkDirty_MUT_VAR_Label))
145                          CCallConv)
146                 [   (CmmKinded (CmmReg (CmmGlobal BaseReg)) PtrHint)
147                   , (CmmKinded mutv PtrHint)  ]
148                 (Just vols)
149                 NoC_SRT -- No SRT b/c we do PlayRisky
150                 CmmMayReturn
151
152 --  #define sizzeofByteArrayzh(r,a) \
153 --     r = (((StgArrWords *)(a))->words * sizeof(W_))
154 emitPrimOp [res] SizeofByteArrayOp [arg] live
155    = stmtC $
156         CmmAssign (CmmLocal res) (CmmMachOp mo_wordMul [
157                           cmmLoadIndexW arg fixedHdrSize,
158                           CmmLit (mkIntCLit wORD_SIZE)
159                         ])
160
161 --  #define sizzeofMutableByteArrayzh(r,a) \
162 --      r = (((StgArrWords *)(a))->words * sizeof(W_))
163 emitPrimOp [res] SizeofMutableByteArrayOp [arg] live
164    = emitPrimOp [res] SizeofByteArrayOp [arg] live
165
166
167 --  #define touchzh(o)                  /* nothing */
168 emitPrimOp [] TouchOp [arg] live
169    = nopC
170
171 --  #define byteArrayContentszh(r,a) r = BYTE_ARR_CTS(a)
172 emitPrimOp [res] ByteArrayContents_Char [arg] live
173    = stmtC (CmmAssign (CmmLocal res) (cmmOffsetB arg arrWordsHdrSize))
174
175 --  #define stableNameToIntzh(r,s)   (r = ((StgStableName *)s)->sn)
176 emitPrimOp [res] StableNameToIntOp [arg] live
177    = stmtC (CmmAssign (CmmLocal res) (cmmLoadIndexW arg fixedHdrSize))
178
179 --  #define eqStableNamezh(r,sn1,sn2)                                   \
180 --    (r = (((StgStableName *)sn1)->sn == ((StgStableName *)sn2)->sn))
181 emitPrimOp [res] EqStableNameOp [arg1,arg2] live
182    = stmtC (CmmAssign (CmmLocal res) (CmmMachOp mo_wordEq [
183                                 cmmLoadIndexW arg1 fixedHdrSize,
184                                 cmmLoadIndexW arg2 fixedHdrSize
185                          ]))
186
187
188 emitPrimOp [res] ReallyUnsafePtrEqualityOp [arg1,arg2] live
189    = stmtC (CmmAssign (CmmLocal res) (CmmMachOp mo_wordEq [arg1,arg2]))
190
191 --  #define addrToHValuezh(r,a) r=(P_)a
192 emitPrimOp [res] AddrToHValueOp [arg] live
193    = stmtC (CmmAssign (CmmLocal res) arg)
194
195 --  #define dataToTagzh(r,a)  r=(GET_TAG(((StgClosure *)a)->header.info))
196 --  Note: argument may be tagged!
197 emitPrimOp [res] DataToTagOp [arg] live
198    = stmtC (CmmAssign (CmmLocal res) (getConstrTag (cmmUntag arg)))
199
200 {- Freezing arrays-of-ptrs requires changing an info table, for the
201    benefit of the generational collector.  It needs to scavenge mutable
202    objects, even if they are in old space.  When they become immutable,
203    they can be removed from this scavenge list.  -}
204
205 --  #define unsafeFreezzeArrayzh(r,a)
206 --      {
207 --        SET_INFO((StgClosure *)a,&stg_MUT_ARR_PTRS_FROZEN0_info);
208 --        r = a;
209 --      }
210 emitPrimOp [res] UnsafeFreezeArrayOp [arg] live
211    = stmtsC [ setInfo arg (CmmLit (CmmLabel mkMAP_FROZEN_infoLabel)),
212              CmmAssign (CmmLocal res) arg ]
213
214 --  #define unsafeFreezzeByteArrayzh(r,a)       r=(a)
215 emitPrimOp [res] UnsafeFreezeByteArrayOp [arg] live
216    = stmtC (CmmAssign (CmmLocal res) arg)
217
218 -- Reading/writing pointer arrays
219
220 emitPrimOp [r] ReadArrayOp  [obj,ix]   live  = doReadPtrArrayOp r obj ix
221 emitPrimOp [r] IndexArrayOp [obj,ix]   live  = doReadPtrArrayOp r obj ix
222 emitPrimOp []  WriteArrayOp [obj,ix,v] live  = doWritePtrArrayOp obj ix v
223
224 -- IndexXXXoffAddr
225
226 emitPrimOp res IndexOffAddrOp_Char      args live = doIndexOffAddrOp (Just mo_u_8ToWord) I8 res args
227 emitPrimOp res IndexOffAddrOp_WideChar  args live = doIndexOffAddrOp (Just mo_u_32ToWord) I32 res args
228 emitPrimOp res IndexOffAddrOp_Int       args live = doIndexOffAddrOp Nothing wordRep res args
229 emitPrimOp res IndexOffAddrOp_Word      args live = doIndexOffAddrOp Nothing wordRep res args
230 emitPrimOp res IndexOffAddrOp_Addr      args live = doIndexOffAddrOp Nothing wordRep res args
231 emitPrimOp res IndexOffAddrOp_Float     args live = doIndexOffAddrOp Nothing F32 res args
232 emitPrimOp res IndexOffAddrOp_Double    args live = doIndexOffAddrOp Nothing F64 res args
233 emitPrimOp res IndexOffAddrOp_StablePtr args live = doIndexOffAddrOp Nothing wordRep res args
234 emitPrimOp res IndexOffAddrOp_Int8      args live = doIndexOffAddrOp (Just mo_s_8ToWord) I8  res args
235 emitPrimOp res IndexOffAddrOp_Int16     args live = doIndexOffAddrOp (Just mo_s_16ToWord) I16 res args
236 emitPrimOp res IndexOffAddrOp_Int32     args live = doIndexOffAddrOp (Just mo_s_32ToWord) I32 res args
237 emitPrimOp res IndexOffAddrOp_Int64     args live = doIndexOffAddrOp Nothing I64 res args
238 emitPrimOp res IndexOffAddrOp_Word8     args live = doIndexOffAddrOp (Just mo_u_8ToWord) I8  res args
239 emitPrimOp res IndexOffAddrOp_Word16    args live = doIndexOffAddrOp (Just mo_u_16ToWord) I16 res args
240 emitPrimOp res IndexOffAddrOp_Word32    args live = doIndexOffAddrOp (Just mo_u_32ToWord) I32 res args
241 emitPrimOp res IndexOffAddrOp_Word64    args live = doIndexOffAddrOp Nothing I64 res args
242
243 -- ReadXXXoffAddr, which are identical, for our purposes, to IndexXXXoffAddr.
244
245 emitPrimOp res ReadOffAddrOp_Char      args live = doIndexOffAddrOp (Just mo_u_8ToWord) I8 res args
246 emitPrimOp res ReadOffAddrOp_WideChar  args live = doIndexOffAddrOp (Just mo_u_32ToWord) I32 res args
247 emitPrimOp res ReadOffAddrOp_Int       args live = doIndexOffAddrOp Nothing wordRep res args
248 emitPrimOp res ReadOffAddrOp_Word      args live = doIndexOffAddrOp Nothing wordRep res args
249 emitPrimOp res ReadOffAddrOp_Addr      args live = doIndexOffAddrOp Nothing wordRep res args
250 emitPrimOp res ReadOffAddrOp_Float     args live = doIndexOffAddrOp Nothing F32 res args
251 emitPrimOp res ReadOffAddrOp_Double    args live = doIndexOffAddrOp Nothing F64 res args
252 emitPrimOp res ReadOffAddrOp_StablePtr args live = doIndexOffAddrOp Nothing wordRep res args
253 emitPrimOp res ReadOffAddrOp_Int8      args live = doIndexOffAddrOp (Just mo_s_8ToWord) I8  res args
254 emitPrimOp res ReadOffAddrOp_Int16     args live = doIndexOffAddrOp (Just mo_s_16ToWord) I16 res args
255 emitPrimOp res ReadOffAddrOp_Int32     args live = doIndexOffAddrOp (Just mo_s_32ToWord) I32 res args
256 emitPrimOp res ReadOffAddrOp_Int64     args live = doIndexOffAddrOp Nothing I64 res args
257 emitPrimOp res ReadOffAddrOp_Word8     args live = doIndexOffAddrOp (Just mo_u_8ToWord) I8  res args
258 emitPrimOp res ReadOffAddrOp_Word16    args live = doIndexOffAddrOp (Just mo_u_16ToWord) I16 res args
259 emitPrimOp res ReadOffAddrOp_Word32    args live = doIndexOffAddrOp (Just mo_u_32ToWord) I32 res args
260 emitPrimOp res ReadOffAddrOp_Word64    args live = doIndexOffAddrOp Nothing I64 res args
261
262 -- IndexXXXArray
263
264 emitPrimOp res IndexByteArrayOp_Char      args live = doIndexByteArrayOp (Just mo_u_8ToWord) I8 res args
265 emitPrimOp res IndexByteArrayOp_WideChar  args live = doIndexByteArrayOp (Just mo_u_32ToWord) I32 res args
266 emitPrimOp res IndexByteArrayOp_Int       args live = doIndexByteArrayOp Nothing wordRep res args
267 emitPrimOp res IndexByteArrayOp_Word      args live = doIndexByteArrayOp Nothing wordRep res args
268 emitPrimOp res IndexByteArrayOp_Addr      args live = doIndexByteArrayOp Nothing wordRep res args
269 emitPrimOp res IndexByteArrayOp_Float     args live = doIndexByteArrayOp Nothing F32 res args
270 emitPrimOp res IndexByteArrayOp_Double    args live = doIndexByteArrayOp Nothing F64 res args
271 emitPrimOp res IndexByteArrayOp_StablePtr args live = doIndexByteArrayOp Nothing wordRep res args
272 emitPrimOp res IndexByteArrayOp_Int8      args live = doIndexByteArrayOp (Just mo_s_8ToWord) I8  res args
273 emitPrimOp res IndexByteArrayOp_Int16     args live = doIndexByteArrayOp (Just mo_s_16ToWord) I16  res args
274 emitPrimOp res IndexByteArrayOp_Int32     args live = doIndexByteArrayOp (Just mo_s_32ToWord) I32  res args
275 emitPrimOp res IndexByteArrayOp_Int64     args live = doIndexByteArrayOp Nothing I64  res args
276 emitPrimOp res IndexByteArrayOp_Word8     args live = doIndexByteArrayOp (Just mo_u_8ToWord) I8  res args
277 emitPrimOp res IndexByteArrayOp_Word16    args live = doIndexByteArrayOp (Just mo_u_16ToWord) I16  res args
278 emitPrimOp res IndexByteArrayOp_Word32    args live = doIndexByteArrayOp (Just mo_u_32ToWord) I32  res args
279 emitPrimOp res IndexByteArrayOp_Word64    args live = doIndexByteArrayOp Nothing I64  res args
280
281 -- ReadXXXArray, identical to IndexXXXArray.
282
283 emitPrimOp res ReadByteArrayOp_Char       args live = doIndexByteArrayOp (Just mo_u_8ToWord) I8 res args
284 emitPrimOp res ReadByteArrayOp_WideChar   args live = doIndexByteArrayOp (Just mo_u_32ToWord) I32 res args
285 emitPrimOp res ReadByteArrayOp_Int        args live = doIndexByteArrayOp Nothing wordRep res args
286 emitPrimOp res ReadByteArrayOp_Word       args live = doIndexByteArrayOp Nothing wordRep res args
287 emitPrimOp res ReadByteArrayOp_Addr       args live = doIndexByteArrayOp Nothing wordRep res args
288 emitPrimOp res ReadByteArrayOp_Float      args live = doIndexByteArrayOp Nothing F32 res args
289 emitPrimOp res ReadByteArrayOp_Double     args live = doIndexByteArrayOp Nothing F64 res args
290 emitPrimOp res ReadByteArrayOp_StablePtr  args live = doIndexByteArrayOp Nothing wordRep res args
291 emitPrimOp res ReadByteArrayOp_Int8       args live = doIndexByteArrayOp (Just mo_s_8ToWord) I8  res args
292 emitPrimOp res ReadByteArrayOp_Int16      args live = doIndexByteArrayOp (Just mo_s_16ToWord) I16  res args
293 emitPrimOp res ReadByteArrayOp_Int32      args live = doIndexByteArrayOp (Just mo_s_32ToWord) I32  res args
294 emitPrimOp res ReadByteArrayOp_Int64      args live = doIndexByteArrayOp Nothing I64  res args
295 emitPrimOp res ReadByteArrayOp_Word8      args live = doIndexByteArrayOp (Just mo_u_8ToWord) I8  res args
296 emitPrimOp res ReadByteArrayOp_Word16     args live = doIndexByteArrayOp (Just mo_u_16ToWord) I16  res args
297 emitPrimOp res ReadByteArrayOp_Word32     args live = doIndexByteArrayOp (Just mo_u_32ToWord) I32  res args
298 emitPrimOp res ReadByteArrayOp_Word64     args live = doIndexByteArrayOp Nothing I64  res args
299
300 -- WriteXXXoffAddr
301
302 emitPrimOp res WriteOffAddrOp_Char       args live = doWriteOffAddrOp (Just mo_WordTo8) I8 res args
303 emitPrimOp res WriteOffAddrOp_WideChar   args live = doWriteOffAddrOp (Just mo_WordTo32) I32 res args
304 emitPrimOp res WriteOffAddrOp_Int        args live = doWriteOffAddrOp Nothing wordRep res args
305 emitPrimOp res WriteOffAddrOp_Word       args live = doWriteOffAddrOp Nothing wordRep res args
306 emitPrimOp res WriteOffAddrOp_Addr       args live = doWriteOffAddrOp Nothing wordRep res args
307 emitPrimOp res WriteOffAddrOp_Float      args live = doWriteOffAddrOp Nothing F32 res args
308 emitPrimOp res WriteOffAddrOp_Double     args live = doWriteOffAddrOp Nothing F64 res args
309 emitPrimOp res WriteOffAddrOp_StablePtr  args live = doWriteOffAddrOp Nothing wordRep res args
310 emitPrimOp res WriteOffAddrOp_Int8       args live = doWriteOffAddrOp (Just mo_WordTo8) I8  res args
311 emitPrimOp res WriteOffAddrOp_Int16      args live = doWriteOffAddrOp (Just mo_WordTo16) I16 res args
312 emitPrimOp res WriteOffAddrOp_Int32      args live = doWriteOffAddrOp (Just mo_WordTo32) I32 res args
313 emitPrimOp res WriteOffAddrOp_Int64      args live = doWriteOffAddrOp Nothing I64 res args
314 emitPrimOp res WriteOffAddrOp_Word8      args live = doWriteOffAddrOp (Just mo_WordTo8) I8  res args
315 emitPrimOp res WriteOffAddrOp_Word16     args live = doWriteOffAddrOp (Just mo_WordTo16) I16 res args
316 emitPrimOp res WriteOffAddrOp_Word32     args live = doWriteOffAddrOp (Just mo_WordTo32) I32 res args
317 emitPrimOp res WriteOffAddrOp_Word64     args live = doWriteOffAddrOp Nothing I64 res args
318
319 -- WriteXXXArray
320
321 emitPrimOp res WriteByteArrayOp_Char      args live = doWriteByteArrayOp (Just mo_WordTo8) I8 res args
322 emitPrimOp res WriteByteArrayOp_WideChar  args live = doWriteByteArrayOp (Just mo_WordTo32) I32 res args
323 emitPrimOp res WriteByteArrayOp_Int       args live = doWriteByteArrayOp Nothing wordRep res args
324 emitPrimOp res WriteByteArrayOp_Word      args live = doWriteByteArrayOp Nothing wordRep res args
325 emitPrimOp res WriteByteArrayOp_Addr      args live = doWriteByteArrayOp Nothing wordRep res args
326 emitPrimOp res WriteByteArrayOp_Float     args live = doWriteByteArrayOp Nothing F32 res args
327 emitPrimOp res WriteByteArrayOp_Double    args live = doWriteByteArrayOp Nothing F64 res args
328 emitPrimOp res WriteByteArrayOp_StablePtr args live = doWriteByteArrayOp Nothing wordRep res args
329 emitPrimOp res WriteByteArrayOp_Int8      args live = doWriteByteArrayOp (Just mo_WordTo8) I8  res args
330 emitPrimOp res WriteByteArrayOp_Int16     args live = doWriteByteArrayOp (Just mo_WordTo16) I16  res args
331 emitPrimOp res WriteByteArrayOp_Int32     args live = doWriteByteArrayOp (Just mo_WordTo32) I32  res args
332 emitPrimOp res WriteByteArrayOp_Int64     args live = doWriteByteArrayOp Nothing I64  res args
333 emitPrimOp res WriteByteArrayOp_Word8     args live = doWriteByteArrayOp (Just mo_WordTo8) I8  res args
334 emitPrimOp res WriteByteArrayOp_Word16    args live = doWriteByteArrayOp (Just mo_WordTo16) I16  res args
335 emitPrimOp res WriteByteArrayOp_Word32    args live = doWriteByteArrayOp (Just mo_WordTo32) I32  res args
336 emitPrimOp res WriteByteArrayOp_Word64    args live = doWriteByteArrayOp Nothing I64  res args
337
338
339 -- The rest just translate straightforwardly
340 emitPrimOp [res] op [arg] live
341    | nopOp op
342    = stmtC (CmmAssign (CmmLocal res) arg)
343
344    | Just (mop,rep) <- narrowOp op
345    = stmtC (CmmAssign (CmmLocal res) (CmmMachOp (mop rep wordRep) [
346                           CmmMachOp (mop wordRep rep) [arg]]))
347
348 emitPrimOp [res] op args live
349    | Just prim <- callishOp op
350    = do vols <- getVolatileRegs live
351         emitForeignCall' PlayRisky
352            [CmmKinded res NoHint] 
353            (CmmPrim prim) 
354            [CmmKinded a NoHint | a<-args]  -- ToDo: hints?
355            (Just vols)
356            NoC_SRT -- No SRT b/c we do PlayRisky
357            CmmMayReturn
358
359    | Just mop <- translateOp op
360    = let stmt = CmmAssign (CmmLocal res) (CmmMachOp mop args) in
361      stmtC stmt
362
363 emitPrimOp _ op _ _
364  = pprPanic "emitPrimOp: can't translate PrimOp" (ppr op)
365
366
367 -- These PrimOps are NOPs in Cmm
368
369 nopOp Int2WordOp     = True
370 nopOp Word2IntOp     = True
371 nopOp Int2AddrOp     = True
372 nopOp Addr2IntOp     = True
373 nopOp ChrOp          = True  -- Int# and Char# are rep'd the same
374 nopOp OrdOp          = True
375 nopOp _              = False
376
377 -- These PrimOps turn into double casts
378
379 narrowOp Narrow8IntOp   = Just (MO_S_Conv, I8)
380 narrowOp Narrow16IntOp  = Just (MO_S_Conv, I16)
381 narrowOp Narrow32IntOp  = Just (MO_S_Conv, I32)
382 narrowOp Narrow8WordOp  = Just (MO_U_Conv, I8)
383 narrowOp Narrow16WordOp = Just (MO_U_Conv, I16)
384 narrowOp Narrow32WordOp = Just (MO_U_Conv, I32)
385 narrowOp _              = Nothing
386
387 -- Native word signless ops
388
389 translateOp IntAddOp       = Just mo_wordAdd
390 translateOp IntSubOp       = Just mo_wordSub
391 translateOp WordAddOp      = Just mo_wordAdd
392 translateOp WordSubOp      = Just mo_wordSub
393 translateOp AddrAddOp      = Just mo_wordAdd
394 translateOp AddrSubOp      = Just mo_wordSub
395
396 translateOp IntEqOp        = Just mo_wordEq
397 translateOp IntNeOp        = Just mo_wordNe
398 translateOp WordEqOp       = Just mo_wordEq
399 translateOp WordNeOp       = Just mo_wordNe
400 translateOp AddrEqOp       = Just mo_wordEq
401 translateOp AddrNeOp       = Just mo_wordNe
402
403 translateOp AndOp          = Just mo_wordAnd
404 translateOp OrOp           = Just mo_wordOr
405 translateOp XorOp          = Just mo_wordXor
406 translateOp NotOp          = Just mo_wordNot
407 translateOp SllOp          = Just mo_wordShl
408 translateOp SrlOp          = Just mo_wordUShr
409
410 translateOp AddrRemOp      = Just mo_wordURem
411
412 -- Native word signed ops
413
414 translateOp IntMulOp        = Just mo_wordMul
415 translateOp IntMulMayOfloOp = Just (MO_S_MulMayOflo wordRep)
416 translateOp IntQuotOp       = Just mo_wordSQuot
417 translateOp IntRemOp        = Just mo_wordSRem
418 translateOp IntNegOp        = Just mo_wordSNeg
419
420
421 translateOp IntGeOp        = Just mo_wordSGe
422 translateOp IntLeOp        = Just mo_wordSLe
423 translateOp IntGtOp        = Just mo_wordSGt
424 translateOp IntLtOp        = Just mo_wordSLt
425
426 translateOp ISllOp         = Just mo_wordShl
427 translateOp ISraOp         = Just mo_wordSShr
428 translateOp ISrlOp         = Just mo_wordUShr
429
430 -- Native word unsigned ops
431
432 translateOp WordGeOp       = Just mo_wordUGe
433 translateOp WordLeOp       = Just mo_wordULe
434 translateOp WordGtOp       = Just mo_wordUGt
435 translateOp WordLtOp       = Just mo_wordULt
436
437 translateOp WordMulOp      = Just mo_wordMul
438 translateOp WordQuotOp     = Just mo_wordUQuot
439 translateOp WordRemOp      = Just mo_wordURem
440
441 translateOp AddrGeOp       = Just mo_wordUGe
442 translateOp AddrLeOp       = Just mo_wordULe
443 translateOp AddrGtOp       = Just mo_wordUGt
444 translateOp AddrLtOp       = Just mo_wordULt
445
446 -- Char# ops
447
448 translateOp CharEqOp       = Just (MO_Eq wordRep)
449 translateOp CharNeOp       = Just (MO_Ne wordRep)
450 translateOp CharGeOp       = Just (MO_U_Ge wordRep)
451 translateOp CharLeOp       = Just (MO_U_Le wordRep)
452 translateOp CharGtOp       = Just (MO_U_Gt wordRep)
453 translateOp CharLtOp       = Just (MO_U_Lt wordRep)
454
455 -- Double ops
456
457 translateOp DoubleEqOp     = Just (MO_Eq F64)
458 translateOp DoubleNeOp     = Just (MO_Ne F64)
459 translateOp DoubleGeOp     = Just (MO_S_Ge F64)
460 translateOp DoubleLeOp     = Just (MO_S_Le F64)
461 translateOp DoubleGtOp     = Just (MO_S_Gt F64)
462 translateOp DoubleLtOp     = Just (MO_S_Lt F64)
463
464 translateOp DoubleAddOp    = Just (MO_Add F64)
465 translateOp DoubleSubOp    = Just (MO_Sub F64)
466 translateOp DoubleMulOp    = Just (MO_Mul F64)
467 translateOp DoubleDivOp    = Just (MO_S_Quot F64)
468 translateOp DoubleNegOp    = Just (MO_S_Neg F64)
469
470 -- Float ops
471
472 translateOp FloatEqOp     = Just (MO_Eq F32)
473 translateOp FloatNeOp     = Just (MO_Ne F32)
474 translateOp FloatGeOp     = Just (MO_S_Ge F32)
475 translateOp FloatLeOp     = Just (MO_S_Le F32)
476 translateOp FloatGtOp     = Just (MO_S_Gt F32)
477 translateOp FloatLtOp     = Just (MO_S_Lt F32)
478
479 translateOp FloatAddOp    = Just (MO_Add F32)
480 translateOp FloatSubOp    = Just (MO_Sub F32)
481 translateOp FloatMulOp    = Just (MO_Mul F32)
482 translateOp FloatDivOp    = Just (MO_S_Quot F32)
483 translateOp FloatNegOp    = Just (MO_S_Neg F32)
484
485 -- Conversions
486
487 translateOp Int2DoubleOp   = Just (MO_S_Conv wordRep F64)
488 translateOp Double2IntOp   = Just (MO_S_Conv F64 wordRep)
489
490 translateOp Int2FloatOp    = Just (MO_S_Conv wordRep F32)
491 translateOp Float2IntOp    = Just (MO_S_Conv F32 wordRep)
492
493 translateOp Float2DoubleOp = Just (MO_S_Conv F32 F64)
494 translateOp Double2FloatOp = Just (MO_S_Conv F64 F32)
495
496 -- Word comparisons masquerading as more exotic things.
497
498 translateOp SameMutVarOp           = Just mo_wordEq
499 translateOp SameMVarOp             = Just mo_wordEq
500 translateOp SameMutableArrayOp     = Just mo_wordEq
501 translateOp SameMutableByteArrayOp = Just mo_wordEq
502 translateOp SameTVarOp             = Just mo_wordEq
503 translateOp EqStablePtrOp          = Just mo_wordEq
504
505 translateOp _ = Nothing
506
507 -- These primops are implemented by CallishMachOps, because they sometimes
508 -- turn into foreign calls depending on the backend.
509
510 callishOp DoublePowerOp  = Just MO_F64_Pwr
511 callishOp DoubleSinOp    = Just MO_F64_Sin
512 callishOp DoubleCosOp    = Just MO_F64_Cos
513 callishOp DoubleTanOp    = Just MO_F64_Tan
514 callishOp DoubleSinhOp   = Just MO_F64_Sinh
515 callishOp DoubleCoshOp   = Just MO_F64_Cosh
516 callishOp DoubleTanhOp   = Just MO_F64_Tanh
517 callishOp DoubleAsinOp   = Just MO_F64_Asin
518 callishOp DoubleAcosOp   = Just MO_F64_Acos
519 callishOp DoubleAtanOp   = Just MO_F64_Atan
520 callishOp DoubleLogOp    = Just MO_F64_Log
521 callishOp DoubleExpOp    = Just MO_F64_Exp
522 callishOp DoubleSqrtOp   = Just MO_F64_Sqrt
523
524 callishOp FloatPowerOp  = Just MO_F32_Pwr
525 callishOp FloatSinOp    = Just MO_F32_Sin
526 callishOp FloatCosOp    = Just MO_F32_Cos
527 callishOp FloatTanOp    = Just MO_F32_Tan
528 callishOp FloatSinhOp   = Just MO_F32_Sinh
529 callishOp FloatCoshOp   = Just MO_F32_Cosh
530 callishOp FloatTanhOp   = Just MO_F32_Tanh
531 callishOp FloatAsinOp   = Just MO_F32_Asin
532 callishOp FloatAcosOp   = Just MO_F32_Acos
533 callishOp FloatAtanOp   = Just MO_F32_Atan
534 callishOp FloatLogOp    = Just MO_F32_Log
535 callishOp FloatExpOp    = Just MO_F32_Exp
536 callishOp FloatSqrtOp   = Just MO_F32_Sqrt
537
538 callishOp _ = Nothing
539
540 ------------------------------------------------------------------------------
541 -- Helpers for translating various minor variants of array indexing.
542
543 doIndexOffAddrOp maybe_post_read_cast rep [res] [addr,idx]
544    = mkBasicIndexedRead 0 maybe_post_read_cast rep res addr idx
545 doIndexOffAddrOp _ _ _ _
546    = panic "CgPrimOp: doIndexOffAddrOp"
547
548 doIndexByteArrayOp maybe_post_read_cast rep [res] [addr,idx]
549    = mkBasicIndexedRead arrWordsHdrSize maybe_post_read_cast rep res addr idx
550 doIndexByteArrayOp _ _ _ _ 
551    = panic "CgPrimOp: doIndexByteArrayOp"
552
553 doReadPtrArrayOp res addr idx
554    = mkBasicIndexedRead arrPtrsHdrSize Nothing wordRep res addr idx
555
556
557 doWriteOffAddrOp maybe_pre_write_cast rep [] [addr,idx,val]
558    = mkBasicIndexedWrite 0 maybe_pre_write_cast rep addr idx val
559 doWriteOffAddrOp _ _ _ _
560    = panic "CgPrimOp: doWriteOffAddrOp"
561
562 doWriteByteArrayOp maybe_pre_write_cast rep [] [addr,idx,val]
563    = mkBasicIndexedWrite arrWordsHdrSize maybe_pre_write_cast rep addr idx val
564 doWriteByteArrayOp _ _ _ _ 
565    = panic "CgPrimOp: doWriteByteArrayOp"
566
567 doWritePtrArrayOp addr idx val
568    = do stmtC (setInfo addr (CmmLit (CmmLabel mkMAP_DIRTY_infoLabel)))
569         mkBasicIndexedWrite arrPtrsHdrSize Nothing wordRep addr idx val
570
571
572 mkBasicIndexedRead off Nothing read_rep res base idx
573    = stmtC (CmmAssign (CmmLocal res) (cmmLoadIndexOffExpr off read_rep base idx))
574 mkBasicIndexedRead off (Just cast) read_rep res base idx
575    = stmtC (CmmAssign (CmmLocal res) (CmmMachOp cast [
576                                 cmmLoadIndexOffExpr off read_rep base idx]))
577
578 mkBasicIndexedWrite off Nothing write_rep base idx val
579    = stmtC (CmmStore (cmmIndexOffExpr off write_rep base idx) val)
580 mkBasicIndexedWrite off (Just cast) write_rep base idx val
581    = stmtC (CmmStore (cmmIndexOffExpr off write_rep base idx) (CmmMachOp cast [val]))
582
583 -- ----------------------------------------------------------------------------
584 -- Misc utils
585
586 cmmIndexOffExpr :: ByteOff -> MachRep -> CmmExpr -> CmmExpr -> CmmExpr
587 cmmIndexOffExpr off rep base idx
588    = cmmIndexExpr rep (cmmOffsetB base off) idx
589
590 cmmLoadIndexOffExpr :: ByteOff -> MachRep -> CmmExpr -> CmmExpr -> CmmExpr
591 cmmLoadIndexOffExpr off rep base idx
592    = CmmLoad (cmmIndexOffExpr off rep base idx) rep
593
594 setInfo :: CmmExpr -> CmmExpr -> CmmStmt
595 setInfo closure_ptr info_ptr = CmmStore closure_ptr info_ptr
596