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(..), getPrimRepArrayElemSize )
21 import UniqSupply ( returnUs, thenUs, getUniqueUs, UniqSM )
22 import Constants ( wORD_SIZE,
23 mIN_INTLIKE, mIN_CHARLIKE, uF_UPDATEE, bLOCK_SIZE,
24 rESERVED_STACK_WORDS )
25 import CLabel ( mkIntlikeClosureLabel, mkCharlikeClosureLabel,
26 mkMAP_FROZEN_infoLabel,
28 import ForeignCall ( ForeignCall(..), CCallSpec(..), CCallTarget(..),
29 CCallConv(..), playSafe, playThreadSafe )
31 import Util ( notNull )
37 The main honchos here are primCode and foreignCallCode, which handle the guts of COpStmts.
41 :: [CAddrMode] -- results
43 -> [CAddrMode] -- args
44 -> UniqSM StixStmtList
47 %************************************************************************
49 \subsubsection{Code for foreign calls}
51 %************************************************************************
53 First, the dreaded @ccall@. We can't handle @casm@s.
55 Usually, this compiles to an assignment, but when the left-hand side
56 is empty, we just perform the call and ignore the result.
58 btw Why not let programmer use casm to provide assembly code instead
61 ToDo: saving/restoring of volatile regs around ccalls.
63 JRS, 001113: always do the call of suspendThread and resumeThread as a ccall
64 rather than inheriting the calling convention of the thing which we're really
68 foreignCallCode lhs call@(CCall (CCallSpec ctarget cconv safety)) rhs
70 | not (playSafe safety)
71 = returnUs (\xs -> ccall : xs)
74 = save_thread_state `thenUs` \ save ->
75 load_thread_state `thenUs` \ load ->
76 getUniqueUs `thenUs` \ uniq ->
78 id = StixTemp (StixVReg uniq IntRep)
81 | playThreadSafe safety = 1
84 suspend = StAssignReg IntRep id
85 (StCall (Left FSLIT("suspendThread")) {-no:cconv-} CCallConv
86 IntRep [StReg stgBaseReg, StInt is_threadSafe ])
88 (StCall (Left FSLIT("resumeThread")) {-no:cconv-} CCallConv
89 VoidRep [StReg id, StInt is_threadSafe ])
91 returnUs (\xs -> save (suspend : ccall : resume : load xs))
96 StaticTarget nm -> (rhs, Left nm)
97 DynamicTarget | notNull rhs -- an assertion
98 -> (tail rhs, Right (amodeToStix (head rhs)))
100 -> ncgPrimopMoan "Native code generator can't handle foreign call"
103 stix_args = map amodeCodeForCCall cargs
104 amodeCodeForCCall x =
105 let base = amodeToStix' x
107 case getAmodeRep x of
108 ArrayRep -> StIndex PtrRep base arrPtrsHS
109 ByteArrayRep -> StIndex IntRep base arrWordsHS
110 ForeignObjRep -> StInd PtrRep (StIndex PtrRep base fixedHS)
114 [] -> StVoidable (StCall stix_target cconv VoidRep stix_args)
115 [lhs] -> mkStAssign pk lhs' (StCall stix_target cconv pk stix_args)
117 lhs' = amodeToStix lhs
118 pk = case getAmodeRep lhs of
120 DoubleRep -> DoubleRep
122 Word64Rep -> Word64Rep
126 %************************************************************************
128 \subsubsection{Code for @CAddrMode@s}
130 %************************************************************************
132 When a character is fetched from a mixed type location, we have to do
133 an extra cast. This is reflected in amodeCode', which is for rhs
134 amodes that might possibly need the extra cast.
137 amodeToStix, amodeToStix' :: CAddrMode -> StixExpr
139 amodeToStix'{-'-} am@(CVal rr CharRep)
140 | mixedTypeLocn am = StMachOp MO_NatS_to_32U [amodeToStix am]
141 | otherwise = amodeToStix am
146 amodeToStix am@(CVal rr CharRep)
148 = StInd IntRep (amodeToStix (CAddr rr))
150 amodeToStix (CVal rr pk) = StInd pk (amodeToStix (CAddr rr))
152 amodeToStix CBytesPerWord
153 = StInt (toInteger wORD_SIZE)
155 amodeToStix (CAddr (SpRel off))
156 = StIndex PtrRep (StReg stgSp) (StInt (toInteger (iBox off)))
158 amodeToStix (CAddr (HpRel off))
159 = StIndex IntRep (StReg stgHp) (StInt (toInteger (- (iBox off))))
161 amodeToStix (CAddr (NodeRel off))
162 = StIndex IntRep (StReg stgNode) (StInt (toInteger (iBox off)))
164 amodeToStix (CAddr (CIndex base off pk))
165 = StIndex pk (amodeToStix base) (amodeToStix off)
167 amodeToStix (CReg magic) = StReg (StixMagicId magic)
168 amodeToStix (CTemp uniq pk) = StReg (StixTemp (StixVReg uniq pk))
170 amodeToStix (CLbl lbl _) = StCLbl lbl
172 -- For CharLike and IntLike, we attempt some trivial constant-folding here.
174 amodeToStix (CCharLike (CLit (MachChar c)))
175 = StIndex Word8Rep cHARLIKE_closure (StInt (toInteger off))
177 off = charLikeSize * (c - mIN_CHARLIKE)
179 amodeToStix (CCharLike x)
180 = panic "amodeToStix.CCharLike"
182 amodeToStix (CIntLike (CLit (MachInt i)))
183 = StIndex Word8Rep iNTLIKE_closure (StInt (toInteger off))
185 off = intLikeSize * (fromInteger (i - mIN_INTLIKE))
187 amodeToStix (CIntLike x)
188 = panic "amodeToStix.CIntLike"
190 amodeToStix (CLit core)
192 MachChar c -> StInt (toInteger c)
193 MachStr s -> StString s
194 MachAddr a -> StInt a
196 MachWord w -> case word2IntLit core of MachInt iw -> StInt iw
197 MachLitLit s _ -> litLitErr
198 MachLabel l -> StCLbl (mkForeignLabel l False{-ToDo: dynamic-})
199 MachFloat d -> StFloat d
200 MachDouble d -> StDouble d
201 _ -> panic "amodeToStix:core literal"
203 amodeToStix (CMacroExpr _ macro [arg])
205 ENTRY_CODE -> amodeToStix arg
206 ARG_TAG -> amodeToStix arg -- just an integer no. of words
208 #ifdef WORDS_BIGENDIAN
210 [StInd WordRep (StIndex PtrRep (amodeToStix arg)
211 (StInt (toInteger (-1)))),
215 [StInd WordRep (StIndex PtrRep (amodeToStix arg)
216 (StInt (toInteger (-1)))),
220 -> StInd PtrRep (StIndex PtrRep (amodeToStix arg)
221 (StInt (toInteger uF_UPDATEE)))
224 = pprPanic "StixPrim.amodeToStix" (pprAmode other)
227 = ncgPrimopMoan "native code generator can't handle lit-lits" empty
230 Sizes of the CharLike and IntLike closures that are arranged as arrays
231 in the data segment. (These are in bytes.)
234 -- The INTLIKE base pointer
236 iNTLIKE_closure :: StixExpr
237 iNTLIKE_closure = StCLbl mkIntlikeClosureLabel
241 cHARLIKE_closure :: StixExpr
242 cHARLIKE_closure = StCLbl mkCharlikeClosureLabel
244 mutArrPtrsFrozen_info = StCLbl mkMAP_FROZEN_infoLabel
246 -- these are the sizes of charLike and intLike closures, in _bytes_.
247 charLikeSize = (fixedHdrSize + 1) * (getPrimRepArrayElemSize PtrRep)
248 intLikeSize = (fixedHdrSize + 1) * (getPrimRepArrayElemSize PtrRep)
254 = getUniqueUs `thenUs` \ tso_uq ->
255 let tso = StixTemp (StixVReg tso_uq ThreadIdRep) in
257 StAssignReg ThreadIdRep tso (StReg stgCurrentTSO)
260 [StReg tso, StInt (toInteger (TSO_SP*BYTES_PER_WORD))])
264 [StReg tso, StInt (toInteger (TSO_SU*BYTES_PER_WORD))])
268 [StReg stgCurrentNursery,
269 StInt (toInteger (BDESCR_FREE * BYTES_PER_WORD))])
271 [StReg stgHp, StInt (toInteger (1 * BYTES_PER_WORD))])
276 = getUniqueUs `thenUs` \ tso_uq ->
277 let tso = StixTemp (StixVReg tso_uq ThreadIdRep) in
279 StAssignReg ThreadIdRep tso (StReg stgCurrentTSO)
284 [StReg tso, StInt (toInteger (TSO_SP*BYTES_PER_WORD))]))
289 [StReg tso, StInt (toInteger (TSO_SU*BYTES_PER_WORD))]))
294 StInt (toInteger ((TSO_STACK + rESERVED_STACK_WORDS)
301 [StReg stgCurrentNursery,
302 StInt (toInteger (BDESCR_FREE * BYTES_PER_WORD))]),
303 StInt (toInteger (1 * BYTES_PER_WORD))
309 (StIndex PtrRep (StReg stgCurrentNursery)
310 (StInt (toInteger BDESCR_START))
314 [StMachOp MO_NatU_Mul
316 (StIndex PtrRep (StReg stgCurrentNursery)
317 (StInt (toInteger BDESCR_BLOCKS))),
318 StInt (toInteger bLOCK_SIZE{-in bytes-})
320 StInt (1 * BYTES_PER_WORD)