summaryrefslogtreecommitdiff
path: root/compiler/main
diff options
context:
space:
mode:
authorSylvain Henry <sylvain@haskus.fr>2020-04-05 17:39:13 +0200
committerSylvain Henry <sylvain@haskus.fr>2020-04-18 20:04:46 +0200
commit15312bbb53f247c9ed2c5cf75100a9f44c1c7227 (patch)
tree8306dcc04a5b7c82464f903044dfdd589e7fdcd7 /compiler/main
parent3ca52151881451ce5b3a7740d003e811b586140d (diff)
downloadhaskell-15312bbb53f247c9ed2c5cf75100a9f44c1c7227.tar.gz
Modules (#13009)
* SysTools * Parser * GHC.Builtin * GHC.Iface.Recomp * Settings Update Haddock submodule Metric Decrease: Naperian parsing001
Diffstat (limited to 'compiler/main')
-rw-r--r--compiler/main/Ar.hs268
-rw-r--r--compiler/main/Constants.hs50
-rw-r--r--compiler/main/Elf.hs460
-rw-r--r--compiler/main/FileCleanup.hs314
-rw-r--r--compiler/main/FileSettings.hs16
-rw-r--r--compiler/main/GhcNameVersion.hs11
-rw-r--r--compiler/main/HeaderInfo.hs357
-rw-r--r--compiler/main/PlatformConstants.hs17
-rw-r--r--compiler/main/Settings.hs203
-rw-r--r--compiler/main/StaticPtrTable.hs2
-rw-r--r--compiler/main/SysTools.hs475
-rw-r--r--compiler/main/SysTools/BaseDir.hs137
-rw-r--r--compiler/main/SysTools/ExtraObj.hs244
-rw-r--r--compiler/main/SysTools/Info.hs262
-rw-r--r--compiler/main/SysTools/Process.hs387
-rw-r--r--compiler/main/SysTools/Settings.hs253
-rw-r--r--compiler/main/SysTools/Tasks.hs373
-rw-r--r--compiler/main/SysTools/Terminal.hs104
-rw-r--r--compiler/main/ToolSettings.hs64
19 files changed, 1 insertions, 3996 deletions
diff --git a/compiler/main/Ar.hs b/compiler/main/Ar.hs
deleted file mode 100644
index 1a1862a6fe..0000000000
--- a/compiler/main/Ar.hs
+++ /dev/null
@@ -1,268 +0,0 @@
-{-# LANGUAGE OverloadedStrings, GeneralizedNewtypeDeriving, CPP #-}
-{- Note: [The need for Ar.hs]
-Building `-staticlib` required the presence of libtool, and was a such
-restricted to mach-o only. As libtool on macOS and gnu libtool are very
-different, there was no simple portable way to support this.
-
-libtool for static archives does essentially: concatinate the input archives,
-add the input objects, and create a symbol index. Using `ar` for this task
-fails as even `ar` (bsd and gnu, llvm, ...) do not provide the same
-features across platforms (e.g. index prefixed retrieval of objects with
-the same name.)
-
-As Archives are rather simple structurally, we can just build the archives
-with Haskell directly and use ranlib on the final result to get the symbol
-index. This should allow us to work around with the differences/abailability
-of libtool across different platforms.
--}
-module Ar
- (ArchiveEntry(..)
- ,Archive(..)
- ,afilter
-
- ,parseAr
-
- ,loadAr
- ,loadObj
- ,writeBSDAr
- ,writeGNUAr
-
- ,isBSDSymdef
- ,isGNUSymdef
- )
- where
-
-import GhcPrelude
-
-import Data.List (mapAccumL, isPrefixOf)
-import Data.Monoid ((<>))
-import Data.Binary.Get
-import Data.Binary.Put
-import Control.Monad
-import Control.Applicative
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Char8 as C
-import qualified Data.ByteString.Lazy as L
-#if !defined(mingw32_HOST_OS)
-import qualified System.Posix.Files as POSIX
-#endif
-import System.FilePath (takeFileName)
-
-data ArchiveEntry = ArchiveEntry
- { filename :: String -- ^ File name.
- , filetime :: Int -- ^ File modification time.
- , fileown :: Int -- ^ File owner.
- , filegrp :: Int -- ^ File group.
- , filemode :: Int -- ^ File mode.
- , filesize :: Int -- ^ File size.
- , filedata :: B.ByteString -- ^ File bytes.
- } deriving (Eq, Show)
-
-newtype Archive = Archive [ArchiveEntry]
- deriving (Eq, Show, Semigroup, Monoid)
-
-afilter :: (ArchiveEntry -> Bool) -> Archive -> Archive
-afilter f (Archive xs) = Archive (filter f xs)
-
-isBSDSymdef, isGNUSymdef :: ArchiveEntry -> Bool
-isBSDSymdef a = "__.SYMDEF" `isPrefixOf` (filename a)
-isGNUSymdef a = "/" == (filename a)
-
--- | Archives have numeric values padded with '\x20' to the right.
-getPaddedInt :: B.ByteString -> Int
-getPaddedInt = read . C.unpack . C.takeWhile (/= '\x20')
-
-putPaddedInt :: Int -> Int -> Put
-putPaddedInt padding i = putPaddedString '\x20' padding (show i)
-
-putPaddedString :: Char -> Int -> String -> Put
-putPaddedString pad padding s = putByteString . C.pack . take padding $ s `mappend` (repeat pad)
-
-getBSDArchEntries :: Get [ArchiveEntry]
-getBSDArchEntries = do
- empty <- isEmpty
- if empty then
- return []
- else do
- name <- getByteString 16
- when ('/' `C.elem` name && C.take 3 name /= "#1/") $
- fail "Looks like GNU Archive"
- time <- getPaddedInt <$> getByteString 12
- own <- getPaddedInt <$> getByteString 6
- grp <- getPaddedInt <$> getByteString 6
- mode <- getPaddedInt <$> getByteString 8
- st_size <- getPaddedInt <$> getByteString 10
- end <- getByteString 2
- when (end /= "\x60\x0a") $
- fail ("[BSD Archive] Invalid archive header end marker for name: " ++
- C.unpack name)
- off1 <- liftM fromIntegral bytesRead :: Get Int
- -- BSD stores extended filenames, by writing #1/<length> into the
- -- name field, the first @length@ bytes then represent the file name
- -- thus the payload size is filesize + file name length.
- name <- if C.unpack (C.take 3 name) == "#1/" then
- liftM (C.unpack . C.takeWhile (/= '\0')) (getByteString $ read $ C.unpack $ C.drop 3 name)
- else
- return $ C.unpack $ C.takeWhile (/= ' ') name
- off2 <- liftM fromIntegral bytesRead :: Get Int
- file <- getByteString (st_size - (off2 - off1))
- -- data sections are two byte aligned (see #15396)
- when (odd st_size) $
- void (getByteString 1)
-
- rest <- getBSDArchEntries
- return $ (ArchiveEntry name time own grp mode (st_size - (off2 - off1)) file) : rest
-
--- | GNU Archives feature a special '//' entry that contains the
--- extended names. Those are referred to as /<num>, where num is the
--- offset into the '//' entry.
--- In addition, filenames are terminated with '/' in the archive.
-getGNUArchEntries :: Maybe ArchiveEntry -> Get [ArchiveEntry]
-getGNUArchEntries extInfo = do
- empty <- isEmpty
- if empty
- then return []
- else
- do
- name <- getByteString 16
- time <- getPaddedInt <$> getByteString 12
- own <- getPaddedInt <$> getByteString 6
- grp <- getPaddedInt <$> getByteString 6
- mode <- getPaddedInt <$> getByteString 8
- st_size <- getPaddedInt <$> getByteString 10
- end <- getByteString 2
- when (end /= "\x60\x0a") $
- fail ("[BSD Archive] Invalid archive header end marker for name: " ++
- C.unpack name)
- file <- getByteString st_size
- -- data sections are two byte aligned (see #15396)
- when (odd st_size) $
- void (getByteString 1)
- name <- return . C.unpack $
- if C.unpack (C.take 1 name) == "/"
- then case C.takeWhile (/= ' ') name of
- name@"/" -> name -- symbol table
- name@"//" -> name -- extendedn file names table
- name -> getExtName extInfo (read . C.unpack $ C.drop 1 name)
- else C.takeWhile (/= '/') name
- case name of
- "/" -> getGNUArchEntries extInfo
- "//" -> getGNUArchEntries (Just (ArchiveEntry name time own grp mode st_size file))
- _ -> (ArchiveEntry name time own grp mode st_size file :) <$> getGNUArchEntries extInfo
-
- where
- getExtName :: Maybe ArchiveEntry -> Int -> B.ByteString
- getExtName Nothing _ = error "Invalid extended filename reference."
- getExtName (Just info) offset = C.takeWhile (/= '/') . C.drop offset $ filedata info
-
--- | put an Archive Entry. This assumes that the entries
--- have been preprocessed to account for the extenden file name
--- table section "//" e.g. for GNU Archives. Or that the names
--- have been move into the payload for BSD Archives.
-putArchEntry :: ArchiveEntry -> PutM ()
-putArchEntry (ArchiveEntry name time own grp mode st_size file) = do
- putPaddedString ' ' 16 name
- putPaddedInt 12 time
- putPaddedInt 6 own
- putPaddedInt 6 grp
- putPaddedInt 8 mode
- putPaddedInt 10 (st_size + pad)
- putByteString "\x60\x0a"
- putByteString file
- when (pad == 1) $
- putWord8 0x0a
- where
- pad = st_size `mod` 2
-
-getArchMagic :: Get ()
-getArchMagic = do
- magic <- liftM C.unpack $ getByteString 8
- if magic /= "!<arch>\n"
- then fail $ "Invalid magic number " ++ show magic
- else return ()
-
-putArchMagic :: Put
-putArchMagic = putByteString $ C.pack "!<arch>\n"
-
-getArch :: Get Archive
-getArch = Archive <$> do
- getArchMagic
- getBSDArchEntries <|> getGNUArchEntries Nothing
-
-putBSDArch :: Archive -> PutM ()
-putBSDArch (Archive as) = do
- putArchMagic
- mapM_ putArchEntry (processEntries as)
-
- where
- padStr pad size str = take size $ str <> repeat pad
- nameSize name = case length name `divMod` 4 of
- (n, 0) -> 4 * n
- (n, _) -> 4 * (n + 1)
- needExt name = length name > 16 || ' ' `elem` name
- processEntry :: ArchiveEntry -> ArchiveEntry
- processEntry archive@(ArchiveEntry name _ _ _ _ st_size _)
- | needExt name = archive { filename = "#1/" <> show sz
- , filedata = C.pack (padStr '\0' sz name) <> filedata archive
- , filesize = st_size + sz }
- | otherwise = archive
-
- where sz = nameSize name
-
- processEntries = map processEntry
-
-putGNUArch :: Archive -> PutM ()
-putGNUArch (Archive as) = do
- putArchMagic
- mapM_ putArchEntry (processEntries as)
-
- where
- processEntry :: ArchiveEntry -> ArchiveEntry -> (ArchiveEntry, ArchiveEntry)
- processEntry extInfo archive@(ArchiveEntry name _ _ _ _ _ _)
- | length name > 15 = ( extInfo { filesize = filesize extInfo + length name + 2
- , filedata = filedata extInfo <> C.pack name <> "/\n" }
- , archive { filename = "/" <> show (filesize extInfo) } )
- | otherwise = ( extInfo, archive { filename = name <> "/" } )
-
- processEntries :: [ArchiveEntry] -> [ArchiveEntry]
- processEntries =
- uncurry (:) . mapAccumL processEntry (ArchiveEntry "//" 0 0 0 0 0 mempty)
-
-parseAr :: B.ByteString -> Archive
-parseAr = runGet getArch . L.fromChunks . pure
-
-writeBSDAr, writeGNUAr :: FilePath -> Archive -> IO ()
-writeBSDAr fp = L.writeFile fp . runPut . putBSDArch
-writeGNUAr fp = L.writeFile fp . runPut . putGNUArch
-
-loadAr :: FilePath -> IO Archive
-loadAr fp = parseAr <$> B.readFile fp
-
-loadObj :: FilePath -> IO ArchiveEntry
-loadObj fp = do
- payload <- B.readFile fp
- (modt, own, grp, mode) <- fileInfo fp
- return $ ArchiveEntry
- (takeFileName fp) modt own grp mode
- (B.length payload) payload
-
--- | Take a filePath and return (mod time, own, grp, mode in decimal)
-fileInfo :: FilePath -> IO ( Int, Int, Int, Int) -- ^ mod time, own, grp, mode (in decimal)
-#if defined(mingw32_HOST_OS)
--- on windows mod time, owner group and mode are zero.
-fileInfo _ = pure (0,0,0,0)
-#else
-fileInfo fp = go <$> POSIX.getFileStatus fp
- where go status = ( fromEnum $ POSIX.modificationTime status
- , fromIntegral $ POSIX.fileOwner status
- , fromIntegral $ POSIX.fileGroup status
- , oct2dec . fromIntegral $ POSIX.fileMode status
- )
-
-oct2dec :: Int -> Int
-oct2dec = foldl' (\a b -> a * 10 + b) 0 . reverse . dec 8
- where dec _ 0 = []
- dec b i = let (rest, last) = i `quotRem` b
- in last:dec b rest
-
-#endif
diff --git a/compiler/main/Constants.hs b/compiler/main/Constants.hs
deleted file mode 100644
index 9935b03583..0000000000
--- a/compiler/main/Constants.hs
+++ /dev/null
@@ -1,50 +0,0 @@
-{-
-(c) The GRASP/AQUA Project, Glasgow University, 1992-1998
-
-\section[Constants]{Info about this compilation}
--}
-
-module Constants (module Constants) where
-
-import GhcPrelude
-
-import Config
-
-hiVersion :: Integer
-hiVersion = read (cProjectVersionInt ++ cProjectPatchLevel) :: Integer
-
--- All pretty arbitrary:
-
-mAX_TUPLE_SIZE :: Int
-mAX_TUPLE_SIZE = 62 -- Should really match the number
- -- of decls in Data.Tuple
-
-mAX_CTUPLE_SIZE :: Int -- Constraint tuples
-mAX_CTUPLE_SIZE = 62 -- Should match the number of decls in GHC.Classes
-
-mAX_SUM_SIZE :: Int
-mAX_SUM_SIZE = 62
-
--- | Default maximum depth for both class instance search and type family
--- reduction. See also #5395.
-mAX_REDUCTION_DEPTH :: Int
-mAX_REDUCTION_DEPTH = 200
-
--- | Default maximum constraint-solver iterations
--- Typically there should be very few
-mAX_SOLVER_ITERATIONS :: Int
-mAX_SOLVER_ITERATIONS = 4
-
-wORD64_SIZE :: Int
-wORD64_SIZE = 8
-
--- Size of float in bytes.
-fLOAT_SIZE :: Int
-fLOAT_SIZE = 4
-
--- Size of double in bytes.
-dOUBLE_SIZE :: Int
-dOUBLE_SIZE = 8
-
-tARGET_MAX_CHAR :: Int
-tARGET_MAX_CHAR = 0x10ffff
diff --git a/compiler/main/Elf.hs b/compiler/main/Elf.hs
deleted file mode 100644
index 4d3b06e731..0000000000
--- a/compiler/main/Elf.hs
+++ /dev/null
@@ -1,460 +0,0 @@
-{-
------------------------------------------------------------------------------
---
--- (c) The University of Glasgow 2015
---
--- ELF format tools
---
------------------------------------------------------------------------------
--}
-
-module Elf (
- readElfSectionByName,
- readElfNoteAsString,
- makeElfNote
- ) where
-
-import GhcPrelude
-
-import AsmUtils
-import Exception
-import GHC.Driver.Session
-import GHC.Platform
-import ErrUtils
-import Maybes (MaybeT(..),runMaybeT)
-import Util (charToC)
-import Outputable (text,hcat,SDoc)
-
-import Control.Monad (when)
-import Data.Binary.Get
-import Data.Word
-import Data.Char (ord)
-import Data.ByteString.Lazy (ByteString)
-import qualified Data.ByteString.Lazy as LBS
-import qualified Data.ByteString.Lazy.Char8 as B8
-
-{- Note [ELF specification]
- ~~~~~~~~~~~~~~~~~~~~~~~~
-
- ELF (Executable and Linking Format) is described in the System V Application
- Binary Interface (or ABI). The latter is composed of two parts: a generic
- part and a processor specific part. The generic ABI describes the parts of
- the interface that remain constant across all hardware implementations of
- System V.
-
- The latest release of the specification of the generic ABI is the version
- 4.1 from March 18, 1997:
-
- - http://www.sco.com/developers/devspecs/gabi41.pdf
-
- Since 1997, snapshots of the draft for the "next" version are published:
-
- - http://www.sco.com/developers/gabi/
-
- Quoting the notice on the website: "There is more than one instance of these
- chapters to permit references to older instances to remain valid. All
- modifications to these chapters are forward-compatible, so that correct use
- of an older specification will not be invalidated by a newer instance.
- Approximately on a yearly basis, a new instance will be saved, as it reaches
- what appears to be a stable state."
-
- Nevertheless we will see that since 1998 it is not true for Note sections.
-
- Many ELF sections
- -----------------
-
- ELF-4.1: the normal section number fields in ELF are limited to 16 bits,
- which runs out of bits when you try to cram in more sections than that. Two
- fields are concerned: the one containing the number of the sections and the
- one containing the index of the section that contains section's names. (The
- same thing applies to the field containing the number of segments, but we
- don't care about it here).
-
- ELF-next: to solve this, theses fields in the ELF header have an escape
- value (different for each case), and the actual section number is stashed
- into unused fields in the first section header.
-
- We support this extension as it is forward-compatible with ELF-4.1.
- Moreover, GHC may generate objects with a lot of sections with the
- "function-sections" feature (one section per function).
-
- Note sections
- -------------
-
- Sections with type "note" (SHT_NOTE in the specification) are used to add
- arbitrary data into an ELF file. An entry in a note section is composed of a
- name, a type and a value.
-
- ELF-4.1: "The note information in sections and program header elements holds
- any number of entries, each of which is an array of 4-byte words in the
- format of the target processor." Each entry has the following format:
- | namesz | Word32: size of the name string (including the ending \0)
- | descsz | Word32: size of the value
- | type | Word32: type of the note
- | name | Name string (with \0 padding to ensure 4-byte alignment)
- | ... |
- | desc | Value (with \0 padding to ensure 4-byte alignment)
- | ... |
-
- ELF-next: "The note information in sections and program header elements
- holds a variable amount of entries. In 64-bit objects (files with
- e_ident[EI_CLASS] equal to ELFCLASS64), each entry is an array of 8-byte
- words in the format of the target processor. In 32-bit objects (files with
- e_ident[EI_CLASS] equal to ELFCLASS32), each entry is an array of 4-byte
- words in the format of the target processor." (from 1998-2015 snapshots)
-
- This is not forward-compatible with ELF-4.1. In practice, for almost all
- platforms namesz, descz and type fields are 4-byte words for both 32-bit and
- 64-bit objects (see elf.h and readelf source code).
-
- The only exception in readelf source code is for IA_64 machines with OpenVMS
- OS: "This OS has so many departures from the ELF standard that we test it at
- many places" (comment for is_ia64_vms() in readelf.c). In this case, namesz,
- descsz and type fields are 8-byte words and name and value fields are padded
- to ensure 8-byte alignment.
-
- We don't support this platform in the following code. Reading a note section
- could be done easily (by testing Machine and OS fields in the ELF header).
- Writing a note section, however, requires that we generate a different
- assembly code for GAS depending on the target platform and this is a little
- bit more involved.
-
--}
-
-
--- | ELF header
---
--- The ELF header indicates the native word size (32-bit or 64-bit) and the
--- endianness of the target machine. We directly store getters for words of
--- different sizes as it is more convenient to use. We also store the word size
--- as it is useful to skip some uninteresting fields.
---
--- Other information such as the target machine and OS are left out as we don't
--- use them yet. We could add them in the future if we ever need them.
-data ElfHeader = ElfHeader
- { gw16 :: Get Word16 -- ^ Get a Word16 with the correct endianness
- , gw32 :: Get Word32 -- ^ Get a Word32 with the correct endianness
- , gwN :: Get Word64 -- ^ Get a Word with the correct word size
- -- and endianness
- , wordSize :: Int -- ^ Word size in bytes
- }
-
-
--- | Read the ELF header
-readElfHeader :: DynFlags -> ByteString -> IO (Maybe ElfHeader)
-readElfHeader dflags bs = runGetOrThrow getHeader bs `catchIO` \_ -> do
- debugTraceMsg dflags 3 $
- text ("Unable to read ELF header")
- return Nothing
- where
- getHeader = do
- magic <- getWord32be
- ws <- getWord8
- endian <- getWord8
- version <- getWord8
- skip 9 -- skip OSABI, ABI version and padding
- when (magic /= 0x7F454C46 || version /= 1) $ fail "Invalid ELF header"
-
- case (ws, endian) of
- -- ELF 32, little endian
- (1,1) -> return . Just $ ElfHeader
- getWord16le
- getWord32le
- (fmap fromIntegral getWord32le) 4
- -- ELF 32, big endian
- (1,2) -> return . Just $ ElfHeader
- getWord16be
- getWord32be
- (fmap fromIntegral getWord32be) 4
- -- ELF 64, little endian
- (2,1) -> return . Just $ ElfHeader
- getWord16le
- getWord32le
- (fmap fromIntegral getWord64le) 8
- -- ELF 64, big endian
- (2,2) -> return . Just $ ElfHeader
- getWord16be
- getWord32be
- (fmap fromIntegral getWord64be) 8
- _ -> fail "Invalid ELF header"
-
-
-------------------
--- SECTIONS
-------------------
-
-
--- | Description of the section table
-data SectionTable = SectionTable
- { sectionTableOffset :: Word64 -- ^ offset of the table describing sections
- , sectionEntrySize :: Word16 -- ^ size of an entry in the section table
- , sectionEntryCount :: Word64 -- ^ number of sections
- , sectionNameIndex :: Word32 -- ^ index of a special section which
- -- contains section's names
- }
-
--- | Read the ELF section table
-readElfSectionTable :: DynFlags
- -> ElfHeader
- -> ByteString
- -> IO (Maybe SectionTable)
-
-readElfSectionTable dflags hdr bs = action `catchIO` \_ -> do
- debugTraceMsg dflags 3 $
- text ("Unable to read ELF section table")
- return Nothing
- where
- getSectionTable :: Get SectionTable
- getSectionTable = do
- skip (24 + 2*wordSize hdr) -- skip header and some other fields
- secTableOffset <- gwN hdr
- skip 10
- entrySize <- gw16 hdr
- entryCount <- gw16 hdr
- secNameIndex <- gw16 hdr
- return (SectionTable secTableOffset entrySize
- (fromIntegral entryCount)
- (fromIntegral secNameIndex))
-
- action = do
- secTable <- runGetOrThrow getSectionTable bs
- -- In some cases, the number of entries and the index of the section
- -- containing section's names must be found in unused fields of the first
- -- section entry (see Note [ELF specification])
- let
- offSize0 = fromIntegral $ sectionTableOffset secTable + 8
- + 3 * fromIntegral (wordSize hdr)
- offLink0 = fromIntegral $ offSize0 + fromIntegral (wordSize hdr)
-
- entryCount' <- if sectionEntryCount secTable /= 0
- then return (sectionEntryCount secTable)
- else runGetOrThrow (gwN hdr) (LBS.drop offSize0 bs)
- entryNameIndex' <- if sectionNameIndex secTable /= 0xffff
- then return (sectionNameIndex secTable)
- else runGetOrThrow (gw32 hdr) (LBS.drop offLink0 bs)
- return (Just $ secTable
- { sectionEntryCount = entryCount'
- , sectionNameIndex = entryNameIndex'
- })
-
-
--- | A section
-data Section = Section
- { entryName :: ByteString -- ^ Name of the section
- , entryBS :: ByteString -- ^ Content of the section
- }
-
--- | Read a ELF section
-readElfSectionByIndex :: DynFlags
- -> ElfHeader
- -> SectionTable
- -> Word64
- -> ByteString
- -> IO (Maybe Section)
-
-readElfSectionByIndex dflags hdr secTable i bs = action `catchIO` \_ -> do
- debugTraceMsg dflags 3 $
- text ("Unable to read ELF section")
- return Nothing
- where
- -- read an entry from the section table
- getEntry = do
- nameIndex <- gw32 hdr
- skip (4+2*wordSize hdr)
- offset <- fmap fromIntegral $ gwN hdr
- size <- fmap fromIntegral $ gwN hdr
- let bs' = LBS.take size (LBS.drop offset bs)
- return (nameIndex,bs')
-
- -- read the entry with the given index in the section table
- getEntryByIndex x = runGetOrThrow getEntry bs'
- where
- bs' = LBS.drop off bs
- off = fromIntegral $ sectionTableOffset secTable +
- x * fromIntegral (sectionEntrySize secTable)
-
- -- Get the name of a section
- getEntryName nameIndex = do
- let idx = fromIntegral (sectionNameIndex secTable)
- (_,nameTable) <- getEntryByIndex idx
- let bs' = LBS.drop nameIndex nameTable
- runGetOrThrow getLazyByteStringNul bs'
-
- action = do
- (nameIndex,bs') <- getEntryByIndex (fromIntegral i)
- name <- getEntryName (fromIntegral nameIndex)
- return (Just $ Section name bs')
-
-
--- | Find a section from its name. Return the section contents.
---
--- We do not perform any check on the section type.
-findSectionFromName :: DynFlags
- -> ElfHeader
- -> SectionTable
- -> String
- -> ByteString
- -> IO (Maybe ByteString)
-findSectionFromName dflags hdr secTable name bs =
- rec [0..sectionEntryCount secTable - 1]
- where
- -- convert the required section name into a ByteString to perform
- -- ByteString comparison instead of String comparison
- name' = B8.pack name
-
- -- compare recursively each section name and return the contents of
- -- the matching one, if any
- rec [] = return Nothing
- rec (x:xs) = do
- me <- readElfSectionByIndex dflags hdr secTable x bs
- case me of
- Just e | entryName e == name' -> return (Just (entryBS e))
- _ -> rec xs
-
-
--- | Given a section name, read its contents as a ByteString.
---
--- If the section isn't found or if there is any parsing error, we return
--- Nothing
-readElfSectionByName :: DynFlags
- -> ByteString
- -> String
- -> IO (Maybe LBS.ByteString)
-
-readElfSectionByName dflags bs name = action `catchIO` \_ -> do
- debugTraceMsg dflags 3 $
- text ("Unable to read ELF section \"" ++ name ++ "\"")
- return Nothing
- where
- action = runMaybeT $ do
- hdr <- MaybeT $ readElfHeader dflags bs
- secTable <- MaybeT $ readElfSectionTable dflags hdr bs
- MaybeT $ findSectionFromName dflags hdr secTable name bs
-
-------------------
--- NOTE SECTIONS
-------------------
-
--- | read a Note as a ByteString
---
--- If you try to read a note from a section which does not support the Note
--- format, the parsing is likely to fail and Nothing will be returned
-readElfNoteBS :: DynFlags
- -> ByteString
- -> String
- -> String
- -> IO (Maybe LBS.ByteString)
-
-readElfNoteBS dflags bs sectionName noteId = action `catchIO` \_ -> do
- debugTraceMsg dflags 3 $
- text ("Unable to read ELF note \"" ++ noteId ++
- "\" in section \"" ++ sectionName ++ "\"")
- return Nothing
- where
- -- align the getter on n bytes
- align n = do
- m <- bytesRead
- if m `mod` n == 0
- then return ()
- else skip 1 >> align n
-
- -- noteId as a bytestring
- noteId' = B8.pack noteId
-
- -- read notes recursively until the one with a valid identifier is found
- findNote hdr = do
- align 4
- namesz <- gw32 hdr
- descsz <- gw32 hdr
- _ <- gw32 hdr -- we don't use the note type
- name <- if namesz == 0
- then return LBS.empty
- else getLazyByteStringNul
- align 4
- desc <- if descsz == 0
- then return LBS.empty
- else getLazyByteString (fromIntegral descsz)
- if name == noteId'
- then return $ Just desc
- else findNote hdr
-
-
- action = runMaybeT $ do
- hdr <- MaybeT $ readElfHeader dflags bs
- sec <- MaybeT $ readElfSectionByName dflags bs sectionName
- MaybeT $ runGetOrThrow (findNote hdr) sec
-
--- | read a Note as a String
---
--- If you try to read a note from a section which does not support the Note
--- format, the parsing is likely to fail and Nothing will be returned
-readElfNoteAsString :: DynFlags
- -> FilePath
- -> String
- -> String
- -> IO (Maybe String)
-
-readElfNoteAsString dflags path sectionName noteId = action `catchIO` \_ -> do
- debugTraceMsg dflags 3 $
- text ("Unable to read ELF note \"" ++ noteId ++
- "\" in section \"" ++ sectionName ++ "\"")
- return Nothing
- where
- action = do
- bs <- LBS.readFile path
- note <- readElfNoteBS dflags bs sectionName noteId
- return (fmap B8.unpack note)
-
-
--- | Generate the GAS code to create a Note section
---
--- Header fields for notes are 32-bit long (see Note [ELF specification]).
-makeElfNote :: Platform -> String -> String -> Word32 -> String -> SDoc
-makeElfNote platform sectionName noteName typ contents = hcat [
- text "\t.section ",
- text sectionName,
- text ",\"\",",
- sectionType platform "note",
- text "\n",
- text "\t.balign 4\n",
-
- -- note name length (+ 1 for ending \0)
- asWord32 (length noteName + 1),
-
- -- note contents size
- asWord32 (length contents),
-
- -- note type
- asWord32 typ,
-
- -- note name (.asciz for \0 ending string) + padding
- text "\t.asciz \"",
- text noteName,
- text "\"\n",
- text "\t.balign 4\n",
-
- -- note contents (.ascii to avoid ending \0) + padding
- text "\t.ascii \"",
- text (escape contents),
- text "\"\n",
- text "\t.balign 4\n"]
- where
- escape :: String -> String
- escape = concatMap (charToC.fromIntegral.ord)
-
- asWord32 :: Show a => a -> SDoc
- asWord32 x = hcat [
- text "\t.4byte ",
- text (show x),
- text "\n"]
-
-
-------------------
--- Helpers
-------------------
-
--- | runGet in IO monad that throws an IOException on failure
-runGetOrThrow :: Get a -> LBS.ByteString -> IO a
-runGetOrThrow g bs = case runGetOrFail g bs of
- Left _ -> fail "Error while reading file"
- Right (_,_,a) -> return a
diff --git a/compiler/main/FileCleanup.hs b/compiler/main/FileCleanup.hs
deleted file mode 100644
index 81d0ce7a40..0000000000
--- a/compiler/main/FileCleanup.hs
+++ /dev/null
@@ -1,314 +0,0 @@
-{-# LANGUAGE CPP #-}
-module FileCleanup
- ( TempFileLifetime(..)
- , cleanTempDirs, cleanTempFiles, cleanCurrentModuleTempFiles
- , addFilesToClean, changeTempFilesLifetime
- , newTempName, newTempLibName, newTempDir
- , withSystemTempDirectory, withTempDirectory
- ) where
-
-import GhcPrelude
-
-import GHC.Driver.Session
-import ErrUtils
-import Outputable
-import Util
-import Exception
-import GHC.Driver.Phases
-
-import Control.Monad
-import Data.List
-import qualified Data.Set as Set
-import qualified Data.Map as Map
-import Data.IORef
-import System.Directory
-import System.FilePath
-import System.IO.Error
-
-#if !defined(mingw32_HOST_OS)
-import qualified System.Posix.Internals
-#endif
-
--- | Used when a temp file is created. This determines which component Set of
--- FilesToClean will get the temp file
-data TempFileLifetime
- = TFL_CurrentModule
- -- ^ A file with lifetime TFL_CurrentModule will be cleaned up at the
- -- end of upweep_mod
- | TFL_GhcSession
- -- ^ A file with lifetime TFL_GhcSession will be cleaned up at the end of
- -- runGhc(T)
- deriving (Show)
-
-cleanTempDirs :: DynFlags -> IO ()
-cleanTempDirs dflags
- = unless (gopt Opt_KeepTmpFiles dflags)
- $ mask_
- $ do let ref = dirsToClean dflags
- ds <- atomicModifyIORef' ref $ \ds -> (Map.empty, ds)
- removeTmpDirs dflags (Map.elems ds)
-
--- | Delete all files in @filesToClean dflags@.
-cleanTempFiles :: DynFlags -> IO ()
-cleanTempFiles dflags
- = unless (gopt Opt_KeepTmpFiles dflags)
- $ mask_
- $ do let ref = filesToClean dflags
- to_delete <- atomicModifyIORef' ref $
- \FilesToClean
- { ftcCurrentModule = cm_files
- , ftcGhcSession = gs_files
- } -> ( emptyFilesToClean
- , Set.toList cm_files ++ Set.toList gs_files)
- removeTmpFiles dflags to_delete
-
--- | Delete all files in @filesToClean dflags@. That have lifetime
--- TFL_CurrentModule.
--- If a file must be cleaned eventually, but must survive a
--- cleanCurrentModuleTempFiles, ensure it has lifetime TFL_GhcSession.
-cleanCurrentModuleTempFiles :: DynFlags -> IO ()
-cleanCurrentModuleTempFiles dflags
- = unless (gopt Opt_KeepTmpFiles dflags)
- $ mask_
- $ do let ref = filesToClean dflags
- to_delete <- atomicModifyIORef' ref $
- \ftc@FilesToClean{ftcCurrentModule = cm_files} ->
- (ftc {ftcCurrentModule = Set.empty}, Set.toList cm_files)
- removeTmpFiles dflags to_delete
-
--- | Ensure that new_files are cleaned on the next call of
--- 'cleanTempFiles' or 'cleanCurrentModuleTempFiles', depending on lifetime.
--- If any of new_files are already tracked, they will have their lifetime
--- updated.
-addFilesToClean :: DynFlags -> TempFileLifetime -> [FilePath] -> IO ()
-addFilesToClean dflags lifetime new_files = modifyIORef' (filesToClean dflags) $
- \FilesToClean
- { ftcCurrentModule = cm_files
- , ftcGhcSession = gs_files
- } -> case lifetime of
- TFL_CurrentModule -> FilesToClean
- { ftcCurrentModule = cm_files `Set.union` new_files_set
- , ftcGhcSession = gs_files `Set.difference` new_files_set
- }
- TFL_GhcSession -> FilesToClean
- { ftcCurrentModule = cm_files `Set.difference` new_files_set
- , ftcGhcSession = gs_files `Set.union` new_files_set
- }
- where
- new_files_set = Set.fromList new_files
-
--- | Update the lifetime of files already being tracked. If any files are
--- not being tracked they will be discarded.
-changeTempFilesLifetime :: DynFlags -> TempFileLifetime -> [FilePath] -> IO ()
-changeTempFilesLifetime dflags lifetime files = do
- FilesToClean
- { ftcCurrentModule = cm_files
- , ftcGhcSession = gs_files
- } <- readIORef (filesToClean dflags)
- let old_set = case lifetime of
- TFL_CurrentModule -> gs_files
- TFL_GhcSession -> cm_files
- existing_files = [f | f <- files, f `Set.member` old_set]
- addFilesToClean dflags lifetime existing_files
-
--- Return a unique numeric temp file suffix
-newTempSuffix :: DynFlags -> IO Int
-newTempSuffix dflags =
- atomicModifyIORef' (nextTempSuffix dflags) $ \n -> (n+1,n)
-
--- Find a temporary name that doesn't already exist.
-newTempName :: DynFlags -> TempFileLifetime -> Suffix -> IO FilePath
-newTempName dflags lifetime extn
- = do d <- getTempDir dflags
- findTempName (d </> "ghc_") -- See Note [Deterministic base name]
- where
- findTempName :: FilePath -> IO FilePath
- findTempName prefix
- = do n <- newTempSuffix dflags
- let filename = prefix ++ show n <.> extn
- b <- doesFileExist filename
- if b then findTempName prefix
- else do -- clean it up later
- addFilesToClean dflags lifetime [filename]
- return filename
-
-newTempDir :: DynFlags -> IO FilePath
-newTempDir dflags
- = do d <- getTempDir dflags
- findTempDir (d </> "ghc_")
- where
- findTempDir :: FilePath -> IO FilePath
- findTempDir prefix
- = do n <- newTempSuffix dflags
- let filename = prefix ++ show n
- b <- doesDirectoryExist filename
- if b then findTempDir prefix
- else do createDirectory filename
- -- see mkTempDir below; this is wrong: -> consIORef (dirsToClean dflags) filename
- return filename
-
-newTempLibName :: DynFlags -> TempFileLifetime -> Suffix
- -> IO (FilePath, FilePath, String)
-newTempLibName dflags lifetime extn
- = do d <- getTempDir dflags
- findTempName d ("ghc_")
- where
- findTempName :: FilePath -> String -> IO (FilePath, FilePath, String)
- findTempName dir prefix
- = do n <- newTempSuffix dflags -- See Note [Deterministic base name]
- let libname = prefix ++ show n
- filename = dir </> "lib" ++ libname <.> extn
- b <- doesFileExist filename
- if b then findTempName dir prefix
- else do -- clean it up later
- addFilesToClean dflags lifetime [filename]
- return (filename, dir, libname)
-
-
--- Return our temporary directory within tmp_dir, creating one if we
--- don't have one yet.
-getTempDir :: DynFlags -> IO FilePath
-getTempDir dflags = do
- mapping <- readIORef dir_ref
- case Map.lookup tmp_dir mapping of
- Nothing -> do
- pid <- getProcessID
- let prefix = tmp_dir </> "ghc" ++ show pid ++ "_"
- mask_ $ mkTempDir prefix
- Just dir -> return dir
- where
- tmp_dir = tmpDir dflags
- dir_ref = dirsToClean dflags
-
- mkTempDir :: FilePath -> IO FilePath
- mkTempDir prefix = do
- n <- newTempSuffix dflags
- let our_dir = prefix ++ show n
-
- -- 1. Speculatively create our new directory.
- createDirectory our_dir
-
- -- 2. Update the dirsToClean mapping unless an entry already exists
- -- (i.e. unless another thread beat us to it).
- their_dir <- atomicModifyIORef' dir_ref $ \mapping ->
- case Map.lookup tmp_dir mapping of
- Just dir -> (mapping, Just dir)
- Nothing -> (Map.insert tmp_dir our_dir mapping, Nothing)
-
- -- 3. If there was an existing entry, return it and delete the
- -- directory we created. Otherwise return the directory we created.
- case their_dir of
- Nothing -> do
- debugTraceMsg dflags 2 $
- text "Created temporary directory:" <+> text our_dir
- return our_dir
- Just dir -> do
- removeDirectory our_dir
- return dir
- `catchIO` \e -> if isAlreadyExistsError e
- then mkTempDir prefix else ioError e
-
-{- Note [Deterministic base name]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The filename of temporary files, especially the basename of C files, can end
-up in the output in some form, e.g. as part of linker debug information. In the
-interest of bit-wise exactly reproducible compilation (#4012), the basename of
-the temporary file no longer contains random information (it used to contain
-the process id).
-
-This is ok, as the temporary directory used contains the pid (see getTempDir).
--}
-removeTmpDirs :: DynFlags -> [FilePath] -> IO ()
-removeTmpDirs dflags ds
- = traceCmd dflags "Deleting temp dirs"
- ("Deleting: " ++ unwords ds)
- (mapM_ (removeWith dflags removeDirectory) ds)
-
-removeTmpFiles :: DynFlags -> [FilePath] -> IO ()
-removeTmpFiles dflags fs
- = warnNon $
- traceCmd dflags "Deleting temp files"
- ("Deleting: " ++ unwords deletees)
- (mapM_ (removeWith dflags removeFile) deletees)
- where
- -- Flat out refuse to delete files that are likely to be source input
- -- files (is there a worse bug than having a compiler delete your source
- -- files?)
- --
- -- Deleting source files is a sign of a bug elsewhere, so prominently flag
- -- the condition.
- warnNon act
- | null non_deletees = act
- | otherwise = do
- putMsg dflags (text "WARNING - NOT deleting source files:"
- <+> hsep (map text non_deletees))
- act
-
- (non_deletees, deletees) = partition isHaskellUserSrcFilename fs
-
-removeWith :: DynFlags -> (FilePath -> IO ()) -> FilePath -> IO ()
-removeWith dflags remover f = remover f `catchIO`
- (\e ->
- let msg = if isDoesNotExistError e
- then text "Warning: deleting non-existent" <+> text f
- else text "Warning: exception raised when deleting"
- <+> text f <> colon
- $$ text (show e)
- in debugTraceMsg dflags 2 msg
- )
-
-#if defined(mingw32_HOST_OS)
--- relies on Int == Int32 on Windows
-foreign import ccall unsafe "_getpid" getProcessID :: IO Int
-#else
-getProcessID :: IO Int
-getProcessID = System.Posix.Internals.c_getpid >>= return . fromIntegral
-#endif
-
--- The following three functions are from the `temporary` package.
-
--- | Create and use a temporary directory in the system standard temporary
--- directory.
---
--- Behaves exactly the same as 'withTempDirectory', except that the parent
--- temporary directory will be that returned by 'getTemporaryDirectory'.
-withSystemTempDirectory :: String -- ^ Directory name template. See 'openTempFile'.
- -> (FilePath -> IO a) -- ^ Callback that can use the directory
- -> IO a
-withSystemTempDirectory template action =
- getTemporaryDirectory >>= \tmpDir -> withTempDirectory tmpDir template action
-
-
--- | Create and use a temporary directory.
---
--- Creates a new temporary directory inside the given directory, making use
--- of the template. The temp directory is deleted after use. For example:
---
--- > withTempDirectory "src" "sdist." $ \tmpDir -> do ...
---
--- The @tmpDir@ will be a new subdirectory of the given directory, e.g.
--- @src/sdist.342@.
-withTempDirectory :: FilePath -- ^ Temp directory to create the directory in
- -> String -- ^ Directory name template. See 'openTempFile'.
- -> (FilePath -> IO a) -- ^ Callback that can use the directory
- -> IO a
-withTempDirectory targetDir template =
- Exception.bracket
- (createTempDirectory targetDir template)
- (ignoringIOErrors . removeDirectoryRecursive)
-
-ignoringIOErrors :: IO () -> IO ()
-ignoringIOErrors ioe = ioe `catch` (\e -> const (return ()) (e :: IOError))
-
-
-createTempDirectory :: FilePath -> String -> IO FilePath
-createTempDirectory dir template = do
- pid <- getProcessID
- findTempName pid
- where findTempName x = do
- let path = dir </> template ++ show x
- createDirectory path
- return path
- `catchIO` \e -> if isAlreadyExistsError e
- then findTempName (x+1) else ioError e
diff --git a/compiler/main/FileSettings.hs b/compiler/main/FileSettings.hs
deleted file mode 100644
index 6179721cfd..0000000000
--- a/compiler/main/FileSettings.hs
+++ /dev/null
@@ -1,16 +0,0 @@
-module FileSettings
- ( FileSettings (..)
- ) where
-
-import GhcPrelude
-
--- | Paths to various files and directories used by GHC, including those that
--- provide more settings.
-data FileSettings = FileSettings
- { fileSettings_ghcUsagePath :: FilePath -- ditto
- , fileSettings_ghciUsagePath :: FilePath -- ditto
- , fileSettings_toolDir :: Maybe FilePath -- ditto
- , fileSettings_topDir :: FilePath -- ditto
- , fileSettings_tmpDir :: String -- no trailing '/'
- , fileSettings_globalPackageDatabase :: FilePath
- }
diff --git a/compiler/main/GhcNameVersion.hs b/compiler/main/GhcNameVersion.hs
deleted file mode 100644
index 96e04186a7..0000000000
--- a/compiler/main/GhcNameVersion.hs
+++ /dev/null
@@ -1,11 +0,0 @@
-module GhcNameVersion
- ( GhcNameVersion (..)
- ) where
-
-import GhcPrelude
-
--- | Settings for what GHC this is.
-data GhcNameVersion = GhcNameVersion
- { ghcNameVersion_programName :: String
- , ghcNameVersion_projectVersion :: String
- }
diff --git a/compiler/main/HeaderInfo.hs b/compiler/main/HeaderInfo.hs
deleted file mode 100644
index cb1b1e3c2b..0000000000
--- a/compiler/main/HeaderInfo.hs
+++ /dev/null
@@ -1,357 +0,0 @@
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE ViewPatterns #-}
-{-# LANGUAGE TypeFamilies #-}
-
------------------------------------------------------------------------------
---
--- | Parsing the top of a Haskell source file to get its module name,
--- imports and options.
---
--- (c) Simon Marlow 2005
--- (c) Lemmih 2006
---
------------------------------------------------------------------------------
-
-module HeaderInfo ( getImports
- , mkPrelImports -- used by the renamer too
- , getOptionsFromFile, getOptions
- , optionsErrorMsgs,
- checkProcessArgsResult ) where
-
-#include "HsVersions.h"
-
-import GhcPrelude
-
-import GHC.Platform
-import GHC.Driver.Types
-import Parser ( parseHeader )
-import Lexer
-import FastString
-import GHC.Hs
-import GHC.Types.Module
-import PrelNames
-import StringBuffer
-import GHC.Types.SrcLoc
-import GHC.Driver.Session
-import ErrUtils
-import Util
-import Outputable
-import Maybes
-import Bag ( emptyBag, listToBag, unitBag )
-import MonadUtils
-import Exception
-import GHC.Types.Basic
-import qualified GHC.LanguageExtensions as LangExt
-
-import Control.Monad
-import System.IO
-import System.IO.Unsafe
-import Data.List
-
-------------------------------------------------------------------------------
-
--- | Parse the imports of a source file.
---
--- Throws a 'SourceError' if parsing fails.
-getImports :: DynFlags
- -> StringBuffer -- ^ Parse this.
- -> FilePath -- ^ Filename the buffer came from. Used for
- -- reporting parse error locations.
- -> FilePath -- ^ The original source filename (used for locations
- -- in the function result)
- -> IO (Either
- ErrorMessages
- ([(Maybe FastString, Located ModuleName)],
- [(Maybe FastString, Located ModuleName)],
- Located ModuleName))
- -- ^ The source imports and normal imports (with optional package
- -- names from -XPackageImports), and the module name.
-getImports dflags buf filename source_filename = do
- let loc = mkRealSrcLoc (mkFastString filename) 1 1
- case unP parseHeader (mkPState dflags buf loc) of
- PFailed pst ->
- -- assuming we're not logging warnings here as per below
- return $ Left $ getErrorMessages pst dflags
- POk pst rdr_module -> fmap Right $ do
- let _ms@(_warns, errs) = getMessages pst dflags
- -- don't log warnings: they'll be reported when we parse the file
- -- for real. See #2500.
- ms = (emptyBag, errs)
- -- logWarnings warns
- if errorsFound dflags ms
- then throwIO $ mkSrcErr errs
- else
- let hsmod = unLoc rdr_module
- mb_mod = hsmodName hsmod
- imps = hsmodImports hsmod
- main_loc = srcLocSpan (mkSrcLoc (mkFastString source_filename)
- 1 1)
- mod = mb_mod `orElse` L main_loc mAIN_NAME
- (src_idecls, ord_idecls) = partition (ideclSource.unLoc) imps
-
- -- GHC.Prim doesn't exist physically, so don't go looking for it.
- ordinary_imps = filter ((/= moduleName gHC_PRIM) . unLoc
- . ideclName . unLoc)
- ord_idecls
-
- implicit_prelude = xopt LangExt.ImplicitPrelude dflags
- implicit_imports = mkPrelImports (unLoc mod) main_loc
- implicit_prelude imps
- convImport (L _ i) = (fmap sl_fs (ideclPkgQual i), ideclName i)
- in
- return (map convImport src_idecls,
- map convImport (implicit_imports ++ ordinary_imps),
- mod)
-
-mkPrelImports :: ModuleName
- -> SrcSpan -- Attribute the "import Prelude" to this location
- -> Bool -> [LImportDecl GhcPs]
- -> [LImportDecl GhcPs]
--- Construct the implicit declaration "import Prelude" (or not)
---
--- NB: opt_NoImplicitPrelude is slightly different to import Prelude ();
--- because the former doesn't even look at Prelude.hi for instance
--- declarations, whereas the latter does.
-mkPrelImports this_mod loc implicit_prelude import_decls
- | this_mod == pRELUDE_NAME
- || explicit_prelude_import
- || not implicit_prelude
- = []
- | otherwise = [preludeImportDecl]
- where
- explicit_prelude_import
- = notNull [ () | L _ (ImportDecl { ideclName = mod
- , ideclPkgQual = Nothing })
- <- import_decls
- , unLoc mod == pRELUDE_NAME ]
-
- preludeImportDecl :: LImportDecl GhcPs
- preludeImportDecl
- = L loc $ ImportDecl { ideclExt = noExtField,
- ideclSourceSrc = NoSourceText,
- ideclName = L loc pRELUDE_NAME,
- ideclPkgQual = Nothing,
- ideclSource = False,
- ideclSafe = False, -- Not a safe import
- ideclQualified = NotQualified,
- ideclImplicit = True, -- Implicit!
- ideclAs = Nothing,
- ideclHiding = Nothing }
-
---------------------------------------------------------------
--- Get options
---------------------------------------------------------------
-
--- | Parse OPTIONS and LANGUAGE pragmas of the source file.
---
--- Throws a 'SourceError' if flag parsing fails (including unsupported flags.)
-getOptionsFromFile :: DynFlags
- -> FilePath -- ^ Input file
- -> IO [Located String] -- ^ Parsed options, if any.
-getOptionsFromFile dflags filename
- = Exception.bracket
- (openBinaryFile filename ReadMode)
- (hClose)
- (\handle -> do
- opts <- fmap (getOptions' dflags)
- (lazyGetToks dflags' filename handle)
- seqList opts $ return opts)
- where -- We don't need to get haddock doc tokens when we're just
- -- getting the options from pragmas, and lazily lexing them
- -- correctly is a little tricky: If there is "\n" or "\n-"
- -- left at the end of a buffer then the haddock doc may
- -- continue past the end of the buffer, despite the fact that
- -- we already have an apparently-complete token.
- -- We therefore just turn Opt_Haddock off when doing the lazy
- -- lex.
- dflags' = gopt_unset dflags Opt_Haddock
-
-blockSize :: Int
--- blockSize = 17 -- for testing :-)
-blockSize = 1024
-
-lazyGetToks :: DynFlags -> FilePath -> Handle -> IO [Located Token]
-lazyGetToks dflags filename handle = do
- buf <- hGetStringBufferBlock handle blockSize
- unsafeInterleaveIO $ lazyLexBuf handle (pragState dflags buf loc) False blockSize
- where
- loc = mkRealSrcLoc (mkFastString filename) 1 1
-
- lazyLexBuf :: Handle -> PState -> Bool -> Int -> IO [Located Token]
- lazyLexBuf handle state eof size = do
- case unP (lexer False return) state of
- POk state' t -> do
- -- pprTrace "lazyLexBuf" (text (show (buffer state'))) (return ())
- if atEnd (buffer state') && not eof
- -- if this token reached the end of the buffer, and we haven't
- -- necessarily read up to the end of the file, then the token might
- -- be truncated, so read some more of the file and lex it again.
- then getMore handle state size
- else case unLoc t of
- ITeof -> return [t]
- _other -> do rest <- lazyLexBuf handle state' eof size
- return (t : rest)
- _ | not eof -> getMore handle state size
- | otherwise -> return [L (mkSrcSpanPs (last_loc state)) ITeof]
- -- parser assumes an ITeof sentinel at the end
-
- getMore :: Handle -> PState -> Int -> IO [Located Token]
- getMore handle state size = do
- -- pprTrace "getMore" (text (show (buffer state))) (return ())
- let new_size = size * 2
- -- double the buffer size each time we read a new block. This
- -- counteracts the quadratic slowdown we otherwise get for very
- -- large module names (#5981)
- nextbuf <- hGetStringBufferBlock handle new_size
- if (len nextbuf == 0) then lazyLexBuf handle state True new_size else do
- newbuf <- appendStringBuffers (buffer state) nextbuf
- unsafeInterleaveIO $ lazyLexBuf handle state{buffer=newbuf} False new_size
-
-
-getToks :: DynFlags -> FilePath -> StringBuffer -> [Located Token]
-getToks dflags filename buf = lexAll (pragState dflags buf loc)
- where
- loc = mkRealSrcLoc (mkFastString filename) 1 1
-
- lexAll state = case unP (lexer False return) state of
- POk _ t@(L _ ITeof) -> [t]
- POk state' t -> t : lexAll state'
- _ -> [L (mkSrcSpanPs (last_loc state)) ITeof]
-
-
--- | Parse OPTIONS and LANGUAGE pragmas of the source file.
---
--- Throws a 'SourceError' if flag parsing fails (including unsupported flags.)
-getOptions :: DynFlags
- -> StringBuffer -- ^ Input Buffer
- -> FilePath -- ^ Source filename. Used for location info.
- -> [Located String] -- ^ Parsed options.
-getOptions dflags buf filename
- = getOptions' dflags (getToks dflags filename buf)
-
--- The token parser is written manually because Happy can't
--- return a partial result when it encounters a lexer error.
--- We want to extract options before the buffer is passed through
--- CPP, so we can't use the same trick as 'getImports'.
-getOptions' :: DynFlags
- -> [Located Token] -- Input buffer
- -> [Located String] -- Options.
-getOptions' dflags toks
- = parseToks toks
- where
- parseToks (open:close:xs)
- | IToptions_prag str <- unLoc open
- , ITclose_prag <- unLoc close
- = case toArgs str of
- Left _err -> optionsParseError str dflags $ -- #15053
- combineSrcSpans (getLoc open) (getLoc close)
- Right args -> map (L (getLoc open)) args ++ parseToks xs
- parseToks (open:close:xs)
- | ITinclude_prag str <- unLoc open
- , ITclose_prag <- unLoc close
- = map (L (getLoc open)) ["-#include",removeSpaces str] ++
- parseToks xs
- parseToks (open:close:xs)
- | ITdocOptions str <- unLoc open
- , ITclose_prag <- unLoc close
- = map (L (getLoc open)) ["-haddock-opts", removeSpaces str]
- ++ parseToks xs
- parseToks (open:xs)
- | ITlanguage_prag <- unLoc open
- = parseLanguage xs
- parseToks (comment:xs) -- Skip over comments
- | isComment (unLoc comment)
- = parseToks xs
- parseToks _ = []
- parseLanguage ((L loc (ITconid fs)):rest)
- = checkExtension dflags (L loc fs) :
- case rest of
- (L _loc ITcomma):more -> parseLanguage more
- (L _loc ITclose_prag):more -> parseToks more
- (L loc _):_ -> languagePragParseError dflags loc
- [] -> panic "getOptions'.parseLanguage(1) went past eof token"
- parseLanguage (tok:_)
- = languagePragParseError dflags (getLoc tok)
- parseLanguage []
- = panic "getOptions'.parseLanguage(2) went past eof token"
-
- isComment :: Token -> Bool
- isComment c =
- case c of
- (ITlineComment {}) -> True
- (ITblockComment {}) -> True
- (ITdocCommentNext {}) -> True
- (ITdocCommentPrev {}) -> True
- (ITdocCommentNamed {}) -> True
- (ITdocSection {}) -> True
- _ -> False
-
------------------------------------------------------------------------------
-
--- | Complain about non-dynamic flags in OPTIONS pragmas.
---
--- Throws a 'SourceError' if the input list is non-empty claiming that the
--- input flags are unknown.
-checkProcessArgsResult :: MonadIO m => DynFlags -> [Located String] -> m ()
-checkProcessArgsResult dflags flags
- = when (notNull flags) $
- liftIO $ throwIO $ mkSrcErr $ listToBag $ map mkMsg flags
- where mkMsg (L loc flag)
- = mkPlainErrMsg dflags loc $
- (text "unknown flag in {-# OPTIONS_GHC #-} pragma:" <+>
- text flag)
-
------------------------------------------------------------------------------
-
-checkExtension :: DynFlags -> Located FastString -> Located String
-checkExtension dflags (L l ext)
--- Checks if a given extension is valid, and if so returns
--- its corresponding flag. Otherwise it throws an exception.
- = if ext' `elem` supported
- then L l ("-X"++ext')
- else unsupportedExtnError dflags l ext'
- where
- ext' = unpackFS ext
- supported = supportedLanguagesAndExtensions $ platformMini $ targetPlatform dflags
-
-languagePragParseError :: DynFlags -> SrcSpan -> a
-languagePragParseError dflags loc =
- throwErr dflags loc $
- vcat [ text "Cannot parse LANGUAGE pragma"
- , text "Expecting comma-separated list of language options,"
- , text "each starting with a capital letter"
- , nest 2 (text "E.g. {-# LANGUAGE TemplateHaskell, GADTs #-}") ]
-
-unsupportedExtnError :: DynFlags -> SrcSpan -> String -> a
-unsupportedExtnError dflags loc unsup =
- throwErr dflags loc $
- 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
- suggestions = fuzzyMatch unsup supported
-
-
-optionsErrorMsgs :: DynFlags -> [String] -> [Located String] -> FilePath -> Messages
-optionsErrorMsgs dflags unhandled_flags flags_lines _filename
- = (emptyBag, listToBag (map mkMsg unhandled_flags_lines))
- where unhandled_flags_lines :: [Located String]
- unhandled_flags_lines = [ L l f
- | f <- unhandled_flags
- , L l f' <- flags_lines
- , f == f' ]
- mkMsg (L flagSpan flag) =
- ErrUtils.mkPlainErrMsg dflags flagSpan $
- text "unknown flag in {-# OPTIONS_GHC #-} pragma:" <+> text flag
-
-optionsParseError :: String -> DynFlags -> SrcSpan -> a -- #15053
-optionsParseError str dflags loc =
- throwErr dflags loc $
- vcat [ text "Error while parsing OPTIONS_GHC pragma."
- , text "Expecting whitespace-separated list of GHC options."
- , text " E.g. {-# OPTIONS_GHC -Wall -O2 #-}"
- , text ("Input was: " ++ show str) ]
-
-throwErr :: DynFlags -> SrcSpan -> SDoc -> a -- #15053
-throwErr dflags loc doc =
- throw $ mkSrcErr $ unitBag $ mkPlainErrMsg dflags loc doc
diff --git a/compiler/main/PlatformConstants.hs b/compiler/main/PlatformConstants.hs
deleted file mode 100644
index 96b0f70e6d..0000000000
--- a/compiler/main/PlatformConstants.hs
+++ /dev/null
@@ -1,17 +0,0 @@
-{-# LANGUAGE CPP #-}
-
--------------------------------------------------------------------------------
---
--- | Platform constants
---
--- (c) The University of Glasgow 2013
---
--------------------------------------------------------------------------------
-
-module PlatformConstants (PlatformConstants(..)) where
-
-import GhcPrelude
-
--- Produced by deriveConstants
-#include "GHCConstantsHaskellType.hs"
-
diff --git a/compiler/main/Settings.hs b/compiler/main/Settings.hs
deleted file mode 100644
index a4e0f8e4a7..0000000000
--- a/compiler/main/Settings.hs
+++ /dev/null
@@ -1,203 +0,0 @@
-module Settings
- ( Settings (..)
- , sProgramName
- , sProjectVersion
- , sGhcUsagePath
- , sGhciUsagePath
- , sToolDir
- , sTopDir
- , sTmpDir
- , sGlobalPackageDatabasePath
- , sLdSupportsCompactUnwind
- , sLdSupportsBuildId
- , sLdSupportsFilelist
- , sLdIsGnuLd
- , sGccSupportsNoPie
- , sPgm_L
- , sPgm_P
- , sPgm_F
- , sPgm_c
- , sPgm_a
- , sPgm_l
- , sPgm_dll
- , sPgm_T
- , sPgm_windres
- , sPgm_libtool
- , sPgm_ar
- , sPgm_ranlib
- , sPgm_lo
- , sPgm_lc
- , sPgm_lcc
- , sPgm_i
- , sOpt_L
- , sOpt_P
- , sOpt_P_fingerprint
- , sOpt_F
- , sOpt_c
- , sOpt_cxx
- , sOpt_a
- , sOpt_l
- , sOpt_windres
- , sOpt_lo
- , sOpt_lc
- , sOpt_lcc
- , sOpt_i
- , sExtraGccViaCFlags
- , sTargetPlatformString
- , sIntegerLibrary
- , sIntegerLibraryType
- , sGhcWithInterpreter
- , sGhcWithNativeCodeGen
- , sGhcWithSMP
- , sGhcRTSWays
- , sTablesNextToCode
- , sLeadingUnderscore
- , sLibFFI
- , sGhcThreaded
- , sGhcDebugged
- , sGhcRtsWithLibdw
- ) where
-
-import GhcPrelude
-
-import CliOption
-import Fingerprint
-import FileSettings
-import GhcNameVersion
-import GHC.Platform
-import PlatformConstants
-import ToolSettings
-
-data Settings = Settings
- { sGhcNameVersion :: {-# UNPACk #-} !GhcNameVersion
- , sFileSettings :: {-# UNPACK #-} !FileSettings
- , sTargetPlatform :: Platform -- Filled in by SysTools
- , sToolSettings :: {-# UNPACK #-} !ToolSettings
- , sPlatformMisc :: {-# UNPACK #-} !PlatformMisc
- , sPlatformConstants :: PlatformConstants
-
- -- You shouldn't need to look things up in rawSettings directly.
- -- They should have their own fields instead.
- , sRawSettings :: [(String, String)]
- }
-
------------------------------------------------------------------------------
--- Accessessors from 'Settings'
-
-sProgramName :: Settings -> String
-sProgramName = ghcNameVersion_programName . sGhcNameVersion
-sProjectVersion :: Settings -> String
-sProjectVersion = ghcNameVersion_projectVersion . sGhcNameVersion
-
-sGhcUsagePath :: Settings -> FilePath
-sGhcUsagePath = fileSettings_ghcUsagePath . sFileSettings
-sGhciUsagePath :: Settings -> FilePath
-sGhciUsagePath = fileSettings_ghciUsagePath . sFileSettings
-sToolDir :: Settings -> Maybe FilePath
-sToolDir = fileSettings_toolDir . sFileSettings
-sTopDir :: Settings -> FilePath
-sTopDir = fileSettings_topDir . sFileSettings
-sTmpDir :: Settings -> String
-sTmpDir = fileSettings_tmpDir . sFileSettings
-sGlobalPackageDatabasePath :: Settings -> FilePath
-sGlobalPackageDatabasePath = fileSettings_globalPackageDatabase . sFileSettings
-
-sLdSupportsCompactUnwind :: Settings -> Bool
-sLdSupportsCompactUnwind = toolSettings_ldSupportsCompactUnwind . sToolSettings
-sLdSupportsBuildId :: Settings -> Bool
-sLdSupportsBuildId = toolSettings_ldSupportsBuildId . sToolSettings
-sLdSupportsFilelist :: Settings -> Bool
-sLdSupportsFilelist = toolSettings_ldSupportsFilelist . sToolSettings
-sLdIsGnuLd :: Settings -> Bool
-sLdIsGnuLd = toolSettings_ldIsGnuLd . sToolSettings
-sGccSupportsNoPie :: Settings -> Bool
-sGccSupportsNoPie = toolSettings_ccSupportsNoPie . sToolSettings
-
-sPgm_L :: Settings -> String
-sPgm_L = toolSettings_pgm_L . sToolSettings
-sPgm_P :: Settings -> (String, [Option])
-sPgm_P = toolSettings_pgm_P . sToolSettings
-sPgm_F :: Settings -> String
-sPgm_F = toolSettings_pgm_F . sToolSettings
-sPgm_c :: Settings -> String
-sPgm_c = toolSettings_pgm_c . sToolSettings
-sPgm_a :: Settings -> (String, [Option])
-sPgm_a = toolSettings_pgm_a . sToolSettings
-sPgm_l :: Settings -> (String, [Option])
-sPgm_l = toolSettings_pgm_l . sToolSettings
-sPgm_dll :: Settings -> (String, [Option])
-sPgm_dll = toolSettings_pgm_dll . sToolSettings
-sPgm_T :: Settings -> String
-sPgm_T = toolSettings_pgm_T . sToolSettings
-sPgm_windres :: Settings -> String
-sPgm_windres = toolSettings_pgm_windres . sToolSettings
-sPgm_libtool :: Settings -> String
-sPgm_libtool = toolSettings_pgm_libtool . sToolSettings
-sPgm_ar :: Settings -> String
-sPgm_ar = toolSettings_pgm_ar . sToolSettings
-sPgm_ranlib :: Settings -> String
-sPgm_ranlib = toolSettings_pgm_ranlib . sToolSettings
-sPgm_lo :: Settings -> (String, [Option])
-sPgm_lo = toolSettings_pgm_lo . sToolSettings
-sPgm_lc :: Settings -> (String, [Option])
-sPgm_lc = toolSettings_pgm_lc . sToolSettings
-sPgm_lcc :: Settings -> (String, [Option])
-sPgm_lcc = toolSettings_pgm_lcc . sToolSettings
-sPgm_i :: Settings -> String
-sPgm_i = toolSettings_pgm_i . sToolSettings
-sOpt_L :: Settings -> [String]
-sOpt_L = toolSettings_opt_L . sToolSettings
-sOpt_P :: Settings -> [String]
-sOpt_P = toolSettings_opt_P . sToolSettings
-sOpt_P_fingerprint :: Settings -> Fingerprint
-sOpt_P_fingerprint = toolSettings_opt_P_fingerprint . sToolSettings
-sOpt_F :: Settings -> [String]
-sOpt_F = toolSettings_opt_F . sToolSettings
-sOpt_c :: Settings -> [String]
-sOpt_c = toolSettings_opt_c . sToolSettings
-sOpt_cxx :: Settings -> [String]
-sOpt_cxx = toolSettings_opt_cxx . sToolSettings
-sOpt_a :: Settings -> [String]
-sOpt_a = toolSettings_opt_a . sToolSettings
-sOpt_l :: Settings -> [String]
-sOpt_l = toolSettings_opt_l . sToolSettings
-sOpt_windres :: Settings -> [String]
-sOpt_windres = toolSettings_opt_windres . sToolSettings
-sOpt_lo :: Settings -> [String]
-sOpt_lo = toolSettings_opt_lo . sToolSettings
-sOpt_lc :: Settings -> [String]
-sOpt_lc = toolSettings_opt_lc . sToolSettings
-sOpt_lcc :: Settings -> [String]
-sOpt_lcc = toolSettings_opt_lcc . sToolSettings
-sOpt_i :: Settings -> [String]
-sOpt_i = toolSettings_opt_i . sToolSettings
-
-sExtraGccViaCFlags :: Settings -> [String]
-sExtraGccViaCFlags = toolSettings_extraGccViaCFlags . sToolSettings
-
-sTargetPlatformString :: Settings -> String
-sTargetPlatformString = platformMisc_targetPlatformString . sPlatformMisc
-sIntegerLibrary :: Settings -> String
-sIntegerLibrary = platformMisc_integerLibrary . sPlatformMisc
-sIntegerLibraryType :: Settings -> IntegerLibrary
-sIntegerLibraryType = platformMisc_integerLibraryType . sPlatformMisc
-sGhcWithInterpreter :: Settings -> Bool
-sGhcWithInterpreter = platformMisc_ghcWithInterpreter . sPlatformMisc
-sGhcWithNativeCodeGen :: Settings -> Bool
-sGhcWithNativeCodeGen = platformMisc_ghcWithNativeCodeGen . sPlatformMisc
-sGhcWithSMP :: Settings -> Bool
-sGhcWithSMP = platformMisc_ghcWithSMP . sPlatformMisc
-sGhcRTSWays :: Settings -> String
-sGhcRTSWays = platformMisc_ghcRTSWays . sPlatformMisc
-sTablesNextToCode :: Settings -> Bool
-sTablesNextToCode = platformMisc_tablesNextToCode . sPlatformMisc
-sLeadingUnderscore :: Settings -> Bool
-sLeadingUnderscore = platformMisc_leadingUnderscore . sPlatformMisc
-sLibFFI :: Settings -> Bool
-sLibFFI = platformMisc_libFFI . sPlatformMisc
-sGhcThreaded :: Settings -> Bool
-sGhcThreaded = platformMisc_ghcThreaded . sPlatformMisc
-sGhcDebugged :: Settings -> Bool
-sGhcDebugged = platformMisc_ghcDebugged . sPlatformMisc
-sGhcRtsWithLibdw :: Settings -> Bool
-sGhcRtsWithLibdw = platformMisc_ghcRtsWithLibdw . sPlatformMisc
diff --git a/compiler/main/StaticPtrTable.hs b/compiler/main/StaticPtrTable.hs
index fd4b734433..006b6f2b39 100644
--- a/compiler/main/StaticPtrTable.hs
+++ b/compiler/main/StaticPtrTable.hs
@@ -136,7 +136,7 @@ import GHC.Types.Module
import GHC.Types.Name
import Outputable
import GHC.Platform
-import PrelNames
+import GHC.Builtin.Names
import GHC.Tc.Utils.Env (lookupGlobal)
import GHC.Core.Type
diff --git a/compiler/main/SysTools.hs b/compiler/main/SysTools.hs
deleted file mode 100644
index ea6eb178ee..0000000000
--- a/compiler/main/SysTools.hs
+++ /dev/null
@@ -1,475 +0,0 @@
-{-
------------------------------------------------------------------------------
---
--- (c) The University of Glasgow 2001-2003
---
--- Access to system tools: gcc, cp, rm etc
---
------------------------------------------------------------------------------
--}
-
-{-# LANGUAGE CPP, MultiWayIf, ScopedTypeVariables #-}
-
-module SysTools (
- -- * Initialisation
- initSysTools,
- lazyInitLlvmConfig,
-
- -- * Interface to system tools
- module SysTools.Tasks,
- module SysTools.Info,
-
- linkDynLib,
-
- copy,
- copyWithHeader,
-
- -- * General utilities
- Option(..),
- expandTopDir,
-
- -- * Platform-specifics
- libmLinkOpts,
-
- -- * Mac OS X frameworks
- getPkgFrameworkOpts,
- getFrameworkOpts
- ) where
-
-#include "HsVersions.h"
-
-import GhcPrelude
-
-import GHC.Settings
-
-import GHC.Types.Module
-import GHC.Driver.Packages
-import Outputable
-import ErrUtils
-import GHC.Platform
-import GHC.Driver.Session
-import GHC.Driver.Ways
-
-import Control.Monad.Trans.Except (runExceptT)
-import System.FilePath
-import System.IO
-import System.IO.Unsafe (unsafeInterleaveIO)
-import SysTools.ExtraObj
-import SysTools.Info
-import SysTools.Tasks
-import SysTools.BaseDir
-import SysTools.Settings
-import qualified Data.Set as Set
-
-{-
-Note [How GHC finds toolchain utilities]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-SysTools.initSysProgs figures out exactly where all the auxiliary programs
-are, and initialises mutable variables to make it easy to call them.
-To do this, it makes use of definitions in Config.hs, which is a Haskell
-file containing variables whose value is figured out by the build system.
-
-Config.hs contains two sorts of things
-
- cGCC, The *names* of the programs
- cCPP e.g. cGCC = gcc
- cUNLIT cCPP = gcc -E
- etc They do *not* include paths
-
-
- cUNLIT_DIR The *path* to the directory containing unlit, split etc
- cSPLIT_DIR *relative* to the root of the build tree,
- for use when running *in-place* in a build tree (only)
-
-
----------------------------------------------
-NOTES for an ALTERNATIVE scheme (i.e *not* what is currently implemented):
-
-Another hair-brained scheme for simplifying the current tool location
-nightmare in GHC: Simon originally suggested using another
-configuration file along the lines of GCC's specs file - which is fine
-except that it means adding code to read yet another configuration
-file. What I didn't notice is that the current package.conf is
-general enough to do this:
-
-Package
- {name = "tools", import_dirs = [], source_dirs = [],
- library_dirs = [], hs_libraries = [], extra_libraries = [],
- include_dirs = [], c_includes = [], package_deps = [],
- extra_ghc_opts = ["-pgmc/usr/bin/gcc","-pgml${topdir}/bin/unlit", ... etc.],
- extra_cc_opts = [], extra_ld_opts = []}
-
-Which would have the advantage that we get to collect together in one
-place the path-specific package stuff with the path-specific tool
-stuff.
- End of NOTES
----------------------------------------------
-
-************************************************************************
-* *
-\subsection{Initialisation}
-* *
-************************************************************************
--}
-
--- Note [LLVM configuration]
--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--- The `llvm-targets` and `llvm-passes` files are shipped with GHC and contain
--- information needed by the LLVM backend to invoke `llc` and `opt`.
--- Specifically:
---
--- * llvm-targets maps autoconf host triples to the corresponding LLVM
--- `data-layout` declarations. This information is extracted from clang using
--- the script in utils/llvm-targets/gen-data-layout.sh and should be updated
--- whenever we target a new version of LLVM.
---
--- * llvm-passes maps GHC optimization levels to sets of LLVM optimization
--- flags that GHC should pass to `opt`.
---
--- This information is contained in files rather the GHC source to allow users
--- to add new targets to GHC without having to recompile the compiler.
---
--- Since this information is only needed by the LLVM backend we load it lazily
--- with unsafeInterleaveIO. Consequently it is important that we lazily pattern
--- match on LlvmConfig until we actually need its contents.
-
-lazyInitLlvmConfig :: String
- -> IO LlvmConfig
-lazyInitLlvmConfig top_dir
- = unsafeInterleaveIO $ do -- see Note [LLVM configuration]
- targets <- readAndParse "llvm-targets" mkLlvmTarget
- passes <- readAndParse "llvm-passes" id
- return $ LlvmConfig { llvmTargets = targets, llvmPasses = passes }
- where
- readAndParse name builder =
- do let llvmConfigFile = top_dir </> name
- llvmConfigStr <- readFile llvmConfigFile
- case maybeReadFuzzy llvmConfigStr of
- Just s -> return (fmap builder <$> s)
- Nothing -> pgmError ("Can't parse " ++ show llvmConfigFile)
-
- mkLlvmTarget :: (String, String, String) -> LlvmTarget
- mkLlvmTarget (dl, cpu, attrs) = LlvmTarget dl cpu (words attrs)
-
-
-initSysTools :: String -- TopDir path
- -> IO Settings -- Set all the mutable variables above, holding
- -- (a) the system programs
- -- (b) the package-config file
- -- (c) the GHC usage message
-initSysTools top_dir = do
- res <- runExceptT $ initSettings top_dir
- case res of
- Right a -> pure a
- Left (SettingsError_MissingData msg) -> pgmError msg
- Left (SettingsError_BadData msg) -> pgmError msg
-
-{- Note [Windows stack usage]
-
-See: #8870 (and #8834 for related info) and #12186
-
-On Windows, occasionally we need to grow the stack. In order to do
-this, we would normally just bump the stack pointer - but there's a
-catch on Windows.
-
-If the stack pointer is bumped by more than a single page, then the
-pages between the initial pointer and the resulting location must be
-properly committed by the Windows virtual memory subsystem. This is
-only needed in the event we bump by more than one page (i.e 4097 bytes
-or more).
-
-Windows compilers solve this by emitting a call to a special function
-called _chkstk, which does this committing of the pages for you.
-
-The reason this was causing a segfault was because due to the fact the
-new code generator tends to generate larger functions, we needed more
-stack space in GHC itself. In the x86 codegen, we needed approximately
-~12kb of stack space in one go, which caused the process to segfault,
-as the intervening pages were not committed.
-
-GCC can emit such a check for us automatically but only when the flag
--fstack-check is used.
-
-See https://gcc.gnu.org/onlinedocs/gnat_ugn/Stack-Overflow-Checking.html
-for more information.
-
--}
-
-copy :: DynFlags -> String -> FilePath -> FilePath -> IO ()
-copy dflags purpose from to = copyWithHeader dflags purpose Nothing from to
-
-copyWithHeader :: DynFlags -> String -> Maybe String -> FilePath -> FilePath
- -> IO ()
-copyWithHeader dflags purpose maybe_header from to = do
- showPass dflags purpose
-
- hout <- openBinaryFile to WriteMode
- hin <- openBinaryFile from ReadMode
- ls <- hGetContents hin -- inefficient, but it'll do for now. ToDo: speed up
- maybe (return ()) (header hout) maybe_header
- hPutStr hout ls
- hClose hout
- hClose hin
- where
- -- write the header string in UTF-8. The header is something like
- -- {-# LINE "foo.hs" #-}
- -- and we want to make sure a Unicode filename isn't mangled.
- header h str = do
- hSetEncoding h utf8
- hPutStr h str
- hSetBinaryMode h True
-
-{-
-************************************************************************
-* *
-\subsection{Support code}
-* *
-************************************************************************
--}
-
-linkDynLib :: DynFlags -> [String] -> [InstalledUnitId] -> IO ()
-linkDynLib dflags0 o_files dep_packages
- = do
- let -- This is a rather ugly hack to fix dynamically linked
- -- GHC on Windows. If GHC is linked with -threaded, then
- -- it links against libHSrts_thr. But if base is linked
- -- against libHSrts, then both end up getting loaded,
- -- and things go wrong. We therefore link the libraries
- -- with the same RTS flags that we link GHC with.
- dflags1 = if platformMisc_ghcThreaded $ platformMisc dflags0
- then addWay' WayThreaded dflags0
- else dflags0
- dflags2 = if platformMisc_ghcDebugged $ platformMisc dflags1
- then addWay' WayDebug dflags1
- else dflags1
- dflags = updateWays dflags2
-
- verbFlags = getVerbFlags dflags
- o_file = outputFile dflags
-
- pkgs <- getPreloadPackagesAnd dflags dep_packages
-
- let pkg_lib_paths = collectLibraryPaths dflags pkgs
- let pkg_lib_path_opts = concatMap get_pkg_lib_path_opts pkg_lib_paths
- get_pkg_lib_path_opts l
- | ( osElfTarget (platformOS (targetPlatform dflags)) ||
- osMachOTarget (platformOS (targetPlatform dflags)) ) &&
- dynLibLoader dflags == SystemDependent &&
- WayDyn `Set.member` ways dflags
- = ["-L" ++ l, "-Xlinker", "-rpath", "-Xlinker", l]
- -- See Note [-Xlinker -rpath vs -Wl,-rpath]
- | otherwise = ["-L" ++ l]
-
- let lib_paths = libraryPaths dflags
- let lib_path_opts = map ("-L"++) lib_paths
-
- -- We don't want to link our dynamic libs against the RTS package,
- -- because the RTS lib comes in several flavours and we want to be
- -- able to pick the flavour when a binary is linked.
- -- On Windows we need to link the RTS import lib as Windows does
- -- not allow undefined symbols.
- -- The RTS library path is still added to the library search path
- -- above in case the RTS is being explicitly linked in (see #3807).
- let platform = targetPlatform dflags
- os = platformOS platform
- pkgs_no_rts = case os of
- OSMinGW32 ->
- pkgs
- _ ->
- filter ((/= rtsUnitId) . packageConfigId) pkgs
- let pkg_link_opts = let (package_hs_libs, extra_libs, other_flags) = collectLinkOpts dflags pkgs_no_rts
- in package_hs_libs ++ extra_libs ++ other_flags
-
- -- probably _stub.o files
- -- and last temporary shared object file
- let extra_ld_inputs = ldInputs dflags
-
- -- frameworks
- pkg_framework_opts <- getPkgFrameworkOpts dflags platform
- (map unitId pkgs)
- let framework_opts = getFrameworkOpts dflags platform
-
- case os of
- OSMinGW32 -> do
- -------------------------------------------------------------
- -- Making a DLL
- -------------------------------------------------------------
- let output_fn = case o_file of
- Just s -> s
- Nothing -> "HSdll.dll"
-
- runLink dflags (
- map Option verbFlags
- ++ [ Option "-o"
- , FileOption "" output_fn
- , Option "-shared"
- ] ++
- [ FileOption "-Wl,--out-implib=" (output_fn ++ ".a")
- | gopt Opt_SharedImplib dflags
- ]
- ++ map (FileOption "") o_files
-
- -- Permit the linker to auto link _symbol to _imp_symbol
- -- This lets us link against DLLs without needing an "import library"
- ++ [Option "-Wl,--enable-auto-import"]
-
- ++ extra_ld_inputs
- ++ map Option (
- lib_path_opts
- ++ pkg_lib_path_opts
- ++ pkg_link_opts
- ))
- _ | os == OSDarwin -> do
- -------------------------------------------------------------------
- -- Making a darwin dylib
- -------------------------------------------------------------------
- -- About the options used for Darwin:
- -- -dynamiclib
- -- Apple's way of saying -shared
- -- -undefined dynamic_lookup:
- -- Without these options, we'd have to specify the correct
- -- dependencies for each of the dylibs. Note that we could
- -- (and should) do without this for all libraries except
- -- the RTS; all we need to do is to pass the correct
- -- HSfoo_dyn.dylib files to the link command.
- -- This feature requires Mac OS X 10.3 or later; there is
- -- a similar feature, -flat_namespace -undefined suppress,
- -- which works on earlier versions, but it has other
- -- disadvantages.
- -- -single_module
- -- Build the dynamic library as a single "module", i.e. no
- -- dynamic binding nonsense when referring to symbols from
- -- within the library. The NCG assumes that this option is
- -- specified (on i386, at least).
- -- -install_name
- -- Mac OS/X stores the path where a dynamic library is (to
- -- be) installed in the library itself. It's called the
- -- "install name" of the library. Then any library or
- -- executable that links against it before it's installed
- -- will search for it in its ultimate install location.
- -- By default we set the install name to the absolute path
- -- at build time, but it can be overridden by the
- -- -dylib-install-name option passed to ghc. Cabal does
- -- this.
- -------------------------------------------------------------------
-
- let output_fn = case o_file of { Just s -> s; Nothing -> "a.out"; }
-
- instName <- case dylibInstallName dflags of
- Just n -> return n
- Nothing -> return $ "@rpath" `combine` (takeFileName output_fn)
- runLink dflags (
- map Option verbFlags
- ++ [ Option "-dynamiclib"
- , Option "-o"
- , FileOption "" output_fn
- ]
- ++ map Option o_files
- ++ [ Option "-undefined",
- Option "dynamic_lookup",
- Option "-single_module" ]
- ++ (if platformArch platform == ArchX86_64
- then [ ]
- else [ Option "-Wl,-read_only_relocs,suppress" ])
- ++ [ Option "-install_name", Option instName ]
- ++ map Option lib_path_opts
- ++ extra_ld_inputs
- ++ map Option framework_opts
- ++ map Option pkg_lib_path_opts
- ++ map Option pkg_link_opts
- ++ map Option pkg_framework_opts
- ++ [ Option "-Wl,-dead_strip_dylibs" ]
- )
- _ -> do
- -------------------------------------------------------------------
- -- Making a DSO
- -------------------------------------------------------------------
-
- let output_fn = case o_file of { Just s -> s; Nothing -> "a.out"; }
- unregisterised = platformUnregisterised (targetPlatform dflags)
- let bsymbolicFlag = -- we need symbolic linking to resolve
- -- non-PIC intra-package-relocations for
- -- performance (where symbolic linking works)
- -- See Note [-Bsymbolic assumptions by GHC]
- ["-Wl,-Bsymbolic" | not unregisterised]
-
- runLink dflags (
- map Option verbFlags
- ++ libmLinkOpts
- ++ [ Option "-o"
- , FileOption "" output_fn
- ]
- ++ map Option o_files
- ++ [ Option "-shared" ]
- ++ map Option bsymbolicFlag
- -- Set the library soname. We use -h rather than -soname as
- -- Solaris 10 doesn't support the latter:
- ++ [ Option ("-Wl,-h," ++ takeFileName output_fn) ]
- ++ extra_ld_inputs
- ++ map Option lib_path_opts
- ++ map Option pkg_lib_path_opts
- ++ map Option pkg_link_opts
- )
-
--- | Some platforms require that we explicitly link against @libm@ if any
--- math-y things are used (which we assume to include all programs). See #14022.
-libmLinkOpts :: [Option]
-libmLinkOpts =
-#if defined(HAVE_LIBM)
- [Option "-lm"]
-#else
- []
-#endif
-
-getPkgFrameworkOpts :: DynFlags -> Platform -> [InstalledUnitId] -> IO [String]
-getPkgFrameworkOpts dflags platform dep_packages
- | platformUsesFrameworks platform = do
- pkg_framework_path_opts <- do
- pkg_framework_paths <- getPackageFrameworkPath dflags dep_packages
- return $ map ("-F" ++) pkg_framework_paths
-
- pkg_framework_opts <- do
- pkg_frameworks <- getPackageFrameworks dflags dep_packages
- return $ concat [ ["-framework", fw] | fw <- pkg_frameworks ]
-
- return (pkg_framework_path_opts ++ pkg_framework_opts)
-
- | otherwise = return []
-
-getFrameworkOpts :: DynFlags -> Platform -> [String]
-getFrameworkOpts dflags platform
- | platformUsesFrameworks platform = framework_path_opts ++ framework_opts
- | otherwise = []
- where
- framework_paths = frameworkPaths dflags
- framework_path_opts = map ("-F" ++) framework_paths
-
- frameworks = cmdlineFrameworks dflags
- -- reverse because they're added in reverse order from the cmd line:
- framework_opts = concat [ ["-framework", fw]
- | fw <- reverse frameworks ]
-
-{-
-Note [-Bsymbolic assumptions by GHC]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-GHC has a few assumptions about interaction of relocations in NCG and linker:
-
-1. -Bsymbolic resolves internal references when the shared library is linked,
- which is important for performance.
-2. When there is a reference to data in a shared library from the main program,
- the runtime linker relocates the data object into the main program using an
- R_*_COPY relocation.
-3. If we used -Bsymbolic, then this results in multiple copies of the data
- object, because some references have already been resolved to point to the
- original instance. This is bad!
-
-We work around [3.] for native compiled code by avoiding the generation of
-R_*_COPY relocations.
-
-Unregisterised compiler can't evade R_*_COPY relocations easily thus we disable
--Bsymbolic linking there.
-
-See related tickets: #4210, #15338
--}
diff --git a/compiler/main/SysTools/BaseDir.hs b/compiler/main/SysTools/BaseDir.hs
deleted file mode 100644
index c4fc71b502..0000000000
--- a/compiler/main/SysTools/BaseDir.hs
+++ /dev/null
@@ -1,137 +0,0 @@
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-{-
------------------------------------------------------------------------------
---
--- (c) The University of Glasgow 2001-2017
---
--- Finding the compiler's base directory.
---
------------------------------------------------------------------------------
--}
-
-module SysTools.BaseDir
- ( expandTopDir, expandToolDir
- , findTopDir, findToolDir
- , tryFindTopDir
- ) where
-
-#include "HsVersions.h"
-
-import GhcPrelude
-
--- See note [Base Dir] for why some of this logic is shared with ghc-pkg.
-import GHC.BaseDir
-
-import Panic
-
-import System.Environment (lookupEnv)
-import System.FilePath
-
--- Windows
-#if defined(mingw32_HOST_OS)
-import System.Directory (doesDirectoryExist)
-#endif
-
-#if defined(mingw32_HOST_OS)
-# if defined(i386_HOST_ARCH)
-# define WINDOWS_CCONV stdcall
-# elif defined(x86_64_HOST_ARCH)
-# define WINDOWS_CCONV ccall
-# else
-# error Unknown mingw32 arch
-# endif
-#endif
-
-{-
-Note [topdir: How GHC finds its files]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-GHC needs various support files (library packages, RTS etc), plus
-various auxiliary programs (cp, gcc, etc). It starts by finding topdir,
-the root of GHC's support files
-
-On Unix:
- - ghc always has a shell wrapper that passes a -B<dir> option
-
-On Windows:
- - ghc never has a shell wrapper.
- - we can find the location of the ghc binary, which is
- $topdir/<foo>/<something>.exe
- where <something> may be "ghc", "ghc-stage2", or similar
- - we strip off the "<foo>/<something>.exe" to leave $topdir.
-
-from topdir we can find package.conf, ghc-asm, etc.
-
-
-Note [tooldir: How GHC finds mingw on Windows]
-
-GHC has some custom logic on Windows for finding the mingw
-toolchain and perl. Depending on whether GHC is built
-with the make build system or Hadrian, and on whether we're
-running a bindist, we might find the mingw toolchain and perl
-either under $topdir/../{mingw, perl}/ or
-$topdir/../../{mingw, perl}/.
-
--}
-
--- | Expand occurrences of the @$tooldir@ interpolation in a string
--- on Windows, leave the string untouched otherwise.
-expandToolDir :: Maybe FilePath -> String -> String
-#if defined(mingw32_HOST_OS)
-expandToolDir (Just tool_dir) s = expandPathVar "tooldir" tool_dir s
-expandToolDir Nothing _ = panic "Could not determine $tooldir"
-#else
-expandToolDir _ s = s
-#endif
-
--- | Returns a Unix-format path pointing to TopDir.
-findTopDir :: Maybe String -- Maybe TopDir path (without the '-B' prefix).
- -> IO String -- TopDir (in Unix format '/' separated)
-findTopDir m_minusb = do
- maybe_exec_dir <- tryFindTopDir m_minusb
- case maybe_exec_dir of
- -- "Just" on Windows, "Nothing" on unix
- Nothing -> throwGhcExceptionIO $
- InstallationError "missing -B<dir> option"
- Just dir -> return dir
-
-tryFindTopDir
- :: Maybe String -- ^ Maybe TopDir path (without the '-B' prefix).
- -> IO (Maybe String) -- ^ TopDir (in Unix format '/' separated)
-tryFindTopDir (Just minusb) = return $ Just $ normalise minusb
-tryFindTopDir Nothing
- = do -- The _GHC_TOP_DIR environment variable can be used to specify
- -- the top dir when the -B argument is not specified. It is not
- -- intended for use by users, it was added specifically for the
- -- purpose of running GHC within GHCi.
- maybe_env_top_dir <- lookupEnv "_GHC_TOP_DIR"
- case maybe_env_top_dir of
- Just env_top_dir -> return $ Just env_top_dir
- -- Try directory of executable
- Nothing -> getBaseDir
-
-
--- See Note [tooldir: How GHC finds mingw and perl on Windows]
--- Returns @Nothing@ when not on Windows.
--- When called on Windows, it either throws an error when the
--- tooldir can't be located, or returns @Just tooldirpath@.
-findToolDir
- :: FilePath -- ^ topdir
- -> IO (Maybe FilePath)
-#if defined(mingw32_HOST_OS)
-findToolDir top_dir = go 0 (top_dir </> "..")
- where maxDepth = 3
- go :: Int -> FilePath -> IO (Maybe FilePath)
- go k path
- | k == maxDepth = throwGhcExceptionIO $
- InstallationError "could not detect mingw toolchain"
- | otherwise = do
- oneLevel <- doesDirectoryExist (path </> "mingw")
- if oneLevel
- then return (Just path)
- else go (k+1) (path </> "..")
-#else
-findToolDir _ = return Nothing
-#endif
diff --git a/compiler/main/SysTools/ExtraObj.hs b/compiler/main/SysTools/ExtraObj.hs
deleted file mode 100644
index 27cc4f7aae..0000000000
--- a/compiler/main/SysTools/ExtraObj.hs
+++ /dev/null
@@ -1,244 +0,0 @@
------------------------------------------------------------------------------
---
--- GHC Extra object linking code
---
--- (c) The GHC Team 2017
---
------------------------------------------------------------------------------
-
-module SysTools.ExtraObj (
- mkExtraObj, mkExtraObjToLinkIntoBinary, mkNoteObjsToLinkIntoBinary,
- checkLinkInfo, getLinkInfo, getCompilerInfo,
- ghcLinkInfoSectionName, ghcLinkInfoNoteName, platformSupportsSavingLinkOpts,
- haveRtsOptsFlags
-) where
-
-import AsmUtils
-import ErrUtils
-import GHC.Driver.Session
-import GHC.Driver.Packages
-import GHC.Platform
-import Outputable
-import GHC.Types.SrcLoc ( noSrcSpan )
-import GHC.Types.Module
-import Elf
-import Util
-import GhcPrelude
-
-import Control.Monad
-import Data.Maybe
-
-import Control.Monad.IO.Class
-
-import FileCleanup
-import SysTools.Tasks
-import SysTools.Info
-
-mkExtraObj :: DynFlags -> Suffix -> String -> IO FilePath
-mkExtraObj dflags extn xs
- = do cFile <- newTempName dflags TFL_CurrentModule extn
- oFile <- newTempName dflags TFL_GhcSession "o"
- writeFile cFile xs
- ccInfo <- liftIO $ getCompilerInfo dflags
- runCc Nothing dflags
- ([Option "-c",
- FileOption "" cFile,
- Option "-o",
- FileOption "" oFile]
- ++ if extn /= "s"
- then cOpts
- else asmOpts ccInfo)
- return oFile
- where
- -- Pass a different set of options to the C compiler depending one whether
- -- we're compiling C or assembler. When compiling C, we pass the usual
- -- set of include directories and PIC flags.
- cOpts = map Option (picCCOpts dflags)
- ++ map (FileOption "-I")
- (includeDirs $ getPackageDetails dflags rtsUnitId)
-
- -- When compiling assembler code, we drop the usual C options, and if the
- -- compiler is Clang, we add an extra argument to tell Clang to ignore
- -- unused command line options. See trac #11684.
- asmOpts ccInfo =
- if any (ccInfo ==) [Clang, AppleClang, AppleClang51]
- then [Option "-Qunused-arguments"]
- else []
-
--- When linking a binary, we need to create a C main() function that
--- starts everything off. This used to be compiled statically as part
--- of the RTS, but that made it hard to change the -rtsopts setting,
--- so now we generate and compile a main() stub as part of every
--- binary and pass the -rtsopts setting directly to the RTS (#5373)
---
--- On Windows, when making a shared library we also may need a DllMain.
---
-mkExtraObjToLinkIntoBinary :: DynFlags -> IO FilePath
-mkExtraObjToLinkIntoBinary dflags = do
- when (gopt Opt_NoHsMain dflags && haveRtsOptsFlags dflags) $ do
- putLogMsg dflags NoReason SevInfo noSrcSpan
- (defaultUserStyle dflags)
- (text "Warning: -rtsopts and -with-rtsopts have no effect with -no-hs-main." $$
- text " Call hs_init_ghc() from your main() function to set these options.")
-
- mkExtraObj dflags "c" (showSDoc dflags main)
- where
- main
- | gopt Opt_NoHsMain dflags = Outputable.empty
- | otherwise
- = case ghcLink dflags of
- LinkDynLib -> if platformOS (targetPlatform dflags) == OSMinGW32
- then dllMain
- else Outputable.empty
- _ -> exeMain
-
- exeMain = vcat [
- text "#include <Rts.h>",
- text "extern StgClosure ZCMain_main_closure;",
- text "int main(int argc, char *argv[])",
- char '{',
- text " RtsConfig __conf = defaultRtsConfig;",
- text " __conf.rts_opts_enabled = "
- <> text (show (rtsOptsEnabled dflags)) <> semi,
- text " __conf.rts_opts_suggestions = "
- <> text (if rtsOptsSuggestions dflags
- then "true"
- else "false") <> semi,
- text "__conf.keep_cafs = "
- <> text (if gopt Opt_KeepCAFs dflags
- then "true"
- else "false") <> semi,
- case rtsOpts dflags of
- Nothing -> Outputable.empty
- Just opts -> text " __conf.rts_opts= " <>
- text (show opts) <> semi,
- text " __conf.rts_hs_main = true;",
- text " return hs_main(argc,argv,&ZCMain_main_closure,__conf);",
- char '}',
- char '\n' -- final newline, to keep gcc happy
- ]
-
- dllMain = vcat [
- text "#include <Rts.h>",
- text "#include <windows.h>",
- text "#include <stdbool.h>",
- char '\n',
- text "bool",
- text "WINAPI",
- text "DllMain ( HINSTANCE hInstance STG_UNUSED",
- text " , DWORD reason STG_UNUSED",
- text " , LPVOID reserved STG_UNUSED",
- text " )",
- text "{",
- text " return true;",
- text "}",
- char '\n' -- final newline, to keep gcc happy
- ]
-
--- Write out the link info section into a new assembly file. Previously
--- this was included as inline assembly in the main.c file but this
--- is pretty fragile. gas gets upset trying to calculate relative offsets
--- that span the .note section (notably .text) when debug info is present
-mkNoteObjsToLinkIntoBinary :: DynFlags -> [InstalledUnitId] -> IO [FilePath]
-mkNoteObjsToLinkIntoBinary dflags dep_packages = do
- link_info <- getLinkInfo dflags dep_packages
-
- if (platformSupportsSavingLinkOpts (platformOS platform ))
- then fmap (:[]) $ mkExtraObj dflags "s" (showSDoc dflags (link_opts link_info))
- else return []
-
- where
- platform = targetPlatform dflags
- link_opts info = hcat [
- -- "link info" section (see Note [LinkInfo section])
- makeElfNote platform ghcLinkInfoSectionName ghcLinkInfoNoteName 0 info,
-
- -- ALL generated assembly must have this section to disable
- -- executable stacks. See also
- -- compiler/nativeGen/AsmCodeGen.hs for another instance
- -- where we need to do this.
- if platformHasGnuNonexecStack platform
- then text ".section .note.GNU-stack,\"\","
- <> sectionType platform "progbits" <> char '\n'
- else Outputable.empty
- ]
-
--- | Return the "link info" string
---
--- See Note [LinkInfo section]
-getLinkInfo :: DynFlags -> [InstalledUnitId] -> IO String
-getLinkInfo dflags dep_packages = do
- package_link_opts <- getPackageLinkOpts dflags dep_packages
- pkg_frameworks <- if platformUsesFrameworks (targetPlatform dflags)
- then getPackageFrameworks dflags dep_packages
- else return []
- let extra_ld_inputs = ldInputs dflags
- let
- link_info = (package_link_opts,
- pkg_frameworks,
- rtsOpts dflags,
- rtsOptsEnabled dflags,
- gopt Opt_NoHsMain dflags,
- map showOpt extra_ld_inputs,
- getOpts dflags opt_l)
- --
- return (show link_info)
-
-platformSupportsSavingLinkOpts :: OS -> Bool
-platformSupportsSavingLinkOpts os
- | os == OSSolaris2 = False -- see #5382
- | otherwise = osElfTarget os
-
--- See Note [LinkInfo section]
-ghcLinkInfoSectionName :: String
-ghcLinkInfoSectionName = ".debug-ghc-link-info"
- -- if we use the ".debug" prefix, then strip will strip it by default
-
--- Identifier for the note (see Note [LinkInfo section])
-ghcLinkInfoNoteName :: String
-ghcLinkInfoNoteName = "GHC link info"
-
--- Returns 'False' if it was, and we can avoid linking, because the
--- previous binary was linked with "the same options".
-checkLinkInfo :: DynFlags -> [InstalledUnitId] -> FilePath -> IO Bool
-checkLinkInfo dflags pkg_deps exe_file
- | not (platformSupportsSavingLinkOpts (platformOS (targetPlatform dflags)))
- -- ToDo: Windows and OS X do not use the ELF binary format, so
- -- readelf does not work there. We need to find another way to do
- -- this.
- = return False -- conservatively we should return True, but not
- -- linking in this case was the behaviour for a long
- -- time so we leave it as-is.
- | otherwise
- = do
- link_info <- getLinkInfo dflags pkg_deps
- debugTraceMsg dflags 3 $ text ("Link info: " ++ link_info)
- m_exe_link_info <- readElfNoteAsString dflags exe_file
- ghcLinkInfoSectionName ghcLinkInfoNoteName
- let sameLinkInfo = (Just link_info == m_exe_link_info)
- debugTraceMsg dflags 3 $ case m_exe_link_info of
- Nothing -> text "Exe link info: Not found"
- Just s
- | sameLinkInfo -> text ("Exe link info is the same")
- | otherwise -> text ("Exe link info is different: " ++ s)
- return (not sameLinkInfo)
-
-{- Note [LinkInfo section]
- ~~~~~~~~~~~~~~~~~~~~~~~
-
-The "link info" is a string representing the parameters of the link. We save
-this information in the binary, and the next time we link, if nothing else has
-changed, we use the link info stored in the existing binary to decide whether
-to re-link or not.
-
-The "link info" string is stored in a ELF section called ".debug-ghc-link-info"
-(see ghcLinkInfoSectionName) with the SHT_NOTE type. For some time, it used to
-not follow the specified record-based format (see #11022).
-
--}
-
-haveRtsOptsFlags :: DynFlags -> Bool
-haveRtsOptsFlags dflags =
- isJust (rtsOpts dflags) || case rtsOptsEnabled dflags of
- RtsOptsSafeOnly -> False
- _ -> True
diff --git a/compiler/main/SysTools/Info.hs b/compiler/main/SysTools/Info.hs
deleted file mode 100644
index b6b74406af..0000000000
--- a/compiler/main/SysTools/Info.hs
+++ /dev/null
@@ -1,262 +0,0 @@
-{-# LANGUAGE ScopedTypeVariables #-}
------------------------------------------------------------------------------
---
--- Compiler information functions
---
--- (c) The GHC Team 2017
---
------------------------------------------------------------------------------
-module SysTools.Info where
-
-import Exception
-import ErrUtils
-import GHC.Driver.Session
-import Outputable
-import Util
-
-import Data.List
-import Data.IORef
-
-import System.IO
-
-import GHC.Platform
-import GhcPrelude
-
-import SysTools.Process
-
-{- Note [Run-time linker info]
-
-See also: #5240, #6063, #10110
-
-Before 'runLink', we need to be sure to get the relevant information
-about the linker we're using at runtime to see if we need any extra
-options. For example, GNU ld requires '--reduce-memory-overheads' and
-'--hash-size=31' in order to use reasonable amounts of memory (see
-trac #5240.) But this isn't supported in GNU gold.
-
-Generally, the linker changing from what was detected at ./configure
-time has always been possible using -pgml, but on Linux it can happen
-'transparently' by installing packages like binutils-gold, which
-change what /usr/bin/ld actually points to.
-
-Clang vs GCC notes:
-
-For gcc, 'gcc -Wl,--version' gives a bunch of output about how to
-invoke the linker before the version information string. For 'clang',
-the version information for 'ld' is all that's output. For this
-reason, we typically need to slurp up all of the standard error output
-and look through it.
-
-Other notes:
-
-We cache the LinkerInfo inside DynFlags, since clients may link
-multiple times. The definition of LinkerInfo is there to avoid a
-circular dependency.
-
--}
-
-{- Note [ELF needed shared libs]
-
-Some distributions change the link editor's default handling of
-ELF DT_NEEDED tags to include only those shared objects that are
-needed to resolve undefined symbols. For Template Haskell we need
-the last temporary shared library also if it is not needed for the
-currently linked temporary shared library. We specify --no-as-needed
-to override the default. This flag exists in GNU ld and GNU gold.
-
-The flag is only needed on ELF systems. On Windows (PE) and Mac OS X
-(Mach-O) the flag is not needed.
-
--}
-
-{- Note [Windows static libGCC]
-
-The GCC versions being upgraded to in #10726 are configured with
-dynamic linking of libgcc supported. This results in libgcc being
-linked dynamically when a shared library is created.
-
-This introduces thus an extra dependency on GCC dll that was not
-needed before by shared libraries created with GHC. This is a particular
-issue on Windows because you get a non-obvious error due to this missing
-dependency. This dependent dll is also not commonly on your path.
-
-For this reason using the static libgcc is preferred as it preserves
-the same behaviour that existed before. There are however some very good
-reasons to have the shared version as well as described on page 181 of
-https://gcc.gnu.org/onlinedocs/gcc-5.2.0/gcc.pdf :
-
-"There are several situations in which an application should use the
- shared ‘libgcc’ instead of the static version. The most common of these
- is when the application wishes to throw and catch exceptions across different
- shared libraries. In that case, each of the libraries as well as the application
- itself should use the shared ‘libgcc’. "
-
--}
-
-neededLinkArgs :: LinkerInfo -> [Option]
-neededLinkArgs (GnuLD o) = o
-neededLinkArgs (GnuGold o) = o
-neededLinkArgs (LlvmLLD o) = o
-neededLinkArgs (DarwinLD o) = o
-neededLinkArgs (SolarisLD o) = o
-neededLinkArgs (AixLD o) = o
-neededLinkArgs UnknownLD = []
-
--- Grab linker info and cache it in DynFlags.
-getLinkerInfo :: DynFlags -> IO LinkerInfo
-getLinkerInfo dflags = do
- info <- readIORef (rtldInfo dflags)
- case info of
- Just v -> return v
- Nothing -> do
- v <- getLinkerInfo' dflags
- writeIORef (rtldInfo dflags) (Just v)
- return v
-
--- See Note [Run-time linker info].
-getLinkerInfo' :: DynFlags -> IO LinkerInfo
-getLinkerInfo' dflags = do
- let platform = targetPlatform dflags
- os = platformOS platform
- (pgm,args0) = pgm_l dflags
- args1 = map Option (getOpts dflags opt_l)
- args2 = args0 ++ args1
- args3 = filter notNull (map showOpt args2)
-
- -- Try to grab the info from the process output.
- parseLinkerInfo stdo _stde _exitc
- | any ("GNU ld" `isPrefixOf`) stdo =
- -- GNU ld specifically needs to use less memory. This especially
- -- hurts on small object files. #5240.
- -- Set DT_NEEDED for all shared libraries. #10110.
- -- TODO: Investigate if these help or hurt when using split sections.
- return (GnuLD $ map Option ["-Wl,--hash-size=31",
- "-Wl,--reduce-memory-overheads",
- -- ELF specific flag
- -- see Note [ELF needed shared libs]
- "-Wl,--no-as-needed"])
-
- | any ("GNU gold" `isPrefixOf`) stdo =
- -- GNU gold only needs --no-as-needed. #10110.
- -- ELF specific flag, see Note [ELF needed shared libs]
- return (GnuGold [Option "-Wl,--no-as-needed"])
-
- | any ("LLD" `isPrefixOf`) stdo =
- return (LlvmLLD $ map Option [
- -- see Note [ELF needed shared libs]
- "-Wl,--no-as-needed"])
-
- -- Unknown linker.
- | otherwise = fail "invalid --version output, or linker is unsupported"
-
- -- Process the executable call
- info <- catchIO (do
- case os of
- OSSolaris2 ->
- -- Solaris uses its own Solaris linker. Even all
- -- GNU C are recommended to configure with Solaris
- -- linker instead of using GNU binutils linker. Also
- -- all GCC distributed with Solaris follows this rule
- -- precisely so we assume here, the Solaris linker is
- -- used.
- return $ SolarisLD []
- OSAIX ->
- -- IBM AIX uses its own non-binutils linker as well
- return $ AixLD []
- OSDarwin ->
- -- Darwin has neither GNU Gold or GNU LD, but a strange linker
- -- that doesn't support --version. We can just assume that's
- -- what we're using.
- return $ DarwinLD []
- OSMinGW32 ->
- -- GHC doesn't support anything but GNU ld on Windows anyway.
- -- Process creation is also fairly expensive on win32, so
- -- we short-circuit here.
- return $ GnuLD $ map Option
- [ -- Reduce ld memory usage
- "-Wl,--hash-size=31"
- , "-Wl,--reduce-memory-overheads"
- -- Emit gcc stack checks
- -- Note [Windows stack usage]
- , "-fstack-check"
- -- Force static linking of libGCC
- -- Note [Windows static libGCC]
- , "-static-libgcc" ]
- _ -> do
- -- In practice, we use the compiler as the linker here. Pass
- -- -Wl,--version to get linker version info.
- (exitc, stdo, stde) <- readProcessEnvWithExitCode pgm
- (["-Wl,--version"] ++ args3)
- c_locale_env
- -- Split the output by lines to make certain kinds
- -- of processing easier. In particular, 'clang' and 'gcc'
- -- have slightly different outputs for '-Wl,--version', but
- -- it's still easy to figure out.
- parseLinkerInfo (lines stdo) (lines stde) exitc
- )
- (\err -> do
- debugTraceMsg dflags 2
- (text "Error (figuring out linker information):" <+>
- text (show err))
- errorMsg dflags $ hang (text "Warning:") 9 $
- text "Couldn't figure out linker information!" $$
- text "Make sure you're using GNU ld, GNU gold" <+>
- text "or the built in OS X linker, etc."
- return UnknownLD)
- return info
-
--- Grab compiler info and cache it in DynFlags.
-getCompilerInfo :: DynFlags -> IO CompilerInfo
-getCompilerInfo dflags = do
- info <- readIORef (rtccInfo dflags)
- case info of
- Just v -> return v
- Nothing -> do
- v <- getCompilerInfo' dflags
- writeIORef (rtccInfo dflags) (Just v)
- return v
-
--- See Note [Run-time linker info].
-getCompilerInfo' :: DynFlags -> IO CompilerInfo
-getCompilerInfo' dflags = do
- let pgm = pgm_c dflags
- -- Try to grab the info from the process output.
- parseCompilerInfo _stdo stde _exitc
- -- Regular GCC
- | any ("gcc version" `isInfixOf`) stde =
- return GCC
- -- Regular clang
- | any ("clang version" `isInfixOf`) stde =
- return Clang
- -- FreeBSD clang
- | any ("FreeBSD clang version" `isInfixOf`) stde =
- return Clang
- -- Xcode 5.1 clang
- | any ("Apple LLVM version 5.1" `isPrefixOf`) stde =
- return AppleClang51
- -- Xcode 5 clang
- | any ("Apple LLVM version" `isPrefixOf`) stde =
- return AppleClang
- -- Xcode 4.1 clang
- | any ("Apple clang version" `isPrefixOf`) stde =
- return AppleClang
- -- Unknown linker.
- | otherwise = fail "invalid -v output, or compiler is unsupported"
-
- -- Process the executable call
- info <- catchIO (do
- (exitc, stdo, stde) <-
- readProcessEnvWithExitCode pgm ["-v"] c_locale_env
- -- Split the output by lines to make certain kinds
- -- of processing easier.
- parseCompilerInfo (lines stdo) (lines stde) exitc
- )
- (\err -> do
- debugTraceMsg dflags 2
- (text "Error (figuring out C compiler information):" <+>
- text (show err))
- errorMsg dflags $ hang (text "Warning:") 9 $
- text "Couldn't figure out C compiler information!" $$
- text "Make sure you're using GNU gcc, or clang"
- return UnknownCC)
- return info
diff --git a/compiler/main/SysTools/Process.hs b/compiler/main/SysTools/Process.hs
deleted file mode 100644
index eda4b29bc0..0000000000
--- a/compiler/main/SysTools/Process.hs
+++ /dev/null
@@ -1,387 +0,0 @@
-{-# LANGUAGE CPP #-}
------------------------------------------------------------------------------
---
--- Misc process handling code for SysTools
---
--- (c) The GHC Team 2017
---
------------------------------------------------------------------------------
-module SysTools.Process where
-
-#include "HsVersions.h"
-
-import Exception
-import ErrUtils
-import GHC.Driver.Session
-import FastString
-import Outputable
-import Panic
-import GhcPrelude
-import Util
-import GHC.Types.SrcLoc ( SrcLoc, mkSrcLoc, noSrcSpan, mkSrcSpan )
-
-import Control.Concurrent
-import Data.Char
-
-import System.Exit
-import System.Environment
-import System.FilePath
-import System.IO
-import System.IO.Error as IO
-import System.Process
-
-import FileCleanup
-
--- | Enable process jobs support on Windows if it can be expected to work (e.g.
--- @process >= 1.6.8.0@).
-enableProcessJobs :: CreateProcess -> CreateProcess
-#if defined(MIN_VERSION_process)
-enableProcessJobs opts = opts { use_process_jobs = True }
-#else
-enableProcessJobs opts = opts
-#endif
-
--- Similar to System.Process.readCreateProcessWithExitCode, but stderr is
--- inherited from the parent process, and output to stderr is not captured.
-readCreateProcessWithExitCode'
- :: CreateProcess
- -> IO (ExitCode, String) -- ^ stdout
-readCreateProcessWithExitCode' proc = do
- (_, Just outh, _, pid) <-
- createProcess proc{ std_out = CreatePipe }
-
- -- fork off a thread to start consuming the output
- output <- hGetContents outh
- outMVar <- newEmptyMVar
- _ <- forkIO $ evaluate (length output) >> putMVar outMVar ()
-
- -- wait on the output
- takeMVar outMVar
- hClose outh
-
- -- wait on the process
- ex <- waitForProcess pid
-
- return (ex, output)
-
-replaceVar :: (String, String) -> [(String, String)] -> [(String, String)]
-replaceVar (var, value) env =
- (var, value) : filter (\(var',_) -> var /= var') env
-
--- | Version of @System.Process.readProcessWithExitCode@ that takes a
--- key-value tuple to insert into the environment.
-readProcessEnvWithExitCode
- :: String -- ^ program path
- -> [String] -- ^ program args
- -> (String, String) -- ^ addition to the environment
- -> IO (ExitCode, String, String) -- ^ (exit_code, stdout, stderr)
-readProcessEnvWithExitCode prog args env_update = do
- current_env <- getEnvironment
- readCreateProcessWithExitCode (enableProcessJobs $ proc prog args) {
- env = Just (replaceVar env_update current_env) } ""
-
--- Don't let gcc localize version info string, #8825
-c_locale_env :: (String, String)
-c_locale_env = ("LANGUAGE", "C")
-
--- If the -B<dir> option is set, add <dir> to PATH. This works around
--- a bug in gcc on Windows Vista where it can't find its auxiliary
--- binaries (see bug #1110).
-getGccEnv :: [Option] -> IO (Maybe [(String,String)])
-getGccEnv opts =
- if null b_dirs
- then return Nothing
- else do env <- getEnvironment
- return (Just (mangle_paths env))
- where
- (b_dirs, _) = partitionWith get_b_opt opts
-
- get_b_opt (Option ('-':'B':dir)) = Left dir
- get_b_opt other = Right other
-
- -- Work around #1110 on Windows only (lest we stumble into #17266).
-#if defined(mingw32_HOST_OS)
- mangle_paths = map mangle_path
- mangle_path (path,paths) | map toUpper path == "PATH"
- = (path, '\"' : head b_dirs ++ "\";" ++ paths)
- mangle_path other = other
-#else
- mangle_paths = id
-#endif
-
-
------------------------------------------------------------------------------
--- Running an external program
-
-runSomething :: DynFlags
- -> String -- For -v message
- -> String -- Command name (possibly a full path)
- -- assumed already dos-ified
- -> [Option] -- Arguments
- -- runSomething will dos-ify them
- -> IO ()
-
-runSomething dflags phase_name pgm args =
- runSomethingFiltered dflags id phase_name pgm args Nothing Nothing
-
--- | Run a command, placing the arguments in an external response file.
---
--- This command is used in order to avoid overlong command line arguments on
--- Windows. The command line arguments are first written to an external,
--- temporary response file, and then passed to the linker via @filepath.
--- response files for passing them in. See:
---
--- https://gcc.gnu.org/wiki/Response_Files
--- https://gitlab.haskell.org/ghc/ghc/issues/10777
-runSomethingResponseFile
- :: DynFlags -> (String->String) -> String -> String -> [Option]
- -> Maybe [(String,String)] -> IO ()
-
-runSomethingResponseFile dflags filter_fn phase_name pgm args mb_env =
- runSomethingWith dflags phase_name pgm args $ \real_args -> do
- fp <- getResponseFile real_args
- let args = ['@':fp]
- r <- builderMainLoop dflags filter_fn pgm args Nothing mb_env
- return (r,())
- where
- getResponseFile args = do
- fp <- newTempName dflags TFL_CurrentModule "rsp"
- withFile fp WriteMode $ \h -> do
-#if defined(mingw32_HOST_OS)
- hSetEncoding h latin1
-#else
- hSetEncoding h utf8
-#endif
- hPutStr h $ unlines $ map escape args
- return fp
-
- -- Note: Response files have backslash-escaping, double quoting, and are
- -- whitespace separated (some implementations use newline, others any
- -- whitespace character). Therefore, escape any backslashes, newlines, and
- -- double quotes in the argument, and surround the content with double
- -- quotes.
- --
- -- Another possibility that could be considered would be to convert
- -- backslashes in the argument to forward slashes. This would generally do
- -- the right thing, since backslashes in general only appear in arguments
- -- as part of file paths on Windows, and the forward slash is accepted for
- -- those. However, escaping is more reliable, in case somehow a backslash
- -- appears in a non-file.
- escape x = concat
- [ "\""
- , concatMap
- (\c ->
- case c of
- '\\' -> "\\\\"
- '\n' -> "\\n"
- '\"' -> "\\\""
- _ -> [c])
- x
- , "\""
- ]
-
-runSomethingFiltered
- :: DynFlags -> (String->String) -> String -> String -> [Option]
- -> Maybe FilePath -> Maybe [(String,String)] -> IO ()
-
-runSomethingFiltered dflags filter_fn phase_name pgm args mb_cwd mb_env = do
- runSomethingWith dflags phase_name pgm args $ \real_args -> do
- r <- builderMainLoop dflags filter_fn pgm real_args mb_cwd mb_env
- return (r,())
-
-runSomethingWith
- :: DynFlags -> String -> String -> [Option]
- -> ([String] -> IO (ExitCode, a))
- -> IO a
-
-runSomethingWith dflags phase_name pgm args io = do
- let real_args = filter notNull (map showOpt args)
- cmdLine = showCommandForUser pgm real_args
- traceCmd dflags phase_name cmdLine $ handleProc pgm phase_name $ io real_args
-
-handleProc :: String -> String -> IO (ExitCode, r) -> IO r
-handleProc pgm phase_name proc = do
- (rc, r) <- proc `catchIO` handler
- case rc of
- ExitSuccess{} -> return r
- ExitFailure n -> throwGhcExceptionIO (
- ProgramError ("`" ++ takeFileName pgm ++ "'" ++
- " failed in phase `" ++ phase_name ++ "'." ++
- " (Exit code: " ++ show n ++ ")"))
- where
- handler err =
- if IO.isDoesNotExistError err
- then does_not_exist
- else throwGhcExceptionIO (ProgramError $ show err)
-
- does_not_exist = throwGhcExceptionIO (InstallationError ("could not execute: " ++ pgm))
-
-
-builderMainLoop :: DynFlags -> (String -> String) -> FilePath
- -> [String] -> Maybe FilePath -> Maybe [(String, String)]
- -> IO ExitCode
-builderMainLoop dflags filter_fn pgm real_args mb_cwd mb_env = do
- chan <- newChan
-
- -- We use a mask here rather than a bracket because we want
- -- to distinguish between cleaning up with and without an
- -- exception. This is to avoid calling terminateProcess
- -- unless an exception was raised.
- let safely inner = mask $ \restore -> do
- -- acquire
- -- On Windows due to how exec is emulated the old process will exit and
- -- a new process will be created. This means waiting for termination of
- -- the parent process will get you in a race condition as the child may
- -- not have finished yet. This caused #16450. To fix this use a
- -- process job to track all child processes and wait for each one to
- -- finish.
- let procdata =
- enableProcessJobs
- $ (proc pgm real_args) { cwd = mb_cwd
- , env = mb_env
- , std_in = CreatePipe
- , std_out = CreatePipe
- , std_err = CreatePipe
- }
- (Just hStdIn, Just hStdOut, Just hStdErr, hProcess) <- restore $
- createProcess_ "builderMainLoop" procdata
- let cleanup_handles = do
- hClose hStdIn
- hClose hStdOut
- hClose hStdErr
- r <- try $ restore $ do
- hSetBuffering hStdOut LineBuffering
- hSetBuffering hStdErr LineBuffering
- let make_reader_proc h = forkIO $ readerProc chan h filter_fn
- bracketOnError (make_reader_proc hStdOut) killThread $ \_ ->
- bracketOnError (make_reader_proc hStdErr) killThread $ \_ ->
- inner hProcess
- case r of
- -- onException
- Left (SomeException e) -> do
- terminateProcess hProcess
- cleanup_handles
- throw e
- -- cleanup when there was no exception
- Right s -> do
- cleanup_handles
- return s
- safely $ \h -> do
- -- we don't want to finish until 2 streams have been complete
- -- (stdout and stderr)
- log_loop chan (2 :: Integer)
- -- after that, we wait for the process to finish and return the exit code.
- waitForProcess h
- where
- -- t starts at the number of streams we're listening to (2) decrements each
- -- time a reader process sends EOF. We are safe from looping forever if a
- -- reader thread dies, because they send EOF in a finally handler.
- log_loop _ 0 = return ()
- log_loop chan t = do
- msg <- readChan chan
- case msg of
- BuildMsg msg -> do
- putLogMsg dflags NoReason SevInfo noSrcSpan
- (defaultUserStyle dflags) msg
- log_loop chan t
- BuildError loc msg -> do
- putLogMsg dflags NoReason SevError (mkSrcSpan loc loc)
- (defaultUserStyle dflags) msg
- log_loop chan t
- EOF ->
- log_loop chan (t-1)
-
-readerProc :: Chan BuildMessage -> Handle -> (String -> String) -> IO ()
-readerProc chan hdl filter_fn =
- (do str <- hGetContents hdl
- loop (linesPlatform (filter_fn str)) Nothing)
- `finally`
- writeChan chan EOF
- -- ToDo: check errors more carefully
- -- ToDo: in the future, the filter should be implemented as
- -- a stream transformer.
- where
- loop [] Nothing = return ()
- loop [] (Just err) = writeChan chan err
- loop (l:ls) in_err =
- case in_err of
- Just err@(BuildError srcLoc msg)
- | leading_whitespace l -> do
- loop ls (Just (BuildError srcLoc (msg $$ text l)))
- | otherwise -> do
- writeChan chan err
- checkError l ls
- Nothing -> do
- checkError l ls
- _ -> panic "readerProc/loop"
-
- checkError l ls
- = case parseError l of
- Nothing -> do
- writeChan chan (BuildMsg (text l))
- loop ls Nothing
- Just (file, lineNum, colNum, msg) -> do
- let srcLoc = mkSrcLoc (mkFastString file) lineNum colNum
- loop ls (Just (BuildError srcLoc (text msg)))
-
- leading_whitespace [] = False
- leading_whitespace (x:_) = isSpace x
-
-parseError :: String -> Maybe (String, Int, Int, String)
-parseError s0 = case breakColon s0 of
- Just (filename, s1) ->
- case breakIntColon s1 of
- Just (lineNum, s2) ->
- case breakIntColon s2 of
- Just (columnNum, s3) ->
- Just (filename, lineNum, columnNum, s3)
- Nothing ->
- Just (filename, lineNum, 0, s2)
- Nothing -> Nothing
- Nothing -> Nothing
-
--- | Break a line of an error message into a filename and the rest of the line,
--- taking care to ignore colons in Windows drive letters (as noted in #17786).
--- For instance,
---
--- * @"hi.c: ABCD"@ is mapped to @Just ("hi.c", "ABCD")@
--- * @"C:\hi.c: ABCD"@ is mapped to @Just ("C:\hi.c", "ABCD")@
-breakColon :: String -> Maybe (String, String)
-breakColon = go []
- where
- -- Don't break on Windows drive letters (e.g. @C:\@ or @C:/@)
- go accum (':':'\\':rest) = go ('\\':':':accum) rest
- go accum (':':'/':rest) = go ('/':':':accum) rest
- go accum (':':rest) = Just (reverse accum, rest)
- go accum (c:rest) = go (c:accum) rest
- go _accum [] = Nothing
-
-breakIntColon :: String -> Maybe (Int, String)
-breakIntColon xs = case break (':' ==) xs of
- (ys, _:zs)
- | not (null ys) && all isAscii ys && all isDigit ys ->
- Just (read ys, zs)
- _ -> Nothing
-
-data BuildMessage
- = BuildMsg !SDoc
- | BuildError !SrcLoc !SDoc
- | EOF
-
--- Divvy up text stream into lines, taking platform dependent
--- line termination into account.
-linesPlatform :: String -> [String]
-#if !defined(mingw32_HOST_OS)
-linesPlatform ls = lines ls
-#else
-linesPlatform "" = []
-linesPlatform xs =
- case lineBreak xs of
- (as,xs1) -> as : linesPlatform xs1
- where
- lineBreak "" = ("","")
- lineBreak ('\r':'\n':xs) = ([],xs)
- lineBreak ('\n':xs) = ([],xs)
- lineBreak (x:xs) = let (as,bs) = lineBreak xs in (x:as,bs)
-
-#endif
diff --git a/compiler/main/SysTools/Settings.hs b/compiler/main/SysTools/Settings.hs
deleted file mode 100644
index 42763f239a..0000000000
--- a/compiler/main/SysTools/Settings.hs
+++ /dev/null
@@ -1,253 +0,0 @@
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module SysTools.Settings
- ( SettingsError (..)
- , initSettings
- ) where
-
-#include "HsVersions.h"
-
-import GhcPrelude
-
-import GHC.Settings
-
-import Config
-import CliOption
-import FileSettings
-import Fingerprint
-import GHC.Platform
-import GhcNameVersion
-import Outputable
-import Settings
-import SysTools.BaseDir
-import ToolSettings
-
-import Control.Monad.Trans.Except
-import Control.Monad.IO.Class
-import qualified Data.Map as Map
-import System.FilePath
-import System.Directory
-
-data SettingsError
- = SettingsError_MissingData String
- | SettingsError_BadData String
-
-initSettings
- :: forall m
- . MonadIO m
- => String -- ^ TopDir path
- -> ExceptT SettingsError m Settings
-initSettings top_dir = do
- -- see Note [topdir: How GHC finds its files]
- -- NB: top_dir is assumed to be in standard Unix
- -- format, '/' separated
- mtool_dir <- liftIO $ findToolDir top_dir
- -- see Note [tooldir: How GHC finds mingw on Windows]
-
- let installed :: FilePath -> FilePath
- installed file = top_dir </> file
- libexec :: FilePath -> FilePath
- libexec file = top_dir </> "bin" </> file
- settingsFile = installed "settings"
- platformConstantsFile = installed "platformConstants"
-
- readFileSafe :: FilePath -> ExceptT SettingsError m String
- readFileSafe path = liftIO (doesFileExist path) >>= \case
- True -> liftIO $ readFile path
- False -> throwE $ SettingsError_MissingData $ "Missing file: " ++ path
-
- settingsStr <- readFileSafe settingsFile
- platformConstantsStr <- readFileSafe platformConstantsFile
- settingsList <- case maybeReadFuzzy settingsStr of
- Just s -> pure s
- Nothing -> throwE $ SettingsError_BadData $
- "Can't parse " ++ show settingsFile
- let mySettings = Map.fromList settingsList
- platformConstants <- case maybeReadFuzzy platformConstantsStr of
- Just s -> pure s
- Nothing -> throwE $ SettingsError_BadData $
- "Can't parse " ++ show platformConstantsFile
- -- See Note [Settings file] for a little more about this file. We're
- -- 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
- 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
- targetPlatformString <- getSetting "target platform string"
- tablesNextToCode <- getBooleanSetting "Tables next to code"
- myExtraGccViaCFlags <- getSetting "GCC extra via C opts"
- -- On Windows, mingw is distributed with GHC,
- -- so we look in TopDir/../mingw/bin,
- -- as well as TopDir/../../mingw/bin for hadrian.
- -- It would perhaps be nice to be able to override this
- -- with the settings file, but it would be a little fiddly
- -- to make that possible, so for now you can't.
- cc_prog <- getToolSetting "C compiler command"
- cc_args_str <- getSetting "C compiler flags"
- cxx_args_str <- getSetting "C++ compiler flags"
- gccSupportsNoPie <- getBooleanSetting "C compiler supports -no-pie"
- cpp_prog <- getToolSetting "Haskell CPP command"
- cpp_args_str <- getSetting "Haskell CPP flags"
-
- platform <- either pgmError pure $ getTargetPlatform settingsFile mySettings
-
- let unreg_cc_args = if platformUnregisterised platform
- then ["-DNO_REGS", "-DUSE_MINIINTERPRETER"]
- else []
- cpp_args = map Option (words cpp_args_str)
- cc_args = words cc_args_str ++ unreg_cc_args
- cxx_args = words cxx_args_str
- ldSupportsCompactUnwind <- getBooleanSetting "ld supports compact unwind"
- ldSupportsBuildId <- getBooleanSetting "ld supports build-id"
- ldSupportsFilelist <- getBooleanSetting "ld supports filelist"
- ldIsGnuLd <- getBooleanSetting "ld is GNU ld"
-
- let globalpkgdb_path = installed "package.conf.d"
- ghc_usage_msg_path = installed "ghc-usage.txt"
- ghci_usage_msg_path = installed "ghci-usage.txt"
-
- -- For all systems, unlit, split, mangle are GHC utilities
- -- architecture-specific stuff is done when building Config.hs
- unlit_path <- getToolSetting "unlit command"
-
- windres_path <- getToolSetting "windres command"
- libtool_path <- getToolSetting "libtool command"
- ar_path <- getToolSetting "ar command"
- ranlib_path <- getToolSetting "ranlib command"
-
- -- TODO this side-effect doesn't belong here. Reading and parsing the settings
- -- should be idempotent and accumulate no resources.
- tmpdir <- liftIO $ getTemporaryDirectory
-
- touch_path <- getToolSetting "touch command"
-
- mkdll_prog <- getToolSetting "dllwrap command"
- let mkdll_args = []
-
- -- cpp is derived from gcc on all platforms
- -- HACK, see setPgmP below. We keep 'words' here to remember to fix
- -- Config.hs one day.
-
-
- -- Other things being equal, as and ld are simply gcc
- cc_link_args_str <- getSetting "C compiler link flags"
- let as_prog = cc_prog
- as_args = map Option cc_args
- ld_prog = cc_prog
- ld_args = map Option (cc_args ++ words cc_link_args_str)
-
- llvmTarget <- getSetting "LLVM target"
-
- -- We just assume on command line
- lc_prog <- getSetting "LLVM llc command"
- lo_prog <- getSetting "LLVM opt command"
- lcc_prog <- getSetting "LLVM clang command"
-
- let iserv_prog = libexec "ghc-iserv"
-
- integerLibrary <- getSetting "integer library"
- integerLibraryType <- case integerLibrary of
- "integer-gmp" -> pure IntegerGMP
- "integer-simple" -> pure IntegerSimple
- _ -> pgmError $ unwords
- [ "Entry for"
- , show "integer library"
- , "must be one of"
- , show "integer-gmp"
- , "or"
- , show "integer-simple"
- ]
-
- ghcWithInterpreter <- getBooleanSetting "Use interpreter"
- ghcWithNativeCodeGen <- getBooleanSetting "Use native code generator"
- ghcWithSMP <- getBooleanSetting "Support SMP"
- ghcRTSWays <- getSetting "RTS ways"
- leadingUnderscore <- getBooleanSetting "Leading underscore"
- useLibFFI <- getBooleanSetting "Use LibFFI"
- ghcThreaded <- getBooleanSetting "Use Threads"
- ghcDebugged <- getBooleanSetting "Use Debugging"
- ghcRtsWithLibdw <- getBooleanSetting "RTS expects libdw"
-
- return $ Settings
- { sGhcNameVersion = GhcNameVersion
- { ghcNameVersion_programName = "ghc"
- , ghcNameVersion_projectVersion = cProjectVersion
- }
-
- , sFileSettings = FileSettings
- { fileSettings_tmpDir = normalise tmpdir
- , fileSettings_ghcUsagePath = ghc_usage_msg_path
- , fileSettings_ghciUsagePath = ghci_usage_msg_path
- , fileSettings_toolDir = mtool_dir
- , fileSettings_topDir = top_dir
- , fileSettings_globalPackageDatabase = globalpkgdb_path
- }
-
- , sToolSettings = ToolSettings
- { toolSettings_ldSupportsCompactUnwind = ldSupportsCompactUnwind
- , toolSettings_ldSupportsBuildId = ldSupportsBuildId
- , toolSettings_ldSupportsFilelist = ldSupportsFilelist
- , toolSettings_ldIsGnuLd = ldIsGnuLd
- , toolSettings_ccSupportsNoPie = gccSupportsNoPie
-
- , toolSettings_pgm_L = unlit_path
- , toolSettings_pgm_P = (cpp_prog, cpp_args)
- , toolSettings_pgm_F = ""
- , toolSettings_pgm_c = cc_prog
- , toolSettings_pgm_a = (as_prog, as_args)
- , toolSettings_pgm_l = (ld_prog, ld_args)
- , toolSettings_pgm_dll = (mkdll_prog,mkdll_args)
- , toolSettings_pgm_T = touch_path
- , toolSettings_pgm_windres = windres_path
- , toolSettings_pgm_libtool = libtool_path
- , toolSettings_pgm_ar = ar_path
- , toolSettings_pgm_ranlib = ranlib_path
- , toolSettings_pgm_lo = (lo_prog,[])
- , toolSettings_pgm_lc = (lc_prog,[])
- , toolSettings_pgm_lcc = (lcc_prog,[])
- , toolSettings_pgm_i = iserv_prog
- , toolSettings_opt_L = []
- , toolSettings_opt_P = []
- , toolSettings_opt_P_fingerprint = fingerprint0
- , toolSettings_opt_F = []
- , toolSettings_opt_c = cc_args
- , toolSettings_opt_cxx = cxx_args
- , toolSettings_opt_a = []
- , toolSettings_opt_l = []
- , toolSettings_opt_windres = []
- , toolSettings_opt_lcc = []
- , toolSettings_opt_lo = []
- , toolSettings_opt_lc = []
- , toolSettings_opt_i = []
-
- , toolSettings_extraGccViaCFlags = words myExtraGccViaCFlags
- }
-
- , sTargetPlatform = platform
- , sPlatformMisc = PlatformMisc
- { platformMisc_targetPlatformString = targetPlatformString
- , platformMisc_integerLibrary = integerLibrary
- , platformMisc_integerLibraryType = integerLibraryType
- , platformMisc_ghcWithInterpreter = ghcWithInterpreter
- , platformMisc_ghcWithNativeCodeGen = ghcWithNativeCodeGen
- , platformMisc_ghcWithSMP = ghcWithSMP
- , platformMisc_ghcRTSWays = ghcRTSWays
- , platformMisc_tablesNextToCode = tablesNextToCode
- , platformMisc_leadingUnderscore = leadingUnderscore
- , platformMisc_libFFI = useLibFFI
- , platformMisc_ghcThreaded = ghcThreaded
- , platformMisc_ghcDebugged = ghcDebugged
- , platformMisc_ghcRtsWithLibdw = ghcRtsWithLibdw
- , platformMisc_llvmTarget = llvmTarget
- }
-
- , sPlatformConstants = platformConstants
-
- , sRawSettings = settingsList
- }
diff --git a/compiler/main/SysTools/Tasks.hs b/compiler/main/SysTools/Tasks.hs
deleted file mode 100644
index e4bbb32dc6..0000000000
--- a/compiler/main/SysTools/Tasks.hs
+++ /dev/null
@@ -1,373 +0,0 @@
-{-# LANGUAGE ScopedTypeVariables #-}
------------------------------------------------------------------------------
---
--- Tasks running external programs for SysTools
---
--- (c) The GHC Team 2017
---
------------------------------------------------------------------------------
-module SysTools.Tasks where
-
-import Exception
-import ErrUtils
-import GHC.Driver.Types
-import GHC.Driver.Session
-import Outputable
-import GHC.Platform
-import Util
-
-import Data.List
-
-import System.IO
-import System.Process
-import GhcPrelude
-
-import GHC.CmmToLlvm.Base (LlvmVersion, llvmVersionStr, supportedLlvmVersion, parseLlvmVersion)
-
-import SysTools.Process
-import SysTools.Info
-
-{-
-************************************************************************
-* *
-\subsection{Running an external program}
-* *
-************************************************************************
--}
-
-runUnlit :: DynFlags -> [Option] -> IO ()
-runUnlit dflags args = traceToolCommand dflags "unlit" $ do
- let prog = pgm_L dflags
- opts = getOpts dflags opt_L
- runSomething dflags "Literate pre-processor" prog
- (map Option opts ++ args)
-
-runCpp :: DynFlags -> [Option] -> IO ()
-runCpp dflags args = traceToolCommand dflags "cpp" $ do
- let (p,args0) = pgm_P dflags
- args1 = map Option (getOpts dflags opt_P)
- args2 = [Option "-Werror" | gopt Opt_WarnIsError dflags]
- ++ [Option "-Wundef" | wopt Opt_WarnCPPUndef dflags]
- mb_env <- getGccEnv args2
- runSomethingFiltered dflags id "C pre-processor" p
- (args0 ++ args1 ++ args2 ++ args) Nothing mb_env
-
-runPp :: DynFlags -> [Option] -> IO ()
-runPp dflags args = traceToolCommand dflags "pp" $ do
- let prog = pgm_F dflags
- opts = map Option (getOpts dflags opt_F)
- runSomething dflags "Haskell pre-processor" prog (args ++ opts)
-
--- | Run compiler of C-like languages and raw objects (such as gcc or clang).
-runCc :: Maybe ForeignSrcLang -> DynFlags -> [Option] -> IO ()
-runCc mLanguage dflags args = traceToolCommand dflags "cc" $ do
- let p = pgm_c dflags
- args1 = map Option userOpts
- args2 = languageOptions ++ args ++ args1
- -- We take care to pass -optc flags in args1 last to ensure that the
- -- user can override flags passed by GHC. See #14452.
- mb_env <- getGccEnv args2
- runSomethingResponseFile dflags cc_filter "C Compiler" p args2 mb_env
- where
- -- discard some harmless warnings from gcc that we can't turn off
- cc_filter = unlines . doFilter . lines
-
- {-
- gcc gives warnings in chunks like so:
- In file included from /foo/bar/baz.h:11,
- from /foo/bar/baz2.h:22,
- from wibble.c:33:
- /foo/flibble:14: global register variable ...
- /foo/flibble:15: warning: call-clobbered r...
- We break it up into its chunks, remove any call-clobbered register
- warnings from each chunk, and then delete any chunks that we have
- emptied of warnings.
- -}
- doFilter = unChunkWarnings . filterWarnings . chunkWarnings []
- -- We can't assume that the output will start with an "In file inc..."
- -- line, so we start off expecting a list of warnings rather than a
- -- location stack.
- chunkWarnings :: [String] -- The location stack to use for the next
- -- list of warnings
- -> [String] -- The remaining lines to look at
- -> [([String], [String])]
- chunkWarnings loc_stack [] = [(loc_stack, [])]
- chunkWarnings loc_stack xs
- = case break loc_stack_start xs of
- (warnings, lss:xs') ->
- case span loc_start_continuation xs' of
- (lsc, xs'') ->
- (loc_stack, warnings) : chunkWarnings (lss : lsc) xs''
- _ -> [(loc_stack, xs)]
-
- filterWarnings :: [([String], [String])] -> [([String], [String])]
- filterWarnings [] = []
- -- If the warnings are already empty then we are probably doing
- -- something wrong, so don't delete anything
- filterWarnings ((xs, []) : zs) = (xs, []) : filterWarnings zs
- filterWarnings ((xs, ys) : zs) = case filter wantedWarning ys of
- [] -> filterWarnings zs
- ys' -> (xs, ys') : filterWarnings zs
-
- unChunkWarnings :: [([String], [String])] -> [String]
- unChunkWarnings [] = []
- unChunkWarnings ((xs, ys) : zs) = xs ++ ys ++ unChunkWarnings zs
-
- loc_stack_start s = "In file included from " `isPrefixOf` s
- loc_start_continuation s = " from " `isPrefixOf` s
- wantedWarning w
- | "warning: call-clobbered register used" `isContainedIn` w = False
- | otherwise = True
-
- -- force the C compiler to interpret this file as C when
- -- compiling .hc files, by adding the -x c option.
- -- Also useful for plain .c files, just in case GHC saw a
- -- -x c option.
- (languageOptions, userOpts) = case mLanguage of
- Nothing -> ([], userOpts_c)
- Just language -> ([Option "-x", Option languageName], opts)
- where
- (languageName, opts) = case language of
- LangC -> ("c", userOpts_c)
- LangCxx -> ("c++", userOpts_cxx)
- LangObjc -> ("objective-c", userOpts_c)
- LangObjcxx -> ("objective-c++", userOpts_cxx)
- LangAsm -> ("assembler", [])
- RawObject -> ("c", []) -- claim C for lack of a better idea
- userOpts_c = getOpts dflags opt_c
- userOpts_cxx = getOpts dflags opt_cxx
-
-isContainedIn :: String -> String -> Bool
-xs `isContainedIn` ys = any (xs `isPrefixOf`) (tails ys)
-
--- | Run the linker with some arguments and return the output
-askLd :: DynFlags -> [Option] -> IO String
-askLd dflags args = traceToolCommand dflags "linker" $ do
- let (p,args0) = pgm_l dflags
- args1 = map Option (getOpts dflags opt_l)
- args2 = args0 ++ args1 ++ args
- mb_env <- getGccEnv args2
- runSomethingWith dflags "gcc" p args2 $ \real_args ->
- readCreateProcessWithExitCode' (proc p real_args){ env = mb_env }
-
-runAs :: DynFlags -> [Option] -> IO ()
-runAs dflags args = traceToolCommand dflags "as" $ do
- let (p,args0) = pgm_a dflags
- args1 = map Option (getOpts dflags opt_a)
- args2 = args0 ++ args1 ++ args
- mb_env <- getGccEnv args2
- runSomethingFiltered dflags id "Assembler" p args2 Nothing mb_env
-
--- | Run the LLVM Optimiser
-runLlvmOpt :: DynFlags -> [Option] -> IO ()
-runLlvmOpt dflags args = traceToolCommand dflags "opt" $ do
- let (p,args0) = pgm_lo dflags
- args1 = map Option (getOpts dflags opt_lo)
- -- We take care to pass -optlo flags (e.g. args0) last to ensure that the
- -- user can override flags passed by GHC. See #14821.
- runSomething dflags "LLVM Optimiser" p (args1 ++ args ++ args0)
-
--- | Run the LLVM Compiler
-runLlvmLlc :: DynFlags -> [Option] -> IO ()
-runLlvmLlc dflags args = traceToolCommand dflags "llc" $ do
- let (p,args0) = pgm_lc dflags
- args1 = map Option (getOpts dflags opt_lc)
- runSomething dflags "LLVM Compiler" p (args0 ++ args1 ++ args)
-
--- | Run the clang compiler (used as an assembler for the LLVM
--- backend on OS X as LLVM doesn't support the OS X system
--- assembler)
-runClang :: DynFlags -> [Option] -> IO ()
-runClang dflags args = traceToolCommand dflags "clang" $ do
- let (clang,_) = pgm_lcc dflags
- -- be careful what options we call clang with
- -- see #5903 and #7617 for bugs caused by this.
- (_,args0) = pgm_a dflags
- args1 = map Option (getOpts dflags opt_a)
- args2 = args0 ++ args1 ++ args
- mb_env <- getGccEnv args2
- Exception.catch (do
- runSomethingFiltered dflags id "Clang (Assembler)" clang args2 Nothing mb_env
- )
- (\(err :: SomeException) -> do
- errorMsg dflags $
- text ("Error running clang! you need clang installed to use the" ++
- " LLVM backend") $+$
- text "(or GHC tried to execute clang incorrectly)"
- throwIO err
- )
-
--- | Figure out which version of LLVM we are running this session
-figureLlvmVersion :: DynFlags -> IO (Maybe LlvmVersion)
-figureLlvmVersion dflags = traceToolCommand dflags "llc" $ do
- let (pgm,opts) = pgm_lc dflags
- args = filter notNull (map showOpt opts)
- -- we grab the args even though they should be useless just in
- -- case the user is using a customised 'llc' that requires some
- -- of the options they've specified. llc doesn't care what other
- -- options are specified when '-version' is used.
- args' = args ++ ["-version"]
- catchIO (do
- (pin, pout, perr, _) <- runInteractiveProcess pgm args'
- Nothing Nothing
- {- > llc -version
- LLVM (http://llvm.org/):
- LLVM version 3.5.2
- ...
- -}
- hSetBinaryMode pout False
- _ <- hGetLine pout
- vline <- hGetLine pout
- let mb_ver = parseLlvmVersion vline
- hClose pin
- hClose pout
- hClose perr
- return mb_ver
- )
- (\err -> do
- debugTraceMsg dflags 2
- (text "Error (figuring out LLVM version):" <+>
- text (show err))
- errorMsg dflags $ vcat
- [ text "Warning:", nest 9 $
- text "Couldn't figure out LLVM version!" $$
- text ("Make sure you have installed LLVM " ++
- llvmVersionStr supportedLlvmVersion) ]
- return Nothing)
-
-
-runLink :: DynFlags -> [Option] -> IO ()
-runLink dflags args = traceToolCommand dflags "linker" $ do
- -- See Note [Run-time linker info]
- --
- -- `-optl` args come at the end, so that later `-l` options
- -- given there manually can fill in symbols needed by
- -- Haskell libraries coming in via `args`.
- linkargs <- neededLinkArgs `fmap` getLinkerInfo dflags
- let (p,args0) = pgm_l dflags
- optl_args = map Option (getOpts dflags opt_l)
- args2 = args0 ++ linkargs ++ args ++ optl_args
- mb_env <- getGccEnv args2
- runSomethingResponseFile dflags ld_filter "Linker" p args2 mb_env
- where
- ld_filter = case (platformOS (targetPlatform dflags)) of
- OSSolaris2 -> sunos_ld_filter
- _ -> id
-{-
- SunOS/Solaris ld emits harmless warning messages about unresolved
- symbols in case of compiling into shared library when we do not
- link against all the required libs. That is the case of GHC which
- does not link against RTS library explicitly in order to be able to
- choose the library later based on binary application linking
- parameters. The warnings look like:
-
-Undefined first referenced
- symbol in file
-stg_ap_n_fast ./T2386_Lib.o
-stg_upd_frame_info ./T2386_Lib.o
-templatezmhaskell_LanguageziHaskellziTHziLib_litE_closure ./T2386_Lib.o
-templatezmhaskell_LanguageziHaskellziTHziLib_appE_closure ./T2386_Lib.o
-templatezmhaskell_LanguageziHaskellziTHziLib_conE_closure ./T2386_Lib.o
-templatezmhaskell_LanguageziHaskellziTHziSyntax_mkNameGzud_closure ./T2386_Lib.o
-newCAF ./T2386_Lib.o
-stg_bh_upd_frame_info ./T2386_Lib.o
-stg_ap_ppp_fast ./T2386_Lib.o
-templatezmhaskell_LanguageziHaskellziTHziLib_stringL_closure ./T2386_Lib.o
-stg_ap_p_fast ./T2386_Lib.o
-stg_ap_pp_fast ./T2386_Lib.o
-ld: warning: symbol referencing errors
-
- this is actually coming from T2386 testcase. The emitting of those
- warnings is also a reason why so many TH testcases fail on Solaris.
-
- Following filter code is SunOS/Solaris linker specific and should
- filter out only linker warnings. Please note that the logic is a
- little bit more complex due to the simple reason that we need to preserve
- any other linker emitted messages. If there are any. Simply speaking
- if we see "Undefined" and later "ld: warning:..." then we omit all
- text between (including) the marks. Otherwise we copy the whole output.
--}
- sunos_ld_filter :: String -> String
- sunos_ld_filter = unlines . sunos_ld_filter' . lines
- sunos_ld_filter' x = if (undefined_found x && ld_warning_found x)
- then (ld_prefix x) ++ (ld_postfix x)
- else x
- breakStartsWith x y = break (isPrefixOf x) y
- ld_prefix = fst . breakStartsWith "Undefined"
- undefined_found = not . null . snd . breakStartsWith "Undefined"
- ld_warn_break = breakStartsWith "ld: warning: symbol referencing errors"
- ld_postfix = tail . snd . ld_warn_break
- ld_warning_found = not . null . snd . ld_warn_break
-
-
-runLibtool :: DynFlags -> [Option] -> IO ()
-runLibtool dflags args = traceToolCommand dflags "libtool" $ do
- linkargs <- neededLinkArgs `fmap` getLinkerInfo dflags
- let args1 = map Option (getOpts dflags opt_l)
- args2 = [Option "-static"] ++ args1 ++ args ++ linkargs
- libtool = pgm_libtool dflags
- mb_env <- getGccEnv args2
- runSomethingFiltered dflags id "Linker" libtool args2 Nothing mb_env
-
-runAr :: DynFlags -> Maybe FilePath -> [Option] -> IO ()
-runAr dflags cwd args = traceToolCommand dflags "ar" $ do
- let ar = pgm_ar dflags
- runSomethingFiltered dflags id "Ar" ar args cwd Nothing
-
-askAr :: DynFlags -> Maybe FilePath -> [Option] -> IO String
-askAr dflags mb_cwd args = traceToolCommand dflags "ar" $ do
- let ar = pgm_ar dflags
- runSomethingWith dflags "Ar" ar args $ \real_args ->
- readCreateProcessWithExitCode' (proc ar real_args){ cwd = mb_cwd }
-
-runRanlib :: DynFlags -> [Option] -> IO ()
-runRanlib dflags args = traceToolCommand dflags "ranlib" $ do
- let ranlib = pgm_ranlib dflags
- runSomethingFiltered dflags id "Ranlib" ranlib args Nothing Nothing
-
-runMkDLL :: DynFlags -> [Option] -> IO ()
-runMkDLL dflags args = traceToolCommand dflags "mkdll" $ do
- let (p,args0) = pgm_dll dflags
- args1 = args0 ++ args
- mb_env <- getGccEnv (args0++args)
- runSomethingFiltered dflags id "Make DLL" p args1 Nothing mb_env
-
-runWindres :: DynFlags -> [Option] -> IO ()
-runWindres dflags args = traceToolCommand dflags "windres" $ do
- let cc = pgm_c dflags
- cc_args = map Option (sOpt_c (settings dflags))
- windres = pgm_windres dflags
- opts = map Option (getOpts dflags opt_windres)
- quote x = "\"" ++ x ++ "\""
- args' = -- If windres.exe and gcc.exe are in a directory containing
- -- spaces then windres fails to run gcc. We therefore need
- -- to tell it what command to use...
- Option ("--preprocessor=" ++
- unwords (map quote (cc :
- map showOpt opts ++
- ["-E", "-xc", "-DRC_INVOKED"])))
- -- ...but if we do that then if windres calls popen then
- -- it can't understand the quoting, so we have to use
- -- --use-temp-file so that it interprets it correctly.
- -- See #1828.
- : Option "--use-temp-file"
- : args
- mb_env <- getGccEnv cc_args
- runSomethingFiltered dflags id "Windres" windres args' Nothing mb_env
-
-touch :: DynFlags -> String -> String -> IO ()
-touch dflags purpose arg = traceToolCommand dflags "touch" $
- runSomething dflags purpose (pgm_T dflags) [FileOption "" arg]
-
--- * Tracing utility
-
--- | Record in the eventlog when the given tool command starts
--- and finishes, prepending the given 'String' with
--- \"systool:\", to easily be able to collect and process
--- all the systool events.
---
--- For those events to show up in the eventlog, you need
--- to run GHC with @-v2@ or @-ddump-timings@.
-traceToolCommand :: DynFlags -> String -> IO a -> IO a
-traceToolCommand dflags tool = withTiming
- dflags (text $ "systool:" ++ tool) (const ())
diff --git a/compiler/main/SysTools/Terminal.hs b/compiler/main/SysTools/Terminal.hs
deleted file mode 100644
index 162dd32010..0000000000
--- a/compiler/main/SysTools/Terminal.hs
+++ /dev/null
@@ -1,104 +0,0 @@
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-module SysTools.Terminal (stderrSupportsAnsiColors) where
-
-import GhcPrelude
-
-#if defined(MIN_VERSION_terminfo)
-import Control.Exception (catch)
-import Data.Maybe (fromMaybe)
-import System.Console.Terminfo (SetupTermError, Terminal, getCapability,
- setupTermFromEnv, termColors)
-import System.Posix (queryTerminal, stdError)
-#elif defined(mingw32_HOST_OS)
-import Control.Exception (catch, try)
-import Data.Bits ((.|.), (.&.))
-import Foreign (Ptr, peek, with)
-import qualified Graphics.Win32 as Win32
-import qualified System.Win32 as Win32
-#endif
-
-import System.IO.Unsafe
-
-#if defined(mingw32_HOST_OS) && !defined(WINAPI)
-# if defined(i386_HOST_ARCH)
-# define WINAPI stdcall
-# elif defined(x86_64_HOST_ARCH)
-# define WINAPI ccall
-# else
-# error unknown architecture
-# endif
-#endif
-
--- | Does the controlling terminal support ANSI color sequences?
--- This memoized to avoid thread-safety issues in ncurses (see #17922).
-stderrSupportsAnsiColors :: Bool
-stderrSupportsAnsiColors = unsafePerformIO stderrSupportsAnsiColors'
-{-# NOINLINE stderrSupportsAnsiColors #-}
-
--- | Check if ANSI escape sequences can be used to control color in stderr.
-stderrSupportsAnsiColors' :: IO Bool
-stderrSupportsAnsiColors' = do
-#if defined(MIN_VERSION_terminfo)
- stderr_available <- queryTerminal stdError
- if stderr_available then
- fmap termSupportsColors setupTermFromEnv
- `catch` \ (_ :: SetupTermError) -> pure False
- else
- pure False
- where
- termSupportsColors :: Terminal -> Bool
- termSupportsColors term = fromMaybe 0 (getCapability term termColors) > 0
-
-#elif defined(mingw32_HOST_OS)
- h <- Win32.getStdHandle Win32.sTD_ERROR_HANDLE
- `catch` \ (_ :: IOError) ->
- pure Win32.nullHANDLE
- if h == Win32.nullHANDLE
- then pure False
- else do
- eMode <- try (getConsoleMode h)
- case eMode of
- Left (_ :: IOError) -> Win32.isMinTTYHandle h
- -- Check if the we're in a MinTTY terminal
- -- (e.g., Cygwin or MSYS2)
- Right mode
- | modeHasVTP mode -> pure True
- | otherwise -> enableVTP h mode
-
- where
-
- enableVTP :: Win32.HANDLE -> Win32.DWORD -> IO Bool
- enableVTP h mode = do
- setConsoleMode h (modeAddVTP mode)
- modeHasVTP <$> getConsoleMode h
- `catch` \ (_ :: IOError) ->
- pure False
-
- modeHasVTP :: Win32.DWORD -> Bool
- modeHasVTP mode = mode .&. eNABLE_VIRTUAL_TERMINAL_PROCESSING /= 0
-
- modeAddVTP :: Win32.DWORD -> Win32.DWORD
- modeAddVTP mode = mode .|. eNABLE_VIRTUAL_TERMINAL_PROCESSING
-
-eNABLE_VIRTUAL_TERMINAL_PROCESSING :: Win32.DWORD
-eNABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
-
-getConsoleMode :: Win32.HANDLE -> IO Win32.DWORD
-getConsoleMode h = with 64 $ \ mode -> do
- Win32.failIfFalse_ "GetConsoleMode" (c_GetConsoleMode h mode)
- peek mode
-
-setConsoleMode :: Win32.HANDLE -> Win32.DWORD -> IO ()
-setConsoleMode h mode = do
- Win32.failIfFalse_ "SetConsoleMode" (c_SetConsoleMode h mode)
-
-foreign import WINAPI unsafe "windows.h GetConsoleMode" c_GetConsoleMode
- :: Win32.HANDLE -> Ptr Win32.DWORD -> IO Win32.BOOL
-
-foreign import WINAPI unsafe "windows.h SetConsoleMode" c_SetConsoleMode
- :: Win32.HANDLE -> Win32.DWORD -> IO Win32.BOOL
-
-#else
- pure False
-#endif
diff --git a/compiler/main/ToolSettings.hs b/compiler/main/ToolSettings.hs
deleted file mode 100644
index 82d125b5f6..0000000000
--- a/compiler/main/ToolSettings.hs
+++ /dev/null
@@ -1,64 +0,0 @@
-module ToolSettings
- ( ToolSettings (..)
- ) where
-
-import GhcPrelude
-
-import CliOption
-import Fingerprint
-
--- | Settings for other executables GHC calls.
---
--- Probably should further split down by phase, or split between
--- platform-specific and platform-agnostic.
-data ToolSettings = ToolSettings
- { toolSettings_ldSupportsCompactUnwind :: Bool
- , toolSettings_ldSupportsBuildId :: Bool
- , toolSettings_ldSupportsFilelist :: Bool
- , toolSettings_ldIsGnuLd :: Bool
- , toolSettings_ccSupportsNoPie :: Bool
-
- -- commands for particular phases
- , toolSettings_pgm_L :: String
- , toolSettings_pgm_P :: (String, [Option])
- , toolSettings_pgm_F :: String
- , toolSettings_pgm_c :: String
- , toolSettings_pgm_a :: (String, [Option])
- , toolSettings_pgm_l :: (String, [Option])
- , toolSettings_pgm_dll :: (String, [Option])
- , toolSettings_pgm_T :: String
- , toolSettings_pgm_windres :: String
- , toolSettings_pgm_libtool :: String
- , toolSettings_pgm_ar :: String
- , toolSettings_pgm_ranlib :: String
- , -- | LLVM: opt llvm optimiser
- toolSettings_pgm_lo :: (String, [Option])
- , -- | LLVM: llc static compiler
- toolSettings_pgm_lc :: (String, [Option])
- , -- | LLVM: c compiler
- toolSettings_pgm_lcc :: (String, [Option])
- , toolSettings_pgm_i :: String
-
- -- options for particular phases
- , toolSettings_opt_L :: [String]
- , toolSettings_opt_P :: [String]
- , -- | cached Fingerprint of sOpt_P
- -- See Note [Repeated -optP hashing]
- toolSettings_opt_P_fingerprint :: Fingerprint
- , toolSettings_opt_F :: [String]
- , toolSettings_opt_c :: [String]
- , toolSettings_opt_cxx :: [String]
- , toolSettings_opt_a :: [String]
- , toolSettings_opt_l :: [String]
- , toolSettings_opt_windres :: [String]
- , -- | LLVM: llvm optimiser
- toolSettings_opt_lo :: [String]
- , -- | LLVM: llc static compiler
- toolSettings_opt_lc :: [String]
- , -- | LLVM: c compiler
- toolSettings_opt_lcc :: [String]
- , -- | iserv options
- toolSettings_opt_i :: [String]
-
- , toolSettings_extraGccViaCFlags :: [String]
- }