2 % (c) The AQUA Project, Glasgow University, 1993-1996
6 #include "HsVersions.h"
9 gmpTake1Return1, gmpTake2Return1, gmpTake2Return2, gmpCompare,
10 gmpInteger2Int, gmpInt2Integer, gmpString2Integer,
11 encodeFloatingKind, decodeFloatingKind
15 #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <= 201
16 IMPORT_DELOOPER(NcgLoop) ( amodeToStix )
18 import {-# SOURCE #-} StixPrim ( amodeToStix )
21 #if __GLASGOW_HASKELL__ >= 202
22 import MachRegs hiding (Addr)
27 import AbsCSyn -- bits and bobs...
28 import Constants ( mIN_MP_INT_SIZE )
29 import Literal ( Literal(..) )
30 import OrdList ( OrdList )
31 import PrimOp ( PrimOp(..) )
32 import PrimRep ( PrimRep(..) )
33 import SMRep ( SMRep(..), SMSpecRepKind, SMUpdateKind )
34 import Stix ( getUniqLabelNCG, sStLitLbl, stgHp, stgHpLim,
35 StixTree(..), SYN_IE(StixTreeList),
38 import StixMacro ( macroCode, heapCheck )
39 import UniqSupply ( returnUs, thenUs, SYN_IE(UniqSM) )
45 :: (CAddrMode,CAddrMode,CAddrMode) -- result (3 parts)
46 -> FAST_STRING -- function name
47 -> (CAddrMode, CAddrMode,CAddrMode,CAddrMode)
49 -> UniqSM StixTreeList
51 argument1 = mpStruct 1 -- out here to avoid CAF (sigh)
52 argument2 = mpStruct 2
56 init2 = StCall SLIT("mpz_init") VoidRep [result2]
57 init3 = StCall SLIT("mpz_init") VoidRep [result3]
58 init4 = StCall SLIT("mpz_init") VoidRep [result4]
60 gmpTake1Return1 res@(car,csr,cdr) rtn arg@(clive,caa,csa,cda)
65 liveness= amodeToStix clive
70 space = mpSpace 2 1 [sa]
71 oldHp = StIndex PtrRep stgHp (StPrim IntNegOp [space])
73 save = StAssign PtrRep safeHp oldHp
74 (a1,a2,a3) = toStruct argument1 (aa,sa,da)
75 mpz_op = StCall rtn VoidRep [result2, argument1]
76 restore = StAssign PtrRep stgHp safeHp
77 (r1,r2,r3) = fromStruct result2 (ar,sr,dr)
79 heapCheck liveness space (StInt 0) `thenUs` \ heap_chk ->
82 (\xs -> a1 : a2 : a3 : save : init2 : mpz_op : r1 : r2 : r3 : restore : xs))
85 :: (CAddrMode,CAddrMode,CAddrMode) -- result (3 parts)
86 -> FAST_STRING -- function name
87 -> (CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode)
88 -- liveness + 2 arguments (3 parts each)
89 -> UniqSM StixTreeList
91 gmpTake2Return1 res@(car,csr,cdr) rtn args@(clive, caa1,csa1,cda1, caa2,csa2,cda2)
96 liveness= amodeToStix clive
97 aa1 = amodeToStix caa1
98 sa1 = amodeToStix csa1
99 da1 = amodeToStix cda1
100 aa2 = amodeToStix caa2
101 sa2 = amodeToStix csa2
102 da2 = amodeToStix cda2
104 space = mpSpace 3 1 [sa1, sa2]
105 oldHp = StIndex PtrRep stgHp (StPrim IntNegOp [space])
107 save = StAssign PtrRep safeHp oldHp
108 (a1,a2,a3) = toStruct argument1 (aa1,sa1,da1)
109 (a4,a5,a6) = toStruct argument2 (aa2,sa2,da2)
110 mpz_op = StCall rtn VoidRep [result3, argument1, argument2]
111 restore = StAssign PtrRep stgHp safeHp
112 (r1,r2,r3) = fromStruct result3 (ar,sr,dr)
114 heapCheck liveness space (StInt 0) `thenUs` \ heap_chk ->
117 (\xs -> a1 : a2 : a3 : a4 : a5 : a6
118 : save : init3 : mpz_op : r1 : r2 : r3 : restore : xs))
121 :: (CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode)
122 -- 2 results (3 parts each)
123 -> FAST_STRING -- function name
124 -> (CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode)
125 -- liveness + 2 arguments (3 parts each)
126 -> UniqSM StixTreeList
128 gmpTake2Return2 res@(car1,csr1,cdr1, car2,csr2,cdr2)
129 rtn args@(clive, caa1,csa1,cda1, caa2,csa2,cda2)
131 ar1 = amodeToStix car1
132 sr1 = amodeToStix csr1
133 dr1 = amodeToStix cdr1
134 ar2 = amodeToStix car2
135 sr2 = amodeToStix csr2
136 dr2 = amodeToStix cdr2
137 liveness= amodeToStix clive
138 aa1 = amodeToStix caa1
139 sa1 = amodeToStix csa1
140 da1 = amodeToStix cda1
141 aa2 = amodeToStix caa2
142 sa2 = amodeToStix csa2
143 da2 = amodeToStix cda2
145 space = StPrim IntMulOp [mpSpace 2 1 [sa1, sa2], StInt 2]
146 oldHp = StIndex PtrRep stgHp (StPrim IntNegOp [space])
148 save = StAssign PtrRep safeHp oldHp
149 (a1,a2,a3) = toStruct argument1 (aa1,sa1,da1)
150 (a4,a5,a6) = toStruct argument2 (aa2,sa2,da2)
151 mpz_op = StCall rtn VoidRep [result3, result4, argument1, argument2]
152 restore = StAssign PtrRep stgHp safeHp
153 (r1,r2,r3) = fromStruct result3 (ar1,sr1,dr1)
154 (r4,r5,r6) = fromStruct result4 (ar2,sr2,dr2)
157 heapCheck liveness space (StInt 0) `thenUs` \ heap_chk ->
160 (\xs -> a1 : a2 : a3 : a4 : a5 : a6
161 : save : init3 : init4 : mpz_op
162 : r1 : r2 : r3 : r4 : r5 : r6 : restore : xs))
165 Although gmpCompare doesn't allocate space, it does temporarily use
166 some space just beyond the heap pointer. This is safe, because the
167 enclosing routine has already guaranteed that this space will be
168 available. (See ``primOpHeapRequired.'')
172 :: CAddrMode -- result (boolean)
173 -> (CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode)
174 -- alloc hp + 2 arguments (3 parts each)
175 -> UniqSM StixTreeList
177 gmpCompare res args@(chp, caa1,csa1,cda1, caa2,csa2,cda2)
179 result = amodeToStix res
181 aa1 = amodeToStix caa1
182 sa1 = amodeToStix csa1
183 da1 = amodeToStix cda1
184 aa2 = amodeToStix caa2
185 sa2 = amodeToStix csa2
186 da2 = amodeToStix cda2
189 argument2 = StIndex IntRep hp (StInt (toInteger mpIntSize))
190 (a1,a2,a3) = toStruct argument1 (aa1,sa1,da1)
191 (a4,a5,a6) = toStruct argument2 (aa2,sa2,da2)
192 mpz_cmp = StCall SLIT("mpz_cmp") IntRep [argument1, argument2]
193 r1 = StAssign IntRep result mpz_cmp
195 returnUs (\xs -> a1 : a2 : a3 : a4 : a5 : a6 : r1 : xs)
198 See the comment above regarding the heap check (or lack thereof).
202 :: CAddrMode -- result
203 -> (CAddrMode, CAddrMode,CAddrMode,CAddrMode) -- alloc hp + argument (3 parts)
204 -> UniqSM StixTreeList
206 gmpInteger2Int res args@(chp, caa,csa,cda)
208 result = amodeToStix res
214 (a1,a2,a3) = toStruct hp (aa,sa,da)
215 mpz_get_si = StCall SLIT("mpz_get_si") IntRep [hp]
216 r1 = StAssign IntRep result mpz_get_si
218 returnUs (\xs -> a1 : a2 : a3 : r1 : xs)
220 arrayOfData_info = sStLitLbl SLIT("ArrayOfData_info")
224 :: (CAddrMode, CAddrMode, CAddrMode) -- result (3 parts)
225 -> (CAddrMode, CAddrMode) -- allocated heap, Int to convert
226 -> UniqSM StixTreeList
228 gmpInt2Integer res@(car,csr,cdr) args@(chp, n)
229 = getUniqLabelNCG `thenUs` \ zlbl ->
230 getUniqLabelNCG `thenUs` \ nlbl ->
231 getUniqLabelNCG `thenUs` \ jlbl ->
239 h1 = StAssign PtrRep (StInd PtrRep hp) arrayOfData_info
240 size = varHdrSizeInWords (DataRep 0) + mIN_MP_INT_SIZE
241 h2 = StAssign IntRep (StInd IntRep (StIndex IntRep hp (StInt 1)))
242 (StInt (toInteger size))
243 cts = StInd IntRep (StIndex IntRep hp dataHS)
244 test1 = StPrim IntEqOp [i, StInt 0]
245 test2 = StPrim IntLtOp [i, StInt 0]
246 cjmp1 = StCondJump zlbl test1
247 cjmp2 = StCondJump nlbl test2
249 p1 = StAssign IntRep cts i
250 p2 = StAssign IntRep sr (StInt 1)
251 p3 = StJump (StCLbl jlbl)
254 n1 = StAssign IntRep cts (StPrim IntNegOp [i])
255 n2 = StAssign IntRep sr (StInt (-1))
256 n3 = StJump (StCLbl jlbl)
259 z1 = StAssign IntRep sr (StInt 0)
262 a1 = StAssign IntRep ar (StInt 1)
263 a2 = StAssign PtrRep dr hp
267 CLit (MachInt c _) ->
268 if c == 0 then h1 : h2 : z1 : a1 : a2 : xs
269 else if c > 0 then h1 : h2 : p1 : p2 : a1 : a2 : xs
270 else h1 : h2 : n1 : n2 : a1 : a2 : xs
271 _ -> h1 : h2 : cjmp1 : cjmp2 : p1 : p2 : p3
272 : n0 : n1 : n2 : n3 : z0 : z1
276 :: (CAddrMode, CAddrMode, CAddrMode) -- result (3 parts)
277 -> (CAddrMode, CAddrMode) -- liveness, string
278 -> UniqSM StixTreeList
280 gmpString2Integer res@(car,csr,cdr) (liveness, str)
281 = getUniqLabelNCG `thenUs` \ ulbl ->
288 (CString s) -> _LENGTH_ s
289 (CLit (MachStr s)) -> _LENGTH_ s
290 _ -> panic "String2Integer"
291 space = len `quot` 8 + 17 + mpIntSize +
292 varHdrSizeInWords (DataRep 0) + fixedHdrSizeInWords
293 oldHp = StIndex PtrRep stgHp (StInt (toInteger (-space)))
295 save = StAssign PtrRep safeHp oldHp
296 result = StIndex IntRep stgHpLim (StInt (toInteger (-mpIntSize)))
297 set_str = StCall SLIT("mpz_init_set_str") IntRep
298 [result, amodeToStix str, StInt 10]
299 test = StPrim IntEqOp [set_str, StInt 0]
300 cjmp = StCondJump ulbl test
301 abort = StCall SLIT("abort") VoidRep []
303 restore = StAssign PtrRep stgHp safeHp
304 (a1,a2,a3) = fromStruct result (ar,sr,dr)
306 macroCode HEAP_CHK [liveness, mkIntCLit space, mkIntCLit_0]
307 `thenUs` \ heap_chk ->
310 (\xs -> save : cjmp : abort : join : a1 : a2 : a3 : restore : xs))
312 mkIntCLit_0 = mkIntCLit 0 -- out here to avoid CAF (sigh)
316 -> CAddrMode -- result
317 -> (CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode)
318 -- heap pointer for result, integer argument (3 parts), exponent
319 -> UniqSM StixTreeList
321 encodeFloatingKind pk res args@(chp, caa,csa,cda, cexpon)
323 result = amodeToStix res
328 expon = amodeToStix cexpon
330 pk' = if sizeOf FloatRep == sizeOf DoubleRep
333 (a1,a2,a3) = toStruct hp (aa,sa,da)
335 FloatRep -> SLIT("__encodeFloat")
336 DoubleRep -> SLIT("__encodeDouble")
337 _ -> panic "encodeFloatingKind"
338 encode = StCall fn pk' [hp, expon]
339 r1 = StAssign pk' result encode
341 returnUs (\xs -> a1 : a2 : a3 : r1 : xs)
345 -> (CAddrMode, CAddrMode, CAddrMode, CAddrMode)
346 -- exponent result, integer result (3 parts)
347 -> (CAddrMode, CAddrMode)
348 -- heap pointer for exponent, floating argument
349 -> UniqSM StixTreeList
351 decodeFloatingKind pk res@(cexponr,car,csr,cdr) args@(chp, carg)
353 exponr = amodeToStix cexponr
358 arg = amodeToStix carg
360 pk' = if sizeOf FloatRep == sizeOf DoubleRep
363 setup = StAssign PtrRep mpData_mantissa (StIndex IntRep hp (StInt 1))
365 FloatRep -> SLIT("__decodeFloat")
366 DoubleRep -> SLIT("__decodeDouble")
367 _ -> panic "decodeFloatingKind"
368 decode = StCall fn VoidRep [mantissa, hp, arg]
369 (a1,a2,a3) = fromStruct mantissa (ar,sr,dr)
370 a4 = StAssign IntRep exponr (StInd IntRep hp)
372 returnUs (\xs -> setup : decode : a1 : a2 : a3 : a4 : xs)
374 mantissa = mpStruct 1 -- out here to avoid CAF (sigh)
375 mpData_mantissa = mpData mantissa
378 Support for the Gnu GMP multi-precision package.
383 mpAlloc, mpSize, mpData :: StixTree -> StixTree
384 mpAlloc base = StInd IntRep base
385 mpSize base = StInd IntRep (StIndex IntRep base (StInt 1))
386 mpData base = StInd PtrRep (StIndex IntRep base (StInt 2))
389 :: Int -- gmp structures needed
390 -> Int -- number of results
391 -> [StixTree] -- sizes to add for estimating result size
392 -> StixTree -- total space
394 mpSpace gmp res sizes
395 = foldr sum (StPrim IntAddOp [fixed, hdrs]) sizes
397 sum x y = StPrim IntAddOp [StPrim IntAbsOp [x], y]
398 fixed = StInt (toInteger (17 * res + gmp * mpIntSize))
399 hdrs = StPrim IntMulOp [dataHS, StInt (toInteger res)]
402 We don't have a truly portable way of allocating local temporaries, so
403 we cheat and use space at the end of the heap. (Thus, negative
404 offsets from HpLim are our temporaries.) Note that you must have
405 performed a heap check which includes the space needed for these
406 temporaries before you use them.
409 mpStruct :: Int -> StixTree
410 mpStruct n = StIndex IntRep stgHpLim (StInt (toInteger (-(n * mpIntSize))))
414 -> (StixTree, StixTree, StixTree)
415 -> (StixTree, StixTree, StixTree)
417 toStruct str (alloc,size,arr)
419 f1 = StAssign IntRep (mpAlloc str) alloc
420 f2 = StAssign IntRep (mpSize str) size
421 f3 = StAssign PtrRep (mpData str) (StIndex PtrRep arr dataHS)
427 -> (StixTree, StixTree, StixTree)
428 -> (StixTree, StixTree, StixTree)
430 fromStruct str (alloc,size,arr)
432 e1 = StAssign IntRep alloc (mpAlloc str)
433 e2 = StAssign IntRep size (mpSize str)
434 e3 = StAssign PtrRep arr (StIndex PtrRep (mpData str)
435 (StPrim IntNegOp [dataHS]))