Note [Evaluated and Properly Tagged]
A pointer is Evaluated and Properly Tagged (EPT) when the pointer
(a) points directly to the value (not to an indirection, and not to a thunk)
(b) is tagged with the tag corresponding to said value (e.g. constructor tag
or arity of a function).
A binder is EPT when all the runtime pointers it binds are EPT.
Note that a lifted EPT pointer will never point to a thunk, nor will it be
tagged `000` (meaning "might be a thunk").
See https://gitlab.haskell.org/ghc/ghc/-/wikis/commentary/rts/haskell-execution/pointer-tagging
for more information on pointer tagging.
Examples:
* Case binders are always EPT; hence an eval
case x of x' { __DEFAULT -> ... }
ensures that x' is EPT even if x was not.
* Data constructor bindings
let x = Just y in ...
are EPT: x will point to the heap-allocated constructor closure for (Just y),
and the tag-bits of the pointer will encode the tag for Just (i.e. `010`).
* In practice, GHC also guarantees that strict fields (and others) are EPT;
see Note [EPT enforcement].
Caveat:
Currently, the proper tag for builtin *unlifted* data types such as `Array#` is
not `001` but `000`, which is not a proper tag for lifted data.
This means that UnliftedRep is not a proper sub-rep of LiftedRep.
SG thinks it would be good to fix this; see #21792. References 1
- EPT enforcement GHC.Stg.EnforceEpt
Referenced by 5
- EPT enforcement GHC.Stg.EnforceEpt
- Tag inference for interactive contexts GHC.Stg.EnforceEpt.Rewrite
- GHC.Stg.EnforceEpt.Rewrite call site
- GHC.StgToCmm.Closure call site
- GHC.Tc.Instance.Class call site