summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKrzysztof Gogolewski <krzysztof.gogolewski@tweag.io>2020-07-16 16:01:09 +0200
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-08-28 02:22:36 -0400
commitc6f50cea42a9ffc947bf4243986663cc820b0ec8 (patch)
tree1afe6d0ac47040f9fe8f43cacb5a211e9a4c32b3
parentbacccb73c9b080c3c01a5e55ecb0a00cd8a77e55 (diff)
downloadhaskell-c6f50cea42a9ffc947bf4243986663cc820b0ec8.tar.gz
Add missing primop documentation (#18454)
- Add three pseudoops to primops.txt.pp, so that Haddock renders the documentation - Update comments - Remove special case for "->" - it's no longer exported from GHC.Prim - Remove reference to Note [Compiling GHC.Prim] - the ad-hoc fix is no longer there after updates to levity polymorphism. - Document GHC.Prim - Remove the comment that lazy is levity-polymorphic. As far as I can tell, it never was: in 80e399639, only the unfolding was given an open type variable. - Remove haddock hack in GHC.Magic - no longer neccessary after adding realWorld# to primops.txt.pp.
-rw-r--r--compiler/GHC/Builtin/Utils.hs3
-rw-r--r--compiler/GHC/Builtin/primops.txt.pp123
-rw-r--r--compiler/GHC/Iface/Load.hs4
-rw-r--r--compiler/GHC/Types/Id/Make.hs37
-rw-r--r--compiler/GHC/Types/Unique/Supply.hs2
-rw-r--r--libraries/ghc-prim/GHC/Magic.hs17
-rw-r--r--utils/genprimopcode/Main.hs6
-rw-r--r--utils/genprimopcode/Parser.y1
8 files changed, 137 insertions, 56 deletions
diff --git a/compiler/GHC/Builtin/Utils.hs b/compiler/GHC/Builtin/Utils.hs
index 208b630e2e..a3d0290acd 100644
--- a/compiler/GHC/Builtin/Utils.hs
+++ b/compiler/GHC/Builtin/Utils.hs
@@ -257,9 +257,6 @@ primOpId op = primOpIds ! primOpTag op
Export lists for pseudo-modules (GHC.Prim)
* *
************************************************************************
-
-GHC.Prim "exports" all the primops and primitive types, some
-wired-in Ids.
-}
ghcPrimExports :: [IfaceExport]
diff --git a/compiler/GHC/Builtin/primops.txt.pp b/compiler/GHC/Builtin/primops.txt.pp
index 37542e2112..59f31faf57 100644
--- a/compiler/GHC/Builtin/primops.txt.pp
+++ b/compiler/GHC/Builtin/primops.txt.pp
@@ -15,14 +15,86 @@
--
-- It should first be preprocessed.
--
+-- Note in particular that Haskell block-style comments are not recognized
+-- here, so stick to '--' (even for Notes spanning multiple lines).
+
+-- Note [GHC.Prim]
+-- ~~~~~~~~~~~~~~~
+-- GHC.Prim is a special module:
+--
+-- * It can be imported by any module (import GHC.Prim).
+-- However, in the future we might change which functions are primitives
+-- and which are defined in Haskell.
+-- Users should import GHC.Exts, which reexports GHC.Prim and is more stable.
+-- In particular, we might move some of the primops to 'foreign import prim'
+-- (see ticket #16929 and Note [When do out-of-line primops go in primops.txt.pp])
+--
+-- * It provides primitives of three sorts:
+-- - primitive types such as Int64#, MutableByteArray#
+-- - primops such as (+#), newTVar#, touch#
+-- - pseudoops such as realWorld#, nullAddr#
+--
+-- * The pseudoops are described in Note [ghcPrimIds (aka pseudoops)]
+-- in GHC.Types.Id.Make.
+--
+-- * The primitives (primtypes, primops, pseudoops) cannot be defined in
+-- source Haskell.
+-- There is no GHC/Prim.hs file with definitions.
+-- Instead, we support importing GHC.Prim by manually defining its
+-- ModIface (see Iface.Load.ghcPrimIface).
+--
+-- * The primitives are listed in this file, primops.txt.pp.
+-- It goes through CPP, which creates primops.txt.
+-- It is then consumed by the utility program genprimopcode, which produces
+-- the following three types of files.
+--
+-- 1. The files with extension .hs-incl.
+-- They can be found by grepping for hs-incl.
+-- They are #included in compiler sources.
+--
+-- One of them, primop-data-decl.hs-incl, defines the PrimOp type:
+-- data PrimOp
+-- = IntAddOp
+-- | IntSubOp
+-- | CharGtOp
+-- | CharGeOp
+-- | ...
+--
+-- The remaining files define properties of the primops
+-- by pattern matching, for example:
+-- primOpFixity IntAddOp = Just (Fixity NoSourceText 6 InfixL)
+-- primOpFixity IntSubOp = Just (Fixity NoSourceText 6 InfixL)
+-- ...
+-- This includes fixity, has-side-effects, commutability,
+-- IDs used to generate Uniques etc.
+--
+-- Additionally, we pattern match on PrimOp when generating Cmm in
+-- GHC/StgToCmm/Prim.hs.
+--
+-- 2. The dummy Prim.hs file, which is used for Haddock and
+-- contains descriptions taken from primops.txt.pp.
+-- All definitions are replaced by placeholders.
+-- See Note [GHC.Prim Docs] in genprimopcode.
+--
+-- 3. The module PrimopWrappers.hs, which wraps every call for GHCi;
+-- see Note [Primop wrappers] in GHC.Builtin.Primops for details.
+--
+-- * This file does not list internal-only equality types
+-- (GHC.Builtin.Types.Prim.unexposedPrimTyCons and coercionToken#
+-- in GHC.Types.Id.Make) which are defined but not exported from GHC.Prim.
+-- Every export of GHC.Prim should be in listed in this file.
+--
+-- * The primitive types should be listed in primTyCons in Builtin.Types.Prim
+-- in addition to primops.txt.pp.
+-- (This task should be delegated to genprimopcode in the future.)
+--
+--
+--
-- Information on how PrimOps are implemented and the steps necessary to
-- add a new one can be found in the Commentary:
--
-- https://gitlab.haskell.org/ghc/ghc/wikis/commentary/prim-ops
--
--- Note in particular that Haskell block-style comments are not recognized
--- here, so stick to '--' (even for Notes spanning multiple lines).
-
-- This file is divided into named sections, each containing or more
-- primop entries. Section headers have the format:
--
@@ -76,7 +148,6 @@ defaults
vector = []
deprecated_msg = {} -- A non-empty message indicates deprecation
-
-- Note [When do out-of-line primops go in primops.txt.pp]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--
@@ -189,19 +260,6 @@ section "The word size story."
#define WORD64 Word#
#endif
--- This type won't be exported directly (since there is no concrete
--- syntax for this sort of export) so we'll have to manually patch
--- export lists in both GHC and Haddock.
-primtype FUN m a b
- {The builtin function type, written in infix form as {\tt a # m -> b}.
- Values of this type are functions taking inputs of type {\tt a} and
- producing outputs of type {\tt b}. The multiplicity of the input is
- {\tt m}.
-
- Note that {\tt FUN m a b} permits levity-polymorphism in both {\tt a} and
- {\tt b}, so that types like {\tt Int\# -> Int\#} can still be well-kinded.
- }
-
------------------------------------------------------------------------
section "Char#"
{Operations on 31-bit characters.}
@@ -3377,6 +3435,37 @@ section "Etc"
{Miscellaneous built-ins}
------------------------------------------------------------------------
+primtype FUN m a b
+ {The builtin function type, written in infix form as {\tt a # m -> b}.
+ Values of this type are functions taking inputs of type {\tt a} and
+ producing outputs of type {\tt b}. The multiplicity of the input is
+ {\tt m}.
+
+ Note that {\tt FUN m a b} permits levity-polymorphism in both {\tt a} and
+ {\tt b}, so that types like {\tt Int\# -> Int\#} can still be well-kinded.
+ }
+
+pseudoop "realWorld#"
+ State# RealWorld
+ { The token used in the implementation of the IO monad as a state monad.
+ It does not pass any information at runtime.
+ See also {\tt GHC.Magic.runRW\#}. }
+
+pseudoop "void#"
+ (# #)
+ { This is an alias for the unboxed unit tuple constructor.
+ In earlier versions of GHC, {\tt void\#} was a value
+ of the primitive type {\tt Void\#}, which is now defined to be {\tt (\# \#)}.
+ }
+ with deprecated_msg = { Use an unboxed unit tuple instead }
+
+pseudoop "magicDict"
+ a
+ { {\tt magicDict} is a special-purpose placeholder value.
+ It is used internally by modules such as {\tt GHC.TypeNats} to cast a typeclass
+ dictionary with a single method. It is eliminated by a rule during compilation.
+ For the details, see Note [magicDictId magic] in GHC. }
+
primtype Proxy# a
{ The type constructor {\tt Proxy#} is used to bear witness to some
type variable. It's used when you want to pass around proxy values
diff --git a/compiler/GHC/Iface/Load.hs b/compiler/GHC/Iface/Load.hs
index 39e08c7eee..f687bf11a6 100644
--- a/compiler/GHC/Iface/Load.hs
+++ b/compiler/GHC/Iface/Load.hs
@@ -915,6 +915,7 @@ findAndReadIface doc_str mod wanted_mod_with_insts hi_boot_file
nest 4 (text "reason:" <+> doc_str)])
-- Check for GHC.Prim, and return its static interface
+ -- See Note [GHC.Prim] in primops.txt.pp.
-- TODO: make this check a function
if mod `installedModuleEq` gHC_PRIM
then do
@@ -1059,6 +1060,7 @@ initExternalPackageState home_unit
*********************************************************
-}
+-- See Note [GHC.Prim] in primops.txt.pp.
ghcPrimIface :: ModIface
ghcPrimIface
= empty_iface {
@@ -1071,7 +1073,7 @@ ghcPrimIface
where
empty_iface = emptyFullModIface gHC_PRIM
- -- The fixities listed here for @`seq`@ or @->@ should match
+ -- The fixity listed here for @`seq`@ should match
-- those in primops.txt.pp (from which Haddock docs are generated).
fixities = (getOccName seqId, Fixity NoSourceText 0 InfixR)
: mapMaybe mkFixity allThePrimOps
diff --git a/compiler/GHC/Types/Id/Make.hs b/compiler/GHC/Types/Id/Make.hs
index 90a3368dea..108dd41dda 100644
--- a/compiler/GHC/Types/Id/Make.hs
+++ b/compiler/GHC/Types/Id/Make.hs
@@ -118,7 +118,8 @@ Note [ghcPrimIds (aka pseudoops)]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ghcPrimIds
- * Are exported from GHC.Prim
+ * Are exported from GHC.Prim (see ghcPrimExports, used in ghcPrimInterface)
+ See Note [GHC.Prim] in primops.txt.pp for the remaining items in GHC.Prim.
* Can't be defined in Haskell, and hence no Haskell binding site,
but have perfectly reasonable unfoldings in Core
@@ -141,7 +142,17 @@ The magicIds
* May or may not have a CompulsoryUnfolding.
* But have some special behaviour that can't be done via an
- unfolding from an interface file
+ unfolding from an interface file.
+
+ * May have IdInfo that differs from what would be imported from GHC.Magic.hi.
+ For example, 'lazy' gets a lazy strictness signature, per Note [lazyId magic].
+
+ The two remaining identifiers in GHC.Magic, runRW# and inline, are not listed
+ in magicIds: they have special behavior but they can be known-key and
+ not wired-in.
+ runRW#: see Note [Simplification of runRW#] in Prep, runRW# code in
+ Simplifier, Note [Linting of runRW#].
+ inline: see Note [inlineId magic]
-}
wiredInIds :: [Id]
@@ -1402,12 +1413,12 @@ These Ids can't be defined in Haskell. They could be defined in
unfoldings in the wired-in GHC.Prim interface file, but we'd have to
ensure that they were definitely, definitely inlined, because there is
no curried identifier for them. That's what mkCompulsoryUnfolding
-does. If we had a way to get a compulsory unfolding from an interface
-file, we could do that, but we don't right now.
+does. Alternatively, we could add the definitions to mi_decls of ghcPrimIface
+but it's not clear if this would be simpler.
-The type variables we use here are "open" type variables: this means
-they can unify with both unlifted and lifted types. Hence we provide
-another gun with which to shoot yourself in the foot.
+coercionToken# is not listed in ghcPrimIds, since its type uses (~#)
+which is not supposed to be used in expressions (GHC throws an assertion
+failure when trying.)
-}
nullAddrName, seqName,
@@ -1422,6 +1433,7 @@ magicDictName = mkWiredInIdName gHC_PRIM (fsLit "magicDict") magicDict
coerceName = mkWiredInIdName gHC_PRIM (fsLit "coerce") coerceKey coerceId
proxyName = mkWiredInIdName gHC_PRIM (fsLit "proxy#") proxyHashKey proxyHashId
+-- Names listed in magicIds; see Note [magicIds]
lazyIdName, oneShotName, noinlineIdName :: Name
lazyIdName = mkWiredInIdName gHC_MAGIC (fsLit "lazy") lazyIdKey lazyId
oneShotName = mkWiredInIdName gHC_MAGIC (fsLit "oneShot") oneShotKey oneShotId
@@ -1598,7 +1610,7 @@ See also: Note [User-defined RULES for seq] in GHC.Core.Opt.Simplify.
Note [lazyId magic]
~~~~~~~~~~~~~~~~~~~
-lazy :: forall a?. a? -> a? (i.e. works for unboxed types too)
+lazy :: forall a. a -> a
'lazy' is used to make sure that a sub-expression, and its free variables,
are truly used call-by-need, with no code motion. Key examples:
@@ -1616,7 +1628,7 @@ are truly used call-by-need, with no code motion. Key examples:
Implementing 'lazy' is a bit tricky:
* It must not have a strictness signature: by being a built-in Id,
- all the info about lazyId comes from here, not from GHC.Base.hi.
+ all the info about lazyId comes from here, not from GHC.Magic.hi.
This is important, because the strictness analyser will spot it as
strict!
@@ -1777,7 +1789,7 @@ voidPrimId = pcMiscPrelId voidPrimIdName unboxedUnitTy
voidArgId :: Id -- Local lambda-bound :: Void#
voidArgId = mkSysLocal (fsLit "void") voidArgIdKey Many unboxedUnitTy
-coercionTokenId :: Id -- :: () ~ ()
+coercionTokenId :: Id -- :: () ~# ()
coercionTokenId -- See Note [Coercion tokens] in "GHC.CoreToStg"
= pcMiscPrelId coercionTokenName
(mkTyConApp eqPrimTyCon [liftedTypeKind, liftedTypeKind, unitTy, unitTy])
@@ -1786,8 +1798,3 @@ coercionTokenId -- See Note [Coercion tokens] in "GHC.CoreToStg"
pcMiscPrelId :: Name -> Type -> IdInfo -> Id
pcMiscPrelId name ty info
= mkVanillaGlobalWithInfo name ty info
- -- We lie and say the thing is imported; otherwise, we get into
- -- a mess with dependency analysis; e.g., core2stg may heave in
- -- random calls to GHCbase.unpackPS__. If GHCbase is the module
- -- being compiled, then it's just a matter of luck if the definition
- -- will be in "the right place" to be in scope.
diff --git a/compiler/GHC/Types/Unique/Supply.hs b/compiler/GHC/Types/Unique/Supply.hs
index a401946732..30181c773e 100644
--- a/compiler/GHC/Types/Unique/Supply.hs
+++ b/compiler/GHC/Types/Unique/Supply.hs
@@ -180,7 +180,7 @@ The magic `inline` function does two things
* It helps ensure that 'm' really does inline.
-Note that 'inline' evaporates in phase 0. See Note [inlineIdMagic]
+Note that 'inline' evaporates in phase 0. See Note [inlineId magic]
in GHC.Core.Opt.ConstantFold.match_inline.
The INLINE pragma on multiShotIO is very important, else the
diff --git a/libraries/ghc-prim/GHC/Magic.hs b/libraries/ghc-prim/GHC/Magic.hs
index d1f2650a96..cd9474271d 100644
--- a/libraries/ghc-prim/GHC/Magic.hs
+++ b/libraries/ghc-prim/GHC/Magic.hs
@@ -1,8 +1,6 @@
-{-# LANGUAGE CPP #-}
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE MagicHash #-}
-{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
@@ -32,13 +30,8 @@ module GHC.Magic ( inline, noinline, lazy, oneShot, runRW# ) where
-- Here import TYPE explicitly 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)
+-- genprimops which Haddock will typecheck (#15935).
+import GHC.Prim (State#, realWorld#, RealWorld)
import GHC.Types (RuntimeRep, TYPE)
-- | The call @inline f@ arranges that @f@ is inlined, regardless of
@@ -83,8 +76,6 @@ noinline x = x
--
-- If 'lazy' were not lazy, 'Control.Parallel.par' would look strict in
-- @y@ which would defeat the whole purpose of 'Control.Parallel.par'.
---
--- 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
@@ -124,8 +115,4 @@ runRW# :: forall (r :: RuntimeRep) (o :: TYPE r).
(State# RealWorld -> o) -> o
-- See Note [runRW magic] in GHC.CoreToStg.Prep.
{-# NOINLINE runRW# #-} -- runRW# is inlined manually in CorePrep
-#if !defined(__HADDOCK_VERSION__)
runRW# m = m realWorld#
-#else
-runRW# = runRW# -- The realWorld# is too much for haddock
-#endif
diff --git a/utils/genprimopcode/Main.hs b/utils/genprimopcode/Main.hs
index a817c75a0d..36daa45a52 100644
--- a/utils/genprimopcode/Main.hs
+++ b/utils/genprimopcode/Main.hs
@@ -1,5 +1,7 @@
------------------------------------------------------------------
-- A primop-table mangling program --
+--
+-- See Note [GHC.Prim] in primops.txt.pp for details.
------------------------------------------------------------------
module Main where
@@ -293,8 +295,6 @@ gen_hs_source (Info defaults entries) =
hdr (PrimOpSpec { name = n }) = wrapOp n ++ ","
hdr (PrimVecOpSpec { name = n }) = wrapOp n ++ ","
hdr (PseudoOpSpec { name = n }) = wrapOp n ++ ","
- hdr (PrimTypeSpec { ty = TyApp (TyCon "->") _ }) = ""
- -- GHC lacks the syntax to explicitly export "->"
hdr (PrimTypeSpec { ty = TyApp (TyCon n) _ }) = wrapOp n ++ ","
hdr (PrimTypeSpec {}) = error $ "Illegal type spec"
hdr (PrimVecTypeSpec { ty = TyApp (VecTyCon n _) _ }) = wrapOp n ++ ","
@@ -398,8 +398,6 @@ keep GHC's renamer and typechecker happy enough for what Haddock
needs. Our main plan is to say
foo :: <type>
foo = foo
-We have to silence GHC's complaints about unboxed-top-level declarations
-with an ad-hoc fix in GHC.Tc.Gen.Bind: see Note [Compiling GHC.Prim] in GHC.Tc.Gen.Bind.
That works for all the primitive functions except tagToEnum#.
If we generate the binding
diff --git a/utils/genprimopcode/Parser.y b/utils/genprimopcode/Parser.y
index efcfee0889..f39af24c7c 100644
--- a/utils/genprimopcode/Parser.y
+++ b/utils/genprimopcode/Parser.y
@@ -163,6 +163,7 @@ paT : pTycon ppTs { TyApp $1 $2 }
pUnboxedTupleTy :: { Ty }
pUnboxedTupleTy : '(#' pCommaTypes '#)' { TyUTup $2 }
+ | '(#' '#)' { TyUTup [] }
pCommaTypes :: { [Ty] }
pCommaTypes : pType ',' pCommaTypes { $1 : $3 }