summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/GHC/CmmToAsm/X86/CodeGen.hs164
-rw-r--r--compiler/GHC/CmmToAsm/X86/Instr.hs4
-rw-r--r--compiler/GHC/Driver/Pipeline/Execute.hs5
-rw-r--r--compiler/GHC/SysTools/Info.hs30
-rw-r--r--compiler/GHC/SysTools/Tasks.hs18
-rw-r--r--configure.ac143
-rw-r--r--driver/gcc/gcc.c66
-rw-r--r--hadrian/src/Oracles/Flag.hs13
-rw-r--r--hadrian/src/Rules/BinaryDist.hs4
-rw-r--r--hadrian/src/Rules/Register.hs7
-rw-r--r--hadrian/src/Settings/Builders/Cabal.hs4
m---------libraries/Cabal0
-rw-r--r--libraries/base/aclocal.m416
-rw-r--r--libraries/base/configure.ac2
-rw-r--r--libraries/base/include/HsBase.h4
m---------libraries/bytestring0
-rw-r--r--libraries/ghc-prim/ghc-prim.cabal2
m---------libraries/process0
m---------libraries/text0
-rw-r--r--m4/fp_check_environ.m47
-rw-r--r--m4/fp_settings.m4145
-rw-r--r--m4/fp_setup_windows_toolchain.m4107
-rw-r--r--mk/config.mk.in12
-rwxr-xr-xmk/get-win32-tarballs.py2
-rw-r--r--rts/CheckUnload.h4
-rw-r--r--rts/HsFFI.c2
-rw-r--r--rts/LibdwPool.h4
-rw-r--r--rts/LinkerInternals.h4
-rw-r--r--rts/Messages.h8
-rw-r--r--rts/PathUtils.h4
-rw-r--r--rts/Profiling.h4
-rw-r--r--rts/RtsFlags.h3
-rw-r--r--rts/RtsSymbolInfo.c3
-rw-r--r--rts/RtsSymbols.c11
-rw-r--r--rts/StaticPtrTable.c2
-rw-r--r--rts/Stats.c12
-rw-r--r--rts/include/Stg.h10
-rw-r--r--rts/include/rts/Messages.h19
-rw-r--r--rts/include/rts/PosixSource.h12
-rw-r--r--rts/include/stg/Types.h12
-rw-r--r--rts/linker/Elf.h3
-rw-r--r--rts/linker/MachO.h3
-rw-r--r--rts/linker/PEi386.c24
-rw-r--r--rts/sm/GC.h4
-rw-r--r--rts/sm/GCUtils.h4
-rw-r--r--rts/sm/MarkStack.h3
-rw-r--r--testsuite/config/ghc1
-rw-r--r--testsuite/driver/runtests.py2
-rw-r--r--testsuite/driver/testglobals.py2
-rw-r--r--testsuite/driver/testlib.py4
-rw-r--r--testsuite/mk/boilerplate.mk2
-rw-r--r--testsuite/tests/codeGen/should_compile/all.T3
-rw-r--r--testsuite/tests/codeGen/should_compile/mk-big-obj.py9
-rw-r--r--testsuite/tests/codeGen/should_fail/all.T2
-rw-r--r--testsuite/tests/ghci/linking/Makefile10
-rw-r--r--testsuite/tests/ghci/linking/all.T4
-rw-r--r--testsuite/tests/ghci/linking/dyn/A.def3
-rw-r--r--testsuite/tests/ghci/linking/dyn/B.def3
-rw-r--r--testsuite/tests/ghci/linking/dyn/Makefile21
-rw-r--r--testsuite/tests/ghci/linking/dyn/all.T8
-rw-r--r--testsuite/tests/linters/Makefile3
-rw-r--r--testsuite/tests/linters/all.T6
-rwxr-xr-xtestsuite/tests/linters/regex-linters/check-rts-includes.py91
-rw-r--r--testsuite/tests/numeric/should_run/all.T3
-rw-r--r--testsuite/tests/plugins/all.T4
-rw-r--r--testsuite/tests/rts/T10672/Makefile4
-rw-r--r--testsuite/tests/rts/T16514_c.c31
-rw-r--r--testsuite/tests/rts/T16514_c.cpp45
-rw-r--r--testsuite/tests/rts/all.T7
-rw-r--r--testsuite/tests/rts/linker/T5435_v_asm_a.stdout-mingw322
-rw-r--r--testsuite/tests/rts/linker/T5435_v_gcc.stdout-mingw322
-rw-r--r--testsuite/tests/rts/linker/all.T10
-rw-r--r--testsuite/tests/rts/linker/unload_multiple_objs/all.T1
-rw-r--r--testsuite/tests/th/T13366C.hs23
-rw-r--r--testsuite/tests/th/T13366C.stdout2
-rw-r--r--testsuite/tests/th/T13366Cxx.hs (renamed from testsuite/tests/th/T13366.hs)14
-rw-r--r--testsuite/tests/th/T13366Cxx.stdout (renamed from testsuite/tests/th/T13366.stdout)2
-rw-r--r--testsuite/tests/th/all.T17
78 files changed, 685 insertions, 566 deletions
diff --git a/compiler/GHC/CmmToAsm/X86/CodeGen.hs b/compiler/GHC/CmmToAsm/X86/CodeGen.hs
index 1fefe3a346..3d2a83c984 100644
--- a/compiler/GHC/CmmToAsm/X86/CodeGen.hs
+++ b/compiler/GHC/CmmToAsm/X86/CodeGen.hs
@@ -437,6 +437,25 @@ temporary, then do the other computation, and then use the temporary:
... (tmp) ...
-}
+{-
+Note [%rip-relative addressing on x86-64]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+On x86-64 GHC produces code for use in the "small" or, when `-fPIC` is set,
+"small PIC" code models defined by the x86-64 System V ABI (section 3.5.1 of
+specification version 0.99).
+
+In general the small code model would allow us to assume that code is located
+between 0 and 2^31 - 1. However, this is not true on Windows which, due to
+high-entropy ASLR, may place the executable image anywhere in 64-bit address
+space. This is problematic since immediate operands in x86-64 are generally
+32-bit sign-extended values (with the exception of the 64-bit MOVABS encoding).
+Consequently, to avoid overflowing we use %rip-relative addressing universally.
+Since %rip-relative addressing comes essentially for free and makes linking far
+easier, we use it even on non-Windows platforms.
+
+See also: the documentation for GCC's `-mcmodel=small` flag.
+-}
+
-- | Check whether an integer will fit in 32 bits.
-- A CmmInt is intended to be truncated to the appropriate
@@ -1139,6 +1158,22 @@ getRegister' _ is32Bit (CmmLit (CmmInt 0 width))
in
return (Any format code)
+-- Handle symbol references with LEA and %rip-relative addressing.
+-- See Note [%rip-relative addressing on x86-64].
+getRegister' platform is32Bit (CmmLit lit)
+ | is_label lit
+ , not is32Bit
+ = do let format = cmmTypeFormat (cmmLitType platform lit)
+ imm = litToImm lit
+ op = OpAddr (AddrBaseIndex EABaseRip EAIndexNone imm)
+ code dst = unitOL (LEA format op (OpReg dst))
+ return (Any format code)
+ where
+ is_label (CmmLabel {}) = True
+ is_label (CmmLabelOff {}) = True
+ is_label (CmmLabelDiffOff {}) = True
+ is_label _ = False
+
-- optimisation for loading small literals on x86_64: take advantage
-- of the automatic zero-extension from 32 to 64 bits, because the 32-bit
-- instruction forms are shorter.
@@ -1156,7 +1191,7 @@ getRegister' platform is32Bit (CmmLit lit)
-- signed literals that fit in 32 bits, but we want unsigned
-- literals here.
-- note2: all labels are small, because we're assuming the
- -- small memory model (see gcc docs, -mcmodel=small).
+ -- small memory model. See Note [%rip-relative addressing on x86-64].
getRegister' platform _ (CmmLit lit)
= do let format = cmmTypeFormat (cmmLitType platform lit)
@@ -1253,7 +1288,7 @@ getAmode e = do
-- This is all just ridiculous, since it carefully undoes
-- what mangleIndexTree has just done.
CmmMachOp (MO_Sub _rep) [x, CmmLit lit@(CmmInt i _)]
- | is32BitLit is32Bit lit
+ | is32BitLit platform lit
-- assert (rep == II32)???
-> do
(x_reg, x_code) <- getSomeReg x
@@ -1261,7 +1296,7 @@ getAmode e = do
return (Amode (AddrBaseIndex (EABaseReg x_reg) EAIndexNone off) x_code)
CmmMachOp (MO_Add _rep) [x, CmmLit lit]
- | is32BitLit is32Bit lit
+ | is32BitLit platform lit
-- assert (rep == II32)???
-> do
(x_reg, x_code) <- getSomeReg x
@@ -1292,8 +1327,16 @@ getAmode e = do
| not (isLit y) -- we already handle valid literals above.
-> x86_complex_amode x y 0 0
+ -- Handle labels with %rip-relative addressing since in general the image
+ -- may be loaded anywhere in the 64-bit address space (e.g. on Windows
+ -- with high-entropy ASLR). See Note [%rip-relative addressing on x86-64].
+ CmmLit lit
+ | not is32Bit
+ , is_label lit
+ -> return (Amode (AddrBaseIndex EABaseRip EAIndexNone (litToImm lit)) nilOL)
+
CmmLit lit
- | is32BitLit is32Bit lit
+ | is32BitLit platform lit
-> return (Amode (ImmAddr (litToImm lit) 0) nilOL)
-- Literal with offsets too big (> 32 bits) fails during the linking phase
@@ -1313,7 +1356,11 @@ getAmode e = do
_ -> do
(reg,code) <- getSomeReg e
return (Amode (AddrBaseIndex (EABaseReg reg) EAIndexNone (ImmInt 0)) code)
-
+ where
+ is_label (CmmLabel{}) = True
+ is_label (CmmLabelOff{}) = True
+ is_label (CmmLabelDiffOff{}) = True
+ is_label _ = False
-- | Like 'getAmode', but on 32-bit use simple register addressing
@@ -1362,9 +1409,8 @@ getNonClobberedOperand (CmmLit lit) =
Amode addr code <- memConstant (mkAlignment $ widthInBytes w) lit
return (OpAddr addr, code)
else do
- is32Bit <- is32BitPlatform
platform <- getPlatform
- if is32BitLit is32Bit lit && not (isFloatType (cmmLitType platform lit))
+ if is32BitLit platform lit && not (isFloatType (cmmLitType platform lit))
then return (OpImm (litToImm lit), nilOL)
else getNonClobberedOperand_generic (CmmLit lit)
@@ -1421,9 +1467,8 @@ getOperand (CmmLit lit) = do
return (OpAddr addr, code)
else do
- is32Bit <- is32BitPlatform
platform <- getPlatform
- if is32BitLit is32Bit lit && not (isFloatType (cmmLitType platform lit))
+ if is32BitLit platform lit && not (isFloatType (cmmLitType platform lit))
then return (OpImm (litToImm lit), nilOL)
else getOperand_generic (CmmLit lit)
@@ -1444,9 +1489,10 @@ getOperand_generic e = do
(reg, code) <- getSomeReg e
return (OpReg reg, code)
-isOperand :: Bool -> CmmExpr -> Bool
+isOperand :: Platform -> CmmExpr -> Bool
isOperand _ (CmmLoad _ _ _) = True
-isOperand is32Bit (CmmLit lit) = is32BitLit is32Bit lit
+isOperand platform (CmmLit lit)
+ = is32BitLit platform lit
|| isSuitableFloatingPointLit lit
isOperand _ _ = False
@@ -1517,21 +1563,28 @@ getRegOrMem e = do
(reg, code) <- getNonClobberedReg e
return (OpReg reg, code)
-is32BitLit :: Bool -> CmmLit -> Bool
-is32BitLit is32Bit lit
- | not is32Bit = case lit of
+is32BitLit :: Platform -> CmmLit -> Bool
+is32BitLit platform _lit
+ | target32Bit platform = True
+is32BitLit platform lit =
+ case lit of
CmmInt i W64 -> is32BitInteger i
- -- assume that labels are in the range 0-2^31-1: this assumes the
- -- small memory model (see gcc docs, -mcmodel=small).
- CmmLabel _ -> True
+ -- Except on Windows, assume that labels are in the range 0-2^31-1: this
+ -- assumes the small memory model. Note [%rip-relative addressing on
+ -- x86-64].
+ CmmLabel _ -> low_image
-- however we can't assume that label offsets are in this range
-- (see #15570)
- CmmLabelOff _ off -> is32BitInteger (fromIntegral off)
- CmmLabelDiffOff _ _ off _ -> is32BitInteger (fromIntegral off)
+ CmmLabelOff _ off -> low_image && is32BitInteger (fromIntegral off)
+ CmmLabelDiffOff _ _ off _ -> low_image && is32BitInteger (fromIntegral off)
_ -> True
-is32BitLit _ _ = True
-
-
+ where
+ -- Is the executable image certain to be located below 4GB? As noted in
+ -- Note [%rip-relative addressing on x86-64], this is not true on Windows.
+ low_image =
+ case platformOS platform of
+ OSMinGW32 -> False -- See Note [%rip-relative addressing on x86-64]
+ _ -> True
-- Set up a condition code for a conditional branch.
@@ -1584,14 +1637,14 @@ machOpToCond mo = case mo of
-- passed back up the tree.
condIntCode :: Cond -> CmmExpr -> CmmExpr -> NatM CondCode
-condIntCode cond x y = do is32Bit <- is32BitPlatform
- condIntCode' is32Bit cond x y
+condIntCode cond x y = do platform <- getPlatform
+ condIntCode' platform cond x y
-condIntCode' :: Bool -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode
+condIntCode' :: Platform -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode
-- memory vs immediate
-condIntCode' is32Bit cond (CmmLoad x pk _) (CmmLit lit)
- | is32BitLit is32Bit lit = do
+condIntCode' platform cond (CmmLoad x pk _) (CmmLit lit)
+ | is32BitLit platform lit = do
Amode x_addr x_code <- getAmode x
let
imm = litToImm lit
@@ -1602,8 +1655,8 @@ condIntCode' is32Bit cond (CmmLoad x pk _) (CmmLit lit)
-- anything vs zero, using a mask
-- TODO: Add some sanity checking!!!!
-condIntCode' is32Bit cond (CmmMachOp (MO_And _) [x,o2]) (CmmLit (CmmInt 0 pk))
- | (CmmLit lit@(CmmInt mask _)) <- o2, is32BitLit is32Bit lit
+condIntCode' platform cond (CmmMachOp (MO_And _) [x,o2]) (CmmLit (CmmInt 0 pk))
+ | (CmmLit lit@(CmmInt mask _)) <- o2, is32BitLit platform lit
= do
(x_reg, x_code) <- getSomeReg x
let
@@ -1622,9 +1675,8 @@ condIntCode' _ cond x (CmmLit (CmmInt 0 pk)) = do
return (CondCode False cond code)
-- anything vs operand
-condIntCode' is32Bit cond x y
- | isOperand is32Bit y = do
- platform <- getPlatform
+condIntCode' platform cond x y
+ | isOperand platform y = do
(x_reg, x_code) <- getNonClobberedReg x
(y_op, y_code) <- getOperand y
let
@@ -1633,9 +1685,8 @@ condIntCode' is32Bit cond x y
return (CondCode False cond code)
-- operand vs. anything: invert the comparison so that we can use a
-- single comparison instruction.
- | isOperand is32Bit x
+ | isOperand platform x
, Just revcond <- maybeFlipCond cond = do
- platform <- getPlatform
(y_reg, y_code) <- getNonClobberedReg y
(x_op, x_code) <- getOperand x
let
@@ -1644,8 +1695,7 @@ condIntCode' is32Bit cond x y
return (CondCode False revcond code)
-- anything vs anything
-condIntCode' _ cond x y = do
- platform <- getPlatform
+condIntCode' platform cond x y = do
(y_reg, y_code) <- getNonClobberedReg y
(x_op, x_code) <- getRegOrMem x
let
@@ -1719,9 +1769,9 @@ assignMem_IntCode pk addr (CmmMachOp op [CmmLoad addr2 _ _,
-- general case
assignMem_IntCode pk addr src = do
- is32Bit <- is32BitPlatform
+ platform <- getPlatform
Amode addr code_addr <- getAmode addr
- (code_src, op_src) <- get_op_RI is32Bit src
+ (code_src, op_src) <- get_op_RI platform src
let
code = code_src `appOL`
code_addr `snocOL`
@@ -1733,8 +1783,8 @@ assignMem_IntCode pk addr src = do
--
return code
where
- get_op_RI :: Bool -> CmmExpr -> NatM (InstrBlock,Operand) -- code, operator
- get_op_RI is32Bit (CmmLit lit) | is32BitLit is32Bit lit
+ get_op_RI :: Platform -> CmmExpr -> NatM (InstrBlock,Operand) -- code, operator
+ get_op_RI platform (CmmLit lit) | is32BitLit platform lit
= return (nilOL, OpImm (litToImm lit))
get_op_RI _ op
= do (reg,code) <- getNonClobberedReg op
@@ -2563,12 +2613,12 @@ genCCall64 addr conv dest_regs args = do
-- pass the arg into the given register
reg_this_arg r
-- "operand" args can be directly assigned into r
- | isOperand False arg = do
+ | isOperand platform arg = do
arg_code <- getAnyReg arg
return (code, (acode `appOL` arg_code r))
-- The last non-operand arg can be directly assigned after its
-- computation without going into a temporary register
- | all (isOperand False) rest = do
+ | all (isOperand platform) rest = do
arg_code <- getAnyReg arg
return (code `appOL` arg_code r,acode)
@@ -2864,11 +2914,21 @@ genSwitch expr targets = do
else do
(reg,e_code) <- getSomeReg indexExpr
lbl <- getNewLabelNat
- let op = OpAddr (AddrBaseIndex EABaseNone (EAIndex reg (platformWordSizeInBytes platform)) (ImmCLbl lbl))
- code = e_code `appOL` toOL [
- JMP_TBL op ids (Section ReadOnlyData lbl) lbl
- ]
- return code
+ let is32bit = target32Bit platform
+ if is32bit
+ then let op = OpAddr (AddrBaseIndex EABaseNone (EAIndex reg (platformWordSizeInBytes platform)) (ImmCLbl lbl))
+ jmp_code = JMP_TBL op ids (Section ReadOnlyData lbl) lbl
+ in return $ e_code `appOL` unitOL jmp_code
+ else do
+ -- See Note [%rip-relative addressing on x86-64].
+ tableReg <- getNewRegNat (intFormat (platformWordWidth platform))
+ let op = OpAddr (AddrBaseIndex (EABaseReg tableReg) (EAIndex reg (platformWordSizeInBytes platform)) (ImmInt 0))
+ code = e_code `appOL` toOL
+ [ LEA (archWordFormat is32bit) (OpAddr (AddrBaseIndex EABaseRip EAIndexNone (ImmCLbl lbl))) (OpReg tableReg)
+ , MOV (archWordFormat is32bit) op (OpReg reg)
+ , JMP_TBL (OpReg reg) ids (Section ReadOnlyData lbl) lbl
+ ]
+ return code
where
(offset, blockIds) = switchTargetsToTable targets
ids = map (fmap DestBlockId) blockIds
@@ -3078,14 +3138,14 @@ trivialCode :: Width -> (Operand -> Operand -> Instr)
-> Maybe (Operand -> Operand -> Instr)
-> CmmExpr -> CmmExpr -> NatM Register
trivialCode width instr m a b
- = do is32Bit <- is32BitPlatform
- trivialCode' is32Bit width instr m a b
+ = do platform <- getPlatform
+ trivialCode' platform width instr m a b
-trivialCode' :: Bool -> Width -> (Operand -> Operand -> Instr)
+trivialCode' :: Platform -> Width -> (Operand -> Operand -> Instr)
-> Maybe (Operand -> Operand -> Instr)
-> CmmExpr -> CmmExpr -> NatM Register
-trivialCode' is32Bit width _ (Just revinstr) (CmmLit lit_a) b
- | is32BitLit is32Bit lit_a = do
+trivialCode' platform width _ (Just revinstr) (CmmLit lit_a) b
+ | is32BitLit platform lit_a = do
b_code <- getAnyReg b
let
code dst
diff --git a/compiler/GHC/CmmToAsm/X86/Instr.hs b/compiler/GHC/CmmToAsm/X86/Instr.hs
index 1f1515b0c9..42b9543204 100644
--- a/compiler/GHC/CmmToAsm/X86/Instr.hs
+++ b/compiler/GHC/CmmToAsm/X86/Instr.hs
@@ -196,6 +196,10 @@ data Instr
-- Moves.
| MOV Format Operand Operand
+ -- ^ N.B. when used with the 'II64' 'Format', the source
+ -- operand is interpreted to be a 32-bit sign-extended value.
+ -- True 64-bit operands need to be moved with @MOVABS@, which we
+ -- currently don't use.
| CMOV Cond Format Operand Reg
| MOVZxL Format Operand Operand
-- ^ The format argument is the size of operand 1 (the number of bits we keep)
diff --git a/compiler/GHC/Driver/Pipeline/Execute.hs b/compiler/GHC/Driver/Pipeline/Execute.hs
index 61fc86c836..da214cdc20 100644
--- a/compiler/GHC/Driver/Pipeline/Execute.hs
+++ b/compiler/GHC/Driver/Pipeline/Execute.hs
@@ -1089,12 +1089,15 @@ enabled in the toolchain:
suggests, this tells the linker to produce a bigobj-enabled COFF object, no a
PE executable.
-We must enable bigobj output in a few places:
+Previously when we used ld.bfd we had to enable bigobj output in a few places:
* When merging object files (GHC.Driver.Pipeline.Execute.joinObjectFiles)
* When assembling (GHC.Driver.Pipeline.runPhase (RealPhase As ...))
+However, this is no longer necessary with ld.lld, which detects that the
+object is large on its own.
+
Unfortunately the big object format is not supported on 32-bit targets so
none of this can be used in that case.
diff --git a/compiler/GHC/SysTools/Info.hs b/compiler/GHC/SysTools/Info.hs
index 580e76ab8e..a953b9da21 100644
--- a/compiler/GHC/SysTools/Info.hs
+++ b/compiler/GHC/SysTools/Info.hs
@@ -68,30 +68,6 @@ The flag is only needed on ELF systems. On Windows (PE) and Mac OS X
-}
-{- 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
@@ -166,12 +142,10 @@ getLinkerInfo' logger dflags = do
-- Process creation is also fairly expensive on win32, so
-- we short-circuit here.
return $ GnuLD $ map Option
- [ -- Emit gcc stack checks
+ [ -- Emit stack checks
-- See Note [Windows stack allocations]
"-fstack-check"
- -- Force static linking of libGCC
- -- See 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.
diff --git a/compiler/GHC/SysTools/Tasks.hs b/compiler/GHC/SysTools/Tasks.hs
index ded526513a..d6532a6234 100644
--- a/compiler/GHC/SysTools/Tasks.hs
+++ b/compiler/GHC/SysTools/Tasks.hs
@@ -374,25 +374,11 @@ runRanlib logger dflags args = traceToolCommand logger "ranlib" $ do
runWindres :: Logger -> DynFlags -> [Option] -> IO ()
runWindres logger dflags args = traceToolCommand logger "windres" $ do
- let cc = pgm_c dflags
- cc_args = map Option (sOpt_c (settings dflags))
+ let 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=" ++ quote cc) ]
- ++ map (Option . ("--preprocessor-arg=" ++) . quote)
- (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 logger id "Windres" windres args' Nothing mb_env
+ runSomethingFiltered logger id "Windres" windres (opts ++ args) Nothing mb_env
touch :: Logger -> DynFlags -> String -> String -> IO ()
touch logger dflags purpose arg = traceToolCommand logger "touch" $
diff --git a/configure.ac b/configure.ac
index 95d0043f59..7f2fb42bc6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -354,111 +354,10 @@ AC_SUBST(TargetHasRTSLinker)
# Requires FPTOOLS_SET_PLATFORMS_VARS to be run first.
FP_FIND_ROOT
-
-if test "$HostOS" = "mingw32"
-then
- # Find the mingw-w64 7z file to extract.
- # NB. If you update the tarballs to a new version of gcc, don't
- # forget to tweak the paths in driver/gcc/gcc.c.
- if test "$HostArch" = "i386"
- then
- mingw_arch="i686"
- tarball_dest_dir="mingw-w64/i686"
- tarball_mingw_dir="mingw32"
- else
- mingw_arch="x86_64"
- tarball_dest_dir="mingw-w64/x86_64"
- tarball_mingw_dir="mingw64"
- fi
-fi
-
-set_up_tarballs() {
- AC_MSG_NOTICE([Checking for Windows toolchain tarballs...])
- local action
- if test "$TarballsAutodownload" = "NO"
- then
- action="verify"
- else
- action="download"
- fi
- $PYTHON mk/get-win32-tarballs.py $action $mingw_arch > missing-win32-tarballs
- case $? in
- 0)
- rm missing-win32-tarballs
- ;;
- 2)
- echo
- echo "Error:"
- echo "Needed msys2 tarballs are missing. You have a few options to get them,"
- echo
- echo " * run configure with the --enable-tarballs-autodownload option"
- echo
- echo " * run mk/get-win32-tarballs.py download $mingw_arch"
- echo
- echo " * manually download the files listed in ./missing-win32-tarballs and place"
- echo " them in the ghc-tarballs directory."
- echo
- exit 1
- ;;
- *)
- echo
- echo "Error fetching msys2 tarballs; see errors above."
- exit 1
- ;;
- esac
-
- # Extract all the tarballs in one go
- if ! test -d inplace/mingw
- then
- AC_MSG_NOTICE([Extracting Windows toolchain from archives (may take a while)...])
- rm -rf inplace/mingw
- local base_dir="../ghc-tarballs/${tarball_dest_dir}"
- ( cd inplace &&
- find "${base_dir}" -name "*.tar.xz" -exec tar --xz -xf {} \; &&
- find "${base_dir}" -name "*.tar.zst" -exec tar --zstd -xf {} \; &&
- rm ".MTREE" &&
- rm ".PKGINFO" &&
- cd .. ) || AC_MSG_ERROR([Could not extract Windows toolchains.])
-
- mv "inplace/${tarball_mingw_dir}" inplace/mingw &&
- touch inplace/mingw
-
- # NB. Now since the GCC is hardcoded to use /mingw32 we need to
- # make a wrapper around it to give it the proper paths
- mv inplace/mingw/bin/gcc.exe inplace/mingw/bin/realgcc.exe
- PATH=`pwd`/inplace/mingw/bin:$PATH
- inplace/mingw/bin/realgcc.exe driver/gcc/gcc.c driver/utils/cwrapper.c driver/utils/getLocation.c -Idriver/utils -o inplace/mingw/bin/gcc.exe
-
- AC_MSG_NOTICE([In-tree MingW-w64 tree created])
- fi
-}
-
-# See Note [tooldir: How GHC finds mingw on Windows]
-if test "$HostOS" = "mingw32" -a "$EnableDistroToolchain" = "NO"
-then
- test -d inplace || mkdir inplace
-
- # NB. Download and extract the MingW-w64 distribution if required
- set_up_tarballs
-
- mingwbin="$hardtop/inplace/mingw/bin/"
- CC="${mingwbin}gcc.exe"
- LD="${mingwbin}ld.exe"
- NM="${mingwbin}nm.exe"
- RANLIB="${mingwbin}ranlib.exe"
- OBJDUMP="${mingwbin}objdump.exe"
- MergeObjsCmd="$LD"
- MergeObjsArgs="-r --oformat=pe-bigobj-x86-64"
- fp_prog_ar="${mingwbin}ar.exe"
-
- AC_PATH_PROG([Genlib],[genlib])
-fi
-
-# We don't want to bundle a MinGW-w64 toolchain
-# So we have to find these individual tools.
-# See Note [tooldir: How GHC finds mingw on Windows]
-if test "$EnableDistroToolchain" = "YES"
-then
+# Extract and configure the Windows toolchain
+if test "$HostOS" = "mingw32" -a "$EnableDistroToolchain" = "NO"; then
+ FP_SETUP_WINDOWS_TOOLCHAIN
+else
# Ideally should use AC_CHECK_TARGET_TOOL but our triples
# are screwed up. Configure doesn't think they're ever equal and
# so never tried without the prefix.
@@ -471,28 +370,28 @@ then
AC_PATH_PROG([DllWrap],[dllwrap])
AC_PATH_PROG([Windres],[windres])
AC_PATH_PROG([Genlib],[genlib])
-else
- AC_CHECK_TARGET_TOOL([Windres],[windres])
- AC_CHECK_TARGET_TOOL([DllWrap],[dllwrap])
- AC_CHECK_TARGET_TOOL([OBJDUMP],[objdump])
-fi
-DllWrapCmd="$DllWrap"
-WindresCmd="$Windres"
+ HAVE_GENLIB=False
+ if test "$HostOS" = "mingw32"; then
+ AC_CHECK_TARGET_TOOL([Windres],[windres])
+ AC_CHECK_TARGET_TOOL([DllWrap],[dllwrap])
+ AC_CHECK_TARGET_TOOL([OBJDUMP],[objdump])
-HAVE_GENLIB=False
-if test "$HostOS" = "mingw32"
-then
- if test "$Genlib" != ""; then
- GenlibCmd="$(cygpath -m $Genlib)"
- HAVE_GENLIB=True
+ if test "$Genlib" != ""; then
+ GenlibCmd="$(cygpath -m $Genlib)"
+ HAVE_GENLIB=True
+ fi
fi
fi
-AC_SUBST([DllWrapCmd])
-AC_SUBST([WindresCmd])
-AC_SUBST([GenlibCmd])
-AC_SUBST([HAVE_GENLIB])
+if test "$HostOS" = "mingw32"; then
+ DllWrapCmd="$DllWrap"
+ WindresCmd="$Windres"
+ AC_SUBST([DllWrapCmd])
+ AC_SUBST([WindresCmd])
+ AC_SUBST([GenlibCmd])
+ AC_SUBST([HAVE_GENLIB])
+fi
FP_ICONV
FP_GMP
diff --git a/driver/gcc/gcc.c b/driver/gcc/gcc.c
deleted file mode 100644
index aa63bb0498..0000000000
--- a/driver/gcc/gcc.c
+++ /dev/null
@@ -1,66 +0,0 @@
-
-/* gcc on mingw is hardcoded to use /mingw (which is c:/mingw) to
- find various files. If this is a different version of mingw to the
- one that we have in the GHC tree then things can go wrong. We
- therefore need to add various -B flags to the gcc commandline,
- so that it uses our in-tree mingw. Hence this wrapper. */
-
-#include "cwrapper.h"
-#include "getLocation.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-int main(int argc, char** argv) {
- char *binDir;
- char *exePath;
- char *preArgv[4];
- char *oldPath;
- char *newPath;
- char *base;
- char *version;
- int n;
-
- binDir = getExecutablePath();
- exePath = mkString("%s/realgcc.exe", binDir);
-
- /* We need programs like
- inplace/mingw/libexec/gcc/mingw32/4.5.0/cc1.exe
- to be able to find the DLLs in inplace/mingw/bin, so we need to
- add it to $PATH */
- oldPath = getenv("PATH");
- if (!oldPath) {
- die("Couldn't read PATH\n");
- }
- n = snprintf(NULL, 0, "PATH=%s;%s", binDir, oldPath);
- n++;
- newPath = malloc(n);
- if (!newPath) {
- die("Couldn't allocate space for PATH\n");
- }
- snprintf(newPath, n, "PATH=%s;%s", binDir, oldPath);
- n = putenv(newPath);
- if (n) {
- die("putenv failed\n");
- }
-
- /* GCC Version. */
- version = mkString("%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
-
- /* Without these -B args, gcc will still work. However, if you
- have a mingw installation in c:/mingw then it will use files
- from that in preference to the in-tree files. */
- preArgv[0] = mkString("-B%s", binDir);
- preArgv[1] = mkString("-B%s/../lib", binDir);
-#if defined(__MINGW64__)
- base = mkString("x86_64-w64-mingw32");
-#else
- base = mkString("i686-w64-mingw32");
-#endif
-
- preArgv[2] = mkString("-B%s/../lib/gcc/%s/%s" , binDir, base, version);
- preArgv[3] = mkString("-B%s/../libexec/gcc/%s/%s", binDir, base, version);
-
- run(exePath, 4, preArgv, argc - 1, argv + 1, NULL);
-}
-
diff --git a/hadrian/src/Oracles/Flag.hs b/hadrian/src/Oracles/Flag.hs
index 40ae3e8f9b..7c05be5a68 100644
--- a/hadrian/src/Oracles/Flag.hs
+++ b/hadrian/src/Oracles/Flag.hs
@@ -1,8 +1,11 @@
{-# LANGUAGE MultiWayIf #-}
module Oracles.Flag (
- Flag (..), flag, getFlag, platformSupportsSharedLibs,
- targetSupportsSMP, useLibffiForAdjustors
+ Flag (..), flag, getFlag,
+ platformSupportsSharedLibs,
+ platformSupportsGhciObjects,
+ targetSupportsSMP,
+ useLibffiForAdjustors
) where
import Hadrian.Oracles.TextFile
@@ -60,6 +63,12 @@ flag f = do
getFlag :: Flag -> Expr c b Bool
getFlag = expr . flag
+-- | Does the platform support object merging (and therefore we can build GHCi objects
+-- when appropriate).
+platformSupportsGhciObjects :: Action Bool
+platformSupportsGhciObjects =
+ not . null <$> settingsFileSetting SettingsFileSetting_MergeObjectsCommand
+
platformSupportsSharedLibs :: Action Bool
platformSupportsSharedLibs = do
windows <- isWinTarget
diff --git a/hadrian/src/Rules/BinaryDist.hs b/hadrian/src/Rules/BinaryDist.hs
index b47eff4eec..3b5dbca5a6 100644
--- a/hadrian/src/Rules/BinaryDist.hs
+++ b/hadrian/src/Rules/BinaryDist.hs
@@ -466,12 +466,12 @@ iservBins = do
-- | Create a wrapper script calls the executable given as first argument
createVersionWrapper :: String -> FilePath -> Action ()
createVersionWrapper versioned_exe install_path = do
- ccPath <- builderPath (Cc CompileC Stage2)
+ ghcPath <- builderPath (Ghc CompileCWithGhc Stage2)
top <- topDirectory
let version_wrapper_dir = top -/- "hadrian" -/- "bindist" -/- "cwrappers"
wrapper_files = [ version_wrapper_dir -/- file | file <- ["version-wrapper.c", "getLocation.c", "cwrapper.c"]]
- cmd ccPath (["-o", install_path, "-I", version_wrapper_dir
+ cmd ghcPath (["-no-hs-main", "-o", install_path, "-I"++version_wrapper_dir
, "-DEXE_PATH=\"" ++ versioned_exe ++ "\""
] ++ wrapper_files)
diff --git a/hadrian/src/Rules/Register.hs b/hadrian/src/Rules/Register.hs
index cefdf04cb7..c510e96c02 100644
--- a/hadrian/src/Rules/Register.hs
+++ b/hadrian/src/Rules/Register.hs
@@ -9,6 +9,7 @@ import Expression ( getContextData )
import Hadrian.BuildPath
import Hadrian.Expression
import Hadrian.Haskell.Cabal
+import Oracles.Flag (platformSupportsGhciObjects)
import Packages
import Rules.Rts
import {-# SOURCE #-} Rules.Library (needLibrary)
@@ -206,12 +207,14 @@ extraTargets context
-- | Given a library 'Package' this action computes all of its targets. Needing
-- all the targets should build the library such that it is ready to be
-- registered into the package database.
--- See 'packageTargets' for the explanation of the @includeGhciLib@ parameter.
+-- See 'Rules.packageTargets' for the explanation of the @includeGhciLib@
+-- parameter.
libraryTargets :: Bool -> Context -> Action [FilePath]
libraryTargets includeGhciLib context@Context {..} = do
libFile <- pkgLibraryFile context
ghciLib <- pkgGhciLibraryFile context
- ghci <- if includeGhciLib && not (wayUnit Dynamic way)
+ ghciObjsSupported <- platformSupportsGhciObjects
+ ghci <- if ghciObjsSupported && includeGhciLib && not (wayUnit Dynamic way)
then interpretInContext context $ getContextData buildGhciLib
else return False
extra <- extraTargets context
diff --git a/hadrian/src/Settings/Builders/Cabal.hs b/hadrian/src/Settings/Builders/Cabal.hs
index 1ef20147ae..c6a83ce12b 100644
--- a/hadrian/src/Settings/Builders/Cabal.hs
+++ b/hadrian/src/Settings/Builders/Cabal.hs
@@ -139,6 +139,7 @@ libraryArgs = do
package <- getPackage
withGhci <- expr ghcWithInterpreter
dynPrograms <- expr (flavour >>= dynamicGhcPrograms)
+ ghciObjsSupported <- expr platformSupportsGhciObjects
let ways = flavourWays ++ [contextWay]
hasVanilla = vanilla `elem` ways
hasProfiling = any (wayUnit Profiling) ways
@@ -149,7 +150,8 @@ libraryArgs = do
, if hasProfiling
then "--enable-library-profiling"
else "--disable-library-profiling"
- , if (hasVanilla || hasProfiling) &&
+ , if ghciObjsSupported &&
+ (hasVanilla || hasProfiling) &&
package /= rts && withGhci && not dynPrograms
then "--enable-library-for-ghci"
else "--disable-library-for-ghci"
diff --git a/libraries/Cabal b/libraries/Cabal
-Subproject d638e33dbc056048b393964286c7fe394b2730d
+Subproject 9eda67ca9a069dce44c627ca5a297b95f4155a6
diff --git a/libraries/base/aclocal.m4 b/libraries/base/aclocal.m4
index 3a028dda16..0336a092a8 100644
--- a/libraries/base/aclocal.m4
+++ b/libraries/base/aclocal.m4
@@ -253,3 +253,19 @@ AS_IF([test "$ac_res" != no],
[$6])dnl
AS_VAR_POPDEF([ac_Search])dnl
])
+
+AC_DEFUN([FP_CHECK_ENVIRON],
+[
+ dnl--------------------------------------------------------------------
+ dnl * Check whether the libc headers provide a declaration for the
+ dnl environ symbol. If not then we will provide one in RtsSymbols.c.
+ dnl See #20512, #20577, #20861.
+ dnl
+ dnl N.B. Windows declares environ in <stdlib.h>; most others declare it
+ dnl in <unistd.h>.
+ dnl--------------------------------------------------------------------
+ AC_CHECK_DECLS([environ], [], [], [
+ #include <stdlib.h>
+ #include <unistd.h>
+ ])
+])
diff --git a/libraries/base/configure.ac b/libraries/base/configure.ac
index e034549476..6fc96d92f4 100644
--- a/libraries/base/configure.ac
+++ b/libraries/base/configure.ac
@@ -189,6 +189,8 @@ FP_CHECK_CONSTS([SIGINT], [
dnl ** can we open files in binary mode?
FP_CHECK_CONST([O_BINARY], [#include <fcntl.h>], [0])
+FP_CHECK_ENVIRON
+
# We don't use iconv or libcharset on Windows, but if configure finds
# them then it can cause problems. So we don't even try looking if
# we are on Windows.
diff --git a/libraries/base/include/HsBase.h b/libraries/base/include/HsBase.h
index d5884473ca..243d9698ee 100644
--- a/libraries/base/include/HsBase.h
+++ b/libraries/base/include/HsBase.h
@@ -552,9 +552,9 @@ INLINE int __hscore_open(char *file, int how, mode_t mode) {
#include <crt_externs.h>
INLINE char **__hscore_environ(void) { return *(_NSGetEnviron()); }
#else
-/* ToDo: write a feature test that doesn't assume 'environ' to
- * be in scope at link-time. */
+#if !HAVE_DECL_ENVIRON
extern char** environ;
+#endif
INLINE char **__hscore_environ(void) { return environ; }
#endif
diff --git a/libraries/bytestring b/libraries/bytestring
-Subproject e84481a06ae4b50984469a79f2c1af4b2f02029
+Subproject a44600feac0d6461964f10f505f8318a4b6aa71
diff --git a/libraries/ghc-prim/ghc-prim.cabal b/libraries/ghc-prim/ghc-prim.cabal
index dbe5d18667..4be29843ae 100644
--- a/libraries/ghc-prim/ghc-prim.cabal
+++ b/libraries/ghc-prim/ghc-prim.cabal
@@ -68,7 +68,7 @@ Library
-- mingw32 which is required by mingwex.
-- user32: provides access to apis to modify user components (UI etc)
-- on Windows. Required because of mingw32.
- extra-libraries: user32, mingw32, mingwex
+ extra-libraries: user32, mingw32, mingwex, ucrt
if os(linux)
-- we need libm, but for musl and other's we might need libc, as libm
diff --git a/libraries/process b/libraries/process
-Subproject 7fd28338c82c89deb3e5db117e87633898046d7
+Subproject 1785cf0314854e4023cd35d05c4e01a9b40a77e
diff --git a/libraries/text b/libraries/text
-Subproject 7b13f15ded23953d5b52b9e74bfe7e2cbc8bb69
+Subproject 5a43fecb62e9769c4cf8b456c7b273901048ea7
diff --git a/m4/fp_check_environ.m4 b/m4/fp_check_environ.m4
index 88bf0a52de..f0daedc9c0 100644
--- a/m4/fp_check_environ.m4
+++ b/m4/fp_check_environ.m4
@@ -4,11 +4,14 @@ AC_DEFUN([FP_CHECK_ENVIRON],
[
dnl--------------------------------------------------------------------
dnl * Check whether the libc headers provide a declaration for the
- dnl environ symbol. If not then we will provide one in RtsSymbols.c.
+ dnl environ symbol. If not then we will provide one in RtsSymbols.c.
dnl See #20512, #20577, #20861.
+ dnl
+ dnl N.B. Windows declares environ in <stdlib.h>; most others declare it
+ dnl in <unistd.h>.
dnl--------------------------------------------------------------------
AC_CHECK_DECLS([environ], [], [], [
+ #include <stdlib.h>
#include <unistd.h>
])
])
-
diff --git a/m4/fp_settings.m4 b/m4/fp_settings.m4
index 09a24f33e1..4db7cd46af 100644
--- a/m4/fp_settings.m4
+++ b/m4/fp_settings.m4
@@ -1,104 +1,113 @@
# FP_SETTINGS
# ----------------------------------
# Set the variables used in the settings file
-# See Note [tooldir: How GHC finds mingw on Windows]
AC_DEFUN([FP_SETTINGS],
[
- if test "$windows" = YES -a "$EnableDistroToolchain" = "NO"
- then
+ SettingsUseDistroMINGW="$EnableDistroToolchain"
+
+ if test "$windows" = YES -a "$EnableDistroToolchain" = "NO"; then
+ # Handle the Windows toolchain installed in FP_SETUP_WINDOWS_TOOLCHAIN.
+ # See Note [tooldir: How GHC finds mingw on Windows]
mingw_bin_prefix='$$tooldir/mingw/bin/'
- SettingsCCompilerCommand="${mingw_bin_prefix}gcc.exe"
- SettingsHaskellCPPCommand="${mingw_bin_prefix}gcc.exe"
- SettingsHaskellCPPFlags="$HaskellCPPArgs"
- SettingsLdCommand="${mingw_bin_prefix}ld.exe"
- # Overrides FIND_MERGE_OBJECTS in order to avoid hard-coding linker
- # path on Windows (#18550).
- SettingsMergeObjectsCommand="${SettingsLdCommand}"
- SettingsMergeObjectsFlags="-r --oformat=pe-bigobj-x86-64"
- SettingsArCommand="${mingw_bin_prefix}ar.exe"
- SettingsRanlibCommand="${mingw_bin_prefix}ranlib.exe"
- SettingsDllWrapCommand="${mingw_bin_prefix}dllwrap.exe"
- SettingsWindresCommand="${mingw_bin_prefix}windres.exe"
- SettingsTouchCommand='$$topdir/bin/touchy.exe'
- elif test "$EnableDistroToolchain" = "YES"
- then
- SettingsCCompilerCommand="$(basename $CC)"
+ SettingsCCompilerCommand="${mingw_bin_prefix}clang.exe"
SettingsCCompilerFlags="$CONF_CC_OPTS_STAGE2"
SettingsCxxCompilerFlags="$CONF_CXX_OPTS_STAGE2"
- SettingsHaskellCPPCommand="$(basename $HaskellCPPCmd)"
+ SettingsCCompilerLinkFlags="$CONF_GCC_LINKER_OPTS_STAGE2"
+ SettingsHaskellCPPCommand="${mingw_bin_prefix}clang.exe"
SettingsHaskellCPPFlags="$HaskellCPPArgs"
- SettingsLdCommand="$(basename $LdCmd)"
- SettingsMergeObjectsCommand="$(basename $MergeObjsCmd)"
- SettingsMergeObjectsFlags="$MergeObjsArgs"
- SettingsArCommand="$(basename $ArCmd)"
- SettingsDllWrapCommand="$(basename $DllWrapCmd)"
- SettingsWindresCommand="$(basename $WindresCmd)"
+ SettingsLdCommand="${mingw_bin_prefix}ld.lld.exe"
+ SettingsLdFlags=""
+ # LLD does not support object merging (#21068)
+ SettingsMergeObjectsCommand=""
+ SettingsMergeObjectsFlags=""
+ SettingsArCommand="${mingw_bin_prefix}llvm-ar.exe"
+ SettingsRanlibCommand="${mingw_bin_prefix}llvm-ranlib.exe"
+ SettingsDllWrapCommand="${mingw_bin_prefix}llvm-dllwrap.exe"
+ SettingsWindresCommand="${mingw_bin_prefix}llvm-windres.exe"
SettingsTouchCommand='$$topdir/bin/touchy.exe'
+
else
+ # This case handles the "normal" platforms (e.g. not Windows) where we
+ # don't provide the toolchain.
+
SettingsCCompilerCommand="$CC"
+ SettingsCCompilerFlags="$CONF_CC_OPTS_STAGE2"
+ SettingsCxxCompilerFlags="$CONF_CXX_OPTS_STAGE2"
SettingsHaskellCPPCommand="$HaskellCPPCmd"
SettingsHaskellCPPFlags="$HaskellCPPArgs"
+ SettingsCCompilerLinkFlags="$CONF_GCC_LINKER_OPTS_STAGE2"
SettingsLdCommand="$LdCmd"
- SettingsMergeObjectsCommand="$MergeObjsCmd"
- SettingsMergeObjectsFlags="$MergeObjsArgs"
+ SettingsLdFlags="$CONF_LD_LINKER_OPTS_STAGE2"
SettingsArCommand="$ArCmd"
SettingsRanlibCommand="$RanlibCmd"
- if test -z "$DllWrapCmd"
- then
+ SettingsMergeObjectsCommand="$MergeObjsCmd"
+ SettingsMergeObjectsFlags="$MergeObjsArgs"
+
+ if test -z "$DllWrapCmd"; then
SettingsDllWrapCommand="/bin/false"
else
SettingsDllWrapCommand="$DllWrapCmd"
fi
- if test -z "$WindresCmd"
- then
+ if test -z "$WindresCmd"; then
SettingsWindresCommand="/bin/false"
else
SettingsWindresCommand="$WindresCmd"
fi
- SettingsTouchCommand='touch'
+
+ if test "$HostOS" = "mingw32"; then
+ SettingsTouchCommand='$$topdir/bin/touchy.exe'
+ else
+ SettingsTouchCommand='touch'
+ fi
+
+ if test "$EnableDistroToolchain" = "YES"; then
+ # If the user specified --enable-distro-toolchain then we just use the
+ # executable names, not paths.
+ SettingsCCompilerCommand="$(basename $SettingsCCompilerCommand)"
+ SettingsHaskellCPPCommand="$(basename $SettingsHaskellCPPCommand)"
+ SettingsLdCommand="$(basename $SettingsLdCommand)"
+ SettingsMergeObjectsCommand="$(basename $SettingsMergeObjectsCommand)"
+ SettingsArCommand="$(basename $SettingsArCommand)"
+ SettingsDllWrapCommand="$(basename $SettingsDllWrapCommand)"
+ SettingsWindresCommand="$(basename $SettingsWindresCommand)"
+ fi
fi
- if test -z "$LibtoolCmd"
- then
- SettingsLibtoolCommand="libtool"
- else
- SettingsLibtoolCommand="$LibtoolCmd"
+
+ # Platform-agnostic tools
+ if test -z "$LibtoolCmd"; then
+ LibtoolCmd="libtool"
fi
- if test -z "$ClangCmd"
- then
- SettingsClangCommand="clang"
- else
- SettingsClangCommand="$ClangCmd"
+ SettingsLibtoolCommand="$LibtoolCmd"
+
+ if test -z "$ClangCmd"; then
+ ClangCmd="clang"
fi
- if test -z "$LlcCmd"
- then
- SettingsLlcCommand="llc"
- else
- SettingsLlcCommand="$LlcCmd"
+ SettingsClangCommand="$ClangCmd"
+
+ # LLVM backend tools
+ if test -z "$LlcCmd"; then
+ LlcCmd="llc"
fi
- if test -z "$OptCmd"
- then
- SettingsOptCommand="opt"
- else
- SettingsOptCommand="$OptCmd"
+ SettingsLlcCommand="$LlcCmd"
+
+ if test -z "$OptCmd"; then
+ OptCmd="opt"
fi
- if test -z "$OtoolCmd"
- then
- SettingsOtoolCommand="otool"
- else
- SettingsOtoolCommand="$OtoolCmd"
+ SettingsOptCommand="$OptCmd"
+
+ # Mac-only tools
+ if test -z "$OtoolCmd"; then
+ OtoolCmd="otool"
fi
- if test -z "$InstallNameToolCmd"
- then
- SettingsInstallNameToolCommand="install_name_tool"
- else
- SettingsInstallNameToolCommand="$InstallNameToolCmd"
+ SettingsOtoolCommand="$OtoolCmd"
+
+ if test -z "$InstallNameToolCmd"; then
+ InstallNameToolCmd="install_name_tool"
fi
- SettingsCCompilerFlags="$CONF_CC_OPTS_STAGE2"
- SettingsCxxCompilerFlags="$CONF_CXX_OPTS_STAGE2"
- SettingsCCompilerLinkFlags="$CONF_GCC_LINKER_OPTS_STAGE2"
+ SettingsInstallNameToolCommand="$InstallNameToolCmd"
+
SettingsCCompilerSupportsNoPie="$CONF_GCC_SUPPORTS_NO_PIE"
- SettingsLdFlags="$CONF_LD_LINKER_OPTS_STAGE2"
- SettingsUseDistroMINGW="$EnableDistroToolchain"
+
AC_SUBST(SettingsCCompilerCommand)
AC_SUBST(SettingsHaskellCPPCommand)
AC_SUBST(SettingsHaskellCPPFlags)
diff --git a/m4/fp_setup_windows_toolchain.m4 b/m4/fp_setup_windows_toolchain.m4
new file mode 100644
index 0000000000..35e322c8a0
--- /dev/null
+++ b/m4/fp_setup_windows_toolchain.m4
@@ -0,0 +1,107 @@
+AC_DEFUN([FP_SETUP_WINDOWS_TOOLCHAIN],[
+ # Find the mingw-w64 archive file to extract.
+ if test "$HostArch" = "i386"
+ then
+ mingw_arch="i686"
+ tarball_dest_dir="mingw-w64/i686"
+ tarball_mingw_dir="clang32"
+ else
+ mingw_arch="x86_64"
+ tarball_dest_dir="mingw-w64/x86_64"
+ tarball_mingw_dir="clang64"
+ fi
+
+ set_up_tarballs() {
+ AC_MSG_NOTICE([Checking for Windows toolchain tarballs...])
+ local action
+ if test "$TarballsAutodownload" = "NO"
+ then
+ action="verify"
+ else
+ action="download"
+ fi
+ $PYTHON mk/get-win32-tarballs.py $action $mingw_arch > missing-win32-tarballs
+ case $? in
+ 0)
+ rm missing-win32-tarballs
+ ;;
+ 2)
+ echo
+ echo "Error:"
+ echo "Needed msys2 tarballs are missing. You have a few options to get them,"
+ echo
+ echo " * run configure with the --enable-tarballs-autodownload option"
+ echo
+ echo " * run mk/get-win32-tarballs.py download $mingw_arch"
+ echo
+ echo " * manually download the files listed in ./missing-win32-tarballs and place"
+ echo " them in the ghc-tarballs directory."
+ echo
+ exit 1
+ ;;
+ *)
+ echo
+ echo "Error fetching msys2 tarballs; see errors above."
+ exit 1
+ ;;
+ esac
+
+ # Extract all the tarballs in one go
+ if ! test -d inplace/mingw
+ then
+ AC_MSG_NOTICE([Extracting Windows toolchain from archives (may take a while)...])
+ rm -rf inplace/mingw
+ local base_dir="../ghc-tarballs/${tarball_dest_dir}"
+ ( cd inplace &&
+ find "${base_dir}" -name "*.tar.xz" -exec tar --xz -xf {} \; &&
+ find "${base_dir}" -name "*.tar.zst" -exec tar --zstd -xf {} \; &&
+ rm ".MTREE" &&
+ rm ".PKGINFO" &&
+ cd .. ) || AC_MSG_ERROR([Could not extract Windows toolchains.])
+
+ mv "inplace/${tarball_mingw_dir}" inplace/mingw &&
+ touch inplace/mingw
+ AC_MSG_NOTICE([In-tree MingW-w64 tree created])
+ fi
+ }
+
+ # See Note [tooldir: How GHC finds mingw on Windows]
+ test -d inplace || mkdir inplace
+
+ # NB. Download and extract the MingW-w64 distribution if required
+ set_up_tarballs
+
+ # N.B. The parameters which get plopped in the `settings` file used by the
+ # resulting compiler are computed in `FP_SETTINGS`.
+
+ # Our Windows toolchain is based around Clang and LLD. We use compiler-rt
+ # for the runtime, libc++ and libc++abi for the C++ standard library
+ # implementation, and libunwind for C++ unwinding.
+ mingwbin="$hardtop/inplace/mingw/bin/"
+
+ CC="${mingwbin}clang.exe"
+ cflags="--rtlib=compiler-rt"
+ CFLAGS="$cflags"
+ CONF_CC_OPTS_STAGE1="$cflags"
+ CONF_CC_OPTS_STAGE2="$cflags"
+
+ cxxflags="--rtlib=compiler-rt --unwindlib=libunwind --stdlib=libc++"
+ CXXFLAGS="$cxxflags"
+ CONF_CXX_OPTS_STAGE1="$cxxflags"
+ CONF_CXX_OPTS_STAGE2="$cxxflags"
+
+ CONF_GCC_LINKER_OPTS_STAGE1="-fuse-ld=lld $cflags"
+ CONF_GCC_LINKER_OPTS_STAGE2="-fuse-ld=lld $cflags"
+
+ LD="${mingwbin}ld.lld.exe"
+ NM="${mingwbin}llvm-nm.exe"
+ AR="${mingwbin}llvm-ar.exe"
+ RANLIB="${mingwbin}llvm-ranlib.exe"
+ OBJDUMP="${mingwbin}llvm-objdump.exe"
+ DLLTOOL="${mingwbin}llvm-dlltool.exe"
+
+ # N.B. LLD does not support -r
+ MergeObjsCmd=""
+ MergeObjsArgs=""
+ AC_PATH_PROG([Genlib],[genlib])
+])
diff --git a/mk/config.mk.in b/mk/config.mk.in
index 06e1dabd96..e1474a34a3 100644
--- a/mk/config.mk.in
+++ b/mk/config.mk.in
@@ -655,11 +655,7 @@ SRC_HSC2HS_OPTS_STAGE0 += --cflag=-D$(HostArch_CPP)_HOST_ARCH --cflag=-D$(HostOS
SRC_HSC2HS_OPTS_STAGE1 += --cflag=-D$(TargetArch_CPP)_HOST_ARCH --cflag=-D$(TargetOS_CPP)_HOST_OS
SRC_HSC2HS_OPTS_STAGE2 += --cflag=-D$(TargetArch_CPP)_HOST_ARCH --cflag=-D$(TargetOS_CPP)_HOST_OS
-ifeq "$(TARGETPLATFORM)" "i386-unknown-mingw32"
-WINDRES = $(INPLACE_MINGW)/bin/windres
-else ifeq "$(TARGETPLATFORM)" "x86_64-unknown-mingw32"
-WINDRES = $(INPLACE_MINGW)/bin/windres
-endif
+WINDRES=@WindresCmd@
#-----------------------------------------------------------------------------
# Python for testsuite driver and code generators
@@ -670,11 +666,7 @@ PYTHON=@PythonCmd@
# Mingwex Library
#
HaveLibMingwEx = @HaveLibMingwEx@
-ifeq "$(TARGETPLATFORM)" "i386-unknown-mingw32"
-DLLTOOL = inplace/mingw/bin/dlltool.exe
-else ifeq "$(TARGETPLATFORM)" "x86_64-unknown-mingw32"
-DLLTOOL = inplace/mingw/bin/dlltool.exe
-endif
+DLLTOOL = @DlltoolCmd@
#-----------------------------------------------------------------------------
# Other standard (ha!) Unix utilities
diff --git a/mk/get-win32-tarballs.py b/mk/get-win32-tarballs.py
index f1ada96b48..351212ba71 100755
--- a/mk/get-win32-tarballs.py
+++ b/mk/get-win32-tarballs.py
@@ -8,7 +8,7 @@ import argparse
import sys
from sys import stderr
-TARBALL_VERSION = '0.3'
+TARBALL_VERSION = '0.7'
BASE_URL = "https://downloads.haskell.org/ghc/mingw/{}".format(TARBALL_VERSION)
DEST = Path('ghc-tarballs/mingw-w64')
ARCHS = ['i686', 'x86_64', 'sources']
diff --git a/rts/CheckUnload.h b/rts/CheckUnload.h
index de07aef1c3..5471544433 100644
--- a/rts/CheckUnload.h
+++ b/rts/CheckUnload.h
@@ -10,10 +10,10 @@
#pragma once
-#include "BeginPrivate.h"
-
#include "LinkerInternals.h"
+#include "BeginPrivate.h"
+
// Currently live objects
extern ObjectCode *objects;
diff --git a/rts/HsFFI.c b/rts/HsFFI.c
index 58651b81e9..0b9f3f0063 100644
--- a/rts/HsFFI.c
+++ b/rts/HsFFI.c
@@ -7,8 +7,8 @@
* ---------------------------------------------------------------------------*/
#include "rts/PosixSource.h"
-#include "HsFFI.h"
#include "Rts.h"
+#include "HsFFI.h"
#include "StablePtr.h"
#include "Task.h"
diff --git a/rts/LibdwPool.h b/rts/LibdwPool.h
index b1c333eebc..563934c7a9 100644
--- a/rts/LibdwPool.h
+++ b/rts/LibdwPool.h
@@ -8,11 +8,11 @@
#pragma once
-#include "BeginPrivate.h"
-
#include "Rts.h"
#include "Libdw.h"
+#include "BeginPrivate.h"
+
#if USE_LIBDW
/* Initialize the pool */
diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h
index 8a71179932..5711b16526 100644
--- a/rts/LinkerInternals.h
+++ b/rts/LinkerInternals.h
@@ -18,8 +18,6 @@
void printLoadedObjects(void);
-#include "BeginPrivate.h"
-
/* Which object file format are we targeting? */
#if defined(linux_HOST_OS) || defined(solaris2_HOST_OS) \
|| defined(linux_android_HOST_OS) \
@@ -403,6 +401,8 @@ typedef struct _RtsSymbolInfo {
SymType type;
} RtsSymbolInfo;
+#include "BeginPrivate.h"
+
void exitLinker( void );
void freeObjectCode (ObjectCode *oc);
diff --git a/rts/Messages.h b/rts/Messages.h
index 8cefcafd97..ecae7e6365 100644
--- a/rts/Messages.h
+++ b/rts/Messages.h
@@ -8,6 +8,10 @@
#pragma once
+#include "Capability.h"
+#include "Updates.h" // for DEBUG_FILL_SLOP
+#include "SMPClosureOps.h"
+
#include "BeginPrivate.h"
uint32_t messageBlackHole(Capability *cap, MessageBlackHole *msg);
@@ -18,10 +22,6 @@ void executeMessage (Capability *cap, Message *m);
void sendMessage (Capability *from_cap, Capability *to_cap, Message *msg);
#endif
-#include "Capability.h"
-#include "Updates.h" // for DEBUG_FILL_SLOP
-#include "SMPClosureOps.h"
-
INLINE_HEADER void
doneWithMsgThrowTo (Capability *cap, MessageThrowTo *m)
{
diff --git a/rts/PathUtils.h b/rts/PathUtils.h
index d30b515f93..df4ab3fefe 100644
--- a/rts/PathUtils.h
+++ b/rts/PathUtils.h
@@ -8,8 +8,6 @@
#pragma once
-#include "BeginPrivate.h"
-
// Use wchar_t for pathnames on Windows (#5697)
#if defined(mingw32_HOST_OS)
#include "fs_rts.h"
@@ -37,6 +35,8 @@
#define pathcopy strcpy
#endif
+#include "BeginPrivate.h"
+
pathchar* pathdup(pathchar *path);
pathchar* pathdir(pathchar *path);
pathchar* mkPath(char* path);
diff --git a/rts/Profiling.h b/rts/Profiling.h
index abb731217a..b3724c3c88 100644
--- a/rts/Profiling.h
+++ b/rts/Profiling.h
@@ -10,13 +10,13 @@
#include <stdio.h>
-#include "BeginPrivate.h"
#include "Rts.h"
-
#if defined(DEBUG)
#include "Arena.h"
#endif
+#include "BeginPrivate.h"
+
#if defined(PROFILING)
#define PROFILING_ONLY(s) s
#else
diff --git a/rts/RtsFlags.h b/rts/RtsFlags.h
index bfcc43af42..6c81081d4d 100644
--- a/rts/RtsFlags.h
+++ b/rts/RtsFlags.h
@@ -9,9 +9,10 @@
#pragma once
-#include "BeginPrivate.h"
#include <stdbool.h>
+#include "BeginPrivate.h"
+
/* Routines that operate-on/to-do-with RTS flags: */
#if defined(mingw32_HOST_OS)
diff --git a/rts/RtsSymbolInfo.c b/rts/RtsSymbolInfo.c
index 1110d582d6..f1f65bd6b6 100644
--- a/rts/RtsSymbolInfo.c
+++ b/rts/RtsSymbolInfo.c
@@ -7,9 +7,8 @@
* ---------------------------------------------------------------------------*/
#include "ghcplatform.h"
-#include "RtsSymbolInfo.h"
-
#include "Rts.h"
+#include "RtsSymbolInfo.h"
#include "HsFFI.h"
#include "Hash.h"
diff --git a/rts/RtsSymbols.c b/rts/RtsSymbols.c
index f4b3aa3953..2818df6ff3 100644
--- a/rts/RtsSymbols.c
+++ b/rts/RtsSymbols.c
@@ -7,9 +7,8 @@
* ---------------------------------------------------------------------------*/
#include "ghcplatform.h"
-#include "RtsSymbols.h"
-
#include "Rts.h"
+#include "RtsSymbols.h"
#include "TopHandler.h"
#include "HsFFI.h"
#include "CloneStack.h"
@@ -162,12 +161,12 @@ extern char **environ;
SymI_HasProto(stg_asyncDoProczh) \
SymI_HasProto(rts_InstallConsoleEvent) \
SymI_HasProto(rts_ConsoleHandlerDone) \
+ SymI_NeedsProto(__mingw_module_is_dll) \
RTS_WIN32_ONLY(SymI_NeedsProto(___chkstk_ms)) \
RTS_WIN64_ONLY(SymI_NeedsProto(___chkstk_ms)) \
- RTS_WIN32_ONLY(SymI_HasProto(_imp___environ)) \
- RTS_WIN64_ONLY(SymI_HasProto(__imp__environ)) \
- RTS_WIN32_ONLY(SymI_HasProto(_imp___iob)) \
- RTS_WIN64_ONLY(SymI_HasProto(__iob_func)) \
+ RTS_WIN64_ONLY(SymI_HasProto(__stdio_common_vswprintf_s)) \
+ RTS_WIN64_ONLY(SymI_HasProto(__stdio_common_vswprintf)) \
+ RTS_WIN64_ONLY(SymI_HasProto(_errno)) \
/* see Note [Symbols for MinGW's printf] */ \
SymI_HasProto(_lock_file) \
SymI_HasProto(_unlock_file) \
diff --git a/rts/StaticPtrTable.c b/rts/StaticPtrTable.c
index 9754cfad41..282d9b7899 100644
--- a/rts/StaticPtrTable.c
+++ b/rts/StaticPtrTable.c
@@ -8,8 +8,8 @@
*
*/
-#include "StaticPtrTable.h"
#include "Rts.h"
+#include "StaticPtrTable.h"
#include "RtsUtils.h"
#include "Hash.h"
#include "StablePtr.h"
diff --git a/rts/Stats.c b/rts/Stats.c
index 16875ce5d2..8d020d53d6 100644
--- a/rts/Stats.c
+++ b/rts/Stats.c
@@ -26,16 +26,6 @@
#include <string.h> // for memset
-#if defined(mingw32_HOST_OS)
-/* On Win64, if we say "printf" then gcc thinks we are going to use
- MS format specifiers like %I64d rather than %llu */
-#define PRINTF gnu_printf
-#else
-/* However, on OS X, "gnu_printf" isn't recognised */
-#define PRINTF printf
-#endif
-
-
#if defined(THREADED_RTS)
// Protects all statistics below
Mutex stats_mutex;
@@ -79,7 +69,7 @@ static Time *GC_coll_cpu = NULL;
static Time *GC_coll_elapsed = NULL;
static Time *GC_coll_max_pause = NULL;
-static int statsPrintf( char *s, ... ) GNUC3_ATTRIBUTE(format (PRINTF, 1, 2));
+static int statsPrintf( char *s, ... ) STG_PRINTF_ATTR(1, 2);
static void statsFlush( void );
static void statsClose( void );
diff --git a/rts/include/Stg.h b/rts/include/Stg.h
index be0995445b..209db1b0f5 100644
--- a/rts/include/Stg.h
+++ b/rts/include/Stg.h
@@ -231,6 +231,16 @@
#define STG_NO_OPTIMIZE /* nothing */
#endif
+// Mark a function as accepting a printf-like format string.
+#if !defined(__GNUC__) && defined(mingw32_HOST_OS)
+/* On Win64, if we say "printf" then gcc thinks we are going to use
+ MS format specifiers like %I64d rather than %llu */
+#define STG_PRINTF_ATTR(fmt_arg, rest) GNUC3_ATTRIBUTE(format(gnu_printf, fmt_arg, rest))
+#else
+/* However, on OS X, "gnu_printf" isn't recognised */
+#define STG_PRINTF_ATTR(fmt_arg, rest) GNUC3_ATTRIBUTE(format(printf, fmt_arg, rest))
+#endif
+
/* -----------------------------------------------------------------------------
Global type definitions
-------------------------------------------------------------------------- */
diff --git a/rts/include/rts/Messages.h b/rts/include/rts/Messages.h
index f9b3009c20..7d4727486e 100644
--- a/rts/include/rts/Messages.h
+++ b/rts/include/rts/Messages.h
@@ -18,15 +18,6 @@
#include <stdarg.h>
-#if defined(mingw32_HOST_OS) && !defined(__clang__)
-/* On Win64, if we say "printf" then gcc thinks we are going to use
- MS format specifiers like %I64d rather than %llu */
-#define PRINTF gnu_printf
-#else
-/* However, on OS X, "gnu_printf" isn't recognised */
-#define PRINTF printf
-#endif
-
/* -----------------------------------------------------------------------------
* Message generation
* -------------------------------------------------------------------------- */
@@ -41,7 +32,7 @@
*/
void barf(const char *s, ...)
GNUC3_ATTRIBUTE(__noreturn__)
- GNUC3_ATTRIBUTE(format(PRINTF, 1, 2));
+ STG_PRINTF_ATTR(1, 2);
void vbarf(const char *s, va_list ap)
GNUC3_ATTRIBUTE(__noreturn__);
@@ -57,7 +48,7 @@ void vbarf(const char *s, va_list ap)
* errorBelch() invokes (*errorMsgFn)().
*/
void errorBelch(const char *s, ...)
- GNUC3_ATTRIBUTE(format (PRINTF, 1, 2));
+ STG_PRINTF_ATTR(1, 2);
void verrorBelch(const char *s, va_list ap);
@@ -71,7 +62,7 @@ void verrorBelch(const char *s, va_list ap);
* sysErrorBelch() invokes (*sysErrorMsgFn)().
*/
void sysErrorBelch(const char *s, ...)
- GNUC3_ATTRIBUTE(format (PRINTF, 1, 2));
+ STG_PRINTF_ATTR(1, 2);
void vsysErrorBelch(const char *s, va_list ap);
@@ -83,7 +74,7 @@ void vsysErrorBelch(const char *s, va_list ap);
* debugBelch() invokes (*debugMsgFn)().
*/
void debugBelch(const char *s, ...)
- GNUC3_ATTRIBUTE(format (PRINTF, 1, 2));
+ STG_PRINTF_ATTR(1, 2);
int vdebugBelch(const char *s, va_list ap);
@@ -103,5 +94,3 @@ extern RtsMsgFunction rtsFatalInternalErrorFn;
extern RtsMsgFunctionRetLen rtsDebugMsgFn;
extern RtsMsgFunction rtsErrorMsgFn;
extern RtsMsgFunction rtsSysErrorMsgFn;
-
-#undef PRINTF
diff --git a/rts/include/rts/PosixSource.h b/rts/include/rts/PosixSource.h
index 13fd7b0ff5..be6c8ecca1 100644
--- a/rts/include/rts/PosixSource.h
+++ b/rts/include/rts/PosixSource.h
@@ -36,3 +36,15 @@
#define _POSIX_C_SOURCE 200809L
#define _XOPEN_SOURCE 700
#endif
+
+#if defined(mingw32_HOST_OS)
+# if defined(__USE_MINGW_ANSI_STDIO)
+# if __USE_MINGW_ANSI_STDIO != 1
+# warning "Mismatch between __USE_MINGW_ANSI_STDIO definitions. \
+If using PosixSource.h make sure it is the first header included."
+# endif
+# else
+/* Inform mingw we want the ISO rather than Windows printf format specifiers. */
+# define __USE_MINGW_ANSI_STDIO 1
+#endif
+#endif
diff --git a/rts/include/stg/Types.h b/rts/include/stg/Types.h
index 05dec27f0c..1a9b1685fa 100644
--- a/rts/include/stg/Types.h
+++ b/rts/include/stg/Types.h
@@ -20,18 +20,6 @@
#pragma once
-#if defined(mingw32_HOST_OS)
-# if defined(__USE_MINGW_ANSI_STDIO)
-# if __USE_MINGW_ANSI_STDIO != 1
-# warning "Mismatch between __USE_MINGW_ANSI_STDIO definitions. \
-If using Rts.h make sure it is the first header included."
-# endif
-# else
-/* Inform mingw we want the ISO rather than Windows printf format specifiers. */
-# define __USE_MINGW_ANSI_STDIO 1
-#endif
-#endif
-
/* ISO C 99 says:
* "C++ implementations should define these macros only when
* __STDC_LIMIT_MACROS is defined before <stdint.h> is included."
diff --git a/rts/linker/Elf.h b/rts/linker/Elf.h
index a16255abba..12bf1772f7 100644
--- a/rts/linker/Elf.h
+++ b/rts/linker/Elf.h
@@ -2,11 +2,10 @@
#include "Rts.h"
#include "LinkerInternals.h"
+#include "linker/ElfTypes.h"
#include "BeginPrivate.h"
-#include <linker/ElfTypes.h>
-
void ocInit_ELF ( ObjectCode* oc );
void ocDeinit_ELF ( ObjectCode* oc );
int ocVerifyImage_ELF ( ObjectCode* oc );
diff --git a/rts/linker/MachO.h b/rts/linker/MachO.h
index 518c2ce569..f55f68ddc8 100644
--- a/rts/linker/MachO.h
+++ b/rts/linker/MachO.h
@@ -1,11 +1,10 @@
#pragma once
#include "Rts.h"
+#include "MachOTypes.h"
#include "BeginPrivate.h"
-#include "MachOTypes.h"
-
void ocInit_MachO ( ObjectCode* oc );
void ocDeinit_MachO ( ObjectCode* oc );
int ocVerifyImage_MachO ( ObjectCode* oc );
diff --git a/rts/linker/PEi386.c b/rts/linker/PEi386.c
index 3a9caf1b80..420a50feae 100644
--- a/rts/linker/PEi386.c
+++ b/rts/linker/PEi386.c
@@ -495,7 +495,7 @@ void freePreloadObjectFile_PEi386(ObjectCode *oc)
See Note [Exception Unwinding]. */
if (oc->info->xdata) {
if (!RtlDeleteFunctionTable (oc->info->xdata->start))
- debugBelch ("Unable to remove Exception handlers for %" PATH_FMT,
+ debugBelch ("Unable to remove Exception handlers for %" PATH_FMT "\n",
oc->fileName);
oc->info->xdata = NULL;
oc->info->pdata = NULL;
@@ -591,7 +591,7 @@ COFF_OBJ_TYPE getObjectType ( char* image, pathchar* fileName )
*************/
COFF_HEADER_INFO* getHeaderInfo ( ObjectCode* oc )
{
- COFF_OBJ_TYPE coff_type = getObjectType (oc->image, oc->fileName);
+ COFF_OBJ_TYPE coff_type = getObjectType (oc->image, OC_INFORMATIVE_FILENAME(oc));
COFF_HEADER_INFO* info
= stgMallocBytes (sizeof(COFF_HEADER_INFO), "getHeaderInfo");
@@ -2199,6 +2199,17 @@ SymbolAddr *lookupSymbol_PEi386(SymbolName *lbl, ObjectCode *dependent, SymType
* Debugging operations.
*/
+typedef struct _SymX { SymbolName* name; uintptr_t loc; } SymX;
+
+static int comp (const void * elem1, const void * elem2)
+{
+ SymX f = *((SymX*)elem1);
+ SymX s = *((SymX*)elem2);
+ if (f.loc > s.loc) return 1;
+ if (f.loc < s.loc) return -1;
+ return 0;
+}
+
pathchar*
resolveSymbolAddr_PEi386 (pathchar* buffer, int size,
SymbolAddr* symbol, uintptr_t* top ){
@@ -2324,7 +2335,6 @@ resolveSymbolAddr_PEi386 (pathchar* buffer, int size,
else if (obj)
{
/* Try to calculate from information inside the rts. */
- typedef struct _SymX { SymbolName* name; uintptr_t loc; } SymX;
SymX* locs = stgCallocBytes (sizeof(SymX), obj->n_symbols,
"resolveSymbolAddr");
int blanks = 0;
@@ -2344,14 +2354,6 @@ resolveSymbolAddr_PEi386 (pathchar* buffer, int size,
locs[i] = sx;
}
}
- int comp (const void * elem1, const void * elem2)
- {
- SymX f = *((SymX*)elem1);
- SymX s = *((SymX*)elem2);
- if (f.loc > s.loc) return 1;
- if (f.loc < s.loc) return -1;
- return 0;
- }
qsort (locs, obj->n_symbols, sizeof (SymX), comp);
uintptr_t key = (uintptr_t)symbol;
SymX* res = NULL;
diff --git a/rts/sm/GC.h b/rts/sm/GC.h
index da90c61302..25de588534 100644
--- a/rts/sm/GC.h
+++ b/rts/sm/GC.h
@@ -13,10 +13,10 @@
#pragma once
-#include "BeginPrivate.h"
-
#include "HeapAlloc.h"
+#include "BeginPrivate.h"
+
void GarbageCollect (uint32_t collect_gen,
bool do_heap_census,
bool is_overflow_gc,
diff --git a/rts/sm/GCUtils.h b/rts/sm/GCUtils.h
index 798a795deb..dec81e1755 100644
--- a/rts/sm/GCUtils.h
+++ b/rts/sm/GCUtils.h
@@ -13,10 +13,10 @@
#pragma once
-#include "BeginPrivate.h"
-
#include "GCTDecl.h"
+#include "BeginPrivate.h"
+
bdescr* allocGroup_sync(uint32_t n);
bdescr* allocGroupOnNode_sync(uint32_t node, uint32_t n);
diff --git a/rts/sm/MarkStack.h b/rts/sm/MarkStack.h
index ca519f871f..8ea47a1865 100644
--- a/rts/sm/MarkStack.h
+++ b/rts/sm/MarkStack.h
@@ -13,9 +13,10 @@
#pragma once
-#include "BeginPrivate.h"
#include "GCUtils.h"
+#include "BeginPrivate.h"
+
INLINE_HEADER void
push_mark_stack(StgPtr p)
{
diff --git a/testsuite/config/ghc b/testsuite/config/ghc
index 632db8fc57..d33101fef8 100644
--- a/testsuite/config/ghc
+++ b/testsuite/config/ghc
@@ -58,6 +58,7 @@ if ghc_with_dynamic_rts:
if windows:
config.supports_dynamic_hs = False
+ config.stdcxx_impl = 'c++'
if (config.have_profiling and ghc_with_threaded_rts):
config.run_ways.append('profthreaded')
diff --git a/testsuite/driver/runtests.py b/testsuite/driver/runtests.py
index d2e25eaa19..0d458924d0 100644
--- a/testsuite/driver/runtests.py
+++ b/testsuite/driver/runtests.py
@@ -232,6 +232,8 @@ else:
print('WARNING: No UTF8 locale found.')
print('You may get some spurious test failures.')
+ghc_env['LIBCXX'] = config.stdcxx_impl
+
# https://stackoverflow.com/a/22254892/1308058
def supports_colors():
"""
diff --git a/testsuite/driver/testglobals.py b/testsuite/driver/testglobals.py
index 6847cece68..b85a14e17a 100644
--- a/testsuite/driver/testglobals.py
+++ b/testsuite/driver/testglobals.py
@@ -217,6 +217,8 @@ class TestConfig:
# The path specifies the file in which to write the dependencies
self.only_report_hadrian_deps = None # type: Optional[Path]
+ # C++ standard library implementation
+ self.stdcxx_impl = 'stdc++' # or c++ for LLVM/libc++ based platforms
def validate(self) -> None:
""" Check the TestConfig for self-consistency """
diff --git a/testsuite/driver/testlib.py b/testsuite/driver/testlib.py
index 7ee179b837..9c9a1760a2 100644
--- a/testsuite/driver/testlib.py
+++ b/testsuite/driver/testlib.py
@@ -1303,7 +1303,9 @@ def framework_fail(name: Optional[TestName], way: Optional[WayName], reason: str
if_verbose(1, '*** framework failure for %s %s ' % (full_name, reason))
name2 = name if name is not None else TestName('none')
way2 = way if way is not None else WayName('none')
- t.framework_failures.append(TestResult(directory, name2, reason, way2))
+ if way not in opts.fragile_ways:
+ # If the test is fragile then we rather report this as a fragile test failure
+ t.framework_failures.append(TestResult(directory, name2, reason, way2))
def framework_warn(name: TestName, way: WayName, reason: str) -> None:
opts = getTestOpts()
diff --git a/testsuite/mk/boilerplate.mk b/testsuite/mk/boilerplate.mk
index 03c281f76d..df1b835b0c 100644
--- a/testsuite/mk/boilerplate.mk
+++ b/testsuite/mk/boilerplate.mk
@@ -308,6 +308,8 @@ ifeq "$(HostOS)" "freebsd"
LIBCXX_PLATFORM = YES
else ifeq "$(HostOS)" "openbsd"
LIBCXX_PLATFORM = YES
+else ifeq "$(HostOS)" "mingw32"
+LIBCXX_PLATFORM = YES
else
LIBCXX_PLATFORM = NO
endif
diff --git a/testsuite/tests/codeGen/should_compile/all.T b/testsuite/tests/codeGen/should_compile/all.T
index 9985580e78..a18451b98e 100644
--- a/testsuite/tests/codeGen/should_compile/all.T
+++ b/testsuite/tests/codeGen/should_compile/all.T
@@ -104,3 +104,6 @@ test('T15570',
# warning: integer constant is so large that it is unsigned
test('T18614', normal, compile, [''])
+test('mk-big-obj',
+ [unless(opsys('mingw32'), skip), pre_cmd('$PYTHON mk-big-obj.py > mk-big-obj.c')],
+ multimod_compile, ['mk-big-obj.c', '-c -v0 -no-hs-main'])
diff --git a/testsuite/tests/codeGen/should_compile/mk-big-obj.py b/testsuite/tests/codeGen/should_compile/mk-big-obj.py
new file mode 100644
index 0000000000..c03fdbf380
--- /dev/null
+++ b/testsuite/tests/codeGen/should_compile/mk-big-obj.py
@@ -0,0 +1,9 @@
+#!/usr/bin/env python3
+
+for i in range(70000):
+ print(f'''
+ int __attribute__((section("text.test{i}")))
+ test{i}(void)
+ {{ return {i}; }}
+ ''')
+
diff --git a/testsuite/tests/codeGen/should_fail/all.T b/testsuite/tests/codeGen/should_fail/all.T
index e23fa03f82..3f2dacee46 100644
--- a/testsuite/tests/codeGen/should_fail/all.T
+++ b/testsuite/tests/codeGen/should_fail/all.T
@@ -7,7 +7,7 @@ test('T8131', [cmm_src, only_ways(llvm_ways)], compile_fail, ['-no-hs-main'])
def check_bounds_test(name):
""" A -fcheck-prim-bounds test that is expected to fail. """
test(name,
- [ignore_stderr, exit_code(3 if opsys('mingw32') else 134)],
+ [ignore_stderr, exit_code(127 if opsys('mingw32') else 134)],
compile_and_run, ['-fcheck-prim-bounds'])
check_bounds_test('CheckBoundsWriteArray')
diff --git a/testsuite/tests/ghci/linking/Makefile b/testsuite/tests/ghci/linking/Makefile
index 78d13c6e8a..7b77e91c09 100644
--- a/testsuite/tests/ghci/linking/Makefile
+++ b/testsuite/tests/ghci/linking/Makefile
@@ -24,12 +24,6 @@ else
DLL = lib$1.so
endif
-ifeq "$(LIBCXX_PLATFORM)" "YES"
-LIBCXX=c++
-else
-LIBCXX=stdc++
-endif
-
.PHONY: ghcilink002
ghcilink002 :
$(RM) -rf dir002
@@ -118,11 +112,7 @@ ghcilink006 :
echo "version: 1.0" >>$(PKG006)
echo "id: test-XXX" >>$(PKG006)
echo "key: test-XXX" >>$(PKG006)
-ifeq "$(WINDOWS)" "YES"
- echo "extra-libraries: stdc++-6" >>$(PKG006)
-else
echo "extra-libraries: $(LIBCXX)" >>$(PKG006)
-endif
'$(GHC_PKG)' init $(LOCAL_PKGCONF006)
'$(GHC_PKG)' --no-user-package-db -f $(LOCAL_PKGCONF006) register $(PKG006) -v0
#
diff --git a/testsuite/tests/ghci/linking/all.T b/testsuite/tests/ghci/linking/all.T
index 40d79cbc09..b4564f0237 100644
--- a/testsuite/tests/ghci/linking/all.T
+++ b/testsuite/tests/ghci/linking/all.T
@@ -12,8 +12,6 @@ test('ghcilink002', [extra_files(['TestLink.hs', 'f.c']),
test('ghcilink003',
[ unless(doing_ghci, skip),
- # libstdc++ is GCC-specific on FreeBSD. FreeBSD has libc++ though.
- when(opsys('freebsd'), fragile(17739)),
# from Big Sur onwards, we can't dlopen libstdc++.dylib
# anymore. Will produce:
# dlopen(libstdc++.dylib, 5): image not found
@@ -36,8 +34,6 @@ test('ghcilink005',
test('ghcilink006',
[ unless(doing_ghci, skip),
- # libstdc++ is GCC-specific on FreeBSD. FreeBSD has libc++ though.
- when(opsys('freebsd'), fragile(17739)),
# from Big Sur onwards, we can't dlopen libstdc++.dylib
# anymore. Will produce:
# dlopen(libstdc++.dylib, 5): image not found
diff --git a/testsuite/tests/ghci/linking/dyn/A.def b/testsuite/tests/ghci/linking/dyn/A.def
new file mode 100644
index 0000000000..5198ddd028
--- /dev/null
+++ b/testsuite/tests/ghci/linking/dyn/A.def
@@ -0,0 +1,3 @@
+LIBRARY libA
+EXPORTS
+foo \ No newline at end of file
diff --git a/testsuite/tests/ghci/linking/dyn/B.def b/testsuite/tests/ghci/linking/dyn/B.def
new file mode 100644
index 0000000000..bdfc2cbfbb
--- /dev/null
+++ b/testsuite/tests/ghci/linking/dyn/B.def
@@ -0,0 +1,3 @@
+LIBRARY libB
+EXPORTS
+bar
diff --git a/testsuite/tests/ghci/linking/dyn/Makefile b/testsuite/tests/ghci/linking/dyn/Makefile
index 7f14f7d08a..da8ee20790 100644
--- a/testsuite/tests/ghci/linking/dyn/Makefile
+++ b/testsuite/tests/ghci/linking/dyn/Makefile
@@ -2,6 +2,16 @@ TOP=../../../..
include $(TOP)/mk/boilerplate.mk
include $(TOP)/mk/test.mk
+# On Windows we must provide module definitions (.def files)
+# for shared libraries, lest the linker exports *everything*, including RTS
+# symbols. This would mean that we couldn't link against multiple dynamic
+# objects simultaneously as the RTS symbols would be defined multiple times.
+ifeq "$(WINDOWS)" "YES"
+DEF = "$1.def"
+else
+DEF =
+endif
+
ifeq "$(WINDOWS)" "YES"
DLL = lib$1.dll
else ifeq "$(DARWIN)" "YES"
@@ -62,16 +72,16 @@ compile_libT10458:
compile_libAB_dep:
rm -rf bin_dep
mkdir bin_dep
- '$(TEST_HC)' $(MY_TEST_HC_OPTS) -odir "bin_dep" -shared A.c -o "bin_dep/$(call DLL,A)"
- '$(TEST_HC)' $(MY_TEST_HC_OPTS) -odir "bin_dep" -shared B.c -o "bin_dep/$(call DLL,B)" -lA -L"./bin_dep"
+ '$(TEST_HC)' $(MY_TEST_HC_OPTS) -odir "bin_dep" -shared A.c -o "bin_dep/$(call DLL,A)" $(call DEF,A)
+ '$(TEST_HC)' $(MY_TEST_HC_OPTS) -odir "bin_dep" -shared B.c -o "bin_dep/$(call DLL,B)" $(call DEF,B) -lA -L"./bin_dep"
rm -f bin_dep/*.a
.PHONY: compile_libAB_dyn
compile_libAB_dyn:
rm -rf bin_dyn
mkdir bin_dyn
- '$(TEST_HC)' $(MY_TEST_HC_OPTS) -odir "bin_dyn" -shared A.c -o "bin_dyn/$(call DLL,A)"
- '$(TEST_HC)' $(MY_TEST_HC_OPTS) -odir "bin_dyn" -shared B.c -o "bin_dyn/$(call DLL,B)" -lA -L"./bin_dyn"
+ '$(TEST_HC)' $(MY_TEST_HC_OPTS) -odir "bin_dyn" -shared A.c -o "bin_dyn/$(call DLL,A)" $(call DEF,A)
+ '$(TEST_HC)' $(MY_TEST_HC_OPTS) -odir "bin_dyn" -shared B.c -o "bin_dyn/$(call DLL,B)" $(call DEF,B) -lA -L"./bin_dyn"
rm -f bin_dyn/*.a
'$(TEST_HC)' $(TEST_HC_OPTS) -ignore-dot-ghci -v0 -o "bin_dyn/$(call EXE,T10955dyn)" -L./bin_dyn -lB -lA T10955dyn.hs -v0
LD_LIBRARY_PATH=./bin_dyn ./bin_dyn/$(call EXE,T10955dyn)
@@ -99,6 +109,7 @@ T1407:
.PHONY: T3242
echo ":q" | '$(TEST_HC)' $(TEST_HC_OPTS_INTERACTIVE) -lm
+# We use gdi32 as library with an import library.
.PHONY: T13606
T13606:
- echo ":q" | '$(TEST_HC)' $(TEST_HC_OPTS_INTERACTIVE) -lgcc_s
+ echo ":q" | '$(TEST_HC)' $(TEST_HC_OPTS_INTERACTIVE) -lgdi32.a
diff --git a/testsuite/tests/ghci/linking/dyn/all.T b/testsuite/tests/ghci/linking/dyn/all.T
index 0092f7febe..9b05ed5fc3 100644
--- a/testsuite/tests/ghci/linking/dyn/all.T
+++ b/testsuite/tests/ghci/linking/dyn/all.T
@@ -16,13 +16,15 @@ test('T3242',
makefile_test, ['T3242'])
test('T10955',
- [extra_files(['A.c', 'B.c']),
- unless(doing_ghci, skip), unless(opsys('mingw32'), skip),
+ [extra_files(['A.c', 'B.c', 'A.def', 'B.def']),
+ unless(doing_ghci, skip),
+ unless(opsys('mingw32'), skip),
pre_cmd('$MAKE -s --no-print-directory compile_libAB_dep'),
extra_hc_opts('-L. -L./bin_dep')],
ghci_script, ['T10955.script'])
-test('T10955dyn', [extra_files(['A.c', 'B.c'])], makefile_test, ['compile_libAB_dyn'])
+test('T10955dyn', [extra_files(['A.c', 'B.c', 'A.def', 'B.def'])],
+ makefile_test, ['compile_libAB_dyn'])
test('T10458',
[extra_files(['A.c']),
diff --git a/testsuite/tests/linters/Makefile b/testsuite/tests/linters/Makefile
index 54ef4db132..2b4c2ad2c3 100644
--- a/testsuite/tests/linters/Makefile
+++ b/testsuite/tests/linters/Makefile
@@ -20,6 +20,9 @@ version-number:
cpp:
(cd $(TOP)/tests/linters/ && python3 regex-linters/check-cpp.py tracked)
+rts-includes:
+ (cd $(TOP)/tests/linters/ && python3 regex-linters/check-rts-includes.py tracked)
+
changelogs:
regex-linters/check-changelogs.sh $(TOP)/..
diff --git a/testsuite/tests/linters/all.T b/testsuite/tests/linters/all.T
index 16700869a4..0e06df6d50 100644
--- a/testsuite/tests/linters/all.T
+++ b/testsuite/tests/linters/all.T
@@ -23,7 +23,11 @@ test('changelogs', [ no_deps if has_ls_files() else skip
test('cpp', [ no_deps if has_ls_files() else skip
, extra_files(["regex-linters"]) ]
- , makefile_test, ['cpp'])
+ , makefile_test, ['cpp'])
+
+test('rts-includes', [ no_deps if has_ls_files() else skip
+ , extra_files(["regex-linters"]) ]
+ , makefile_test, ['rts-includes'])
test('version-number', [ no_deps if has_ls_files() else skip
, extra_files(["regex-linters"]) ]
diff --git a/testsuite/tests/linters/regex-linters/check-rts-includes.py b/testsuite/tests/linters/regex-linters/check-rts-includes.py
new file mode 100755
index 0000000000..14f22995b6
--- /dev/null
+++ b/testsuite/tests/linters/regex-linters/check-rts-includes.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env python3
+
+# A linter to warn for ASSERT macros which are separated from their argument
+# list by a space, which Clang's CPP barfs on
+
+from pathlib import Path
+from linter import run_linters, Linter, Warning
+
+from typing import List, Tuple
+import re
+
+INCLUDE_RE = re.compile('# *include ([<"][^">]+[>"])')
+
+def get_includes(file: Path) -> List[Tuple[int, str]]:
+ txt = file.read_text()
+ return [ (line_no+1, m.group(1) )
+ for (line_no, line) in enumerate(txt.split('\n'))
+ for m in [INCLUDE_RE.match(line)]
+ if m is not None
+ if m.group(1) != "rts/PosixSource.h"]
+
+def in_rts_dir(path: Path) -> bool:
+ return len(path.parts) > 0 and path.parts[0] == 'rts'
+
+class RtsHIncludeOrderLinter(Linter):
+ """
+ Verify that "PosixSource.h" is always the first #include in source files to
+ ensure __USE_MINGW_ANSI_STDIO is defined before system headers are
+ #include'd.
+ """
+ def __init__(self):
+ Linter.__init__(self)
+ self.add_path_filter(in_rts_dir)
+ self.add_path_filter(lambda path: path.suffix == '.c')
+
+ def lint(self, path: Path):
+ # We do allow a few small headers to precede Rts.h
+ ALLOWED_HEADERS = {
+ '"ghcconfig.h"',
+ '"ghcplatform.h"',
+ }
+
+ includes = get_includes(path)
+ headers = [x[1] for x in includes]
+ lines = path.read_text().split('\n')
+
+ if '"PosixSource.h"' in headers:
+ for line_no, header in includes:
+ if header == '"PosixSource.h"':
+ break
+ elif header in ALLOWED_HEADERS:
+ continue
+
+ self.add_warning(Warning(
+ path=path,
+ line_no=line_no,
+ line_content=lines[line_no-1],
+ message="PosixSource.h must be first header included in each file"))
+
+class PrivateIncludeLinter(Linter):
+ """
+ Verify that system headers are not #include'd in <BeginPrivate.h> blocks as this
+ can result in very hard-to-diagnose linking errors due to hidden library functions.
+ """
+ def __init__(self):
+ Linter.__init__(self)
+ self.add_path_filter(in_rts_dir)
+ self.add_path_filter(lambda path: path.suffix == '.h')
+
+ def lint(self, path: Path):
+ private = False
+ lines = path.read_text().split('\n')
+ for line_no, include in get_includes(path):
+ if include == '"BeginPrivate.h"':
+ private = True
+ elif include == '"EndPrivate.h"':
+ private = False
+ elif private:
+ self.add_warning(Warning(
+ path=path,
+ line_no=line_no,
+ line_content=lines[line_no-1],
+ message='System header %s found inside of <BeginPrivate.h> block' % include))
+
+linters = [
+ RtsHIncludeOrderLinter(),
+ PrivateIncludeLinter(),
+]
+
+if __name__ == '__main__':
+ run_linters(linters)
diff --git a/testsuite/tests/numeric/should_run/all.T b/testsuite/tests/numeric/should_run/all.T
index b0580c7e2c..68888545f8 100644
--- a/testsuite/tests/numeric/should_run/all.T
+++ b/testsuite/tests/numeric/should_run/all.T
@@ -41,8 +41,7 @@ test('arith018', normal, compile_and_run, [''])
test('arith019', normal, compile_and_run, [''])
test('expfloat', normal, compile_and_run, [''])
-test('FloatFnInverses', [when(opsys('mingw32'), expect_broken(15670))],
- compile_and_run, [''])
+test('FloatFnInverses', normal, compile_and_run, [''])
test('T1603', skip, compile_and_run, [''])
test('T3676', expect_broken(3676), compile_and_run, [''])
diff --git a/testsuite/tests/plugins/all.T b/testsuite/tests/plugins/all.T
index 4e8663c73b..dca05d885c 100644
--- a/testsuite/tests/plugins/all.T
+++ b/testsuite/tests/plugins/all.T
@@ -99,7 +99,7 @@ test('plugins15',
test('T10420',
[extra_files(['rule-defining-plugin/']),
-
+ when(opsys('mingw32'), expect_broken(21322)),
pre_cmd('$MAKE -s --no-print-directory -C rule-defining-plugin package.T10420 TOP={top}')],
makefile_test, [])
@@ -258,11 +258,13 @@ test('T20218b',
test('test-defaulting-plugin',
[extra_files(['defaulting-plugin/']),
+ when(opsys('mingw32'), fragile(21293)),
pre_cmd('$MAKE -s --no-print-directory -C defaulting-plugin package.test-defaulting-plugin TOP={top}')],
makefile_test, [])
test('test-defaulting-plugin-fail',
[extra_files(['defaulting-plugin/']),
+ when(opsys('mingw32'), fragile(21293)),
pre_cmd('$MAKE -s --no-print-directory -C defaulting-plugin package.test-defaulting-plugin-fail TOP={top}')],
makefile_test, [])
diff --git a/testsuite/tests/rts/T10672/Makefile b/testsuite/tests/rts/T10672/Makefile
index 5fc458857e..bcc9a5c22b 100644
--- a/testsuite/tests/rts/T10672/Makefile
+++ b/testsuite/tests/rts/T10672/Makefile
@@ -3,9 +3,9 @@ include $(TOP)/mk/boilerplate.mk
include $(TOP)/mk/test.mk
T10672_x64:
- '$(TEST_HC)' $(TEST_HC_OPTS) -v0 -rtsopts=none -fforce-recomp -lgcc_s_seh-1 -lstdc++-6 \
+ '$(TEST_HC)' $(TEST_HC_OPTS) -v0 -rtsopts=none -fforce-recomp -lgcc_s_seh-1 -l${LIBCXX} \
Main.hs Printf.hs cxxy.cpp
T10672_x86:
- '$(TEST_HC)' $(TEST_HC_OPTS) -v0 -rtsopts=none -fforce-recomp -lgcc_s_dw2-1 -lstdc++-6 \
+ '$(TEST_HC)' $(TEST_HC_OPTS) -v0 -rtsopts=none -fforce-recomp -lgcc_s_dw2-1 -${LIBCXX} \
Main.hs Printf.hs cxxy.cpp
diff --git a/testsuite/tests/rts/T16514_c.c b/testsuite/tests/rts/T16514_c.c
new file mode 100644
index 0000000000..9acb7d7d1f
--- /dev/null
+++ b/testsuite/tests/rts/T16514_c.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+
+void fn_hs();
+void fn() {
+ fn_hs();
+}
+
+void check(double sqrt2, double sqrt3, double sqrt5,
+ double sqrt8, double sqrt13, double sqrt21)
+{
+ printf("%f %f %f %f %f %f\n", sqrt2, sqrt3, sqrt5, sqrt8, sqrt13, sqrt21);
+ if (sqrt2 != 1.41421 || sqrt3 != 1.73205 || sqrt5 != 2.23607 ||
+ sqrt8 != 2.82843 || sqrt13 != 3.60555 || sqrt21 != 4.58258) {
+ fprintf(stderr, "xmm registers have been scratched\n");
+ }
+}
+
+int test() {
+ double sqrt2 = 1.41421;
+ double sqrt3 = 1.73205;
+ double sqrt5 = 2.23607;
+ double sqrt8 = 2.82843;
+ double sqrt13 = 3.60555;
+ double sqrt21 = 4.58258;
+ check(sqrt2, sqrt3, sqrt5, sqrt8, sqrt13, sqrt21);
+ fn();
+ check(sqrt2, sqrt3, sqrt5, sqrt8, sqrt13, sqrt21);
+ fn();
+ check(sqrt2, sqrt3, sqrt5, sqrt8, sqrt13, sqrt21);
+ return 0;
+} \ No newline at end of file
diff --git a/testsuite/tests/rts/T16514_c.cpp b/testsuite/tests/rts/T16514_c.cpp
deleted file mode 100644
index 1474741ec0..0000000000
--- a/testsuite/tests/rts/T16514_c.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#include <iostream>
-#include <stdexcept>
-
-extern "C" {
-
-void fn_hs();
-void fn() {
- fn_hs();
-}
-
-void check(double sqrt2, double sqrt3, double sqrt5,
- double sqrt8, double sqrt13, double sqrt21) {
- std::cout << std::fixed << sqrt2 << " " << sqrt3 << " " << sqrt5 << " "
- << sqrt8 << " " << sqrt13 << " " << sqrt21 << std::endl;
- if (sqrt2 != 1.41421 || sqrt3 != 1.73205 || sqrt5 != 2.23607 ||
- sqrt8 != 2.82843 || sqrt13 != 3.60555 || sqrt21 != 4.58258) {
- throw std::runtime_error("xmm registers have been scratched");
- }
-}
-
-int test() {
- try {
- double sqrt2 = 1.41421;
- double sqrt3 = 1.73205;
- double sqrt5 = 2.23607;
- double sqrt8 = 2.82843;
- double sqrt13 = 3.60555;
- double sqrt21 = 4.58258;
- check(sqrt2, sqrt3, sqrt5, sqrt8, sqrt13, sqrt21);
- fn();
- check(sqrt2, sqrt3, sqrt5, sqrt8, sqrt13, sqrt21);
- try {
- fn();
- } catch (const std::exception &) {
- }
- check(sqrt2, sqrt3, sqrt5, sqrt8, sqrt13, sqrt21);
- } catch (const std::exception &e) {
- std::cerr << e.what() << std::endl;
- return 1;
- }
- return 0;
-}
-
-} // extern "C"
-
diff --git a/testsuite/tests/rts/all.T b/testsuite/tests/rts/all.T
index c13f1aa0ea..75dcf5ac58 100644
--- a/testsuite/tests/rts/all.T
+++ b/testsuite/tests/rts/all.T
@@ -387,7 +387,7 @@ test('T10904', [ omit_ways(['ghci']), extra_run_opts('20000') ],
test('T10728', [extra_run_opts('+RTS -maxN3 -RTS'), only_ways(['threaded2'])],
compile_and_run, [''])
-test('T9405', [when(msys(), expect_broken(12714))], makefile_test, ['T9405'])
+test('T9405', [when(opsys('mingw32'), expect_broken(21361))], makefile_test, ['T9405'])
test('T11788', when(ghc_dynamic(), skip),
makefile_test, ['T11788'])
@@ -474,9 +474,10 @@ test('keep-cafs',
# Test proper functioning of C++ exceptions within a C++ program.
# On darwin, this requires -fcompact-unwind.
# When -fcompact-unwind becomes default, generalize test to all platforms.
-test('T11829', unless(opsys('darwin'), skip), compile_and_run, ['T11829_c.cpp -lstdc++ -fcompact-unwind'])
+test('T11829', unless(opsys('darwin'), skip), compile_and_run,
+ ['T11829_c.cpp -l{} -fcompact-unwind'.format(config.stdcxx_impl)])
-test('T16514', unless(opsys('mingw32'), skip), compile_and_run, ['T16514_c.cpp -lstdc++'])
+test('T16514', normal, compile_and_run, ['T16514_c.c'])
test('test-zeroongc', extra_run_opts('-DZ'), compile_and_run, ['-debug'])
test('T13676',
diff --git a/testsuite/tests/rts/linker/T5435_v_asm_a.stdout-mingw32 b/testsuite/tests/rts/linker/T5435_v_asm_a.stdout-mingw32
index 293bd12fb0..f5f0ff1284 100644
--- a/testsuite/tests/rts/linker/T5435_v_asm_a.stdout-mingw32
+++ b/testsuite/tests/rts/linker/T5435_v_asm_a.stdout-mingw32
@@ -1,3 +1,3 @@
+success
ctors1
ctors2
-success
diff --git a/testsuite/tests/rts/linker/T5435_v_gcc.stdout-mingw32 b/testsuite/tests/rts/linker/T5435_v_gcc.stdout-mingw32
new file mode 100644
index 0000000000..ebe1f4f250
--- /dev/null
+++ b/testsuite/tests/rts/linker/T5435_v_gcc.stdout-mingw32
@@ -0,0 +1,2 @@
+success
+initializer run
diff --git a/testsuite/tests/rts/linker/all.T b/testsuite/tests/rts/linker/all.T
index e42db98922..0cb93370aa 100644
--- a/testsuite/tests/rts/linker/all.T
+++ b/testsuite/tests/rts/linker/all.T
@@ -82,6 +82,7 @@ test('T5435_dyn_gcc', extra_files(['T5435.hs', 'T5435_gcc.c']) , makefile_test,
######################################
test('linker_unload',
[extra_files(['LinkerUnload.hs', 'Test.hs']),
+ when(opsys('mingw32'), expect_broken(21354)),
req_rts_linker],
makefile_test, ['linker_unload'])
@@ -119,8 +120,9 @@ test('T7072',
test('T20918',
- [extra_files(['T20918_v.cc']),
- unless(opsys('mingw32'), skip),
- req_rts_linker],
- makefile_test, ['T20918'])
+ [extra_files(['T20918_v.cc']),
+ unless(opsys('mingw32'), skip),
+ when(opsys('mingw32'), expect_broken(2)),
+ req_rts_linker],
+ makefile_test, ['T20918'])
diff --git a/testsuite/tests/rts/linker/unload_multiple_objs/all.T b/testsuite/tests/rts/linker/unload_multiple_objs/all.T
index 52f35b4e26..85548af491 100644
--- a/testsuite/tests/rts/linker/unload_multiple_objs/all.T
+++ b/testsuite/tests/rts/linker/unload_multiple_objs/all.T
@@ -1,4 +1,5 @@
test('linker_unload_multiple_objs',
[extra_files(['../LinkerUnload.hs', 'A.hs', 'B.hs', 'C.hs', 'D.hs',]),
+ when(opsys('mingw32'), expect_broken(21354)),
req_rts_linker],
run_command, ['$MAKE -s --no-print-directory linker_unload_multiple_objs'])
diff --git a/testsuite/tests/th/T13366C.hs b/testsuite/tests/th/T13366C.hs
new file mode 100644
index 0000000000..246687dcf0
--- /dev/null
+++ b/testsuite/tests/th/T13366C.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# OPTIONS_GHC -optc-DA_MACRO=1 -optcxx-DA_MACRO=1 #-}
+
+import Language.Haskell.TH.Syntax
+import System.IO (hFlush, stdout)
+
+foreign import ccall fc :: Int -> IO Int
+
+do addForeignSource LangC $ unlines
+ [ "#include <stdio.h>"
+ , "int fc(int x) {"
+ , " printf(\"calling f(%d)\\n\",x);"
+ , " fflush(stdout);"
+ , " return A_MACRO + x;"
+ , "}"
+ ]
+ return []
+
+main :: IO ()
+main = do
+ fc 2 >>= print
+ hFlush stdout
diff --git a/testsuite/tests/th/T13366C.stdout b/testsuite/tests/th/T13366C.stdout
new file mode 100644
index 0000000000..2ab79e85b8
--- /dev/null
+++ b/testsuite/tests/th/T13366C.stdout
@@ -0,0 +1,2 @@
+calling f(2)
+3
diff --git a/testsuite/tests/th/T13366.hs b/testsuite/tests/th/T13366Cxx.hs
index 7d998f2ae8..37ab25a4d1 100644
--- a/testsuite/tests/th/T13366.hs
+++ b/testsuite/tests/th/T13366Cxx.hs
@@ -5,18 +5,6 @@
import Language.Haskell.TH.Syntax
import System.IO (hFlush, stdout)
-foreign import ccall fc :: Int -> IO Int
-
-do addForeignSource LangC $ unlines
- [ "#include <stdio.h>"
- , "int fc(int x) {"
- , " printf(\"calling f(%d)\\n\",x);"
- , " fflush(stdout);"
- , " return A_MACRO + x;"
- , "}"
- ]
- return []
-
foreign import ccall fcxx :: Int -> IO Int
do addForeignSource LangCxx $ unlines
@@ -33,7 +21,5 @@ do addForeignSource LangCxx $ unlines
main :: IO ()
main = do
- fc 2 >>= print
- hFlush stdout
fcxx 5 >>= print
hFlush stdout
diff --git a/testsuite/tests/th/T13366.stdout b/testsuite/tests/th/T13366Cxx.stdout
index 16cfeeb9fa..bdf7a41a33 100644
--- a/testsuite/tests/th/T13366.stdout
+++ b/testsuite/tests/th/T13366Cxx.stdout
@@ -1,4 +1,2 @@
-calling f(2)
-3
calling fcxx(5)
6
diff --git a/testsuite/tests/th/all.T b/testsuite/tests/th/all.T
index d04bb08b29..2a003b8141 100644
--- a/testsuite/tests/th/all.T
+++ b/testsuite/tests/th/all.T
@@ -52,8 +52,7 @@ test('TH_NestedSplices', [], multimod_compile,
# normal way first, which is why the work is done by a Makefile rule.
test('TH_spliceE5_prof',
[req_profiling, only_ways(['normal']),
- when(ghc_dynamic(), expect_broken(11495)),
- when(opsys('mingw32'), expect_broken(18271))],
+ when(ghc_dynamic(), expect_broken(11495))],
makefile_test, ['TH_spliceE5_prof'])
test('TH_spliceE5_prof_ext', [req_profiling, req_rts_linker, only_ways(['normal'])],
@@ -395,14 +394,16 @@ test('T13018', normal, compile, ['-v0'])
test('T13123', normal, compile, ['-v0'])
test('T13098', normal, compile, ['-v0'])
test('T11046', normal, multimod_compile, ['T11046','-v0'])
-test('T13366',
+test('T13366C',
+ [expect_broken_for(13366, ['ghci'])],
+ compile_and_run,
+ ['-v0'])
+test('T13366Cxx',
[expect_broken_for(13366, ['ghci']),
- # libstdc++ is GCC-specific on FreeBSD, the test will
- # fail with clang, and pass with GCC.
- when(opsys('freebsd'), fragile(17739)),
- when(opsys('darwin'), expect_broken(16083))],
+ when(opsys('darwin'), expect_broken(16083))
+ ],
compile_and_run,
- ['-lstdc++ -v0'] if not opsys('openbsd') else ['-lc++ -lc++abi -v0'])
+ ['-l{} -v0'.format(config.stdcxx_impl)])
test('T13473', normal, multimod_compile_and_run,
['T13473.hs', '-v0 ' + config.ghc_th_way_flags])
test('T13587', expect_broken(13587), compile_and_run, ['-v0'])