PrimOps.hs 27.3 KB
 Austin Seipp committed Dec 03, 2014 1 2 3 {- (c) The GRASP/AQUA Project, Glasgow University, 1992-1998  simonpj committed Jun 08, 1999 4 \section[PrimOp]{Primitive operations (machine-level)}  Austin Seipp committed Dec 03, 2014 5 -}  simonpj committed Jun 08, 1999 6   Herbert Valerio Riedel committed May 15, 2014 7 8 {-# LANGUAGE CPP #-}  Sylvain Henry committed Apr 18, 2020 9 module GHC.Builtin.PrimOps (  gmainlan@microsoft.com committed Sep 22, 2013 10  PrimOp(..), PrimOpVecCat(..), allThePrimOps,  Sylvain Henry committed Jul 07, 2020 11  primOpType, primOpSig, primOpResultType,  Ian Lynagh committed Sep 30, 2011 12  primOpTag, maxPrimOpTag, primOpOcc,  Ben Gamari committed Jun 25, 2019 13  primOpWrapperId,  simonpj committed Jun 08, 1999 14   Ian Lynagh committed Sep 30, 2011 15  tagToEnumKey,  simonpj@microsoft.com committed Aug 16, 2006 16   Simon Marlow committed May 24, 2011 17  primOpOutOfLine, primOpCodeSize,  Simon Peyton Jones committed Jan 12, 2012 18  primOpOkForSpeculation, primOpOkForSideEffects,  mniip committed Apr 23, 2020 19  primOpIsCheap, primOpFixity, primOpDocs,  simonpj committed Jun 08, 1999 20   Simon Peyton Jones committed Apr 28, 2017 21  getPrimOpResultInfo, isComparisonPrimOp, PrimOpResultInfo(..),  Duncan Coutts committed Jun 09, 2009 22 23  PrimCall(..)  simonpj committed Jun 08, 1999 24 25 26 27  ) where #include "HsVersions.h"  Sylvain Henry committed Apr 26, 2020 28 import GHC.Prelude  Herbert Valerio Riedel committed Sep 19, 2017 29   Sylvain Henry committed Apr 18, 2020 30 31 import GHC.Builtin.Types.Prim import GHC.Builtin.Types  simonpj committed Jun 08, 1999 32   Sylvain Henry committed Jan 25, 2020 33 import GHC.Cmm.Type  Sylvain Henry committed Mar 29, 2020 34 35 36 37 import GHC.Types.Demand import GHC.Types.Id ( Id, mkVanillaGlobalWithInfo ) import GHC.Types.Id.Info ( vanillaIdInfo, setCafInfo, CafInfo(NoCafRefs) ) import GHC.Types.Name  Sylvain Henry committed Apr 18, 2020 38 import GHC.Builtin.Names ( gHC_PRIMOPWRAPPERS )  Sylvain Henry committed Mar 16, 2020 39 40 import GHC.Core.TyCon ( TyCon, isPrimTyCon, PrimRep(..) ) import GHC.Core.Type  Krzysztof Gogolewski committed Aug 26, 2020 41 import GHC.Types.RepType ( tyConPrimRep1 )  Sylvain Henry committed Mar 29, 2020 42 43 44 45 import GHC.Types.Basic ( Arity, Fixity(..), FixityDirection(..), Boxity(..), SourceText(..) ) import GHC.Types.SrcLoc ( wiredInSrcSpan ) import GHC.Types.ForeignCall ( CLabelString )  Aditya Gupta committed Aug 22, 2020 46 47 import GHC.Types.Unique ( Unique) import GHC.Builtin.Uniques (mkPrimOpIdUnique, mkPrimOpWrapperUnique )  Sylvain Henry committed Oct 01, 2020 48 import GHC.Unit.Types ( Unit )  Sylvain Henry committed Apr 26, 2020 49 50 import GHC.Utils.Outputable import GHC.Data.FastString  simonpj committed Jun 08, 1999 51   Austin Seipp committed Dec 03, 2014 52 53 54 {- ************************************************************************ * *  simonpj committed Jun 08, 1999 55 \subsection[PrimOp-datatype]{Datatype for @PrimOp@ (an enumeration)}  Austin Seipp committed Dec 03, 2014 56 57 * * ************************************************************************  simonpj committed Jun 08, 1999 58 59  These are in \tr{state-interface.verb} order.  Austin Seipp committed Dec 03, 2014 60 -}  sewardj committed Aug 07, 2000 61   Ian Lynagh committed Sep 30, 2011 62 -- supplies:  sewardj committed Aug 07, 2000 63 -- data PrimOp = ...  sewardj committed Aug 08, 2000 64 #include "primop-data-decl.hs-incl"  simonpj committed Jun 08, 1999 65   Ian Lynagh committed Sep 30, 2011 66 -- supplies  thomie committed Aug 21, 2015 67 -- primOpTag :: PrimOp -> Int  sewardj committed Aug 08, 2000 68 #include "primop-tag.hs-incl"  thomie committed Aug 21, 2015 69 primOpTag _ = error "primOpTag: unknown primop"  simonpj committed Jun 08, 1999 70   sewardj committed Aug 07, 2000 71   simonpj committed Jun 08, 1999 72 instance Eq PrimOp where  thomie committed Aug 21, 2015 73  op1 == op2 = primOpTag op1 == primOpTag op2  simonpj committed Jun 08, 1999 74 75  instance Ord PrimOp where  thomie committed Aug 21, 2015 76 77 78 79  op1 < op2 = primOpTag op1 < primOpTag op2 op1 <= op2 = primOpTag op1 <= primOpTag op2 op1 >= op2 = primOpTag op1 >= primOpTag op2 op1 > op2 = primOpTag op1 > primOpTag op2  simonpj committed Jun 08, 1999 80  op1 compare op2 | op1 < op2 = LT  Ian Lynagh committed Sep 30, 2011 81 82  | op1 == op2 = EQ | otherwise = GT  simonpj committed Jun 08, 1999 83 84 85 86  instance Outputable PrimOp where ppr op = pprPrimOp op  gmainlan@microsoft.com committed Sep 22, 2013 87 88 89 90 data PrimOpVecCat = IntVec | WordVec | FloatVec  Austin Seipp committed Dec 03, 2014 91 -- An @Enum@-derived list would be better; meanwhile... (ToDo)  simonpj committed Oct 09, 2003 92   sewardj committed Aug 07, 2000 93 94 allThePrimOps :: [PrimOp] allThePrimOps =  sewardj committed Aug 08, 2000 95 #include "primop-list.hs-incl"  simonpj committed Jun 08, 1999 96   simonpj@microsoft.com committed Aug 16, 2006 97 98 99 tagToEnumKey :: Unique tagToEnumKey = mkPrimOpIdUnique (primOpTag TagToEnumOp)  Austin Seipp committed Dec 03, 2014 100 101 102 {- ************************************************************************ * *  simonpj committed Jun 08, 1999 103 \subsection[PrimOp-info]{The essential info about each @PrimOp@}  Austin Seipp committed Dec 03, 2014 104 105 106 107 * * ************************************************************************ -}  simonpj committed Jun 08, 1999 108 data PrimOpInfo  Krzysztof Gogolewski committed Aug 26, 2020 109  = Compare OccName -- string :: T -> T -> Int#  Ian Lynagh committed Sep 30, 2011 110 111 112 113 114  Type | GenPrimOp OccName -- string :: \/a1..an . T1 -> .. -> Tk -> T [TyVar] [Type] Type  simonpj committed Jun 08, 1999 115   Krzysztof Gogolewski committed Aug 26, 2020 116 mkCompare :: FastString -> Type -> PrimOpInfo  simonmar committed Jan 06, 2006 117 mkCompare str ty = Compare (mkVarOccFS str) ty  Ian Lynagh committed Mar 29, 2008 118 119  mkGenPrimOp :: FastString -> [TyVar] -> [Type] -> Type -> PrimOpInfo  simonmar committed Jan 06, 2006 120 mkGenPrimOp str tvs tys ty = GenPrimOp (mkVarOccFS str) tvs tys ty  simonpj committed Jun 08, 1999 121   Austin Seipp committed Dec 03, 2014 122 123 124 {- ************************************************************************ * *  simonpj committed Jun 08, 1999 125 \subsubsection{Strictness}  Austin Seipp committed Dec 03, 2014 126 127 * * ************************************************************************  simonpj committed Jun 08, 1999 128 129  Not all primops are strict!  Austin Seipp committed Dec 03, 2014 130 -}  simonpj committed Jun 08, 1999 131   simonmar committed Dec 10, 2001 132 primOpStrictness :: PrimOp -> Arity -> StrictSig  Ian Lynagh committed Sep 30, 2011 133 134 135  -- See Demand.StrictnessInfo for discussion of what the results -- The arity should be the arity of the primop; that's why -- this function isn't exported.  sewardj committed Aug 08, 2000 136 #include "primop-strictness.hs-incl"  simonpj committed Jun 08, 1999 137   Austin Seipp committed Dec 03, 2014 138 139 140 {- ************************************************************************ * *  Michal Terepeta committed Nov 23, 2012 141 \subsubsection{Fixity}  Austin Seipp committed Dec 03, 2014 142 143 144 * * ************************************************************************ -}  Michal Terepeta committed Nov 23, 2012 145 146 147 148  primOpFixity :: PrimOp -> Maybe Fixity #include "primop-fixity.hs-incl"  mniip committed Apr 23, 2020 149 150 151 152 153 154 {- ************************************************************************ * * \subsubsection{Docs} * * ************************************************************************  mniip committed Apr 23, 2020 155   mniip committed Apr 23, 2020 156 See Note [GHC.Prim Docs]  mniip committed Apr 23, 2020 157 158 -}  mniip committed Apr 23, 2020 159 primOpDocs :: [(String, String)]  mniip committed Apr 23, 2020 160 161 #include "primop-docs.hs-incl"  Austin Seipp committed Dec 03, 2014 162 163 164 {- ************************************************************************ * *  simonpj committed Jun 08, 1999 165 \subsubsection[PrimOp-comparison]{PrimOpInfo basic comparison ops}  Austin Seipp committed Dec 03, 2014 166 167 * * ************************************************************************  simonpj committed Jun 08, 1999 168 169 170  @primOpInfo@ gives all essential information (from which everything else, notably a type, can be constructed) for each @PrimOp@.  Austin Seipp committed Dec 03, 2014 171 -}  simonpj committed Jun 08, 1999 172 173  primOpInfo :: PrimOp -> PrimOpInfo  sewardj committed Aug 08, 2000 174 #include "primop-primop-info.hs-incl"  gmainlan@microsoft.com committed Sep 22, 2013 175 primOpInfo _ = error "primOpInfo: unknown primop"  simonpj committed Jun 08, 1999 176   Austin Seipp committed Dec 03, 2014 177 {-  sewardj committed Aug 07, 2000 178 Here are a load of comments from the old primOp info:  simonpj committed Jun 08, 1999 179 180 181 182 183 184 185 186  A @Word#@ is an unsigned @Int#@. @decodeFloat#@ is given w/ Integer-stuff (it's similar). @decodeDouble#@ is given w/ Integer-stuff (it's similar). Decoding of floating-point numbers is sorta Integer-related. Encoding  rodlogic committed Feb 09, 2015 187 is done with plain ccalls now (see PrelNumExtra.hs).  simonpj committed Jun 08, 1999 188 189 190  A @Weak@ Pointer is created by the @mkWeak#@ primitive:  Ian Lynagh committed Sep 30, 2011 191 192  mkWeak# :: k -> v -> f -> State# RealWorld -> (# State# RealWorld, Weak# v #)  simonpj committed Jun 08, 1999 193 194 195  In practice, you'll use the higher-level  Ian Lynagh committed Sep 30, 2011 196 197  data Weak v = Weak# v mkWeak :: k -> v -> IO () -> IO (Weak v)  simonpj committed Jun 08, 1999 198 199 200 201 202  The following operation dereferences a weak pointer. The weak pointer may have been finalized, so the operation returns a result code which must be inspected before looking at the dereferenced value.  Ian Lynagh committed Sep 30, 2011 203 204  deRefWeak# :: Weak# v -> State# RealWorld -> (# State# RealWorld, v, Int# #)  simonpj committed Jun 08, 1999 205 206 207 208 209  Only look at v if the Int# returned is /= 0 !! The higher-level op is  Ian Lynagh committed Sep 30, 2011 210  deRefWeak :: Weak v -> IO (Maybe v)  simonpj committed Jun 08, 1999 211 212  Weak pointers can be finalized early by using the finalize# operation:  Ian Lynagh committed Sep 30, 2011 213 214 215  finalizeWeak# :: Weak# v -> State# RealWorld -> (# State# RealWorld, Int#, IO () #)  simonpj committed Jun 08, 1999 216 217 218  The Int# returned is either  Ian Lynagh committed Sep 30, 2011 219 220  0 if the weak pointer has already been finalized, or it has no finalizer (the third component is then invalid).  simonpj committed Jun 08, 1999 221   Ian Lynagh committed Sep 30, 2011 222 223  1 if the weak pointer is still alive, with the finalizer returned as the third component.  simonpj committed Jun 08, 1999 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260  A {\em stable name/pointer} is an index into a table of stable name entries. Since the garbage collector is told about stable pointers, it is safe to pass a stable pointer to external systems such as C routines. \begin{verbatim} makeStablePtr# :: a -> State# RealWorld -> (# State# RealWorld, StablePtr# a #) freeStablePtr :: StablePtr# a -> State# RealWorld -> State# RealWorld deRefStablePtr# :: StablePtr# a -> State# RealWorld -> (# State# RealWorld, a #) eqStablePtr# :: StablePtr# a -> StablePtr# a -> Int# \end{verbatim} It may seem a bit surprising that @makeStablePtr#@ is a @IO@ operation since it doesn't (directly) involve IO operations. The reason is that if some optimisation pass decided to duplicate calls to @makeStablePtr#@ and we only pass one of the stable pointers over, a massive space leak can result. Putting it into the IO monad prevents this. (Another reason for putting them in a monad is to ensure correct sequencing wrt the side-effecting @freeStablePtr@ operation.) An important property of stable pointers is that if you call makeStablePtr# twice on the same object you get the same stable pointer back. Note that we can implement @freeStablePtr#@ using @_ccall_@ (and, besides, it's not likely to be used from Haskell) so it's not a primop. Question: Why @RealWorld@ - won't any instance of @_ST@ do the job? [ADR] Stable Names ~~~~~~~~~~~~ A stable name is like a stable pointer, but with three important differences:  Ian Lynagh committed Sep 30, 2011 261 262 263  (a) You can't deRef one to get back to the original object. (b) You can convert one to an Int. (c) You don't need to 'freeStableName'  simonpj committed Jun 08, 1999 264 265 266 267 268 269  The existence of a stable name doesn't guarantee to keep the object it points to alive (unlike a stable pointer), hence (a). Invariants:  Ian Lynagh committed Sep 30, 2011 270 271 272 273 274  (a) makeStableName always returns the same value for a given object (same as stable pointers). (b) if two stable names are equal, it implies that the objects from which they were created were the same.  simonpj committed Jun 08, 1999 275   Ian Lynagh committed Sep 30, 2011 276 277  (c) stableNameToInt always returns the same Int for a given stable name.  simonpj committed Jun 08, 1999 278 279   Krzysztof Gogolewski committed Oct 12, 2013 280 These primops are pretty weird.  simonpj committed Jun 08, 1999 281   Ian Lynagh committed Sep 30, 2011 282  tagToEnum# :: Int -> a (result type must be an enumerated type)  simonpj committed Jun 08, 1999 283 284 285 286  The constraints aren't currently checked by the front end, but the code generator will fall over if they aren't satisfied.  Austin Seipp committed Dec 03, 2014 287 288 ************************************************************************ * *  Simon Peyton Jones committed Dec 12, 2011 289  Which PrimOps are out-of-line  Austin Seipp committed Dec 03, 2014 290 291 * * ************************************************************************  simonpj committed Jun 08, 1999 292 293 294  Some PrimOps need to be called out-of-line because they either need to perform a heap check or they block.  Austin Seipp committed Dec 03, 2014 295 -}  simonpj committed Jun 08, 1999 296   apt committed Aug 17, 2001 297 primOpOutOfLine :: PrimOp -> Bool  sewardj committed Aug 08, 2000 298 #include "primop-out-of-line.hs-incl"  simonpj committed Aug 24, 1999 299   Austin Seipp committed Dec 03, 2014 300 301 302 {- ************************************************************************ * *  Simon Peyton Jones committed Dec 12, 2011 303  Failure and side effects  Austin Seipp committed Dec 03, 2014 304 305 * * ************************************************************************  Simon Peyton Jones committed Dec 12, 2011 306   Ben Gamari committed Jun 14, 2019 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 Note [Checking versus non-checking primops] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In GHC primops break down into two classes: a. Checking primops behave, for instance, like division. In this case the primop may throw an exception (e.g. division-by-zero) and is consequently is marked with the can_fail flag described below. The ability to fail comes at the expense of precluding some optimizations. b. Non-checking primops behavior, for instance, like addition. While addition can overflow it does not produce an exception. So can_fail is set to False, and we get more optimisation opportunities. But we must never throw an exception, so we cannot rewrite to a call to error. It is important that a non-checking primop never be transformed in a way that would cause it to bottom. Doing so would violate Core's let/app invariant  Sylvain Henry committed Feb 26, 2020 324  (see Note [Core let/app invariant] in GHC.Core) which is critical to  Ben Gamari committed Jun 14, 2019 325 326 327  the simplifier's ability to float without fear of changing program meaning.  Simon Peyton Jones committed Dec 12, 2011 328 329 Note [PrimOp can_fail and has_side_effects] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  Simon Peyton Jones committed Jan 12, 2012 330 331 332 Both can_fail and has_side_effects mean that the primop has some effect that is not captured entirely by its result value.  Simon Peyton Jones committed Aug 07, 2014 333 334 335 336 337 338 339 340 341 342 343 344 345 346 ---------- has_side_effects --------------------- A primop "has_side_effects" if it has some *write* effect, visible elsewhere - writing to the world (I/O) - writing to a mutable data structure (writeIORef) - throwing a synchronous Haskell exception Often such primops have a type like State -> input -> (State, output) so the state token guarantees ordering. In general we rely *only* on data dependencies of the state token to enforce write-effect ordering * NB1: if you inline unsafePerformIO, you may end up with side-effecting ops whose 'state' output is discarded.  Ryan Scott committed Mar 15, 2019 347  And programmers may do that by hand; see #9390.  Simon Peyton Jones committed Aug 07, 2014 348 349 350 351 352 353 354 355 356 357  That is why we (conservatively) do not discard write-effecting primops even if both their state and result is discarded. * NB2: We consider primops, such as raiseIO#, that can raise a (Haskell) synchronous exception to "have_side_effects" but not "can_fail". We must be careful about not discarding such things; see the paper "A semantics for imprecise exceptions". * NB3: *Read* effects (like reading an IORef) don't count here, because it doesn't matter if we don't do them, or do them more than  Gabor Greif committed Aug 07, 2014 358  once. *Sequencing* is maintained by the data dependency of the state  Simon Peyton Jones committed Aug 07, 2014 359 360 361  token. ---------- can_fail ----------------------------  Gabor Greif committed Aug 07, 2014 362 A primop "can_fail" if it can fail with an *unchecked* exception on  Simon Peyton Jones committed Aug 07, 2014 363 some elements of its input domain. Main examples:  Brian Wignall committed Jan 12, 2020 364  division (fails on zero denominator)  Simon Peyton Jones committed Aug 07, 2014 365 366  array indexing (fails if the index is out of bounds)  Gabor Greif committed Aug 07, 2014 367 368 An "unchecked exception" is one that is an outright error, (not turned into a Haskell exception,) such as seg-fault or  Simon Peyton Jones committed Aug 07, 2014 369 370 divide-by-zero error. Such can_fail primops are ALWAYS surrounded with a test that checks for the bad cases, but we need to be  Gabor Greif committed Aug 07, 2014 371 very careful about code motion that might move it out of  Simon Peyton Jones committed Aug 07, 2014 372 373 374 375 376 377 378 379 the scope of the test. Note [Transformations affected by can_fail and has_side_effects] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The can_fail and has_side_effects properties have the following effect on program transformations. Summary table is followed by details. can_fail has_side_effects  Vladislav Zavialov committed Feb 01, 2017 380 Discard YES NO  Simon Peyton Jones committed Aug 07, 2014 381 382 383 384 385 386 387 388 389 390 Float in YES YES Float out NO NO Duplicate YES NO * Discarding. case (a op b) of _ -> rhs ===> rhs You should not discard a has_side_effects primop; e.g. case (writeIntArray# a i v s of (# _, _ #) -> True Arguably you should be able to discard this, since the returned stat token is not used, but that relies on NEVER inlining unsafePerformIO, and programmers sometimes write  Ryan Scott committed Mar 15, 2019 391  this kind of stuff by hand (#9390). So we (conservatively)  Simon Peyton Jones committed Aug 07, 2014 392 393 394 395 396  never discard a has_side_effects primop. However, it's fine to discard a can_fail primop. For example case (indexIntArray# a i) of _ -> True We can discard indexIntArray#; it has can_fail, but not  Ryan Scott committed Mar 15, 2019 397  has_side_effects; see #5658 which was all about this.  Simon Peyton Jones committed Aug 07, 2014 398 399 400 401 402 403 404 405 406 407  Notice that indexIntArray# is (in a more general handling of effects) read effect, but we don't care about that here, and treat read effects as *not* has_side_effects. Similarly (a /# b) can be discarded. It can seg-fault or cause a hardware exception, but not a synchronous Haskell exception.  Gabor Greif committed Aug 07, 2014 408  Synchronous Haskell exceptions, e.g. from raiseIO#, are treated  Simon Peyton Jones committed Aug 07, 2014 409 410 411 412 413 414 415  as has_side_effects and hence are not discarded. * Float in. You can float a can_fail or has_side_effects primop *inwards*, but not inside a lambda (see Duplication below). * Float out. You must not float a can_fail primop *outwards* lest you escape the dynamic scope of the test. Example:  Simon Peyton Jones committed Jan 12, 2012 416 417 418 419 420 421 422 423 424  case d ># 0# of True -> case x /# d of r -> r +# 1 False -> 0 Here we must not float the case outwards to give case x/# d of r -> case d ># 0# of True -> r +# 1 False -> 0  Simon Peyton Jones committed Aug 07, 2014 425 426  Nor can you float out a has_side_effects primop. For example: if blah then case writeMutVar# v True s0 of (# s1 #) -> s1  Simon Peyton Jones committed Jan 12, 2012 427  else s0  Simon Peyton Jones committed Aug 07, 2014 428  Notice that s0 is mentioned in both branches of the 'if', but  Simon Peyton Jones committed Jan 12, 2012 429 430  only one of these two will actually be consumed. But if we float out to  Simon Peyton Jones committed Aug 07, 2014 431 432  case writeMutVar# v True s0 of (# s1 #) -> if blah then s1 else s0  Simon Peyton Jones committed Jan 12, 2012 433 434 435  the writeMutVar will be performed in both branches, which is utterly wrong.  Simon Peyton Jones committed Aug 07, 2014 436 437 438 439 * Duplication. You cannot duplicate a has_side_effect primop. You might wonder how this can occur given the state token threading, but just look at Control.Monad.ST.Lazy.Imp.strictToLazy! We get something like this  Simon Peyton Jones committed Jan 12, 2012 440  p = case readMutVar# s v of  Sylvain Henry committed Jun 17, 2020 441  (# s', r #) -> (State# s', r)  Simon Peyton Jones committed Jan 12, 2012 442 443 444 445 446  s' = case p of (s', r) -> s' r = case p of (s', r) -> r (All these bindings are boxed.) If we inline p at its two call sites, we get a catastrophe: because the read is performed once when  Simon Peyton Jones committed Aug 07, 2014 447  s' is demanded, and once when 'r' is demanded, which may be much  Ryan Scott committed Mar 15, 2019 448  later. Utterly wrong. #3207 is real example of this happening.  Simon Peyton Jones committed Jan 12, 2012 449   Simon Peyton Jones committed Aug 07, 2014 450 451  However, it's fine to duplicate a can_fail primop. That is really the only difference between can_fail and has_side_effects.  Simon Peyton Jones committed Jan 12, 2012 452   Gabor Greif committed Aug 07, 2014 453 Note [Implementation: how can_fail/has_side_effects affect transformations]  Simon Peyton Jones committed Aug 07, 2014 454 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  Jan Hrček committed Jun 28, 2020 455 How do we ensure that floating/duplication/discarding are done right  Simon Peyton Jones committed Aug 07, 2014 456 in the simplifier?  Simon Peyton Jones committed Jan 12, 2012 457   Simon Peyton Jones committed Aug 07, 2014 458 459 460 Two main predicates on primpops test these flags: primOpOkForSideEffects <=> not has_side_effects primOpOkForSpeculation <=> not (has_side_effects || can_fail)  Simon Peyton Jones committed Dec 12, 2011 461   Simon Peyton Jones committed Jan 12, 2012 462 463 464  * The "no-float-out" thing is achieved by ensuring that we never let-bind a can_fail or has_side_effects primop. The RHS of a let-binding (which can float in and out freely) satisfies  Simon Peyton Jones committed Aug 07, 2014 465 466  exprOkForSpeculation; this is the let/app invariant. And exprOkForSpeculation is false of can_fail and has_side_effects.  Simon Peyton Jones committed Dec 12, 2011 467   Simon Peyton Jones committed Aug 07, 2014 468  * So can_fail and has_side_effects primops will appear only as the  Simon Peyton Jones committed Jan 12, 2012 469 470  scrutinees of cases, and that's why the FloatIn pass is capable of floating case bindings inwards.  Simon Peyton Jones committed Dec 12, 2011 471   Simon Peyton Jones committed Jan 12, 2012 472 473  * The no-duplicate thing is done via primOpIsCheap, by making has_side_effects things (very very very) not-cheap!  Austin Seipp committed Dec 03, 2014 474 -}  Simon Peyton Jones committed Dec 12, 2011 475 476 477 478 479 480 481  primOpHasSideEffects :: PrimOp -> Bool #include "primop-has-side-effects.hs-incl" primOpCanFail :: PrimOp -> Bool #include "primop-can-fail.hs-incl"  simonpj committed Jun 08, 1999 482 primOpOkForSpeculation :: PrimOp -> Bool  Simon Peyton Jones committed Aug 07, 2014 483  -- See Note [PrimOp can_fail and has_side_effects]  Sylvain Henry committed Feb 26, 2020 484  -- See comments with GHC.Core.Utils.exprOkForSpeculation  Simon Peyton Jones committed Aug 07, 2014 485  -- primOpOkForSpeculation => primOpOkForSideEffects  Ian Lynagh committed Sep 30, 2011 486 primOpOkForSpeculation op  Simon Peyton Jones committed Aug 07, 2014 487 488 489  = primOpOkForSideEffects op && not (primOpOutOfLine op || primOpCanFail op) -- I think the "out of line" test is because out of line things can  Gabor Greif committed Aug 07, 2014 490  -- be expensive (eg sine, cosine), and so we may not want to speculate them  Simon Peyton Jones committed Jan 12, 2012 491 492 493 494  primOpOkForSideEffects :: PrimOp -> Bool primOpOkForSideEffects op = not (primOpHasSideEffects op)  Simon Peyton Jones committed Jan 13, 2012 495   Austin Seipp committed Dec 03, 2014 496 {-  Simon Marlow committed Jan 16, 2012 497 498 Note [primOpIsCheap] ~~~~~~~~~~~~~~~~~~~~  Sylvain Henry committed Mar 18, 2020 499   Sylvain Henry committed Apr 18, 2020 500 @primOpIsCheap@, as used in GHC.Core.Opt.Simplify.Utils. For now (HACK  Simon Marlow committed Jan 16, 2012 501 502 503 504 WARNING), we just borrow some other predicates for a what-should-be-good-enough test. "Cheap" means willing to call it more than once, and/or push it inside a lambda. The latter could change the behaviour of 'seq' for primops that can fail, so we don't treat them as cheap.  Austin Seipp committed Dec 03, 2014 505 -}  Simon Marlow committed Jan 16, 2012 506 507  primOpIsCheap :: PrimOp -> Bool  Simon Peyton Jones committed Aug 07, 2014 508 -- See Note [PrimOp can_fail and has_side_effects]  Simon Marlow committed Jan 16, 2012 509 primOpIsCheap op = primOpOkForSpeculation op  Ian Lynagh committed Sep 30, 2011 510 511 -- In March 2001, we changed this to -- primOpIsCheap op = False  simonpj committed Apr 27, 2004 512 -- thereby making *no* primops seem cheap. But this killed eta  Ian Lynagh committed Sep 30, 2011 513 -- expansion on case (x ==# y) of True -> \s -> ...  simonpj committed Apr 27, 2004 514 -- which is bad. In particular a loop like  Ian Lynagh committed Sep 30, 2011 515 -- doLoop n = loop 0  simonpj committed Apr 27, 2004 516 517 518 519 -- where -- loop i | i == n = return () -- | otherwise = bar i >> loop (i+1) -- allocated a closure every time round because it doesn't eta expand.  Ian Lynagh committed Sep 30, 2011 520 --  simonpj committed Apr 27, 2004 521 -- The problem that originally gave rise to the change was  Ian Lynagh committed Sep 30, 2011 522 -- let x = a +# b *# c in x +# x  simonpj committed Apr 27, 2004 523 524 525 -- were we don't want to inline x. But primopIsCheap doesn't control -- that (it's exprIsDupable that does) so the problem doesn't occur -- even if primOpIsCheap sometimes says 'True'.  Simon Peyton Jones committed Dec 12, 2011 526   Austin Seipp committed Dec 03, 2014 527 528 529 {- ************************************************************************ * *  Simon Peyton Jones committed Dec 12, 2011 530  PrimOp code size  Austin Seipp committed Dec 03, 2014 531 532 * * ************************************************************************  Simon Peyton Jones committed Dec 12, 2011 533   Simon Marlow committed May 24, 2011 534 535 536 primOpCodeSize ~~~~~~~~~~~~~~ Gives an indication of the code size of a primop, for the purposes of  Sylvain Henry committed Feb 26, 2020 537 calculating unfolding sizes; see GHC.Core.Unfold.sizeExpr.  Austin Seipp committed Dec 03, 2014 538 -}  simonpj committed Jun 08, 1999 539   Simon Marlow committed May 24, 2011 540 541 542 543 544 primOpCodeSize :: PrimOp -> Int #include "primop-code-size.hs-incl" primOpCodeSizeDefault :: Int primOpCodeSizeDefault = 1  Sylvain Henry committed Feb 26, 2020 545  -- GHC.Core.Unfold.primOpSize already takes into account primOpOutOfLine  Simon Marlow committed May 24, 2011 546  -- and adds some further costs for the args in that case.  simonpj committed Jun 08, 1999 547   Simon Marlow committed May 24, 2011 548 549 primOpCodeSizeForeignCall :: Int primOpCodeSizeForeignCall = 4  Simon Marlow committed May 15, 2009 550   Austin Seipp committed Dec 03, 2014 551 552 553 {- ************************************************************************ * *  Simon Peyton Jones committed Dec 12, 2011 554  PrimOp types  Austin Seipp committed Dec 03, 2014 555 556 557 * * ************************************************************************ -}  simonpj committed Jun 08, 1999 558 559 560  primOpType :: PrimOp -> Type -- you may want to use primOpSig instead primOpType op  Ian Lynagh committed Mar 29, 2008 561 562  = case primOpInfo op of Compare _occ ty -> compare_fun_ty ty  simonpj committed Jun 08, 1999 563   Ian Lynagh committed Sep 30, 2011 564  GenPrimOp _occ tyvars arg_tys res_ty ->  Krzysztof Gogolewski committed Jun 17, 2020 565  mkSpecForAllTys tyvars (mkVisFunTysMany arg_tys res_ty)  simonpj committed Jun 08, 1999 566   Sylvain Henry committed Jul 07, 2020 567 568 569 570 571 572 primOpResultType :: PrimOp -> Type primOpResultType op = case primOpInfo op of Compare _occ _ty -> intPrimTy GenPrimOp _occ _tyvars _arg_tys res_ty -> res_ty  simonpj committed Jun 08, 1999 573 primOpOcc :: PrimOp -> OccName  Ian Lynagh committed Mar 29, 2008 574 575 576 primOpOcc op = case primOpInfo op of Compare occ _ -> occ GenPrimOp occ _ _ _ -> occ  simonpj committed Jun 08, 1999 577   Ben Gamari committed Jun 25, 2019 578 579 {- Note [Primop wrappers] ~~~~~~~~~~~~~~~~~~~~~~~~~  Ben Gamari committed May 29, 2020 580 581 582 583 584 585  To support (limited) use of primops in GHCi genprimopcode generates the GHC.PrimopWrappers module. This module contains a "primop wrapper" binding for each primop. These are standard Haskell functions mirroring the types of the primops they wrap. For instance, in the case of plusInt# we would have:  Ben Gamari committed Jun 25, 2019 586 587 588  module GHC.PrimopWrappers where import GHC.Prim as P  Ben Gamari committed May 29, 2020 589 590  plusInt# :: Int# -> Int# -> Int#  Ben Gamari committed Jun 25, 2019 591 592  plusInt# a b = P.plusInt# a b  Ben Gamari committed May 29, 2020 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 The Id for the wrapper of a primop can be found using 'GHC.Builtin.PrimOp.primOpWrapperId'. However, GHCi does not use this mechanism to link primops; it rather does a rather hacky symbol lookup (see GHC.ByteCode.Linker.primopToCLabel). TODO: Perhaps this should be changed? Note that these wrappers aren't *quite* as expressive as their unwrapped breathern in that they may exhibit less levity polymorphism. For instance, consider the case of mkWeakNoFinalizer# which has type: mkWeakNoFinalizer# :: forall (r :: RuntimeRep) (k :: TYPE r) (v :: Type). k -> v -> State# RealWorld -> (# State# RealWorld, Weak# v #) Naively we could generate a wrapper of the form, mkWeakNoFinalizer# k v s = GHC.Prim.mkWeakNoFinalizer# k v s However, this would require that 'k' bind the levity-polymorphic key, which is disallowed by our levity polymorphism validity checks (see Note [Levity polymorphism invariants] in GHC.Core). Consequently, we give the wrapper the simpler, less polymorphic type mkWeakNoFinalizer# :: forall (k :: Type) (v :: Type). k -> v -> State# RealWorld -> (# State# RealWorld, Weak# v #) This simplification tends to be good enough for GHCi uses given that there are few levity polymorphic primops and we do little simplification on interpreted code anyways. TODO: This behavior is actually wrong; a program becomes ill-typed upon replacing a real primop occurrence with one of its wrapper due to the fact that the former has an additional type binder. Hmmm.... Note [Eta expanding primops] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ STG requires that primop applications be saturated. This makes code generation significantly simpler since otherwise we would need to define a calling convention for curried applications that can accomodate levity polymorphism. To ensure saturation, CorePrep eta expands expand all primop applications as described in Note [Eta expansion of hasNoBinding things in CorePrep] in GHC.Core.Prep. Historical Note: For a short period around GHC 8.8 we rewrote unsaturated primop applications to rather use the primop's wrapper (see Note [Primop wrappers] in GHC.Builtin.PrimOps) instead of eta expansion. This was because at the time CoreTidy would try to predict the CAFfyness of bindings that would be produced by CorePrep for inclusion in interface files. Eta expanding during CorePrep proved to be very difficult to predict, leading to nasty inconsistencies in CAFfyness determinations (see #16846).  Ben Gamari committed Jun 25, 2019 651   Ben Gamari committed May 29, 2020 652 653 654 655 656 Thankfully, we now no longer try to predict CAFfyness but rather compute it on GHC STG (see Note [SRTs] in GHC.Cmm.Info.Build) and inject it into the interface file after code generation (see TODO: Refer to whatever falls out of #18096). This is much simpler and avoids the potential for inconsistency, allowing us to return to the somewhat simpler eta expansion approach for unsaturated primops.  Ben Gamari committed Jun 25, 2019 657   Ben Gamari committed May 29, 2020 658 See #18079.  Ben Gamari committed Jun 25, 2019 659 660 661 662 663 664 665 666 667 668 669 670 -} -- | Returns the 'Id' of the wrapper associated with the given 'PrimOp'. -- See Note [Primop wrappers]. primOpWrapperId :: PrimOp -> Id primOpWrapperId op = mkVanillaGlobalWithInfo name ty info where info = setCafInfo vanillaIdInfo NoCafRefs name = mkExternalName uniq gHC_PRIMOPWRAPPERS (primOpOcc op) wiredInSrcSpan uniq = mkPrimOpWrapperUnique (primOpTag op) ty = primOpType op  Simon Peyton Jones committed Apr 28, 2017 671 672 isComparisonPrimOp :: PrimOp -> Bool isComparisonPrimOp op = case primOpInfo op of  Krzysztof Gogolewski committed Aug 26, 2020 673 674  Compare {} -> True GenPrimOp {} -> False  Simon Peyton Jones committed Apr 28, 2017 675   simonpj committed Jun 08, 1999 676 677 -- primOpSig is like primOpType but gives the result split apart: -- (type variables, argument types, result type)  simonpj committed Mar 23, 2000 678 -- It also gives arity, strictness info  simonpj committed Jun 08, 1999 679   simonmar committed Dec 10, 2001 680 primOpSig :: PrimOp -> ([TyVar], [Type], Type, Arity, StrictSig)  simonpj committed Jun 08, 1999 681 primOpSig op  sewardj committed Aug 07, 2000 682  = (tyvars, arg_tys, res_ty, arity, primOpStrictness op arity)  simonpj committed Mar 23, 2000 683 684 685 686  where arity = length arg_tys (tyvars, arg_tys, res_ty) = case (primOpInfo op) of  Jan Stolarek committed Aug 14, 2013 687 688  Compare _occ ty -> ([], [ty,ty], intPrimTy) GenPrimOp _occ tyvars arg_tys res_ty -> (tyvars, arg_tys, res_ty )  simonpj committed Jun 08, 1999 689 690  data PrimOpResultInfo  Ian Lynagh committed Sep 30, 2011 691 692  = ReturnsPrim PrimRep | ReturnsAlg TyCon  simonpj committed Jun 08, 1999 693 694 695 696 697 698 699 700  -- Some PrimOps need not return a manifest primitive or algebraic value -- (i.e. they might return a polymorphic value). These PrimOps *must* -- be out of line, or the code generator won't work. getPrimOpResultInfo :: PrimOp -> PrimOpResultInfo getPrimOpResultInfo op = case (primOpInfo op) of  Richard Eisenberg committed Jan 19, 2017 701 702  Compare _ _ -> ReturnsPrim (tyConPrimRep1 intPrimTyCon) GenPrimOp _ _ _ ty | isPrimTyCon tc -> ReturnsPrim (tyConPrimRep1 tc)  Ian Lynagh committed Sep 30, 2011 703 704 705 706  | otherwise -> ReturnsAlg tc where tc = tyConAppTyCon ty -- All primops return a tycon-app result  Ömer Sinan Ağacan committed Jul 21, 2016 707 708  -- The tycon can be an unboxed tuple or sum, though, -- which gives rise to a ReturnAlg  simonpj committed Jun 08, 1999 709   Austin Seipp committed Dec 03, 2014 710 {-  Ian Lynagh committed Oct 03, 2011 711 712 713 714 We do not currently make use of whether primops are commutable. We used to try to move constants to the right hand side for strength reduction.  Austin Seipp committed Dec 03, 2014 715 -}  simonpj committed Jun 08, 1999 716   Ian Lynagh committed Oct 03, 2011 717 {-  simonpj committed Jun 08, 1999 718 commutableOp :: PrimOp -> Bool  sewardj committed Aug 08, 2000 719 #include "primop-commutable.hs-incl"  Ian Lynagh committed Oct 03, 2011 720 -}  simonpj committed Jun 08, 1999 721   Austin Seipp committed Dec 03, 2014 722 723 -- Utils:  Krzysztof Gogolewski committed Aug 26, 2020 724 compare_fun_ty :: Type -> Type  Krzysztof Gogolewski committed Jun 17, 2020 725 compare_fun_ty ty = mkVisFunTysMany [ty, ty] intPrimTy  simonpj committed Jun 08, 1999 726   Austin Seipp committed Dec 03, 2014 727 728 -- Output stuff:  simonpj committed Jun 08, 1999 729 pprPrimOp :: PrimOp -> SDoc  simonmar committed Mar 05, 2002 730 pprPrimOp other_op = pprOccName (primOpOcc other_op)  Duncan Coutts committed Jun 09, 2009 731   Austin Seipp committed Dec 03, 2014 732 733 734 {- ************************************************************************ * *  Duncan Coutts committed Jun 09, 2009 735 \subsubsection[PrimCall]{User-imported primitive calls}  Austin Seipp committed Dec 03, 2014 736 737 738 * * ************************************************************************ -}  Duncan Coutts committed Jun 09, 2009 739   Sylvain Henry committed Apr 30, 2020 740 data PrimCall = PrimCall CLabelString Unit  Duncan Coutts committed Jun 09, 2009 741 742  instance Outputable PrimCall where  Ian Lynagh committed Sep 30, 2011 743 744  ppr (PrimCall lbl pkgId) = text "__primcall" <+> ppr pkgId <+> ppr lbl