Add support for `hpc` in the bytecode interpreter
Adds support to produce .tix from interpreted bytecode.
Conceptually, we insert HPC ticks into the bytecode similar to how we insert breakpoints. HPC and breakpoints do not share the same tick array or index.
Further, we teach the bytecode interpreter how to handle hpc ticks.
A tricky bit is "registering" a bytecode object for HPC instrumentation.
In the compiled case, this is achieved via CStub and initializer/finalizers .init sections which are called when executable is run.
See https://maskray.me/blog/2021-11-07-init-ctors-init-array for an explanation.
After the initializers have been invoked, which is before hs_init_ghc, we then call startup_hpc in hs_init_ghc iff any modules were "registered" for hpc instrumentation via hs_hpc_module.
Since bytecode objects are loaded after starting up GHCi, this workflow doesn't work for supporting hpc.
We fix this issue by employing the same technique as is for SptEntrys:
- We introduce a new field to
CompiledByteCode, calledByteCodeHpcInfowhich contains enough information to callhs_hpc_module, allowing us to register the module forhpcinstrumentation`. - After registering the module, we unconditionally call
startupHpc, to make sure the .tix file is written.
Calling startupHpc multiple times is safe.
Calling hs_hpc_module multiple times for the same module is also safe.
A generalisation of this could be to call the initialisation functions of both SptEntry and Hpc that can be found in the CStub.
Closes #27036 (closed)