From 735f9d6bac316a0c1c68a8b49bba465f07b01cdd Mon Sep 17 00:00:00 2001
From: Sylvain Henry <sylvain@haskus.fr>
Date: Mon, 29 Jun 2020 19:58:56 +0200
Subject: [PATCH] Replace ghcWithNativeCodeGen with a proper Backend datatype

* Represent backends with a `Backend` datatype in GHC.Driver.Backend

* Don't detect the default backend to use for the target platform at
  compile time in Hadrian/make but at runtime. It makes "Settings"
  simpler and it is a step toward making GHC multi-target.

* The latter change also fixes hadrian which has not been updated to
  take into account that the NCG now supports AIX and PPC64 (cf
  df26b95559fd467abc0a3a4151127c95cb5011b9 and
  d3c1dda60d0ec07fc7f593bfd83ec9457dfa7984)

* Also we don't treat iOS specifically anymore (cf
  cb4878ffd18a3c70f98bdbb413cd3c4d1f054e1f)
---
 compiler/GHC/Cmm/CLabel.hs         |  2 +-
 compiler/GHC/Driver/Backend.hs     | 43 ++++++++++++++++++++++++++++++
 compiler/GHC/Driver/Session.hs     | 42 +++++++++++++++++------------
 compiler/GHC/Settings/IO.hs        |  2 --
 compiler/ghc.cabal.in              |  1 +
 distrib/cross-port                 |  1 -
 distrib/hc-build                   |  1 -
 hadrian/src/Oracles/Flag.hs        |  9 +------
 hadrian/src/Rules/Generate.hs      |  1 -
 includes/ghc.mk                    |  1 -
 libraries/ghc-boot/GHC/Platform.hs |  1 -
 mk/config.mk.in                    | 13 ---------
 12 files changed, 71 insertions(+), 46 deletions(-)
 create mode 100644 compiler/GHC/Driver/Backend.hs

diff --git a/compiler/GHC/Cmm/CLabel.hs b/compiler/GHC/Cmm/CLabel.hs
index 6c9810c10e3..47487c7ebe8 100644
--- a/compiler/GHC/Cmm/CLabel.hs
+++ b/compiler/GHC/Cmm/CLabel.hs
@@ -1255,7 +1255,7 @@ pprCLabel dflags = \case
 
   where
     platform = targetPlatform dflags
-    useNCG   = platformMisc_ghcWithNativeCodeGen (platformMisc dflags)
+    useNCG   = hscTarget dflags == HscAsm
 
     maybe_underscore :: SDoc -> SDoc
     maybe_underscore doc =
