Rodrigo Mesquita pushed to branch wip/fendor/no-code-output-constr at Glasgow Haskell Compiler / GHC
Commits:
-
2b3ffb19
by Rodrigo Mesquita at 2026-06-24T16:05:48+01:00
5 changed files:
- compiler/GHC/Driver/Backend.hs
- compiler/GHC/Driver/CodeOutput.hs
- compiler/GHC/Driver/Main/Compile.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Session.hs
Changes:
| ... | ... | @@ -118,7 +118,6 @@ import GHC.Driver.Phases |
| 118 | 118 | |
| 119 | 119 | |
| 120 | 120 | import GHC.Utils.Error
|
| 121 | -import GHC.Utils.Panic
|
|
| 122 | 121 | |
| 123 | 122 | import GHC.Driver.Pipeline.Monad
|
| 124 | 123 | import GHC.Platform
|
| ... | ... | @@ -369,7 +368,8 @@ data PrimitiveImplementation |
| 369 | 368 | -- We expect one function per back end—or more precisely, one function
|
| 370 | 369 | -- for each back end that writes code to a file. (The interpreter
|
| 371 | 370 | -- does not write to files; its output lives only in memory.)
|
| 372 | - |
|
| 371 | +--
|
|
| 372 | +-- See Note [Backend Defunctionalization]
|
|
| 373 | 373 | data DefunctionalizedCodeOutput
|
| 374 | 374 | = NcgCodeOutput
|
| 375 | 375 | | ViaCCodeOutput
|
| ... | ... | @@ -779,20 +779,33 @@ backendCDefs (Named NoBackend) = NoCDefs |
| 779 | 779 | -- > -> Set UnitId -- ^ dependencies
|
| 780 | 780 | -- > -> Stream IO RawCmmGroup a -- results from `StgToCmm`
|
| 781 | 781 | -- > -> IO a
|
| 782 | -backendCodeOutput :: Backend -> DefunctionalizedCodeOutput
|
|
| 783 | -backendCodeOutput (Named NCG) = NcgCodeOutput
|
|
| 784 | -backendCodeOutput (Named LLVM) = LlvmCodeOutput
|
|
| 785 | -backendCodeOutput (Named ViaC) = ViaCCodeOutput
|
|
| 786 | -backendCodeOutput (Named JavaScript) = JSCodeOutput
|
|
| 787 | -backendCodeOutput (Named Bytecode) = panic "backendCodeOutput: bytecodeBackend"
|
|
| 788 | -backendCodeOutput (Named NoBackend) = panic "backendCodeOutput: noBackend"
|
|
| 782 | +--
|
|
| 783 | +-- See Note [Backend Defunctionalization]
|
|
| 784 | +--
|
|
| 785 | +-- === __WARNING__
|
|
| 786 | +--
|
|
| 787 | +-- Do NOT use 'backendCodeOutput' (or other functions in this module) as a
|
|
| 788 | +-- proxy for the 'Backend', which is __abstract by design__.
|
|
| 789 | +--
|
|
| 790 | +-- If you need to determine some property of the backend, do NOT match on
|
|
| 791 | +-- 'DefunctionalizedCodeOutput'; Instead, write a new property predicate in
|
|
| 792 | +-- this module. This makes it easier to add new backends because essentially
|
|
| 793 | +-- all backend properties depended upon throughout the compiler are all found
|
|
| 794 | +-- here.
|
|
| 795 | +backendCodeOutput :: Backend -> Maybe DefunctionalizedCodeOutput
|
|
| 796 | +backendCodeOutput (Named NCG) = Just NcgCodeOutput
|
|
| 797 | +backendCodeOutput (Named LLVM) = Just LlvmCodeOutput
|
|
| 798 | +backendCodeOutput (Named ViaC) = Just ViaCCodeOutput
|
|
| 799 | +backendCodeOutput (Named JavaScript) = Just JSCodeOutput
|
|
| 800 | +backendCodeOutput (Named Bytecode) = Nothing
|
|
| 801 | +backendCodeOutput (Named NoBackend) = Nothing
|
|
| 789 | 802 | |
| 790 | 803 | backendUseJSLinker :: Backend -> Bool
|
| 791 | 804 | backendUseJSLinker (Named NCG) = False
|
| 792 | 805 | backendUseJSLinker (Named LLVM) = False
|
| 793 | 806 | backendUseJSLinker (Named ViaC) = False
|
| 794 | 807 | backendUseJSLinker (Named JavaScript) = True
|
| 795 | -backendUseJSLinker (Named Bytecode) = False
|
|
| 808 | +backendUseJSLinker (Named Bytecode) = False
|
|
| 796 | 809 | backendUseJSLinker (Named NoBackend) = False
|
| 797 | 810 | |
| 798 | 811 | -- | This (defunctionalized) function tells the compiler
|
| ... | ... | @@ -4,7 +4,6 @@ |
| 4 | 4 | \section{Code output phase}
|
| 5 | 5 | -}
|
| 6 | 6 | |
| 7 | - |
|
| 8 | 7 | module GHC.Driver.CodeOutput
|
| 9 | 8 | ( codeOutput
|
| 10 | 9 | , outputForeignStubs
|
| ... | ... | @@ -50,7 +49,7 @@ import GHC.Utils.Outputable |
| 50 | 49 | import GHC.Utils.Logger
|
| 51 | 50 | import GHC.Utils.Exception ( bracket )
|
| 52 | 51 | import GHC.Utils.Ppr (Mode(..))
|
| 53 | -import GHC.Utils.Panic.Plain ( pgmError )
|
|
| 52 | +import GHC.Utils.Panic.Plain ( panic, pgmError )
|
|
| 54 | 53 | |
| 55 | 54 | import GHC.Unit
|
| 56 | 55 | import GHC.Unit.Finder ( mkStubPaths )
|
| ... | ... | @@ -63,7 +62,6 @@ import GHC.Types.Unique.Supply ( UniqueTag(..) ) |
| 63 | 62 | import System.IO
|
| 64 | 63 | import Data.Set (Set)
|
| 65 | 64 | import qualified Data.Set as Set
|
| 66 | -import GHC.Plugins (panic)
|
|
| 67 | 65 | |
| 68 | 66 | {-
|
| 69 | 67 | ************************************************************************
|
| ... | ... | @@ -125,11 +123,12 @@ codeOutput logger tmpfs llvm_config dflags unit_state this_mod filenm location g |
| 125 | 123 | |
| 126 | 124 | ; let dus1 = newTagDUniqSupply CodeGenTag dus0
|
| 127 | 125 | ; (stubs, a) <- case backendCodeOutput (backend dflags) of
|
| 128 | - NcgCodeOutput -> outputAsm logger dflags this_mod location filenm dus1
|
|
| 129 | - final_stream
|
|
| 130 | - ViaCCodeOutput -> outputC logger dflags filenm dus1 final_stream pkg_deps
|
|
| 131 | - LlvmCodeOutput -> outputLlvm logger llvm_config dflags filenm dus1 final_stream
|
|
| 132 | - JSCodeOutput -> outputJS logger llvm_config dflags filenm final_stream
|
|
| 126 | + Just NcgCodeOutput -> outputAsm logger dflags this_mod location filenm dus1
|
|
| 127 | + final_stream
|
|
| 128 | + Just ViaCCodeOutput -> outputC logger dflags filenm dus1 final_stream pkg_deps
|
|
| 129 | + Just LlvmCodeOutput -> outputLlvm logger llvm_config dflags filenm dus1 final_stream
|
|
| 130 | + Just JSCodeOutput -> outputJS logger llvm_config dflags filenm final_stream
|
|
| 131 | + Nothing -> panic $ "backendCodeOutput: " ++ show (backend dflags) ++ " doesn't support code output"
|
|
| 133 | 132 | ; stubs_exist <- outputForeignStubs logger tmpfs dflags unit_state this_mod location stubs
|
| 134 | 133 | ; return (filenm, stubs_exist, foreign_fps, a)
|
| 135 | 134 | }
|
| ... | ... | @@ -2,6 +2,7 @@ |
| 2 | 2 | {-# LANGUAGE MultiWayIf #-}
|
| 3 | 3 | |
| 4 | 4 | {-# OPTIONS_GHC -fprof-auto-top #-}
|
| 5 | +{-# OPTIONS_GHC -Wno-x-backend #-} -- we do use backendCodeOutput for defunctionalization
|
|
| 5 | 6 | |
| 6 | 7 | -------------------------------------------------------------------------------
|
| 7 | 8 | --
|
| ... | ... | @@ -670,7 +671,7 @@ hscGenHardCode hsc_env cgguts mod_loc output_filename = do |
| 670 | 671 | -- next withTiming after this will be "Assembler" (hard code only).
|
| 671 | 672 | withTiming logger (text "CodeGen"<+>brackets (ppr this_mod)) (const ())
|
| 672 | 673 | $ case backendCodeOutput (backend dflags) of
|
| 673 | - JSCodeOutput ->
|
|
| 674 | + Just JSCodeOutput ->
|
|
| 674 | 675 | do
|
| 675 | 676 | let js_config = initStgToJSConfig dflags
|
| 676 | 677 | |
| ... | ... | @@ -696,7 +697,7 @@ hscGenHardCode hsc_env cgguts mod_loc output_filename = do |
| 696 | 697 | stgToJS logger js_config stg_binds this_mod spt_entries foreign_stubs0 cost_centre_info output_filename
|
| 697 | 698 | return (output_filename, stub_c_exists, foreign_fps, Just stg_cg_infos, Just cmm_cg_infos)
|
| 698 | 699 | |
| 699 | - _ ->
|
|
| 700 | + Just _ ->
|
|
| 700 | 701 | do
|
| 701 | 702 | cmms <- {-# SCC "StgToCmm" #-}
|
| 702 | 703 | doCodeGen hsc_env this_mod denv tycons
|
| ... | ... | @@ -724,6 +725,7 @@ hscGenHardCode hsc_env cgguts mod_loc output_filename = do |
| 724 | 725 | foreign_stubs foreign_files dependencies (initDUniqSupply 'n' 0) rawcmms1
|
| 725 | 726 | return ( output_filename, stub_c_exists, foreign_fps
|
| 726 | 727 | , Just stg_cg_infos, Just cmm_cg_infos)
|
| 728 | + Nothing -> panic $ "backendCodeOutput: " ++ show (backend dflags) ++ " doesn't support code output"
|
|
| 727 | 729 | |
| 728 | 730 | |
| 729 | 731 | -- The part of CgGuts that we need for HscInteractive
|
| ... | ... | @@ -743,7 +743,7 @@ compileEmptyStub dflags hsc_env basename location mod_name = do |
| 743 | 743 | let home_unit = hsc_home_unit hsc_env
|
| 744 | 744 | |
| 745 | 745 | case backendCodeOutput (backend dflags) of
|
| 746 | - JSCodeOutput -> do
|
|
| 746 | + Just JSCodeOutput -> do
|
|
| 747 | 747 | empty_stub <- newTempName logger tmpfs (tmpDir dflags) TFL_CurrentModule "js"
|
| 748 | 748 | let src = ppr (mkHomeModule home_unit mod_name) <+> text "= 0;"
|
| 749 | 749 | writeFile empty_stub (showSDoc dflags (pprCode src))
|
| ... | ... | @@ -752,7 +752,7 @@ compileEmptyStub dflags hsc_env basename location mod_name = do |
| 752 | 752 | _ <- runPipeline (hsc_hooks hsc_env) pipeline
|
| 753 | 753 | pure ()
|
| 754 | 754 | |
| 755 | - _ -> do
|
|
| 755 | + Just _ -> do
|
|
| 756 | 756 | empty_stub <- newTempName logger tmpfs (tmpDir dflags) TFL_CurrentModule "c"
|
| 757 | 757 | let src = text "int" <+> ppr (mkHomeModule home_unit mod_name) <+> text "= 0;"
|
| 758 | 758 | writeFile empty_stub (showSDoc dflags (pprCode src))
|
| ... | ... | @@ -760,6 +760,7 @@ compileEmptyStub dflags hsc_env basename location mod_name = do |
| 760 | 760 | pipeline = viaCPipeline HCc pipe_env hsc_env (Just location) empty_stub
|
| 761 | 761 | _ <- runPipeline (hsc_hooks hsc_env) pipeline
|
| 762 | 762 | pure ()
|
| 763 | + Nothing -> panic $ "backendCodeOutput: " ++ show (backend dflags) ++ " doesn't support code output"
|
|
| 763 | 764 | |
| 764 | 765 | |
| 765 | 766 |
| ... | ... | @@ -3856,8 +3856,8 @@ makeDynFlagsConsistent dflags |
| 3856 | 3856 | && os == OSMinGW32
|
| 3857 | 3857 | && arch == ArchAArch64
|
| 3858 | 3858 | = case backendCodeOutput (backend dflags) of
|
| 3859 | - LlvmCodeOutput -> pgmError "-fllvm is incompatible with enabled TablesNextToCode at Windows Aarch64"
|
|
| 3860 | - NcgCodeOutput -> pgmError "-fasm is incompatible with enabled TablesNextToCode at Windows Aarch64"
|
|
| 3859 | + Just LlvmCodeOutput -> pgmError "-fllvm is incompatible with enabled TablesNextToCode at Windows Aarch64"
|
|
| 3860 | + Just NcgCodeOutput -> pgmError "-fasm is incompatible with enabled TablesNextToCode at Windows Aarch64"
|
|
| 3861 | 3861 | _ -> (dflags, mempty, mempty)
|
| 3862 | 3862 | |
| 3863 | 3863 | -- When we do ghci, force using dyn ways if the target RTS linker
|