[project @ 2002-12-11 15:36:20 by simonmar]
[ghc-hetmet.git] / ghc / compiler / nativeGen / StixPrim.lhs
1 %
2 % (c) The AQUA Project, Glasgow University, 1993-1998
3 %
4
5 \begin{code}
6 module StixPrim ( amodeToStix, amodeToStix', foreignCallCode )
7 where
8
9 #include "HsVersions.h"
10
11 -- import MachMisc
12 import Stix
13
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, 
27                           mkForeignLabel )
28 import ForeignCall      ( ForeignCall(..), CCallSpec(..), CCallTarget(..),
29                           CCallConv(..), playSafe, playThreadSafe )
30 import Outputable
31 import Util             ( notNull )
32 import FastTypes
33
34 #include "NCG.h"
35 \end{code}
36
37 The main honchos here are primCode and foreignCallCode, which handle the guts of COpStmts.
38
39 \begin{code}
40 foreignCallCode
41     :: [CAddrMode]      -- results
42     -> ForeignCall      -- op
43     -> [CAddrMode]      -- args
44     -> UniqSM StixStmtList
45 \end{code}
46
47 %************************************************************************
48 %*                                                                      *
49 \subsubsection{Code for foreign calls}
50 %*                                                                      *
51 %************************************************************************
52
53 First, the dreaded @ccall@.  We can't handle @casm@s.
54
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.
57
58 btw Why not let programmer use casm to provide assembly code instead
59 of C code?  ADR
60
61 ToDo: saving/restoring of volatile regs around ccalls.
62
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
65 calling.
66
67 \begin{code}
68 foreignCallCode lhs call@(CCall (CCallSpec ctarget cconv safety)) rhs
69
70   | not (playSafe safety) 
71   = returnUs (\xs -> ccall : xs)
72
73   | otherwise
74   = save_thread_state `thenUs` \ save ->
75     load_thread_state `thenUs` \ load -> 
76     getUniqueUs       `thenUs` \ uniq -> 
77     let
78        id  = StixTemp (StixVReg uniq IntRep)
79        
80        is_threadSafe
81         | playThreadSafe safety = 1
82         | otherwise             = 0
83     
84        suspend = StAssignReg IntRep id 
85                  (StCall (Left FSLIT("suspendThread")) {-no:cconv-} CCallConv
86                          IntRep [StReg stgBaseReg, StInt is_threadSafe ])
87        resume  = StVoidable 
88                  (StCall (Left FSLIT("resumeThread")) {-no:cconv-} CCallConv
89                          VoidRep [StReg id, StInt is_threadSafe ])
90     in
91     returnUs (\xs -> save (suspend : ccall : resume : load xs))
92
93   where
94     (cargs, stix_target)
95         = case ctarget of
96              StaticTarget nm -> (rhs, Left nm)
97              DynamicTarget |  notNull rhs -- an assertion
98                            -> (tail rhs, Right (amodeToStix (head rhs)))
99              CasmTarget _
100                 -> ncgPrimopMoan "Native code generator can't handle foreign call" 
101                                  (ppr call)
102
103     stix_args = map amodeToStix' cargs
104
105     ccall = case lhs of
106       []    -> StVoidable (StCall stix_target cconv VoidRep stix_args)
107       [lhs] -> mkStAssign pk lhs' (StCall stix_target cconv pk stix_args)
108             where
109                lhs' = amodeToStix lhs
110                pk   = case getAmodeRep lhs of
111                         FloatRep  -> FloatRep
112                         DoubleRep -> DoubleRep
113                         Int64Rep  -> Int64Rep
114                         Word64Rep -> Word64Rep
115                         other     -> IntRep
116 \end{code}
117
118 %************************************************************************
119 %*                                                                      *
120 \subsubsection{Code for @CAddrMode@s}
121 %*                                                                      *
122 %************************************************************************
123
124 When a character is fetched from a mixed type location, we have to do
125 an extra cast.  This is reflected in amodeCode', which is for rhs
126 amodes that might possibly need the extra cast.
127
128 \begin{code}
129 amodeToStix, amodeToStix' :: CAddrMode -> StixExpr
130
131 amodeToStix'{-'-} am@(CVal rr CharRep)
132   | mixedTypeLocn am = StMachOp MO_NatS_to_32U [amodeToStix am]
133   | otherwise        = amodeToStix am
134 amodeToStix' am 
135   = amodeToStix am
136
137 -----------
138 amodeToStix am@(CVal rr CharRep)
139   | mixedTypeLocn am
140   = StInd IntRep (amodeToStix (CAddr rr))
141
142 amodeToStix (CVal rr pk) = StInd pk (amodeToStix (CAddr rr))
143
144 amodeToStix CBytesPerWord
145   = StInt (toInteger wORD_SIZE)
146
147 amodeToStix (CAddr (SpRel off))
148   = StIndex PtrRep (StReg stgSp) (StInt (toInteger (iBox off)))
149
150 amodeToStix (CAddr (HpRel off))
151   = StIndex IntRep (StReg stgHp) (StInt (toInteger (- (iBox off))))
152
153 amodeToStix (CAddr (NodeRel off))
154   = StIndex IntRep (StReg stgNode) (StInt (toInteger (iBox off)))
155
156 amodeToStix (CAddr (CIndex base off pk))
157   = StIndex pk (amodeToStix base) (amodeToStix off)
158
159 amodeToStix (CReg magic)    = StReg (StixMagicId magic)
160 amodeToStix (CTemp uniq pk) = StReg (StixTemp (StixVReg uniq pk))
161
162 amodeToStix (CLbl      lbl _) = StCLbl lbl
163
164  -- For CharLike and IntLike, we attempt some trivial constant-folding here.
165
166 amodeToStix (CCharLike (CLit (MachChar c)))
167   = StIndex Word8Rep cHARLIKE_closure (StInt (toInteger off))
168   where
169     off = charLikeSize * (c - mIN_CHARLIKE)
170
171 amodeToStix (CCharLike x)
172   = panic "amodeToStix.CCharLike"
173
174 amodeToStix (CIntLike (CLit (MachInt i)))
175   = StIndex Word8Rep iNTLIKE_closure (StInt (toInteger off))
176   where
177     off = intLikeSize * (fromInteger (i - mIN_INTLIKE))
178
179 amodeToStix (CIntLike x)
180   = panic "amodeToStix.CIntLike"
181
182 amodeToStix (CLit core)
183   = case core of
184       MachChar c     -> StInt (toInteger c)
185       MachStr s      -> StString s
186       MachAddr a     -> StInt a
187       MachInt i      -> StInt i
188       MachWord w     -> case word2IntLit core of MachInt iw -> StInt iw
189       MachLitLit s _ -> litLitErr
190       MachLabel l    -> StCLbl (mkForeignLabel l False{-ToDo: dynamic-})
191       MachFloat d    -> StFloat d
192       MachDouble d   -> StDouble d
193       _ -> panic "amodeToStix:core literal"
194
195 amodeToStix (CMacroExpr _ macro [arg])
196   = let 
197         arg_amode = amodeToStix arg
198     in  
199     case macro of
200       ENTRY_CODE -> arg_amode
201       ARG_TAG    -> arg_amode -- just an integer no. of words
202       GET_TAG    -> 
203 #ifdef WORDS_BIGENDIAN
204                     StMachOp MO_Nat_And
205                         [StInd WordRep (StIndex PtrRep arg_amode
206                                                 (StInt (toInteger (-1)))),
207                          StInt 65535]
208 #else
209                     StMachOp MO_Nat_Shr
210                         [StInd WordRep (StIndex PtrRep arg_amode
211                                                 (StInt (toInteger (-1)))),
212                          StInt 16]
213 #endif
214       UPD_FRAME_UPDATEE
215          -> StInd PtrRep (StIndex PtrRep arg_amode 
216                                          (StInt (toInteger uF_UPDATEE)))
217
218       BYTE_ARR_CTS -> StIndex IntRep arg_amode arrWordsHS
219       PTRS_ARR_CTS -> StIndex PtrRep arg_amode arrPtrsHS
220       ForeignObj_CLOSURE_DATA -> StInd PtrRep (StIndex PtrRep arg_amode fixedHS)
221
222
223 amodeToStix other
224    = pprPanic "StixPrim.amodeToStix" (pprAmode other)
225
226 litLitErr 
227    = ncgPrimopMoan "native code generator can't handle lit-lits" empty
228 \end{code}
229
230 Sizes of the CharLike and IntLike closures that are arranged as arrays
231 in the data segment.  (These are in bytes.)
232
233 \begin{code}
234 -- The INTLIKE base pointer
235
236 iNTLIKE_closure :: StixExpr
237 iNTLIKE_closure = StCLbl mkIntlikeClosureLabel
238
239 -- The CHARLIKE base
240
241 cHARLIKE_closure :: StixExpr
242 cHARLIKE_closure = StCLbl mkCharlikeClosureLabel
243
244 mutArrPtrsFrozen_info = StCLbl mkMAP_FROZEN_infoLabel
245
246 -- these are the sizes of charLike and intLike closures, in _bytes_.
247 charLikeSize = (fixedHdrSize + 1) * (getPrimRepSizeInBytes PtrRep)
248 intLikeSize  = (fixedHdrSize + 1) * (getPrimRepSizeInBytes PtrRep)
249 \end{code}
250
251
252 \begin{code}
253 save_thread_state 
254    = getUniqueUs   `thenUs` \ tso_uq -> 
255      let tso = StixTemp (StixVReg tso_uq PtrRep) in
256      returnUs (\xs ->
257         StAssignReg PtrRep tso (StReg stgCurrentTSO)
258         : StAssignMem PtrRep
259              (StMachOp MO_Nat_Add
260                        [StReg tso, StInt (toInteger (TSO_SP*BYTES_PER_WORD))])
261              (StReg stgSp)
262         : StAssignMem PtrRep
263              (StMachOp MO_Nat_Add
264                        [StReg stgCurrentNursery, 
265                         StInt (toInteger (BDESCR_FREE * BYTES_PER_WORD))])
266              (StMachOp MO_Nat_Add 
267                        [StReg stgHp, StInt (toInteger (1 * BYTES_PER_WORD))]) 
268         : xs
269      )
270
271 load_thread_state 
272    = getUniqueUs   `thenUs` \ tso_uq -> 
273      let tso = StixTemp (StixVReg tso_uq PtrRep) in
274      returnUs (\xs ->
275         StAssignReg PtrRep tso (StReg stgCurrentTSO)
276         : StAssignReg PtrRep 
277              stgSp
278              (StInd PtrRep 
279                   (StMachOp MO_Nat_Add
280                             [StReg tso, StInt (toInteger (TSO_SP*BYTES_PER_WORD))]))
281         : StAssignReg PtrRep 
282              stgSpLim
283              (StMachOp MO_Nat_Add 
284                        [StReg tso, 
285                         StInt (toInteger ((TSO_STACK + rESERVED_STACK_WORDS)
286                                           *BYTES_PER_WORD))])
287         : StAssignReg PtrRep 
288              stgHp
289              (StMachOp MO_Nat_Sub 
290                        [StInd PtrRep 
291                               (StMachOp MO_Nat_Add
292                                         [StReg stgCurrentNursery, 
293                                          StInt (toInteger (BDESCR_FREE * BYTES_PER_WORD))]),
294                         StInt (toInteger (1 * BYTES_PER_WORD))
295                        ]) 
296         : StAssignReg PtrRep 
297              stgHpLim
298              (StIndex Word8Rep 
299                 (StInd PtrRep 
300                        (StIndex PtrRep (StReg stgCurrentNursery)
301                                        (StInt (toInteger BDESCR_START))
302                        )
303                 )
304                 (StMachOp MO_Nat_Sub
305                    [StMachOp MO_NatU_Mul
306                       [StInd WordRep 
307                              (StIndex PtrRep (StReg stgCurrentNursery)
308                                              (StInt (toInteger BDESCR_BLOCKS))),
309                        StInt (toInteger bLOCK_SIZE{-in bytes-})
310                       ],
311                       StInt (1 * BYTES_PER_WORD)
312                    ]
313                 )
314
315              ) 
316
317         : xs
318      )
319 \end{code}