content: {-# LANGUAGE MultiWayIf, LambdaCase #-}
  
  {-|
  Module      : GHC.Driver.Backend
  Description : Back ends for code generation
  
  This module exports the `Backend` type and all the available values
  of that type.  The type is abstract, and GHC assumes a "closed world":
  all the back ends are known and are known here.  The compiler driver
  chooses a `Backend` value based on how it is asked to generate code.
  
  A `Backend` value encapsulates the knowledge needed to take Cmm, STG,
  or Core and write assembly language to a file.  A back end also
  provides a function that enables the compiler driver to run an
  assembler on the code that is written, if any (the "post-backend
  pipeline").  Finally, a back end has myriad /properties/.  Properties
  mediate interactions between a back end and the rest of the compiler,
  especially the driver.  Examples include the following:
  
   * Property `backendValidityOfCImport` says whether the back end can
     import foreign C functions.
  
   * Property `backendForcesOptimization0` says whether the back end can
     be used with optimization levels higher than `-O0`.
  
   * Property `backendCDefs` tells the compiler driver, "if you're using
     this back end, then these are the command-line flags you should add
     to any invocation of the C compiler."
  
  These properties are used elsewhere in GHC, primarily in the driver, to
  fine-tune operations according to the capabilities of the chosen back
  end.  You might use a property to make GHC aware of a potential
  limitation of certain back ends, or a special feature available only
  in certain back ends.  If your client code needs to know a fact that
  is not exposed in an existing property, you would define and export a
  new property.  Conditioning client code on the /identity/ or /name/ of
  a back end is Not Done.
  
  For full details, see the documentation of each property.
  -}
  
  module GHC.Driver.Backend
     ( -- * The @Backend@ type
       Backend  -- note: type is abstract
     -- * Available back ends
     , ncgBackend
     , llvmBackend
     , jsBackend
     , viaCBackend
     , bytecodeBackend
     , interpreterBackend
     , noBackend
     , allBackends
  
      -- * Types used to specify properties of back ends
     , PrimitiveImplementation(..)
       -- ** Properties that stand for functions
       -- *** Back-end function for code generation
     , DefunctionalizedCodeOutput(..)
       -- *** Back-end functions for assembly
     , DefunctionalizedPostHscPipeline(..)
       -- *** Other back-end functions
     , DefunctionalizedCDefs(..)
       -- ** Names of back ends (for API clients of version 9.4 or earlier)
     , BackendName
  
  
  
       -- * Properties of back ends
     , backendDescription
     , backendWritesFiles
     , backendWritesBytecodeFiles
     , backendPipelineOutput
     , backendCanReuseLoadedCode
     , backendGeneratesCode
     , backendGeneratesCodeForHsBoot
     , backendSupportsInterfaceWriting
     , backendRespectsSpecialise
     , backendWantsGlobalBindings
     , backendHasNativeSwitch
     , backendPrimitiveImplementation
     , backendSimdValidity
     , backendSupportsEmbeddedBlobs
     , backendNeedsPlatformNcgSupport
     , backendSupportsUnsplitProcPoints
     , backendSwappableWithViaC
     , backendUnregisterisedAbiOnly
     , backendGeneratesHc
     , backendSptIsDynamic
     , backendSupportsBreakpoints
     , backendForcesOptimization0
     , backendNeedsFullWays
     , backendSupportsHpc
     , backendSupportsCImport
     , backendSupportsCExport
     , backendCDefs
     , backendCodeOutput
     , backendUseJSLinker
     , backendPostHscPipeline
     , backendNormalSuccessorPhase
     , backendName
     , backendValidityOfCImport
     , backendValidityOfCExport
  
     -- * Other functions of back ends
     , platformDefaultBackend
     , platformNcgSupported
     )
  
  where
  
  
  import GHC.Prelude
  
  import GHC.Driver.Backend.Internal (BackendName(..))
  import GHC.Driver.Phases
  
  
  import GHC.Utils.Error
  import GHC.Utils.Panic
  
  import GHC.Driver.Pipeline.Monad
  import GHC.Platform
  
  
  ---------------------------------------------------------------------------------
  --
  --   DESIGN CONSIDERATIONS
  --
  --
  --
  -- The `Backend` type is made abstract in order to make it possible to
  -- add new back ends without having to inspect or modify much code
  -- elsewhere in GHC.  Adding a new back end would be /easiest/ if
  -- `Backend` were represented as a record type, but in peer review,
  -- the clear will of the majority was to use a sum type.  As a result,
  -- when adding a new back end it is necessary to modify /every/
  -- function in this module that expects `Backend` as its first argument.
  -- **By design, these functions have no default/wildcard cases.** This
  -- design forces the author of a new back end to consider the semantics
  -- in every case, rather than relying on a default that may be wrong.
  -- The names and documentation of the functions defined in the `Backend`
  -- record are sufficiently descriptive that the author of a new back
  -- end will be able to identify correct result values without having to go
  -- spelunking throughout the compiler.
  --
  -- While the design localizes /most/ back-end logic in this module,
  -- the author of a new back end will still have to make changes
  -- elsewhere in the compiler:
  --
  --   * For reasons described in Note [Backend Defunctionalization],
  --     code-generation and post-backend pipeline functions, among other
  --     functions, cannot be placed in the `Backend` record itself.
  --     Instead, the /names/ of those functions are placed.  Each name is
  --     a value constructor in one of the algebraic data types defined in
  --     this module.  The named function is then defined near its point
  --     of use.
  --
  --     The author of a new back end will have to consider whether an
  --     existing function will do or whether a new function needs to be
  --     defined.  When a new function needs to be defined, the author
  --     must take two steps:
  --
  --       - Add a value constructor to the relevant data type here
  --         in the `Backend` module
  --
  --       - Add a case to the location in the compiler (there should be
  --         exactly one) where the value constructors of the relevant
  --         data type are used
  --
  --   * When a new back end is defined, it's quite possible that the
  --     compiler driver will have to be changed in some way.  Just because
  --     the driver supports five back ends doesn't mean it will support a sixth
  --     without changes.
  --
  -- The collection of functions exported from this module hasn't
  -- really been "designed"; it's what emerged from a refactoring of
  -- older code.  The real design criterion was "make it crystal clear
  -- what has to be done to add a new back end."
  --
  -- One issue remains unresolved: some of the error messages and
  -- warning messages used in the driver assume a "closed world": they
  -- think they know all the back ends that exist, and they are not shy
  -- about enumerating them.  Just one set of error messages has been
  -- ported to have an open-world assumption: these are the error
  -- messages associated with type checking of foreign imports and
  -- exports.  To allow other errors to be issued with an open-world
  -- assumption, use functions `backendValidityOfCImport` and
  -- `backendValidityOfCExport` as models, and have a look at how the
  -- 'expected back ends' are used in modules "GHC.Tc.Gen.Foreign" and
  -- "GHC.Tc.Errors.Ppr"
  --
  ---------------------------------------------------------------------------------
  
  
  platformDefaultBackend :: Platform -> Backend
  platformDefaultBackend platform = if
        | platformUnregisterised platform -> viaCBackend
        | platformNcgSupported platform   -> ncgBackend
        | platformJSSupported platform    -> jsBackend
        | otherwise                       -> llvmBackend
  
  -- | Is the platform supported by the Native Code Generator?
  platformNcgSupported :: Platform -> Bool
  platformNcgSupported platform = if
        | platformUnregisterised platform -> False -- NCG doesn't support unregisterised ABI
        | ncgValidArch                    -> True
        | otherwise                       -> False
     where
        ncgValidArch = case platformArch platform of
           ArchX86       -> True
           ArchX86_64    -> True
           ArchPPC       -> True
           ArchPPC_64 {} -> True
           ArchAArch64   -> True
           ArchWasm32    -> True
           ArchRISCV64   -> True
           ArchLoongArch64 -> True
           _             -> False
  
  -- | Is the platform supported by the JS backend?
  platformJSSupported :: Platform -> Bool
  platformJSSupported platform
    | platformArch platform == ArchJavaScript = True
    | otherwise                               = False
  
  
  -- | A value of type @Backend@ represents one of GHC's back ends.
  -- The set of back ends cannot be extended except by modifying the
  -- definition of @Backend@ in this module.
  --
  -- The @Backend@ type is abstract; that is, its value constructors are
  -- not exported.  It's crucial that they not be exported, because a
  -- value of type @Backend@ carries only the back end's /name/, not its
  -- behavior or properties.  If @Backend@ were not abstract, then code
  -- elsewhere in the compiler could depend directly on the name, not on
  -- the semantics, which would make it challenging to create a new back end.
  -- Because @Backend@ /is/ abstract, all the obligations of a new back
  -- end are enumerated in this module, in the form of functions that
  -- take @Backend@ as an argument.
  --
  -- The issue of abstraction is discussed at great length in #20927 and !7442.
  
  
  newtype Backend = Named BackendName
    -- Must be a newtype so that it has no `Eq` instance and
    -- a different `Show` instance.
  
  -- | The Show instance is for messages /only/.  If code depends on
  -- what's in the string, you deserve what happens to you.
  
  instance Show Backend where
    show = backendDescription
  
  
  ncgBackend, llvmBackend, viaCBackend, bytecodeBackend, interpreterBackend, jsBackend, noBackend
      :: Backend
  
  -- | The native code generator.
  -- Compiles Cmm code into textual assembler, then relies on
  -- an external assembler toolchain to produce machine code.
  --
  -- Only supports a few platforms (X86, PowerPC, SPARC).
  --
  -- See "GHC.CmmToAsm".
  ncgBackend = Named NCG
  
  -- | The LLVM backend.
  --
  -- Compiles Cmm code into LLVM textual IR, then relies on
  -- LLVM toolchain to produce machine code.
  --
  -- It relies on LLVM support for the calling convention used
  -- by the NCG backend to produce code objects ABI compatible
  -- with it (see "cc 10" or "ghccc" calling convention in
  -- https://llvm.org/docs/LangRef.html#calling-conventions).
  --
  -- Supports a few platforms (X86, AArch64, s390x, ARM).
  --
  -- See "GHC.CmmToLlvm"
  llvmBackend = Named LLVM
  
  -- | The JavaScript Backend
  --
  -- See documentation in GHC.StgToJS
  jsBackend = Named JavaScript
  
  -- | Via-C ("unregisterised") backend.
  --
  -- Compiles Cmm code into C code, then relies on a C compiler
  -- to produce machine code.
  --
  -- It produces code objects that are /not/ ABI compatible
  -- with those produced by NCG and LLVM backends.
  --
  -- Produced code is expected to be less efficient than the
  -- one produced by NCG and LLVM backends because STG
  -- registers are not pinned into real registers.  On the
  -- other hand, it supports more target platforms (those
  -- having a valid C toolchain).
  --
  -- See "GHC.CmmToC"
  viaCBackend = Named ViaC
  
  -- | The ByteCode interpreter.
  --
  -- Produce ByteCode objects (BCO, see "GHC.ByteCode") that
  -- can be interpreted. It is used by GHCi.
  --
  -- Currently some extensions are not supported
  -- (foreign primops).
  --
  -- See "GHC.StgToByteCode"
  bytecodeBackend = Named Bytecode
  
  {-# DEPRECATED interpreterBackend "Renamed to bytecodeBackend" #-}
  interpreterBackend = bytecodeBackend
  
  
  -- | A dummy back end that generates no code.
  --
  -- Use this back end to disable code generation. It is particularly
  -- useful when GHC is used as a library for other purpose than
  -- generating code (e.g. to generate documentation with Haddock) or
  -- when the user requested it (via `-fno-code`) for some reason.
  noBackend = Named NoBackend
  
  ---------------------------------------------------------------------------------
  
  
  
  
  -- | This enumeration type specifies how the back end wishes GHC's
  -- primitives to be implemented.  (Module "GHC.StgToCmm.Prim" provides
  -- a generic implementation of every primitive, but some primitives,
  -- like `IntQuotRemOp`, can be implemented more efficiently by
  -- certain back ends on certain platforms.  For example, by using a
  -- machine instruction that simultaneously computes quotient and remainder.)
  --
  -- For the meaning of each alternative, consult
  -- "GHC.StgToCmm.Config".  (In a perfect world, type
  -- `PrimitiveImplementation` would be defined there, in the module
  -- that determines its meaning.  But I could not figure out how to do
  -- it without mutual recursion across module boundaries.)
  
  data PrimitiveImplementation
      = LlvmPrimitives    -- ^ Primitives supported by LLVM
      | NcgPrimitives     -- ^ Primitives supported by the native code generator
      | JSPrimitives      -- ^ Primitives supported by JS backend
      | GenericPrimitives -- ^ Primitives supported by all back ends
    deriving Show
  
  
  -- | Names a function that generates code and writes the results to a
  --  file, of this type:
  --
  --  >    Logger
  --  > -> DynFlags
  --  > -> Module -- ^ module being compiled
  --  > -> ModLocation
  --  > -> FilePath -- ^ Where to write output
  --  > -> Set UnitId -- ^ dependencies
  --  > -> Stream IO RawCmmGroup a -- results from `StgToCmm`
  --  > -> IO a
  --
  -- The functions so named are defined in "GHC.Driver.CodeOutput".
  --
  -- We expect one function per back end—or more precisely, one function
  -- for each back end that writes code to a file.  (The interpreter
  -- does not write to files; its output lives only in memory.)
  
  data DefunctionalizedCodeOutput
    = NcgCodeOutput
    | ViaCCodeOutput
    | LlvmCodeOutput
    | JSCodeOutput
  
  
  -- | Names a function that tells the driver what should happen after
  -- assembly code is written.  This might include running a C compiler,
  -- running LLVM, running an assembler, or various similar activities.
  -- The function named normally has this type:
  --
  -- >    TPipelineClass TPhase m
  -- > => PipeEnv
  -- > -> HscEnv
  -- > -> Maybe ModLocation
  -- > -> FilePath
  -- > -> m (Maybe FilePath)
  --
  -- The functions so named are defined in "GHC.Driver.Pipeline".
  
  data DefunctionalizedPostHscPipeline
    = NcgPostHscPipeline
    | ViaCPostHscPipeline
    | LlvmPostHscPipeline
    | JSPostHscPipeline
    | NoPostHscPipeline -- ^ After code generation, nothing else need happen.
  
  -- | Names a function that tells the driver what command-line options
  -- to include when invoking a C compiler.  It's meant for @-D@ options that
  -- define symbols for the C preprocessor.  Because the exact symbols
  -- defined might depend on versions of tools located in the file
  -- system (/cough/ LLVM /cough/), the function requires an `IO` action.
  -- The function named has this type:
  --
  -- > Logger -> DynFlags -> IO [String]
  
  data DefunctionalizedCDefs
    = NoCDefs   -- ^ No additional command-line options are needed
  
    | LlvmCDefs -- ^ Return command-line options that tell GHC about the
                -- LLVM version.
  
  ---------------------------------------------------------------------------------
  
  
  
  -- | An informal description of the back end, for use in
  -- issuing warning messages /only/.  If code depends on
  -- what's in the string, you deserve what happens to you.
  backendDescription :: Backend -> String
  backendDescription (Named NCG)         = "native code generator"
  backendDescription (Named LLVM)        = "LLVM"
  backendDescription (Named ViaC)        = "compiling via C"
  backendDescription (Named JavaScript)  = "compiling to JavaScript"
  backendDescription (Named Bytecode) = "byte-code interpreter"
  backendDescription (Named NoBackend)   = "no code generated"
  
  -- | This flag tells the compiler driver whether the back
  -- end will write files: interface files and object files.
  -- It is typically true for "real" back ends that generate
  -- code into the filesystem.  (That means, not the bytecode backend.)
  --
  -- NOTE: The bytecode backend does generate files now, but this field is used
  -- in the compiler as a proxy for "is a backend which generates normal object files".
  backendWritesFiles :: Backend -> Bool
  backendWritesFiles (Named NCG)         = True
  backendWritesFiles (Named LLVM)        = True
  backendWritesFiles (Named ViaC)        = True
  backendWritesFiles (Named JavaScript)  = True
  backendWritesFiles (Named Bytecode) = False
  backendWritesFiles (Named NoBackend)   = False
  
  -- | Whether the back end by default will produce bytecode files.
  backendWritesBytecodeFiles :: Backend -> Bool
  backendWritesBytecodeFiles (Named NCG)         = False
  backendWritesBytecodeFiles (Named LLVM)        = False
  backendWritesBytecodeFiles (Named ViaC)        = False
  backendWritesBytecodeFiles (Named JavaScript)  = False
  backendWritesBytecodeFiles (Named Bytecode) = True
  backendWritesBytecodeFiles (Named NoBackend)   = False
  
  -- | When the back end does write files, this value tells
  -- the compiler in what manner of file the output should go:
  -- temporary, persistent, or specific.
  backendPipelineOutput :: Backend -> PipelineOutput
  backendPipelineOutput (Named NCG)  = Persistent
  backendPipelineOutput (Named LLVM) = Persistent
  backendPipelineOutput (Named ViaC) = Persistent
  backendPipelineOutput (Named JavaScript)  = Persistent
  backendPipelineOutput (Named Bytecode) = NoOutputFile
  backendPipelineOutput (Named NoBackend)   = NoOutputFile
  
  -- | This flag tells the driver whether the back end can
  -- reuse code (bytecode or object code) that has been
  -- loaded dynamically.  Likely true only of the interpreter.
  backendCanReuseLoadedCode :: Backend -> Bool
  backendCanReuseLoadedCode (Named NCG)         = False
  backendCanReuseLoadedCode (Named LLVM)        = False
  backendCanReuseLoadedCode (Named ViaC)        = False
  backendCanReuseLoadedCode (Named JavaScript)  = False
  backendCanReuseLoadedCode (Named Bytecode) = True
  backendCanReuseLoadedCode (Named NoBackend)   = False
  
  -- | It is is true of every back end except @-fno-code@
  -- that it "generates code."  Surprisingly, this property
  -- influences the driver in a ton of ways.  Some examples:
  --
  --   * If the back end does not generate code, then the
  --     driver needs to turn on code generation for
  --     Template Haskell (because that code needs to be
  --     generated and run at compile time).
  --
  --   * If the back end does not generate code, then the
  --     driver does not need to deal with an output file.
  --
  --   * If the back end /does/ generated code, then the
  --     driver supports `HscRecomp`.  If not, recompilation
  --     does not need a linkable (and is automatically up
  --     to date).
  --
  backendGeneratesCode :: Backend -> Bool
  backendGeneratesCode (Named NCG)         = True
  backendGeneratesCode (Named LLVM)        = True
  backendGeneratesCode (Named ViaC)        = True
  backendGeneratesCode (Named JavaScript)  = True
  backendGeneratesCode (Named Bytecode) = True
  backendGeneratesCode (Named NoBackend)   = False
  
  backendGeneratesCodeForHsBoot :: Backend -> Bool
  backendGeneratesCodeForHsBoot (Named NCG)         = True
  backendGeneratesCodeForHsBoot (Named LLVM)        = True
  backendGeneratesCodeForHsBoot (Named ViaC)        = True
  backendGeneratesCodeForHsBoot (Named JavaScript)  = True
  backendGeneratesCodeForHsBoot (Named Bytecode) = False
  backendGeneratesCodeForHsBoot (Named NoBackend)   = False
  
  -- | When set, this flag turns on interface writing for
  -- Backpack.  It should probably be the same as
  -- `backendGeneratesCode`, but it is kept distinct for
  -- reasons described in Note [-fno-code mode].
  backendSupportsInterfaceWriting :: Backend -> Bool
  backendSupportsInterfaceWriting (Named NCG)         = True
  backendSupportsInterfaceWriting (Named LLVM)        = True
  backendSupportsInterfaceWriting (Named ViaC)        = True
  backendSupportsInterfaceWriting (Named JavaScript)  = True
  backendSupportsInterfaceWriting (Named Bytecode) = True
  backendSupportsInterfaceWriting (Named NoBackend)   = False
  
  -- | When preparing code for this back end, the type
  -- checker should pay attention to SPECIALISE pragmas.  If
  -- this flag is `False`, then the type checker ignores
  -- SPECIALISE pragmas (for imported things?).
  backendRespectsSpecialise :: Backend -> Bool
  backendRespectsSpecialise (Named NCG)         = True
  backendRespectsSpecialise (Named LLVM)        = True
  backendRespectsSpecialise (Named ViaC)        = True
  backendRespectsSpecialise (Named JavaScript)  = True
  backendRespectsSpecialise (Named Bytecode) = False
  backendRespectsSpecialise (Named NoBackend)   = False
  
  -- | This back end wants the `mi_top_env` field of a
  -- `ModIface` to be populated (with the top-level bindings
  -- of the original source).  Only true for the interpreter.
  backendWantsGlobalBindings :: Backend -> Bool
  backendWantsGlobalBindings (Named NCG)         = False
  backendWantsGlobalBindings (Named LLVM)        = False
  backendWantsGlobalBindings (Named ViaC)        = False
  backendWantsGlobalBindings (Named JavaScript)  = False
  backendWantsGlobalBindings (Named NoBackend)   = False
  backendWantsGlobalBindings (Named Bytecode) = True
  
  -- | The back end targets a technology that implements
  -- `switch` natively.  (For example, LLVM or C.) Therefore
  -- it is not necessary for GHC to ccompile a Cmm `Switch`
  -- form into a decision tree with jump tables at the
  -- leaves.
  backendHasNativeSwitch :: Backend -> Bool
  backendHasNativeSwitch (Named NCG)         = False
  backendHasNativeSwitch (Named LLVM)        = True
  backendHasNativeSwitch (Named ViaC)        = True
  backendHasNativeSwitch (Named JavaScript)  = True
  backendHasNativeSwitch (Named Bytecode) = False
  backendHasNativeSwitch (Named NoBackend)   = False
  
  -- | As noted in the documentation for
  -- `PrimitiveImplementation`, certain primitives have
  -- multiple implementations, depending on the capabilities
  -- of the back end.  This field signals to module
  -- "GHC.StgToCmm.Prim" what implementations to use with
  -- this back end.
  backendPrimitiveImplementation :: Backend -> PrimitiveImplementation
  backendPrimitiveImplementation (Named NCG)         = NcgPrimitives
  backendPrimitiveImplementation (Named LLVM)        = LlvmPrimitives
  backendPrimitiveImplementation (Named JavaScript)  = JSPrimitives
  backendPrimitiveImplementation (Named ViaC)        = GenericPrimitives
  backendPrimitiveImplementation (Named Bytecode) = GenericPrimitives
  backendPrimitiveImplementation (Named NoBackend)   = GenericPrimitives
  
  -- | When this value is `IsValid`, the back end is
  -- compatible with vector instructions.  When it is
  -- `NotValid`, it carries a message that is shown to
  -- users.
  backendSimdValidity :: Backend -> Validity' String
  backendSimdValidity (Named NCG)         = IsValid
  backendSimdValidity (Named LLVM)        = IsValid
  backendSimdValidity (Named ViaC)        = NotValid $ unlines ["SIMD vector instructions require using the NCG or the LLVM backend."]
  backendSimdValidity (Named JavaScript)  = NotValid $ unlines ["SIMD vector instructions require using the NCG or the LLVM backend."]
  backendSimdValidity (Named Bytecode) = NotValid $ unlines ["SIMD vector instructions require using the NCG or the LLVM backend."]
  backendSimdValidity (Named NoBackend)   = NotValid $ unlines ["SIMD vector instructions require using the NCG or the LLVM backend."]
  
  -- | This flag says whether the back end supports large
  -- binary blobs.  See Note [Embedding large binary blobs]
  -- in "GHC.CmmToAsm.Ppr".
  backendSupportsEmbeddedBlobs :: Backend -> Bool
  backendSupportsEmbeddedBlobs (Named NCG)         = True
  backendSupportsEmbeddedBlobs (Named LLVM)        = False
  backendSupportsEmbeddedBlobs (Named ViaC)        = False
  backendSupportsEmbeddedBlobs (Named JavaScript)  = False
  backendSupportsEmbeddedBlobs (Named Bytecode) = False
  backendSupportsEmbeddedBlobs (Named NoBackend)   = False
  
  -- | This flag tells the compiler driver that the back end
  -- does not support every target platform; it supports
  -- only platforms that claim NCG support.  (It's set only
  -- for the native code generator.)  Crufty.  If the driver
  -- tries to use the native code generator /without/
  -- platform support, the driver fails over to the LLVM
  -- back end.
  backendNeedsPlatformNcgSupport :: Backend -> Bool
  backendNeedsPlatformNcgSupport (Named NCG)         = True
  backendNeedsPlatformNcgSupport (Named LLVM)        = False
  backendNeedsPlatformNcgSupport (Named ViaC)        = False
  backendNeedsPlatformNcgSupport (Named JavaScript)  = False
  backendNeedsPlatformNcgSupport (Named Bytecode) = False
  backendNeedsPlatformNcgSupport (Named NoBackend)   = False
  
  -- | This flag is set if the back end can generate code
  -- for proc points.  If the flag is not set, then a Cmm
  -- pass needs to split proc points (that is, turn each
  -- proc point into a standalone procedure).
  backendSupportsUnsplitProcPoints :: Backend -> Bool
  backendSupportsUnsplitProcPoints (Named NCG)         = True
  backendSupportsUnsplitProcPoints (Named LLVM)        = False
  backendSupportsUnsplitProcPoints (Named ViaC)        = False
  backendSupportsUnsplitProcPoints (Named JavaScript)  = False
  backendSupportsUnsplitProcPoints (Named Bytecode) = False
  backendSupportsUnsplitProcPoints (Named NoBackend)   = False
  
  -- | This flag guides the driver in resolving issues about
  -- API support on the target platform. If the flag is set,
  -- then these things are true:
  --
  --    * When the target platform supports /only/ an unregisterised API,
  --      this backend can be replaced with compilation via C.
  --
  --    * When the target does /not/ support an unregisterised API,
  --      this back end can replace compilation via C.
  --
  backendSwappableWithViaC :: Backend -> Bool
  backendSwappableWithViaC (Named NCG)         = True
  backendSwappableWithViaC (Named LLVM)        = True
  backendSwappableWithViaC (Named ViaC)        = False
  backendSwappableWithViaC (Named JavaScript)  = False
  backendSwappableWithViaC (Named Bytecode) = False
  backendSwappableWithViaC (Named NoBackend)   = False
  
  -- | This flag is true if the back end works *only* with
  -- the unregisterised ABI.
  backendUnregisterisedAbiOnly :: Backend -> Bool
  backendUnregisterisedAbiOnly (Named NCG)         = False
  backendUnregisterisedAbiOnly (Named LLVM)        = False
  backendUnregisterisedAbiOnly (Named ViaC)        = True
  backendUnregisterisedAbiOnly (Named JavaScript)  = False
  backendUnregisterisedAbiOnly (Named Bytecode) = False
  backendUnregisterisedAbiOnly (Named NoBackend)   = False
  
  -- | This flag is set if the back end generates C code in
  -- a @.hc@ file.  The flag lets the compiler driver know
  -- if the command-line flag @-C@ is meaningful.
  backendGeneratesHc :: Backend -> Bool
  backendGeneratesHc (Named NCG)         = False
  backendGeneratesHc (Named LLVM)        = False
  backendGeneratesHc (Named ViaC)        = True
  backendGeneratesHc (Named JavaScript)  = False
  backendGeneratesHc (Named Bytecode) = False
  backendGeneratesHc (Named NoBackend)   = False
  
  -- | This flag says whether SPT (static pointer table)
  -- entries will be inserted dynamically if needed.  If
  -- this flag is `False`, then "GHC.Iface.Tidy" should emit C
  -- stubs that initialize the SPT entries.
  backendSptIsDynamic :: Backend -> Bool
  backendSptIsDynamic (Named NCG)         = False
  backendSptIsDynamic (Named LLVM)        = False
  backendSptIsDynamic (Named ViaC)        = False
  backendSptIsDynamic (Named JavaScript)  = False
  backendSptIsDynamic (Named Bytecode) = True
  backendSptIsDynamic (Named NoBackend)   = False
  
  -- | If this flag is unset, then the driver ignores the flag @-fbreak-points@,
  -- since backends other than the interpreter tend to panic on breakpoints.
  backendSupportsBreakpoints :: Backend -> Bool
  backendSupportsBreakpoints = \case
    Named NCG         -> False
    Named LLVM        -> False
    Named ViaC        -> False
    Named JavaScript  -> False
    Named Bytecode -> True
    Named NoBackend   -> False
  
  -- | If this flag is set, then the driver forces the
  -- optimization level to 0, issuing a warning message if
  -- the command line requested a higher optimization level.
  backendForcesOptimization0 :: Backend -> Bool
  backendForcesOptimization0 (Named NCG)         = False
  backendForcesOptimization0 (Named LLVM)        = False
  backendForcesOptimization0 (Named ViaC)        = False
  backendForcesOptimization0 (Named JavaScript)  = False
  backendForcesOptimization0 (Named Bytecode) = True
  backendForcesOptimization0 (Named NoBackend)   = False
  
  -- | I don't understand exactly how this works.  But if
  -- this flag is set *and* another condition is met, then
  -- @ghc/Main.hs@ will alter the `DynFlags` so that all the
  -- `hostFullWays` are asked for.  It is set only for the interpreter.
  backendNeedsFullWays :: Backend -> Bool
  backendNeedsFullWays (Named NCG)         = False
  backendNeedsFullWays (Named LLVM)        = False
  backendNeedsFullWays (Named ViaC)        = False
  backendNeedsFullWays (Named JavaScript)  = False
  backendNeedsFullWays (Named Bytecode) = True
  backendNeedsFullWays (Named NoBackend)   = False
  
  -- | This flag says whether the back end supports Haskell
  -- Program Coverage (HPC). If not, the compiler driver
  -- will ignore the `-fhpc` option (and will issue a
  -- warning message if it is used).
  backendSupportsHpc :: Backend -> Bool
  backendSupportsHpc (Named NCG)         = True
  backendSupportsHpc (Named LLVM)        = True
  backendSupportsHpc (Named ViaC)        = True
  backendSupportsHpc (Named JavaScript)  = False
  -- TODO: @terrorjack thinks that the bytecode backend should support HPC now since (!13493)
  backendSupportsHpc (Named Bytecode) = False
  backendSupportsHpc (Named NoBackend)   = True
  
  -- | This flag says whether the back end supports foreign
  -- import of C functions.  ("Supports" means "does not
  -- barf on," so @-fno-code@ supports foreign C imports.)
  backendSupportsCImport :: Backend -> Bool
  backendSupportsCImport (Named NCG)         = True
  backendSupportsCImport (Named LLVM)        = True
  backendSupportsCImport (Named ViaC)        = True
  backendSupportsCImport (Named JavaScript)  = True
  backendSupportsCImport (Named Bytecode) = True
  backendSupportsCImport (Named NoBackend)   = True
  
  -- | This flag says whether the back end supports foreign
  -- export of Haskell functions to C.
  backendSupportsCExport :: Backend -> Bool
  backendSupportsCExport (Named NCG)         = True
  backendSupportsCExport (Named LLVM)        = True
  backendSupportsCExport (Named ViaC)        = True
  backendSupportsCExport (Named JavaScript)  = True
  backendSupportsCExport (Named Bytecode) = False
  backendSupportsCExport (Named NoBackend)   = True
  
  -- | When using this back end, it may be necessary or
  -- advisable to pass some `-D` options to a C compiler.
  -- This (defunctionalized) function produces those
  -- options, if any.  An IO action may be necessary in
  -- order to interrogate external tools about what version
  -- they are, for example.
  --
  -- The function's type is
  -- @
  -- Logger -> DynFlags -> IO [String]
  -- @
  --
  -- This field is usually defaulted.
  backendCDefs :: Backend -> DefunctionalizedCDefs
  backendCDefs (Named NCG)         = NoCDefs
  backendCDefs (Named LLVM)        = LlvmCDefs
  backendCDefs (Named ViaC)        = NoCDefs
  backendCDefs (Named JavaScript)  = NoCDefs
  backendCDefs (Named Bytecode) = NoCDefs
  backendCDefs (Named NoBackend)   = NoCDefs
  
  -- | This (defunctionalized) function generates code and
  -- writes it to a file.  The type of the function is
  --
  -- >    Logger
  -- > -> DynFlags
  -- > -> Module -- ^ module being compiled
  -- > -> ModLocation
  -- > -> FilePath -- ^ Where to write output
  -- > -> Set UnitId -- ^ dependencies
  -- > -> Stream IO RawCmmGroup a -- results from `StgToCmm`
  -- > -> IO a
  backendCodeOutput :: Backend -> DefunctionalizedCodeOutput
  backendCodeOutput (Named NCG)         = NcgCodeOutput
  backendCodeOutput (Named LLVM)        = LlvmCodeOutput
  backendCodeOutput (Named ViaC)        = ViaCCodeOutput
  backendCodeOutput (Named JavaScript)  = JSCodeOutput
  backendCodeOutput (Named Bytecode) = panic "backendCodeOutput: bytecodeBackend"
  backendCodeOutput (Named NoBackend)   = panic "backendCodeOutput: noBackend"
  
  backendUseJSLinker :: Backend -> Bool
  backendUseJSLinker (Named NCG)         = False
  backendUseJSLinker (Named LLVM)        = False
  backendUseJSLinker (Named ViaC)        = False
  backendUseJSLinker (Named JavaScript)  = True
  backendUseJSLinker (Named Bytecode) = False
  backendUseJSLinker (Named NoBackend)   = False
  
  -- | This (defunctionalized) function tells the compiler
  -- driver what else has to be run after code output.
  -- The type of the function is
  --
  -- >
  -- >    TPipelineClass TPhase m
  -- > => PipeEnv
  -- > -> HscEnv
  -- > -> Maybe ModLocation
  -- > -> FilePath
  -- > -> m (Maybe FilePath)
  backendPostHscPipeline :: Backend -> DefunctionalizedPostHscPipeline
  backendPostHscPipeline (Named NCG)  = NcgPostHscPipeline
  backendPostHscPipeline (Named LLVM) = LlvmPostHscPipeline
  backendPostHscPipeline (Named ViaC) = ViaCPostHscPipeline
  backendPostHscPipeline (Named JavaScript)  = JSPostHscPipeline
  backendPostHscPipeline (Named Bytecode) = NoPostHscPipeline
  backendPostHscPipeline (Named NoBackend) = NoPostHscPipeline
  
  -- | Somewhere in the compiler driver, when compiling
  -- Haskell source (as opposed to a boot file or a sig
  -- file), it needs to know what to do with the code that
  -- the `backendCodeOutput` writes to a file.  This `Phase`
  -- value gives instructions like "run the C compiler",
  -- "run the assembler," or "run the LLVM Optimizer."
  backendNormalSuccessorPhase :: Backend -> Phase
  backendNormalSuccessorPhase (Named NCG)  = As False
  backendNormalSuccessorPhase (Named LLVM) = LlvmOpt
  backendNormalSuccessorPhase (Named ViaC) = HCc
  backendNormalSuccessorPhase (Named JavaScript)  = StopLn
  backendNormalSuccessorPhase (Named Bytecode) = StopLn
  backendNormalSuccessorPhase (Named NoBackend)   = StopLn
  
  -- | Name of the back end, if any.  Used to migrate legacy
  -- clients of the GHC API.  Code within the GHC source
  -- tree should not refer to a back end's name.
  backendName :: Backend -> BackendName
  backendName (Named NCG)  = NCG
  backendName (Named LLVM) = LLVM
  backendName (Named ViaC) = ViaC
  backendName (Named JavaScript)  = JavaScript
  backendName (Named Bytecode) = Bytecode
  backendName (Named NoBackend)   = NoBackend
  
  
  
  -- | A list of all back ends.  They are ordered as we wish them to
  -- appear when they are enumerated in error messages.
  
  allBackends :: [Backend]
  allBackends = [ ncgBackend
                , llvmBackend
                , viaCBackend
                , jsBackend
                , bytecodeBackend
                , noBackend
                ]
  
  -- | When foreign C import or export is invalid, the carried value
  -- enumerates the /valid/ back ends.
  
  backendValidityOfCImport, backendValidityOfCExport :: Backend -> Validity' [Backend]
  
  backendValidityOfCImport backend =
      if backendSupportsCImport backend then
          IsValid
      else
          NotValid $ filter backendSupportsCImport allBackends
  
  backendValidityOfCExport backend =
      if backendSupportsCExport backend then
          IsValid
      else
          NotValid $ filter backendSupportsCExport allBackends
  
  
  
  
  {-
  Note [Backend Defunctionalization]
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  I had hoped to include code-output and post-hsc-pipeline functions
  directly in the `Backend` record itself.  But this agenda was derailed
  by mutual recursion in the types:
  
    - A `DynFlags` record contains a back end of type `Backend`.
    - A `Backend` contains a code-output function.
    - A code-output function takes Cmm as input.
    - Cmm can include a `CLabel`.
    - A `CLabel` can have elements that are defined in
      `GHC.Driver.Session`, where `DynFlags` is defined.
  
  There is also a nasty issue in the values: a typical post-backend
  pipeline function both depends on and is depended upon by functions in
  "GHC.Driver.Pipeline".
  
  I'm cut the Gordian not by removing the function types from the
  `Backend` record.  Instead, a function is represented by its /name/.
  This representation is an example of an old trick called
  /defunctionalization/, which has been used in both compilers and
  interpreters for languages with first-class, nested functions.  Here,
  a function's name is a value of an algebraic data type.  For example,
  a code-output function is represented by a value of this type:
  
      data DefunctionalizedCodeOutput
        = NcgCodeOutput
        | ViaCCodeOutput
        | LlvmCodeOutput
  
  Such a function may be applied in one of two ways:
  
    - In this particular example, a `case` expression in module
      "GHC.Driver.CodeOutput" discriminates on the value and calls the
      designated function.
  
    - In another example, a function of type `DefunctionalizedCDefs` is
      applied by calling function `applyCDefs`, which has this type:
  
      @
      applyCDefs :: DefunctionalizedCDefs -> Logger -> DynFlags -> IO [String]
      @
  
      Function `applyCDefs` is defined in module "GHC.SysTools.Cpp".
  
  I don't love this solution, but defunctionalization is a standard
  thing, and it makes the meanings of the enumeration values clear.
  
  Anyone defining a new back end will need to extend both the
  `DefunctionalizedCodeOutput` type and the corresponding apply
  function.
  -}
  