diff --git a/compiler/GHC/Driver/Backend.hs b/compiler/GHC/Driver/Backend.hs
new file mode 100644
index 00000000000..8f227d2a2b9
--- /dev/null
+++ b/compiler/GHC/Driver/Backend.hs
@@ -0,0 +1,43 @@
+{-# LANGUAGE MultiWayIf #-}
+
+-- | Code generation backends
+module GHC.Driver.Backend
+   ( Backend (..)
+   , platformDefaultBackend
+   , platformNcgSupported
+   )
+where
+
+import GHC.Prelude
+import GHC.Platform
+
+-- | Backend
+data Backend
+   = NCG           -- ^ Native code generator backend
+   | LLVM          -- ^ LLVM backend
+   | ViaC          -- ^ Via-C backend
+   | Interpreter   -- ^ Interpreter
+   deriving (Eq,Ord,Show,Read)
+
+-- | Default backend to use for the given platform.
+platformDefaultBackend :: Platform -> Backend
+platformDefaultBackend platform = if
+      | platformUnregisterised platform -> ViaC
+      | platformNcgSupported platform   -> NCG
+      | otherwise                       -> LLVM
+
+
+-- | 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
+         ArchSPARC     -> True
+         _             -> False
diff --git a/compiler/GHC/Driver/Session.hs b/compiler/GHC/Driver/Session.hs
index 04ff23d5feb..7d5c72ba743 100644
--- a/compiler/GHC/Driver/Session.hs
+++ b/compiler/GHC/Driver/Session.hs
@@ -253,6 +253,7 @@ import {-# SOURCE #-} GHC.Unit.State (UnitState, emptyUnitState, UnitDatabase, u
 import GHC.Driver.Phases ( Phase(..), phaseInputExt )
 import GHC.Driver.Flags
 import GHC.Driver.Ways
+import GHC.Driver.Backend
 import GHC.Settings.Config
 import GHC.Utils.CliOption
 import GHC.Driver.CmdLine hiding (WarnReason(..))
@@ -1151,16 +1152,15 @@ instance Outputable PackageFlag where
 -- | The 'HscTarget' value corresponding to the default way to create
 -- object files on the current platform.
 
-defaultHscTarget :: Platform -> PlatformMisc -> HscTarget
-defaultHscTarget platform pMisc
-  | platformUnregisterised platform = HscC
-  | platformMisc_ghcWithNativeCodeGen pMisc = HscAsm
+defaultHscTarget :: Platform -> HscTarget
+defaultHscTarget platform
+  | platformUnregisterised platform        = HscC
+  | NCG <- platformDefaultBackend platform = HscAsm
   | otherwise = HscLlvm
 
 defaultObjectTarget :: DynFlags -> HscTarget
 defaultObjectTarget dflags = defaultHscTarget
   (targetPlatform dflags)
-  (platformMisc dflags)
 
 data DynLibLoader
   = Deployable
@@ -1272,7 +1272,7 @@ defaultDynFlags mySettings llvmConfig =
      DynFlags {
         ghcMode                 = CompManager,
         ghcLink                 = LinkBinary,
-        hscTarget               = defaultHscTarget (sTargetPlatform mySettings) (sPlatformMisc mySettings),
+        hscTarget               = defaultHscTarget (sTargetPlatform mySettings),
         verbosity               = 0,
         optLevel                = 0,
         debugLevel              = 0,
@@ -4856,7 +4856,8 @@ compilerInfo dflags
        ("Target platform",             platformMisc_targetPlatformString $ platformMisc dflags),
        ("Have interpreter",            showBool $ platformMisc_ghcWithInterpreter $ platformMisc dflags),
        ("Object splitting supported",  showBool False),
-       ("Have native code generator",  showBool $ platformMisc_ghcWithNativeCodeGen $ platformMisc dflags),
+       ("Have native code generator",  showBool $ platformNcgSupported (targetPlatform dflags)),
+       ("Target default backend",      show $ platformDefaultBackend (targetPlatform dflags)),
        -- Whether or not we support @-dynamic-too@
        ("Support dynamic-too",         showBool $ not isWindows),
        -- Whether or not we support the @-j@ flag with @--make@.
@@ -4951,28 +4952,35 @@ makeDynFlagsConsistent dflags
     = let dflags' = gopt_unset dflags Opt_BuildDynamicToo
           warn    = "-dynamic-too is not supported on Windows"
       in loop dflags' warn
+
+   -- Via-C backend only supports unregisterised convention. Switch to a backend
+   -- supporting it if possible.
  | hscTarget dflags == HscC &&
    not (platformUnregisterised (targetPlatform dflags))
-    = if platformMisc_ghcWithNativeCodeGen $ platformMisc dflags
-      then let dflags' = dflags { hscTarget = HscAsm }
-               warn = "Compiler not unregisterised, so using native code generator rather than compiling via C"
-           in loop dflags' warn
-      else let dflags' = dflags { hscTarget = HscLlvm }
-               warn = "Compiler not unregisterised, so using LLVM rather than compiling via C"
-           in loop dflags' warn
+    = case platformDefaultBackend (targetPlatform dflags) of
+         NCG  -> let dflags' = dflags { hscTarget = HscAsm }
+                     warn = "Target platform doesn't use unregisterised ABI, so using native code generator rather than compiling via C"
+                 in loop dflags' warn
+         LLVM -> let dflags' = dflags { hscTarget = HscLlvm }
+                     warn = "Target platform doesn't use unregisterised ABI, so using LLVM rather than compiling via C"
+                 in loop dflags' warn
+         _    -> pgmError "Compiling via C is only supported with unregisterised ABI but target platform doesn't use it."
  | gopt Opt_Hpc dflags && hscTarget dflags == HscInterpreted
     = let dflags' = gopt_unset dflags Opt_Hpc
           warn = "Hpc can't be used with byte-code interpreter. Ignoring -fhpc."
       in loop dflags' warn
+
  | hscTarget dflags `elem` [HscAsm, HscLlvm] &&
    platformUnregisterised (targetPlatform dflags)
     = loop (dflags { hscTarget = HscC })
-           "Compiler unregisterised, so compiling via C"
+           "Target platform uses unregisterised ABI, so compiling via C"
+
  | hscTarget dflags == HscAsm &&
-   not (platformMisc_ghcWithNativeCodeGen $ platformMisc dflags)
+   not (platformNcgSupported $ targetPlatform dflags)
       = let dflags' = dflags { hscTarget = HscLlvm }
-            warn = "No native code generator, so using LLVM"
+            warn = "Native code generator doesn't support target platform, so using LLVM"
         in loop dflags' warn
+
  | not (osElfTarget os) && gopt Opt_PIE dflags
     = loop (gopt_unset dflags Opt_PIE)
            "Position-independent only supported on ELF platforms"
diff --git a/compiler/GHC/Settings/IO.hs b/compiler/GHC/Settings/IO.hs
index 956b28d2705..c84bf280bce 100644
--- a/compiler/GHC/Settings/IO.hs
+++ b/compiler/GHC/Settings/IO.hs
@@ -149,7 +149,6 @@ initSettings top_dir = do
   let iserv_prog = libexec "ghc-iserv"
 
   ghcWithInterpreter <- getBooleanSetting "Use interpreter"
-  ghcWithNativeCodeGen <- getBooleanSetting "Use native code generator"
   ghcWithSMP <- getBooleanSetting "Support SMP"
   ghcRTSWays <- getSetting "RTS ways"
   useLibFFI <- getBooleanSetting "Use LibFFI"
@@ -216,7 +215,6 @@ initSettings top_dir = do
     , sPlatformMisc = PlatformMisc
       { platformMisc_targetPlatformString = targetPlatformString
       , platformMisc_ghcWithInterpreter = ghcWithInterpreter
-      , platformMisc_ghcWithNativeCodeGen = ghcWithNativeCodeGen
       , platformMisc_ghcWithSMP = ghcWithSMP
       , platformMisc_ghcRTSWays = ghcRTSWays
       , platformMisc_libFFI = useLibFFI
diff --git a/compiler/ghc.cabal.in b/compiler/ghc.cabal.in
index 755ef4dab7c..7d896b8ad37 100644
--- a/compiler/ghc.cabal.in
+++ b/compiler/ghc.cabal.in
@@ -162,6 +162,7 @@ Library
         GHC.Iface.Ext.Ast
         GHC.SysTools.Ar
         GHC.SysTools.FileCleanup
+        GHC.Driver.Backend
         GHC.Driver.Backpack
         GHC.Driver.Backpack.Syntax
         GHC.Types.Name.Shape
diff --git a/distrib/cross-port b/distrib/cross-port
index 4a1854135a1..29dd804e825 100644
--- a/distrib/cross-port
+++ b/distrib/cross-port
@@ -62,7 +62,6 @@ if [ ! -f b2-stamp ]; then
    # code too.  If you don't want it to, then comment out this line:
    echo "GhcUnregisterised = YES" >> mk/build.mk
    echo "SRC_HC_OPTS += -keep-hc-file -fvia-C" >> mk/build.mk
-   echo "GhcWithNativeCodeGen = NO" >> mk/build.mk
    echo "GhcWithInterpreter = NO" >> mk/build.mk
 
    # we just need to build the compiler and utils...
diff --git a/distrib/hc-build b/distrib/hc-build
index 13afaa7adb9..ad39854d9e4 100644
--- a/distrib/hc-build
+++ b/distrib/hc-build
@@ -31,7 +31,6 @@ case "$configopts" in
 cat >>mk/build.mk <<END
 GhcUnregisterised=YES
 GhcWithInterpreter=NO
-GhcWithNativeCodeGen=NO
 GhcLibWays=
 GhcWithSMP=NO
 END
diff --git a/hadrian/src/Oracles/Flag.hs b/hadrian/src/Oracles/Flag.hs
index 2de81cfdd6e..4f88af64325 100644
--- a/hadrian/src/Oracles/Flag.hs
+++ b/hadrian/src/Oracles/Flag.hs
@@ -2,7 +2,7 @@
 
 module Oracles.Flag (
     Flag (..), flag, getFlag, platformSupportsSharedLibs,
-    ghcWithNativeCodeGen, targetSupportsSMP
+    targetSupportsSMP
     ) where
 
 import Hadrian.Oracles.TextFile
@@ -77,10 +77,3 @@ targetSupportsSMP = do
      , ver < ARMv7          -> return False
      | goodArch             -> return True
      | otherwise            -> return False
-
-ghcWithNativeCodeGen :: Action Bool
-ghcWithNativeCodeGen = do
-    goodArch <- anyTargetArch ["i386", "x86_64", "sparc", "powerpc"]
-    badOs    <- anyTargetOs ["ios", "aix"]
-    ghcUnreg <- flag GhcUnregisterised
-    return $ goodArch && not badOs && not ghcUnreg
diff --git a/hadrian/src/Rules/Generate.hs b/hadrian/src/Rules/Generate.hs
index 62a7bbebbc7..e2097d8d795 100644
--- a/hadrian/src/Rules/Generate.hs
+++ b/hadrian/src/Rules/Generate.hs
@@ -315,7 +315,6 @@ generateSettings = do
 
         , ("BigNum backend", getBignumBackend)
         , ("Use interpreter", expr $ yesNo <$> ghcWithInterpreter)
-        , ("Use native code generator", expr $ yesNo <$> ghcWithNativeCodeGen)
         , ("Support SMP", expr $ yesNo <$> targetSupportsSMP)
         , ("RTS ways", unwords . map show <$> getRtsWays)
         , ("Tables next to code", expr $ yesNo <$> flag TablesNextToCode)
diff --git a/includes/ghc.mk b/includes/ghc.mk
index cb95d9089bb..efae7e3a22d 100644
--- a/includes/ghc.mk
+++ b/includes/ghc.mk
@@ -250,7 +250,6 @@ $(includes_SETTINGS) : includes/Makefile | $$(dir $$@)/.
 	@echo
 	@echo ',("bignum backend", "$(BIGNUM_BACKEND)")' >> $@
 	@echo ',("Use interpreter", "$(GhcWithInterpreter)")' >> $@
-	@echo ',("Use native code generator", "$(GhcWithNativeCodeGen)")' >> $@
 	@echo ',("Support SMP", "$(GhcWithSMP)")' >> $@
 	@echo ',("RTS ways", "$(GhcRTSWays)")' >> $@
 	@echo ',("Tables next to code", "$(TablesNextToCode)")' >> $@
diff --git a/libraries/ghc-boot/GHC/Platform.hs b/libraries/ghc-boot/GHC/Platform.hs
index 46387c52a22..326b93f9fab 100644
--- a/libraries/ghc-boot/GHC/Platform.hs
+++ b/libraries/ghc-boot/GHC/Platform.hs
@@ -295,7 +295,6 @@ data PlatformMisc = PlatformMisc
   { -- TODO Recalculate string from richer info?
     platformMisc_targetPlatformString :: String
   , platformMisc_ghcWithInterpreter   :: Bool
-  , platformMisc_ghcWithNativeCodeGen :: Bool
   , platformMisc_ghcWithSMP           :: Bool
   , platformMisc_ghcRTSWays           :: String
   , platformMisc_libFFI               :: Bool
diff --git a/mk/config.mk.in b/mk/config.mk.in
index 9c4cdc95735..4269dec785f 100644
--- a/mk/config.mk.in
+++ b/mk/config.mk.in
@@ -173,19 +173,6 @@ endif
 #
 GhcUnregisterised=@Unregisterised@
 
-# Build a compiler with a native code generator backend
-# (as well as a C backend)
-#
-# Target platforms supported:
-#   i386, powerpc, powerpc64, sparc
-#   IOS is not supported
-ArchSupportsNCG=$(strip $(patsubst $(TargetArch_CPP), YES, $(findstring $(TargetArch_CPP), i386 x86_64 powerpc powerpc64 powerpc64le sparc)))
-OsSupportsNCG=$(strip $(patsubst $(TargetOS_CPP), YES, $(patsubst ios,,$(TargetOS_CPP))))
-
-GhcWithNativeCodeGen := $(strip\
-    $(if $(filter YESYESNO,\
-		  $(OsSupportsNCG)$(ArchSupportsNCG)$(GhcUnregisterised)),YES,NO))
-
 # ArchSupportsSMP should be set iff there is support for that arch in
 # includes/stg/SMP.h
 ifeq "$(TargetArch_CPP)" "arm"
-- 
GitLab