2 % (c) The AQUA Project, Glasgow University, 1993-1998
6 module StixPrim ( primCode, amodeToStix, amodeToStix', foreignCallCode )
9 #include "HsVersions.h"
15 import AbsCSyn hiding ( spRel )
16 import AbsCUtils ( getAmodeRep, mixedTypeLocn )
17 import SMRep ( fixedHdrSize )
18 import Literal ( Literal(..), word2IntLit )
19 import PrimOp ( PrimOp(..) )
20 import PrimRep ( PrimRep(..), getPrimRepSizeInBytes )
21 import UniqSupply ( returnUs, thenUs, getUniqueUs, UniqSM )
22 import Constants ( mIN_INTLIKE, mIN_CHARLIKE, uF_UPDATEE, bLOCK_SIZE,
23 rESERVED_STACK_WORDS )
24 import CLabel ( mkIntlikeClosureLabel, mkCharlikeClosureLabel,
25 mkMAP_FROZEN_infoLabel, mkEMPTY_MVAR_infoLabel,
27 import ForeignCall ( ForeignCall(..), CCallSpec(..), CCallTarget(..),
28 CCallConv(..), playSafe )
35 The main honchos here are primCode anf foreignCallCode, which handle the guts of COpStmts.
39 :: [CAddrMode] -- results
41 -> [CAddrMode] -- args
42 -> UniqSM StixTreeList
45 :: [CAddrMode] -- results
47 -> [CAddrMode] -- args
48 -> UniqSM StixTreeList
51 %************************************************************************
53 \subsubsection{Code for foreign calls}
55 %************************************************************************
57 First, the dreaded @ccall@. We can't handle @casm@s.
59 Usually, this compiles to an assignment, but when the left-hand side
60 is empty, we just perform the call and ignore the result.
62 btw Why not let programmer use casm to provide assembly code instead
65 ToDo: saving/restoring of volatile regs around ccalls.
67 JRS, 001113: always do the call of suspendThread and resumeThread as a ccall
68 rather than inheriting the calling convention of the thing which we're really
72 foreignCallCode lhs (CCall (CCallSpec (StaticTarget fn) cconv safety)) rhs
73 | not (playSafe safety) = returnUs (\xs -> ccall : xs)
76 = save_thread_state `thenUs` \ save ->
77 load_thread_state `thenUs` \ load ->
78 getUniqueUs `thenUs` \ uniq ->
80 id = StReg (StixTemp uniq IntRep)
82 suspend = StAssign IntRep id
83 (StCall SLIT("suspendThread") {-no:cconv-} CCallConv
85 resume = StCall SLIT("resumeThread") {-no:cconv-} CCallConv
88 returnUs (\xs -> save (suspend : ccall : resume : load xs))
91 args = map amodeCodeForCCall rhs
93 let base = amodeToStix' x
96 ArrayRep -> StIndex PtrRep base arrPtrsHS
97 ByteArrayRep -> StIndex IntRep base arrWordsHS
98 ForeignObjRep -> StInd PtrRep (StIndex PtrRep base fixedHS)
102 [] -> StCall fn cconv VoidRep args
103 [lhs] -> StAssign pk lhs' (StCall fn cconv pk args)
105 lhs' = amodeToStix lhs
106 pk = case getAmodeRep lhs of
108 DoubleRep -> DoubleRep
111 foreignCallCode lhs call rhs
112 = ncgPrimopMoan "Native code generator can't handle foreign call" (ppr call)
116 %************************************************************************
118 \subsubsection{Code for primops}
120 %************************************************************************
122 The (MP) integer operations are a true nightmare. Since we don't have
123 a convenient abstract way of allocating temporary variables on the (C)
124 stack, we use the space just below HpLim for the @MP_INT@ structures,
125 and modify our heap check accordingly.
128 -- NB: ordering of clauses somewhere driven by
129 -- the desire to getting sane patt-matching behavior
131 primCode [res] IntegerCmpOp args@[sa1,da1, sa2,da2]
132 = gmpCompare res (sa1,da1, sa2,da2)
134 primCode [res] IntegerCmpIntOp args@[sa1,da1,ai]
135 = gmpCompareInt res (sa1,da1,ai)
137 primCode [res] Integer2IntOp arg@[sa,da]
138 = gmpInteger2Int res (sa,da)
140 primCode [res] Integer2WordOp arg@[sa,da]
141 = gmpInteger2Word res (sa,da)
143 primCode [res] Int2WordOp [arg]
144 = simpleCoercion IntRep{-WordRep?-} res arg
146 primCode [res] Word2IntOp [arg]
147 = simpleCoercion IntRep res arg
149 primCode [res] AddrToHValueOp [arg]
150 = simpleCoercion PtrRep res arg
152 #if (WORD_SIZE_IN_BITS == 32 || WORD_SIZE_IN_BITS == 64)
153 primCode [res] Int2AddrOp [arg]
154 = simpleCoercion AddrRep res arg
156 primCode [res] Addr2IntOp [arg]
157 = simpleCoercion IntRep res arg
160 primCode [res] Narrow8IntOp [arg]
161 = narrowingCoercion IntRep Int8Rep res arg
162 primCode [res] Narrow16IntOp [arg]
163 = narrowingCoercion IntRep Int16Rep res arg
164 primCode [res] Narrow32IntOp [arg]
165 = narrowingCoercion IntRep Int32Rep res arg
167 primCode [res] Narrow8WordOp [arg]
168 = narrowingCoercion WordRep Word8Rep res arg
169 primCode [res] Narrow16WordOp [arg]
170 = narrowingCoercion WordRep Word16Rep res arg
171 primCode [res] Narrow32WordOp [arg]
172 = narrowingCoercion WordRep Word32Rep res arg
176 primCode [res] SameMutableArrayOp args
178 compare = StPrim AddrEqOp (map amodeToStix args)
179 assign = StAssign IntRep (amodeToStix res) compare
181 returnUs (\xs -> assign : xs)
183 primCode res@[_] SameMutableByteArrayOp args
184 = primCode res SameMutableArrayOp args
186 primCode res@[_] SameMutVarOp args
187 = primCode res SameMutableArrayOp args
191 primCode res@[_] SameMVarOp args
192 = primCode res SameMutableArrayOp args
194 -- #define isEmptyMVarzh(r,a) \
195 -- r =(I_)((GET_INFO((StgMVar*)(a))) == &stg_EMPTY_MVAR_info )
196 primCode [res] IsEmptyMVarOp [arg]
197 = let res' = amodeToStix res
198 arg' = amodeToStix arg
199 arg_info = StInd PtrRep arg'
200 em_info = StCLbl mkEMPTY_MVAR_infoLabel
201 same = StPrim IntEqOp [arg_info, em_info]
202 assign = StAssign IntRep res' same
204 returnUs (\xs -> assign : xs)
206 -- #define myThreadIdzh(t) (t = CurrentTSO)
207 primCode [res] MyThreadIdOp []
208 = let res' = amodeToStix res
209 in returnUs (\xs -> StAssign ThreadIdRep res' stgCurrentTSO : xs)
213 Freezing an array of pointers is a double assignment. We fix the
214 header of the ``new'' closure because the lhs is probably a better
215 addressing mode for the indirection (most likely, it's a VanillaReg).
219 primCode [lhs] UnsafeFreezeArrayOp [rhs]
221 lhs' = amodeToStix lhs
222 rhs' = amodeToStix rhs
223 header = StInd PtrRep lhs'
224 assign = StAssign PtrRep lhs' rhs'
225 freeze = StAssign PtrRep header mutArrPtrsFrozen_info
227 returnUs (\xs -> assign : freeze : xs)
229 primCode [lhs] UnsafeFreezeByteArrayOp [rhs]
230 = simpleCoercion PtrRep lhs rhs
233 Returning the size of (mutable) byte arrays is just
234 an indexing operation.
237 primCode [lhs] SizeofByteArrayOp [rhs]
239 lhs' = amodeToStix lhs
240 rhs' = amodeToStix rhs
241 sz = StIndex IntRep rhs' fixedHS
242 assign = StAssign IntRep lhs' (StInd IntRep sz)
244 returnUs (\xs -> assign : xs)
246 primCode [lhs] SizeofMutableByteArrayOp [rhs]
248 lhs' = amodeToStix lhs
249 rhs' = amodeToStix rhs
250 sz = StIndex IntRep rhs' fixedHS
251 assign = StAssign IntRep lhs' (StInd IntRep sz)
253 returnUs (\xs -> assign : xs)
257 Most other array primitives translate to simple indexing.
260 primCode lhs@[_] IndexArrayOp args
261 = primCode lhs ReadArrayOp args
263 primCode [lhs] ReadArrayOp [obj, ix]
265 lhs' = amodeToStix lhs
266 obj' = amodeToStix obj
268 base = StIndex IntRep obj' arrPtrsHS
269 assign = StAssign PtrRep lhs' (StInd PtrRep (StIndex PtrRep base ix'))
271 returnUs (\xs -> assign : xs)
273 primCode [] WriteArrayOp [obj, ix, v]
275 obj' = amodeToStix obj
278 base = StIndex IntRep obj' arrPtrsHS
279 assign = StAssign PtrRep (StInd PtrRep (StIndex PtrRep base ix')) v'
281 returnUs (\xs -> assign : xs)
283 primCode [] WriteForeignObjOp [obj, v]
285 obj' = amodeToStix obj
287 obj'' = StIndex AddrRep obj' (StInt 4711) -- fixedHS
288 assign = StAssign AddrRep (StInd AddrRep obj'') v'
290 returnUs (\xs -> assign : xs)
292 -- NB: indexing in "pk" units, *not* in bytes (WDP 95/09)
293 primCode ls IndexByteArrayOp_Char rs = primCode_ReadByteArrayOp Word8Rep ls rs
294 primCode ls IndexByteArrayOp_WideChar rs = primCode_ReadByteArrayOp CharRep ls rs
295 primCode ls IndexByteArrayOp_Int rs = primCode_ReadByteArrayOp IntRep ls rs
296 primCode ls IndexByteArrayOp_Word rs = primCode_ReadByteArrayOp WordRep ls rs
297 primCode ls IndexByteArrayOp_Addr rs = primCode_ReadByteArrayOp AddrRep ls rs
298 primCode ls IndexByteArrayOp_Float rs = primCode_ReadByteArrayOp FloatRep ls rs
299 primCode ls IndexByteArrayOp_Double rs = primCode_ReadByteArrayOp DoubleRep ls rs
300 primCode ls IndexByteArrayOp_StablePtr rs = primCode_ReadByteArrayOp StablePtrRep ls rs
301 primCode ls IndexByteArrayOp_Int8 rs = primCode_ReadByteArrayOp Int8Rep ls rs
302 primCode ls IndexByteArrayOp_Int16 rs = primCode_ReadByteArrayOp Int16Rep ls rs
303 primCode ls IndexByteArrayOp_Int32 rs = primCode_ReadByteArrayOp Int32Rep ls rs
304 primCode ls IndexByteArrayOp_Int64 rs = primCode_ReadByteArrayOp Int64Rep ls rs
305 primCode ls IndexByteArrayOp_Word8 rs = primCode_ReadByteArrayOp Word8Rep ls rs
306 primCode ls IndexByteArrayOp_Word16 rs = primCode_ReadByteArrayOp Word16Rep ls rs
307 primCode ls IndexByteArrayOp_Word32 rs = primCode_ReadByteArrayOp Word32Rep ls rs
308 primCode ls IndexByteArrayOp_Word64 rs = primCode_ReadByteArrayOp Word64Rep ls rs
310 primCode ls ReadByteArrayOp_Char rs = primCode_ReadByteArrayOp Word8Rep ls rs
311 primCode ls ReadByteArrayOp_WideChar rs = primCode_ReadByteArrayOp CharRep ls rs
312 primCode ls ReadByteArrayOp_Int rs = primCode_ReadByteArrayOp IntRep ls rs
313 primCode ls ReadByteArrayOp_Word rs = primCode_ReadByteArrayOp WordRep ls rs
314 primCode ls ReadByteArrayOp_Addr rs = primCode_ReadByteArrayOp AddrRep ls rs
315 primCode ls ReadByteArrayOp_Float rs = primCode_ReadByteArrayOp FloatRep ls rs
316 primCode ls ReadByteArrayOp_Double rs = primCode_ReadByteArrayOp DoubleRep ls rs
317 primCode ls ReadByteArrayOp_StablePtr rs = primCode_ReadByteArrayOp StablePtrRep ls rs
318 primCode ls ReadByteArrayOp_Int8 rs = primCode_ReadByteArrayOp Int8Rep ls rs
319 primCode ls ReadByteArrayOp_Int16 rs = primCode_ReadByteArrayOp Int16Rep ls rs
320 primCode ls ReadByteArrayOp_Int32 rs = primCode_ReadByteArrayOp Int32Rep ls rs
321 primCode ls ReadByteArrayOp_Int64 rs = primCode_ReadByteArrayOp Int64Rep ls rs
322 primCode ls ReadByteArrayOp_Word8 rs = primCode_ReadByteArrayOp Word8Rep ls rs
323 primCode ls ReadByteArrayOp_Word16 rs = primCode_ReadByteArrayOp Word16Rep ls rs
324 primCode ls ReadByteArrayOp_Word32 rs = primCode_ReadByteArrayOp Word32Rep ls rs
325 primCode ls ReadByteArrayOp_Word64 rs = primCode_ReadByteArrayOp Word64Rep ls rs
327 primCode ls WriteByteArrayOp_Char rs = primCode_WriteByteArrayOp Word8Rep ls rs
328 primCode ls WriteByteArrayOp_WideChar rs = primCode_WriteByteArrayOp CharRep ls rs
329 primCode ls WriteByteArrayOp_Int rs = primCode_WriteByteArrayOp IntRep ls rs
330 primCode ls WriteByteArrayOp_Word rs = primCode_WriteByteArrayOp WordRep ls rs
331 primCode ls WriteByteArrayOp_Addr rs = primCode_WriteByteArrayOp AddrRep ls rs
332 primCode ls WriteByteArrayOp_Float rs = primCode_WriteByteArrayOp FloatRep ls rs
333 primCode ls WriteByteArrayOp_Double rs = primCode_WriteByteArrayOp DoubleRep ls rs
334 primCode ls WriteByteArrayOp_StablePtr rs = primCode_WriteByteArrayOp StablePtrRep ls rs
335 primCode ls WriteByteArrayOp_Int8 rs = primCode_WriteByteArrayOp Int8Rep ls rs
336 primCode ls WriteByteArrayOp_Int16 rs = primCode_WriteByteArrayOp Int16Rep ls rs
337 primCode ls WriteByteArrayOp_Int32 rs = primCode_WriteByteArrayOp Int32Rep ls rs
338 primCode ls WriteByteArrayOp_Int64 rs = primCode_WriteByteArrayOp Int64Rep ls rs
339 primCode ls WriteByteArrayOp_Word8 rs = primCode_WriteByteArrayOp Word8Rep ls rs
340 primCode ls WriteByteArrayOp_Word16 rs = primCode_WriteByteArrayOp Word16Rep ls rs
341 primCode ls WriteByteArrayOp_Word32 rs = primCode_WriteByteArrayOp Word32Rep ls rs
342 primCode ls WriteByteArrayOp_Word64 rs = primCode_WriteByteArrayOp Word64Rep ls rs
344 primCode ls IndexOffAddrOp_Char rs = primCode_IndexOffAddrOp Word8Rep ls rs
345 primCode ls IndexOffAddrOp_WideChar rs = primCode_IndexOffAddrOp CharRep ls rs
346 primCode ls IndexOffAddrOp_Int rs = primCode_IndexOffAddrOp IntRep ls rs
347 primCode ls IndexOffAddrOp_Word rs = primCode_IndexOffAddrOp WordRep ls rs
348 primCode ls IndexOffAddrOp_Addr rs = primCode_IndexOffAddrOp AddrRep ls rs
349 primCode ls IndexOffAddrOp_Float rs = primCode_IndexOffAddrOp FloatRep ls rs
350 primCode ls IndexOffAddrOp_Double rs = primCode_IndexOffAddrOp DoubleRep ls rs
351 primCode ls IndexOffAddrOp_StablePtr rs = primCode_IndexOffAddrOp StablePtrRep ls rs
352 primCode ls IndexOffAddrOp_Int8 rs = primCode_IndexOffAddrOp Int8Rep ls rs
353 primCode ls IndexOffAddrOp_Int16 rs = primCode_IndexOffAddrOp Int16Rep ls rs
354 primCode ls IndexOffAddrOp_Int32 rs = primCode_IndexOffAddrOp Int32Rep ls rs
355 primCode ls IndexOffAddrOp_Int64 rs = primCode_IndexOffAddrOp Int64Rep ls rs
356 primCode ls IndexOffAddrOp_Word8 rs = primCode_IndexOffAddrOp Word8Rep ls rs
357 primCode ls IndexOffAddrOp_Word16 rs = primCode_IndexOffAddrOp Word16Rep ls rs
358 primCode ls IndexOffAddrOp_Word32 rs = primCode_IndexOffAddrOp Word32Rep ls rs
359 primCode ls IndexOffAddrOp_Word64 rs = primCode_IndexOffAddrOp Word64Rep ls rs
361 primCode ls IndexOffForeignObjOp_Char rs = primCode_IndexOffForeignObjOp Word8Rep ls rs
362 primCode ls IndexOffForeignObjOp_WideChar rs = primCode_IndexOffForeignObjOp CharRep ls rs
363 primCode ls IndexOffForeignObjOp_Int rs = primCode_IndexOffForeignObjOp IntRep ls rs
364 primCode ls IndexOffForeignObjOp_Word rs = primCode_IndexOffForeignObjOp WordRep ls rs
365 primCode ls IndexOffForeignObjOp_Addr rs = primCode_IndexOffForeignObjOp AddrRep ls rs
366 primCode ls IndexOffForeignObjOp_Float rs = primCode_IndexOffForeignObjOp FloatRep ls rs
367 primCode ls IndexOffForeignObjOp_Double rs = primCode_IndexOffForeignObjOp DoubleRep ls rs
368 primCode ls IndexOffForeignObjOp_StablePtr rs = primCode_IndexOffForeignObjOp StablePtrRep ls rs
369 primCode ls IndexOffForeignObjOp_Int8 rs = primCode_IndexOffForeignObjOp Int8Rep ls rs
370 primCode ls IndexOffForeignObjOp_Int16 rs = primCode_IndexOffForeignObjOp Int16Rep ls rs
371 primCode ls IndexOffForeignObjOp_Int32 rs = primCode_IndexOffForeignObjOp Int32Rep ls rs
372 primCode ls IndexOffForeignObjOp_Int64 rs = primCode_IndexOffForeignObjOp Int64Rep ls rs
373 primCode ls IndexOffForeignObjOp_Word8 rs = primCode_IndexOffForeignObjOp Word8Rep ls rs
374 primCode ls IndexOffForeignObjOp_Word16 rs = primCode_IndexOffForeignObjOp Word16Rep ls rs
375 primCode ls IndexOffForeignObjOp_Word32 rs = primCode_IndexOffForeignObjOp Word32Rep ls rs
376 primCode ls IndexOffForeignObjOp_Word64 rs = primCode_IndexOffForeignObjOp Word64Rep ls rs
378 primCode ls ReadOffAddrOp_Char rs = primCode_IndexOffAddrOp Word8Rep ls rs
379 primCode ls ReadOffAddrOp_WideChar rs = primCode_IndexOffAddrOp CharRep ls rs
380 primCode ls ReadOffAddrOp_Int rs = primCode_IndexOffAddrOp IntRep ls rs
381 primCode ls ReadOffAddrOp_Word rs = primCode_IndexOffAddrOp WordRep ls rs
382 primCode ls ReadOffAddrOp_Addr rs = primCode_IndexOffAddrOp AddrRep ls rs
383 primCode ls ReadOffAddrOp_Float rs = primCode_IndexOffAddrOp FloatRep ls rs
384 primCode ls ReadOffAddrOp_Double rs = primCode_IndexOffAddrOp DoubleRep ls rs
385 primCode ls ReadOffAddrOp_StablePtr rs = primCode_IndexOffAddrOp StablePtrRep ls rs
386 primCode ls ReadOffAddrOp_Int8 rs = primCode_IndexOffAddrOp Int8Rep ls rs
387 primCode ls ReadOffAddrOp_Int16 rs = primCode_IndexOffAddrOp Int16Rep ls rs
388 primCode ls ReadOffAddrOp_Int32 rs = primCode_IndexOffAddrOp Int32Rep ls rs
389 primCode ls ReadOffAddrOp_Int64 rs = primCode_IndexOffAddrOp Int64Rep ls rs
390 primCode ls ReadOffAddrOp_Word8 rs = primCode_IndexOffAddrOp Word8Rep ls rs
391 primCode ls ReadOffAddrOp_Word16 rs = primCode_IndexOffAddrOp Word16Rep ls rs
392 primCode ls ReadOffAddrOp_Word32 rs = primCode_IndexOffAddrOp Word32Rep ls rs
393 primCode ls ReadOffAddrOp_Word64 rs = primCode_IndexOffAddrOp Word64Rep ls rs
395 primCode ls WriteOffAddrOp_Char rs = primCode_WriteOffAddrOp Word8Rep ls rs
396 primCode ls WriteOffAddrOp_WideChar rs = primCode_WriteOffAddrOp CharRep ls rs
397 primCode ls WriteOffAddrOp_Int rs = primCode_WriteOffAddrOp IntRep ls rs
398 primCode ls WriteOffAddrOp_Word rs = primCode_WriteOffAddrOp WordRep ls rs
399 primCode ls WriteOffAddrOp_Addr rs = primCode_WriteOffAddrOp AddrRep ls rs
400 primCode ls WriteOffAddrOp_Float rs = primCode_WriteOffAddrOp FloatRep ls rs
401 primCode ls WriteOffAddrOp_Double rs = primCode_WriteOffAddrOp DoubleRep ls rs
402 primCode ls WriteOffAddrOp_StablePtr rs = primCode_WriteOffAddrOp StablePtrRep ls rs
403 primCode ls WriteOffAddrOp_Int8 rs = primCode_WriteOffAddrOp Int8Rep ls rs
404 primCode ls WriteOffAddrOp_Int16 rs = primCode_WriteOffAddrOp Int16Rep ls rs
405 primCode ls WriteOffAddrOp_Int32 rs = primCode_WriteOffAddrOp Int32Rep ls rs
406 primCode ls WriteOffAddrOp_Int64 rs = primCode_WriteOffAddrOp Int64Rep ls rs
407 primCode ls WriteOffAddrOp_Word8 rs = primCode_WriteOffAddrOp Word8Rep ls rs
408 primCode ls WriteOffAddrOp_Word16 rs = primCode_WriteOffAddrOp Word16Rep ls rs
409 primCode ls WriteOffAddrOp_Word32 rs = primCode_WriteOffAddrOp Word32Rep ls rs
410 primCode ls WriteOffAddrOp_Word64 rs = primCode_WriteOffAddrOp Word64Rep ls rs
415 DataToTagOp won't work for 64-bit archs, as it is.
418 primCode [lhs] DataToTagOp [arg]
419 = let lhs' = amodeToStix lhs
420 arg' = amodeToStix arg
421 infoptr = StInd PtrRep arg'
422 word_32 = StInd WordRep (StIndex PtrRep infoptr (StInt (-1)))
423 masked_le32 = StPrim SrlOp [word_32, StInt 16]
424 masked_be32 = StPrim AndOp [word_32, StInt 65535]
425 #ifdef WORDS_BIGENDIAN
430 assign = StAssign IntRep lhs' masked
432 returnUs (\xs -> assign : xs)
435 MutVars are pretty simple.
436 #define writeMutVarzh(a,v) (P_)(((StgMutVar *)(a))->var)=(v)
439 primCode [] WriteMutVarOp [aa,vv]
440 = let aa_s = amodeToStix aa
441 vv_s = amodeToStix vv
442 var_field = StIndex PtrRep aa_s fixedHS
443 assign = StAssign PtrRep (StInd PtrRep var_field) vv_s
445 returnUs (\xs -> assign : xs)
447 primCode [rr] ReadMutVarOp [aa]
448 = let aa_s = amodeToStix aa
449 rr_s = amodeToStix rr
450 var_field = StIndex PtrRep aa_s fixedHS
451 assign = StAssign PtrRep rr_s (StInd PtrRep var_field)
453 returnUs (\xs -> assign : xs)
459 primCode [rr] ForeignObjToAddrOp [fo]
460 = let code = StAssign AddrRep (amodeToStix rr)
462 (StIndex PtrRep (amodeToStix fo) fixedHS))
464 returnUs (\xs -> code : xs)
466 primCode [] TouchOp [_] = returnUs id
469 Now the more mundane operations.
474 lhs' = map amodeToStix lhs
475 rhs' = map amodeToStix' rhs
476 pk = getAmodeRep (head lhs)
478 returnUs (\ xs -> simplePrim pk lhs' op rhs' : xs)
481 Helper fns for some array ops.
484 primCode_ReadByteArrayOp pk [lhs] [obj, ix]
486 lhs' = amodeToStix lhs
487 obj' = amodeToStix obj
489 base = StIndex IntRep obj' arrWordsHS
490 assign = StAssign pk lhs' (StInd pk (StIndex pk base ix'))
492 returnUs (\xs -> assign : xs)
495 primCode_IndexOffAddrOp pk [lhs] [obj, ix]
497 lhs' = amodeToStix lhs
498 obj' = amodeToStix obj
500 assign = StAssign pk lhs' (StInd pk (StIndex pk obj' ix'))
502 returnUs (\xs -> assign : xs)
505 primCode_IndexOffForeignObjOp pk [lhs] [obj, ix]
507 lhs' = amodeToStix lhs
508 obj' = amodeToStix obj
510 obj'' = StIndex AddrRep obj' fixedHS
511 assign = StAssign pk lhs' (StInd pk (StIndex pk obj'' ix'))
513 returnUs (\xs -> assign : xs)
516 primCode_WriteOffAddrOp pk [] [obj, ix, v]
518 obj' = amodeToStix obj
521 assign = StAssign pk (StInd pk (StIndex pk obj' ix')) v'
523 returnUs (\xs -> assign : xs)
526 primCode_WriteByteArrayOp pk [] [obj, ix, v]
528 obj' = amodeToStix obj
531 base = StIndex IntRep obj' arrWordsHS
532 assign = StAssign pk (StInd pk (StIndex pk base ix')) v'
534 returnUs (\xs -> assign : xs)
543 -> UniqSM StixTreeList
545 simpleCoercion pk lhs rhs
546 = returnUs (\xs -> StAssign pk (amodeToStix lhs) (amodeToStix rhs) : xs)
549 -- Rewrite a narrowing coercion into a pair of shifts.
551 :: PrimRep -> PrimRep
552 -> CAddrMode -> CAddrMode
553 -> UniqSM StixTreeList
555 narrowingCoercion pks pkd dst src
557 = panic "StixPrim.narrowingCoercion"
559 = returnUs (\xs -> StAssign pkd dst' src' : xs)
561 = returnUs (\xs -> assign : xs)
563 szs = getPrimRepSizeInBytes pks
564 szd = getPrimRepSizeInBytes pkd
565 src' = amodeToStix src
566 dst' = amodeToStix dst
567 shift_amt = fromIntegral (8 * (szs - szd))
571 (StPrim (if signed then ISraOp else SrlOp)
572 [StPrim SllOp [src', StInt shift_amt],
576 Int8Rep -> True; Int16Rep -> True
577 Int32Rep -> True; Int64Rep -> True; IntRep -> True
578 Word8Rep -> False; Word16Rep -> False
579 Word32Rep -> False; Word64Rep -> False; WordRep -> False
580 other -> pprPanic "StixPrim.narrowingCoercion" (ppr pkd)
583 Here we try to rewrite primitives into a form the code generator can
584 understand. Any primitives not handled here must be handled at the
585 level of the specific code generator.
589 :: PrimRep -- Rep of first destination
590 -> [StixTree] -- Destinations
596 Now look for something more conventional.
599 simplePrim pk [lhs] op rest = StAssign pk lhs (StPrim op rest)
600 simplePrim pk as op bs = ncgPrimopMoan "simplPrim(all targets)" (ppr op)
603 %---------------------------------------------------------------------
605 Here we generate the Stix code for CAddrModes.
607 When a character is fetched from a mixed type location, we have to do
608 an extra cast. This is reflected in amodeCode', which is for rhs
609 amodes that might possibly need the extra cast.
612 amodeToStix, amodeToStix' :: CAddrMode -> StixTree
614 amodeToStix'{-'-} am@(CVal rr CharRep)
615 | mixedTypeLocn am = StPrim ChrOp [amodeToStix am]
616 | otherwise = amodeToStix am
618 amodeToStix' am = amodeToStix am
621 amodeToStix am@(CVal rr CharRep)
623 = StInd IntRep (amodeToStix (CAddr rr))
625 amodeToStix (CVal rr pk) = StInd pk (amodeToStix (CAddr rr))
627 amodeToStix (CAddr (SpRel off))
628 = StIndex PtrRep stgSp (StInt (toInteger (iBox off)))
630 amodeToStix (CAddr (HpRel off))
631 = StIndex IntRep stgHp (StInt (toInteger (- (iBox off))))
633 amodeToStix (CAddr (NodeRel off))
634 = StIndex IntRep stgNode (StInt (toInteger (iBox off)))
636 amodeToStix (CAddr (CIndex base off pk))
637 = StIndex pk (amodeToStix base) (amodeToStix off)
639 amodeToStix (CReg magic) = StReg (StixMagicId magic)
640 amodeToStix (CTemp uniq pk) = StReg (StixTemp uniq pk)
642 amodeToStix (CLbl lbl _) = StCLbl lbl
644 -- For CharLike and IntLike, we attempt some trivial constant-folding here.
646 amodeToStix (CCharLike (CLit (MachChar c)))
647 = StIndex Word8Rep cHARLIKE_closure (StInt (toInteger off))
649 off = charLikeSize * (c - mIN_CHARLIKE)
651 amodeToStix (CCharLike x)
654 amodeToStix (CIntLike (CLit (MachInt i)))
655 = StIndex Word8Rep iNTLIKE_closure (StInt (toInteger off))
657 off = intLikeSize * (fromInteger (i - mIN_INTLIKE))
659 amodeToStix (CIntLike x)
662 amodeToStix (CLit core)
664 MachChar c -> StInt (toInteger c)
665 MachStr s -> StString s
666 MachAddr a -> StInt a
668 MachWord w -> case word2IntLit core of MachInt iw -> StInt iw
669 MachLitLit s _ -> litLitErr
670 MachLabel l -> StCLbl (mkForeignLabel l False{-ToDo: dynamic-})
671 MachFloat d -> StFloat d
672 MachDouble d -> StDouble d
673 _ -> panic "amodeToStix:core literal"
675 amodeToStix (CMacroExpr _ macro [arg])
677 ENTRY_CODE -> amodeToStix arg
678 ARG_TAG -> amodeToStix arg -- just an integer no. of words
680 #ifdef WORDS_BIGENDIAN
682 [StInd WordRep (StIndex PtrRep (amodeToStix arg)
683 (StInt (toInteger (-1)))),
687 [StInd WordRep (StIndex PtrRep (amodeToStix arg)
688 (StInt (toInteger (-1)))),
692 -> StInd PtrRep (StIndex PtrRep (amodeToStix arg)
693 (StInt (toInteger uF_UPDATEE)))
696 panic "native code generator can't compile lit-lits, use -fvia-C"
699 Sizes of the CharLike and IntLike closures that are arranged as arrays
700 in the data segment. (These are in bytes.)
703 -- The INTLIKE base pointer
705 iNTLIKE_closure :: StixTree
706 iNTLIKE_closure = StCLbl mkIntlikeClosureLabel
710 cHARLIKE_closure :: StixTree
711 cHARLIKE_closure = StCLbl mkCharlikeClosureLabel
713 mutArrPtrsFrozen_info = StCLbl mkMAP_FROZEN_infoLabel
715 -- these are the sizes of charLike and intLike closures, in _bytes_.
716 charLikeSize = (fixedHdrSize + 1) * (sizeOf PtrRep)
717 intLikeSize = (fixedHdrSize + 1) * (sizeOf PtrRep)
723 = getUniqueUs `thenUs` \tso_uq ->
724 let tso = StReg (StixTemp tso_uq ThreadIdRep) in
726 StAssign ThreadIdRep tso stgCurrentTSO :
728 (StInd PtrRep (StPrim IntAddOp
729 [tso, StInt (toInteger (TSO_SP*BYTES_PER_WORD))]))
732 (StInd PtrRep (StPrim IntAddOp
733 [tso, StInt (toInteger (TSO_SU*BYTES_PER_WORD))]))
736 (StInd PtrRep (StPrim IntAddOp
738 StInt (toInteger (BDESCR_FREE * BYTES_PER_WORD))]))
739 (StPrim IntAddOp [stgHp, StInt (toInteger (1 * BYTES_PER_WORD))]) :
744 = getUniqueUs `thenUs` \tso_uq ->
745 let tso = StReg (StixTemp tso_uq ThreadIdRep) in
747 StAssign ThreadIdRep tso stgCurrentTSO :
748 StAssign PtrRep stgSp
749 (StInd PtrRep (StPrim IntAddOp
750 [tso, StInt (toInteger (TSO_SP*BYTES_PER_WORD))])) :
751 StAssign PtrRep stgSu
752 (StInd PtrRep (StPrim IntAddOp
753 [tso, StInt (toInteger (TSO_SU*BYTES_PER_WORD))])) :
754 StAssign PtrRep stgSpLim
755 (StPrim IntAddOp [tso,
756 StInt (toInteger ((TSO_STACK + rESERVED_STACK_WORDS)
757 *BYTES_PER_WORD))]) :
758 StAssign PtrRep stgHp
760 StInd PtrRep (StPrim IntAddOp
762 StInt (toInteger (BDESCR_FREE * BYTES_PER_WORD))]),
763 StInt (toInteger (1 * BYTES_PER_WORD))
765 StAssign PtrRep stgHpLim
767 StInd PtrRep (StPrim IntAddOp
769 StInt (toInteger (BDESCR_START * BYTES_PER_WORD))]),
770 StInt (toInteger (bLOCK_SIZE - (1 * BYTES_PER_WORD)))