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 ( 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 )
38 The main honchos here are primCode and foreignCallCode, which handle the guts of COpStmts.
42 :: [CAddrMode] -- results
44 -> [CAddrMode] -- args
45 -> UniqSM StixStmtList
48 %************************************************************************
50 \subsubsection{Code for foreign calls}
52 %************************************************************************
54 First, the dreaded @ccall@. We can't handle @casm@s.
56 Usually, this compiles to an assignment, but when the left-hand side
57 is empty, we just perform the call and ignore the result.
59 btw Why not let programmer use casm to provide assembly code instead
62 ToDo: saving/restoring of volatile regs around ccalls.
64 JRS, 001113: always do the call of suspendThread and resumeThread as a ccall
65 rather than inheriting the calling convention of the thing which we're really
69 foreignCallCode lhs call@(CCall (CCallSpec ctarget cconv safety)) rhs
71 | not (playSafe safety)
72 = returnUs (\xs -> ccall : xs)
75 = save_thread_state `thenUs` \ save ->
76 load_thread_state `thenUs` \ load ->
77 getUniqueUs `thenUs` \ uniq ->
79 id = StixTemp (StixVReg uniq IntRep)
82 | playThreadSafe safety = 1
85 suspend = StAssignReg IntRep id
86 (StCall (Left FSLIT("suspendThread")) {-no:cconv-} CCallConv
87 IntRep [StReg stgBaseReg, StInt is_threadSafe ])
89 (StCall (Left FSLIT("resumeThread")) {-no:cconv-} CCallConv
90 VoidRep [StReg id, StInt is_threadSafe ])
92 returnUs (\xs -> save (suspend : ccall : resume : load xs))
97 StaticTarget nm -> (rhs, Left nm)
98 DynamicTarget | notNull rhs -- an assertion
99 -> (tail rhs, Right (amodeToStix (head rhs)))
101 -> ncgPrimopMoan "Native code generator can't handle foreign call"
104 stix_args = map amodeToStix' cargs
107 [] -> StVoidable (StCall stix_target cconv VoidRep stix_args)
108 [lhs] -> mkStAssign pk lhs' (StCall stix_target cconv pk stix_args)
110 lhs' = amodeToStix lhs
111 pk = case getAmodeRep lhs of
113 DoubleRep -> DoubleRep
115 Word64Rep -> Word64Rep
118 -- a bit late to catch this here..
119 foreignCallCode _ DNCall{} _
120 = panic "foreignCallCode: .NET interop not supported via NCG; compile with -fvia-C"
123 %************************************************************************
125 \subsubsection{Code for @CAddrMode@s}
127 %************************************************************************
129 When a character is fetched from a mixed type location, we have to do
130 an extra cast. This is reflected in amodeCode', which is for rhs
131 amodes that might possibly need the extra cast.
134 amodeToStix, amodeToStix' :: CAddrMode -> StixExpr
136 amodeToStix'{-'-} am@(CVal rr CharRep)
137 | mixedTypeLocn am = StMachOp MO_NatS_to_32U [amodeToStix am]
138 | otherwise = amodeToStix am
143 amodeToStix am@(CVal rr CharRep)
145 = StInd IntRep (amodeToStix (CAddr rr))
147 amodeToStix (CVal rr pk) = StInd pk (amodeToStix (CAddr rr))
149 amodeToStix (CAddr (SpRel off))
150 = StIndex PtrRep (StReg stgSp) (StInt (toInteger (iBox off)))
152 amodeToStix (CAddr (HpRel off))
153 = StIndex IntRep (StReg stgHp) (StInt (toInteger (- (iBox off))))
155 amodeToStix (CAddr (NodeRel off))
156 = StIndex IntRep (StReg stgNode) (StInt (toInteger (iBox off)))
158 amodeToStix (CAddr (CIndex base off pk))
159 = StIndex pk (amodeToStix base) (amodeToStix off)
161 amodeToStix (CReg magic) = StReg (StixMagicId magic)
162 amodeToStix (CTemp uniq pk) = StReg (StixTemp (StixVReg uniq pk))
164 amodeToStix (CLbl lbl _) = StCLbl lbl
166 -- For CharLike and IntLike, we attempt some trivial constant-folding here.
168 amodeToStix (CCharLike (CLit (MachChar c)))
169 = StIndex Word8Rep cHARLIKE_closure (StInt (toInteger off))
171 off = charLikeSize * (c - mIN_CHARLIKE)
173 amodeToStix (CCharLike x)
174 = panic "amodeToStix.CCharLike"
176 amodeToStix (CIntLike (CLit (MachInt i)))
177 = StIndex Word8Rep iNTLIKE_closure (StInt (toInteger off))
179 off = intLikeSize * (fromInteger (i - mIN_INTLIKE))
181 amodeToStix (CIntLike x)
182 = panic "amodeToStix.CIntLike"
184 amodeToStix (CLit core)
186 MachChar c -> StInt (toInteger c)
187 MachStr s -> StString s
188 MachNullAddr -> StInt 0
190 MachWord w -> case word2IntLit core of MachInt iw -> StInt iw
191 MachLitLit s _ -> litLitErr
192 -- dreadful, but rare.
193 MachLabel l (Just x) -> StCLbl (mkForeignLabel (mkFastString (unpackFS l ++ '@':show x)) False)
194 MachLabel l _ -> StCLbl (mkForeignLabel l False{-ToDo: dynamic-})
195 MachFloat d -> StFloat d
196 MachDouble d -> StDouble d
197 _ -> panic "amodeToStix:core literal"
199 amodeToStix (CMacroExpr _ macro [arg])
201 arg_amode = amodeToStix arg
204 ENTRY_CODE -> arg_amode
205 ARG_TAG -> arg_amode -- just an integer no. of words
207 #ifdef WORDS_BIGENDIAN
209 [StInd WordRep (StIndex PtrRep arg_amode
210 (StInt (toInteger (-1)))),
214 [StInd WordRep (StIndex PtrRep arg_amode
215 (StInt (toInteger (-1)))),
219 -> StInd PtrRep (StIndex PtrRep arg_amode
220 (StInt (toInteger uF_UPDATEE)))
222 BYTE_ARR_CTS -> StIndex IntRep arg_amode arrWordsHS
223 PTRS_ARR_CTS -> StIndex PtrRep arg_amode arrPtrsHS
224 ForeignObj_CLOSURE_DATA -> StInd PtrRep (StIndex PtrRep arg_amode fixedHS)
228 = pprPanic "StixPrim.amodeToStix" (pprAmode other)
231 = ncgPrimopMoan "native code generator can't handle lit-lits" empty
234 Sizes of the CharLike and IntLike closures that are arranged as arrays
235 in the data segment. (These are in bytes.)
238 -- The INTLIKE base pointer
240 iNTLIKE_closure :: StixExpr
241 iNTLIKE_closure = StCLbl mkIntlikeClosureLabel
245 cHARLIKE_closure :: StixExpr
246 cHARLIKE_closure = StCLbl mkCharlikeClosureLabel
248 mutArrPtrsFrozen_info = StCLbl mkMAP_FROZEN_infoLabel
250 -- these are the sizes of charLike and intLike closures, in _bytes_.
251 charLikeSize = (fixedHdrSize + 1) * (getPrimRepSizeInBytes PtrRep)
252 intLikeSize = (fixedHdrSize + 1) * (getPrimRepSizeInBytes PtrRep)
258 = getUniqueUs `thenUs` \ tso_uq ->
259 let tso = StixTemp (StixVReg tso_uq PtrRep) in
261 StAssignReg PtrRep tso (StReg stgCurrentTSO)
264 [StReg tso, StInt (toInteger (TSO_SP*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 PtrRep) in
279 StAssignReg PtrRep tso (StReg stgCurrentTSO)
284 [StReg tso, StInt (toInteger (TSO_SP*BYTES_PER_WORD))]))
289 StInt (toInteger ((TSO_STACK + rESERVED_STACK_WORDS)
296 [StReg stgCurrentNursery,
297 StInt (toInteger (BDESCR_FREE * BYTES_PER_WORD))]),
298 StInt (toInteger (1 * BYTES_PER_WORD))
304 (StIndex PtrRep (StReg stgCurrentNursery)
305 (StInt (toInteger BDESCR_START))
309 [StMachOp MO_NatU_Mul
311 (StIndex PtrRep (StReg stgCurrentNursery)
312 (StInt (toInteger BDESCR_BLOCKS))),
313 StInt (toInteger bLOCK_SIZE{-in bytes-})
315 StInt (1 * BYTES_PER_WORD)