Note [Deterministic Uniques in the CG]
GHC produces fully deterministic object code. To achieve this, there is a key pass (detRenameCmmGroup) which renames all non-deterministic uniques in the Cmm code right after StgToCmm. See Note [Object determinism] for the big picture and some details. The code generation pipeline that processes this renamed, deterministic, Cmm, however, may still need to generate new uniques. If we were to resort to the non-deterministic unique supply used in the rest of the compiler, our renaming efforts would be for naught. Therefore, after having renamed Cmm deterministically, we must ensure that all uniques created by the code generation pipeline use a deterministic source of uniques. Most often, this means don't use `UniqSM` in the Cmm passes, use `UniqDSM`: `UniqDSM` is a pure state monad with an incrementing counter from which we source new uniques. Unlike `UniqSM`, there's no way to `split` the supply, but it turns out this was rarely really needed for code generation and migrating from UniqSM to UniqDSM was easy. Secondly, the `DUniqSupply` used to run a `UniqDSM` must be threaded through all passes to guarantee uniques in different passes are unique amongst them altogether. Specifically, the same `DUniqSupply` must be threaded through the CG Streaming pipeline, starting with Driver.Main calling `StgToCmm.codeGen`, `cmmPipeline`, `cmmToRawCmm`, and `codeOutput` in sequence. To thread resources through the `Stream` abstraction, we use the `UniqDSMT` transformer on top of `IO` as the Monad underlying the Stream. `UniqDSMT` will thread the `DUniqSupply` through every pass applied to the `Stream`, for every element. We use @type CgStream = Stream (UniqDSMT IO)@ for the Stream used in code generation which that carries through the deterministic unique supply. Unlike non-deterministic unique supplies which can be split into supplies using different tags, or where a new supply with a new tag can be brought from the void, a `DUniqSupply` needs to be sampled iteratively. To use a different tag during a specific pass (to more easily identify uniques created in it), the tag should be manually set and then reset on the unique supply. There's also the auxiliary `setTagUDSMT` which sets the tag for all uniques supplied in the given action, and resets it implicitly. See also Note [Object determinism] in GHC.StgToCmm
References 1
- Object determinism GHC.StgToCmm
Referenced by 8
- GHC.Driver.CodeOutput call site ×4
- GHC.CmmToLlvm call site
- Object determinism GHC.StgToCmm
- GHC.StgToCmm call site
- GHC.Types.Unique.DSM call site