2 % (c) The GRASP/AQUA Project, Glasgow University, 1994-1996
5 % ---------------------------------------------------------------------------
7 \section[Costs]{Evaluating the costs of computing some abstract C code}
9 This module provides all necessary functions for computing for a given
10 abstract~C Program the costs of executing that program. This is done by the
14 {\verb type CostRes = (Int, Int, Int, Int, Int)}
15 {\verb costs :: AbstractC -> CostRes }
18 The meaning of the result tuple is:
20 \item The first component ({\tt i}) counts the number of integer,
21 arithmetic and bit-manipulating instructions.
22 \item The second component ({\tt b}) counts the number of branches (direct
23 branches as well as indirect ones).
24 \item The third component ({\tt l}) counts the number of load instructions.
25 \item The fourth component ({\tt s}) counts the number of store
27 \item The fifth component ({\tt f}) counts the number of floating point
31 This function is needed in GrAnSim for parallelism.
33 These are first suggestions for scaling the costs. But, this scaling should be done in the RTS rather than the compiler (this really should be tunable!):
39 #define INT_ARITHM_COSTS 1
40 #define GMP_ARITHM_COSTS 3 {- any clue for GMP costs ? -}
41 #define FLOAT_ARITHM_COSTS 3 {- any clue for float costs ? -}
42 #define BRANCH_COSTS 2
47 #include "HsVersions.h"
49 #define ACCUM_COSTS(i,b,l,s,f) (i+b+l+s+f)
51 #define NUM_REGS 10 {- PprAbsCSyn.lhs -} {- runtime/c-as-asm/CallWrap_C.lc -}
52 #define RESTORE_COSTS (Cost (0, 0, NUM_REGS, 0, 0) :: CostRes)
53 #define SAVE_COSTS (Cost (0, 0, 0, NUM_REGS, 0) :: CostRes)
54 #define CCALL_COSTS_GUESS (Cost (50, 0, 0, 0, 0) :: CostRes)
57 addrModeCosts, CostRes(Cost), nullCosts, Side(..)
63 import PrimOp ( primOpNeedsWrapper, PrimOp(..) )
65 -- --------------------------------------------------------------------------
66 data CostRes = Cost (Int, Int, Int, Int, Int)
69 nullCosts = Cost (0, 0, 0, 0, 0) :: CostRes
70 initHdrCosts = Cost (2, 0, 0, 1, 0) :: CostRes
71 errorCosts = Cost (-1, -1, -1, -1, -1) -- just for debugging
73 oneArithm = Cost (1, 0, 0, 0, 0) :: CostRes
75 instance Eq CostRes where
76 (==) t1 t2 = i && b && l && s && f
77 where (i,b,l,s,f) = binOp' (==) t1 t2
79 instance Num CostRes where
87 mapOp :: (Int -> Int) -> CostRes -> CostRes
88 mapOp g ( Cost (i, b, l, s, f) ) = Cost (g i, g b, g l, g s, g f)
90 foldrOp :: (Int -> a -> a) -> a -> CostRes -> a
91 foldrOp o x ( Cost (i1, b1, l1, s1, f1) ) =
92 i1 `o` ( b1 `o` ( l1 `o` ( s1 `o` ( f1 `o` x))))
94 binOp :: (Int -> Int -> Int) -> CostRes -> CostRes -> CostRes
95 binOp o ( Cost (i1, b1, l1, s1, f1) ) ( Cost (i2, b2, l2, s2, f2) ) =
96 ( Cost (i1 `o` i2, b1 `o` b2, l1 `o` l2, s1 `o` s2, f1 `o` f2) )
98 binOp' :: (Int -> Int -> a) -> CostRes -> CostRes -> (a,a,a,a,a)
99 binOp' o ( Cost (i1, b1, l1, s1, f1) ) ( Cost (i2, b2, l2, s2, f2) ) =
100 (i1 `o` i2, b1 `o` b2, l1 `o` l2, s1 `o` s2, f1 `o` f2)
102 -- --------------------------------------------------------------------------
104 data Side = Lhs | Rhs
107 -- --------------------------------------------------------------------------
109 costs :: AbstractC -> CostRes
115 AbsCStmts absC1 absC2 -> costs absC1 + costs absC2
117 CAssign (CReg _) (CReg _) -> Cost (1,0,0,0,0) -- typ.: mov %reg1,%reg2
119 CAssign (CReg _) (CTemp _ _) -> Cost (1,0,0,0,0)
121 CAssign (CReg _) (CAddr _) -> Cost (1,0,0,0,0) -- typ.: add %reg1,<adr>,%reg2
123 CAssign target_m source_m -> addrModeCosts target_m Lhs +
124 addrModeCosts source_m Rhs
126 CJump (CLbl _ _) -> Cost (0,1,0,0,0) -- no ld for call necessary
128 CJump mode -> addrModeCosts mode Rhs +
131 CFallThrough mode -> addrModeCosts mode Rhs + -- chu' 0.24
134 CReturn mode info -> case info of
135 DirectReturn -> addrModeCosts mode Rhs +
138 -- i.e. ld address to reg and call reg
140 DynamicVectoredReturn mode' ->
141 addrModeCosts mode Rhs +
142 addrModeCosts mode' Rhs +
145 {- generates code like this:
146 JMP_(<mode>)[RVREL(<mode'>)];
147 i.e. 1 possb ld for mode'
152 StaticVectoredReturn _ -> addrModeCosts mode Rhs +
155 -- as above with mode' fixed to CLit
156 -- typically 2 ld + 1 call; 1st ld due
159 CSwitch mode alts absC -> nullCosts
160 {- for handling costs of all branches of
161 a CSwitch see PprAbsC.
164 Costs before CSwitch +
165 addrModeCosts of head +
166 Costs for 1 cond branch +
167 Costs for body of branch
170 CCodeBlock _ absC -> costs absC
172 CInitHdr cl_info reg_rel cost_centre inplace_upd -> initHdrCosts
174 {- This is more fancy but superflous: The addr modes
175 are fixed and so the costs are const!
177 argCosts + initHdrCosts
178 where argCosts = addrModeCosts (CAddr reg_rel) Rhs +
179 addrModeCosts base_lbl + -- CLbl!
180 3*addrModeCosts (mkIntCLit 1{- any val -})
182 {- this extends to something like
184 For costing the args of this macro
185 see PprAbsC.lhs where args are inserted -}
187 COpStmt modes_res primOp modes_args _ _ ->
194 if primOpNeedsWrapper primOp then SAVE_COSTS + RESTORE_COSTS
198 foldl (+) nullCosts [addrModeCosts mode Lhs | mode <- modes_res] +
199 foldl (+) nullCosts [addrModeCosts mode Rhs | mode <- modes_args] +
201 if primOpNeedsWrapper primOp then SAVE_COSTS + RESTORE_COSTS
204 CSimultaneous absC -> costs absC
206 CMacroStmt macro modes -> stmtMacroCosts macro modes
208 CCallProfCtrMacro _ _ -> nullCosts
209 {- we don't count profiling in GrAnSim -}
211 CCallProfCCMacro _ _ -> nullCosts
212 {- we don't count profiling in GrAnSim -}
214 -- *** the next three [or so...] are DATA (those above are CODE) ***
215 -- as they are data rather than code they all have nullCosts -- HWL
217 CStaticClosure _ _ _ _ -> nullCosts
219 CClosureInfoAndCode _ _ _ _ _ _ -> nullCosts
221 CRetVector _ _ _ -> nullCosts
223 CRetUnVector _ _ -> nullCosts
225 CFlatRetVector _ _ -> nullCosts
227 CCostCentreDecl _ _ -> nullCosts
229 CClosureUpdInfo _ -> nullCosts
231 CSplitMarker -> nullCosts
233 -- ---------------------------------------------------------------------------
235 addrModeCosts :: CAddrMode -> Side -> CostRes
237 -- addrModeCosts _ _ = nullCosts
239 addrModeCosts addr_mode side =
244 CVal _ _ -> if lhs then Cost (0, 0, 0, 1, 0)
245 else Cost (0, 0, 1, 0, 0)
247 CAddr _ -> if lhs then Cost (0, 0, 0, 1, 0) -- ??unchecked
248 else Cost (0, 0, 1, 0, 0)
250 CReg _ -> nullCosts {- loading from, storing to reg is free ! -}
251 {- for costing CReg->Creg ops see special -}
252 {- case in costs fct -}
253 CTableEntry base_mode offset_mode kind ->
254 addrModeCosts base_mode side +
255 addrModeCosts offset_mode side +
258 CTemp _ _ -> nullCosts {- if lhs then Cost (0, 0, 0, 1, 0)
259 else Cost (0, 0, 1, 0, 0) -}
260 -- ``Temporaries'' correspond to local variables in C, and registers in
262 -- I assume they can be somewhat optimized by gcc -- HWL
264 CLbl _ _ -> if lhs then Cost (0, 0, 0, 1, 0)
265 else Cost (2, 0, 0, 0, 0)
266 -- Rhs: typically: sethi %hi(lbl),%tmp_reg
267 -- or %tmp_reg,%lo(lbl),%target_reg
269 CUnVecLbl _ _ -> if lhs then Cost (0, 0, 0, 1, 0)
270 else Cost (2, 0, 0, 0, 0)
273 -- Check the following 3 (checked form CLit on)
275 CCharLike mode -> if lhs then Cost (0, 0, 0, 1, 0)
276 else Cost (0, 0, 1, 0, 0)
278 CIntLike mode -> if lhs then Cost (0, 0, 0, 1, 0)
279 else Cost (0, 0, 1, 0, 0)
281 CString _ -> if lhs then Cost (0, 0, 0, 1, 0)
282 else Cost (0, 0, 1, 0, 0)
284 CLit _ -> if lhs then nullCosts -- should never occur
285 else Cost (1, 0, 0, 0, 0) -- typ.: mov lit,%reg
287 CLitLit _ _ -> if lhs then nullCosts
288 else Cost (1, 0, 0, 0, 0)
291 COffset _ -> if lhs then nullCosts
292 else Cost (1, 0, 0, 0, 0)
295 CCode absC -> costs absC
297 CLabelledCode _ absC -> costs absC
299 CJoinPoint _ _ -> if lhs then Cost (0, 0, 0, 1, 0)
300 else Cost (0, 0, 1, 0, 0)
302 CMacroExpr _ macro mode_list -> exprMacroCosts side macro mode_list
304 CCostCentre _ _ -> nullCosts
306 -- ---------------------------------------------------------------------------
308 exprMacroCosts :: Side -> CExprMacro -> [CAddrMode] -> CostRes
310 exprMacroCosts side macro mode_list =
312 arg_costs = foldl (+) nullCosts
313 (map (\ x -> addrModeCosts x Rhs) mode_list)
317 INFO_PTR -> if side == Lhs then Cost (0, 0, 0, 1, 0)
318 else Cost (0, 0, 1, 0, 0)
319 ENTRY_CODE -> nullCosts
320 INFO_TAG -> if side == Lhs then Cost (0, 0, 0, 1, 0)
321 else Cost (0, 0, 1, 0, 0)
322 EVAL_TAG -> if side == Lhs then Cost (1, 0, 0, 1, 0)
323 else Cost (1, 0, 1, 0, 0)
324 -- costs of INFO_TAG + (1,0,0,0,0)
326 -- ---------------------------------------------------------------------------
328 stmtMacroCosts :: CStmtMacro -> [CAddrMode] -> CostRes
330 stmtMacroCosts macro modes =
332 arg_costs = foldl (+) nullCosts
333 [addrModeCosts mode Rhs | mode <- modes]
336 ARGS_CHK_A_LOAD_NODE -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
337 -- p=probability of PAP (instead of AP): + p*(3,1,0,0,0)
338 ARGS_CHK_A -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
339 -- p=probability of PAP (instead of AP): + p*(0,1,0,0,0)
340 ARGS_CHK_B_LOAD_NODE -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
341 ARGS_CHK_B -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
342 HEAP_CHK -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
343 -- STK_CHK -> (2, 1, 0, 0, 0) {- StgMacros.lh -}
344 STK_CHK -> Cost (0, 0, 0, 0, 0) {- StgMacros.lh -}
345 UPD_CAF -> Cost (7, 0, 1, 3, 0) {- SMupdate.lh -}
346 UPD_IND -> Cost (8, 2, 2, 0, 0) {- SMupdate.lh
347 updatee in old-gen: Cost (4, 1, 1, 0, 0)
348 updatee in new-gen: Cost (4, 1, 1, 0, 0)
349 NB: we include costs fo checking if there is
350 a BQ, but we omit costs for awakening BQ
351 (these probably differ between old-gen and
353 UPD_INPLACE_NOPTRS -> Cost (13, 3, 3, 2, 0) {- SMupdate.lh
354 common for both: Cost (4, 1, 1, 0, 0)
355 updatee in old-gen: Cost (14, 3, 2, 4, 0)
356 updatee in new-gen: Cost (4, 1, 1, 0, 0) -}
357 UPD_INPLACE_PTRS -> Cost (13, 3, 3, 2, 0) {- SMupdate.lh
358 common for both: Cost (4, 1, 1, 0, 0)
359 updatee in old-gen: Cost (14, 3, 2, 4, 0)
360 updatee in new-gen: Cost (4, 1, 1, 0, 0) -}
362 UPD_BH_UPDATABLE -> Cost (3, 0, 0, 1, 0) {- SMupdate.lh -}
363 UPD_BH_SINGLE_ENTRY -> Cost (3, 0, 0, 1, 0) {- SMupdate.lh -}
364 PUSH_STD_UPD_FRAME -> Cost (3, 0, 0, 4, 0) {- SMupdate.lh -}
365 POP_STD_UPD_FRAME -> Cost (1, 0, 3, 0, 0) {- SMupdate.lh -}
366 SET_TAG -> nullCosts {- COptRegs.lh -}
367 GRAN_FETCH -> nullCosts {- GrAnSim bookkeeping -}
368 GRAN_RESCHEDULE -> nullCosts {- GrAnSim bookkeeping -}
369 GRAN_FETCH_AND_RESCHEDULE -> nullCosts {- GrAnSim bookkeeping -}
370 GRAN_YIELD -> nullCosts {- GrAnSim bookkeeping -- added SOF -}
371 THREAD_CONTEXT_SWITCH -> nullCosts {- GrAnSim bookkeeping -}
372 _ -> trace ("Costs.stmtMacroCosts: "++show macro) nullCosts
374 -- ---------------------------------------------------------------------------
378 [ FloatGtOp , FloatGeOp , FloatEqOp , FloatNeOp , FloatLtOp , FloatLeOp
379 , DoubleGtOp , DoubleGeOp , DoubleEqOp , DoubleNeOp , DoubleLtOp , DoubleLeOp
380 , FloatAddOp , FloatSubOp , FloatMulOp , FloatDivOp , FloatNegOp
381 , Float2IntOp , Int2FloatOp
382 , FloatExpOp , FloatLogOp , FloatSqrtOp
383 , FloatSinOp , FloatCosOp , FloatTanOp
384 , FloatAsinOp , FloatAcosOp , FloatAtanOp
385 , FloatSinhOp , FloatCoshOp , FloatTanhOp
387 , DoubleAddOp , DoubleSubOp , DoubleMulOp , DoubleDivOp , DoubleNegOp
388 , Double2IntOp , Int2DoubleOp
389 , Double2FloatOp , Float2DoubleOp
390 , DoubleExpOp , DoubleLogOp , DoubleSqrtOp
391 , DoubleSinOp , DoubleCosOp , DoubleTanOp
392 , DoubleAsinOp , DoubleAcosOp , DoubleAtanOp
393 , DoubleSinhOp , DoubleCoshOp , DoubleTanhOp
395 , FloatEncodeOp , FloatDecodeOp
396 , DoubleEncodeOp , DoubleDecodeOp
401 [ IntegerAddOp , IntegerSubOp , IntegerMulOp
402 , IntegerQuotRemOp , IntegerDivModOp , IntegerNegOp
404 , Integer2IntOp , Int2IntegerOp
409 abs_costs = nullCosts -- NB: This is normal STG code with costs already
410 -- included; no need to add costs again.
412 umul_costs = Cost (21,4,0,0,0) -- due to spy counts
413 rem_costs = Cost (30,15,0,0,0) -- due to spy counts
414 div_costs = Cost (30,15,0,0,0) -- due to spy counts
416 primOpCosts :: PrimOp -> CostRes
420 primOpCosts (CCallOp _ _ _ _ _) = SAVE_COSTS + RESTORE_COSTS
421 -- don't guess costs of ccall proper
422 -- for exact costing use a GRAN_EXEC
425 -- Usually 3 mov instructions are needed to get args and res in right place.
427 primOpCosts IntMulOp = Cost (3, 1, 0, 0, 0) + umul_costs
428 primOpCosts IntQuotOp = Cost (3, 1, 0, 0, 0) + div_costs
429 primOpCosts IntRemOp = Cost (3, 1, 0, 0, 0) + rem_costs
430 primOpCosts IntNegOp = Cost (1, 1, 0, 0, 0) -- translates into 1 sub
431 primOpCosts IntAbsOp = Cost (0, 1, 0, 0, 0) -- abs closure already costed
433 primOpCosts FloatGtOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
434 primOpCosts FloatGeOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
435 primOpCosts FloatEqOp = Cost (0, 0, 0, 0, 2) -- cheap f-comp
436 primOpCosts FloatNeOp = Cost (0, 0, 0, 0, 2) -- cheap f-comp
437 primOpCosts FloatLtOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
438 primOpCosts FloatLeOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
439 primOpCosts DoubleGtOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
440 primOpCosts DoubleGeOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
441 primOpCosts DoubleEqOp = Cost (0, 0, 0, 0, 2) -- cheap f-comp
442 primOpCosts DoubleNeOp = Cost (0, 0, 0, 0, 2) -- cheap f-comp
443 primOpCosts DoubleLtOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
444 primOpCosts DoubleLeOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
446 primOpCosts FloatExpOp = Cost (2, 1, 4, 4, 3)
447 primOpCosts FloatLogOp = Cost (2, 1, 4, 4, 3)
448 primOpCosts FloatSqrtOp = Cost (2, 1, 4, 4, 3)
449 primOpCosts FloatSinOp = Cost (2, 1, 4, 4, 3)
450 primOpCosts FloatCosOp = Cost (2, 1, 4, 4, 3)
451 primOpCosts FloatTanOp = Cost (2, 1, 4, 4, 3)
452 primOpCosts FloatAsinOp = Cost (2, 1, 4, 4, 3)
453 primOpCosts FloatAcosOp = Cost (2, 1, 4, 4, 3)
454 primOpCosts FloatAtanOp = Cost (2, 1, 4, 4, 3)
455 primOpCosts FloatSinhOp = Cost (2, 1, 4, 4, 3)
456 primOpCosts FloatCoshOp = Cost (2, 1, 4, 4, 3)
457 primOpCosts FloatTanhOp = Cost (2, 1, 4, 4, 3)
458 --primOpCosts FloatAsinhOp = Cost (2, 1, 4, 4, 3)
459 --primOpCosts FloatAcoshOp = Cost (2, 1, 4, 4, 3)
460 --primOpCosts FloatAtanhOp = Cost (2, 1, 4, 4, 3)
461 primOpCosts FloatPowerOp = Cost (2, 1, 4, 4, 3)
463 {- There should be special handling of the Array PrimOps in here HWL -}
466 | primOp `elem` floatOps = Cost (0, 0, 0, 0, 1) :: CostRes
467 | primOp `elem` gmpOps = Cost (30, 5, 10, 10, 0) :: CostRes -- GUESS; check it
468 | otherwise = Cost (1, 0, 0, 0, 0)
470 -- ---------------------------------------------------------------------------
471 {- HWL: currently unused
473 costsByKind :: PrimRep -> Side -> CostRes
475 -- The following PrimKinds say that the data is already in a reg
477 costsByKind CharRep _ = nullCosts
478 costsByKind IntRep _ = nullCosts
479 costsByKind WordRep _ = nullCosts
480 costsByKind AddrRep _ = nullCosts
481 costsByKind FloatRep _ = nullCosts
482 costsByKind DoubleRep _ = nullCosts
484 -- ---------------------------------------------------------------------------
487 This is the data structure of {\tt PrimOp} copied from prelude/PrimOp.lhs.
488 I include here some comments about the estimated costs for these @PrimOps@.
489 Compare with the @primOpCosts@ fct above. -- HWL
493 -- I assume all these basic comparisons take just one ALU instruction
494 -- Checked that for Char, Int; Word, Addr should be the same as Int.
496 = CharGtOp | CharGeOp | CharEqOp | CharNeOp | CharLtOp | CharLeOp
497 | IntGtOp | IntGeOp | IntEqOp | IntNeOp | IntLtOp | IntLeOp
498 | WordGtOp | WordGeOp | WordEqOp | WordNeOp | WordLtOp | WordLeOp
499 | AddrGtOp | AddrGeOp | AddrEqOp | AddrNeOp | AddrLtOp | AddrLeOp
501 -- Analogously, these take one FP unit instruction
502 -- Haven't checked that, yet.
504 | FloatGtOp | FloatGeOp | FloatEqOp | FloatNeOp | FloatLtOp | FloatLeOp
505 | DoubleGtOp | DoubleGeOp | DoubleEqOp | DoubleNeOp | DoubleLtOp | DoubleLeOp
507 -- 1 ALU op; unchecked
510 -- these just take 1 ALU op; checked
511 | IntAddOp | IntSubOp
513 -- but these take more than that; see special cases in primOpCosts
514 -- I counted the generated ass. instructions for these -> checked
515 | IntMulOp | IntQuotOp
516 | IntRemOp | IntNegOp | IntAbsOp
518 -- Rest is unchecked so far -- HWL
520 -- Word#-related ops:
521 | AndOp | OrOp | NotOp | XorOp | ShiftLOp | ShiftROp
522 | Int2WordOp | Word2IntOp -- casts
524 -- Addr#-related ops:
525 | Int2AddrOp | Addr2IntOp -- casts
527 -- Float#-related ops:
528 | FloatAddOp | FloatSubOp | FloatMulOp | FloatDivOp | FloatNegOp
529 | Float2IntOp | Int2FloatOp
531 | FloatExpOp | FloatLogOp | FloatSqrtOp
532 | FloatSinOp | FloatCosOp | FloatTanOp
533 | FloatAsinOp | FloatAcosOp | FloatAtanOp
534 | FloatSinhOp | FloatCoshOp | FloatTanhOp
535 -- not all machines have these available conveniently:
536 -- | FloatAsinhOp | FloatAcoshOp | FloatAtanhOp
537 | FloatPowerOp -- ** op
539 -- Double#-related ops:
540 | DoubleAddOp | DoubleSubOp | DoubleMulOp | DoubleDivOp | DoubleNegOp
541 | Double2IntOp | Int2DoubleOp
542 | Double2FloatOp | Float2DoubleOp
544 | DoubleExpOp | DoubleLogOp | DoubleSqrtOp
545 | DoubleSinOp | DoubleCosOp | DoubleTanOp
546 | DoubleAsinOp | DoubleAcosOp | DoubleAtanOp
547 | DoubleSinhOp | DoubleCoshOp | DoubleTanhOp
548 -- not all machines have these available conveniently:
549 -- | DoubleAsinhOp | DoubleAcoshOp | DoubleAtanhOp
550 | DoublePowerOp -- ** op
552 -- Integer (and related...) ops:
553 -- slightly weird -- to match GMP package.
554 | IntegerAddOp | IntegerSubOp | IntegerMulOp
555 | IntegerQuotRemOp | IntegerDivModOp | IntegerNegOp
559 | Integer2IntOp | Int2IntegerOp
560 | Addr2IntegerOp -- "Addr" is *always* a literal string
563 | FloatEncodeOp | FloatDecodeOp
564 | DoubleEncodeOp | DoubleDecodeOp
566 -- primitive ops for primitive arrays
569 | NewByteArrayOp PrimRep
572 | SameMutableByteArrayOp
574 | ReadArrayOp | WriteArrayOp | IndexArrayOp -- for arrays of Haskell ptrs
576 | ReadByteArrayOp PrimRep
577 | WriteByteArrayOp PrimRep
578 | IndexByteArrayOp PrimRep
579 | IndexOffAddrOp PrimRep
580 -- PrimRep can be one of {Char,Int,Addr,Float,Double}Kind.
581 -- This is just a cheesy encoding of a bunch of ops.
582 -- Note that ForeignObjRep is not included -- the only way of
583 -- creating a ForeignObj is with a ccall or casm.
585 | UnsafeFreezeArrayOp | UnsafeFreezeByteArrayOp
587 | MakeStablePtrOp | DeRefStablePtrOp
590 A special ``trap-door'' to use in making calls direct to C functions:
591 Note: From GrAn point of view, CCall is probably very expensive
592 The programmer can specify the costs of the Ccall by inserting
593 a GRAN_EXEC(a,b,l,s,f) at the end of the C- code, specifing the
594 number or arithm., branch, load, store and floating point instructions
598 | CCallOp String -- An "unboxed" ccall# to this named function
599 Bool -- True <=> really a "casm"
600 Bool -- True <=> might invoke Haskell GC
601 [Type] -- Unboxed argument; the state-token
602 -- argument will have been put *first*
603 Type -- Return type; one of the "StateAnd<blah>#" types
605 -- (... to be continued ... )