Magic.hs 5.12 KB
Newer Older
1
{-# LANGUAGE CPP #-}
dterei's avatar
dterei committed
2
{-# LANGUAGE Trustworthy #-}
dterei's avatar
dterei committed
3
{-# LANGUAGE NoImplicitPrelude #-}
4 5
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
6 7
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}
David Feuer's avatar
David Feuer committed
8
{-# LANGUAGE ScopedTypeVariables #-}
9

Ian Lynagh's avatar
Ian Lynagh committed
10 11 12 13 14 15 16 17 18 19 20
-----------------------------------------------------------------------------
-- |
-- Module      :  GHC.Magic
-- Copyright   :  (c) The University of Glasgow 2009
-- License     :  see libraries/ghc-prim/LICENSE
--
-- Maintainer  :  cvs-ghc@haskell.org
-- Stability   :  internal
-- Portability :  non-portable (GHC Extensions)
--
-- GHC magic.
dterei's avatar
dterei committed
21
--
Ian Lynagh's avatar
Ian Lynagh committed
22 23 24 25 26
-- Use GHC.Exts from the base package instead of importing this
-- module directly.
--
-----------------------------------------------------------------------------

27
module GHC.Magic ( inline, noinline, lazy, oneShot, runRW# ) where
Ian Lynagh's avatar
Ian Lynagh committed
28

29 30 31 32
--------------------------------------------------
--        See Note [magicIds] in MkId.hs
--------------------------------------------------

David Eichmann's avatar
David Eichmann committed
33 34 35 36 37 38 39 40 41
-- Here import TYPE explicitely from GHC.Types and not from GHC.Prim. This is
-- because TYPE is not exported by the source Haskell module generated by
-- genprimops which Haddock will typecheck.
-- Likewise, realWorld# is not generated by genprimops so we use CPP and only
-- import/use it when not building haddock docs.
#if !defined(__HADDOCK_VERSION__)
import GHC.Prim (realWorld#)
#endif
import GHC.Prim (State#, RealWorld)
David Feuer's avatar
David Feuer committed
42
import GHC.Types (RuntimeRep, TYPE)
43

Alec Theriault's avatar
Alec Theriault committed
44
-- | The call @inline f@ arranges that @f@ is inlined, regardless of
rwbarton's avatar
rwbarton committed
45 46
-- its size. More precisely, the call @inline f@ rewrites to the
-- right-hand side of @f@'s definition. This allows the programmer to
47
-- control inlining from a particular call site rather than the
Alec Theriault's avatar
Alec Theriault committed
48
-- definition site of the function (c.f. @INLINE@ pragmas).
49 50
--
-- This inlining occurs regardless of the argument to the call or the
rwbarton's avatar
rwbarton committed
51 52
-- size of @f@'s definition; it is unconditional. The main caveat is
-- that @f@'s definition must be visible to the compiler; it is
Alec Theriault's avatar
Alec Theriault committed
53
-- therefore recommended to mark the function with an @INLINABLE@
54 55 56 57 58
-- pragma at its definition so that GHC guarantees to record its
-- unfolding regardless of size.
--
-- If no inlining takes place, the 'inline' function expands to the
-- identity function in Phase zero, so its use imposes no overhead.
Ian Lynagh's avatar
Ian Lynagh committed
59
{-# NOINLINE[0] inline #-}
60
inline :: a -> a
Ian Lynagh's avatar
Ian Lynagh committed
61 62
inline x = x

Alec Theriault's avatar
Alec Theriault committed
63
-- | The call @noinline f@ arranges that @f@ will not be inlined.
64 65 66 67 68 69
-- It is removed during CorePrep so that its use imposes no overhead
-- (besides the fact that it blocks inlining.)
{-# NOINLINE noinline #-}
noinline :: a -> a
noinline x = x

70
-- | The 'lazy' function restrains strictness analysis a little. The
Alec Theriault's avatar
Alec Theriault committed
71
-- call @lazy e@ means the same as @e@, but 'lazy' has a magical
72 73 74 75 76 77 78 79 80 81 82 83
-- property so far as strictness analysis is concerned: it is lazy in
-- its first argument, even though its semantics is strict. After
-- strictness analysis has run, calls to 'lazy' are inlined to be the
-- identity function.
--
-- This behaviour is occasionally useful when controlling evaluation
-- order. Notably, 'lazy' is used in the library definition of
-- 'Control.Parallel.par':
--
-- > par :: a -> b -> b
-- > par x y = case (par# x) of _ -> lazy y
--
Alec Theriault's avatar
Alec Theriault committed
84 85
-- If 'lazy' were not lazy, 'Control.Parallel.par' would look strict in
-- @y@ which would defeat the whole purpose of 'Control.Parallel.par'.
86 87 88 89 90
--
-- Like 'seq', the argument of 'lazy' can have an unboxed type.
lazy :: a -> a
lazy x = x
-- Implementation note: its strictness and unfolding are over-ridden
91
-- by the definition in MkId.hs; in both cases to nothing at all.
92 93 94 95
-- That way, 'lazy' does not get inlined, and the strictness analyser
-- sees it as lazy.  Then the worker/wrapper phase inlines it.
-- Result: happiness

Joachim Breitner's avatar
Joachim Breitner committed
96 97 98 99 100

-- | The 'oneShot' function can be used to give a hint to the compiler that its
-- argument will be called at most once, which may (or may not) enable certain
-- optimizations. It can be useful to improve the performance of code in continuation
-- passing style.
Joachim Breitner's avatar
Joachim Breitner committed
101 102 103 104 105
--
-- If 'oneShot' is used wrongly, then it may be that computations whose result
-- that would otherwise be shared are re-evaluated every time they are used. Otherwise,
-- the use of `oneShot` is safe.
--
David Feuer's avatar
David Feuer committed
106 107 108 109 110
-- 'oneShot' is representation polymorphic: the type variables may refer to lifted
-- or unlifted types.
oneShot :: forall (q :: RuntimeRep) (r :: RuntimeRep)
                  (a :: TYPE q) (b :: TYPE r).
           (a -> b) -> a -> b
Joachim Breitner's avatar
Joachim Breitner committed
111
oneShot f = f
112
-- Implementation note: This is wired in in MkId.hs, so the code here is
Joachim Breitner's avatar
Joachim Breitner committed
113
-- mostly there to have a place for the documentation.
114

Alec Theriault's avatar
Alec Theriault committed
115 116
-- | Apply a function to a @'State#' 'RealWorld'@ token. When manually applying
-- a function to `realWorld#`, it is necessary to use @NOINLINE@ to prevent
David Feuer's avatar
David Feuer committed
117 118 119 120 121 122 123 124
-- semantically undesirable floating. `runRW#` is inlined, but only very late
-- in compilation after all floating is complete.

-- 'runRW#' is representation polymorphic: the result may have a lifted or
-- unlifted type.

runRW# :: forall (r :: RuntimeRep) (o :: TYPE r).
          (State# RealWorld -> o) -> o
Simon Peyton Jones's avatar
Simon Peyton Jones committed
125 126
-- See Note [runRW magic] in CorePrep
{-# NOINLINE runRW# #-}  -- runRW# is inlined manually in CorePrep
127 128 129 130 131
#if !defined(__HADDOCK_VERSION__)
runRW# m = m realWorld#
#else
runRW# = runRW#   -- The realWorld# is too much for haddock
#endif