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(..)
64 -- --------------------------------------------------------------------------
66 -- a module of "stubs" that don't do anything
67 data CostRes = Cost (Int, Int, Int, Int, Int)
70 nullCosts = Cost (0, 0, 0, 0, 0) :: CostRes
72 costs :: AbstractC -> CostRes
73 addrModeCosts :: CAddrMode -> Side -> CostRes
75 addrModeCosts _ _ = nullCosts
77 instance Eq CostRes; instance Text CostRes
79 instance Num CostRes where
85 data CostRes = Cost (Int, Int, Int, Int, Int)
88 nullCosts = Cost (0, 0, 0, 0, 0) :: CostRes
89 initHdrCosts = Cost (2, 0, 0, 1, 0) :: CostRes
90 errorCosts = Cost (-1, -1, -1, -1, -1) -- just for debugging
92 oneArithm = Cost (1, 0, 0, 0, 0) :: CostRes
94 instance Eq CostRes where
95 (==) t1 t2 = i && b && l && s && f
96 where (i,b,l,s,f) = binOp' (==) t1 t2
98 instance Num CostRes where
102 negate = mapOp negate
104 signum = mapOp signum
106 mapOp :: (Int -> Int) -> CostRes -> CostRes
107 mapOp g ( Cost (i, b, l, s, f) ) = Cost (g i, g b, g l, g s, g f)
109 foldrOp :: (Int -> a -> a) -> a -> CostRes -> a
110 foldrOp o x ( Cost (i1, b1, l1, s1, f1) ) =
111 i1 `o` ( b1 `o` ( l1 `o` ( s1 `o` ( f1 `o` x))))
113 binOp :: (Int -> Int -> Int) -> CostRes -> CostRes -> CostRes
114 binOp o ( Cost (i1, b1, l1, s1, f1) ) ( Cost (i2, b2, l2, s2, f2) ) =
115 ( Cost (i1 `o` i2, b1 `o` b2, l1 `o` l2, s1 `o` s2, f1 `o` f2) )
117 binOp' :: (Int -> Int -> a) -> CostRes -> CostRes -> (a,a,a,a,a)
118 binOp' o ( Cost (i1, b1, l1, s1, f1) ) ( Cost (i2, b2, l2, s2, f2) ) =
119 (i1 `o` i2, b1 `o` b2, l1 `o` l2, s1 `o` s2, f1 `o` f2)
121 -- --------------------------------------------------------------------------
123 data Side = Lhs | Rhs
126 -- --------------------------------------------------------------------------
128 costs :: AbstractC -> CostRes
134 AbsCStmts absC1 absC2 -> costs absC1 + costs absC2
136 CAssign (CReg _) (CReg _) -> Cost (1,0,0,0,0) -- typ.: mov %reg1,%reg2
138 CAssign (CReg _) (CTemp _ _) -> Cost (1,0,0,0,0)
140 CAssign (CReg _) (CAddr _) -> Cost (1,0,0,0,0) -- typ.: add %reg1,<adr>,%reg2
142 CAssign target_m source_m -> addrModeCosts target_m Lhs +
143 addrModeCosts source_m Rhs
145 CJump (CLbl _ _) -> Cost (0,1,0,0,0) -- no ld for call necessary
147 CJump mode -> addrModeCosts mode Rhs +
150 CFallThrough mode -> addrModeCosts mode Rhs + -- chu' 0.24
153 CReturn mode info -> case info of
154 DirectReturn -> addrModeCosts mode Rhs +
157 -- i.e. ld address to reg and call reg
159 DynamicVectoredReturn mode' ->
160 addrModeCosts mode Rhs +
161 addrModeCosts mode' Rhs +
164 {- generates code like this:
165 JMP_(<mode>)[RVREL(<mode'>)];
166 i.e. 1 possb ld for mode'
171 StaticVectoredReturn _ -> addrModeCosts mode Rhs +
174 -- as above with mode' fixed to CLit
175 -- typically 2 ld + 1 call; 1st ld due
178 CSwitch mode alts absC -> nullCosts
179 {- for handling costs of all branches of
180 a CSwitch see PprAbsC.
183 Costs before CSwitch +
184 addrModeCosts of head +
185 Costs for 1 cond branch +
186 Costs for body of branch
189 CCodeBlock _ absC -> costs absC
191 CInitHdr cl_info reg_rel cost_centre inplace_upd -> initHdrCosts
193 {- This is more fancy but superflous: The addr modes
194 are fixed and so the costs are const!
196 argCosts + initHdrCosts
197 where argCosts = addrModeCosts (CAddr reg_rel) Rhs +
198 addrModeCosts base_lbl + -- CLbl!
199 3*addrModeCosts (mkIntCLit 1{- any val -})
201 {- this extends to something like
203 For costing the args of this macro
204 see PprAbsC.lhs where args are inserted -}
206 COpStmt modes_res primOp modes_args _ _ ->
213 if primOpNeedsWrapper primOp then SAVE_COSTS + RESTORE_COSTS
217 foldl (+) nullCosts [addrModeCosts mode Lhs | mode <- modes_res] +
218 foldl (+) nullCosts [addrModeCosts mode Rhs | mode <- modes_args] +
220 if primOpNeedsWrapper primOp then SAVE_COSTS + RESTORE_COSTS
223 CSimultaneous absC -> costs absC
225 CMacroStmt macro modes -> stmtMacroCosts macro modes
227 CCallProfCtrMacro _ _ -> nullCosts
228 {- we don't count profiling in GrAnSim -}
230 CCallProfCCMacro _ _ -> nullCosts
231 {- we don't count profiling in GrAnSim -}
233 -- *** the next three [or so...] are DATA (those above are CODE) ***
234 -- as they are data rather than code they all have nullCosts -- HWL
236 CStaticClosure _ _ _ _ -> nullCosts
238 CClosureInfoAndCode _ _ _ _ _ _ -> nullCosts
240 CRetVector _ _ _ -> nullCosts
242 CRetUnVector _ _ -> nullCosts
244 CFlatRetVector _ _ -> nullCosts
246 CCostCentreDecl _ _ -> nullCosts
248 CClosureUpdInfo _ -> nullCosts
250 CSplitMarker -> nullCosts
252 -- ---------------------------------------------------------------------------
254 addrModeCosts :: CAddrMode -> Side -> CostRes
256 -- addrModeCosts _ _ = nullCosts
258 addrModeCosts addr_mode side =
263 CVal _ _ -> if lhs then Cost (0, 0, 0, 1, 0)
264 else Cost (0, 0, 1, 0, 0)
266 CAddr _ -> if lhs then Cost (0, 0, 0, 1, 0) -- ??unchecked
267 else Cost (0, 0, 1, 0, 0)
269 CReg _ -> nullCosts {- loading from, storing to reg is free ! -}
270 {- for costing CReg->Creg ops see special -}
271 {- case in costs fct -}
272 CTableEntry base_mode offset_mode kind ->
273 addrModeCosts base_mode side +
274 addrModeCosts offset_mode side +
277 CTemp _ _ -> nullCosts {- if lhs then Cost (0, 0, 0, 1, 0)
278 else Cost (0, 0, 1, 0, 0) -}
279 -- ``Temporaries'' correspond to local variables in C, and registers in
281 -- I assume they can be somewhat optimized by gcc -- HWL
283 CLbl _ _ -> if lhs then Cost (0, 0, 0, 1, 0)
284 else Cost (2, 0, 0, 0, 0)
285 -- Rhs: typically: sethi %hi(lbl),%tmp_reg
286 -- or %tmp_reg,%lo(lbl),%target_reg
288 CUnVecLbl _ _ -> if lhs then Cost (0, 0, 0, 1, 0)
289 else Cost (2, 0, 0, 0, 0)
292 -- Check the following 3 (checked form CLit on)
294 CCharLike mode -> if lhs then Cost (0, 0, 0, 1, 0)
295 else Cost (0, 0, 1, 0, 0)
297 CIntLike mode -> if lhs then Cost (0, 0, 0, 1, 0)
298 else Cost (0, 0, 1, 0, 0)
300 CString _ -> if lhs then Cost (0, 0, 0, 1, 0)
301 else Cost (0, 0, 1, 0, 0)
303 CLit _ -> if lhs then nullCosts -- should never occur
304 else Cost (1, 0, 0, 0, 0) -- typ.: mov lit,%reg
306 CLitLit _ _ -> if lhs then nullCosts
307 else Cost (1, 0, 0, 0, 0)
310 COffset _ -> if lhs then nullCosts
311 else Cost (1, 0, 0, 0, 0)
314 CCode absC -> costs absC
316 CLabelledCode _ absC -> costs absC
318 CJoinPoint _ _ -> if lhs then Cost (0, 0, 0, 1, 0)
319 else Cost (0, 0, 1, 0, 0)
321 CMacroExpr _ macro mode_list -> exprMacroCosts side macro mode_list
323 CCostCentre _ _ -> nullCosts
325 -- ---------------------------------------------------------------------------
327 exprMacroCosts :: Side -> CExprMacro -> [CAddrMode] -> CostRes
329 exprMacroCosts side macro mode_list =
331 arg_costs = foldl (+) nullCosts
332 (map (\ x -> addrModeCosts x Rhs) mode_list)
336 INFO_PTR -> if side == Lhs then Cost (0, 0, 0, 1, 0)
337 else Cost (0, 0, 1, 0, 0)
338 ENTRY_CODE -> nullCosts
339 INFO_TAG -> if side == Lhs then Cost (0, 0, 0, 1, 0)
340 else Cost (0, 0, 1, 0, 0)
341 EVAL_TAG -> if side == Lhs then Cost (1, 0, 0, 1, 0)
342 else Cost (1, 0, 1, 0, 0)
343 -- costs of INFO_TAG + (1,0,0,0,0)
345 -- ---------------------------------------------------------------------------
347 stmtMacroCosts :: CStmtMacro -> [CAddrMode] -> CostRes
349 stmtMacroCosts macro modes =
351 arg_costs = foldl (+) nullCosts
352 [addrModeCosts mode Rhs | mode <- modes]
355 ARGS_CHK_A_LOAD_NODE -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
356 -- p=probability of PAP (instead of AP): + p*(3,1,0,0,0)
357 ARGS_CHK_A -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
358 -- p=probability of PAP (instead of AP): + p*(0,1,0,0,0)
359 ARGS_CHK_B_LOAD_NODE -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
360 ARGS_CHK_B -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
361 HEAP_CHK -> Cost (2, 1, 0, 0, 0) {- StgMacros.lh -}
362 -- STK_CHK -> (2, 1, 0, 0, 0) {- StgMacros.lh -}
363 STK_CHK -> Cost (0, 0, 0, 0, 0) {- StgMacros.lh -}
364 UPD_CAF -> Cost (7, 0, 1, 3, 0) {- SMupdate.lh -}
365 UPD_IND -> Cost (8, 2, 2, 0, 0) {- SMupdate.lh
366 updatee in old-gen: Cost (4, 1, 1, 0, 0)
367 updatee in new-gen: Cost (4, 1, 1, 0, 0)
368 NB: we include costs fo checking if there is
369 a BQ, but we omit costs for awakening BQ
370 (these probably differ between old-gen and
372 UPD_INPLACE_NOPTRS -> Cost (13, 3, 3, 2, 0) {- SMupdate.lh
373 common for both: Cost (4, 1, 1, 0, 0)
374 updatee in old-gen: Cost (14, 3, 2, 4, 0)
375 updatee in new-gen: Cost (4, 1, 1, 0, 0) -}
376 UPD_INPLACE_PTRS -> Cost (13, 3, 3, 2, 0) {- SMupdate.lh
377 common for both: Cost (4, 1, 1, 0, 0)
378 updatee in old-gen: Cost (14, 3, 2, 4, 0)
379 updatee in new-gen: Cost (4, 1, 1, 0, 0) -}
381 UPD_BH_UPDATABLE -> Cost (3, 0, 0, 1, 0) {- SMupdate.lh -}
382 UPD_BH_SINGLE_ENTRY -> Cost (3, 0, 0, 1, 0) {- SMupdate.lh -}
383 PUSH_STD_UPD_FRAME -> Cost (3, 0, 0, 4, 0) {- SMupdate.lh -}
384 POP_STD_UPD_FRAME -> Cost (1, 0, 3, 0, 0) {- SMupdate.lh -}
385 SET_ARITY -> nullCosts {- StgMacros.lh -}
386 CHK_ARITY -> nullCosts {- StgMacros.lh -}
387 SET_TAG -> nullCosts {- COptRegs.lh -}
388 GRAN_FETCH -> nullCosts {- GrAnSim bookkeeping -}
389 GRAN_RESCHEDULE -> nullCosts {- GrAnSim bookkeeping -}
390 GRAN_FETCH_AND_RESCHEDULE -> nullCosts {- GrAnSim bookkeeping -}
391 THREAD_CONTEXT_SWITCH -> nullCosts {- GrAnSim bookkeeping -}
393 -- ---------------------------------------------------------------------------
397 [ FloatGtOp , FloatGeOp , FloatEqOp , FloatNeOp , FloatLtOp , FloatLeOp
398 , DoubleGtOp , DoubleGeOp , DoubleEqOp , DoubleNeOp , DoubleLtOp , DoubleLeOp
399 , FloatAddOp , FloatSubOp , FloatMulOp , FloatDivOp , FloatNegOp
400 , Float2IntOp , Int2FloatOp
401 , FloatExpOp , FloatLogOp , FloatSqrtOp
402 , FloatSinOp , FloatCosOp , FloatTanOp
403 , FloatAsinOp , FloatAcosOp , FloatAtanOp
404 , FloatSinhOp , FloatCoshOp , FloatTanhOp
406 , DoubleAddOp , DoubleSubOp , DoubleMulOp , DoubleDivOp , DoubleNegOp
407 , Double2IntOp , Int2DoubleOp
408 , Double2FloatOp , Float2DoubleOp
409 , DoubleExpOp , DoubleLogOp , DoubleSqrtOp
410 , DoubleSinOp , DoubleCosOp , DoubleTanOp
411 , DoubleAsinOp , DoubleAcosOp , DoubleAtanOp
412 , DoubleSinhOp , DoubleCoshOp , DoubleTanhOp
414 , FloatEncodeOp , FloatDecodeOp
415 , DoubleEncodeOp , DoubleDecodeOp
420 [ IntegerAddOp , IntegerSubOp , IntegerMulOp
421 , IntegerQuotRemOp , IntegerDivModOp , IntegerNegOp
423 , Integer2IntOp , Int2IntegerOp
428 -- Haven't found the .umul .div .rem macros yet
429 -- If they are not Haskell cde, they are not costed, yet
431 abs_costs = nullCosts -- NB: This is normal STG code with costs already
432 -- included; no need to add costs again.
434 umul_costs = Cost (21,4,0,0,0) -- due to spy counts
435 rem_costs = Cost (30,15,0,0,0) -- due to spy counts
436 div_costs = Cost (30,15,0,0,0) -- due to spy counts
438 primOpCosts :: PrimOp -> CostRes
442 primOpCosts (CCallOp _ _ _ _ _) = SAVE_COSTS + CCALL_COSTS_GUESS +
443 RESTORE_COSTS -- GUESS; check it
445 -- Usually 3 mov instructions are needed to get args and res in right place.
447 primOpCosts IntMulOp = Cost (3, 1, 0, 0, 0) + umul_costs
448 primOpCosts IntQuotOp = Cost (3, 1, 0, 0, 0) + div_costs
449 primOpCosts IntRemOp = Cost (3, 1, 0, 0, 0) + rem_costs
450 primOpCosts IntNegOp = Cost (1, 1, 0, 0, 0) -- translates into 1 sub
451 primOpCosts IntAbsOp = Cost (0, 1, 0, 0, 0) -- abs closure already costed
453 primOpCosts FloatGtOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
454 primOpCosts FloatGeOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
455 primOpCosts FloatEqOp = Cost (0, 0, 0, 0, 2) -- cheap f-comp
456 primOpCosts FloatNeOp = Cost (0, 0, 0, 0, 2) -- cheap f-comp
457 primOpCosts FloatLtOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
458 primOpCosts FloatLeOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
459 primOpCosts DoubleGtOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
460 primOpCosts DoubleGeOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
461 primOpCosts DoubleEqOp = Cost (0, 0, 0, 0, 2) -- cheap f-comp
462 primOpCosts DoubleNeOp = Cost (0, 0, 0, 0, 2) -- cheap f-comp
463 primOpCosts DoubleLtOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
464 primOpCosts DoubleLeOp = Cost (2, 0, 0, 0, 2) -- expensive f-comp
466 primOpCosts FloatExpOp = Cost (2, 1, 4, 4, 3)
467 primOpCosts FloatLogOp = Cost (2, 1, 4, 4, 3)
468 primOpCosts FloatSqrtOp = Cost (2, 1, 4, 4, 3)
469 primOpCosts FloatSinOp = Cost (2, 1, 4, 4, 3)
470 primOpCosts FloatCosOp = Cost (2, 1, 4, 4, 3)
471 primOpCosts FloatTanOp = Cost (2, 1, 4, 4, 3)
472 primOpCosts FloatAsinOp = Cost (2, 1, 4, 4, 3)
473 primOpCosts FloatAcosOp = Cost (2, 1, 4, 4, 3)
474 primOpCosts FloatAtanOp = Cost (2, 1, 4, 4, 3)
475 primOpCosts FloatSinhOp = Cost (2, 1, 4, 4, 3)
476 primOpCosts FloatCoshOp = Cost (2, 1, 4, 4, 3)
477 primOpCosts FloatTanhOp = Cost (2, 1, 4, 4, 3)
478 --primOpCosts FloatAsinhOp = Cost (2, 1, 4, 4, 3)
479 --primOpCosts FloatAcoshOp = Cost (2, 1, 4, 4, 3)
480 --primOpCosts FloatAtanhOp = Cost (2, 1, 4, 4, 3)
481 primOpCosts FloatPowerOp = Cost (2, 1, 4, 4, 3)
483 {- There should be special handling of the Array PrimOps in here HWL -}
486 | primOp `elem` floatOps = Cost (0, 0, 0, 0, 1) :: CostRes
487 | primOp `elem` gmpOps = Cost (50, 5, 10, 10, 0) :: CostRes -- GUESS; check it
488 | otherwise = Cost (1, 0, 0, 0, 0)
490 -- ---------------------------------------------------------------------------
491 {- HWL: currently unused
493 costsByKind :: PrimRep -> Side -> CostRes
495 -- The following PrimKinds say that the data is already in a reg
497 costsByKind CharRep _ = nullCosts
498 costsByKind IntRep _ = nullCosts
499 costsByKind WordRep _ = nullCosts
500 costsByKind AddrRep _ = nullCosts
501 costsByKind FloatRep _ = nullCosts
502 costsByKind DoubleRep _ = nullCosts
504 -- ---------------------------------------------------------------------------
509 This is the data structure of {\tt PrimOp} copied from prelude/PrimOp.lhs.
510 I include here some comments about the estimated costs for these @PrimOps@.
511 Compare with the @primOpCosts@ fct above. -- HWL
515 -- I assume all these basic comparisons take just one ALU instruction
516 -- Checked that for Char, Int; Word, Addr should be the same as Int.
518 = CharGtOp | CharGeOp | CharEqOp | CharNeOp | CharLtOp | CharLeOp
519 | IntGtOp | IntGeOp | IntEqOp | IntNeOp | IntLtOp | IntLeOp
520 | WordGtOp | WordGeOp | WordEqOp | WordNeOp | WordLtOp | WordLeOp
521 | AddrGtOp | AddrGeOp | AddrEqOp | AddrNeOp | AddrLtOp | AddrLeOp
523 -- Analogously, these take one FP unit instruction
524 -- Haven't checked that, yet.
526 | FloatGtOp | FloatGeOp | FloatEqOp | FloatNeOp | FloatLtOp | FloatLeOp
527 | DoubleGtOp | DoubleGeOp | DoubleEqOp | DoubleNeOp | DoubleLtOp | DoubleLeOp
529 -- 1 ALU op; unchecked
532 -- these just take 1 ALU op; checked
533 | IntAddOp | IntSubOp
535 -- but these take more than that; see special cases in primOpCosts
536 -- I counted the generated ass. instructions for these -> checked
537 | IntMulOp | IntQuotOp
538 | IntRemOp | IntNegOp | IntAbsOp
540 -- Rest is unchecked so far -- HWL
542 -- Word#-related ops:
543 | AndOp | OrOp | NotOp | ShiftLOp | ShiftROp
544 | Int2WordOp | Word2IntOp -- casts
546 -- Addr#-related ops:
547 | Int2AddrOp | Addr2IntOp -- casts
549 -- Float#-related ops:
550 | FloatAddOp | FloatSubOp | FloatMulOp | FloatDivOp | FloatNegOp
551 | Float2IntOp | Int2FloatOp
553 | FloatExpOp | FloatLogOp | FloatSqrtOp
554 | FloatSinOp | FloatCosOp | FloatTanOp
555 | FloatAsinOp | FloatAcosOp | FloatAtanOp
556 | FloatSinhOp | FloatCoshOp | FloatTanhOp
557 -- not all machines have these available conveniently:
558 -- | FloatAsinhOp | FloatAcoshOp | FloatAtanhOp
559 | FloatPowerOp -- ** op
561 -- Double#-related ops:
562 | DoubleAddOp | DoubleSubOp | DoubleMulOp | DoubleDivOp | DoubleNegOp
563 | Double2IntOp | Int2DoubleOp
564 | Double2FloatOp | Float2DoubleOp
566 | DoubleExpOp | DoubleLogOp | DoubleSqrtOp
567 | DoubleSinOp | DoubleCosOp | DoubleTanOp
568 | DoubleAsinOp | DoubleAcosOp | DoubleAtanOp
569 | DoubleSinhOp | DoubleCoshOp | DoubleTanhOp
570 -- not all machines have these available conveniently:
571 -- | DoubleAsinhOp | DoubleAcoshOp | DoubleAtanhOp
572 | DoublePowerOp -- ** op
574 -- Integer (and related...) ops:
575 -- slightly weird -- to match GMP package.
576 | IntegerAddOp | IntegerSubOp | IntegerMulOp
577 | IntegerQuotRemOp | IntegerDivModOp | IntegerNegOp
581 | Integer2IntOp | Int2IntegerOp
582 | Addr2IntegerOp -- "Addr" is *always* a literal string
585 | FloatEncodeOp | FloatDecodeOp
586 | DoubleEncodeOp | DoubleDecodeOp
588 -- primitive ops for primitive arrays
591 | NewByteArrayOp PrimRep
594 | SameMutableByteArrayOp
596 | ReadArrayOp | WriteArrayOp | IndexArrayOp -- for arrays of Haskell ptrs
598 | ReadByteArrayOp PrimRep
599 | WriteByteArrayOp PrimRep
600 | IndexByteArrayOp PrimRep
601 | IndexOffAddrOp PrimRep
602 -- PrimRep can be one of {Char,Int,Addr,Float,Double}Kind.
603 -- This is just a cheesy encoding of a bunch of ops.
604 -- Note that MallocPtrRep is not included -- the only way of
605 -- creating a MallocPtr is with a ccall or casm.
607 | UnsafeFreezeArrayOp | UnsafeFreezeByteArrayOp
609 | MakeStablePtrOp | DeRefStablePtrOp
612 A special ``trap-door'' to use in making calls direct to C functions:
613 Note: From GrAn point of view, CCall is probably very expensive -- HWL
616 | CCallOp String -- An "unboxed" ccall# to this named function
617 Bool -- True <=> really a "casm"
618 Bool -- True <=> might invoke Haskell GC
619 [Type] -- Unboxed argument; the state-token
620 -- argument will have been put *first*
621 Type -- Return type; one of the "StateAnd<blah>#" types
623 -- (... to be continued ... )