Refactor command-line options handling (DynFlags)
At present command-line options are parsed and directly stored into a huge record named DynFlags. For example, passing -fspec-constr-recursive=10 will directly set the specConstrRecursive field of the DynFlags record to 10.
In addition:
- some options can be passed per module (cf
OPTIONS_GHCpragma) - some options can be (un)set interactively in GHCi
- some options can also be read from package environment files
- some options are automatically and dynamically set by the compiler (e.g. with
-dynamic-too) - we
will soonnow have options per home-unit with the multiple home-units work
Issues:
- We don't track the provenance of the values stored in DynFlags fields:
- we don't know if it's a default value, a user defined one or an automatically set one
- we don't know how it has been passed by the user (real command line, OPTIONS_GHC pragma, interactively, etc.)
- We do a bad job filtering options that are allowed interactively or not, and in OPTIONS_GHC pragma or not. See #19348.
- We can't easily validate options against others. For example if a user passes
-fllvmand then-fasmwe have no way to warn that only the latter will be taken into account.
Proposals:
-
Add an intermediate AST representation for parsed options:
Options = Seq (Located Option). UseLocatedto track the provenance of each option. This AST can then be lowered intoDynFlagswithcacheOptions :: Options -> DynFlags. -
Add support for concatening/appending
Optionswith validation and warning/error reports with location. -
Use
Optionsto store parsedGHC_OPTIONSpragma (i.e.ms_hspp_opts :: Options). Correctly validate options passed this way against the global ones. -
Better
Optionvalidation in GHCi. Correctly report options that do nothing. Ideally, make GHCi interpretOptions considering the current state of the interpreter instead of setting someDynFlagsfields and hoping for no failure. -
Add a
source :: Optionsfield toDynFlagswith the invariant thatcacheOptions (source df) == df. [Rename DynFlags into OptionsCache?]
Project Status (This section added per this comment)
Please tick these off as you finish them and list the relevant MR.
Phase 1: Isolation
This is tracked in #17957.
Phase 2: Correctness
Goal of this phase is to add validation to the handshakes between compiler phases. Once Cmm from Isolation is done, CmmToAsm and CmmToLlvm could be picked up by whomever.
-
CmmToAsm -
CmmToLlvm -
Cmm -
StgToCmm -
Stg -
CoreToStg -
Core.Opt
Phase 3: Efficiency
Goal of this phase is to use the additions from Correctness to remove runtime checks in guards, since by this point the checks should be held in the type system. And reduce the amount of references carried around that could be redundant, for example if foo only needs a single field from PhaseConfig then pass that field rather than the whole config.
This one should be a lot of easy wins but will require lots of perf testing. This one could also be done in parallel after the corresponding checkbox in Correctness is done.
-
CmmToAsm -
CmmToLlvm -
Cmm -
StgToCmm -
Stg -
CoreToStg -
Core.Opt