2 % (c) The AQUA Project, Glasgow University, 1993-1998
6 module StixPrim ( amodeToStix, amodeToStix', foreignCallCode )
9 #include "HsVersions.h"
14 import PprAbsC ( pprAmode )
15 import AbsCSyn hiding ( spRel )
16 import AbsCUtils ( getAmodeRep, mixedTypeLocn )
17 import SMRep ( fixedHdrSize )
18 import Literal ( Literal(..), word2IntLit )
19 import MachOp ( MachOp(..) )
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 and foreignCallCode, which handle the guts of COpStmts.
39 :: [CAddrMode] -- results
41 -> [CAddrMode] -- args
42 -> UniqSM StixStmtList
45 %************************************************************************
47 \subsubsection{Code for foreign calls}
49 %************************************************************************
51 First, the dreaded @ccall@. We can't handle @casm@s.
53 Usually, this compiles to an assignment, but when the left-hand side
54 is empty, we just perform the call and ignore the result.
56 btw Why not let programmer use casm to provide assembly code instead
59 ToDo: saving/restoring of volatile regs around ccalls.
61 JRS, 001113: always do the call of suspendThread and resumeThread as a ccall
62 rather than inheriting the calling convention of the thing which we're really
66 foreignCallCode lhs (CCall (CCallSpec (StaticTarget fn) cconv safety)) rhs
68 | not (playSafe safety)
69 = returnUs (\xs -> ccall : xs)
72 = save_thread_state `thenUs` \ save ->
73 load_thread_state `thenUs` \ load ->
74 getUniqueUs `thenUs` \ uniq ->
76 id = StixTemp (StixVReg uniq IntRep)
78 suspend = StAssignReg IntRep id
79 (StCall SLIT("suspendThread") {-no:cconv-} CCallConv
80 IntRep [StReg stgBaseReg])
82 (StCall SLIT("resumeThread") {-no:cconv-} CCallConv
85 returnUs (\xs -> save (suspend : ccall : resume : load xs))
88 args = map amodeCodeForCCall rhs
90 let base = amodeToStix' x
93 ArrayRep -> StIndex PtrRep base arrPtrsHS
94 ByteArrayRep -> StIndex IntRep base arrWordsHS
95 ForeignObjRep -> StInd PtrRep (StIndex PtrRep base fixedHS)
99 [] -> StVoidable (StCall fn cconv VoidRep args)
100 [lhs] -> mkStAssign pk lhs' (StCall fn cconv pk args)
102 lhs' = amodeToStix lhs
103 pk = case getAmodeRep lhs of
105 DoubleRep -> DoubleRep
108 foreignCallCode lhs call rhs
109 = ncgPrimopMoan "Native code generator can't handle foreign call" (ppr call)
112 %************************************************************************
114 \subsubsection{Code for @CAddrMode@s}
116 %************************************************************************
118 When a character is fetched from a mixed type location, we have to do
119 an extra cast. This is reflected in amodeCode', which is for rhs
120 amodes that might possibly need the extra cast.
123 amodeToStix, amodeToStix' :: CAddrMode -> StixExpr
125 amodeToStix'{-'-} am@(CVal rr CharRep)
126 | mixedTypeLocn am = StMachOp MO_NatS_to_32U [amodeToStix am]
127 | otherwise = amodeToStix am
132 amodeToStix am@(CVal rr CharRep)
134 = StInd IntRep (amodeToStix (CAddr rr))
136 amodeToStix (CVal rr pk) = StInd pk (amodeToStix (CAddr rr))
138 amodeToStix (CMem pk addr) = StInd pk (amodeToStix addr)
140 amodeToStix (CAddr (SpRel off))
141 = StIndex PtrRep (StReg stgSp) (StInt (toInteger (iBox off)))
143 amodeToStix (CAddr (HpRel off))
144 = StIndex IntRep (StReg stgHp) (StInt (toInteger (- (iBox off))))
146 amodeToStix (CAddr (NodeRel off))
147 = StIndex IntRep (StReg stgNode) (StInt (toInteger (iBox off)))
149 amodeToStix (CAddr (CIndex base off pk))
150 = StIndex pk (amodeToStix base) (amodeToStix off)
152 amodeToStix (CReg magic) = StReg (StixMagicId magic)
153 amodeToStix (CTemp uniq pk) = StReg (StixTemp (StixVReg uniq pk))
155 amodeToStix (CLbl lbl _) = StCLbl lbl
157 -- For CharLike and IntLike, we attempt some trivial constant-folding here.
159 amodeToStix (CCharLike (CLit (MachChar c)))
160 = StIndex Word8Rep cHARLIKE_closure (StInt (toInteger off))
162 off = charLikeSize * (c - mIN_CHARLIKE)
164 amodeToStix (CCharLike x)
165 = panic "amodeToStix.CCharLike"
167 amodeToStix (CIntLike (CLit (MachInt i)))
168 = StIndex Word8Rep iNTLIKE_closure (StInt (toInteger off))
170 off = intLikeSize * (fromInteger (i - mIN_INTLIKE))
172 amodeToStix (CIntLike x)
173 = panic "amodeToStix.CIntLike"
175 amodeToStix (CLit core)
177 MachChar c -> StInt (toInteger c)
178 MachStr s -> StString s
179 MachAddr a -> StInt a
181 MachWord w -> case word2IntLit core of MachInt iw -> StInt iw
182 MachLitLit s _ -> litLitErr
183 MachLabel l -> StCLbl (mkForeignLabel l False{-ToDo: dynamic-})
184 MachFloat d -> StFloat d
185 MachDouble d -> StDouble d
186 _ -> panic "amodeToStix:core literal"
188 amodeToStix (CMacroExpr _ macro [arg])
190 ENTRY_CODE -> amodeToStix arg
191 ARG_TAG -> amodeToStix arg -- just an integer no. of words
193 #ifdef WORDS_BIGENDIAN
195 [StInd WordRep (StIndex PtrRep (amodeToStix arg)
196 (StInt (toInteger (-1)))),
200 [StInd WordRep (StIndex PtrRep (amodeToStix arg)
201 (StInt (toInteger (-1)))),
205 -> StInd PtrRep (StIndex PtrRep (amodeToStix arg)
206 (StInt (toInteger uF_UPDATEE)))
209 = pprPanic "StixPrim.amodeToStix" (pprAmode other)
212 = ncgPrimopMoan "native code generator can't handle lit-lits" empty
215 Sizes of the CharLike and IntLike closures that are arranged as arrays
216 in the data segment. (These are in bytes.)
219 -- The INTLIKE base pointer
221 iNTLIKE_closure :: StixExpr
222 iNTLIKE_closure = StCLbl mkIntlikeClosureLabel
226 cHARLIKE_closure :: StixExpr
227 cHARLIKE_closure = StCLbl mkCharlikeClosureLabel
229 mutArrPtrsFrozen_info = StCLbl mkMAP_FROZEN_infoLabel
231 -- these are the sizes of charLike and intLike closures, in _bytes_.
232 charLikeSize = (fixedHdrSize + 1) * (sizeOf PtrRep)
233 intLikeSize = (fixedHdrSize + 1) * (sizeOf PtrRep)
239 = getUniqueUs `thenUs` \ tso_uq ->
240 let tso = StixTemp (StixVReg tso_uq ThreadIdRep) in
242 StAssignReg ThreadIdRep tso (StReg stgCurrentTSO)
245 [StReg tso, StInt (toInteger (TSO_SP*BYTES_PER_WORD))])
249 [StReg tso, StInt (toInteger (TSO_SU*BYTES_PER_WORD))])
253 [StReg stgCurrentNursery,
254 StInt (toInteger (BDESCR_FREE * BYTES_PER_WORD))])
256 [StReg stgHp, StInt (toInteger (1 * BYTES_PER_WORD))])
261 = getUniqueUs `thenUs` \ tso_uq ->
262 let tso = StixTemp (StixVReg tso_uq ThreadIdRep) in
264 StAssignReg ThreadIdRep tso (StReg stgCurrentTSO)
269 [StReg tso, StInt (toInteger (TSO_SP*BYTES_PER_WORD))]))
274 [StReg tso, StInt (toInteger (TSO_SU*BYTES_PER_WORD))]))
279 StInt (toInteger ((TSO_STACK + rESERVED_STACK_WORDS)
286 [StReg stgCurrentNursery,
287 StInt (toInteger (BDESCR_FREE * BYTES_PER_WORD))]),
288 StInt (toInteger (1 * BYTES_PER_WORD))
295 [StReg stgCurrentNursery,
296 StInt (toInteger (BDESCR_START * BYTES_PER_WORD))]),
297 StInt (toInteger (bLOCK_SIZE - (1 * BYTES_PER_WORD)))