diff options
author | Krzysztof Gogolewski <krzysztof.gogolewski@tweag.io> | 2020-07-16 16:01:09 +0200 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2020-08-28 02:22:36 -0400 |
commit | c6f50cea42a9ffc947bf4243986663cc820b0ec8 (patch) | |
tree | 1afe6d0ac47040f9fe8f43cacb5a211e9a4c32b3 | |
parent | bacccb73c9b080c3c01a5e55ecb0a00cd8a77e55 (diff) | |
download | haskell-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.hs | 3 | ||||
-rw-r--r-- | compiler/GHC/Builtin/primops.txt.pp | 123 | ||||
-rw-r--r-- | compiler/GHC/Iface/Load.hs | 4 | ||||
-rw-r--r-- | compiler/GHC/Types/Id/Make.hs | 37 | ||||
-rw-r--r-- | compiler/GHC/Types/Unique/Supply.hs | 2 | ||||
-rw-r--r-- | libraries/ghc-prim/GHC/Magic.hs | 17 | ||||
-rw-r--r-- | utils/genprimopcode/Main.hs | 6 | ||||
-rw-r--r-- | utils/genprimopcode/Parser.y | 1 |
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 } |