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 #define ACCUM_COSTS(i,b,l,s,f) (i+b+l+s+f)
49 #define NUM_REGS 10 {- PprAbsCSyn.lhs -} {- runtime/c-as-asm/CallWrap_C.lc -}
50 #define RESTORE_COSTS (Cost (0, 0, NUM_REGS, 0, 0) :: CostRes)
51 #define SAVE_COSTS (Cost (0, 0, 0, NUM_REGS, 0) :: CostRes)
52 #define CCALL_COSTS_GUESS (Cost (50, 0, 0, 0, 0) :: CostRes)
55 addrModeCosts, CostRes(Cost), nullCosts, Side(..)
58 #include "HsVersions.h"
61 import PrimOp ( primOpNeedsWrapper, PrimOp(..) )
62 import GlaExts ( trace )
64 -- --------------------------------------------------------------------------
65 data CostRes = Cost (Int, Int, Int, Int, Int)
68 nullCosts = Cost (0, 0, 0, 0, 0) :: CostRes
69 initHdrCosts = Cost (2, 0, 0, 1, 0) :: CostRes
70 errorCosts = Cost (-1, -1, -1, -1, -1) -- just for debugging
72 oneArithm = Cost (1, 0, 0, 0, 0) :: CostRes
74 instance Eq CostRes where
75 (==) t1 t2 = i && b && l && s && f
76 where (i,b,l,s,f) = binOp' (==) t1 t2
78 instance Num CostRes where
86 mapOp :: (Int -> Int) -> CostRes -> CostRes
87 mapOp g ( Cost (i, b, l, s, f) ) = Cost (g i, g b, g l, g s, g f)
89 foldrOp :: (Int -> a -> a) -> a -> CostRes -> a
90 foldrOp o x ( Cost (i1, b1, l1, s1, f1) ) =
91 i1 `o` ( b1 `o` ( l1 `o` ( s1 `o` ( f1 `o` x))))
93 binOp :: (Int -> Int -> Int) -> CostRes -> CostRes -> CostRes
94 binOp o ( Cost (i1, b1, l1, s1, f1) ) ( Cost (i2, b2, l2, s2, f2) ) =
95 ( Cost (i1 `o` i2, b1 `o` b2, l1 `o` l2, s1 `o` s2, f1 `o` f2) )
97 binOp' :: (Int -> Int -> a) -> CostRes -> CostRes -> (a,a,a,a,a)
98 binOp' o ( Cost (i1, b1, l1, s1, f1) ) ( Cost (i2, b2, l2, s2, f2) ) =
99 (i1 `o` i2, b1 `o` b2, l1 `o` l2, s1 `o` s2, f1 `o` f2)
101 -- --------------------------------------------------------------------------
103 data Side = Lhs | Rhs
106 -- --------------------------------------------------------------------------
108 costs :: AbstractC -> CostRes
114 AbsCStmts absC1 absC2 -> costs absC1 + costs absC2
116 CAssign (CReg _) (CReg _) -> Cost (1,0,0,0,0) -- typ.: mov %reg1,%reg2
118 CAssign (CReg _) (CTemp _ _) -> Cost (1,0,0,0,0)
120 CAssign (CReg _) (CAddr _) -> Cost (1,0,0,0,0) -- typ.: add %reg1,<adr>,%reg2
122 CAssign target_m source_m -> addrModeCosts target_m Lhs +
123 addrModeCosts source_m Rhs
125 CJump (CLbl _ _) -> Cost (0,1,0,0,0) -- no ld for call necessary
127 CJump mode -> addrModeCosts mode Rhs +
130 CFallThrough mode -> addrModeCosts mode Rhs + -- chu' 0.24
133 CReturn mode info -> case info of
134 DirectReturn -> addrModeCosts mode Rhs +
137 -- i.e. ld address to reg and call reg
139 DynamicVectoredReturn mode' ->
140 addrModeCosts mode Rhs +
141 addrModeCosts mode' Rhs +
144 {- generates code like this:
145 JMP_(<mode>)[RVREL(<mode'>)];
146 i.e. 1 possb ld for mode'
151 StaticVectoredReturn _ -> addrModeCosts mode Rhs +
154 -- as above with mode' fixed to CLit
155 -- typically 2 ld + 1 call; 1st ld due
158 CSwitch mode alts absC -> nullCosts
159 {- for handling costs of all branches of
160 a CSwitch see PprAbsC.
163 Costs before CSwitch +
164 addrModeCosts of head +
165 Costs for 1 cond branch +
166 Costs for body of branch
169 CCodeBlock _ absC -> costs absC
171 CInitHdr cl_info reg_rel cost_centre inplace_upd -> initHdrCosts
173 {- This is more fancy but superflous: The addr modes
174 are fixed and so the costs are const!
176 argCosts + initHdrCosts
177 where argCosts = addrModeCosts (CAddr reg_rel) Rhs +
178 addrModeCosts base_lbl + -- CLbl!
179 3*addrModeCosts (mkIntCLit 1{- any val -})
181 {- this extends to something like
183 For costing the args of this macro
184 see PprAbsC.lhs where args are inserted -}
186 COpStmt modes_res primOp modes_args _ _ ->
193 if primOpNeedsWrapper primOp then SAVE_COSTS + RESTORE_COSTS
197 foldl (+) nullCosts [addrModeCosts mode Lhs | mode <- modes_res] +
198 foldl (+) nullCosts [addrModeCosts mode Rhs | mode <- modes_args] +
200 if primOpNeedsWrapper primOp then SAVE_COSTS + RESTORE_COSTS
203 CSimultaneous absC -> costs absC
205 CMacroStmt macro modes -> stmtMacroCosts macro modes
207 CCallProfCtrMacro _ _ -> nullCosts
208 {- we don't count profiling in GrAnSim -}
210 CCallProfCCMacro _ _ -> nullCosts
211 {- we don't count profiling in GrAnSim -}
213 -- *** the next three [or so...] are DATA (those above are CODE) ***
214 -- as they are data rather than code they all have nullCosts -- HWL
216 CStaticClosure _ _ _ _ -> nullCosts
218 CClosureInfoAndCode _ _ _ _ _ _ -> nullCosts
220 CRetVector _ _ _ -> nullCosts
222 CRetUnVector _ _ -> nullCosts
224 CFlatRetVector _ _ -> nullCosts
226 CCostCentreDecl _ _ -> nullCosts
228 CClosureUpdInfo _ -> nullCosts
230 CSplitMarker -> nullCosts
232 -- ---------------------------------------------------------------------------
234 addrModeCosts :: CAddrMode -> Side -> CostRes
236 -- addrModeCosts _ _ = nullCosts
238 addrModeCosts addr_mode side =
243 CVal _ _ -> if lhs then Cost (0, 0, 0, 1, 0)
244 else Cost (0, 0, 1, 0, 0)
246 CAddr _ -> if lhs then Cost (0, 0, 0, 1, 0) -- ??unchecked
247 else Cost (0, 0, 1, 0, 0)
249 CReg _ -> nullCosts {- loading from, storing to reg is free ! -}
250 {- for costing CReg->Creg ops see special -}
251 {- case in costs fct -}
252 CTableEntry base_mode offset_mode kind ->
253 addrModeCosts base_mode side +
254 addrModeCosts offset_mode side +
257 CTemp _ _ -> nullCosts {- if lhs then Cost (0, 0, 0, 1, 0)
258 else Cost (0, 0, 1, 0, 0) -}
259 -- ``Temporaries'' correspond to local variables in C, and registers in
261 -- I assume they can be somewhat optimized by gcc -- HWL
263 CLbl _ _ -> if lhs then Cost (0, 0, 0, 1, 0)
264 else Cost (2, 0, 0, 0, 0)
265 -- Rhs: typically: sethi %hi(lbl),%tmp_reg
266 -- or %tmp_reg,%lo(lbl),%target_reg
268 CUnVecLbl _ _ -> if lhs then Cost (0, 0, 0, 1, 0)
269 else Cost (2, 0, 0, 0, 0)
272 -- Check the following 3 (checked form CLit on)
274 CCharLike mode -> if lhs then Cost (0, 0, 0, 1, 0)
275 else Cost (0, 0, 1, 0, 0)
277 CIntLike mode -> if lhs then Cost (0, 0, 0, 1, 0)
278 else Cost (0, 0, 1, 0, 0)
280 CString _ -> if lhs then Cost (0, 0, 0, 1, 0)
281 else Cost (0, 0, 1, 0, 0)
283 CLit _ -> if lhs then nullCosts -- should never occur
284 else Cost (1, 0, 0, 0, 0) -- typ.: mov lit,%reg
286 CLitLit _ _ -> if lhs then nullCosts
287 else Cost (1, 0, 0, 0, 0)
290 COffset _ -> if lhs then nullCosts
291 else Cost (1, 0, 0, 0, 0)
294 CCode absC -> costs absC
296 CLabelledCode _ absC -> costs absC
298 CJoinPoint _ _ -> if lhs then Cost (0, 0, 0, 1, 0)
299 else Cost (0, 0, 1, 0, 0)
301 CMacroExpr _ macro mode_list -> exprMacroCosts side macro mode_list
303 CCostCentre _ _ -> nullCosts
305 -- ---------------------------------------------------------------------------
307 exprMacroCosts :: Side -> CExprMacro -> [CAddrMode] -> CostRes
309 exprMacroCosts side macro mode_list =
311 arg_costs = foldl (+) nullCosts
312 (map (\ x -> addrModeCosts x Rhs) mode_list)
316 INFO_PTR -> if side == Lhs then Cost (0, 0, 0, 1, 0)
317 else Cost (0, 0, 1, 0, 0)
318 ENTRY_CODE -> nullCosts
319 INFO_TAG -> if side == Lhs then Cost (0, 0, 0, 1, 0)
320 else Cost (0, 0, 1, 0, 0)
321 EVAL_TAG -> if side == Lhs then Cost (1, 0, 0, 1, 0)
322 else Cost (1, 0, 1, 0, 0)
323 -- costs of INFO_TAG + (1,0,0,0,0)
325 -- ---------------------------------------------------------------------------
327 stmtMacroCosts :: CStmtMacro -> [CAddrMode] -> CostRes
329 stmtMacroCosts macro modes =
331 arg_costs = foldl (+) nullCosts
332 [addrModeCosts mode Rhs | mode <- modes]
335 ARGS_CHK_A_LOAD_NODE -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
336 -- p=probability of PAP (instead of AP): + p*(3,1,0,0,0)
337 ARGS_CHK_A -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
338 -- p=probability of PAP (instead of AP): + p*(0,1,0,0,0)
339 ARGS_CHK_B_LOAD_NODE -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
340 ARGS_CHK_B -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
341 HEAP_CHK -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
342 -- STK_CHK -> (2, 1, 0, 0, 0) {- StgMacros.lh -}
343 STK_CHK -> Cost (0, 0, 0, 0, 0) {- StgMacros.lh -}
344 UPD_CAF -> Cost (7, 0, 1, 3, 0) {- SMupdate.lh -}
345 UPD_IND -> Cost (8, 2, 2, 0, 0) {- SMupdate.lh
346 updatee in old-gen: Cost (4, 1, 1, 0, 0)
347 updatee in new-gen: Cost (4, 1, 1, 0, 0)
348 NB: we include costs fo checking if there is
349 a BQ, but we omit costs for awakening BQ
350 (these probably differ between old-gen and
352 UPD_INPLACE_NOPTRS -> Cost (13, 3, 3, 2, 0) {- SMupdate.lh
353 common for both: Cost (4, 1, 1, 0, 0)
354 updatee in old-gen: Cost (14, 3, 2, 4, 0)
355 updatee in new-gen: Cost (4, 1, 1, 0, 0) -}
356 UPD_INPLACE_PTRS -> Cost (13, 3, 3, 2, 0) {- SMupdate.lh
357 common for both: Cost (4, 1, 1, 0, 0)
358 updatee in old-gen: Cost (14, 3, 2, 4, 0)
359 updatee in new-gen: Cost (4, 1, 1, 0, 0) -}
361 UPD_BH_UPDATABLE -> Cost (3, 0, 0, 1, 0) {- SMupdate.lh -}
362 UPD_BH_SINGLE_ENTRY -> Cost (3, 0, 0, 1, 0) {- SMupdate.lh -}
363 PUSH_STD_UPD_FRAME -> Cost (3, 0, 0, 4, 0) {- SMupdate.lh -}
364 POP_STD_UPD_FRAME -> Cost (1, 0, 3, 0, 0) {- SMupdate.lh -}
365 SET_TAG -> nullCosts {- COptRegs.lh -}
366 GRAN_FETCH -> nullCosts {- GrAnSim bookkeeping -}
367 GRAN_RESCHEDULE -> nullCosts {- GrAnSim bookkeeping -}
368 GRAN_FETCH_AND_RESCHEDULE -> nullCosts {- GrAnSim bookkeeping -}
369 GRAN_YIELD -> nullCosts {- GrAnSim bookkeeping -- added SOF -}
370 THREAD_CONTEXT_SWITCH -> nullCosts {- GrAnSim bookkeeping -}
371 _ -> trace ("Costs.stmtMacroCosts: "++show macro) nullCosts
373 -- ---------------------------------------------------------------------------
377 [ FloatGtOp , FloatGeOp , FloatEqOp , FloatNeOp , FloatLtOp , FloatLeOp
378 , DoubleGtOp , DoubleGeOp , DoubleEqOp , DoubleNeOp , DoubleLtOp , DoubleLeOp
379 , FloatAddOp , FloatSubOp , FloatMulOp , FloatDivOp , FloatNegOp
380 , Float2IntOp , Int2FloatOp
381 , FloatExpOp , FloatLogOp , FloatSqrtOp
382 , FloatSinOp , FloatCosOp , FloatTanOp
383 , FloatAsinOp , FloatAcosOp , FloatAtanOp
384 , FloatSinhOp , FloatCoshOp , FloatTanhOp
386 , DoubleAddOp , DoubleSubOp , DoubleMulOp , DoubleDivOp , DoubleNegOp
387 , Double2IntOp , Int2DoubleOp
388 , Double2FloatOp , Float2DoubleOp
389 , DoubleExpOp , DoubleLogOp , DoubleSqrtOp
390 , DoubleSinOp , DoubleCosOp , DoubleTanOp
391 , DoubleAsinOp , DoubleAcosOp , DoubleAtanOp
392 , DoubleSinhOp , DoubleCoshOp , DoubleTanhOp
394 , FloatEncodeOp , FloatDecodeOp
395 , DoubleEncodeOp , DoubleDecodeOp
400 [ IntegerAddOp , IntegerSubOp , IntegerMulOp
401 , IntegerQuotRemOp , IntegerDivModOp , IntegerNegOp
403 , Integer2IntOp , Int2IntegerOp
408 abs_costs = nullCosts -- NB: This is normal STG code with costs already
409 -- included; no need to add costs again.
411 umul_costs = Cost (21,4,0,0,0) -- due to spy counts
412 rem_costs = Cost (30,15,0,0,0) -- due to spy counts
413 div_costs = Cost (30,15,0,0,0) -- due to spy counts
415 primOpCosts :: PrimOp -> CostRes
419 primOpCosts (CCallOp _ _ _ _ _) = SAVE_COSTS + RESTORE_COSTS
420 -- don't guess costs of ccall proper
421 -- for exact costing use a GRAN_EXEC
424 -- Usually 3 mov instructions are needed to get args and res in right place.
426 primOpCosts IntMulOp = Cost (3, 1, 0, 0, 0) + umul_costs
427 primOpCosts IntQuotOp = Cost (3, 1, 0, 0, 0) + div_costs
428 primOpCosts IntRemOp = Cost (3, 1, 0, 0, 0) + rem_costs
429 primOpCosts IntNegOp = Cost (1, 1, 0, 0, 0) -- translates into 1 sub
430 primOpCosts IntAbsOp = Cost (0, 1, 0, 0, 0) -- abs closure already costed
432 primOpCosts FloatGtOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
433 primOpCosts FloatGeOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
434 primOpCosts FloatEqOp = Cost (0, 0, 0, 0, 2) -- cheap f-comp
435 primOpCosts FloatNeOp = Cost (0, 0, 0, 0, 2) -- cheap f-comp
436 primOpCosts FloatLtOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
437 primOpCosts FloatLeOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
438 primOpCosts DoubleGtOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
439 primOpCosts DoubleGeOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
440 primOpCosts DoubleEqOp = Cost (0, 0, 0, 0, 2) -- cheap f-comp
441 primOpCosts DoubleNeOp = Cost (0, 0, 0, 0, 2) -- cheap f-comp
442 primOpCosts DoubleLtOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
443 primOpCosts DoubleLeOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
445 primOpCosts FloatExpOp = Cost (2, 1, 4, 4, 3)
446 primOpCosts FloatLogOp = Cost (2, 1, 4, 4, 3)
447 primOpCosts FloatSqrtOp = Cost (2, 1, 4, 4, 3)
448 primOpCosts FloatSinOp = Cost (2, 1, 4, 4, 3)
449 primOpCosts FloatCosOp = Cost (2, 1, 4, 4, 3)
450 primOpCosts FloatTanOp = Cost (2, 1, 4, 4, 3)
451 primOpCosts FloatAsinOp = Cost (2, 1, 4, 4, 3)
452 primOpCosts FloatAcosOp = Cost (2, 1, 4, 4, 3)
453 primOpCosts FloatAtanOp = Cost (2, 1, 4, 4, 3)
454 primOpCosts FloatSinhOp = Cost (2, 1, 4, 4, 3)
455 primOpCosts FloatCoshOp = Cost (2, 1, 4, 4, 3)
456 primOpCosts FloatTanhOp = Cost (2, 1, 4, 4, 3)
457 --primOpCosts FloatAsinhOp = Cost (2, 1, 4, 4, 3)
458 --primOpCosts FloatAcoshOp = Cost (2, 1, 4, 4, 3)
459 --primOpCosts FloatAtanhOp = Cost (2, 1, 4, 4, 3)
460 primOpCosts FloatPowerOp = Cost (2, 1, 4, 4, 3)
462 {- There should be special handling of the Array PrimOps in here HWL -}
465 | primOp `elem` floatOps = Cost (0, 0, 0, 0, 1) :: CostRes
466 | primOp `elem` gmpOps = Cost (30, 5, 10, 10, 0) :: CostRes -- GUESS; check it
467 | otherwise = Cost (1, 0, 0, 0, 0)
469 -- ---------------------------------------------------------------------------
470 {- HWL: currently unused
472 costsByKind :: PrimRep -> Side -> CostRes
474 -- The following PrimKinds say that the data is already in a reg
476 costsByKind CharRep _ = nullCosts
477 costsByKind IntRep _ = nullCosts
478 costsByKind WordRep _ = nullCosts
479 costsByKind AddrRep _ = nullCosts
480 costsByKind FloatRep _ = nullCosts
481 costsByKind DoubleRep _ = nullCosts
483 -- ---------------------------------------------------------------------------
486 This is the data structure of {\tt PrimOp} copied from prelude/PrimOp.lhs.
487 I include here some comments about the estimated costs for these @PrimOps@.
488 Compare with the @primOpCosts@ fct above. -- HWL
492 -- I assume all these basic comparisons take just one ALU instruction
493 -- Checked that for Char, Int; Word, Addr should be the same as Int.
495 = CharGtOp | CharGeOp | CharEqOp | CharNeOp | CharLtOp | CharLeOp
496 | IntGtOp | IntGeOp | IntEqOp | IntNeOp | IntLtOp | IntLeOp
497 | WordGtOp | WordGeOp | WordEqOp | WordNeOp | WordLtOp | WordLeOp
498 | AddrGtOp | AddrGeOp | AddrEqOp | AddrNeOp | AddrLtOp | AddrLeOp
500 -- Analogously, these take one FP unit instruction
501 -- Haven't checked that, yet.
503 | FloatGtOp | FloatGeOp | FloatEqOp | FloatNeOp | FloatLtOp | FloatLeOp
504 | DoubleGtOp | DoubleGeOp | DoubleEqOp | DoubleNeOp | DoubleLtOp | DoubleLeOp
506 -- 1 ALU op; unchecked
509 -- these just take 1 ALU op; checked
510 | IntAddOp | IntSubOp
512 -- but these take more than that; see special cases in primOpCosts
513 -- I counted the generated ass. instructions for these -> checked
514 | IntMulOp | IntQuotOp
515 | IntRemOp | IntNegOp | IntAbsOp
517 -- Rest is unchecked so far -- HWL
519 -- Word#-related ops:
520 | AndOp | OrOp | NotOp | XorOp | ShiftLOp | ShiftROp
521 | Int2WordOp | Word2IntOp -- casts
523 -- Addr#-related ops:
524 | Int2AddrOp | Addr2IntOp -- casts
526 -- Float#-related ops:
527 | FloatAddOp | FloatSubOp | FloatMulOp | FloatDivOp | FloatNegOp
528 | Float2IntOp | Int2FloatOp
530 | FloatExpOp | FloatLogOp | FloatSqrtOp
531 | FloatSinOp | FloatCosOp | FloatTanOp
532 | FloatAsinOp | FloatAcosOp | FloatAtanOp
533 | FloatSinhOp | FloatCoshOp | FloatTanhOp
534 -- not all machines have these available conveniently:
535 -- | FloatAsinhOp | FloatAcoshOp | FloatAtanhOp
536 | FloatPowerOp -- ** op
538 -- Double#-related ops:
539 | DoubleAddOp | DoubleSubOp | DoubleMulOp | DoubleDivOp | DoubleNegOp
540 | Double2IntOp | Int2DoubleOp
541 | Double2FloatOp | Float2DoubleOp
543 | DoubleExpOp | DoubleLogOp | DoubleSqrtOp
544 | DoubleSinOp | DoubleCosOp | DoubleTanOp
545 | DoubleAsinOp | DoubleAcosOp | DoubleAtanOp
546 | DoubleSinhOp | DoubleCoshOp | DoubleTanhOp
547 -- not all machines have these available conveniently:
548 -- | DoubleAsinhOp | DoubleAcoshOp | DoubleAtanhOp
549 | DoublePowerOp -- ** op
551 -- Integer (and related...) ops:
552 -- slightly weird -- to match GMP package.
553 | IntegerAddOp | IntegerSubOp | IntegerMulOp
554 | IntegerQuotRemOp | IntegerDivModOp | IntegerNegOp
558 | Integer2IntOp | Int2IntegerOp
559 | Addr2IntegerOp -- "Addr" is *always* a literal string
562 | FloatEncodeOp | FloatDecodeOp
563 | DoubleEncodeOp | DoubleDecodeOp
565 -- primitive ops for primitive arrays
568 | NewByteArrayOp PrimRep
571 | SameMutableByteArrayOp
573 | ReadArrayOp | WriteArrayOp | IndexArrayOp -- for arrays of Haskell ptrs
575 | ReadByteArrayOp PrimRep
576 | WriteByteArrayOp PrimRep
577 | IndexByteArrayOp PrimRep
578 | IndexOffAddrOp PrimRep
579 -- PrimRep can be one of {Char,Int,Addr,Float,Double}Kind.
580 -- This is just a cheesy encoding of a bunch of ops.
581 -- Note that ForeignObjRep is not included -- the only way of
582 -- creating a ForeignObj is with a ccall or casm.
584 | UnsafeFreezeArrayOp | UnsafeFreezeByteArrayOp
586 | MakeStablePtrOp | DeRefStablePtrOp
589 A special ``trap-door'' to use in making calls direct to C functions:
590 Note: From GrAn point of view, CCall is probably very expensive
591 The programmer can specify the costs of the Ccall by inserting
592 a GRAN_EXEC(a,b,l,s,f) at the end of the C- code, specifing the
593 number or arithm., branch, load, store and floating point instructions
597 | CCallOp String -- An "unboxed" ccall# to this named function
598 Bool -- True <=> really a "casm"
599 Bool -- True <=> might invoke Haskell GC
600 [Type] -- Unboxed argument; the state-token
601 -- argument will have been put *first*
602 Type -- Return type; one of the "StateAnd<blah>#" types
604 -- (... to be continued ... )