2 % (c) The GRASP/AQUA Project, Glasgow University, 1994-1995
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(..)
67 -- --------------------------------------------------------------------------
69 -- a module of "stubs" that don't do anything
70 data CostRes = Cost (Int, Int, Int, Int, Int)
73 nullCosts = Cost (0, 0, 0, 0, 0) :: CostRes
75 costs :: AbstractC -> CostRes
76 addrModeCosts :: CAddrMode -> Side -> CostRes
78 addrModeCosts _ _ = nullCosts
80 instance Eq CostRes; instance Text CostRes
82 instance Num CostRes where
88 data CostRes = Cost (Int, Int, Int, Int, Int)
91 nullCosts = Cost (0, 0, 0, 0, 0) :: CostRes
92 initHdrCosts = Cost (2, 0, 0, 1, 0) :: CostRes
93 errorCosts = Cost (-1, -1, -1, -1, -1) -- just for debugging
95 oneArithm = Cost (1, 0, 0, 0, 0) :: CostRes
97 instance Eq CostRes where
98 (==) t1 t2 = i && b && l && s && f
99 where (i,b,l,s,f) = binOp' (==) t1 t2
101 instance Num CostRes where
105 negate = mapOp negate
107 signum = mapOp signum
109 mapOp :: (Int -> Int) -> CostRes -> CostRes
110 mapOp g ( Cost (i, b, l, s, f) ) = Cost (g i, g b, g l, g s, g f)
112 foldrOp :: (Int -> a -> a) -> a -> CostRes -> a
113 foldrOp o x ( Cost (i1, b1, l1, s1, f1) ) =
114 i1 `o` ( b1 `o` ( l1 `o` ( s1 `o` ( f1 `o` x))))
116 binOp :: (Int -> Int -> Int) -> CostRes -> CostRes -> CostRes
117 binOp o ( Cost (i1, b1, l1, s1, f1) ) ( Cost (i2, b2, l2, s2, f2) ) =
118 ( Cost (i1 `o` i2, b1 `o` b2, l1 `o` l2, s1 `o` s2, f1 `o` f2) )
120 binOp' :: (Int -> Int -> a) -> CostRes -> CostRes -> (a,a,a,a,a)
121 binOp' o ( Cost (i1, b1, l1, s1, f1) ) ( Cost (i2, b2, l2, s2, f2) ) =
122 (i1 `o` i2, b1 `o` b2, l1 `o` l2, s1 `o` s2, f1 `o` f2)
124 -- --------------------------------------------------------------------------
126 data Side = Lhs | Rhs
129 -- --------------------------------------------------------------------------
131 costs :: AbstractC -> CostRes
137 AbsCStmts absC1 absC2 -> costs absC1 + costs absC2
139 CAssign (CReg _) (CReg _) -> Cost (1,0,0,0,0) -- typ.: mov %reg1,%reg2
141 CAssign (CReg _) (CTemp _ _) -> Cost (1,0,0,0,0)
143 CAssign (CReg _) (CAddr _) -> Cost (1,0,0,0,0) -- typ.: add %reg1,<adr>,%reg2
145 CAssign target_m source_m -> addrModeCosts target_m Lhs +
146 addrModeCosts source_m Rhs
148 CJump (CLbl _ _) -> Cost (0,1,0,0,0) -- no ld for call necessary
150 CJump mode -> addrModeCosts mode Rhs +
153 CFallThrough mode -> addrModeCosts mode Rhs + -- chu' 0.24
156 CReturn mode info -> case info of
157 DirectReturn -> addrModeCosts mode Rhs +
160 -- i.e. ld address to reg and call reg
162 DynamicVectoredReturn mode' ->
163 addrModeCosts mode Rhs +
164 addrModeCosts mode' Rhs +
167 {- generates code like this:
168 JMP_(<mode>)[RVREL(<mode'>)];
169 i.e. 1 possb ld for mode'
174 StaticVectoredReturn _ -> addrModeCosts mode Rhs +
177 -- as above with mode' fixed to CLit
178 -- typically 2 ld + 1 call; 1st ld due
181 CSwitch mode alts absC -> nullCosts
182 {- for handling costs of all branches of
183 a CSwitch see PprAbsC.
186 Costs before CSwitch +
187 addrModeCosts of head +
188 Costs for 1 cond branch +
189 Costs for body of branch
192 CCodeBlock _ absC -> costs absC
194 CInitHdr cl_info reg_rel cost_centre inplace_upd -> initHdrCosts
196 {- This is more fancy but superflous: The addr modes
197 are fixed and so the costs are const!
199 argCosts + initHdrCosts
200 where argCosts = addrModeCosts (CAddr reg_rel) Rhs +
201 addrModeCosts base_lbl + -- CLbl!
202 3*addrModeCosts (mkIntCLit 1{- any val -})
204 {- this extends to something like
206 For costing the args of this macro
207 see PprAbsC.lhs where args are inserted -}
209 COpStmt modes_res primOp modes_args _ _ ->
216 if primOpNeedsWrapper primOp then SAVE_COSTS + RESTORE_COSTS
220 foldl (+) nullCosts [addrModeCosts mode Lhs | mode <- modes_res] +
221 foldl (+) nullCosts [addrModeCosts mode Rhs | mode <- modes_args] +
223 if primOpNeedsWrapper primOp then SAVE_COSTS + RESTORE_COSTS
226 CSimultaneous absC -> costs absC
228 CMacroStmt macro modes -> stmtMacroCosts macro modes
230 CCallProfCtrMacro _ _ -> nullCosts
231 {- we don't count profiling in GrAnSim -}
233 CCallProfCCMacro _ _ -> nullCosts
234 {- we don't count profiling in GrAnSim -}
236 -- *** the next three [or so...] are DATA (those above are CODE) ***
237 -- as they are data rather than code they all have nullCosts -- HWL
239 CStaticClosure _ _ _ _ -> nullCosts
241 CClosureInfoAndCode _ _ _ _ _ -> nullCosts
243 CRetVector _ _ _ -> nullCosts
245 CRetUnVector _ _ -> nullCosts
247 CFlatRetVector _ _ -> nullCosts
249 CCostCentreDecl _ _ -> nullCosts
251 CClosureUpdInfo _ -> nullCosts
253 CSplitMarker -> nullCosts
255 -- ---------------------------------------------------------------------------
257 addrModeCosts :: CAddrMode -> Side -> CostRes
259 -- addrModeCosts _ _ = nullCosts
261 addrModeCosts addr_mode side =
266 CVal _ _ -> if lhs then Cost (0, 0, 0, 1, 0)
267 else Cost (0, 0, 1, 0, 0)
269 CAddr _ -> if lhs then Cost (0, 0, 0, 1, 0) -- ??unchecked
270 else Cost (0, 0, 1, 0, 0)
272 CReg _ -> nullCosts {- loading from, storing to reg is free ! -}
273 {- for costing CReg->Creg ops see special -}
274 {- case in costs fct -}
275 CTableEntry base_mode offset_mode kind ->
276 addrModeCosts base_mode side +
277 addrModeCosts offset_mode side +
280 CTemp _ _ -> nullCosts {- if lhs then Cost (0, 0, 0, 1, 0)
281 else Cost (0, 0, 1, 0, 0) -}
282 -- ``Temporaries'' correspond to local variables in C, and registers in
284 -- I assume they can be somewhat optimized by gcc -- HWL
286 CLbl _ _ -> if lhs then Cost (0, 0, 0, 1, 0)
287 else Cost (2, 0, 0, 0, 0)
288 -- Rhs: typically: sethi %hi(lbl),%tmp_reg
289 -- or %tmp_reg,%lo(lbl),%target_reg
291 CUnVecLbl _ _ -> if lhs then Cost (0, 0, 0, 1, 0)
292 else Cost (2, 0, 0, 0, 0)
295 -- Check the following 3 (checked form CLit on)
297 CCharLike mode -> if lhs then Cost (0, 0, 0, 1, 0)
298 else Cost (0, 0, 1, 0, 0)
300 CIntLike mode -> if lhs then Cost (0, 0, 0, 1, 0)
301 else Cost (0, 0, 1, 0, 0)
303 CString _ -> if lhs then Cost (0, 0, 0, 1, 0)
304 else Cost (0, 0, 1, 0, 0)
306 CLit _ -> if lhs then nullCosts -- should never occur
307 else Cost (1, 0, 0, 0, 0) -- typ.: mov lit,%reg
309 CLitLit _ _ -> if lhs then nullCosts
310 else Cost (1, 0, 0, 0, 0)
313 COffset _ -> if lhs then nullCosts
314 else Cost (1, 0, 0, 0, 0)
317 CCode absC -> costs absC
319 CLabelledCode _ absC -> costs absC
321 CJoinPoint _ _ -> if lhs then Cost (0, 0, 0, 1, 0)
322 else Cost (0, 0, 1, 0, 0)
324 CMacroExpr _ macro mode_list -> exprMacroCosts side macro mode_list
326 CCostCentre _ _ -> nullCosts
328 -- ---------------------------------------------------------------------------
330 exprMacroCosts :: Side -> CExprMacro -> [CAddrMode] -> CostRes
332 exprMacroCosts side macro mode_list =
334 arg_costs = foldl (+) nullCosts
335 (map (\ x -> addrModeCosts x Rhs) mode_list)
339 INFO_PTR -> if side == Lhs then Cost (0, 0, 0, 1, 0)
340 else Cost (0, 0, 1, 0, 0)
341 ENTRY_CODE -> nullCosts
342 INFO_TAG -> if side == Lhs then Cost (0, 0, 0, 1, 0)
343 else Cost (0, 0, 1, 0, 0)
344 EVAL_TAG -> if side == Lhs then Cost (1, 0, 0, 1, 0)
345 else Cost (1, 0, 1, 0, 0)
346 -- costs of INFO_TAG + (1,0,0,0,0)
348 -- ---------------------------------------------------------------------------
350 stmtMacroCosts :: CStmtMacro -> [CAddrMode] -> CostRes
352 stmtMacroCosts macro modes =
354 arg_costs = foldl (+) nullCosts
355 [addrModeCosts mode Rhs | mode <- modes]
358 ARGS_CHK_A_LOAD_NODE -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
359 -- p=probability of PAP (instead of AP): + p*(3,1,0,0,0)
360 ARGS_CHK_A -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
361 -- p=probability of PAP (instead of AP): + p*(0,1,0,0,0)
362 ARGS_CHK_B_LOAD_NODE -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
363 ARGS_CHK_B -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
364 HEAP_CHK -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
365 -- STK_CHK -> (2, 1, 0, 0, 0) {- StgMacros.lh -}
366 STK_CHK -> Cost (0, 0, 0, 0, 0) {- StgMacros.lh -}
367 UPD_CAF -> Cost (7, 0, 1, 3, 0) {- SMupdate.lh -}
368 UPD_IND -> Cost (8, 2, 2, 0, 0) {- SMupdate.lh
369 updatee in old-gen: Cost (4, 1, 1, 0, 0)
370 updatee in new-gen: Cost (4, 1, 1, 0, 0)
371 NB: we include costs fo checking if there is
372 a BQ, but we omit costs for awakening BQ
373 (these probably differ between old-gen and
375 UPD_INPLACE_NOPTRS -> Cost (13, 3, 3, 2, 0) {- SMupdate.lh
376 common for both: Cost (4, 1, 1, 0, 0)
377 updatee in old-gen: Cost (14, 3, 2, 4, 0)
378 updatee in new-gen: Cost (4, 1, 1, 0, 0) -}
379 UPD_INPLACE_PTRS -> Cost (13, 3, 3, 2, 0) {- SMupdate.lh
380 common for both: Cost (4, 1, 1, 0, 0)
381 updatee in old-gen: Cost (14, 3, 2, 4, 0)
382 updatee in new-gen: Cost (4, 1, 1, 0, 0) -}
384 UPD_BH_UPDATABLE -> Cost (3, 0, 0, 1, 0) {- SMupdate.lh -}
385 UPD_BH_SINGLE_ENTRY -> Cost (3, 0, 0, 1, 0) {- SMupdate.lh -}
386 PUSH_STD_UPD_FRAME -> Cost (3, 0, 0, 4, 0) {- SMupdate.lh -}
387 POP_STD_UPD_FRAME -> Cost (1, 0, 3, 0, 0) {- SMupdate.lh -}
388 SET_ARITY -> nullCosts {- StgMacros.lh -}
389 CHK_ARITY -> nullCosts {- StgMacros.lh -}
390 SET_TAG -> nullCosts {- COptRegs.lh -}
391 GRAN_FETCH -> nullCosts {- GrAnSim bookkeeping -}
392 GRAN_RESCHEDULE -> nullCosts {- GrAnSim bookkeeping -}
393 GRAN_FETCH_AND_RESCHEDULE -> nullCosts {- GrAnSim bookkeeping -}
394 THREAD_CONTEXT_SWITCH -> nullCosts {- GrAnSim bookkeeping -}
396 -- ---------------------------------------------------------------------------
400 [ FloatGtOp , FloatGeOp , FloatEqOp , FloatNeOp , FloatLtOp , FloatLeOp
401 , DoubleGtOp , DoubleGeOp , DoubleEqOp , DoubleNeOp , DoubleLtOp , DoubleLeOp
402 , FloatAddOp , FloatSubOp , FloatMulOp , FloatDivOp , FloatNegOp
403 , Float2IntOp , Int2FloatOp
404 , FloatExpOp , FloatLogOp , FloatSqrtOp
405 , FloatSinOp , FloatCosOp , FloatTanOp
406 , FloatAsinOp , FloatAcosOp , FloatAtanOp
407 , FloatSinhOp , FloatCoshOp , FloatTanhOp
409 , DoubleAddOp , DoubleSubOp , DoubleMulOp , DoubleDivOp , DoubleNegOp
410 , Double2IntOp , Int2DoubleOp
411 , Double2FloatOp , Float2DoubleOp
412 , DoubleExpOp , DoubleLogOp , DoubleSqrtOp
413 , DoubleSinOp , DoubleCosOp , DoubleTanOp
414 , DoubleAsinOp , DoubleAcosOp , DoubleAtanOp
415 , DoubleSinhOp , DoubleCoshOp , DoubleTanhOp
417 , FloatEncodeOp , FloatDecodeOp
418 , DoubleEncodeOp , DoubleDecodeOp
423 [ IntegerAddOp , IntegerSubOp , IntegerMulOp
424 , IntegerQuotRemOp , IntegerDivModOp , IntegerNegOp
426 , Integer2IntOp , Int2IntegerOp
431 -- Haven't found the .umul .div .rem macros yet
432 -- If they are not Haskell cde, they are not costed, yet
434 abs_costs = nullCosts -- NB: This is normal STG code with costs already
435 -- included; no need to add costs again.
437 umul_costs = Cost (21,4,0,0,0) -- due to spy counts
438 rem_costs = Cost (30,15,0,0,0) -- due to spy counts
439 div_costs = Cost (30,15,0,0,0) -- due to spy counts
441 primOpCosts :: PrimOp -> CostRes
445 primOpCosts (CCallOp _ _ _ _ _) = SAVE_COSTS + CCALL_COSTS_GUESS +
446 RESTORE_COSTS -- GUESS; check it
448 -- Usually 3 mov instructions are needed to get args and res in right place.
450 primOpCosts IntMulOp = Cost (3, 1, 0, 0, 0) + umul_costs
451 primOpCosts IntQuotOp = Cost (3, 1, 0, 0, 0) + div_costs
452 primOpCosts IntDivOp = Cost (3, 1, 0, 0, 0) -- div dclosure already costed
453 primOpCosts IntRemOp = Cost (3, 1, 0, 0, 0) + rem_costs
454 primOpCosts IntNegOp = Cost (1, 1, 0, 0, 0) -- translates into 1 sub
455 primOpCosts IntAbsOp = Cost (0, 1, 0, 0, 0) -- abs closure already costed
457 primOpCosts FloatGtOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
458 primOpCosts FloatGeOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
459 primOpCosts FloatEqOp = Cost (0, 0, 0, 0, 2) -- cheap f-comp
460 primOpCosts FloatNeOp = Cost (0, 0, 0, 0, 2) -- cheap f-comp
461 primOpCosts FloatLtOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
462 primOpCosts FloatLeOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
463 primOpCosts DoubleGtOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
464 primOpCosts DoubleGeOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
465 primOpCosts DoubleEqOp = Cost (0, 0, 0, 0, 2) -- cheap f-comp
466 primOpCosts DoubleNeOp = Cost (0, 0, 0, 0, 2) -- cheap f-comp
467 primOpCosts DoubleLtOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
468 primOpCosts DoubleLeOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
470 primOpCosts FloatExpOp = Cost (2, 1, 4, 4, 3)
471 primOpCosts FloatLogOp = Cost (2, 1, 4, 4, 3)
472 primOpCosts FloatSqrtOp = Cost (2, 1, 4, 4, 3)
473 primOpCosts FloatSinOp = Cost (2, 1, 4, 4, 3)
474 primOpCosts FloatCosOp = Cost (2, 1, 4, 4, 3)
475 primOpCosts FloatTanOp = Cost (2, 1, 4, 4, 3)
476 primOpCosts FloatAsinOp = Cost (2, 1, 4, 4, 3)
477 primOpCosts FloatAcosOp = Cost (2, 1, 4, 4, 3)
478 primOpCosts FloatAtanOp = Cost (2, 1, 4, 4, 3)
479 primOpCosts FloatSinhOp = Cost (2, 1, 4, 4, 3)
480 primOpCosts FloatCoshOp = Cost (2, 1, 4, 4, 3)
481 primOpCosts FloatTanhOp = Cost (2, 1, 4, 4, 3)
482 --primOpCosts FloatAsinhOp = Cost (2, 1, 4, 4, 3)
483 --primOpCosts FloatAcoshOp = Cost (2, 1, 4, 4, 3)
484 --primOpCosts FloatAtanhOp = Cost (2, 1, 4, 4, 3)
485 primOpCosts FloatPowerOp = Cost (2, 1, 4, 4, 3)
487 {- There should be special handling of the Array PrimOps in here HWL -}
490 | primOp `elem` floatOps = Cost (0, 0, 0, 0, 1) :: CostRes
491 | primOp `elem` gmpOps = Cost (50, 5, 10, 10, 0) :: CostRes -- GUESS; check it
492 | otherwise = Cost (1, 0, 0, 0, 0)
494 -- ---------------------------------------------------------------------------
495 {- HWL: currently unused
497 costsByKind :: PrimKind -> Side -> CostRes
499 -- The following PrimKinds say that the data is already in a reg
501 costsByKind CharKind _ = nullCosts
502 costsByKind IntKind _ = nullCosts
503 costsByKind WordKind _ = nullCosts
504 costsByKind AddrKind _ = nullCosts
505 costsByKind FloatKind _ = nullCosts
506 costsByKind DoubleKind _ = nullCosts
508 -- ---------------------------------------------------------------------------
513 This is the data structure of {\tt PrimOp} copied from prelude/PrimOps.lhs.
514 I include here some comments about the estimated costs for these @PrimOps@.
515 Compare with the @primOpCosts@ fct above. -- HWL
519 -- I assume all these basic comparisons take just one ALU instruction
520 -- Checked that for Char, Int; Word, Addr should be the same as Int.
522 = CharGtOp | CharGeOp | CharEqOp | CharNeOp | CharLtOp | CharLeOp
523 | IntGtOp | IntGeOp | IntEqOp | IntNeOp | IntLtOp | IntLeOp
524 | WordGtOp | WordGeOp | WordEqOp | WordNeOp | WordLtOp | WordLeOp
525 | AddrGtOp | AddrGeOp | AddrEqOp | AddrNeOp | AddrLtOp | AddrLeOp
527 -- Analogously, these take one FP unit instruction
528 -- Haven't checked that, yet.
530 | FloatGtOp | FloatGeOp | FloatEqOp | FloatNeOp | FloatLtOp | FloatLeOp
531 | DoubleGtOp | DoubleGeOp | DoubleEqOp | DoubleNeOp | DoubleLtOp | DoubleLeOp
533 -- 1 ALU op; unchecked
536 -- these just take 1 ALU op; checked
537 | IntAddOp | IntSubOp
539 -- but these take more than that; see special cases in primOpCosts
540 -- I counted the generated ass. instructions for these -> checked
541 | IntMulOp | IntQuotOp
542 | IntDivOp | IntRemOp | IntNegOp | IntAbsOp
544 -- Rest is unchecked so far -- HWL
546 -- Word#-related ops:
547 | AndOp | OrOp | NotOp | ShiftLOp | ShiftROp
548 | Int2WordOp | Word2IntOp -- casts
550 -- Addr#-related ops:
551 | Int2AddrOp | Addr2IntOp -- casts
553 -- Float#-related ops:
554 | FloatAddOp | FloatSubOp | FloatMulOp | FloatDivOp | FloatNegOp
555 | Float2IntOp | Int2FloatOp
557 | FloatExpOp | FloatLogOp | FloatSqrtOp
558 | FloatSinOp | FloatCosOp | FloatTanOp
559 | FloatAsinOp | FloatAcosOp | FloatAtanOp
560 | FloatSinhOp | FloatCoshOp | FloatTanhOp
561 -- not all machines have these available conveniently:
562 -- | FloatAsinhOp | FloatAcoshOp | FloatAtanhOp
563 | FloatPowerOp -- ** op
565 -- Double#-related ops:
566 | DoubleAddOp | DoubleSubOp | DoubleMulOp | DoubleDivOp | DoubleNegOp
567 | Double2IntOp | Int2DoubleOp
568 | Double2FloatOp | Float2DoubleOp
570 | DoubleExpOp | DoubleLogOp | DoubleSqrtOp
571 | DoubleSinOp | DoubleCosOp | DoubleTanOp
572 | DoubleAsinOp | DoubleAcosOp | DoubleAtanOp
573 | DoubleSinhOp | DoubleCoshOp | DoubleTanhOp
574 -- not all machines have these available conveniently:
575 -- | DoubleAsinhOp | DoubleAcoshOp | DoubleAtanhOp
576 | DoublePowerOp -- ** op
578 -- Integer (and related...) ops:
579 -- slightly weird -- to match GMP package.
580 | IntegerAddOp | IntegerSubOp | IntegerMulOp
581 | IntegerQuotRemOp | IntegerDivModOp | IntegerNegOp
585 | Integer2IntOp | Int2IntegerOp
586 | Addr2IntegerOp -- "Addr" is *always* a literal string
589 | FloatEncodeOp | FloatDecodeOp
590 | DoubleEncodeOp | DoubleDecodeOp
592 -- primitive ops for primitive arrays
595 | NewByteArrayOp PrimKind
598 | SameMutableByteArrayOp
600 | ReadArrayOp | WriteArrayOp | IndexArrayOp -- for arrays of Haskell ptrs
602 | ReadByteArrayOp PrimKind
603 | WriteByteArrayOp PrimKind
604 | IndexByteArrayOp PrimKind
605 | IndexOffAddrOp PrimKind
606 -- PrimKind can be one of {Char,Int,Addr,Float,Double}Kind.
607 -- This is just a cheesy encoding of a bunch of ops.
608 -- Note that MallocPtrKind is not included -- the only way of
609 -- creating a MallocPtr is with a ccall or casm.
611 | UnsafeFreezeArrayOp | UnsafeFreezeByteArrayOp
613 | MakeStablePtrOp | DeRefStablePtrOp
616 A special ``trap-door'' to use in making calls direct to C functions:
617 Note: From GrAn point of view, CCall is probably very expensive -- HWL
620 | CCallOp String -- An "unboxed" ccall# to this named function
621 Bool -- True <=> really a "casm"
622 Bool -- True <=> might invoke Haskell GC
623 [UniType] -- Unboxed argument; the state-token
624 -- argument will have been put *first*
625 UniType -- Return type; one of the "StateAnd<blah>#" types
627 -- (... to be continued ... )