2 % (c) The AQUA Project, Glasgow University, 1993-1995
6 #include "HsVersions.h"
9 gmpTake1Return1, gmpTake2Return1, gmpTake2Return2,
10 gmpCompare, gmpInteger2Int, gmpInt2Integer, gmpString2Integer,
11 encodeFloatingKind, decodeFloatingKind
14 IMPORT_Trace -- ToDo: rm debugging
17 import CgCompInfo ( mIN_MP_INT_SIZE )
20 import AbsPrel ( PrimOp(..)
21 IF_ATTACK_PRAGMAS(COMMA tagOf_PrimOp)
22 IF_ATTACK_PRAGMAS(COMMA pprPrimOp)
24 import SMRep ( SMRep(..), SMSpecRepKind, SMUpdateKind(..) )
36 -> (CAddrMode,CAddrMode,CAddrMode) -- result (3 parts)
37 -> FAST_STRING -- function name
38 -> (CAddrMode, CAddrMode,CAddrMode,CAddrMode)
40 -> SUniqSM StixTreeList
42 argument1 = mpStruct 1 -- out here to avoid CAF (sigh)
43 argument2 = mpStruct 2
47 init2 = StCall SLIT("mpz_init") VoidKind [result2]
48 init3 = StCall SLIT("mpz_init") VoidKind [result3]
49 init4 = StCall SLIT("mpz_init") VoidKind [result4]
51 -- hacking with Uncle Will:
52 #define target_STRICT target@(Target _ _ _ _ _ _ _ _)
54 gmpTake1Return1 target_STRICT res@(car,csr,cdr) rtn arg@(clive,caa,csa,cda) =
56 a2stix = amodeToStix target
57 data_hs = dataHS target
62 liveness= a2stix clive
67 space = mpSpace data_hs 2 1 [sa]
68 oldHp = StIndex PtrKind stgHp (StPrim IntNegOp [space])
69 safeHp = saveLoc target Hp
70 save = StAssign PtrKind safeHp oldHp
71 (a1,a2,a3) = toStruct data_hs argument1 (aa,sa,da)
72 mpz_op = StCall rtn VoidKind [result2, argument1]
73 restore = StAssign PtrKind stgHp safeHp
74 (r1,r2,r3) = fromStruct data_hs result2 (ar,sr,dr)
76 heapCheck target liveness space (StInt 0) `thenSUs` \ heap_chk ->
79 (\xs -> a1 : a2 : a3 : save : init2 : mpz_op : r1 : r2 : r3 : restore : xs))
83 -> (CAddrMode,CAddrMode,CAddrMode) -- result (3 parts)
84 -> FAST_STRING -- function name
85 -> (CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode)
86 -- liveness + 2 arguments (3 parts each)
87 -> SUniqSM StixTreeList
89 gmpTake2Return1 target_STRICT res@(car,csr,cdr) rtn args@(clive, caa1,csa1,cda1, caa2,csa2,cda2) =
91 a2stix = amodeToStix target
92 data_hs = dataHS target
97 liveness= a2stix clive
105 space = mpSpace data_hs 3 1 [sa1, sa2]
106 oldHp = StIndex PtrKind stgHp (StPrim IntNegOp [space])
107 safeHp = saveLoc target Hp
108 save = StAssign PtrKind safeHp oldHp
109 (a1,a2,a3) = toStruct data_hs argument1 (aa1,sa1,da1)
110 (a4,a5,a6) = toStruct data_hs argument2 (aa2,sa2,da2)
111 mpz_op = StCall rtn VoidKind [result3, argument1, argument2]
112 restore = StAssign PtrKind stgHp safeHp
113 (r1,r2,r3) = fromStruct data_hs result3 (ar,sr,dr)
115 heapCheck target liveness space (StInt 0) `thenSUs` \ heap_chk ->
117 returnSUs (heap_chk .
118 (\xs -> a1 : a2 : a3 : a4 : a5 : a6
119 : save : init3 : mpz_op : r1 : r2 : r3 : restore : xs))
123 -> (CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode)
124 -- 2 results (3 parts each)
125 -> FAST_STRING -- function name
126 -> (CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode)
127 -- liveness + 2 arguments (3 parts each)
128 -> SUniqSM StixTreeList
130 gmpTake2Return2 target_STRICT res@(car1,csr1,cdr1, car2,csr2,cdr2)
131 rtn args@(clive, caa1,csa1,cda1, caa2,csa2,cda2) =
133 a2stix = amodeToStix target
134 data_hs = dataHS target
142 liveness= a2stix clive
150 space = StPrim IntMulOp [mpSpace data_hs 2 1 [sa1, sa2], StInt 2]
151 oldHp = StIndex PtrKind stgHp (StPrim IntNegOp [space])
152 safeHp = saveLoc target Hp
153 save = StAssign PtrKind safeHp oldHp
154 (a1,a2,a3) = toStruct data_hs argument1 (aa1,sa1,da1)
155 (a4,a5,a6) = toStruct data_hs argument2 (aa2,sa2,da2)
156 mpz_op = StCall rtn VoidKind [result3, result4, argument1, argument2]
157 restore = StAssign PtrKind stgHp safeHp
158 (r1,r2,r3) = fromStruct data_hs result3 (ar1,sr1,dr1)
159 (r4,r5,r6) = fromStruct data_hs result4 (ar2,sr2,dr2)
162 heapCheck target liveness space (StInt 0) `thenSUs` \ heap_chk ->
164 returnSUs (heap_chk .
165 (\xs -> a1 : a2 : a3 : a4 : a5 : a6
166 : save : init3 : init4 : mpz_op
167 : r1 : r2 : r3 : r4 : r5 : r6 : restore : xs))
171 Although gmpCompare doesn't allocate space, it does temporarily use
172 some space just beyond the heap pointer. This is safe, because the
173 enclosing routine has already guaranteed that this space will be
174 available. (See ``primOpHeapRequired.'')
180 -> CAddrMode -- result (boolean)
181 -> (CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode)
182 -- alloc hp + 2 arguments (3 parts each)
183 -> SUniqSM StixTreeList
185 gmpCompare target_STRICT res args@(chp, caa1,csa1,cda1, caa2,csa2,cda2) =
187 a2stix = amodeToStix target
188 data_hs = dataHS target
200 argument2 = StIndex IntKind hp (StInt (toInteger mpIntSize))
201 (a1,a2,a3) = toStruct data_hs argument1 (aa1,sa1,da1)
202 (a4,a5,a6) = toStruct data_hs argument2 (aa2,sa2,da2)
203 mpz_cmp = StCall SLIT("mpz_cmp") IntKind [argument1, argument2]
204 r1 = StAssign IntKind result mpz_cmp
206 returnSUs (\xs -> a1 : a2 : a3 : a4 : a5 : a6 : r1 : xs)
210 See the comment above regarding the heap check (or lack thereof).
216 -> CAddrMode -- result
217 -> (CAddrMode, CAddrMode,CAddrMode,CAddrMode) -- alloc hp + argument (3 parts)
218 -> SUniqSM StixTreeList
220 gmpInteger2Int target_STRICT res args@(chp, caa,csa,cda) =
222 a2stix = amodeToStix target
223 data_hs = dataHS target
231 (a1,a2,a3) = toStruct data_hs hp (aa,sa,da)
232 mpz_get_si = StCall SLIT("mpz_get_si") IntKind [hp]
233 r1 = StAssign IntKind result mpz_get_si
235 returnSUs (\xs -> a1 : a2 : a3 : r1 : xs)
237 arrayOfData_info = sStLitLbl SLIT("ArrayOfData_info")
241 -> (CAddrMode, CAddrMode, CAddrMode) -- result (3 parts)
242 -> (CAddrMode, CAddrMode) -- allocated heap, Int to convert
243 -> SUniqSM StixTreeList
245 gmpInt2Integer target_STRICT res@(car,csr,cdr) args@(chp, n) =
246 getUniqLabelNCG `thenSUs` \ zlbl ->
247 getUniqLabelNCG `thenSUs` \ nlbl ->
248 getUniqLabelNCG `thenSUs` \ jlbl ->
250 a2stix = amodeToStix target
258 h1 = StAssign PtrKind (StInd PtrKind hp) arrayOfData_info
259 size = varHeaderSize target (DataRep 0) + mIN_MP_INT_SIZE
260 h2 = StAssign IntKind (StInd IntKind (StIndex IntKind hp (StInt 1)))
261 (StInt (toInteger size))
262 cts = StInd IntKind (StIndex IntKind hp (dataHS target))
263 test1 = StPrim IntEqOp [i, StInt 0]
264 test2 = StPrim IntLtOp [i, StInt 0]
265 cjmp1 = StCondJump zlbl test1
266 cjmp2 = StCondJump nlbl test2
268 p1 = StAssign IntKind cts i
269 p2 = StAssign IntKind sr (StInt 1)
270 p3 = StJump (StCLbl jlbl)
273 n1 = StAssign IntKind cts (StPrim IntNegOp [i])
274 n2 = StAssign IntKind sr (StInt (-1))
275 n3 = StJump (StCLbl jlbl)
278 z1 = StAssign IntKind sr (StInt 0)
281 a1 = StAssign IntKind ar (StInt 1)
282 a2 = StAssign PtrKind dr hp
286 CLit (MachInt c _) ->
287 if c == 0 then h1 : h2 : z1 : a1 : a2 : xs
288 else if c > 0 then h1 : h2 : p1 : p2 : a1 : a2 : xs
289 else h1 : h2 : n1 : n2 : a1 : a2 : xs
290 _ -> h1 : h2 : cjmp1 : cjmp2 : p1 : p2 : p3
291 : n0 : n1 : n2 : n3 : z0 : z1
296 -> (CAddrMode, CAddrMode, CAddrMode) -- result (3 parts)
297 -> (CAddrMode, CAddrMode) -- liveness, string
298 -> SUniqSM StixTreeList
300 gmpString2Integer target_STRICT res@(car,csr,cdr) (liveness, str) =
301 getUniqLabelNCG `thenSUs` \ ulbl ->
303 a2stix = amodeToStix target
304 data_hs = dataHS target
311 (CString s) -> _LENGTH_ s
312 (CLit (MachStr s)) -> _LENGTH_ s
313 _ -> panic "String2Integer"
314 space = len `quot` 8 + 17 + mpIntSize +
315 varHeaderSize target (DataRep 0) + fixedHeaderSize target
316 oldHp = StIndex PtrKind stgHp (StInt (toInteger (-space)))
317 safeHp = saveLoc target Hp
318 save = StAssign PtrKind safeHp oldHp
319 result = StIndex IntKind stgHpLim (StInt (toInteger (-mpIntSize)))
320 set_str = StCall SLIT("mpz_init_set_str") IntKind
321 [result, a2stix str, StInt 10]
322 test = StPrim IntEqOp [set_str, StInt 0]
323 cjmp = StCondJump ulbl test
324 abort = StCall SLIT("abort") VoidKind []
326 restore = StAssign PtrKind stgHp safeHp
327 (a1,a2,a3) = fromStruct data_hs result (ar,sr,dr)
329 macroCode target HEAP_CHK [liveness, mkIntCLit space, mkIntCLit_0]
330 `thenSUs` \ heap_chk ->
332 returnSUs (heap_chk .
333 (\xs -> save : cjmp : abort : join : a1 : a2 : a3 : restore : xs))
335 mkIntCLit_0 = mkIntCLit 0 -- out here to avoid CAF (sigh)
340 -> CAddrMode -- result
341 -> (CAddrMode,CAddrMode,CAddrMode,CAddrMode,CAddrMode)
342 -- heap pointer for result, integer argument (3 parts), exponent
343 -> SUniqSM StixTreeList
345 encodeFloatingKind pk target_STRICT res args@(chp, caa,csa,cda, cexpon) =
347 a2stix = amodeToStix target
348 size_of = sizeof target
349 data_hs = dataHS target
356 expon = a2stix cexpon
358 pk' = if size_of FloatKind == size_of DoubleKind
361 (a1,a2,a3) = toStruct data_hs hp (aa,sa,da)
363 FloatKind -> SLIT("__encodeFloat")
364 DoubleKind -> SLIT("__encodeDouble")
365 _ -> panic "encodeFloatingKind"
366 encode = StCall fn pk' [hp, expon]
367 r1 = StAssign pk' result encode
369 returnSUs (\xs -> a1 : a2 : a3 : r1 : xs)
374 -> (CAddrMode, CAddrMode, CAddrMode, CAddrMode)
375 -- exponent result, integer result (3 parts)
376 -> (CAddrMode, CAddrMode)
377 -- heap pointer for exponent, floating argument
378 -> SUniqSM StixTreeList
380 decodeFloatingKind pk target_STRICT res@(cexponr,car,csr,cdr) args@(chp, carg) =
382 a2stix = amodeToStix target
383 size_of = sizeof target
384 data_hs = dataHS target
386 exponr = a2stix cexponr
393 pk' = if size_of FloatKind == size_of DoubleKind
396 setup = StAssign PtrKind mpData_mantissa (StIndex IntKind hp (StInt 1))
398 FloatKind -> SLIT("__decodeFloat")
399 DoubleKind -> SLIT("__decodeDouble")
400 _ -> panic "decodeFloatingKind"
401 decode = StCall fn VoidKind [mantissa, hp, arg]
402 (a1,a2,a3) = fromStruct data_hs mantissa (ar,sr,dr)
403 a4 = StAssign IntKind exponr (StInd IntKind hp)
405 returnSUs (\xs -> setup : decode : a1 : a2 : a3 : a4 : xs)
407 mantissa = mpStruct 1 -- out here to avoid CAF (sigh)
408 mpData_mantissa = mpData mantissa
411 Support for the Gnu GMP multi-precision package.
417 mpAlloc, mpSize, mpData :: StixTree -> StixTree
418 mpAlloc base = StInd IntKind base
419 mpSize base = StInd IntKind (StIndex IntKind base (StInt 1))
420 mpData base = StInd PtrKind (StIndex IntKind base (StInt 2))
423 :: StixTree -- dataHs from Target
424 -> Int -- gmp structures needed
425 -> Int -- number of results
426 -> [StixTree] -- sizes to add for estimating result size
427 -> StixTree -- total space
429 mpSpace data_hs gmp res sizes =
430 foldr sum (StPrim IntAddOp [fixed, hdrs]) sizes
432 sum x y = StPrim IntAddOp [StPrim IntAbsOp [x], y]
433 fixed = StInt (toInteger (17 * res + gmp * mpIntSize))
434 hdrs = StPrim IntMulOp [data_hs, StInt (toInteger res)]
438 We don't have a truly portable way of allocating local temporaries, so we
439 cheat and use space at the end of the heap. (Thus, negative offsets from
440 HpLim are our temporaries.) Note that you must have performed a heap check
441 which includes the space needed for these temporaries before you use them.
444 mpStruct :: Int -> StixTree
445 mpStruct n = StIndex IntKind stgHpLim (StInt (toInteger (-(n * mpIntSize))))
448 :: StixTree -- dataHS, from Target
450 -> (StixTree, StixTree, StixTree)
451 -> (StixTree, StixTree, StixTree)
453 toStruct data_hs str (alloc,size,arr) =
455 f1 = StAssign IntKind (mpAlloc str) alloc
456 f2 = StAssign IntKind (mpSize str) size
457 f3 = StAssign PtrKind (mpData str) (StIndex PtrKind arr data_hs)
462 :: StixTree -- dataHS, from Target
464 -> (StixTree, StixTree, StixTree)
465 -> (StixTree, StixTree, StixTree)
467 fromStruct data_hs str (alloc,size,arr) =
469 e1 = StAssign IntKind alloc (mpAlloc str)
470 e2 = StAssign IntKind size (mpSize str)
471 e3 = StAssign PtrKind arr (StIndex PtrKind (mpData str)
472 (StPrim IntNegOp [data_hs]))