These tickishs are meant to carry the (simplified and prepared) Core
through the later compilation stages.
- Core notes are only useful in certain scenarios (mostly profiling), and will end up taking up significant space in object files. We therefore use another GHC flag (-fsave-core) to decide whether we annotate them or not.
- Annotations happen after CorePrep. This is slightly tricky, as CoreToStg moves ticks around even after this point. We have to be careful to ensure ticks end up where we intend them to be.
- We take the easy route to just "point" into the Core code directly. This is slightly awkward given that Core is normally a more stright- forward data structure. We have to short-circuit Eq/Ord, for example.
- We only annotate the interesting control flow points, which are either top-level or let binding bodies as well as case branches.
- In order to establish an identity and later perform sub-expression checks, we safe a binder (of the binding or case) and the case constructor (if applicable, otherwise __DEFAULT).