diff options
author | Sylvain Henry <sylvain@haskus.fr> | 2020-07-21 19:15:59 +0200 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2020-07-25 00:45:08 -0400 |
commit | 7721b923d53fb9eb93f80bb93b4c3bd976c05b4c (patch) | |
tree | edc61b1ed9885e442c7327460052f10d1ca589fa | |
parent | 73145d57f961c73b5853da7881d6a21e48e05909 (diff) | |
download | haskell-7721b923d53fb9eb93f80bb93b4c3bd976c05b4c.tar.gz |
Move GHC.Platform into the compiler
Previously it was in ghc-boot so that ghc-pkg could use it. However it
wasn't necessary because ghc-pkg only uses a subset of it: reading
target arch and OS from the settings file. This is now done via
GHC.Platform.ArchOS (was called PlatformMini before).
-rw-r--r-- | compiler/GHC.hs | 6 | ||||
-rw-r--r-- | compiler/GHC/Driver/Pipeline.hs | 1 | ||||
-rw-r--r-- | compiler/GHC/Driver/Session.hs | 16 | ||||
-rw-r--r-- | compiler/GHC/Parser/Header.hs | 4 | ||||
-rw-r--r-- | compiler/GHC/Platform.hs (renamed from libraries/ghc-boot/GHC/Platform.hs) | 212 | ||||
-rw-r--r-- | compiler/GHC/Settings.hs | 1 | ||||
-rw-r--r-- | compiler/GHC/Settings/IO.hs | 41 | ||||
-rw-r--r-- | compiler/GHC/Unit/State.hs | 6 | ||||
-rw-r--r-- | compiler/ghc.cabal.in | 9 | ||||
-rw-r--r-- | ghc/Main.hs | 8 | ||||
-rw-r--r-- | hadrian/src/Rules/Generate.hs | 17 | ||||
-rw-r--r-- | libraries/ghc-boot/GHC/Platform/ArchOS.hs | 152 | ||||
-rw-r--r-- | libraries/ghc-boot/GHC/Settings/Platform.hs | 103 | ||||
-rw-r--r-- | libraries/ghc-boot/GHC/Settings/Utils.hs | 57 | ||||
-rw-r--r-- | libraries/ghc-boot/GHC/UniqueSubdir.hs | 14 | ||||
-rw-r--r-- | libraries/ghc-boot/ghc-boot.cabal.in | 3 | ||||
-rw-r--r-- | libraries/ghc-boot/ghc.mk | 15 | ||||
-rw-r--r-- | utils/ghc-pkg/Main.hs | 21 |
18 files changed, 337 insertions, 349 deletions
diff --git a/compiler/GHC.hs b/compiler/GHC.hs index c7fac76828..22ce5fac18 100644 --- a/compiler/GHC.hs +++ b/compiler/GHC.hs @@ -1683,11 +1683,11 @@ interpretPackageEnv dflags = do where -- Loading environments (by name or by location) - platformArchOs = platformMini (targetPlatform dflags) + archOS = platformArchOS (targetPlatform dflags) namedEnvPath :: String -> MaybeT IO FilePath namedEnvPath name = do - appdir <- versionedAppDir (programName dflags) platformArchOs + appdir <- versionedAppDir (programName dflags) archOS return $ appdir </> "environments" </> name probeEnvName :: String -> MaybeT IO FilePath @@ -1724,7 +1724,7 @@ interpretPackageEnv dflags = do -- e.g. .ghc.environment.x86_64-linux-7.6.3 localEnvFileName :: FilePath - localEnvFileName = ".ghc.environment" <.> versionedFilePath platformArchOs + localEnvFileName = ".ghc.environment" <.> versionedFilePath archOS -- Search for an env file, starting in the current dir and looking upwards. -- Fail if we get to the users home dir or the filesystem root. That is, diff --git a/compiler/GHC/Driver/Pipeline.hs b/compiler/GHC/Driver/Pipeline.hs index 1603c38e71..36010a76af 100644 --- a/compiler/GHC/Driver/Pipeline.hs +++ b/compiler/GHC/Driver/Pipeline.hs @@ -42,6 +42,7 @@ import GHC.Prelude import GHC.Driver.Pipeline.Monad import GHC.Unit.State import GHC.Platform.Ways +import GHC.Platform.ArchOS import GHC.Parser.Header import GHC.Driver.Phases import GHC.SysTools diff --git a/compiler/GHC/Driver/Session.hs b/compiler/GHC/Driver/Session.hs index 2c2c3db7c2..01555dff8f 100644 --- a/compiler/GHC/Driver/Session.hs +++ b/compiler/GHC/Driver/Session.hs @@ -1000,13 +1000,13 @@ opt_i dflags= toolSettings_opt_i $ toolSettings dflags -- | The directory for this version of ghc in the user's app directory -- (typically something like @~/.ghc/x86_64-linux-7.6.3@) -- -versionedAppDir :: String -> PlatformMini -> MaybeT IO FilePath +versionedAppDir :: String -> ArchOS -> MaybeT IO FilePath versionedAppDir appname platform = do -- Make sure we handle the case the HOME isn't set (see #11678) appdir <- tryMaybeT $ getAppUserDataDirectory appname return $ appdir </> versionedFilePath platform -versionedFilePath :: PlatformMini -> FilePath +versionedFilePath :: ArchOS -> FilePath versionedFilePath platform = uniqueSubdir platform -- | The 'GhcMode' tells us whether we're doing multi-module @@ -3633,8 +3633,8 @@ supportedLanguages = map (flagSpecName . snd) languageFlagsDeps supportedLanguageOverlays :: [String] supportedLanguageOverlays = map (flagSpecName . snd) safeHaskellFlagsDeps -supportedExtensions :: PlatformMini -> [String] -supportedExtensions targetPlatformMini = concatMap toFlagSpecNamePair xFlags +supportedExtensions :: ArchOS -> [String] +supportedExtensions (ArchOS _ os) = concatMap toFlagSpecNamePair xFlags where toFlagSpecNamePair flg -- IMPORTANT! Make sure that `ghc --supported-extensions` omits @@ -3645,13 +3645,13 @@ supportedExtensions targetPlatformMini = concatMap toFlagSpecNamePair xFlags | isAIX, flagSpecFlag flg == LangExt.QuasiQuotes = [noName] | otherwise = [name, noName] where - isAIX = platformMini_os targetPlatformMini == OSAIX + isAIX = os == OSAIX noName = "No" ++ name name = flagSpecName flg -supportedLanguagesAndExtensions :: PlatformMini -> [String] -supportedLanguagesAndExtensions targetPlatformMini = - supportedLanguages ++ supportedLanguageOverlays ++ supportedExtensions targetPlatformMini +supportedLanguagesAndExtensions :: ArchOS -> [String] +supportedLanguagesAndExtensions arch_os = + supportedLanguages ++ supportedLanguageOverlays ++ supportedExtensions arch_os -- | These -X<blah> flags cannot be reversed with -XNo<blah> languageFlagsDeps :: [(Deprecation, FlagSpec Language)] diff --git a/compiler/GHC/Parser/Header.hs b/compiler/GHC/Parser/Header.hs index bfdeb71631..dfc7aec2ad 100644 --- a/compiler/GHC/Parser/Header.hs +++ b/compiler/GHC/Parser/Header.hs @@ -316,7 +316,7 @@ checkExtension dflags (L l ext) else unsupportedExtnError dflags l ext' where ext' = unpackFS ext - supported = supportedLanguagesAndExtensions $ platformMini $ targetPlatform dflags + supported = supportedLanguagesAndExtensions $ platformArchOS $ targetPlatform dflags languagePragParseError :: DynFlags -> SrcSpan -> a languagePragParseError dflags loc = @@ -332,7 +332,7 @@ unsupportedExtnError dflags loc unsup = text "Unsupported extension: " <> text unsup $$ if null suggestions then Outputable.empty else text "Perhaps you meant" <+> quotedListWithOr (map text suggestions) where - supported = supportedLanguagesAndExtensions $ platformMini $ targetPlatform dflags + supported = supportedLanguagesAndExtensions $ platformArchOS $ targetPlatform dflags suggestions = fuzzyMatch unsup supported diff --git a/libraries/ghc-boot/GHC/Platform.hs b/compiler/GHC/Platform.hs index 9191dda44f..56a18e9c88 100644 --- a/libraries/ghc-boot/GHC/Platform.hs +++ b/compiler/GHC/Platform.hs @@ -1,14 +1,13 @@ -{-# LANGUAGE LambdaCase, ScopedTypeVariables #-} +{-# LANGUAGE ScopedTypeVariables #-} --- | A description of the platform we're compiling for. --- +-- | Platform description module GHC.Platform - ( PlatformMini(..) + ( Platform (..) , PlatformWordSize(..) , PlatformConstants(..) - , Platform(..) , platformArch , platformOS + , ArchOS(..) , Arch(..) , OS(..) , ArmISA(..) @@ -30,34 +29,26 @@ module GHC.Platform , platformInIntRange , platformInWordRange , PlatformMisc(..) - , stringEncodeArch - , stringEncodeOS , SseVersion (..) , BmiVersion (..) ) where import Prelude -- See Note [Why do we import Prelude here?] -import GHC.Read -import GHC.ByteOrder (ByteOrder(..)) -import GHC.Platform.Constants + import Data.Word import Data.Int --- | Contains the bare-bones arch and os information. This isn't enough for --- code gen, but useful for tasks where we can fall back upon the host --- platform, as this is all we know about the host platform. -data PlatformMini - = PlatformMini - { platformMini_arch :: Arch - , platformMini_os :: OS - } - deriving (Read, Show, Eq) +import GHC.Read +import GHC.ByteOrder (ByteOrder(..)) +import GHC.Platform.Constants +import GHC.Platform.ArchOS --- | Contains enough information for the native code generator to emit --- code for this platform. +-- | Platform description +-- +-- This is used to describe platforms so that we can generate code for them. data Platform = Platform - { platformMini :: !PlatformMini + { platformArchOS :: !ArchOS -- ^ Architecture and OS , platformWordSize :: !PlatformWordSize -- ^ Word size , platformByteOrder :: !ByteOrder -- ^ Byte order (endianness) , platformUnregisterised :: !Bool @@ -101,152 +92,21 @@ platformWordSizeInBytes p = platformWordSizeInBits :: Platform -> Int platformWordSizeInBits p = platformWordSizeInBytes p * 8 --- | Legacy accessor +-- | Platform architecture platformArch :: Platform -> Arch -platformArch = platformMini_arch . platformMini +platformArch platform = case platformArchOS platform of + ArchOS arch _ -> arch --- | Legacy accessor +-- | Platform OS platformOS :: Platform -> OS -platformOS = platformMini_os . platformMini - --- | Architectures that the native code generator knows about. --- TODO: It might be nice to extend these constructors with information --- about what instruction set extensions an architecture might support. --- -data Arch - = ArchUnknown - | ArchX86 - | ArchX86_64 - | ArchPPC - | ArchPPC_64 - { ppc_64ABI :: PPC_64ABI - } - | ArchS390X - | ArchSPARC - | ArchSPARC64 - | ArchARM - { armISA :: ArmISA - , armISAExt :: [ArmISAExt] - , armABI :: ArmABI - } - | ArchARM64 - | ArchAlpha - | ArchMipseb - | ArchMipsel - | ArchJavaScript - deriving (Read, Show, Eq) - --- Note [Platform Syntax] --- ~~~~~~~~~~~~~~~~~~~~~~ --- There is a very loose encoding of platforms shared by many tools we are --- encoding to here. GNU Config (http://git.savannah.gnu.org/cgit/config.git), --- and LLVM's http://llvm.org/doxygen/classllvm_1_1Triple.html are perhaps the --- most definitional parsers. The basic syntax is a list of '-'-separated --- components. The Unix 'uname' command syntax is related but briefer. --- --- Those two parsers are quite forgiving, and even the 'config.sub' --- normalization is forgiving too. The "best" way to encode a platform is --- therefore somewhat a matter of taste. --- --- The 'stringEncode*' functions here convert each part of GHC's structured --- notion of a platform into one dash-separated component. - --- | See Note [Platform Syntax]. -stringEncodeArch :: Arch -> String -stringEncodeArch = \case - ArchUnknown -> "unknown" - ArchX86 -> "i386" - ArchX86_64 -> "x86_64" - ArchPPC -> "powerpc" - ArchPPC_64 { ppc_64ABI = abi } -> case abi of - ELF_V1 -> "powerpc64" - ELF_V2 -> "powerpc64le" - ArchS390X -> "s390x" - ArchSPARC -> "sparc" - ArchSPARC64 -> "sparc64" - ArchARM { armISA = isa, armISAExt = _, armABI = _ } -> "arm" ++ vsuf - where - vsuf = case isa of - ARMv5 -> "v5" - ARMv6 -> "v6" - ARMv7 -> "v7" - ArchARM64 -> "aarch64" - ArchAlpha -> "alpha" - ArchMipseb -> "mipseb" - ArchMipsel -> "mipsel" - ArchJavaScript -> "js" +platformOS platform = case platformArchOS platform of + ArchOS _ os -> os isARM :: Arch -> Bool isARM (ArchARM {}) = True isARM ArchARM64 = True isARM _ = False --- | Operating systems that the native code generator knows about. --- Having OSUnknown should produce a sensible default, but no promises. -data OS - = OSUnknown - | OSLinux - | OSDarwin - | OSSolaris2 - | OSMinGW32 - | OSFreeBSD - | OSDragonFly - | OSOpenBSD - | OSNetBSD - | OSKFreeBSD - | OSHaiku - | OSQNXNTO - | OSAIX - | OSHurd - deriving (Read, Show, Eq) - --- | See Note [Platform Syntax]. -stringEncodeOS :: OS -> String -stringEncodeOS = \case - OSUnknown -> "unknown" - OSLinux -> "linux" - OSDarwin -> "darwin" - OSSolaris2 -> "solaris2" - OSMinGW32 -> "mingw32" - OSFreeBSD -> "freebsd" - OSDragonFly -> "dragonfly" - OSOpenBSD -> "openbsd" - OSNetBSD -> "netbsd" - OSKFreeBSD -> "kfreebsdgnu" - OSHaiku -> "haiku" - OSQNXNTO -> "nto-qnx" - OSAIX -> "aix" - OSHurd -> "hurd" - --- | ARM Instruction Set Architecture, Extensions and ABI --- -data ArmISA - = ARMv5 - | ARMv6 - | ARMv7 - deriving (Read, Show, Eq) - -data ArmISAExt - = VFPv2 - | VFPv3 - | VFPv3D16 - | NEON - | IWMMX2 - deriving (Read, Show, Eq) - -data ArmABI - = SOFT - | SOFTFP - | HARD - deriving (Read, Show, Eq) - --- | PowerPC 64-bit ABI --- -data PPC_64ABI - = ELF_V1 - | ELF_V2 - deriving (Read, Show, Eq) - -- | This predicate tells us whether the platform is 32-bit. target32Bit :: Platform -> Bool target32Bit p = @@ -291,23 +151,6 @@ osSubsectionsViaSymbols :: OS -> Bool osSubsectionsViaSymbols OSDarwin = True osSubsectionsViaSymbols _ = False --- | Platform-specific settings formerly hard-coded in Config.hs. --- --- These should probably be all be triaged whether they can be computed from --- other settings or belong in another another place (like 'Platform' above). -data PlatformMisc = PlatformMisc - { -- TODO Recalculate string from richer info? - platformMisc_targetPlatformString :: String - , platformMisc_ghcWithInterpreter :: Bool - , platformMisc_ghcWithSMP :: Bool - , platformMisc_ghcRTSWays :: String - , platformMisc_libFFI :: Bool - , platformMisc_ghcThreaded :: Bool - , platformMisc_ghcDebugged :: Bool - , platformMisc_ghcRtsWithLibdw :: Bool - , platformMisc_llvmTarget :: String - } - -- | Minimum representable Int value for the given platform platformMinInt :: Platform -> Integer platformMinInt p = case platformWordSize p of @@ -354,3 +197,20 @@ data BmiVersion | BMI2 deriving (Eq, Ord) + +-- | Platform-specific settings formerly hard-coded in Config.hs. +-- +-- These should probably be all be triaged whether they can be computed from +-- other settings or belong in another another place (like 'Platform' above). +data PlatformMisc = PlatformMisc + { -- TODO Recalculate string from richer info? + platformMisc_targetPlatformString :: String + , platformMisc_ghcWithInterpreter :: Bool + , platformMisc_ghcWithSMP :: Bool + , platformMisc_ghcRTSWays :: String + , platformMisc_libFFI :: Bool + , platformMisc_ghcThreaded :: Bool + , platformMisc_ghcDebugged :: Bool + , platformMisc_ghcRtsWithLibdw :: Bool + , platformMisc_llvmTarget :: String + } diff --git a/compiler/GHC/Settings.hs b/compiler/GHC/Settings.hs index 12ad3ce94b..49a2018252 100644 --- a/compiler/GHC/Settings.hs +++ b/compiler/GHC/Settings.hs @@ -8,7 +8,6 @@ module GHC.Settings , GhcNameVersion (..) , Platform (..) , PlatformMisc (..) - , PlatformMini (..) -- * Accessors , sProgramName , sProjectVersion diff --git a/compiler/GHC/Settings/IO.hs b/compiler/GHC/Settings/IO.hs index c4e47618d2..d1ec388195 100644 --- a/compiler/GHC/Settings/IO.hs +++ b/compiler/GHC/Settings/IO.hs @@ -11,7 +11,6 @@ module GHC.Settings.IO import GHC.Prelude -import GHC.Settings.Platform import GHC.Settings.Utils import GHC.Settings.Config @@ -71,12 +70,12 @@ initSettings top_dir = do -- just partially applying those functions and throwing 'Left's; they're -- written in a very portable style to keep ghc-boot light. let getSetting key = either pgmError pure $ - getFilePathSetting0 top_dir settingsFile mySettings key + getRawFilePathSetting top_dir settingsFile mySettings key getToolSetting :: String -> ExceptT SettingsError m String getToolSetting key = expandToolDir mtool_dir <$> getSetting key getBooleanSetting :: String -> ExceptT SettingsError m Bool getBooleanSetting key = either pgmError pure $ - getBooleanSetting0 settingsFile mySettings key + getRawBooleanSetting settingsFile mySettings key targetPlatformString <- getSetting "target platform string" myExtraGccViaCFlags <- getSetting "GCC extra via C opts" -- On Windows, mingw is distributed with GHC, @@ -228,3 +227,39 @@ initSettings top_dir = do , sRawSettings = settingsList } + +getTargetPlatform + :: FilePath -- ^ Settings filepath (for error messages) + -> RawSettings -- ^ Raw settings file contents + -> PlatformConstants -- ^ Platform constants + -> Either String Platform +getTargetPlatform settingsFile settings constants = do + let + getBooleanSetting = getRawBooleanSetting settingsFile settings + readSetting :: (Show a, Read a) => String -> Either String a + readSetting = readRawSetting settingsFile settings + + targetArchOS <- getTargetArchOS settingsFile settings + targetWordSize <- readSetting "target word size" + targetWordBigEndian <- getBooleanSetting "target word big endian" + targetLeadingUnderscore <- getBooleanSetting "Leading underscore" + targetUnregisterised <- getBooleanSetting "Unregisterised" + targetHasGnuNonexecStack <- getBooleanSetting "target has GNU nonexec stack" + targetHasIdentDirective <- getBooleanSetting "target has .ident directive" + targetHasSubsectionsViaSymbols <- getBooleanSetting "target has subsections via symbols" + crossCompiling <- getBooleanSetting "cross compiling" + tablesNextToCode <- getBooleanSetting "Tables next to code" + + pure $ Platform + { platformArchOS = targetArchOS + , platformWordSize = targetWordSize + , platformByteOrder = if targetWordBigEndian then BigEndian else LittleEndian + , platformUnregisterised = targetUnregisterised + , platformHasGnuNonexecStack = targetHasGnuNonexecStack + , platformHasIdentDirective = targetHasIdentDirective + , platformHasSubsectionsViaSymbols = targetHasSubsectionsViaSymbols + , platformIsCrossCompiling = crossCompiling + , platformLeadingUnderscore = targetLeadingUnderscore + , platformTablesNextToCode = tablesNextToCode + , platformConstants = constants + } diff --git a/compiler/GHC/Unit/State.hs b/compiler/GHC/Unit/State.hs index fb50966195..93c0b86dc8 100644 --- a/compiler/GHC/Unit/State.hs +++ b/compiler/GHC/Unit/State.hs @@ -314,7 +314,7 @@ instance Monoid UnitVisibility where -- | Unit configuration data UnitConfig = UnitConfig - { unitConfigPlatformArchOs :: !PlatformMini -- ^ Platform + { unitConfigPlatformArchOS :: !ArchOS -- ^ Platform arch and OS , unitConfigWays :: !(Set Way) -- ^ Ways to use , unitConfigProgramName :: !String -- ^ Name of the compiler (e.g. "GHC", "GHCJS"). Used to fetch environment @@ -356,7 +356,7 @@ initUnitConfig dflags = | otherwise = filter (/= homeUnitId dflags) [baseUnitId, rtsUnitId] in UnitConfig - { unitConfigPlatformArchOs = platformMini (targetPlatform dflags) + { unitConfigPlatformArchOS = platformArchOS (targetPlatform dflags) , unitConfigProgramName = programName dflags , unitConfigWays = ways dflags @@ -646,7 +646,7 @@ getUnitDbRefs cfg = do resolveUnitDatabase :: UnitConfig -> PkgDbRef -> IO (Maybe FilePath) resolveUnitDatabase cfg GlobalPkgDb = return $ Just (unitConfigGlobalDB cfg) resolveUnitDatabase cfg UserPkgDb = runMaybeT $ do - dir <- versionedAppDir (unitConfigProgramName cfg) (unitConfigPlatformArchOs cfg) + dir <- versionedAppDir (unitConfigProgramName cfg) (unitConfigPlatformArchOS cfg) let pkgconf = dir </> unitConfigDBName cfg exist <- tryMaybeT $ doesDirectoryExist pkgconf if exist then return pkgconf else mzero diff --git a/compiler/ghc.cabal.in b/compiler/ghc.cabal.in index 5c153817e7..efa45c89e4 100644 --- a/compiler/ghc.cabal.in +++ b/compiler/ghc.cabal.in @@ -181,8 +181,6 @@ Library GHC.Driver.Monad GHC.Driver.Hooks GHC.Driver.Flags - GHC.Platform.Ways - GHC.Platform.Profile GHC.Types.Id GHC.Types.Id.Info GHC.Core.Predicate @@ -258,6 +256,9 @@ Library GHC.Cmm.Ppr.Decl GHC.Cmm.Ppr.Expr GHC.Data.Bitmap + GHC.Platform + GHC.Platform.Ways + GHC.Platform.Profile GHC.Platform.Regs GHC.Platform.ARM GHC.Platform.ARM64 @@ -566,6 +567,10 @@ Library GHC.Cmm.Dataflow.Graph GHC.Cmm.Dataflow.Label + reexported-modules: + GHC.Platform.ArchOS + GHC.Platform.Host + Exposed-Modules: GHC.CmmToAsm GHC.CmmToAsm.Reg.Target diff --git a/ghc/Main.hs b/ghc/Main.hs index 41435af878..fa6608761d 100644 --- a/ghc/Main.hs +++ b/ghc/Main.hs @@ -792,16 +792,16 @@ showSupportedExtensions m_top_dir = do Nothing -> throwE $ SettingsError_MissingData "Could not find the top directory, missing -B flag" Just dir -> pure dir initSettings top_dir - targetPlatformMini <- case res of - Right s -> pure $ platformMini $ sTargetPlatform s + arch_os <- case res of + Right s -> pure $ platformArchOS $ sTargetPlatform s Left (SettingsError_MissingData msg) -> do hPutStrLn stderr $ "WARNING: " ++ show msg hPutStrLn stderr $ "cannot know target platform so guessing target == host (native compiler)." - pure cHostPlatformMini + pure hostPlatformArchOS Left (SettingsError_BadData msg) -> do hPutStrLn stderr msg exitWith $ ExitFailure 1 - mapM_ putStrLn $ supportedLanguagesAndExtensions targetPlatformMini + mapM_ putStrLn $ supportedLanguagesAndExtensions arch_os showVersion :: IO () showVersion = putStrLn (cProjectName ++ ", version " ++ cProjectVersion) diff --git a/hadrian/src/Rules/Generate.hs b/hadrian/src/Rules/Generate.hs index 98ea2bd353..7a51814b07 100644 --- a/hadrian/src/Rules/Generate.hs +++ b/hadrian/src/Rules/Generate.hs @@ -474,17 +474,14 @@ generatePlatformHostHs = do return $ unlines [ "module GHC.Platform.Host where" , "" - , "import GHC.Platform" + , "import GHC.Platform.ArchOS" , "" - , "cHostPlatformArch :: Arch" - , "cHostPlatformArch = " ++ cHostPlatformArch + , "hostPlatformArch :: Arch" + , "hostPlatformArch = " ++ cHostPlatformArch , "" - , "cHostPlatformOS :: OS" - , "cHostPlatformOS = " ++ cHostPlatformOS + , "hostPlatformOS :: OS" + , "hostPlatformOS = " ++ cHostPlatformOS , "" - , "cHostPlatformMini :: PlatformMini" - , "cHostPlatformMini = PlatformMini" - , " { platformMini_arch = cHostPlatformArch" - , " , platformMini_os = cHostPlatformOS" - , " }" + , "hostPlatformArchOS :: ArchOS" + , "hostPlatformArchOS = ArchOS hostPlatformArch hostPlatformOS" ] diff --git a/libraries/ghc-boot/GHC/Platform/ArchOS.hs b/libraries/ghc-boot/GHC/Platform/ArchOS.hs new file mode 100644 index 0000000000..bd3ef5f4cc --- /dev/null +++ b/libraries/ghc-boot/GHC/Platform/ArchOS.hs @@ -0,0 +1,152 @@ +{-# LANGUAGE LambdaCase, ScopedTypeVariables #-} + +-- | Platform architecture and OS +-- +-- We need it in ghc-boot because ghc-pkg needs it. +module GHC.Platform.ArchOS + ( ArchOS(..) + , Arch(..) + , OS(..) + , ArmISA(..) + , ArmISAExt(..) + , ArmABI(..) + , PPC_64ABI(..) + , stringEncodeArch + , stringEncodeOS + ) +where + +import Prelude -- See Note [Why do we import Prelude here?] + +-- | Platform architecture and OS. +data ArchOS + = ArchOS Arch OS + deriving (Read, Show, Eq) + +-- | Architectures +-- +-- TODO: It might be nice to extend these constructors with information about +-- what instruction set extensions an architecture might support. +-- +data Arch + = ArchUnknown + | ArchX86 + | ArchX86_64 + | ArchPPC + | ArchPPC_64 PPC_64ABI + | ArchS390X + | ArchSPARC + | ArchSPARC64 + | ArchARM ArmISA [ArmISAExt] ArmABI + | ArchARM64 + | ArchAlpha + | ArchMipseb + | ArchMipsel + | ArchJavaScript + deriving (Read, Show, Eq) + +-- | ARM Instruction Set Architecture +data ArmISA + = ARMv5 + | ARMv6 + | ARMv7 + deriving (Read, Show, Eq) + +-- | ARM extensions +data ArmISAExt + = VFPv2 + | VFPv3 + | VFPv3D16 + | NEON + | IWMMX2 + deriving (Read, Show, Eq) + +-- | ARM ABI +data ArmABI + = SOFT + | SOFTFP + | HARD + deriving (Read, Show, Eq) + +-- | PowerPC 64-bit ABI +data PPC_64ABI + = ELF_V1 + | ELF_V2 + deriving (Read, Show, Eq) + +-- | Operating systems. +-- +-- Using OSUnknown to generate code should produce a sensible default, but no +-- promises. +data OS + = OSUnknown + | OSLinux + | OSDarwin + | OSSolaris2 + | OSMinGW32 + | OSFreeBSD + | OSDragonFly + | OSOpenBSD + | OSNetBSD + | OSKFreeBSD + | OSHaiku + | OSQNXNTO + | OSAIX + | OSHurd + deriving (Read, Show, Eq) + + +-- Note [Platform Syntax] +-- ~~~~~~~~~~~~~~~~~~~~~~ +-- +-- There is a very loose encoding of platforms shared by many tools we are +-- encoding to here. GNU Config (http://git.savannah.gnu.org/cgit/config.git), +-- and LLVM's http://llvm.org/doxygen/classllvm_1_1Triple.html are perhaps the +-- most definitional parsers. The basic syntax is a list of '-'-separated +-- components. The Unix 'uname' command syntax is related but briefer. +-- +-- Those two parsers are quite forgiving, and even the 'config.sub' +-- normalization is forgiving too. The "best" way to encode a platform is +-- therefore somewhat a matter of taste. +-- +-- The 'stringEncode*' functions here convert each part of GHC's structured +-- notion of a platform into one dash-separated component. + +-- | See Note [Platform Syntax]. +stringEncodeArch :: Arch -> String +stringEncodeArch = \case + ArchUnknown -> "unknown" + ArchX86 -> "i386" + ArchX86_64 -> "x86_64" + ArchPPC -> "powerpc" + ArchPPC_64 ELF_V1 -> "powerpc64" + ArchPPC_64 ELF_V2 -> "powerpc64le" + ArchS390X -> "s390x" + ArchSPARC -> "sparc" + ArchSPARC64 -> "sparc64" + ArchARM ARMv5 _ _ -> "armv5" + ArchARM ARMv6 _ _ -> "armv6" + ArchARM ARMv7 _ _ -> "armv7" + ArchARM64 -> "aarch64" + ArchAlpha -> "alpha" + ArchMipseb -> "mipseb" + ArchMipsel -> "mipsel" + ArchJavaScript -> "js" + +-- | See Note [Platform Syntax]. +stringEncodeOS :: OS -> String +stringEncodeOS = \case + OSUnknown -> "unknown" + OSLinux -> "linux" + OSDarwin -> "darwin" + OSSolaris2 -> "solaris2" + OSMinGW32 -> "mingw32" + OSFreeBSD -> "freebsd" + OSDragonFly -> "dragonfly" + OSOpenBSD -> "openbsd" + OSNetBSD -> "netbsd" + OSKFreeBSD -> "kfreebsdgnu" + OSHaiku -> "haiku" + OSQNXNTO -> "nto-qnx" + OSAIX -> "aix" + OSHurd -> "hurd" diff --git a/libraries/ghc-boot/GHC/Settings/Platform.hs b/libraries/ghc-boot/GHC/Settings/Platform.hs deleted file mode 100644 index 95278da76e..0000000000 --- a/libraries/ghc-boot/GHC/Settings/Platform.hs +++ /dev/null @@ -1,103 +0,0 @@ --- Note [Settings file] --- ~~~~~~~~~~~~~~~~~~~~ --- --- GHC has a file, `${top_dir}/settings`, which is the main source of run-time --- configuration. ghc-pkg needs just a little bit of it: the target platform CPU --- arch and OS. It uses that to figure out what subdirectory of `~/.ghc` is --- associated with the current version/target. --- --- This module has just enough code to read key value pairs from the settings --- file, and read the target platform from those pairs. --- --- The "0" suffix is because the caller will partially apply it, and that will --- in turn be used a few more times. -module GHC.Settings.Platform where - -import Prelude -- See Note [Why do we import Prelude here?] - -import GHC.BaseDir -import GHC.Platform -import GHC.Settings.Utils - -import Data.Map (Map) -import qualified Data.Map as Map - ------------------------------------------------------------------------------ --- parts of settings file - -getTargetPlatform - :: FilePath -- ^ Settings filepath (for error messages) - -> RawSettings -- ^ Raw settings file contents - -> PlatformConstants -- ^ Platform constants - -> Either String Platform -getTargetPlatform settingsFile mySettings constants = do - let - getBooleanSetting = getBooleanSetting0 settingsFile mySettings - readSetting :: (Show a, Read a) => String -> Either String a - readSetting = readSetting0 settingsFile mySettings - - targetArch <- readSetting "target arch" - targetOS <- readSetting "target os" - targetWordSize <- readSetting "target word size" - targetWordBigEndian <- getBooleanSetting "target word big endian" - targetLeadingUnderscore <- getBooleanSetting "Leading underscore" - targetUnregisterised <- getBooleanSetting "Unregisterised" - targetHasGnuNonexecStack <- getBooleanSetting "target has GNU nonexec stack" - targetHasIdentDirective <- getBooleanSetting "target has .ident directive" - targetHasSubsectionsViaSymbols <- getBooleanSetting "target has subsections via symbols" - crossCompiling <- getBooleanSetting "cross compiling" - tablesNextToCode <- getBooleanSetting "Tables next to code" - - pure $ Platform - { platformMini = PlatformMini - { platformMini_arch = targetArch - , platformMini_os = targetOS - } - , platformWordSize = targetWordSize - , platformByteOrder = if targetWordBigEndian then BigEndian else LittleEndian - , platformUnregisterised = targetUnregisterised - , platformHasGnuNonexecStack = targetHasGnuNonexecStack - , platformHasIdentDirective = targetHasIdentDirective - , platformHasSubsectionsViaSymbols = targetHasSubsectionsViaSymbols - , platformIsCrossCompiling = crossCompiling - , platformLeadingUnderscore = targetLeadingUnderscore - , platformTablesNextToCode = tablesNextToCode - , platformConstants = constants - } - ------------------------------------------------------------------------------ --- settings file helpers - -type RawSettings = Map String String - --- | See Note [Settings file] for "0" suffix -getSetting0 - :: FilePath -> RawSettings -> String -> Either String String -getSetting0 settingsFile mySettings key = case Map.lookup key mySettings of - Just xs -> Right xs - Nothing -> Left $ "No entry for " ++ show key ++ " in " ++ show settingsFile - --- | See Note [Settings file] for "0" suffix -getFilePathSetting0 - :: FilePath -> FilePath -> RawSettings -> String -> Either String String -getFilePathSetting0 top_dir settingsFile mySettings key = - expandTopDir top_dir <$> getSetting0 settingsFile mySettings key - --- | See Note [Settings file] for "0" suffix -getBooleanSetting0 - :: FilePath -> RawSettings -> String -> Either String Bool -getBooleanSetting0 settingsFile mySettings key = do - rawValue <- getSetting0 settingsFile mySettings key - case rawValue of - "YES" -> Right True - "NO" -> Right False - xs -> Left $ "Bad value for " ++ show key ++ ": " ++ show xs - --- | See Note [Settings file] for "0" suffix -readSetting0 - :: (Show a, Read a) => FilePath -> RawSettings -> String -> Either String a -readSetting0 settingsFile mySettings key = case Map.lookup key mySettings of - Just xs -> case maybeRead xs of - Just v -> Right v - Nothing -> Left $ "Failed to read " ++ show key ++ " value " ++ show xs - Nothing -> Left $ "No entry for " ++ show key ++ " in " ++ show settingsFile diff --git a/libraries/ghc-boot/GHC/Settings/Utils.hs b/libraries/ghc-boot/GHC/Settings/Utils.hs index 1f1cd67030..4ccbbf23b6 100644 --- a/libraries/ghc-boot/GHC/Settings/Utils.hs +++ b/libraries/ghc-boot/GHC/Settings/Utils.hs @@ -3,6 +3,11 @@ module GHC.Settings.Utils where import Prelude -- See Note [Why do we import Prelude here?] import Data.Char (isSpace) +import Data.Map (Map) +import qualified Data.Map as Map + +import GHC.BaseDir +import GHC.Platform.ArchOS maybeRead :: Read a => String -> Maybe a maybeRead str = case reads str of @@ -13,3 +18,55 @@ maybeReadFuzzy :: Read a => String -> Maybe a maybeReadFuzzy str = case reads str of [(x, s)] | all isSpace s -> Just x _ -> Nothing + + +-- Note [Settings file] +-- ~~~~~~~~~~~~~~~~~~~~ +-- +-- GHC has a file, `${top_dir}/settings`, which is the main source of run-time +-- configuration. ghc-pkg needs just a little bit of it: the target platform CPU +-- arch and OS. It uses that to figure out what subdirectory of `~/.ghc` is +-- associated with the current version/target platform. +-- +-- This module has just enough code to read key value pairs from the settings +-- file, and read the target platform from those pairs. + +type RawSettings = Map String String + +-- | Read target Arch/OS from the settings +getTargetArchOS + :: FilePath -- ^ Settings filepath (for error messages) + -> RawSettings -- ^ Raw settings file contents + -> Either String ArchOS +getTargetArchOS settingsFile settings = + ArchOS <$> readRawSetting settingsFile settings "target arch" + <*> readRawSetting settingsFile settings "target os" + + +getRawSetting + :: FilePath -> RawSettings -> String -> Either String String +getRawSetting settingsFile settings key = case Map.lookup key settings of + Just xs -> Right xs + Nothing -> Left $ "No entry for " ++ show key ++ " in " ++ show settingsFile + +getRawFilePathSetting + :: FilePath -> FilePath -> RawSettings -> String -> Either String String +getRawFilePathSetting top_dir settingsFile settings key = + expandTopDir top_dir <$> getRawSetting settingsFile settings key + +getRawBooleanSetting + :: FilePath -> RawSettings -> String -> Either String Bool +getRawBooleanSetting settingsFile settings key = do + rawValue <- getRawSetting settingsFile settings key + case rawValue of + "YES" -> Right True + "NO" -> Right False + xs -> Left $ "Bad value for " ++ show key ++ ": " ++ show xs + +readRawSetting + :: (Show a, Read a) => FilePath -> RawSettings -> String -> Either String a +readRawSetting settingsFile settings key = case Map.lookup key settings of + Just xs -> case maybeRead xs of + Just v -> Right v + Nothing -> Left $ "Failed to read " ++ show key ++ " value " ++ show xs + Nothing -> Left $ "No entry for " ++ show key ++ " in " ++ show settingsFile diff --git a/libraries/ghc-boot/GHC/UniqueSubdir.hs b/libraries/ghc-boot/GHC/UniqueSubdir.hs index b59fdc43ce..5ffaafefd8 100644 --- a/libraries/ghc-boot/GHC/UniqueSubdir.hs +++ b/libraries/ghc-boot/GHC/UniqueSubdir.hs @@ -6,19 +6,15 @@ import Prelude -- See Note [Why do we import Prelude here?] import Data.List (intercalate) -import GHC.Platform +import GHC.Platform.ArchOS import GHC.Version (cProjectVersion) -- | A filepath like @x86_64-linux-7.6.3@ with the platform string to use when -- constructing platform-version-dependent files that need to co-exist. --- --- 'ghc-pkg' falls back on the host platform if the settings file is missing, --- and so needs this since we don't have information about the host platform in --- as much detail as 'Platform', so we use 'PlatformMini' instead. -uniqueSubdir :: PlatformMini -> FilePath -uniqueSubdir archOs = intercalate "-" - [ stringEncodeArch $ platformMini_arch archOs - , stringEncodeOS $ platformMini_os archOs +uniqueSubdir :: ArchOS -> FilePath +uniqueSubdir (ArchOS arch os) = intercalate "-" + [ stringEncodeArch arch + , stringEncodeOS os , cProjectVersion ] -- NB: This functionality is reimplemented in Cabal, so if you diff --git a/libraries/ghc-boot/ghc-boot.cabal.in b/libraries/ghc-boot/ghc-boot.cabal.in index aed65d8f0a..e320a5725f 100644 --- a/libraries/ghc-boot/ghc-boot.cabal.in +++ b/libraries/ghc-boot/ghc-boot.cabal.in @@ -43,10 +43,9 @@ Library GHC.Serialized GHC.ForeignSrcLang GHC.HandleEncoding - GHC.Platform + GHC.Platform.ArchOS GHC.Platform.Host GHC.Platform.Constants - GHC.Settings.Platform GHC.Settings.Utils GHC.UniqueSubdir GHC.Version diff --git a/libraries/ghc-boot/ghc.mk b/libraries/ghc-boot/ghc.mk index 9c5d695d8c..d183ccc501 100644 --- a/libraries/ghc-boot/ghc.mk +++ b/libraries/ghc-boot/ghc.mk @@ -42,17 +42,14 @@ libraries/ghc-boot/dist-install/build/GHC/Platform/Host.hs: mk/project.mk | $$(d @echo >> $@ @echo 'import GHC.Platform' >> $@ @echo >> $@ - @echo 'cHostPlatformArch :: Arch' >> $@ - @echo 'cHostPlatformArch = $(HaskellHostArch)' >> $@ + @echo 'hostPlatformArch :: Arch' >> $@ + @echo 'hostPlatformArch = $(HaskellHostArch)' >> $@ @echo >> $@ - @echo 'cHostPlatformOS :: OS' >> $@ - @echo 'cHostPlatformOS = $(HaskellHostOs)' >> $@ + @echo 'hostPlatformOS :: OS' >> $@ + @echo 'hostPlatformOS = $(HaskellHostOs)' >> $@ @echo >> $@ - @echo 'cHostPlatformMini :: PlatformMini' >> $@ - @echo 'cHostPlatformMini = PlatformMini' >> $@ - @echo ' { platformMini_arch = cHostPlatformArch' >> $@ - @echo ' , platformMini_os = cHostPlatformOS' >> $@ - @echo ' }' >> $@ + @echo 'hostPlatformArchOS :: ArchOS' >> $@ + @echo 'hostPlatformArchOS = ArchOS hostPlatformArch hostPlatformOS' >> $@ @echo done. libraries/ghc-boot/dist-boot/package-data.mk: \ diff --git a/utils/ghc-pkg/Main.hs b/utils/ghc-pkg/Main.hs index 91637f5fab..3c7a65ddf6 100644 --- a/utils/ghc-pkg/Main.hs +++ b/utils/ghc-pkg/Main.hs @@ -34,10 +34,8 @@ import qualified GHC.Unit.Database as GhcPkg import GHC.Unit.Database import GHC.HandleEncoding import GHC.BaseDir (getBaseDir) -import GHC.Settings.Platform (getTargetPlatform) -import GHC.Settings.Utils (maybeReadFuzzy) -import GHC.Platform (platformMini) -import GHC.Platform.Host (cHostPlatformMini) +import GHC.Settings.Utils (getTargetArchOS, maybeReadFuzzy) +import GHC.Platform.Host (hostPlatformArchOS) import GHC.UniqueSubdir (uniqueSubdir) import GHC.Version ( cProjectVersion ) import qualified Distribution.Simple.PackageIndex as PackageIndex @@ -643,13 +641,12 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do Right appdir -> do -- See Note [Settings File] about this file, and why we need GHC to share it with us. let settingsFile = top_dir </> "settings" - let constantsFile = top_dir </> "platformConstants" exists_settings_file <- doesFileExist settingsFile - targetPlatformMini <- case exists_settings_file of + targetArchOS <- case exists_settings_file of False -> do warn $ "WARNING: settings file doesn't exist " ++ show settingsFile warn "cannot know target platform so guessing target == host (native compiler)." - pure cHostPlatformMini + pure hostPlatformArchOS True -> do settingsStr <- readFile settingsFile mySettings <- case maybeReadFuzzy settingsStr of @@ -657,14 +654,10 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do -- It's excusable to not have a settings file (for now at -- least) but completely inexcusable to have a malformed one. Nothing -> die $ "Can't parse settings file " ++ show settingsFile - constantsStr <- readFile constantsFile - constants <- case maybeReadFuzzy constantsStr of - Just s -> pure s - Nothing -> die $ "Can't parse platform constants file " ++ show constantsFile - case getTargetPlatform settingsFile mySettings constants of - Right platform -> pure $ platformMini platform + case getTargetArchOS settingsFile mySettings of + Right archOS -> pure archOS Left e -> die e - let subdir = uniqueSubdir targetPlatformMini + let subdir = uniqueSubdir targetArchOS dir = appdir </> subdir r <- lookForPackageDBIn dir case r of |