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_GHC
pragma) - 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
-fllvm
and then-fasm
we 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)
. UseLocated
to track the provenance of each option. This AST can then be lowered intoDynFlags
withcacheOptions :: Options -> DynFlags
. -
Add support for concatening/appending
Options
with validation and warning/error reports with location. -
Use
Options
to store parsedGHC_OPTIONS
pragma (i.e.ms_hspp_opts :: Options
). Correctly validate options passed this way against the global ones. -
Better
Option
validation in GHCi. Correctly report options that do nothing. Ideally, make GHCi interpretOption
s considering the current state of the interpreter instead of setting someDynFlags
fields and hoping for no failure. -
Add a
source :: Options
field toDynFlags
with the invariant thatcacheOptions (source df) == df
. [Rename DynFlags into OptionsCache?]
this comment)
Project Status (This section added perPlease 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