| 1 | % |
|---|
| 2 | % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 |
|---|
| 3 | % |
|---|
| 4 | \section[PrimOp]{Primitive operations (machine-level)} |
|---|
| 5 | |
|---|
| 6 | \begin{code} |
|---|
| 7 | module PrimOp ( |
|---|
| 8 | PrimOp(..), allThePrimOps, |
|---|
| 9 | primOpType, primOpSig, |
|---|
| 10 | primOpTag, maxPrimOpTag, primOpOcc, |
|---|
| 11 | |
|---|
| 12 | tagToEnumKey, |
|---|
| 13 | |
|---|
| 14 | primOpOutOfLine, primOpCodeSize, |
|---|
| 15 | primOpOkForSpeculation, primOpOkForSideEffects, |
|---|
| 16 | primOpIsCheap, |
|---|
| 17 | |
|---|
| 18 | getPrimOpResultInfo, PrimOpResultInfo(..), |
|---|
| 19 | |
|---|
| 20 | PrimCall(..) |
|---|
| 21 | ) where |
|---|
| 22 | |
|---|
| 23 | #include "HsVersions.h" |
|---|
| 24 | |
|---|
| 25 | import TysPrim |
|---|
| 26 | import TysWiredIn |
|---|
| 27 | |
|---|
| 28 | import Demand |
|---|
| 29 | import Var ( TyVar ) |
|---|
| 30 | import OccName ( OccName, pprOccName, mkVarOccFS ) |
|---|
| 31 | import TyCon ( TyCon, isPrimTyCon, tyConPrimRep, PrimRep(..) ) |
|---|
| 32 | import Type ( Type, mkForAllTys, mkFunTy, mkFunTys, tyConAppTyCon, |
|---|
| 33 | typePrimRep ) |
|---|
| 34 | import BasicTypes ( Arity, TupleSort(..) ) |
|---|
| 35 | import ForeignCall ( CLabelString ) |
|---|
| 36 | import Unique ( Unique, mkPrimOpIdUnique ) |
|---|
| 37 | import Outputable |
|---|
| 38 | import FastTypes |
|---|
| 39 | import FastString |
|---|
| 40 | import Module ( PackageId ) |
|---|
| 41 | \end{code} |
|---|
| 42 | |
|---|
| 43 | %************************************************************************ |
|---|
| 44 | %* * |
|---|
| 45 | \subsection[PrimOp-datatype]{Datatype for @PrimOp@ (an enumeration)} |
|---|
| 46 | %* * |
|---|
| 47 | %************************************************************************ |
|---|
| 48 | |
|---|
| 49 | These are in \tr{state-interface.verb} order. |
|---|
| 50 | |
|---|
| 51 | \begin{code} |
|---|
| 52 | |
|---|
| 53 | -- supplies: |
|---|
| 54 | -- data PrimOp = ... |
|---|
| 55 | #include "primop-data-decl.hs-incl" |
|---|
| 56 | \end{code} |
|---|
| 57 | |
|---|
| 58 | Used for the Ord instance |
|---|
| 59 | |
|---|
| 60 | \begin{code} |
|---|
| 61 | primOpTag :: PrimOp -> Int |
|---|
| 62 | primOpTag op = iBox (tagOf_PrimOp op) |
|---|
| 63 | |
|---|
| 64 | -- supplies |
|---|
| 65 | -- tagOf_PrimOp :: PrimOp -> FastInt |
|---|
| 66 | #include "primop-tag.hs-incl" |
|---|
| 67 | |
|---|
| 68 | |
|---|
| 69 | instance Eq PrimOp where |
|---|
| 70 | op1 == op2 = tagOf_PrimOp op1 ==# tagOf_PrimOp op2 |
|---|
| 71 | |
|---|
| 72 | instance Ord PrimOp where |
|---|
| 73 | op1 < op2 = tagOf_PrimOp op1 <# tagOf_PrimOp op2 |
|---|
| 74 | op1 <= op2 = tagOf_PrimOp op1 <=# tagOf_PrimOp op2 |
|---|
| 75 | op1 >= op2 = tagOf_PrimOp op1 >=# tagOf_PrimOp op2 |
|---|
| 76 | op1 > op2 = tagOf_PrimOp op1 ># tagOf_PrimOp op2 |
|---|
| 77 | op1 `compare` op2 | op1 < op2 = LT |
|---|
| 78 | | op1 == op2 = EQ |
|---|
| 79 | | otherwise = GT |
|---|
| 80 | |
|---|
| 81 | instance Outputable PrimOp where |
|---|
| 82 | ppr op = pprPrimOp op |
|---|
| 83 | |
|---|
| 84 | instance Show PrimOp where |
|---|
| 85 | showsPrec p op = showsPrecSDoc p (pprPrimOp op) |
|---|
| 86 | \end{code} |
|---|
| 87 | |
|---|
| 88 | An @Enum@-derived list would be better; meanwhile... (ToDo) |
|---|
| 89 | |
|---|
| 90 | \begin{code} |
|---|
| 91 | allThePrimOps :: [PrimOp] |
|---|
| 92 | allThePrimOps = |
|---|
| 93 | #include "primop-list.hs-incl" |
|---|
| 94 | \end{code} |
|---|
| 95 | |
|---|
| 96 | \begin{code} |
|---|
| 97 | tagToEnumKey :: Unique |
|---|
| 98 | tagToEnumKey = mkPrimOpIdUnique (primOpTag TagToEnumOp) |
|---|
| 99 | \end{code} |
|---|
| 100 | |
|---|
| 101 | |
|---|
| 102 | |
|---|
| 103 | %************************************************************************ |
|---|
| 104 | %* * |
|---|
| 105 | \subsection[PrimOp-info]{The essential info about each @PrimOp@} |
|---|
| 106 | %* * |
|---|
| 107 | %************************************************************************ |
|---|
| 108 | |
|---|
| 109 | The @String@ in the @PrimOpInfos@ is the ``base name'' by which the user may |
|---|
| 110 | refer to the primitive operation. The conventional \tr{#}-for- |
|---|
| 111 | unboxed ops is added on later. |
|---|
| 112 | |
|---|
| 113 | The reason for the funny characters in the names is so we do not |
|---|
| 114 | interfere with the programmer's Haskell name spaces. |
|---|
| 115 | |
|---|
| 116 | We use @PrimKinds@ for the ``type'' information, because they're |
|---|
| 117 | (slightly) more convenient to use than @TyCons@. |
|---|
| 118 | \begin{code} |
|---|
| 119 | data PrimOpInfo |
|---|
| 120 | = Dyadic OccName -- string :: T -> T -> T |
|---|
| 121 | Type |
|---|
| 122 | | Monadic OccName -- string :: T -> T |
|---|
| 123 | Type |
|---|
| 124 | | Compare OccName -- string :: T -> T -> Bool |
|---|
| 125 | Type |
|---|
| 126 | |
|---|
| 127 | | GenPrimOp OccName -- string :: \/a1..an . T1 -> .. -> Tk -> T |
|---|
| 128 | [TyVar] |
|---|
| 129 | [Type] |
|---|
| 130 | Type |
|---|
| 131 | |
|---|
| 132 | mkDyadic, mkMonadic, mkCompare :: FastString -> Type -> PrimOpInfo |
|---|
| 133 | mkDyadic str ty = Dyadic (mkVarOccFS str) ty |
|---|
| 134 | mkMonadic str ty = Monadic (mkVarOccFS str) ty |
|---|
| 135 | mkCompare str ty = Compare (mkVarOccFS str) ty |
|---|
| 136 | |
|---|
| 137 | mkGenPrimOp :: FastString -> [TyVar] -> [Type] -> Type -> PrimOpInfo |
|---|
| 138 | mkGenPrimOp str tvs tys ty = GenPrimOp (mkVarOccFS str) tvs tys ty |
|---|
| 139 | \end{code} |
|---|
| 140 | |
|---|
| 141 | %************************************************************************ |
|---|
| 142 | %* * |
|---|
| 143 | \subsubsection{Strictness} |
|---|
| 144 | %* * |
|---|
| 145 | %************************************************************************ |
|---|
| 146 | |
|---|
| 147 | Not all primops are strict! |
|---|
| 148 | |
|---|
| 149 | \begin{code} |
|---|
| 150 | primOpStrictness :: PrimOp -> Arity -> StrictSig |
|---|
| 151 | -- See Demand.StrictnessInfo for discussion of what the results |
|---|
| 152 | -- The arity should be the arity of the primop; that's why |
|---|
| 153 | -- this function isn't exported. |
|---|
| 154 | #include "primop-strictness.hs-incl" |
|---|
| 155 | \end{code} |
|---|
| 156 | |
|---|
| 157 | %************************************************************************ |
|---|
| 158 | %* * |
|---|
| 159 | \subsubsection[PrimOp-comparison]{PrimOpInfo basic comparison ops} |
|---|
| 160 | %* * |
|---|
| 161 | %************************************************************************ |
|---|
| 162 | |
|---|
| 163 | @primOpInfo@ gives all essential information (from which everything |
|---|
| 164 | else, notably a type, can be constructed) for each @PrimOp@. |
|---|
| 165 | |
|---|
| 166 | \begin{code} |
|---|
| 167 | primOpInfo :: PrimOp -> PrimOpInfo |
|---|
| 168 | #include "primop-primop-info.hs-incl" |
|---|
| 169 | \end{code} |
|---|
| 170 | |
|---|
| 171 | Here are a load of comments from the old primOp info: |
|---|
| 172 | |
|---|
| 173 | A @Word#@ is an unsigned @Int#@. |
|---|
| 174 | |
|---|
| 175 | @decodeFloat#@ is given w/ Integer-stuff (it's similar). |
|---|
| 176 | |
|---|
| 177 | @decodeDouble#@ is given w/ Integer-stuff (it's similar). |
|---|
| 178 | |
|---|
| 179 | Decoding of floating-point numbers is sorta Integer-related. Encoding |
|---|
| 180 | is done with plain ccalls now (see PrelNumExtra.lhs). |
|---|
| 181 | |
|---|
| 182 | A @Weak@ Pointer is created by the @mkWeak#@ primitive: |
|---|
| 183 | |
|---|
| 184 | mkWeak# :: k -> v -> f -> State# RealWorld |
|---|
| 185 | -> (# State# RealWorld, Weak# v #) |
|---|
| 186 | |
|---|
| 187 | In practice, you'll use the higher-level |
|---|
| 188 | |
|---|
| 189 | data Weak v = Weak# v |
|---|
| 190 | mkWeak :: k -> v -> IO () -> IO (Weak v) |
|---|
| 191 | |
|---|
| 192 | The following operation dereferences a weak pointer. The weak pointer |
|---|
| 193 | may have been finalized, so the operation returns a result code which |
|---|
| 194 | must be inspected before looking at the dereferenced value. |
|---|
| 195 | |
|---|
| 196 | deRefWeak# :: Weak# v -> State# RealWorld -> |
|---|
| 197 | (# State# RealWorld, v, Int# #) |
|---|
| 198 | |
|---|
| 199 | Only look at v if the Int# returned is /= 0 !! |
|---|
| 200 | |
|---|
| 201 | The higher-level op is |
|---|
| 202 | |
|---|
| 203 | deRefWeak :: Weak v -> IO (Maybe v) |
|---|
| 204 | |
|---|
| 205 | Weak pointers can be finalized early by using the finalize# operation: |
|---|
| 206 | |
|---|
| 207 | finalizeWeak# :: Weak# v -> State# RealWorld -> |
|---|
| 208 | (# State# RealWorld, Int#, IO () #) |
|---|
| 209 | |
|---|
| 210 | The Int# returned is either |
|---|
| 211 | |
|---|
| 212 | 0 if the weak pointer has already been finalized, or it has no |
|---|
| 213 | finalizer (the third component is then invalid). |
|---|
| 214 | |
|---|
| 215 | 1 if the weak pointer is still alive, with the finalizer returned |
|---|
| 216 | as the third component. |
|---|
| 217 | |
|---|
| 218 | A {\em stable name/pointer} is an index into a table of stable name |
|---|
| 219 | entries. Since the garbage collector is told about stable pointers, |
|---|
| 220 | it is safe to pass a stable pointer to external systems such as C |
|---|
| 221 | routines. |
|---|
| 222 | |
|---|
| 223 | \begin{verbatim} |
|---|
| 224 | makeStablePtr# :: a -> State# RealWorld -> (# State# RealWorld, StablePtr# a #) |
|---|
| 225 | freeStablePtr :: StablePtr# a -> State# RealWorld -> State# RealWorld |
|---|
| 226 | deRefStablePtr# :: StablePtr# a -> State# RealWorld -> (# State# RealWorld, a #) |
|---|
| 227 | eqStablePtr# :: StablePtr# a -> StablePtr# a -> Int# |
|---|
| 228 | \end{verbatim} |
|---|
| 229 | |
|---|
| 230 | It may seem a bit surprising that @makeStablePtr#@ is a @IO@ |
|---|
| 231 | operation since it doesn't (directly) involve IO operations. The |
|---|
| 232 | reason is that if some optimisation pass decided to duplicate calls to |
|---|
| 233 | @makeStablePtr#@ and we only pass one of the stable pointers over, a |
|---|
| 234 | massive space leak can result. Putting it into the IO monad |
|---|
| 235 | prevents this. (Another reason for putting them in a monad is to |
|---|
| 236 | ensure correct sequencing wrt the side-effecting @freeStablePtr@ |
|---|
| 237 | operation.) |
|---|
| 238 | |
|---|
| 239 | An important property of stable pointers is that if you call |
|---|
| 240 | makeStablePtr# twice on the same object you get the same stable |
|---|
| 241 | pointer back. |
|---|
| 242 | |
|---|
| 243 | Note that we can implement @freeStablePtr#@ using @_ccall_@ (and, |
|---|
| 244 | besides, it's not likely to be used from Haskell) so it's not a |
|---|
| 245 | primop. |
|---|
| 246 | |
|---|
| 247 | Question: Why @RealWorld@ - won't any instance of @_ST@ do the job? [ADR] |
|---|
| 248 | |
|---|
| 249 | Stable Names |
|---|
| 250 | ~~~~~~~~~~~~ |
|---|
| 251 | |
|---|
| 252 | A stable name is like a stable pointer, but with three important differences: |
|---|
| 253 | |
|---|
| 254 | (a) You can't deRef one to get back to the original object. |
|---|
| 255 | (b) You can convert one to an Int. |
|---|
| 256 | (c) You don't need to 'freeStableName' |
|---|
| 257 | |
|---|
| 258 | The existence of a stable name doesn't guarantee to keep the object it |
|---|
| 259 | points to alive (unlike a stable pointer), hence (a). |
|---|
| 260 | |
|---|
| 261 | Invariants: |
|---|
| 262 | |
|---|
| 263 | (a) makeStableName always returns the same value for a given |
|---|
| 264 | object (same as stable pointers). |
|---|
| 265 | |
|---|
| 266 | (b) if two stable names are equal, it implies that the objects |
|---|
| 267 | from which they were created were the same. |
|---|
| 268 | |
|---|
| 269 | (c) stableNameToInt always returns the same Int for a given |
|---|
| 270 | stable name. |
|---|
| 271 | |
|---|
| 272 | |
|---|
| 273 | -- HWL: The first 4 Int# in all par... annotations denote: |
|---|
| 274 | -- name, granularity info, size of result, degree of parallelism |
|---|
| 275 | -- Same structure as _seq_ i.e. returns Int# |
|---|
| 276 | -- KSW: v, the second arg in parAt# and parAtForNow#, is used only to determine |
|---|
| 277 | -- `the processor containing the expression v'; it is not evaluated |
|---|
| 278 | |
|---|
| 279 | These primops are pretty wierd. |
|---|
| 280 | |
|---|
| 281 | dataToTag# :: a -> Int (arg must be an evaluated data type) |
|---|
| 282 | tagToEnum# :: Int -> a (result type must be an enumerated type) |
|---|
| 283 | |
|---|
| 284 | The constraints aren't currently checked by the front end, but the |
|---|
| 285 | code generator will fall over if they aren't satisfied. |
|---|
| 286 | |
|---|
| 287 | %************************************************************************ |
|---|
| 288 | %* * |
|---|
| 289 | Which PrimOps are out-of-line |
|---|
| 290 | %* * |
|---|
| 291 | %************************************************************************ |
|---|
| 292 | |
|---|
| 293 | Some PrimOps need to be called out-of-line because they either need to |
|---|
| 294 | perform a heap check or they block. |
|---|
| 295 | |
|---|
| 296 | |
|---|
| 297 | \begin{code} |
|---|
| 298 | primOpOutOfLine :: PrimOp -> Bool |
|---|
| 299 | #include "primop-out-of-line.hs-incl" |
|---|
| 300 | \end{code} |
|---|
| 301 | |
|---|
| 302 | |
|---|
| 303 | %************************************************************************ |
|---|
| 304 | %* * |
|---|
| 305 | Failure and side effects |
|---|
| 306 | %* * |
|---|
| 307 | %************************************************************************ |
|---|
| 308 | |
|---|
| 309 | Note [PrimOp can_fail and has_side_effects] |
|---|
| 310 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 311 | Both can_fail and has_side_effects mean that the primop has |
|---|
| 312 | some effect that is not captured entirely by its result value. |
|---|
| 313 | |
|---|
| 314 | ---------- has_side_effects --------------------- |
|---|
| 315 | Has some imperative side effect, perhaps on the world (I/O), |
|---|
| 316 | or perhaps on some mutable data structure (writeIORef). |
|---|
| 317 | Generally speaking all such primops have a type like |
|---|
| 318 | State -> input -> (State, output) |
|---|
| 319 | so the state token guarantees ordering, and also ensures |
|---|
| 320 | that the primop is executed even if 'output' is discarded. |
|---|
| 321 | |
|---|
| 322 | ---------- can_fail ---------------------------- |
|---|
| 323 | Can fail with a seg-fault or divide-by-zero error on some elements |
|---|
| 324 | of its input domain. Main examples: |
|---|
| 325 | division (fails on zero demoninator |
|---|
| 326 | array indexing (fails if the index is out of bounds) |
|---|
| 327 | However (ASSUMPTION), these can_fail primops are ALWAYS surrounded |
|---|
| 328 | with a test that checks for the bad cases. |
|---|
| 329 | |
|---|
| 330 | Consequences: |
|---|
| 331 | |
|---|
| 332 | * You can discard a can_fail primop, or float it _inwards_. |
|---|
| 333 | But you cannot float it _outwards_, lest you escape the |
|---|
| 334 | dynamic scope of the test. Example: |
|---|
| 335 | case d ># 0# of |
|---|
| 336 | True -> case x /# d of r -> r +# 1 |
|---|
| 337 | False -> 0 |
|---|
| 338 | Here we must not float the case outwards to give |
|---|
| 339 | case x/# d of r -> |
|---|
| 340 | case d ># 0# of |
|---|
| 341 | True -> r +# 1 |
|---|
| 342 | False -> 0 |
|---|
| 343 | |
|---|
| 344 | * I believe that exactly the same rules apply to a has_side_effects |
|---|
| 345 | primop; you can discard it (remember, the state token will keep |
|---|
| 346 | it alive if necessary), or float it in, but not float it out. |
|---|
| 347 | |
|---|
| 348 | Example of the latter |
|---|
| 349 | if blah then let! s1 = writeMutVar s0 v True in s1 |
|---|
| 350 | else s0 |
|---|
| 351 | Notice that s0 is mentioned in both branches of the 'if', but |
|---|
| 352 | only one of these two will actually be consumed. But if we |
|---|
| 353 | float out to |
|---|
| 354 | let! s1 = writeMutVar s0 v True |
|---|
| 355 | in if blah then s1 else s0 |
|---|
| 356 | the writeMutVar will be performed in both branches, which is |
|---|
| 357 | utterly wrong. |
|---|
| 358 | |
|---|
| 359 | * You cannot duplicate a has_side_effect primop. You might wonder |
|---|
| 360 | how this can occur given the state token threading, but just look |
|---|
| 361 | at Control.Monad.ST.Lazy.Imp.strictToLazy! We get something like |
|---|
| 362 | this |
|---|
| 363 | p = case readMutVar# s v of |
|---|
| 364 | (# s', r #) -> (S# s', r) |
|---|
| 365 | s' = case p of (s', r) -> s' |
|---|
| 366 | r = case p of (s', r) -> r |
|---|
| 367 | |
|---|
| 368 | (All these bindings are boxed.) If we inline p at its two call |
|---|
| 369 | sites, we get a catastrophe: because the read is performed once when |
|---|
| 370 | s' is demanded, and once when 'r' is demanded, which may be much |
|---|
| 371 | later. Utterly wrong. Trac #3207 is real example of this happening. |
|---|
| 372 | |
|---|
| 373 | However, it's fine to duplicate a can_fail primop. That is |
|---|
| 374 | the difference between can_fail and has_side_effects. |
|---|
| 375 | |
|---|
| 376 | can_fail has_side_effects |
|---|
| 377 | Discard YES YES |
|---|
| 378 | Float in YES YES |
|---|
| 379 | Float out NO NO |
|---|
| 380 | Duplicate YES NO |
|---|
| 381 | |
|---|
| 382 | How do we achieve these effects? |
|---|
| 383 | |
|---|
| 384 | Note [primOpOkForSpeculation] |
|---|
| 385 | * The "no-float-out" thing is achieved by ensuring that we never |
|---|
| 386 | let-bind a can_fail or has_side_effects primop. The RHS of a |
|---|
| 387 | let-binding (which can float in and out freely) satisfies |
|---|
| 388 | exprOkForSpeculation. And exprOkForSpeculation is false of |
|---|
| 389 | can_fail and no_side_effect. |
|---|
| 390 | |
|---|
| 391 | * So can_fail and no_side_effect primops will appear only as the |
|---|
| 392 | scrutinees of cases, and that's why the FloatIn pass is capable |
|---|
| 393 | of floating case bindings inwards. |
|---|
| 394 | |
|---|
| 395 | * The no-duplicate thing is done via primOpIsCheap, by making |
|---|
| 396 | has_side_effects things (very very very) not-cheap! |
|---|
| 397 | |
|---|
| 398 | |
|---|
| 399 | \begin{code} |
|---|
| 400 | primOpHasSideEffects :: PrimOp -> Bool |
|---|
| 401 | #include "primop-has-side-effects.hs-incl" |
|---|
| 402 | |
|---|
| 403 | primOpCanFail :: PrimOp -> Bool |
|---|
| 404 | #include "primop-can-fail.hs-incl" |
|---|
| 405 | |
|---|
| 406 | primOpOkForSpeculation :: PrimOp -> Bool |
|---|
| 407 | -- See Note [primOpOkForSpeculation and primOpOkForFloatOut] |
|---|
| 408 | -- See comments with CoreUtils.exprOkForSpeculation |
|---|
| 409 | primOpOkForSpeculation op |
|---|
| 410 | = not (primOpHasSideEffects op || primOpOutOfLine op || primOpCanFail op) |
|---|
| 411 | |
|---|
| 412 | primOpOkForSideEffects :: PrimOp -> Bool |
|---|
| 413 | primOpOkForSideEffects op |
|---|
| 414 | = not (primOpHasSideEffects op) |
|---|
| 415 | \end{code} |
|---|
| 416 | |
|---|
| 417 | |
|---|
| 418 | Note [primOpIsCheap] |
|---|
| 419 | ~~~~~~~~~~~~~~~~~~~~ |
|---|
| 420 | @primOpIsCheap@, as used in \tr{SimplUtils.lhs}. For now (HACK |
|---|
| 421 | WARNING), we just borrow some other predicates for a |
|---|
| 422 | what-should-be-good-enough test. "Cheap" means willing to call it more |
|---|
| 423 | than once, and/or push it inside a lambda. The latter could change the |
|---|
| 424 | behaviour of 'seq' for primops that can fail, so we don't treat them as cheap. |
|---|
| 425 | |
|---|
| 426 | \begin{code} |
|---|
| 427 | primOpIsCheap :: PrimOp -> Bool |
|---|
| 428 | primOpIsCheap op = primOpOkForSpeculation op |
|---|
| 429 | -- In March 2001, we changed this to |
|---|
| 430 | -- primOpIsCheap op = False |
|---|
| 431 | -- thereby making *no* primops seem cheap. But this killed eta |
|---|
| 432 | -- expansion on case (x ==# y) of True -> \s -> ... |
|---|
| 433 | -- which is bad. In particular a loop like |
|---|
| 434 | -- doLoop n = loop 0 |
|---|
| 435 | -- where |
|---|
| 436 | -- loop i | i == n = return () |
|---|
| 437 | -- | otherwise = bar i >> loop (i+1) |
|---|
| 438 | -- allocated a closure every time round because it doesn't eta expand. |
|---|
| 439 | -- |
|---|
| 440 | -- The problem that originally gave rise to the change was |
|---|
| 441 | -- let x = a +# b *# c in x +# x |
|---|
| 442 | -- were we don't want to inline x. But primopIsCheap doesn't control |
|---|
| 443 | -- that (it's exprIsDupable that does) so the problem doesn't occur |
|---|
| 444 | -- even if primOpIsCheap sometimes says 'True'. |
|---|
| 445 | \end{code} |
|---|
| 446 | |
|---|
| 447 | |
|---|
| 448 | %************************************************************************ |
|---|
| 449 | %* * |
|---|
| 450 | PrimOp code size |
|---|
| 451 | %* * |
|---|
| 452 | %************************************************************************ |
|---|
| 453 | |
|---|
| 454 | primOpCodeSize |
|---|
| 455 | ~~~~~~~~~~~~~~ |
|---|
| 456 | Gives an indication of the code size of a primop, for the purposes of |
|---|
| 457 | calculating unfolding sizes; see CoreUnfold.sizeExpr. |
|---|
| 458 | |
|---|
| 459 | \begin{code} |
|---|
| 460 | primOpCodeSize :: PrimOp -> Int |
|---|
| 461 | #include "primop-code-size.hs-incl" |
|---|
| 462 | |
|---|
| 463 | primOpCodeSizeDefault :: Int |
|---|
| 464 | primOpCodeSizeDefault = 1 |
|---|
| 465 | -- CoreUnfold.primOpSize already takes into account primOpOutOfLine |
|---|
| 466 | -- and adds some further costs for the args in that case. |
|---|
| 467 | |
|---|
| 468 | primOpCodeSizeForeignCall :: Int |
|---|
| 469 | primOpCodeSizeForeignCall = 4 |
|---|
| 470 | \end{code} |
|---|
| 471 | |
|---|
| 472 | |
|---|
| 473 | %************************************************************************ |
|---|
| 474 | %* * |
|---|
| 475 | PrimOp types |
|---|
| 476 | %* * |
|---|
| 477 | %************************************************************************ |
|---|
| 478 | |
|---|
| 479 | \begin{code} |
|---|
| 480 | primOpType :: PrimOp -> Type -- you may want to use primOpSig instead |
|---|
| 481 | primOpType op |
|---|
| 482 | = case primOpInfo op of |
|---|
| 483 | Dyadic _occ ty -> dyadic_fun_ty ty |
|---|
| 484 | Monadic _occ ty -> monadic_fun_ty ty |
|---|
| 485 | Compare _occ ty -> compare_fun_ty ty |
|---|
| 486 | |
|---|
| 487 | GenPrimOp _occ tyvars arg_tys res_ty -> |
|---|
| 488 | mkForAllTys tyvars (mkFunTys arg_tys res_ty) |
|---|
| 489 | |
|---|
| 490 | primOpOcc :: PrimOp -> OccName |
|---|
| 491 | primOpOcc op = case primOpInfo op of |
|---|
| 492 | Dyadic occ _ -> occ |
|---|
| 493 | Monadic occ _ -> occ |
|---|
| 494 | Compare occ _ -> occ |
|---|
| 495 | GenPrimOp occ _ _ _ -> occ |
|---|
| 496 | |
|---|
| 497 | -- primOpSig is like primOpType but gives the result split apart: |
|---|
| 498 | -- (type variables, argument types, result type) |
|---|
| 499 | -- It also gives arity, strictness info |
|---|
| 500 | |
|---|
| 501 | primOpSig :: PrimOp -> ([TyVar], [Type], Type, Arity, StrictSig) |
|---|
| 502 | primOpSig op |
|---|
| 503 | = (tyvars, arg_tys, res_ty, arity, primOpStrictness op arity) |
|---|
| 504 | where |
|---|
| 505 | arity = length arg_tys |
|---|
| 506 | (tyvars, arg_tys, res_ty) |
|---|
| 507 | = case (primOpInfo op) of |
|---|
| 508 | Monadic _occ ty -> ([], [ty], ty ) |
|---|
| 509 | Dyadic _occ ty -> ([], [ty,ty], ty ) |
|---|
| 510 | Compare _occ ty -> ([], [ty,ty], boolTy) |
|---|
| 511 | GenPrimOp _occ tyvars arg_tys res_ty -> (tyvars, arg_tys, res_ty) |
|---|
| 512 | \end{code} |
|---|
| 513 | |
|---|
| 514 | \begin{code} |
|---|
| 515 | data PrimOpResultInfo |
|---|
| 516 | = ReturnsPrim PrimRep |
|---|
| 517 | | ReturnsAlg TyCon |
|---|
| 518 | |
|---|
| 519 | -- Some PrimOps need not return a manifest primitive or algebraic value |
|---|
| 520 | -- (i.e. they might return a polymorphic value). These PrimOps *must* |
|---|
| 521 | -- be out of line, or the code generator won't work. |
|---|
| 522 | |
|---|
| 523 | getPrimOpResultInfo :: PrimOp -> PrimOpResultInfo |
|---|
| 524 | getPrimOpResultInfo op |
|---|
| 525 | = case (primOpInfo op) of |
|---|
| 526 | Dyadic _ ty -> ReturnsPrim (typePrimRep ty) |
|---|
| 527 | Monadic _ ty -> ReturnsPrim (typePrimRep ty) |
|---|
| 528 | Compare _ _ -> ReturnsAlg boolTyCon |
|---|
| 529 | GenPrimOp _ _ _ ty | isPrimTyCon tc -> ReturnsPrim (tyConPrimRep tc) |
|---|
| 530 | | otherwise -> ReturnsAlg tc |
|---|
| 531 | where |
|---|
| 532 | tc = tyConAppTyCon ty |
|---|
| 533 | -- All primops return a tycon-app result |
|---|
| 534 | -- The tycon can be an unboxed tuple, though, which |
|---|
| 535 | -- gives rise to a ReturnAlg |
|---|
| 536 | \end{code} |
|---|
| 537 | |
|---|
| 538 | We do not currently make use of whether primops are commutable. |
|---|
| 539 | |
|---|
| 540 | We used to try to move constants to the right hand side for strength |
|---|
| 541 | reduction. |
|---|
| 542 | |
|---|
| 543 | \begin{code} |
|---|
| 544 | {- |
|---|
| 545 | commutableOp :: PrimOp -> Bool |
|---|
| 546 | #include "primop-commutable.hs-incl" |
|---|
| 547 | -} |
|---|
| 548 | \end{code} |
|---|
| 549 | |
|---|
| 550 | Utils: |
|---|
| 551 | \begin{code} |
|---|
| 552 | dyadic_fun_ty, monadic_fun_ty, compare_fun_ty :: Type -> Type |
|---|
| 553 | dyadic_fun_ty ty = mkFunTys [ty, ty] ty |
|---|
| 554 | monadic_fun_ty ty = mkFunTy ty ty |
|---|
| 555 | compare_fun_ty ty = mkFunTys [ty, ty] boolTy |
|---|
| 556 | \end{code} |
|---|
| 557 | |
|---|
| 558 | Output stuff: |
|---|
| 559 | \begin{code} |
|---|
| 560 | pprPrimOp :: PrimOp -> SDoc |
|---|
| 561 | pprPrimOp other_op = pprOccName (primOpOcc other_op) |
|---|
| 562 | \end{code} |
|---|
| 563 | |
|---|
| 564 | |
|---|
| 565 | %************************************************************************ |
|---|
| 566 | %* * |
|---|
| 567 | \subsubsection[PrimCall]{User-imported primitive calls} |
|---|
| 568 | %* * |
|---|
| 569 | %************************************************************************ |
|---|
| 570 | |
|---|
| 571 | \begin{code} |
|---|
| 572 | data PrimCall = PrimCall CLabelString PackageId |
|---|
| 573 | |
|---|
| 574 | instance Outputable PrimCall where |
|---|
| 575 | ppr (PrimCall lbl pkgId) |
|---|
| 576 | = text "__primcall" <+> ppr pkgId <+> ppr lbl |
|---|
| 577 | |
|---|
| 578 | \end{code} |
|---|