summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Palka <patrick@parcs.ath.cx>2013-09-04 12:10:27 -0400
committerPatrick Palka <patrick@parcs.ath.cx>2013-09-04 12:10:27 -0400
commitd127a697192851ea6bf308525a8a8895da71b639 (patch)
tree895f8976273df8e96b7c52382529ca0dfee61a5a
parenta2e338f3ae5a101d333fb260ed58ec238106e88e (diff)
parent32ade417f7e82b6fbcb6f1c93871ba3141a8f5c8 (diff)
downloadhaskell-d127a697192851ea6bf308525a8a8895da71b639.tar.gz
Merge remote-tracking branch 'origin/master' into ghc-parmake-gsoc
-rw-r--r--aclocal.m414
-rwxr-xr-xboot2
-rw-r--r--compiler/basicTypes/MkId.lhs33
-rw-r--r--compiler/cmm/CmmNode.hs81
-rw-r--r--compiler/cmm/CmmSink.hs120
-rw-r--r--compiler/codeGen/StgCmm.hs2
-rw-r--r--compiler/codeGen/StgCmmBind.hs3
-rw-r--r--compiler/codeGen/StgCmmCon.hs2
-rw-r--r--compiler/codeGen/StgCmmExpr.hs2
-rw-r--r--compiler/codeGen/StgCmmForeign.hs2
-rw-r--r--compiler/codeGen/StgCmmHeap.hs2
-rw-r--r--compiler/codeGen/StgCmmLayout.hs2
-rw-r--r--compiler/codeGen/StgCmmPrim.hs2
-rw-r--r--compiler/coreSyn/CoreLint.lhs23
-rw-r--r--compiler/coreSyn/CorePrep.lhs2
-rw-r--r--compiler/coreSyn/CoreSyn.lhs31
-rw-r--r--compiler/coreSyn/CoreUnfold.lhs2
-rw-r--r--compiler/coreSyn/PprCore.lhs1
-rw-r--r--compiler/deSugar/Desugar.lhs29
-rw-r--r--compiler/iface/IfaceSyn.lhs15
-rw-r--r--compiler/iface/MkIface.lhs1
-rw-r--r--compiler/iface/TcIface.lhs46
-rw-r--r--compiler/main/HscMain.hs48
-rw-r--r--compiler/main/TidyPgm.lhs2
-rw-r--r--compiler/prelude/primops.txt.pp23
-rw-r--r--compiler/rename/RnExpr.lhs6
-rw-r--r--compiler/rename/RnPat.lhs5
-rw-r--r--compiler/rename/RnTypes.lhs4
-rw-r--r--compiler/simplCore/CoreMonad.lhs84
-rw-r--r--compiler/simplCore/OccurAnal.lhs70
-rw-r--r--compiler/simplCore/SimplCore.lhs15
-rw-r--r--compiler/specialise/Specialise.lhs6
-rw-r--r--compiler/typecheck/TcBinds.lhs5
-rw-r--r--compiler/typecheck/TcInstDcls.lhs4
-rw-r--r--compiler/typecheck/TcMType.lhs6
-rw-r--r--compiler/typecheck/TcSMonad.lhs1
-rw-r--r--compiler/typecheck/TcTyClsDecls.lhs16
-rw-r--r--compiler/typecheck/TcTyDecls.lhs22
-rw-r--r--compiler/typecheck/TcType.lhs2
-rw-r--r--compiler/typecheck/TcValidity.lhs23
-rw-r--r--compiler/types/Coercion.lhs5
-rw-r--r--compiler/types/Type.lhs10
-rw-r--r--compiler/types/TypeRep.lhs18
-rw-r--r--docs/users_guide/7.8.1-notes.xml19
-rw-r--r--docs/users_guide/flags.xml233
-rw-r--r--docs/users_guide/glasgow_exts.xml238
-rw-r--r--driver/ghc-usage.txt3
-rw-r--r--includes/rts/Linker.h2
-rw-r--r--includes/stg/MiscClosures.h3
-rw-r--r--includes/stg/SMP.h27
m---------libraries/haskeline0
m---------libraries/time0
-rw-r--r--mk/config.mk.in1
-rw-r--r--mk/install.mk.in2
-rw-r--r--mk/validate-settings.mk9
-rw-r--r--packages94
-rw-r--r--rts/Capability.c83
-rw-r--r--rts/Capability.h8
-rw-r--r--rts/CheckUnload.c13
-rw-r--r--rts/Linker.c5
-rw-r--r--rts/PrimOps.cmm60
-rw-r--r--rts/Profiling.c2
-rw-r--r--rts/Proftimer.c2
-rw-r--r--rts/RetainerProfile.c2
-rw-r--r--rts/Schedule.c87
-rw-r--r--rts/Stats.c34
-rw-r--r--rts/Task.c28
-rw-r--r--rts/Task.h5
-rw-r--r--rts/Threads.c2
-rw-r--r--rts/Timer.c2
-rw-r--r--rts/sm/Compact.c2
-rw-r--r--rts/sm/GC.c52
-rw-r--r--rts/sm/Sanity.c14
-rw-r--r--rts/sm/Storage.c10
-rw-r--r--rules/shell-wrapper.mk2
-rwxr-xr-xsync-all3
-rw-r--r--utils/hp2ps/Axes.c12
-rwxr-xr-xvalidate50
78 files changed, 1120 insertions, 781 deletions
diff --git a/aclocal.m4 b/aclocal.m4
index 7e555446a1..151cc2ea2c 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1184,6 +1184,7 @@ AC_SUBST(GccLT46)
dnl Check to see if the C compiler is clang or llvm-gcc
dnl
+GccIsClang=NO
AC_DEFUN([FP_CC_LLVM_BACKEND],
[AC_REQUIRE([AC_PROG_CC])
AC_MSG_CHECKING([whether C compiler is clang])
@@ -1191,6 +1192,7 @@ $CC -x c /dev/null -dM -E > conftest.txt 2>&1
if grep "__clang__" conftest.txt >/dev/null 2>&1; then
AC_SUBST([CC_CLANG_BACKEND], [1])
AC_SUBST([CC_LLVM_BACKEND], [1])
+ GccIsClang=YES
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
@@ -1205,6 +1207,7 @@ else
AC_MSG_RESULT([no])
fi
fi
+AC_SUBST(GccIsClang)
rm -f conftest.txt
])
@@ -2049,7 +2052,16 @@ AC_DEFUN([FIND_GCC],[
then
$1="$CC"
else
- FP_ARG_WITH_PATH_GNU_PROG([$1], [$2], [$3])
+ FP_ARG_WITH_PATH_GNU_PROG_OPTIONAL([$1], [$2], [$3])
+ # From Xcode 5 on, OS X command line tools do not include gcc anymore. Use clang.
+ if test -z "$$1"
+ then
+ FP_ARG_WITH_PATH_GNU_PROG_OPTIONAL([$1], [clang], [clang])
+ fi
+ if test -z "$$1"
+ then
+ AC_MSG_ERROR([cannot find $3 nor clang in your PATH])
+ fi
fi
AC_SUBST($1)
])
diff --git a/boot b/boot
index 3c17e4c94f..13747421ed 100755
--- a/boot
+++ b/boot
@@ -58,7 +58,7 @@ sub sanity_check_tree {
if (/^#/) {
# Comment; do nothing
}
- elsif (/^([a-zA-Z0-9\/.-]+) +([^ ]+) +[^ ]+$/) {
+ elsif (/^([a-zA-Z0-9\/.-]+) +([^ ]+) +[^ ]+ +[^ ]+$/) {
$dir = $1;
$tag = $2;
diff --git a/compiler/basicTypes/MkId.lhs b/compiler/basicTypes/MkId.lhs
index 14e29c1d99..21553ab4f9 100644
--- a/compiler/basicTypes/MkId.lhs
+++ b/compiler/basicTypes/MkId.lhs
@@ -695,8 +695,7 @@ dataConArgUnpack arg_ty
-- An interface file specified Unpacked, but we couldn't unpack it
isUnpackableType :: FamInstEnvs -> Type -> Bool
--- True if we can unpack the UNPACK fields of the constructor
--- without involving the NameSet tycons
+-- True if we can unpack the UNPACK the argument type
-- See Note [Recursive unboxing]
-- We look "deeply" inside rather than relying on the DataCons
-- we encounter on the way, because otherwise we might well
@@ -730,9 +729,11 @@ isUnpackableType fam_envs ty
-- NB: dataConStrictMarks gives the *user* request;
-- We'd get a black hole if we used dataConRepBangs
- attempt_unpack (HsUnpack {}) = True
- attempt_unpack (HsUserBang (Just unpk) _) = unpk
- attempt_unpack _ = False
+ attempt_unpack (HsUnpack {}) = True
+ attempt_unpack (HsUserBang (Just unpk) bang) = bang && unpk
+ attempt_unpack (HsUserBang Nothing bang) = bang -- Be conservative
+ attempt_unpack HsStrict = False
+ attempt_unpack HsNoBang = False
\end{code}
Note [Unpack one-wide fields]
@@ -761,14 +762,26 @@ Here we can represent T with an Int#.
Note [Recursive unboxing]
~~~~~~~~~~~~~~~~~~~~~~~~~
-Be careful not to try to unbox this!
- data T = MkT {-# UNPACK #-} !T Int
-Reason: consider
+Consider
data R = MkR {-# UNPACK #-} !S Int
data S = MkS {-# UNPACK #-} !Int
The representation arguments of MkR are the *representation* arguments
-of S (plus Int); the rep args of MkS are Int#. This is obviously no
-good for T, because then we'd get an infinite number of arguments.
+of S (plus Int); the rep args of MkS are Int#. This is all fine.
+
+But be careful not to try to unbox this!
+ data T = MkT {-# UNPACK #-} !T Int
+Because then we'd get an infinite number of arguments.
+
+Here is a more complicated case:
+ data S = MkS {-# UNPACK #-} !T Int
+ data T = MkT {-# UNPACK #-} !S Int
+Each of S and T must decide independendently whether to unpack
+and they had better not both say yes. So they must both say no.
+
+Also behave conservatively when there is no UNPACK pragma
+ data T = MkS !T Int
+with -funbox-strict-fields or -funbox-small-strict-fields
+we need to behave as if there was an UNPACK pragma there.
But it's the *argument* type that matters. This is fine:
data S = MkS S !Int
diff --git a/compiler/cmm/CmmNode.hs b/compiler/cmm/CmmNode.hs
index 47811bcd7f..7a4fb98a79 100644
--- a/compiler/cmm/CmmNode.hs
+++ b/compiler/cmm/CmmNode.hs
@@ -52,7 +52,7 @@ data CmmNode e x where
[CmmActual] -> -- zero or more arguments
CmmNode O O
-- Semantics: clobbers any GlobalRegs for which callerSaves r == True
- -- See Note [foreign calls clobber GlobalRegs]
+ -- See Note [Unsafe foreign calls clobber caller-save registers]
--
-- Invariant: the arguments and the ForeignTarget must not
-- mention any registers for which CodeGen.Platform.callerSaves
@@ -158,8 +158,8 @@ made manifest in CmmLayoutStack, where they are lowered into the above
sequence.
-}
-{- Note [foreign calls clobber GlobalRegs]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+{- Note [Unsafe foreign calls clobber caller-save registers]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A foreign call is defined to clobber any GlobalRegs that are mapped to
caller-saves machine registers (according to the prevailing C ABI).
@@ -329,8 +329,9 @@ instance DefinerOfRegs GlobalReg (CmmNode e x) where
foldRegsDefd dflags f z n = case n of
CmmAssign lhs _ -> fold f z lhs
CmmUnsafeForeignCall tgt _ _ -> fold f z (foreignTargetRegs tgt)
- CmmCall {} -> fold f z activeRegs
- CmmForeignCall {tgt=tgt} -> fold f z (foreignTargetRegs tgt)
+ CmmCall {} -> fold f z activeRegs
+ CmmForeignCall {} -> fold f z activeRegs
+ -- See Note [Safe foreign calls clobber STG registers]
_ -> z
where fold :: forall a b.
DefinerOfRegs GlobalReg a =>
@@ -344,6 +345,74 @@ instance DefinerOfRegs GlobalReg (CmmNode e x) where
foreignTargetRegs (ForeignTarget _ (ForeignConvention _ _ _ CmmNeverReturns)) = []
foreignTargetRegs _ = activeCallerSavesRegs
+-- Note [Safe foreign calls clobber STG registers]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--
+-- During stack layout phase every safe foreign call is expanded into a block
+-- that contains unsafe foreign call (instead of safe foreign call) and ends
+-- with a normal call (See Note [Foreign calls]). This means that we must
+-- treat safe foreign call as if it was a normal call (because eventually it
+-- will be). This is important if we try to run sinking pass before stack
+-- layout phase. Consider this example of what might go wrong (this is cmm
+-- code from stablename001 test). Here is code after common block elimination
+-- (before stack layout):
+--
+-- c1q6:
+-- _s1pf::P64 = R1;
+-- _c1q8::I64 = performMajorGC;
+-- I64[(young<c1q9> + 8)] = c1q9;
+-- foreign call "ccall" arg hints: [] result hints: [] (_c1q8::I64)(...)
+-- returns to c1q9 args: ([]) ress: ([])ret_args: 8ret_off: 8;
+-- c1q9:
+-- I64[(young<c1qb> + 8)] = c1qb;
+-- R1 = _s1pc::P64;
+-- call stg_makeStableName#(R1) returns to c1qb, args: 8, res: 8, upd: 8;
+--
+-- If we run sinking pass now (still before stack layout) we will get this:
+--
+-- c1q6:
+-- I64[(young<c1q9> + 8)] = c1q9;
+-- foreign call "ccall" arg hints: [] result hints: [] performMajorGC(...)
+-- returns to c1q9 args: ([]) ress: ([])ret_args: 8ret_off: 8;
+-- c1q9:
+-- I64[(young<c1qb> + 8)] = c1qb;
+-- _s1pf::P64 = R1; <------ _s1pf sunk past safe foreign call
+-- R1 = _s1pc::P64;
+-- call stg_makeStableName#(R1) returns to c1qb, args: 8, res: 8, upd: 8;
+--
+-- Notice that _s1pf was sunk past a foreign call. When we run stack layout
+-- safe call to performMajorGC will be turned into:
+--
+-- c1q6:
+-- _s1pc::P64 = P64[Sp + 8];
+-- I64[Sp - 8] = c1q9;
+-- Sp = Sp - 8;
+-- I64[I64[CurrentTSO + 24] + 16] = Sp;
+-- P64[CurrentNursery + 8] = Hp + 8;
+-- (_u1qI::I64) = call "ccall" arg hints: [PtrHint,]
+-- result hints: [PtrHint] suspendThread(BaseReg, 0);
+-- call "ccall" arg hints: [] result hints: [] performMajorGC();
+-- (_u1qJ::I64) = call "ccall" arg hints: [PtrHint]
+-- result hints: [PtrHint] resumeThread(_u1qI::I64);
+-- BaseReg = _u1qJ::I64;
+-- _u1qK::P64 = CurrentTSO;
+-- _u1qL::P64 = I64[_u1qK::P64 + 24];
+-- Sp = I64[_u1qL::P64 + 16];
+-- SpLim = _u1qL::P64 + 192;
+-- HpAlloc = 0;
+-- Hp = I64[CurrentNursery + 8] - 8;
+-- HpLim = I64[CurrentNursery] + (%MO_SS_Conv_W32_W64(I32[CurrentNursery + 48]) * 4096 - 1);
+-- call (I64[Sp])() returns to c1q9, args: 8, res: 8, upd: 8;
+-- c1q9:
+-- I64[(young<c1qb> + 8)] = c1qb;
+-- _s1pf::P64 = R1; <------ INCORRECT!
+-- R1 = _s1pc::P64;
+-- call stg_makeStableName#(R1) returns to c1qb, args: 8, res: 8, upd: 8;
+--
+-- Notice that c1q6 now ends with a call. Sinking _s1pf::P64 = R1 past that
+-- call is clearly incorrect. This is what would happen if we assumed that
+-- safe foreign call has the same semantics as unsafe foreign call. To prevent
+-- this we need to treat safe foreign call as if was normal call.
-----------------------------------
-- mapping Expr in CmmNode
@@ -429,6 +498,8 @@ foldExpForeignTarget exp (ForeignTarget e _) z = exp e z
foldExpForeignTarget _ (PrimTarget _) z = z
-- Take a folder on expressions and apply it recursively.
+-- Specifically (wrapRecExpf f e z) deals with CmmMachOp and CmmLoad
+-- itself, delegating all the other CmmExpr forms to 'f'.
wrapRecExpf :: (CmmExpr -> z -> z) -> CmmExpr -> z -> z
wrapRecExpf f e@(CmmMachOp _ es) z = foldr (wrapRecExpf f) (f e z) es
wrapRecExpf f e@(CmmLoad addr _) z = wrapRecExpf f addr (f e z)
diff --git a/compiler/cmm/CmmSink.hs b/compiler/cmm/CmmSink.hs
index 9f8a3975e7..41323ecad3 100644
--- a/compiler/cmm/CmmSink.hs
+++ b/compiler/cmm/CmmSink.hs
@@ -43,38 +43,52 @@ import qualified Data.Set as Set
--
-- * Start by doing liveness analysis.
--
--- * Keep a list of assignments A; earlier ones may refer to later ones
+-- * Keep a list of assignments A; earlier ones may refer to later ones.
+-- Currently we only sink assignments to local registers, because we don't
+-- have liveness information about global registers.
--
-- * Walk forwards through the graph, look at each node N:
--- * If any assignments in A (1) occur only once in N, and (2) are
--- not live after N, inline the assignment and remove it
--- from A.
--- * If N is an assignment:
--- * If the register is not live after N, discard it
--- * otherwise pick up the assignment and add it to A
--- * If N is a non-assignment node:
+--
+-- * If it is a dead assignment, i.e. assignment to a register that is
+-- not used after N, discard it.
+--
+-- * Try to inline based on current list of assignments
+-- * If any assignments in A (1) occur only once in N, and (2) are
+-- not live after N, inline the assignment and remove it
+-- from A.
+--
+-- * If an assignment in A is cheap (RHS is local register), then
+-- inline the assignment and keep it in A in case it is used afterwards.
+--
+-- * Otherwise don't inline.
+--
+-- * If N is assignment to a local register pick up the assignment
+-- and add it to A.
+--
+-- * If N is not an assignment to a local register:
-- * remove any assignments from A that conflict with N, and
--- place them before N in the current block. (we call this
--- "dropping" the assignments).
+-- place them before N in the current block. We call this
+-- "dropping" the assignments.
+--
-- * An assignment conflicts with N if it:
-- - assigns to a register mentioned in N
-- - mentions a register assigned by N
-- - reads from memory written by N
-- * do this recursively, dropping dependent assignments
--- * At a multi-way branch:
--- * drop any assignments that are live on more than one branch
--- * if any successor has more than one predecessor (a
--- join-point), drop everything live in that successor
---
--- As a side-effect we'll delete some dead assignments (transitively,
--- even). This isn't as good as removeDeadAssignments, but it's much
--- cheaper.
-
--- If we do this *before* stack layout, we might be able to avoid
--- saving some things across calls/procpoints.
--
--- *but*, that will invalidate the liveness analysis, and we'll have
--- to re-do it.
+-- * At an exit node:
+-- * drop any assignments that are live on more than one successor
+-- and are not trivial
+-- * if any successor has more than one predecessor (a join-point),
+-- drop everything live in that successor. Since we only propagate
+-- assignments that are not dead at the successor, we will therefore
+-- eliminate all assignments dead at this point. Thus analysis of a
+-- join-point will always begin with an empty list of assignments.
+--
+--
+-- As a result of above algorithm, sinking deletes some dead assignments
+-- (transitively, even). This isn't as good as removeDeadAssignments,
+-- but it's much cheaper.
-- -----------------------------------------------------------------------------
-- things that we aren't optimising very well yet.
@@ -122,6 +136,12 @@ type Assignment = (LocalReg, CmmExpr, AbsMem)
-- Assignment caches AbsMem, an abstraction of the memory read by
-- the RHS of the assignment.
+type Assignments = [Assignment]
+ -- A sequence of assignements; kept in *reverse* order
+ -- So the list [ x=e1, y=e2 ] means the sequence of assignments
+ -- y = e2
+ -- x = e1
+
cmmSink :: DynFlags -> CmmGraph -> CmmGraph
cmmSink dflags graph = ofBlockList (g_entry graph) $ sink mapEmpty $ blocks
where
@@ -132,7 +152,7 @@ cmmSink dflags graph = ofBlockList (g_entry graph) $ sink mapEmpty $ blocks
join_pts = findJoinPoints blocks
- sink :: BlockEnv [Assignment] -> [CmmBlock] -> [CmmBlock]
+ sink :: BlockEnv Assignments -> [CmmBlock] -> [CmmBlock]
sink _ [] = []
sink sunk (b:bs) =
-- pprTrace "sink" (ppr lbl) $
@@ -209,7 +229,8 @@ isSmall _ = False
isTrivial :: CmmExpr -> Bool
isTrivial (CmmReg (CmmLocal _)) = True
--- isTrivial (CmmLit _) = True
+-- isTrivial (CmmLit _) = True -- Disabled because it used to make thing worse.
+ -- Needs further investigation
isTrivial _ = False
--
@@ -234,7 +255,7 @@ findJoinPoints blocks = mapFilter (>1) succ_counts
-- filter the list of assignments to remove any assignments that
-- are not live in a continuation.
--
-filterAssignments :: DynFlags -> LocalRegSet -> [Assignment] -> [Assignment]
+filterAssignments :: DynFlags -> LocalRegSet -> Assignments -> Assignments
filterAssignments dflags live assigs = reverse (go assigs [])
where go [] kept = kept
go (a@(r,_,_):as) kept | needed = go as (a:kept)
@@ -249,26 +270,36 @@ filterAssignments dflags live assigs = reverse (go assigs [])
-- -----------------------------------------------------------------------------
-- Walk through the nodes of a block, sinking and inlining assignments
-- as we go.
+--
+-- On input we pass in a:
+-- * list of nodes in the block
+-- * a list of assignments that appeared *before* this block and
+-- that are being sunk.
+--
+-- On output we get:
+-- * a new block
+-- * a list of assignments that will be placed *after* that block.
+--
walk :: DynFlags
-> [(LocalRegSet, CmmNode O O)] -- nodes of the block, annotated with
-- the set of registers live *after*
-- this node.
- -> [Assignment] -- The current list of
+ -> Assignments -- The current list of
-- assignments we are sinking.
-- Later assignments may refer
-- to earlier ones.
-> ( Block CmmNode O O -- The new block
- , [Assignment] -- Assignments to sink further
+ , Assignments -- Assignments to sink further
)
walk dflags nodes assigs = go nodes emptyBlock assigs
where
go [] block as = (block, as)
go ((live,node):ns) block as
- | shouldDiscard node live = go ns block as
+ | shouldDiscard node live = go ns block as -- discard dead assignment
| Just a <- shouldSink dflags node2 = go ns block (a : as1)
| otherwise = go ns block' as'
where
@@ -316,17 +347,17 @@ shouldDiscard node live
CmmAssign r (CmmReg r') | r == r' -> True
CmmAssign (CmmLocal r) _ -> not (r `Set.member` live)
_otherwise -> False
-
+
toNode :: Assignment -> CmmNode O O
toNode (r,rhs,_) = CmmAssign (CmmLocal r) rhs
-dropAssignmentsSimple :: DynFlags -> (Assignment -> Bool) -> [Assignment]
- -> ([CmmNode O O], [Assignment])
+dropAssignmentsSimple :: DynFlags -> (Assignment -> Bool) -> Assignments
+ -> ([CmmNode O O], Assignments)
dropAssignmentsSimple dflags f = dropAssignments dflags (\a _ -> (f a, ())) ()
-dropAssignments :: DynFlags -> (Assignment -> s -> (Bool, s)) -> s -> [Assignment]
- -> ([CmmNode O O], [Assignment])
+dropAssignments :: DynFlags -> (Assignment -> s -> (Bool, s)) -> s -> Assignments
+ -> ([CmmNode O O], Assignments)
dropAssignments dflags should_drop state assigs
= (dropped, reverse kept)
where
@@ -351,16 +382,16 @@ tryToInline
-- that is live after the node, unless
-- it is small enough to duplicate.
-> CmmNode O x -- The node to inline into
- -> [Assignment] -- Assignments to inline
+ -> Assignments -- Assignments to inline
-> (
CmmNode O x -- New node
- , [Assignment] -- Remaining assignments
+ , Assignments -- Remaining assignments
)
tryToInline dflags live node assigs = go usages node [] assigs
where
- usages :: UniqFM Int
- usages = foldRegsUsed dflags addUsage emptyUFM node
+ usages :: UniqFM Int -- Maps each LocalReg to a count of how often it is used
+ usages = foldLocalRegsUsed dflags addUsage emptyUFM node
go _usages node _skipped [] = (node, [])
@@ -371,10 +402,10 @@ tryToInline dflags live node assigs = go usages node [] assigs
| otherwise = dont_inline
where
inline_and_discard = go usages' inl_node skipped rest
- where usages' = foldRegsUsed dflags addUsage usages rhs
+ where usages' = foldLocalRegsUsed dflags addUsage usages rhs
- dont_inline = keep node -- don't inline the assignment, keep it
- inline_and_keep = keep inl_node -- inline the assignment, keep it
+ dont_inline = keep node -- don't inline the assignment, keep it
+ inline_and_keep = keep inl_node -- inline the assignment, keep it
keep node' = (final_node, a : rest')
where (final_node, rest') = go usages' node' (l:skipped) rest
@@ -470,10 +501,10 @@ conflicts dflags (r, rhs, addr) node
| SpMem{} <- addr, CmmAssign (CmmGlobal Sp) _ <- node = True
-- (4) assignments that read caller-saves GlobalRegs conflict with a
- -- foreign call. See Note [foreign calls clobber GlobalRegs].
+ -- foreign call. See Note [Unsafe foreign calls clobber caller-save registers]
| CmmUnsafeForeignCall{} <- node, anyCallerSavesRegs dflags rhs = True
- -- (5) foreign calls clobber heap: see Note [foreign calls clobber heap]
+ -- (5) foreign calls clobber heap: see Note [Foreign calls clobber heap]
| CmmUnsafeForeignCall{} <- node, memConflicts addr AnyMem = True
-- (6) native calls clobber any memory
@@ -532,7 +563,8 @@ data AbsMem
-- that was written in the same basic block. To take advantage of
-- non-aliasing of heap memory we will have to be more clever.
--- Note [foreign calls clobber]
+-- Note [Foreign calls clobber heap]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--
-- It is tempting to say that foreign calls clobber only
-- non-heap/stack memory, but unfortunately we break this invariant in
diff --git a/compiler/codeGen/StgCmm.hs b/compiler/codeGen/StgCmm.hs
index 9b1bce4b57..bf950c4158 100644
--- a/compiler/codeGen/StgCmm.hs
+++ b/compiler/codeGen/StgCmm.hs
@@ -11,7 +11,7 @@ module StgCmm ( codeGen ) where
#define FAST_STRING_NOT_NEEDED
#include "HsVersions.h"
-import StgCmmProf
+import StgCmmProf (initCostCentres, ldvEnter)
import StgCmmMonad
import StgCmmEnv
import StgCmmBind
diff --git a/compiler/codeGen/StgCmmBind.hs b/compiler/codeGen/StgCmmBind.hs
index dccefd0fb0..4762c5a4e0 100644
--- a/compiler/codeGen/StgCmmBind.hs
+++ b/compiler/codeGen/StgCmmBind.hs
@@ -20,7 +20,8 @@ import StgCmmMonad
import StgCmmEnv
import StgCmmCon
import StgCmmHeap
-import StgCmmProf
+import StgCmmProf (curCCS, ldvEnterClosure, enterCostCentreFun, enterCostCentreThunk,
+ initUpdFrameProf, costCentreFrom)
import StgCmmTicky
import StgCmmLayout
import StgCmmUtils
diff --git a/compiler/codeGen/StgCmmCon.hs b/compiler/codeGen/StgCmmCon.hs
index 57d4759346..eb00bbf0c0 100644
--- a/compiler/codeGen/StgCmmCon.hs
+++ b/compiler/codeGen/StgCmmCon.hs
@@ -23,7 +23,7 @@ import StgCmmEnv
import StgCmmHeap
import StgCmmUtils
import StgCmmClosure
-import StgCmmProf
+import StgCmmProf ( curCCS )
import CmmExpr
import CLabel
diff --git a/compiler/codeGen/StgCmmExpr.hs b/compiler/codeGen/StgCmmExpr.hs
index 331e65819f..c7fddd49dc 100644
--- a/compiler/codeGen/StgCmmExpr.hs
+++ b/compiler/codeGen/StgCmmExpr.hs
@@ -17,7 +17,7 @@ import StgCmmMonad
import StgCmmHeap
import StgCmmEnv
import StgCmmCon
-import StgCmmProf
+import StgCmmProf (saveCurrentCostCentre, restoreCurrentCostCentre, emitSetCCC)
import StgCmmLayout
import StgCmmPrim
import StgCmmHpc
diff --git a/compiler/codeGen/StgCmmForeign.hs b/compiler/codeGen/StgCmmForeign.hs
index 0b782fffcc..a688074b9e 100644
--- a/compiler/codeGen/StgCmmForeign.hs
+++ b/compiler/codeGen/StgCmmForeign.hs
@@ -18,7 +18,7 @@ module StgCmmForeign (
#include "HsVersions.h"
import StgSyn
-import StgCmmProf
+import StgCmmProf (storeCurCCS, ccsType, curCCS)
import StgCmmEnv
import StgCmmMonad
import StgCmmUtils
diff --git a/compiler/codeGen/StgCmmHeap.hs b/compiler/codeGen/StgCmmHeap.hs
index 97233aa500..f4c58e95e1 100644
--- a/compiler/codeGen/StgCmmHeap.hs
+++ b/compiler/codeGen/StgCmmHeap.hs
@@ -28,7 +28,7 @@ import CLabel
import StgCmmLayout
import StgCmmUtils
import StgCmmMonad
-import StgCmmProf
+import StgCmmProf (profDynAlloc, dynProfHdr, staticProfHdr)
import StgCmmTicky
import StgCmmClosure
import StgCmmEnv
diff --git a/compiler/codeGen/StgCmmLayout.hs b/compiler/codeGen/StgCmmLayout.hs
index 6c6e49dafa..b52d4e57df 100644
--- a/compiler/codeGen/StgCmmLayout.hs
+++ b/compiler/codeGen/StgCmmLayout.hs
@@ -29,7 +29,7 @@ import StgCmmArgRep -- notably: ( slowCallPattern )
import StgCmmTicky
import StgCmmMonad
import StgCmmUtils
-import StgCmmProf
+import StgCmmProf (curCCS)
import MkGraph
import SMRep
diff --git a/compiler/codeGen/StgCmmPrim.hs b/compiler/codeGen/StgCmmPrim.hs
index c11df7009c..bb58024a4e 100644
--- a/compiler/codeGen/StgCmmPrim.hs
+++ b/compiler/codeGen/StgCmmPrim.hs
@@ -21,7 +21,7 @@ import StgCmmMonad
import StgCmmUtils
import StgCmmTicky
import StgCmmHeap
-import StgCmmProf
+import StgCmmProf ( costCentreFrom, curCCS )
import DynFlags
import Platform
diff --git a/compiler/coreSyn/CoreLint.lhs b/compiler/coreSyn/CoreLint.lhs
index 68aaea5b5c..1913e3ab93 100644
--- a/compiler/coreSyn/CoreLint.lhs
+++ b/compiler/coreSyn/CoreLint.lhs
@@ -16,7 +16,7 @@ A ``lint'' pass to check for Core correctness
{-# OPTIONS_GHC -fprof-auto #-}
-module CoreLint ( lintCoreBindings, lintUnfolding ) where
+module CoreLint ( lintCoreBindings, lintUnfolding, lintExpr ) where
#include "HsVersions.h"
@@ -120,14 +120,15 @@ find an occurence of an Id, we fetch it from the in-scope set.
\begin{code}
-lintCoreBindings :: CoreProgram -> (Bag MsgDoc, Bag MsgDoc)
+lintCoreBindings :: [Var] -> CoreProgram -> (Bag MsgDoc, Bag MsgDoc)
-- Returns (warnings, errors)
-- If you edit this function, you may need to update the GHC formalism
-- See Note [GHC Formalism]
-lintCoreBindings binds
+lintCoreBindings local_in_scope binds
= initL $
- addLoc TopLevelBindings $
- addInScopeVars binders $
+ addLoc TopLevelBindings $
+ addInScopeVars local_in_scope $
+ addInScopeVars binders $
-- Put all the top-level binders in scope at the start
-- This is because transformation rules can bring something
-- into use 'unexpectedly'
@@ -178,6 +179,18 @@ lintUnfolding locn vars expr
(_warns, errs) = initL (addLoc (ImportedUnfolding locn) $
addInScopeVars vars $
lintCoreExpr expr)
+
+lintExpr :: [Var] -- Treat these as in scope
+ -> CoreExpr
+ -> Maybe MsgDoc -- Nothing => OK
+
+lintExpr vars expr
+ | isEmptyBag errs = Nothing
+ | otherwise = Just (pprMessageBag errs)
+ where
+ (_warns, errs) = initL (addLoc TopLevelBindings $
+ addInScopeVars vars $
+ lintCoreExpr expr)
\end{code}
%************************************************************************
diff --git a/compiler/coreSyn/CorePrep.lhs b/compiler/coreSyn/CorePrep.lhs
index d87fdfc197..1a21253f39 100644
--- a/compiler/coreSyn/CorePrep.lhs
+++ b/compiler/coreSyn/CorePrep.lhs
@@ -172,7 +172,7 @@ corePrepPgm dflags hsc_env binds data_tycons = do
floats2 <- corePrepTopBinds initialCorePrepEnv implicit_binds
return (deFloatTop (floats1 `appendFloats` floats2))
- endPass dflags CorePrep binds_out []
+ endPass hsc_env CorePrep binds_out []
return binds_out
corePrepExpr :: DynFlags -> HscEnv -> CoreExpr -> IO CoreExpr
diff --git a/compiler/coreSyn/CoreSyn.lhs b/compiler/coreSyn/CoreSyn.lhs
index dd7307d190..baa28bc0cc 100644
--- a/compiler/coreSyn/CoreSyn.lhs
+++ b/compiler/coreSyn/CoreSyn.lhs
@@ -714,7 +714,9 @@ data Unfolding
------------------------------------------------
data UnfoldingSource
- = InlineRhs -- The current rhs of the function
+ = -- See also Note [Historical note: unfoldings for wrappers]
+
+ InlineRhs -- The current rhs of the function
-- Replace uf_tmpl each time around
| InlineStable -- From an INLINE or INLINABLE pragma
@@ -739,13 +741,6 @@ data UnfoldingSource
-- (see MkId.lhs, calls to mkCompulsoryUnfolding).
-- Inline absolutely always, however boring the context.
- | InlineWrapper -- This unfolding is the wrapper in a
- -- worker/wrapper split from the strictness
- -- analyser
- --
- -- cf some history in TcIface's Note [wrappers
- -- in interface files]
-
-- | 'UnfoldingGuidance' says when unfolding should take place
@@ -775,6 +770,25 @@ data UnfoldingGuidance
| UnfNever -- The RHS is big, so don't inline it
\end{code}
+Note [Historical note: unfoldings for wrappers]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We used to have a nice clever scheme in interface files for
+wrappers. A wrapper's unfolding can be reconstructed from its worker's
+id and its strictness. This decreased .hi file size (sometimes
+significantly, for modules like GHC.Classes with many high-arity w/w
+splits) and had a slight corresponding effect on compile times.
+
+However, when we added the second demand analysis, this scheme lead to
+some Core lint errors. The second analysis could change the strictness
+signatures, which sometimes resulted in a wrapper's regenerated
+unfolding applying the wrapper to too many arguments.
+
+Instead of repairing the clever .hi scheme, we abandoned it in favor
+of simplicity. The .hi sizes are usually insignificant (excluding the
++1M for base libraries), and compile time barely increases (~+1% for
+nofib). The nicer upshot is that the UnfoldingSource no longer mentions
+an Id, so, eg, substitutions need not traverse them.
+
Note [DFun unfoldings]
~~~~~~~~~~~~~~~~~~~~~~
@@ -844,7 +858,6 @@ isStableSource :: UnfoldingSource -> Bool
-- Keep the unfolding template
isStableSource InlineCompulsory = True
isStableSource InlineStable = True
-isStableSource InlineWrapper = True
isStableSource InlineRhs = False
-- | Retrieves the template of an unfolding: panics if none is known
diff --git a/compiler/coreSyn/CoreUnfold.lhs b/compiler/coreSyn/CoreUnfold.lhs
index bbf9e0eb40..896f3723d2 100644
--- a/compiler/coreSyn/CoreUnfold.lhs
+++ b/compiler/coreSyn/CoreUnfold.lhs
@@ -103,7 +103,7 @@ mkDFunUnfolding bndrs con ops
mkWwInlineRule :: CoreExpr -> Arity -> Unfolding
mkWwInlineRule expr arity
- = mkCoreUnfolding InlineWrapper True
+ = mkCoreUnfolding InlineStable True
(simpleOptExpr expr) arity
(UnfWhen unSaturatedOk boringCxtNotOk)
diff --git a/compiler/coreSyn/PprCore.lhs b/compiler/coreSyn/PprCore.lhs
index 64e7d63590..00f9a9346f 100644
--- a/compiler/coreSyn/PprCore.lhs
+++ b/compiler/coreSyn/PprCore.lhs
@@ -422,7 +422,6 @@ instance Outputable UnfoldingGuidance where
instance Outputable UnfoldingSource where
ppr InlineCompulsory = ptext (sLit "Compulsory")
- ppr InlineWrapper = ptext (sLit "Wrapper")
ppr InlineStable = ptext (sLit "InlineStable")
ppr InlineRhs = ptext (sLit "<vanilla>")
diff --git a/compiler/deSugar/Desugar.lhs b/compiler/deSugar/Desugar.lhs
index b65304a118..20a8a57299 100644
--- a/compiler/deSugar/Desugar.lhs
+++ b/compiler/deSugar/Desugar.lhs
@@ -143,14 +143,14 @@ deSugar hsc_env
#ifdef DEBUG
-- Debug only as pre-simple-optimisation program may be really big
- ; endPass dflags CoreDesugar final_pgm rules_for_imps
+ ; endPass hsc_env CoreDesugar final_pgm rules_for_imps
#endif
; (ds_binds, ds_rules_for_imps, ds_vects)
<- simpleOptPgm dflags mod final_pgm rules_for_imps vects0
-- The simpleOptPgm gets rid of type
-- bindings plus any stupid dead code
- ; endPass dflags CoreDesugarOpt ds_binds ds_rules_for_imps
+ ; endPass hsc_env CoreDesugarOpt ds_binds ds_rules_for_imps
; let used_names = mkUsedNames tcg_env
; deps <- mkDependencies tcg_env
@@ -226,22 +226,23 @@ deSugarExpr :: HscEnv
-> IO (Messages, Maybe CoreExpr)
-- Prints its own errors; returns Nothing if error occurred
-deSugarExpr hsc_env this_mod rdr_env type_env tc_expr = do
- let dflags = hsc_dflags hsc_env
- showPass dflags "Desugar"
+deSugarExpr hsc_env this_mod rdr_env type_env tc_expr
+ = do { let dflags = hsc_dflags hsc_env
+ ; showPass dflags "Desugar"
- -- Do desugaring
- (msgs, mb_core_expr) <- initDs hsc_env this_mod rdr_env type_env $
- dsLExpr tc_expr
+ -- Do desugaring
+ ; (msgs, mb_core_expr) <- initDs hsc_env this_mod rdr_env type_env $
+ dsLExpr tc_expr
- case mb_core_expr of
- Nothing -> return (msgs, Nothing)
- Just expr -> do
+ ; case mb_core_expr of {
+ Nothing -> return (msgs, Nothing) ;
+ Just expr ->
- -- Dump output
- dumpIfSet_dyn dflags Opt_D_dump_ds "Desugared" (pprCoreExpr expr)
+
+ -- Dump output
+ do { dumpIfSet_dyn dflags Opt_D_dump_ds "Desugared" (pprCoreExpr expr)
- return (msgs, Just expr)
+ ; return (msgs, Just expr) } } }
\end{code}
%************************************************************************
diff --git a/compiler/iface/IfaceSyn.lhs b/compiler/iface/IfaceSyn.lhs
index 8dc4188bb9..f6e68e2836 100644
--- a/compiler/iface/IfaceSyn.lhs
+++ b/compiler/iface/IfaceSyn.lhs
@@ -583,8 +583,6 @@ data IfaceUnfolding
Bool -- OK to inline even if context is boring
IfaceExpr
- | IfWrapper IfaceExpr -- cf TcIface's Note [wrappers in interface files]
-
| IfDFunUnfold [IfaceBndr] [IfaceExpr]
instance Binary IfaceUnfolding where
@@ -598,15 +596,12 @@ instance Binary IfaceUnfolding where
put_ bh b
put_ bh c
put_ bh d
- put_ bh (IfWrapper e) = do
- putByte bh 2
- put_ bh e
put_ bh (IfDFunUnfold as bs) = do
- putByte bh 3
+ putByte bh 2
put_ bh as
put_ bh bs
put_ bh (IfCompulsory e) = do
- putByte bh 4
+ putByte bh 3
put_ bh e
get bh = do
h <- getByte bh
@@ -619,9 +614,7 @@ instance Binary IfaceUnfolding where
c <- get bh
d <- get bh
return (IfInlineRule a b c d)
- 2 -> do e <- get bh
- return (IfWrapper e)
- 3 -> do as <- get bh
+ 2 -> do as <- get bh
bs <- get bh
return (IfDFunUnfold as bs)
_ -> do e <- get bh
@@ -1288,7 +1281,6 @@ instance Outputable IfaceUnfolding where
ppr (IfInlineRule a uok bok e) = sep [ptext (sLit "InlineRule")
<+> ppr (a,uok,bok),
pprParendIfaceExpr e]
- ppr (IfWrapper e) = ptext (sLit "Wrapper:") <+> parens (ppr e)
ppr (IfDFunUnfold bs es) = hang (ptext (sLit "DFun:") <+> sep (map ppr bs) <> dot)
2 (sep (map pprParendIfaceExpr es))
@@ -1446,7 +1438,6 @@ freeNamesIfUnfold :: IfaceUnfolding -> NameSet
freeNamesIfUnfold (IfCoreUnfold _ e) = freeNamesIfExpr e
freeNamesIfUnfold (IfCompulsory e) = freeNamesIfExpr e
freeNamesIfUnfold (IfInlineRule _ _ _ e) = freeNamesIfExpr e
-freeNamesIfUnfold (IfWrapper e) = freeNamesIfExpr e
freeNamesIfUnfold (IfDFunUnfold bs es) = fnList freeNamesIfBndr bs &&& fnList freeNamesIfExpr es
freeNamesIfExpr :: IfaceExpr -> NameSet
diff --git a/compiler/iface/MkIface.lhs b/compiler/iface/MkIface.lhs
index d3b56d1f7b..44f99d520e 100644
--- a/compiler/iface/MkIface.lhs
+++ b/compiler/iface/MkIface.lhs
@@ -1762,7 +1762,6 @@ toIfUnfolding lb (CoreUnfolding { uf_tmpl = rhs, uf_arity = arity
-> case guidance of
UnfWhen unsat_ok boring_ok -> IfInlineRule arity unsat_ok boring_ok if_rhs
_other -> IfCoreUnfold True if_rhs
- InlineWrapper -> IfWrapper if_rhs
InlineCompulsory -> IfCompulsory if_rhs
InlineRhs -> IfCoreUnfold False if_rhs
-- Yes, even if guidance is UnfNever, expose the unfolding
diff --git a/compiler/iface/TcIface.lhs b/compiler/iface/TcIface.lhs
index dffd69b9ed..2d2e867390 100644
--- a/compiler/iface/TcIface.lhs
+++ b/compiler/iface/TcIface.lhs
@@ -605,33 +605,36 @@ tcIfaceDataCons tycon_name tycon _ if_cons
ifConStricts = if_stricts})
= bindIfaceTyVars univ_tvs $ \ univ_tyvars -> do
bindIfaceTyVars ex_tvs $ \ ex_tyvars -> do
- { name <- lookupIfaceTop occ
+ { traceIf (text "Start interface-file tc_con_decl" <+> ppr occ)
+ ; name <- lookupIfaceTop occ
-- Read the context and argument types, but lazily for two reasons
-- (a) to avoid looking tugging on a recursive use of
-- the type itself, which is knot-tied
-- (b) to avoid faulting in the component types unless
-- they are really needed
- ; ~(eq_spec, theta, arg_tys) <- forkM (mk_doc name) $
+ ; ~(eq_spec, theta, arg_tys, stricts) <- forkM (mk_doc name) $
do { eq_spec <- tcIfaceEqSpec spec
; theta <- tcIfaceCtxt ctxt
; arg_tys <- mapM tcIfaceType args
- ; return (eq_spec, theta, arg_tys) }
+ ; stricts <- mapM tc_strict if_stricts
+ -- The IfBang field can mention
+ -- the type itself; hence inside forkM
+ ; return (eq_spec, theta, arg_tys, stricts) }
; lbl_names <- mapM lookupIfaceTop field_lbls
- ; stricts <- mapM tc_strict if_stricts
-
-- Remember, tycon is the representation tycon
; let orig_res_ty = mkFamilyTyConApp tycon
(substTyVars (mkTopTvSubst eq_spec) univ_tyvars)
- ; buildDataCon (pprPanic "tcIfaceDataCons: FamInstEnvs" (ppr name))
+ ; con <- buildDataCon (pprPanic "tcIfaceDataCons: FamInstEnvs" (ppr name))
name is_infix
stricts lbl_names
univ_tyvars ex_tyvars
eq_spec theta
arg_tys orig_res_ty tycon
- }
+ ; traceIf (text "Done interface-file tc_con_decl" <+> ppr name)
+ ; return con }
mk_doc con_name = ptext (sLit "Constructor") <+> ppr con_name
tc_strict IfNoBang = return HsNoBang
@@ -1204,25 +1207,6 @@ do_one (IfaceRec pairs) thing_inside
%* *
%************************************************************************
-Note [wrappers in interface files]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We used to have a nice clever scheme in interface files for
-wrappers. A wrapper's unfolding can be reconstructed from its worker's
-id and its strictness. This decreased .hi file size (sometimes
-significantly, for modules like GHC.Classes with many high-arity w/w
-splits) and had a slight corresponding effect on compile times.
-
-However, when we added the second demand analysis, this scheme lead to
-some Core lint errors. The second analysis could change the strictness
-signatures, which sometimes resulted in a wrapper's regenerated
-unfolding applying the wrapper to too many arguments.
-
-Instead of repairing the clever .hi scheme, we abandoned it in favor
-of simplicity. The .hi sizes are usually insignificant (excluding the
-+1M for base libraries), and compile time barely increases (~+1% for
-nofib). The nicer upshot is that unfolding sources no longer include
-an Id, so, eg, substitutions need not traverse them any longer.
-
\begin{code}
tcIdDetails :: Type -> IfaceIdDetails -> IfL IdDetails
tcIdDetails _ IfVanillaId = return VanillaId
@@ -1300,16 +1284,6 @@ tcUnfolding name dfun_ty _ (IfDFunUnfold bs ops)
where
doc = text "Class ops for dfun" <+> ppr name
(_, _, cls, _) = tcSplitDFunTy dfun_ty
-
-tcUnfolding name _ info (IfWrapper if_expr)
- = do { mb_expr <- tcPragExpr name if_expr
- ; return $ case mb_expr of
- Nothing -> NoUnfolding
- Just expr -> mkWwInlineRule expr arity -- see Note [wrappers in interface files]
- }
- where
- -- Arity should occur before unfolding!
- arity = arityInfo info
\end{code}
For unfoldings we try to do the job lazily, so that we never type check
diff --git a/compiler/main/HscMain.hs b/compiler/main/HscMain.hs
index e884fe5bcf..ad1b7c503a 100644
--- a/compiler/main/HscMain.hs
+++ b/compiler/main/HscMain.hs
@@ -81,9 +81,8 @@ import CoreTidy ( tidyExpr )
import Type ( Type )
import PrelNames
import {- Kind parts of -} Type ( Kind )
-import CoreLint ( lintUnfolding )
+import CoreMonad ( lintInteractiveExpr )
import DsMeta ( templateHaskellNames )
-import VarSet
import VarEnv ( emptyTidyEnv )
import Panic
@@ -1385,12 +1384,12 @@ hscStmtWithLocation hsc_env0 stmt source linenumber =
-- Desugar it
ds_expr <- ioMsgMaybe $
- deSugarExpr hsc_env iNTERACTIVE rdr_env type_env tc_expr
+ deSugarExpr hsc_env iNTERACTIVE rdr_env type_env tc_expr
+ liftIO (lintInteractiveExpr "desugar expression" hsc_env ds_expr)
handleWarnings
-- Then code-gen, and link it
- hsc_env <- getHscEnv
- hval <- liftIO $ hscCompileCoreExpr hsc_env src_span ds_expr
+ hval <- liftIO $ hscCompileCoreExpr hsc_env src_span ds_expr
let hval_io = unsafeCoerce# hval :: IO [HValue]
return $ Just (ids, hval_io, fix_env)
@@ -1618,37 +1617,28 @@ hscCompileCoreExpr hsc_env srcspan ds_expr
= throwIO (InstallationError "You can't call hscCompileCoreExpr in a profiled compiler")
-- Otherwise you get a seg-fault when you run it
- | otherwise = do
- let dflags = hsc_dflags hsc_env
- let lint_on = gopt Opt_DoCoreLinting dflags
+ | otherwise
+ = do { let dflags = hsc_dflags hsc_env
- {- Simplify it -}
- simpl_expr <- simplifyExpr dflags ds_expr
+ {- Simplify it -}
+ ; simpl_expr <- simplifyExpr dflags ds_expr
- {- Tidy it (temporary, until coreSat does cloning) -}
- let tidy_expr = tidyExpr emptyTidyEnv simpl_expr
+ {- Tidy it (temporary, until coreSat does cloning) -}
+ ; let tidy_expr = tidyExpr emptyTidyEnv simpl_expr
- {- Prepare for codegen -}
- prepd_expr <- corePrepExpr dflags hsc_env tidy_expr
+ {- Prepare for codegen -}
+ ; prepd_expr <- corePrepExpr dflags hsc_env tidy_expr
- {- Lint if necessary -}
- -- ToDo: improve SrcLoc
- when lint_on $
- let ictxt = hsc_IC hsc_env
- te = mkTypeEnvWithImplicits (ic_tythings ictxt ++ map AnId (ic_sys_vars ictxt))
- tyvars = varSetElems $ tyThingsTyVars $ typeEnvElts $ te
- vars = typeEnvIds te
- in case lintUnfolding noSrcLoc (tyvars ++ vars) prepd_expr of
- Just err -> pprPanic "hscCompileCoreExpr" err
- Nothing -> return ()
+ {- Lint if necessary -}
+ ; lintInteractiveExpr "hscCompileExpr" hsc_env prepd_expr
- {- Convert to BCOs -}
- bcos <- coreExprToBCOs dflags iNTERACTIVE prepd_expr
+ {- Convert to BCOs -}
+ ; bcos <- coreExprToBCOs dflags iNTERACTIVE prepd_expr
- {- link it -}
- hval <- linkExpr hsc_env srcspan bcos
+ {- link it -}
+ ; hval <- linkExpr hsc_env srcspan bcos
- return hval
+ ; return hval }
#endif
diff --git a/compiler/main/TidyPgm.lhs b/compiler/main/TidyPgm.lhs
index 214e7f3315..d6a3da13e6 100644
--- a/compiler/main/TidyPgm.lhs
+++ b/compiler/main/TidyPgm.lhs
@@ -363,7 +363,7 @@ tidyProgram hsc_env (ModGuts { mg_module = mod
; alg_tycons = filter isAlgTyCon (typeEnvTyCons type_env)
}
- ; endPass dflags CoreTidy all_tidy_binds tidy_rules
+ ; endPass hsc_env CoreTidy all_tidy_binds tidy_rules
-- If the endPass didn't print the rules, but ddump-rules is
-- on, print now
diff --git a/compiler/prelude/primops.txt.pp b/compiler/prelude/primops.txt.pp
index e275b23778..094c2f55e6 100644
--- a/compiler/prelude/primops.txt.pp
+++ b/compiler/prelude/primops.txt.pp
@@ -794,6 +794,14 @@ primop ThawArrayOp "thawArray#" GenPrimOp
has_side_effects = True
code_size = { primOpCodeSizeForeignCall + 4 }
+primop CasArrayOp "casArray#" GenPrimOp
+ MutableArray# s a -> Int# -> a -> a -> State# s -> (# State# s, Int#, a #)
+ {Unsafe, machine-level atomic compare and swap on an element within an Array.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+
------------------------------------------------------------------------
section "Byte Arrays"
{Operations on {\tt ByteArray\#}. A {\tt ByteArray\#} is a just a region of
@@ -1110,6 +1118,21 @@ primop SetByteArrayOp "setByteArray#" GenPrimOp
code_size = { primOpCodeSizeForeignCall + 4 }
can_fail = True
+primop CasByteArrayOp_Int "casIntArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> Int# -> Int# -> State# s -> (# State# s, Int# #)
+ {Machine-level atomic compare and swap on a word within a ByteArray.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+primop FetchAddByteArrayOp_Int "fetchAddIntArray#" GenPrimOp
+ MutableByteArray# s -> Int# -> Int# -> State# s -> (# State# s, Int# #)
+ {Machine-level word-sized fetch-and-add within a ByteArray.}
+ with
+ out_of_line = True
+ has_side_effects = True
+
+
------------------------------------------------------------------------
section "Arrays of arrays"
{Operations on {\tt ArrayArray\#}. An {\tt ArrayArray\#} contains references to {\em unpointed}
diff --git a/compiler/rename/RnExpr.lhs b/compiler/rename/RnExpr.lhs
index 0ef169085b..23501e3e1a 100644
--- a/compiler/rename/RnExpr.lhs
+++ b/compiler/rename/RnExpr.lhs
@@ -189,8 +189,10 @@ rnExpr (HsSpliceE splice)
rnExpr e@(HsQuasiQuoteE _) = pprPanic "Cant do quasiquotation without GHCi" (ppr e)
#else
rnExpr (HsQuasiQuoteE qq)
- = runQuasiQuoteExpr qq `thenM` \ (L _ expr') ->
- rnExpr expr'
+ = runQuasiQuoteExpr qq `thenM` \ lexpr' ->
+ -- Wrap the result of the quasi-quoter in parens so that we don't
+ -- lose the outermost location set by runQuasiQuote (#7918)
+ rnExpr (HsPar lexpr')
#endif /* GHCI */
---------------------------------------------
diff --git a/compiler/rename/RnPat.lhs b/compiler/rename/RnPat.lhs
index 90a83d6a8e..e7cecf8f3f 100644
--- a/compiler/rename/RnPat.lhs
+++ b/compiler/rename/RnPat.lhs
@@ -416,8 +416,9 @@ rnPatAndThen _ p@(QuasiQuotePat {})
#else
rnPatAndThen mk (QuasiQuotePat qq)
= do { pat <- liftCps $ runQuasiQuotePat qq
- ; L _ pat' <- rnLPatAndThen mk pat
- ; return pat' }
+ -- Wrap the result of the quasi-quoter in parens so that we don't
+ -- lose the outermost location set by runQuasiQuote (#7918)
+ ; rnPatAndThen mk (ParPat pat) }
#endif /* GHCI */
rnPatAndThen _ pat = pprPanic "rnLPatAndThen" (ppr pat)
diff --git a/compiler/rename/RnTypes.lhs b/compiler/rename/RnTypes.lhs
index a1c4bac25c..c13ea336e4 100644
--- a/compiler/rename/RnTypes.lhs
+++ b/compiler/rename/RnTypes.lhs
@@ -269,7 +269,9 @@ rnHsTyKi _ _ ty@(HsQuasiQuoteTy _) = pprPanic "Can't do quasiquotation without G
rnHsTyKi isType doc (HsQuasiQuoteTy qq)
= ASSERT( isType )
do { ty <- runQuasiQuoteType qq
- ; rnHsType doc (unLoc ty) }
+ -- Wrap the result of the quasi-quoter in parens so that we don't
+ -- lose the outermost location set by runQuasiQuote (#7918)
+ ; rnHsType doc (HsParTy ty) }
#endif
rnHsTyKi isType _ (HsCoreTy ty)
diff --git a/compiler/simplCore/CoreMonad.lhs b/compiler/simplCore/CoreMonad.lhs
index 31547e14a2..0af8201170 100644
--- a/compiler/simplCore/CoreMonad.lhs
+++ b/compiler/simplCore/CoreMonad.lhs
@@ -50,7 +50,8 @@ module CoreMonad (
getAnnotations, getFirstAnnotations,
-- ** Debug output
- showPass, endPass, dumpPassResult, lintPassResult, dumpIfSet,
+ showPass, endPass, dumpPassResult, lintPassResult,
+ lintInteractiveExpr, dumpIfSet,
-- ** Screen output
putMsg, putMsgS, errorMsg, errorMsgS,
@@ -70,7 +71,7 @@ import Name( Name )
import CoreSyn
import PprCore
import CoreUtils
-import CoreLint ( lintCoreBindings )
+import CoreLint ( lintCoreBindings, lintExpr )
import HscTypes
import Module
import DynFlags
@@ -78,12 +79,13 @@ import StaticFlags
import Rules ( RuleBase )
import BasicTypes ( CompilerPhase(..) )
import Annotations
-import Id ( Id )
import IOEnv hiding ( liftIO, failM, failWithM )
import qualified IOEnv ( liftIO )
import TcEnv ( tcLookupGlobal )
import TcRnMonad ( initTcForLookup )
+import Var
+import VarSet
import Outputable
import FastString
@@ -136,11 +138,12 @@ stuff before and after core passes, and do Core Lint when necessary.
showPass :: DynFlags -> CoreToDo -> IO ()
showPass dflags pass = Err.showPass dflags (showPpr dflags pass)
-endPass :: DynFlags -> CoreToDo -> CoreProgram -> [CoreRule] -> IO ()
-endPass dflags pass binds rules
+endPass :: HscEnv -> CoreToDo -> CoreProgram -> [CoreRule] -> IO ()
+endPass hsc_env pass binds rules
= do { dumpPassResult dflags mb_flag (ppr pass) (pprPassDetails pass) binds rules
- ; lintPassResult dflags pass binds }
+ ; lintPassResult hsc_env pass binds }
where
+ dflags = hsc_dflags hsc_env
mb_flag = case coreDumpFlag pass of
Just flag | dopt flag dflags -> Just flag
| dopt Opt_D_verbose_core2core dflags -> Just flag
@@ -178,12 +181,16 @@ dumpPassResult dflags mb_flag hdr extra_info binds rules
, ptext (sLit "------ Local rules for imported ids --------")
, pprRules rules ]
-lintPassResult :: DynFlags -> CoreToDo -> CoreProgram -> IO ()
-lintPassResult dflags pass binds
- = when (gopt Opt_DoCoreLinting dflags) $
- do { let (warns, errs) = lintCoreBindings binds
+lintPassResult :: HscEnv -> CoreToDo -> CoreProgram -> IO ()
+lintPassResult hsc_env pass binds
+ | not (gopt Opt_DoCoreLinting dflags)
+ = return ()
+ | otherwise
+ = do { let (warns, errs) = lintCoreBindings (interactiveInScope hsc_env) binds
; Err.showPass dflags ("Core Linted result of " ++ showPpr dflags pass)
; displayLintResults dflags pass warns errs binds }
+ where
+ dflags = hsc_dflags hsc_env
displayLintResults :: DynFlags -> CoreToDo
-> Bag Err.MsgDoc -> Bag Err.MsgDoc -> CoreProgram
@@ -191,7 +198,7 @@ displayLintResults :: DynFlags -> CoreToDo
displayLintResults dflags pass warns errs binds
| not (isEmptyBag errs)
= do { log_action dflags dflags Err.SevDump noSrcSpan defaultDumpStyle
- (vcat [ banner "errors", Err.pprMessageBag errs
+ (vcat [ lint_banner "errors" (ppr pass), Err.pprMessageBag errs
, ptext (sLit "*** Offending Program ***")
, pprCoreBindings binds
, ptext (sLit "*** End of Offense ***") ])
@@ -206,19 +213,66 @@ displayLintResults dflags pass warns errs binds
, not opt_NoDebugOutput
, showLintWarnings pass
= log_action dflags dflags Err.SevDump noSrcSpan defaultDumpStyle
- (banner "warnings" $$ Err.pprMessageBag warns)
+ (lint_banner "warnings" (ppr pass) $$ Err.pprMessageBag warns)
| otherwise = return ()
where
- banner string = ptext (sLit "*** Core Lint") <+> text string
- <+> ptext (sLit ": in result of") <+> ppr pass
- <+> ptext (sLit "***")
+
+lint_banner :: String -> SDoc -> SDoc
+lint_banner string pass = ptext (sLit "*** Core Lint") <+> text string
+ <+> ptext (sLit ": in result of") <+> pass
+ <+> ptext (sLit "***")
showLintWarnings :: CoreToDo -> Bool
-- Disable Lint warnings on the first simplifier pass, because
-- there may be some INLINE knots still tied, which is tiresomely noisy
showLintWarnings (CoreDoSimplify _ (SimplMode { sm_phase = InitialPhase })) = False
showLintWarnings _ = True
+
+lintInteractiveExpr :: String -> HscEnv -> CoreExpr -> IO ()
+lintInteractiveExpr what hsc_env expr
+ | not (gopt Opt_DoCoreLinting dflags)
+ = return ()
+ | Just err <- lintExpr (interactiveInScope hsc_env) expr
+ = do { display_lint_err err
+ ; Err.ghcExit dflags 1 }
+ | otherwise
+ = return ()
+ where
+ dflags = hsc_dflags hsc_env
+
+ display_lint_err err
+ = do { log_action dflags dflags Err.SevDump noSrcSpan defaultDumpStyle
+ (vcat [ lint_banner "errors" (text what)
+ , err
+ , ptext (sLit "*** Offending Program ***")
+ , pprCoreExpr expr
+ , ptext (sLit "*** End of Offense ***") ])
+ ; Err.ghcExit dflags 1 }
+
+interactiveInScope :: HscEnv -> [Var]
+-- In GHCi we may lint expressions, or bindings arising from 'deriving'
+-- clauses, that mention variables bound in the interactive context.
+-- These are Local things (see Note [Interactively-bound Ids in GHCi] in TcRnDriver).
+-- So we have to tell Lint about them, lest it reports them as out of scope.
+--
+-- We do this by find local-named things that may appear free in interactive
+-- context. This function is pretty revolting and quite possibly not quite right.
+-- When we are not in GHCi, the interactive context (hsc_IC hsc_env) is empty
+-- so this is a (cheap) no-op.
+--
+-- See Trac #8215 for an example
+interactiveInScope hsc_env
+ = tyvars ++ vars
+ where
+ ictxt = hsc_IC hsc_env
+ te = mkTypeEnvWithImplicits (ic_tythings ictxt ++ map AnId (ic_sys_vars ictxt))
+ vars = typeEnvIds te
+ tyvars = varSetElems $ tyThingsTyVars $ typeEnvElts $ te
+ -- Why the type variables? How can the top level envt have free tyvars?
+ -- I think it's becuase of the GHCi debugger, which can bind variables
+ -- f :: [t] -> [t]
+ -- where t is a RuntimeUnk (see TcType)
\end{code}
diff --git a/compiler/simplCore/OccurAnal.lhs b/compiler/simplCore/OccurAnal.lhs
index 75d5364f63..d17b0561f5 100644
--- a/compiler/simplCore/OccurAnal.lhs
+++ b/compiler/simplCore/OccurAnal.lhs
@@ -878,14 +878,13 @@ reOrderNodes depth bndr_set weak_fvs (node : nodes) binds
| isDFunId bndr = 9 -- Never choose a DFun as a loop breaker
-- Note [DFuns should not be loop breakers]
- | Just inl_source <- isStableCoreUnfolding_maybe (idUnfolding bndr)
- = case inl_source of
- InlineWrapper -> 10 -- Note [INLINE pragmas]
- _other -> 3 -- Data structures are more important than this
- -- so that dictionary/method recursion unravels
- -- Note that this case hits all InlineRule things, so we
- -- never look at 'rhs' for InlineRule stuff. That's right, because
- -- 'rhs' is irrelevant for inlining things with an InlineRule
+ | Just _ <- isStableCoreUnfolding_maybe (idUnfolding bndr)
+ = 3 -- Note [INLINE pragmas]
+ -- Data structures are more important than INLINE pragmas
+ -- so that dictionary/method recursion unravels
+ -- Note that this case hits all InlineRule things, so we
+ -- never look at 'rhs' for InlineRule stuff. That's right, because
+ -- 'rhs' is irrelevant for inlining things with an InlineRule
| is_con_app rhs = 5 -- Data types help with cases: Note [Constructor applications]
@@ -968,32 +967,37 @@ Avoid choosing a function with an INLINE pramga as the loop breaker!
If such a function is mutually-recursive with a non-INLINE thing,
then the latter should be the loop-breaker.
-Usually this is just a question of optimisation. But a particularly
-bad case is wrappers generated by the demand analyser: if you make
-then into a loop breaker you may get an infinite inlining loop. For
-example:
- rec {
- $wfoo x = ....foo x....
+ ----> Historical note, dating from when strictness wrappers
+ were generated from the strictness signatures:
- {-loop brk-} foo x = ...$wfoo x...
- }
-The interface file sees the unfolding for $wfoo, and sees that foo is
-strict (and hence it gets an auto-generated wrapper). Result: an
-infinite inlining in the importing scope. So be a bit careful if you
-change this. A good example is Tree.repTree in
-nofib/spectral/minimax. If the repTree wrapper is chosen as the loop
-breaker then compiling Game.hs goes into an infinite loop. This
-happened when we gave is_con_app a lower score than inline candidates:
-
- Tree.repTree
- = __inline_me (/\a. \w w1 w2 ->
- case Tree.$wrepTree @ a w w1 w2 of
- { (# ww1, ww2 #) -> Branch @ a ww1 ww2 })
- Tree.$wrepTree
- = /\a w w1 w2 ->
- (# w2_smP, map a (Tree a) (Tree.repTree a w1 w) (w w2) #)
-
-Here we do *not* want to choose 'repTree' as the loop breaker.
+ Usually this is just a question of optimisation. But a particularly
+ bad case is wrappers generated by the demand analyser: if you make
+ then into a loop breaker you may get an infinite inlining loop. For
+ example:
+ rec {
+ $wfoo x = ....foo x....
+
+ {-loop brk-} foo x = ...$wfoo x...
+ }
+ The interface file sees the unfolding for $wfoo, and sees that foo is
+ strict (and hence it gets an auto-generated wrapper). Result: an
+ infinite inlining in the importing scope. So be a bit careful if you
+ change this. A good example is Tree.repTree in
+ nofib/spectral/minimax. If the repTree wrapper is chosen as the loop
+ breaker then compiling Game.hs goes into an infinite loop. This
+ happened when we gave is_con_app a lower score than inline candidates:
+
+ Tree.repTree
+ = __inline_me (/\a. \w w1 w2 ->
+ case Tree.$wrepTree @ a w w1 w2 of
+ { (# ww1, ww2 #) -> Branch @ a ww1 ww2 })
+ Tree.$wrepTree
+ = /\a w w1 w2 ->
+ (# w2_smP, map a (Tree a) (Tree.repTree a w1 w) (w w2) #)
+
+ Here we do *not* want to choose 'repTree' as the loop breaker.
+
+ -----> End of historical note
Note [DFuns should not be loop breakers]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/compiler/simplCore/SimplCore.lhs b/compiler/simplCore/SimplCore.lhs
index a3101f715e..4b07d3bb1c 100644
--- a/compiler/simplCore/SimplCore.lhs
+++ b/compiler/simplCore/SimplCore.lhs
@@ -370,10 +370,11 @@ runCorePasses passes guts
do_pass guts CoreDoNothing = return guts
do_pass guts (CoreDoPasses ps) = runCorePasses ps guts
do_pass guts pass
- = do { dflags <- getDynFlags
+ = do { hsc_env <- getHscEnv
+ ; let dflags = hsc_dflags hsc_env
; liftIO $ showPass dflags pass
; guts' <- doCorePass dflags pass guts
- ; liftIO $ endPass dflags pass (mg_binds guts') (mg_rules guts')
+ ; liftIO $ endPass hsc_env pass (mg_binds guts') (mg_rules guts')
; return guts' }
doCorePass :: DynFlags -> CoreToDo -> ModGuts -> CoreM ModGuts
@@ -676,7 +677,8 @@ simplifyPgmIO pass@(CoreDoSimplify max_iterations mode)
let { binds2 = {-# SCC "ZapInd" #-} shortOutIndirections binds1 } ;
-- Dump the result of this iteration
- end_iteration dflags pass iteration_no counts1 binds2 rules1 ;
+ dump_end_iteration dflags iteration_no counts1 binds2 rules1 ;
+ lintPassResult hsc_env pass binds2 ;
-- Loop
do_iteration us2 (iteration_no + 1) (counts1:counts_so_far) binds2 rules1
@@ -693,11 +695,10 @@ simplifyPgmIO pass@(CoreDoSimplify max_iterations mode)
simplifyPgmIO _ _ _ _ _ = panic "simplifyPgmIO"
-------------------
-end_iteration :: DynFlags -> CoreToDo -> Int
+dump_end_iteration :: DynFlags -> Int
-> SimplCount -> CoreProgram -> [CoreRule] -> IO ()
-end_iteration dflags pass iteration_no counts binds rules
- = do { dumpPassResult dflags mb_flag hdr pp_counts binds rules
- ; lintPassResult dflags pass binds }
+dump_end_iteration dflags iteration_no counts binds rules
+ = dumpPassResult dflags mb_flag hdr pp_counts binds rules
where
mb_flag | dopt Opt_D_dump_simpl_iterations dflags = Just Opt_D_dump_simpl_phases
| otherwise = Nothing
diff --git a/compiler/specialise/Specialise.lhs b/compiler/specialise/Specialise.lhs
index bf73bec240..a175e5ed4b 100644
--- a/compiler/specialise/Specialise.lhs
+++ b/compiler/specialise/Specialise.lhs
@@ -10,7 +10,7 @@ module Specialise ( specProgram ) where
import Id
import TcType hiding( substTy, extendTvSubstList )
-import Type( TyVar, isDictTy, mkPiTypes, classifyPredType, PredTree(..), isIPClass )
+import Type hiding( substTy, extendTvSubstList )
import Coercion( Coercion )
import CoreMonad
import qualified CoreSubst
@@ -1614,10 +1614,10 @@ mkCallUDs env f args
_trace_doc = vcat [ppr f, ppr args, ppr n_tyvars, ppr n_dicts
, ppr (map (interestingDict env) dicts)]
(tyvars, theta, _) = tcSplitSigmaTy (idType f)
- constrained_tyvars = tyVarsOfTypes theta
+ constrained_tyvars = closeOverKinds (tyVarsOfTypes theta)
n_tyvars = length tyvars
n_dicts = length theta
-
+
spec_tys = [mk_spec_ty tv ty | (tv, Type ty) <- tyvars `zip` args]
dicts = [dict_expr | (_, dict_expr) <- theta `zip` (drop n_tyvars args)]
diff --git a/compiler/typecheck/TcBinds.lhs b/compiler/typecheck/TcBinds.lhs
index b8bef9e0b2..2a33955148 100644
--- a/compiler/typecheck/TcBinds.lhs
+++ b/compiler/typecheck/TcBinds.lhs
@@ -559,9 +559,8 @@ mkExport prag_fn qtvs theta (poly_name, mb_sig, mono_id)
-- In the inference case (no signature) this stuff figures out
-- the right type variables and theta to quantify over
-- See Note [Impedence matching]
- my_tvs1 = growThetaTyVars theta (tyVarsOfType mono_ty)
- my_tvs2 = foldVarSet (\tv tvs -> tyVarsOfType (tyVarKind tv) `unionVarSet` tvs)
- my_tvs1 my_tvs1 -- Add kind variables! Trac #7916
+ my_tvs2 = closeOverKinds (growThetaTyVars theta (tyVarsOfType mono_ty))
+ -- Include kind variables! Trac #7916
my_tvs = filter (`elemVarSet` my_tvs2) qtvs -- Maintain original order
my_theta = filter (quantifyPred my_tvs2) theta
inferred_poly_ty = mkSigmaTy my_tvs my_theta mono_ty
diff --git a/compiler/typecheck/TcInstDcls.lhs b/compiler/typecheck/TcInstDcls.lhs
index 1481b2552d..9f89afe0af 100644
--- a/compiler/typecheck/TcInstDcls.lhs
+++ b/compiler/typecheck/TcInstDcls.lhs
@@ -409,7 +409,7 @@ tcInstDecls1 tycl_decls inst_decls deriv_decls
-- Remove any handwritten instance of poly-kinded Typeable and warn
; dflags <- getDynFlags
; when (wopt Opt_WarnTypeableInstances dflags) $
- mapM_ (addWarnTc . instMsg) typeable_instances
+ mapM_ (failWithTc . instMsg) typeable_instances
-- Check that if the module is compiled with -XSafe, there are no
-- hand written instances of old Typeable as then unsafe casts could be
@@ -444,7 +444,7 @@ tcInstDecls1 tycl_decls inst_decls deriv_decls
typInstErr = ptext $ sLit $ "Can't create hand written instances of Typeable in Safe"
++ " Haskell! Can only derive them"
- instMsg i = hang (ptext (sLit $ "Typeable instances can only be derived; ignoring "
+ instMsg i = hang (ptext (sLit $ "Typeable instances can only be derived; replace "
++ "the following instance:"))
2 (pprInstance (iSpec i))
diff --git a/compiler/typecheck/TcMType.lhs b/compiler/typecheck/TcMType.lhs
index 481cb89ab0..6049d5be9f 100644
--- a/compiler/typecheck/TcMType.lhs
+++ b/compiler/typecheck/TcMType.lhs
@@ -511,11 +511,9 @@ quantifyTyVars :: TcTyVarSet -> TcTyVarSet -> TcM [TcTyVar]
quantifyTyVars gbl_tvs tkvs
= do { tkvs <- zonkTyVarsAndFV tkvs
; gbl_tvs <- zonkTyVarsAndFV gbl_tvs
- ; let (kvs1, tvs) = partitionVarSet isKindVar (tkvs `minusVarSet` gbl_tvs)
- kvs2 = varSetElems (foldVarSet add_kvs kvs1 tvs
- `minusVarSet` gbl_tvs )
- add_kvs tv kvs = tyVarsOfType (tyVarKind tv) `unionVarSet` kvs
+ ; let (kvs, tvs) = partitionVarSet isKindVar (closeOverKinds tkvs `minusVarSet` gbl_tvs)
-- NB kinds of tvs are zonked by zonkTyVarsAndFV
+ kvs2 = varSetElems kvs
qtvs = varSetElems tvs
-- In the non-PolyKinds case, default the kind variables
diff --git a/compiler/typecheck/TcSMonad.lhs b/compiler/typecheck/TcSMonad.lhs
index 0b2e484f7a..5674b47ee2 100644
--- a/compiler/typecheck/TcSMonad.lhs
+++ b/compiler/typecheck/TcSMonad.lhs
@@ -1639,6 +1639,7 @@ matchOpenFam :: TyCon -> [Type] -> TcS (Maybe FamInstMatch)
matchOpenFam tycon args = wrapTcS $ tcLookupFamInst tycon args
matchFam :: TyCon -> [Type] -> TcS (Maybe (TcCoercion, TcType))
+-- Given (F tys) return (ty, co), where co :: F tys ~ ty
matchFam tycon args
| isOpenSynFamilyTyCon tycon
= do { maybe_match <- matchOpenFam tycon args
diff --git a/compiler/typecheck/TcTyClsDecls.lhs b/compiler/typecheck/TcTyClsDecls.lhs
index 70e72f593f..f4e4dabd1b 100644
--- a/compiler/typecheck/TcTyClsDecls.lhs
+++ b/compiler/typecheck/TcTyClsDecls.lhs
@@ -1524,14 +1524,16 @@ checkValidRoles tc
= return ()
where
check_dc_roles datacon
- = let univ_tvs = dataConUnivTyVars datacon
- ex_tvs = dataConExTyVars datacon
- args = dataConRepArgTys datacon
- univ_roles = zipVarEnv univ_tvs (tyConRoles tc)
+ = do { traceTc "check_dc_roles" (ppr datacon <+> ppr (tyConRoles tc))
+ ; mapM_ (check_ty_roles role_env Representational) $
+ eqSpecPreds eq_spec ++ theta ++ arg_tys }
+ -- See Note [Role-checking data constructor arguments] in TcTyDecls
+ where
+ (univ_tvs, ex_tvs, eq_spec, theta, arg_tys, _res_ty) = dataConFullSig datacon
+ univ_roles = zipVarEnv univ_tvs (tyConRoles tc)
-- zipVarEnv uses zipEqual, but we don't want that for ex_tvs
- ex_roles = mkVarEnv (zip ex_tvs (repeat Nominal))
- role_env = univ_roles `plusVarEnv` ex_roles in
- mapM_ (check_ty_roles role_env Representational) args
+ ex_roles = mkVarEnv (zip ex_tvs (repeat Nominal))
+ role_env = univ_roles `plusVarEnv` ex_roles
check_ty_roles env role (TyVarTy tv)
= case lookupVarEnv env tv of
diff --git a/compiler/typecheck/TcTyDecls.lhs b/compiler/typecheck/TcTyDecls.lhs
index bea2cd19be..5091cab802 100644
--- a/compiler/typecheck/TcTyDecls.lhs
+++ b/compiler/typecheck/TcTyDecls.lhs
@@ -615,6 +615,19 @@ roles(~#) = N, N
With -dcore-lint on, the output of this algorithm is checked in checkValidRoles,
called from checkValidTycon.
+Note [Role-checking data constructor arguments]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider
+ data T a where
+ MkT :: Eq b => F a -> (a->a) -> T (G a)
+
+Then we want to check the roles at which 'a' is used
+in MkT's type. We want to work on the user-written type,
+so we need to take into account
+ * the arguments: (F a) and (a->a)
+ * the context: C a b
+ * the result type: (G a) -- this is in the eq_spec
+
\begin{code}
type RoleEnv = NameEnv [Role] -- from tycon names to roles
type RoleAnnots = NameEnv [Maybe Role] -- from tycon names to role annotations,
@@ -695,9 +708,12 @@ irClass tc_name cls
-- See Note [Role inference]
irDataCon :: Name -> DataCon -> RoleM ()
irDataCon tc_name datacon
- = addRoleInferenceInfo tc_name (dataConUnivTyVars datacon) $
- let ex_var_set = mkVarSet $ dataConExTyVars datacon in
- mapM_ (irType ex_var_set) (dataConRepArgTys datacon)
+ = addRoleInferenceInfo tc_name univ_tvs $
+ mapM_ (irType ex_var_set) (eqSpecPreds eq_spec ++ theta ++ arg_tys)
+ -- See Note [Role-checking data constructor arguments]
+ where
+ (univ_tvs, ex_tvs, eq_spec, theta, arg_tys, _res_ty) = dataConFullSig datacon
+ ex_var_set = mkVarSet ex_tvs
irType :: VarSet -> Type -> RoleM ()
irType = go
diff --git a/compiler/typecheck/TcType.lhs b/compiler/typecheck/TcType.lhs
index 8a8de41159..af67808044 100644
--- a/compiler/typecheck/TcType.lhs
+++ b/compiler/typecheck/TcType.lhs
@@ -142,7 +142,7 @@ module TcType (
isUnboxedTupleType, -- Ditto
isPrimitiveType,
- tyVarsOfType, tyVarsOfTypes,
+ tyVarsOfType, tyVarsOfTypes, closeOverKinds,
tcTyVarsOfType, tcTyVarsOfTypes,
pprKind, pprParendKind, pprSigmaType,
diff --git a/compiler/typecheck/TcValidity.lhs b/compiler/typecheck/TcValidity.lhs
index 968d8695cc..1d68ede3b7 100644
--- a/compiler/typecheck/TcValidity.lhs
+++ b/compiler/typecheck/TcValidity.lhs
@@ -70,21 +70,23 @@ checkAmbiguity ctxt ty
| otherwise
= do { allow_ambiguous <- xoptM Opt_AllowAmbiguousTypes
; unless allow_ambiguous $
- do {(subst, _tvs) <- tcInstSkolTyVars (varSetElems (tyVarsOfType ty))
+ do { traceTc "Ambiguity check for" (ppr ty)
+ ; (subst, _tvs) <- tcInstSkolTyVars (varSetElems (tyVarsOfType ty))
; let ty' = substTy subst ty
-- The type might have free TyVars,
-- so we skolemise them as TcTyVars
-- Tiresome; but the type inference engine expects TcTyVars
- ; (_wrap, wanted) <- addErrCtxtM (mk_msg ty') $
- captureConstraints $
- tcSubType (AmbigOrigin ctxt) ctxt ty' ty'
-- Solve the constraints eagerly because an ambiguous type
- -- can cause a cascade of further errors. The free tyvars
- -- are skolemised, so we can safely use tcSimplifyTop
- ; _ev_binds <- simplifyTop wanted
-
- ; return () } }
+ -- can cause a cascade of further errors. Since the free
+ -- tyvars are skolemised, we can safely use tcSimplifyTop
+ ; addErrCtxtM (mk_msg ty') $
+ do { (_wrap, wanted) <- captureConstraints $
+ tcSubType (AmbigOrigin ctxt) ctxt ty' ty'
+ ; _ev_binds <- simplifyTop wanted
+ ; return () }
+
+ ; traceTc "Done ambiguity check for" (ppr ty) } }
where
mk_msg ty tidy_env
= return (tidy_env', msg)
@@ -174,7 +176,8 @@ checkValidType ctxt ty
-- Check that the thing has kind Type, and is lifted if necessary
-- Do this second, because we can't usefully take the kind of an
-- ill-formed type such as (a~Int)
- ; check_kind ctxt ty }
+ ; check_kind ctxt ty
+ ; traceTc "checkValidType done" (ppr ty <+> text "::" <+> ppr (typeKind ty)) }
checkValidMonoType :: Type -> TcM ()
checkValidMonoType ty = check_mono_type SigmaCtxt MustBeMonoType ty
diff --git a/compiler/types/Coercion.lhs b/compiler/types/Coercion.lhs
index 6cda16b9ec..b0da3edd53 100644
--- a/compiler/types/Coercion.lhs
+++ b/compiler/types/Coercion.lhs
@@ -802,7 +802,7 @@ isReflCo_maybe _ = Nothing
mkCoVarCo :: CoVar -> Coercion
-- cv :: s ~# t
mkCoVarCo cv
- | ty1 `eqType` ty2 = Refl Nominal ty1
+ | ty1 `eqType` ty2 = Refl (coVarRole cv) ty1
| otherwise = CoVarCo cv
where
(ty1, ty2) = ASSERT( isCoVar cv ) coVarKind cv
@@ -1360,8 +1360,7 @@ subst_co subst co
substCoVar :: CvSubst -> CoVar -> Coercion
substCoVar (CvSubst in_scope _ cenv) cv
- | Just co <- lookupVarEnv cenv cv = ASSERT2( coercionRole co == Nominal, ppr co )
- co
+ | Just co <- lookupVarEnv cenv cv = co
| Just cv1 <- lookupInScope in_scope cv = ASSERT( isCoVar cv1 ) CoVarCo cv1
| otherwise = WARN( True, ptext (sLit "substCoVar not in scope") <+> ppr cv $$ ppr in_scope)
ASSERT( isCoVar cv ) CoVarCo cv
diff --git a/compiler/types/Type.lhs b/compiler/types/Type.lhs
index 8596dde439..5753aba0c1 100644
--- a/compiler/types/Type.lhs
+++ b/compiler/types/Type.lhs
@@ -85,7 +85,7 @@ module Type (
constraintKindTyCon, anyKindTyCon,
-- * Type free variables
- tyVarsOfType, tyVarsOfTypes,
+ tyVarsOfType, tyVarsOfTypes, closeOverKinds,
expandTypeSynonyms,
typeSize, varSetElemsKvsFirst,
@@ -171,7 +171,6 @@ import Util
import Outputable
import FastString
-import Data.List ( partition )
import Maybes ( orElse )
import Data.Maybe ( isJust )
import Control.Monad ( guard )
@@ -995,13 +994,6 @@ typeSize (AppTy t1 t2) = typeSize t1 + typeSize t2
typeSize (FunTy t1 t2) = typeSize t1 + typeSize t2
typeSize (ForAllTy _ t) = 1 + typeSize t
typeSize (TyConApp _ ts) = 1 + sum (map typeSize ts)
-
-varSetElemsKvsFirst :: VarSet -> [TyVar]
--- {k1,a,k2,b} --> [k1,k2,a,b]
-varSetElemsKvsFirst set
- = kvs ++ tvs
- where
- (kvs, tvs) = partition isKindVar (varSetElems set)
\end{code}
diff --git a/compiler/types/TypeRep.lhs b/compiler/types/TypeRep.lhs
index cb5b8f0f18..2b127369d4 100644
--- a/compiler/types/TypeRep.lhs
+++ b/compiler/types/TypeRep.lhs
@@ -45,7 +45,7 @@ module TypeRep (
pprPrefixApp, pprArrowChain, ppr_type,
-- Free variables
- tyVarsOfType, tyVarsOfTypes,
+ tyVarsOfType, tyVarsOfTypes, closeOverKinds, varSetElemsKvsFirst,
-- * Tidying type related things up for printing
tidyType, tidyTypes,
@@ -85,7 +85,7 @@ import StaticFlags( opt_PprStyle_Debug )
import Util
-- libraries
-import Data.List( mapAccumL )
+import Data.List( mapAccumL, partition )
import qualified Data.Data as Data hiding ( TyCon )
\end{code}
@@ -327,6 +327,20 @@ tyVarsOfType (ForAllTy tyvar ty) = delVarSet (tyVarsOfType ty) tyvar
tyVarsOfTypes :: [Type] -> TyVarSet
tyVarsOfTypes tys = foldr (unionVarSet . tyVarsOfType) emptyVarSet tys
+
+closeOverKinds :: TyVarSet -> TyVarSet
+-- Add the kind variables free in the kinds
+-- of the tyvars in the given set
+closeOverKinds tvs
+ = foldVarSet (\tv ktvs -> tyVarsOfType (tyVarKind tv) `unionVarSet` ktvs)
+ tvs tvs
+
+varSetElemsKvsFirst :: VarSet -> [TyVar]
+-- {k1,a,k2,b} --> [k1,k2,a,b]
+varSetElemsKvsFirst set
+ = kvs ++ tvs
+ where
+ (kvs, tvs) = partition isKindVar (varSetElems set)
\end{code}
%************************************************************************
diff --git a/docs/users_guide/7.8.1-notes.xml b/docs/users_guide/7.8.1-notes.xml
index 4719403e66..85d2f61053 100644
--- a/docs/users_guide/7.8.1-notes.xml
+++ b/docs/users_guide/7.8.1-notes.xml
@@ -236,7 +236,7 @@
dynamically-linkable <literal>.dyn_o</literal>
file. The output suffix of the dynamic objects can
be controlled by the flag
- <literal>-dyno</literal>.
+ <literal>-dynosuf</literal>.
</para>
<para>
@@ -318,6 +318,23 @@
<itemizedlist>
<listitem>
<para>
+ The RTS linker can now unload object code at
+ runtime (when using the GHC API
+ <literal>ObjLink</literal> module.) Previously,
+ GHC would not unload the old object file, causing
+ a gradual memory leak as more objects were loaded
+ over time.
+ </para>
+
+ <para>
+ Note that this change in unloading behavior
+ <emphasis>only</emphasis> affects statically
+ linked binaries, and not dynamic ones.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
The performance of <literal>StablePtr</literal>s and
<literal>StableName</literal>s has been improved.
</para>
diff --git a/docs/users_guide/flags.xml b/docs/users_guide/flags.xml
index 648180c184..ee577e6ead 100644
--- a/docs/users_guide/flags.xml
+++ b/docs/users_guide/flags.xml
@@ -699,23 +699,10 @@
<entry><option>-fno-glasgow-exts</option></entry>
</row>
<row>
- <entry><option>-XOverlappingInstances</option></entry>
- <entry>Enable <link linkend="instance-overlap">overlapping instances</link></entry>
- <entry>dynamic</entry>
- <entry><option>-XNoOverlappingInstances</option></entry>
- </row>
- <row>
- <entry><option>-XIncoherentInstances</option></entry>
- <entry>Enable <link linkend="instance-overlap">incoherent instances</link>.
- Implies <option>-XOverlappingInstances</option> </entry>
- <entry>dynamic</entry>
- <entry><option>-XNoIncoherentInstances</option></entry>
- </row>
- <row>
- <entry><option>-XUndecidableInstances</option></entry>
- <entry>Enable <link linkend="undecidable-instances">undecidable instances</link></entry>
+ <entry><option>-firrefutable-tuples</option></entry>
+ <entry>Make tuple pattern matching irrefutable</entry>
<entry>dynamic</entry>
- <entry><option>-XNoUndecidableInstances</option></entry>
+ <entry><option>-fno-irrefutable-tuples</option></entry>
</row>
<row>
<entry><option>-fcontext-stack=N</option><replaceable>n</replaceable></entry>
@@ -724,6 +711,14 @@
<entry></entry>
</row>
<row>
+ <entry><option>-XAllowAmbiguousTypes</option></entry>
+ <entry>Allow the user to write <link linkend="ambiguity">ambiguous types</link>,
+ and the type inference engine to infer them.
+ </entry>
+ <entry>dynamic</entry>
+ <entry><option>-XNoAllowAmbiguousTypes</option></entry>
+ </row>
+ <row>
<entry><option>-XArrows</option></entry>
<entry>Enable <link linkend="arrow-notation">arrow
notation</link> extension</entry>
@@ -731,6 +726,43 @@
<entry><option>-XNoArrows</option></entry>
</row>
<row>
+ <entry><option>-XAutoDeriveTypeable</option></entry>
+ <entry>Automatically <link linkend="auto-derive-typeable">derive Typeable instances for every datatype and type class declaration</link>.
+ Implies <option>-XDeriveDataTypeable</option>.</entry>
+ <entry>dynamic</entry>
+ <entry><option>-XNoAutoDeriveTypeable</option></entry>
+ </row>
+ <row>
+ <entry><option>-XConstraintKinds</option></entry>
+ <entry>Enable a <link linkend="constraint-kind">kind of constraints</link>.</entry>
+ <entry>dynamic</entry>
+ <entry><option>-XNoConstraintKinds</option></entry>
+ </row>
+ <row>
+ <entry><option>-XDataKinds</option></entry>
+ <entry>Enable <link linkend="promotion">datatype promotion</link>.</entry>
+ <entry>dynamic</entry>
+ <entry><option>-XNoDataKinds</option></entry>
+ </row>
+ <row>
+ <entry><option>-XDeriveDataTypeable</option></entry>
+ <entry>Enable <link linkend="deriving-typeable">deriving for the Data and Typeable classes</link>.</entry>
+ <entry>dynamic</entry>
+ <entry><option>-XNoDeriveDataTypeable</option></entry>
+ </row>
+ <row>
+ <entry><option>-XDeriveGeneric</option></entry>
+ <entry>Enable <link linkend="deriving-typeable">deriving for the Generic class</link>.</entry>
+ <entry>dynamic</entry>
+ <entry><option>-XNoDeriveGeneric</option></entry>
+ </row>
+ <row>
+ <entry><option>-XGeneralizedNewtypeDeriving</option></entry>
+ <entry>Enable <link linkend="newtype-deriving">newtype deriving</link>.</entry>
+ <entry>dynamic</entry>
+ <entry><option>-XNoGeneralizedNewtypeDeriving</option></entry>
+ </row>
+ <row>
<entry><option>-XDisambiguateRecordFields</option></entry>
<entry>Enable <link linkend="disambiguate-fields">record
field disambiguation</link></entry>
@@ -738,6 +770,19 @@
<entry><option>-XNoDisambiguateRecordFields</option></entry>
</row>
<row>
+ <entry><option>-XEmptyCase</option></entry>
+ <entry>Allow <link linkend="empty-case">empty case alternatives</link>
+ </entry>
+ <entry>dynamic</entry>
+ <entry><option>-XNoEmptyCase</option></entry>
+ </row>
+ <row>
+ <entry><option>-XExtendedDefaultRules</option></entry>
+ <entry>Use GHCi's <link linkend="extended-default-rules">extended default rules</link> in a normal module</entry>
+ <entry>dynamic</entry>
+ <entry><option>-XNoExtendedDefaultRules</option></entry>
+ </row>
+ <row>
<entry><option>-XForeignFunctionInterface</option></entry>
<entry>Enable <link linkend="ffi">foreign function interface</link> (implied by
<option>-fglasgow-exts</option>)</entry>
@@ -745,6 +790,20 @@
<entry><option>-XNoForeignFunctionInterface</option></entry>
</row>
<row>
+ <entry><option>-XGADTs</option></entry>
+ <entry>Enable <link linkend="gadt">generalised algebraic data types</link>.
+ </entry>
+ <entry>dynamic</entry>
+ <entry><option>-XNoGADTs</option></entry>
+ </row>
+ <row>
+ <entry><option>-XGADTSyntax</option></entry>
+ <entry>Enable <link linkend="gadt-style">generalised algebraic data type syntax</link>.
+ </entry>
+ <entry>dynamic</entry>
+ <entry><option>-XNoGADTSyntax</option></entry>
+ </row>
+ <row>
<entry><option>-XGenerics</option></entry>
<entry>Deprecated, does nothing. No longer enables <link linkend="generic-classes">generic classes</link>.
See also GHC's support for
@@ -760,22 +819,17 @@
<entry><option>-XNoImplicitParams</option></entry>
</row>
<row>
- <entry><option>-firrefutable-tuples</option></entry>
- <entry>Make tuple pattern matching irrefutable</entry>
- <entry>dynamic</entry>
- <entry><option>-fno-irrefutable-tuples</option></entry>
- </row>
- <row>
<entry><option>-XNoImplicitPrelude</option></entry>
<entry>Don't implicitly <literal>import Prelude</literal></entry>
<entry>dynamic</entry>
<entry><option>-XImplicitPrelude</option></entry>
</row>
<row>
- <entry><option>-XRebindableSyntax</option></entry>
- <entry>Employ <link linkend="rebindable-syntax">rebindable syntax</link></entry>
+ <entry><option>-XIncoherentInstances</option></entry>
+ <entry>Enable <link linkend="instance-overlap">incoherent instances</link>.
+ Implies <option>-XOverlappingInstances</option> </entry>
<entry>dynamic</entry>
- <entry><option>-XNoRebindableSyntax</option></entry>
+ <entry><option>-XNoIncoherentInstances</option></entry>
</row>
<row>
<entry><option>-XNoMonomorphismRestriction</option></entry>
@@ -784,16 +838,16 @@
<entry><option>-XMonomorphismRrestriction</option></entry>
</row>
<row>
- <entry><option>-XNoNPlusKPatterns</option></entry>
- <entry>Disable support for <literal>n+k</literal> patterns</entry>
+ <entry><option>-XNegativeLiterals</option></entry>
+ <entry>Enable support for <link linkend="negative-literals">negative literals</link></entry>
<entry>dynamic</entry>
- <entry><option>-XNPlusKPatterns</option></entry>
+ <entry><option>-XNoNegativeLiterals</option></entry>
</row>
<row>
- <entry><option>-XNegativeLiterals</option></entry>
- <entry>Enable support for negative literals</entry>
+ <entry><option>-XNoNPlusKPatterns</option></entry>
+ <entry>Disable support for <literal>n+k</literal> patterns</entry>
<entry>dynamic</entry>
- <entry><option>-XNoNegativeLiterals</option></entry>
+ <entry><option>-XNPlusKPatterns</option></entry>
</row>
<row>
<entry><option>-XNumDecimals</option></entry>
@@ -802,22 +856,17 @@
<entry><option>-XNoNumDecimals</option></entry>
</row>
<row>
- <entry><option>-XNoTraditionalRecordSyntax</option></entry>
- <entry>Disable support for traditional record syntax (as supported by Haskell 98) <literal>C {f = x}</literal></entry>
- <entry>dynamic</entry>
- <entry><option>-XTraditionalRecordSyntax</option></entry>
- </row>
- <row>
- <entry><option>-XRelaxedPolyRec</option></entry>
- <entry>Relaxed checking for <link linkend="typing-binds">mutually-recursive polymorphic functions</link></entry>
+ <entry><option>-XOverlappingInstances</option></entry>
+ <entry>Enable <link linkend="instance-overlap">overlapping instances</link></entry>
<entry>dynamic</entry>
- <entry><option>-XNoRelaxedPolyRec</option></entry>
+ <entry><option>-XNoOverlappingInstances</option></entry>
</row>
<row>
- <entry><option>-XExtendedDefaultRules</option></entry>
- <entry>Use GHCi's <link linkend="extended-default-rules">extended default rules</link> in a normal module</entry>
+ <entry><option>-XOverloadedLists</option></entry>
+ <entry>Enable <link linkend="overloaded-lists">overloaded lists</link>.
+ </entry>
<entry>dynamic</entry>
- <entry><option>-XNoExtendedDefaultRules</option></entry>
+ <entry><option>-XNoOverloadedLists</option></entry>
</row>
<row>
<entry><option>-XOverloadedStrings</option></entry>
@@ -827,25 +876,22 @@
<entry><option>-XNoOverloadedStrings</option></entry>
</row>
<row>
- <entry><option>-XOverloadedLists</option></entry>
- <entry>Enable <link linkend="overloaded-lists">overloaded lists</link>.
- </entry>
+ <entry><option>-XQuasiQuotes</option></entry>
+ <entry>Enable <link linkend="th-quasiquotation">quasiquotation</link>.</entry>
<entry>dynamic</entry>
- <entry><option>-XNoOverloadedLists</option></entry>
+ <entry><option>-XNoQuasiQuotes</option></entry>
</row>
<row>
- <entry><option>-XGADTs</option></entry>
- <entry>Enable <link linkend="gadt">generalised algebraic data types</link>.
- </entry>
+ <entry><option>-XRelaxedPolyRec</option></entry>
+ <entry>Relaxed checking for <link linkend="typing-binds">mutually-recursive polymorphic functions</link></entry>
<entry>dynamic</entry>
- <entry><option>-XNoGADTs</option></entry>
+ <entry><option>-XNoRelaxedPolyRec</option></entry>
</row>
<row>
- <entry><option>-XGADTSyntax</option></entry>
- <entry>Enable <link linkend="gadt-style">generalised algebraic data type syntax</link>.
- </entry>
+ <entry><option>-XNoTraditionalRecordSyntax</option></entry>
+ <entry>Disable support for traditional record syntax (as supported by Haskell 98) <literal>C {f = x}</literal></entry>
<entry>dynamic</entry>
- <entry><option>-XNoGADTSyntax</option></entry>
+ <entry><option>-XTraditionalRecordSyntax</option></entry>
</row>
<row>
<entry><option>-XTypeFamilies</option></entry>
@@ -854,16 +900,10 @@
<entry><option>-XNoTypeFamilies</option></entry>
</row>
<row>
- <entry><option>-XConstraintKinds</option></entry>
- <entry>Enable a <link linkend="constraint-kind">kind of constraints</link>.</entry>
- <entry>dynamic</entry>
- <entry><option>-XNoConstraintKinds</option></entry>
- </row>
- <row>
- <entry><option>-XDataKinds</option></entry>
- <entry>Enable <link linkend="promotion">datatype promotion</link>.</entry>
+ <entry><option>-XUndecidableInstances</option></entry>
+ <entry>Enable <link linkend="undecidable-instances">undecidable instances</link></entry>
<entry>dynamic</entry>
- <entry><option>-XNoDataKinds</option></entry>
+ <entry><option>-XNoUndecidableInstances</option></entry>
</row>
<row>
<entry><option>-XPolyKinds</option></entry>
@@ -873,13 +913,6 @@
<entry><option>-XNoPolyKinds</option></entry>
</row>
<row>
- <entry><option>-XScopedTypeVariables</option></entry>
- <entry>Enable <link linkend="scoped-type-variables">lexically-scoped type variables</link>.
- Implied by <option>-fglasgow-exts</option>.</entry>
- <entry>dynamic</entry>
- <entry><option>-XNoScopedTypeVariables</option></entry>
- </row>
- <row>
<entry><option>-XMonoLocalBinds</option></entry>
<entry>Enable <link linkend="mono-local-binds">do not generalise local bindings</link>.
Implied by <option>-XTypeFamilies</option> and <option>-XGADTs</option>.
@@ -888,6 +921,19 @@
<entry><option>-XNoMonoLocalBinds</option></entry>
</row>
<row>
+ <entry><option>-XRebindableSyntax</option></entry>
+ <entry>Employ <link linkend="rebindable-syntax">rebindable syntax</link></entry>
+ <entry>dynamic</entry>
+ <entry><option>-XNoRebindableSyntax</option></entry>
+ </row>
+ <row>
+ <entry><option>-XScopedTypeVariables</option></entry>
+ <entry>Enable <link linkend="scoped-type-variables">lexically-scoped type variables</link>.
+ Implied by <option>-fglasgow-exts</option>.</entry>
+ <entry>dynamic</entry>
+ <entry><option>-XNoScopedTypeVariables</option></entry>
+ </row>
+ <row>
<entry><option>-XTemplateHaskell</option></entry>
<entry>Enable <link linkend="template-haskell">Template Haskell</link>.
No longer implied by <option>-fglasgow-exts</option>.</entry>
@@ -895,12 +941,6 @@
<entry><option>-XNoTemplateHaskell</option></entry>
</row>
<row>
- <entry><option>-XQuasiQuotes</option></entry>
- <entry>Enable <link linkend="th-quasiquotation">quasiquotation</link>.</entry>
- <entry>dynamic</entry>
- <entry><option>-XNoQuasiQuotes</option></entry>
- </row>
- <row>
<entry><option>-XBangPatterns</option></entry>
<entry>Enable <link linkend="bang-patterns">bang patterns</link>.</entry>
<entry>dynamic</entry>
@@ -1033,7 +1073,9 @@
</row>
<row>
<entry><option>-XExplicitNamespaces</option></entry>
- <entry>Enable using the keyword <literal>type</literal> to specify the namespace of entries in imports and exports.</entry>
+ <entry>Enable using the keyword <literal>type</literal> to specify the namespace of
+ entries in imports and exports (<xref linkend="explicit-namespaces"/>).
+ Implied by <option>-XTypeOperators</option> and <option>-XTypeFamilies</option>.</entry>
<entry>dynamic</entry>
<entry><option>-XNoExplicitNamespaces</option></entry>
</row>
@@ -1080,31 +1122,6 @@
<entry><option>-XNoStandaloneDeriving</option></entry>
</row>
<row>
- <entry><option>-XDeriveDataTypeable</option></entry>
- <entry>Enable <link linkend="deriving-typeable">deriving for the Data and Typeable classes</link>.</entry>
- <entry>dynamic</entry>
- <entry><option>-XNoDeriveDataTypeable</option></entry>
- </row>
- <row>
- <entry><option>-XAutoDeriveTypeable</option></entry>
- <entry>Automatically <link linkend="auto-derive-typeable">derive Typeable instances for every datatype and type class declaration</link>.
- Implies <option>-XDeriveDataTypeable</option>.</entry>
- <entry>dynamic</entry>
- <entry><option>-XNoAutoDeriveTypeable</option></entry>
- </row>
- <row>
- <entry><option>-XDeriveGeneric</option></entry>
- <entry>Enable <link linkend="deriving-typeable">deriving for the Generic class</link>.</entry>
- <entry>dynamic</entry>
- <entry><option>-XNoDeriveGeneric</option></entry>
- </row>
- <row>
- <entry><option>-XGeneralizedNewtypeDeriving</option></entry>
- <entry>Enable <link linkend="newtype-deriving">newtype deriving</link>.</entry>
- <entry>dynamic</entry>
- <entry><option>-XNoGeneralizedNewtypeDeriving</option></entry>
- </row>
- <row>
<entry><option>-XTypeSynonymInstances</option></entry>
<entry>Enable <link linkend="flexible-instance-head">type synonyms in instance heads</link>.</entry>
<entry>dynamic</entry>
@@ -1190,14 +1207,14 @@
<entry><option>-</option></entry>
</row>
<row>
- <entry><option>-fpackage-trust</option></entry>
- <entry>Enable <link linkend="safe-haskell">Safe Haskell</link> trusted package requirement for trustworty modules.</entry>
+ <entry><option>-XTypeHoles</option></entry>
+ <entry>Enable <link linkend="type-holes">holes</link> in expressions.</entry>
<entry>dynamic</entry>
- <entry><option>-</option></entry>
+ <entry><option>--XNoTypeHoles</option></entry>
</row>
<row>
- <entry><option>-XTypeHoles</option></entry>
- <entry>Enable <link linkend="type-holes">holes</link> in expressions.</entry>
+ <entry><option>-fpackage-trust</option></entry>
+ <entry>Enable <link linkend="safe-haskell">Safe Haskell</link> trusted package requirement for trustworty modules.</entry>
<entry>dynamic</entry>
<entry><option>-</option></entry>
</row>
diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml
index 46e4cbdb01..c825da90c7 100644
--- a/docs/users_guide/glasgow_exts.xml
+++ b/docs/users_guide/glasgow_exts.xml
@@ -2112,6 +2112,36 @@ import safe qualified Network.Socket as NS
</sect2>
+<sect2 id="explicit-namespaces">
+<title>Explicit namespaces in import/export</title>
+
+<para> In an import or export list, such as
+<programlisting>
+ module M( f, (++) ) where ...
+ import N( f, (++) )
+ ...
+</programlisting>
+the entities <literal>f</literal> and <literal>(++)</literal> are <emphasis>values</emphasis>.
+However, with type operators (<xref linkend="type-operators"/>) it becomes possible
+to declare <literal>(++)</literal> as a <emphasis>type constructor</emphasis>. In that
+case, how would you export or import it?
+</para>
+<para>
+The <option>-XExplicitNamespaces</option> extension allows you to prefix the name of
+a type constructor in an import or export list with "<literal>type</literal>" to
+disambiguate this case, thus:
+<programlisting>
+ module M( f, type (++) ) where ...
+ import N( f, type (++) )
+ ...
+ module N( f, type (++) ) where
+ data family a ++ b = L a | R b
+</programlisting>
+The extension <option>-XExplicitNamespaces</option>
+is implied by <option>-XTypeOperators</option> and (for some reason) by <option>-XTypeFamilies</option>.
+</para>
+</sect2>
+
<sect2 id="syntax-stolen">
<title>Summary of stolen syntax</title>
@@ -2385,11 +2415,13 @@ There is now some potential ambiguity in import and export lists; for example
if you write <literal>import M( (+) )</literal> do you mean the
<emphasis>function</emphasis> <literal>(+)</literal> or the
<emphasis>type constructor</emphasis> <literal>(+)</literal>?
-The default is the former, but GHC allows you to specify the latter
+The default is the former, but with <option>-XExplicitNamespaces</option> (which is implied
+by <option>-XExplicitTypeOperators</option>) GHC allows you to specify the latter
by preceding it with the keyword <literal>type</literal>, thus:
<programlisting>
import M( type (+) )
</programlisting>
+See <xref linkend="explicit-namespaces"/>.
</para></listitem>
<listitem><para>
The fixity of a type operator may be set using the usual fixity declarations
@@ -4642,30 +4674,44 @@ The willingness to be overlapped or incoherent is a property of
the <emphasis>instance declaration</emphasis> itself, controlled by the
presence or otherwise of the <option>-XOverlappingInstances</option>
and <option>-XIncoherentInstances</option> flags when that module is
-being defined. Specifically, during the lookup process:
+being defined. Suppose we are searching for an instance of the
+<emphasis>target constraint</emphasis> <literal>(C ty1 .. tyn)</literal>.
+The search works like this.
<itemizedlist>
<listitem><para>
-If the constraint being looked up matches two instance declarations IA and IB,
-and
-<itemizedlist>
-<listitem><para>IB is a substitution instance of IA (but not vice versa);
-that is, IB is strictly more specific than IA</para></listitem>
-<listitem><para>either IA or IB was compiled with <option>-XOverlappingInstances</option></para></listitem>
-</itemizedlist>
-then the less-specific instance IA is ignored.
+Find all instances I that <emphasis>match</emphasis> the target constraint;
+that is, the target constraint is a substitution instance of I. These
+instance declarations are the <emphasis>candidates</emphasis>.
</para></listitem>
+
+<listitem><para>
+Find all <emphasis>non-candidate</emphasis> instances
+that <emphasis>unify</emphasis> with the target constraint.
+Such non-candidates instances might match when the target constraint is further
+instantiated. If all of them were compiled with
+<option>-XIncoherentInstances</option>, proceed; if not, the search fails.
+</para></listitem>
+
<listitem><para>
-Suppose an instance declaration does not match the constraint being looked up, but
-does <emphasis>unify</emphasis> with it, so that it might match when the constraint is further
-instantiated. Usually GHC will regard this as a reason for not committing to
-some other constraint. But if the instance declaration was compiled with
-<option>-XIncoherentInstances</option>, GHC will skip the "does-it-unify?"
-check for that declaration.
+Eliminate any candidate IX for which both of the following hold:
+
+<itemizedlist>
+<listitem><para>There is another candidate IY that is strictly more specific;
+that is, IY is a substitution instance of IX but not vice versa.
+</para></listitem>
+<listitem><para>Either IX or IY was compiled with
+<option>-XOverlappingInstances</option>.
</para></listitem>
+</itemizedlist>
+
+</para></listitem>
+
<listitem><para>
-If two instance declarations are matched and either is compiled with
-<option>-XIncoherentInstances</option>, then that declaration is ignored.
+If only one candidate remains, pick it.
+Otherwise if all remaining candidates were compiled with
+<option>-XInccoherentInstances</option>, pick an arbitrary candidate.
</para></listitem>
+
</itemizedlist>
These rules make it possible for a library author to design a library that relies on
overlapping instances without the library client having to know.
@@ -6386,106 +6432,91 @@ The flag <option>-XFlexibleContexts</option> also lifts the corresponding
restriction on class declarations (<xref linkend="superclass-rules"/>) and instance declarations
(<xref linkend="instance-rules"/>).
</para>
+</sect2>
-<para>
-GHC imposes the following restrictions on the constraints in a type signature.
-Consider the type:
+<sect2 id="ambiguity"><title>Ambiguous types and the ambiguity check</title>
+<para>
+Each user-written type signature is subjected to an
+<emphasis>ambiguity check</emphasis>.
+The ambiguity check rejects functions that can never be called; for example:
<programlisting>
- forall tv1..tvn (c1, ...,cn) => type
+ f :: C a => Int
</programlisting>
-
-(Here, we write the "foralls" explicitly, although the Haskell source
-language omits them; in Haskell 98, all the free type variables of an
-explicit source-language type signature are universally quantified,
-except for the class type variables in a class declaration. However,
-in GHC, you can give the foralls if you want. See <xref linkend="explicit-foralls"/>).
+The idea is there can be no legal calls to <literal>f</literal> because every call will
+give rise to an ambiguous constraint.
</para>
-
<para>
-
-<orderedlist>
-<listitem>
-
+The <emphasis>only</emphasis> purpose of the
+ambiguity check is to report functions that cannot possibly be called.
+We could soundly omit the
+ambiguity check on type signatures entirely, at the expense of
+delaying ambiguity errors to call sites. Indeed, the language extension
+<option>-XAllowAmbiguousTypes</option> switches off the ambiguity check.
+</para>
<para>
- <emphasis>Each universally quantified type variable
-<literal>tvi</literal> must be reachable from <literal>type</literal></emphasis>.
-
-A type variable <literal>a</literal> is "reachable" if it appears
-in the same constraint as either a type variable free in
-<literal>type</literal>, or another reachable type variable.
-A value with a type that does not obey
-this reachability restriction cannot be used without introducing
-ambiguity; that is why the type is rejected.
-Here, for example, is an illegal type:
-
-
+Ambiguity can be subtle. Consider this example which uses functional dependencies:
<programlisting>
- forall a. Eq a => Int
+ class D a b | a -> b where ..
+ h :: D Int b => Int
</programlisting>
-
-
-When a value with this type was used, the constraint <literal>Eq tv</literal>
-would be introduced where <literal>tv</literal> is a fresh type variable, and
-(in the dictionary-translation implementation) the value would be
-applied to a dictionary for <literal>Eq tv</literal>. The difficulty is that we
-can never know which instance of <literal>Eq</literal> to use because we never
-get any more information about <literal>tv</literal>.
-</para>
-<para>
-Note
-that the reachability condition is weaker than saying that <literal>a</literal> is
-functionally dependent on a type variable free in
-<literal>type</literal> (see <xref
-linkend="functional-dependencies"/>). The reason for this is there
-might be a "hidden" dependency, in a superclass perhaps. So
-"reachable" is a conservative approximation to "functionally dependent".
-For example, consider:
+The <literal>Int</literal> may well fix <literal>b</literal> at the call site, so that signature should
+not be rejected. Moreover, the dependencies might be hidden. Consider
+<programlisting>
+ class X a b where ...
+ class D a b | a -> b where ...
+ instance D a b => X [a] b where...
+ h :: X a b => a -> a
+</programlisting>
+Here <literal>h</literal>'s type looks ambiguous in <literal>b</literal>, but here's a legal call:
<programlisting>
- class C a b | a -> b where ...
- class C a b => D a b where ...
- f :: forall a b. D a b => a -> a
+ ...(h [True])...
</programlisting>
-This is fine, because in fact <literal>a</literal> does functionally determine <literal>b</literal>
-but that is not immediately apparent from <literal>f</literal>'s type.
+That gives rise to a <literal>(X [Bool] beta)</literal> constraint, and using the
+instance means we need <literal>(D Bool beta)</literal> and that
+fixes <literal>beta</literal> via <literal>D</literal>'s
+fundep!
</para>
-</listitem>
-<listitem>
-
<para>
- <emphasis>Every constraint <literal>ci</literal> must mention at least one of the
-universally quantified type variables <literal>tvi</literal></emphasis>.
-
-For example, this type is OK because <literal>C a b</literal> mentions the
-universally quantified type variable <literal>b</literal>:
-
-
+Behind all these special cases there is a simple guiding principle.
+Consider
<programlisting>
- forall a. C a b => burble
-</programlisting>
+ f :: <replaceable>type</replaceable>
+ f = ...blah...
-
-The next type is illegal because the constraint <literal>Eq b</literal> does not
-mention <literal>a</literal>:
-
-
-<programlisting>
- forall a. Eq b => burble
+ g :: <replaceable>type</replaceable>
+ g = f
</programlisting>
-
-
-The reason for this restriction is milder than the other one. The
-excluded types are never useful or necessary (because the offending
-context doesn't need to be witnessed at this point; it can be floated
-out). Furthermore, floating them out increases sharing. Lastly,
-excluding them is a conservative choice; it leaves a patch of
-territory free in case we need it later.
-
+You would think that the definition of <literal>g</literal> would surely typecheck!
+After all <literal>f</literal> has exactly the same type, and <literal>g=f</literal>.
+But in fact <literal>f</literal>'s type
+is instantiated and the instantiated constraints are solved against
+the constraints bound by <literal>g</literal>'s signature. So, in the case an ambiguous type, solving will fail.
+For example, consider the earlier definition <literal>f :: C a => Int</literal>. Then in <literal>g</literal>'s definition,
+we'll instantiate to <literal>(C alpha)</literal> and try to
+deduce <literal>(C alpha)</literal> from <literal>(C a)</literal>,
+and fail.
+</para>
+<para>
+So in fact we use this as our <emphasis>definition</emphasis> of ambiguity: a type
+<literal><replaceable>ty</replaceable></literal> is
+ambiguious if and only if <literal>((undefined :: <replaceable>ty</replaceable>)
+:: <replaceable>ty</replaceable>)</literal> would fail to typecheck. We use a
+very similar test for <emphasis>inferred</emphasis> types, to ensure that they too are
+unambiguous.
</para>
-</listitem>
-
-</orderedlist>
+<para>
+<emphasis>A historical note.</emphasis>
+GHC used to impose some more restrictive and less principled conditions
+on type signatures. For type type
+<literal>forall tv1..tvn (c1, ...,cn) => type</literal>
+GHC used to require (a) that each universally quantified type variable
+<literal>tvi</literal> must be "reachable" from <literal>type</literal>,
+and (b) that every constraint <literal>ci</literal> mentions at least one of the
+universally quantified type variables <literal>tvi</literal>.
+These ad-hoc restrictions are completely subsumed by the new ambiguity check.
+<emphasis>End of historical note.</emphasis>
</para>
</sect2>
@@ -6498,9 +6529,7 @@ territory free in case we need it later.
J Lewis, MB Shields, E Meijer, J Launchbury,
27th ACM Symposium on Principles of Programming Languages (POPL'00),
Boston, Jan 2000.
-</para>
-
-<para>(Most of the following, still rather incomplete, documentation is
+(Most of the following, still rather incomplete, documentation is
due to Jeff Lewis.)</para>
<para>Implicit parameter support is enabled with the option
@@ -7612,8 +7641,9 @@ Failed, modules loaded: none.
This ensures that an unbound identifier is never reported with a too polymorphic type, like
<literal>forall a. a</literal>, when used multiple times for types that can not be unified.
</para>
-
</sect2>
+
+
</sect1>
<!-- ==================== End of type system extensions ================= -->
diff --git a/driver/ghc-usage.txt b/driver/ghc-usage.txt
index b45199bdc1..4eda2c1724 100644
--- a/driver/ghc-usage.txt
+++ b/driver/ghc-usage.txt
@@ -77,4 +77,7 @@ online copy can be found here:
http://haskell.org/haskellwiki/GHC
+If you *really* want to see every option, then you can pass
+'--show-options' to the compiler.
+
------------------------------------------------------------------------
diff --git a/includes/rts/Linker.h b/includes/rts/Linker.h
index e900e858c1..28f0a0e928 100644
--- a/includes/rts/Linker.h
+++ b/includes/rts/Linker.h
@@ -16,8 +16,10 @@
#if defined(mingw32_HOST_OS)
typedef wchar_t pathchar;
+#define PATH_FMT "ls"
#else
typedef char pathchar;
+#define PATH_FMT "s"
#endif
/* initialize the object linker */
diff --git a/includes/stg/MiscClosures.h b/includes/stg/MiscClosures.h
index b0ed03b814..876f39a02c 100644
--- a/includes/stg/MiscClosures.h
+++ b/includes/stg/MiscClosures.h
@@ -364,9 +364,12 @@ RTS_FUN_DECL(stg_word64ToIntegerzh);
#endif
RTS_FUN_DECL(stg_unsafeThawArrayzh);
+RTS_FUN_DECL(stg_casArrayzh);
RTS_FUN_DECL(stg_newByteArrayzh);
RTS_FUN_DECL(stg_newPinnedByteArrayzh);
RTS_FUN_DECL(stg_newAlignedPinnedByteArrayzh);
+RTS_FUN_DECL(stg_casIntArrayzh);
+RTS_FUN_DECL(stg_fetchAddIntArrayzh);
RTS_FUN_DECL(stg_newArrayzh);
RTS_FUN_DECL(stg_newArrayArrayzh);
diff --git a/includes/stg/SMP.h b/includes/stg/SMP.h
index 99c25fe355..07ea522328 100644
--- a/includes/stg/SMP.h
+++ b/includes/stg/SMP.h
@@ -52,13 +52,14 @@ EXTERN_INLINE StgWord xchg(StgPtr p, StgWord w);
EXTERN_INLINE StgWord cas(StgVolatilePtr p, StgWord o, StgWord n);
/*
- * Atomic increment
+ * Atomic addition by the provided quantity
*
- * atomic_inc(p) {
- * return ++(*p);
+ * atomic_inc(p, n) {
+ * return ((*p) += n);
* }
*/
-EXTERN_INLINE StgWord atomic_inc(StgVolatilePtr p);
+EXTERN_INLINE StgWord atomic_inc(StgVolatilePtr p, StgWord n);
+
/*
* Atomic decrement
@@ -236,22 +237,24 @@ cas(StgVolatilePtr p, StgWord o, StgWord n)
#endif
}
+// RRN: Generalized to arbitrary increments to enable fetch-and-add in
+// Haskell code (fetchAddIntArray#).
EXTERN_INLINE StgWord
-atomic_inc(StgVolatilePtr p)
+atomic_inc(StgVolatilePtr p, StgWord incr)
{
#if defined(i386_HOST_ARCH) || defined(x86_64_HOST_ARCH)
StgWord r;
- r = 1;
+ r = incr;
__asm__ __volatile__ (
"lock\nxadd %0,%1":
"+r" (r), "+m" (*p):
);
- return r+1;
+ return r + incr;
#else
StgWord old, new;
do {
old = *p;
- new = old + 1;
+ new = old + incr;
} while (cas(p, old, new) != old);
return new;
#endif
@@ -393,12 +396,14 @@ cas(StgVolatilePtr p, StgWord o, StgWord n)
return result;
}
-INLINE_HEADER StgWord
-atomic_inc(StgVolatilePtr p)
+EXTERN_INLINE StgWord atomic_inc(StgVolatilePtr p, StgWord incr);
+EXTERN_INLINE StgWord
+atomic_inc(StgVolatilePtr p, StgWord incr)
{
- return ++(*p);
+ return ((*p) += incr);
}
+
INLINE_HEADER StgWord
atomic_dec(StgVolatilePtr p)
{
diff --git a/libraries/haskeline b/libraries/haskeline
-Subproject 40bcd6ac30577d1d240166674d1e328ac52c1fd
+Subproject 495b00b4f125c0b4e7f1e966cd961eae89cffdc
diff --git a/libraries/time b/libraries/time
-Subproject 12ba4321d34d646cf9040ad12810c4257d26ade
+Subproject d4f019b2c6a332be5443b5bf88d0c7fef91523c
diff --git a/mk/config.mk.in b/mk/config.mk.in
index 0c2003b680..6402ac5680 100644
--- a/mk/config.mk.in
+++ b/mk/config.mk.in
@@ -490,6 +490,7 @@ endif
TargetPlatformFull = @TargetPlatformFull@
GccLT34 = @GccLT34@
GccLT46 = @GccLT46@
+GccIsClang = @GccIsClang@
CC = $(WhatGccIsCalled)
CC_STAGE0 = @CC_STAGE0@
diff --git a/mk/install.mk.in b/mk/install.mk.in
index 2808c1f784..d6f68abd19 100644
--- a/mk/install.mk.in
+++ b/mk/install.mk.in
@@ -105,7 +105,7 @@ else
# to be in the same place (and things like ghc-pkg need to agree on
# where package.conf is, so we just set it globally).
#
-ghclibdir = $(libdir)/ghc-$(ProjectVersion)
+ghclibdir = $(libdir)/$(CrossCompilePrefix)ghc-$(ProjectVersion)
ghcdocdir = $(datarootdir)/doc/ghc
endif
diff --git a/mk/validate-settings.mk b/mk/validate-settings.mk
index 9aa824d5bc..ba645a4190 100644
--- a/mk/validate-settings.mk
+++ b/mk/validate-settings.mk
@@ -10,6 +10,8 @@ HADDOCK_DOCS = YES
#####################
# Warnings
+ifneq "$(GccIsClang)" "YES"
+
# Debian doesn't turn -Werror=unused-but-set-variable on by default, so
# we turn it on explicitly for consistency with other users
ifeq "$(GccLT46)" "NO"
@@ -18,6 +20,13 @@ SRC_CC_WARNING_OPTS += -Werror=unused-but-set-variable
SRC_CC_WARNING_OPTS += -Wno-error=inline
endif
+else
+
+# Don't warn about unknown GCC pragmas when using clang
+SRC_CC_WARNING_OPTS += -Wno-unknown-pragmas
+
+endif
+
SRC_CC_OPTS += $(WERROR) -Wall
SRC_HC_OPTS += $(WERROR) -Wall
diff --git a/packages b/packages
index ecba5c8252..39d8d8da49 100644
--- a/packages
+++ b/packages
@@ -2,7 +2,7 @@
# the *repositories* that make up GHC. It is parsed by
# * boot
# * sync-all
-# * rules/extra-packages.mk
+# * rules/foreachLibrary.mk
#
# Some of this information is duplicated elsewhere in the build system:
# See Trac #3896
@@ -20,11 +20,13 @@
# - nofib and testsuite are optional helpers
#
# The format of the lines in this file is:
-# localpath tag remotepath
+# localpath tag remotepath upstreamurl
# where
# * 'localpath' is where to put the repository in a checked out tree.
# * 'remotepath' is where the repository is in the central repository.
# It is - for submodules.
+# * 'upstreamurl' is the upstream Git repo location for packages
+# maintained outside of GHC HQ.
#
# * The 'tag' determines when "darcs-all get" will get the
# repo. If the tag is "-" then it will always get it, but if there
@@ -39,47 +41,47 @@
#
# Lines that start with a '#' are comments.
#
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# localpath tag remotepath
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-ghc-tarballs windows ghc-tarballs.git
-libffi-tarballs - libffi-tarballs.git
-utils/hsc2hs - hsc2hs.git
-utils/haddock - haddock.git
-libraries/array - packages/array.git
-libraries/base - packages/base.git
-libraries/binary - -
-libraries/bytestring - -
-libraries/Cabal - -
-libraries/containers - -
-libraries/deepseq - packages/deepseq.git
-libraries/directory - packages/directory.git
-libraries/filepath - packages/filepath.git
-libraries/ghc-prim - packages/ghc-prim.git
-libraries/haskeline - -
-libraries/haskell98 - packages/haskell98.git
-libraries/haskell2010 - packages/haskell2010.git
-libraries/hoopl - packages/hoopl.git
-libraries/hpc - packages/hpc.git
-libraries/integer-gmp - packages/integer-gmp.git
-libraries/integer-simple - packages/integer-simple.git
-libraries/old-locale - packages/old-locale.git
-libraries/old-time - packages/old-time.git
-libraries/pretty - -
-libraries/process - packages/process.git
-libraries/template-haskell - packages/template-haskell.git
-libraries/terminfo - -
-libraries/time - -
-libraries/transformers - -
-libraries/unix - packages/unix.git
-libraries/Win32 - -
-libraries/xhtml - -
-testsuite testsuite testsuite.git
-nofib nofib nofib.git
-libraries/parallel extra packages/parallel.git
-libraries/stm extra packages/stm.git
-libraries/random dph -
-libraries/primitive dph -
-libraries/vector dph -
-libraries/dph dph packages/dph.git
-. - ghc.git
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# localpath tag remotepath upstreamurl
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ghc-tarballs windows ghc-tarballs.git -
+libffi-tarballs - libffi-tarballs.git -
+utils/hsc2hs - hsc2hs.git -
+utils/haddock - haddock.git -
+libraries/array - packages/array.git -
+libraries/base - packages/base.git -
+libraries/binary - - https://github.com/kolmodin/binary.git
+libraries/bytestring - - https://github.com/haskell/bytestring.git
+libraries/Cabal - - https://github.com/haskell/cabal.git
+libraries/containers - - https://github.com/haskell/containers.git
+libraries/deepseq - packages/deepseq.git -
+libraries/directory - packages/directory.git -
+libraries/filepath - packages/filepath.git -
+libraries/ghc-prim - packages/ghc-prim.git -
+libraries/haskeline - - http://git.haskell.org/darcs-mirrors/haskeline.git
+libraries/haskell98 - packages/haskell98.git -
+libraries/haskell2010 - packages/haskell2010.git -
+libraries/hoopl - packages/hoopl.git -
+libraries/hpc - packages/hpc.git -
+libraries/integer-gmp - packages/integer-gmp.git -
+libraries/integer-simple - packages/integer-simple.git -
+libraries/old-locale - packages/old-locale.git -
+libraries/old-time - packages/old-time.git -
+libraries/pretty - - https://github.com/haskell/pretty.git
+libraries/process - packages/process.git -
+libraries/template-haskell - packages/template-haskell.git -
+libraries/terminfo - - http://git.haskell.org/darcs-mirrors/terminfo.git
+libraries/time - - http://git.haskell.org/darcs-mirrors/time.git
+libraries/transformers - - http://git.haskell.org/darcs-mirrors/transformers.git
+libraries/unix - packages/unix.git -
+libraries/Win32 - - https://github.com/haskell/win32.git
+libraries/xhtml - - https://github.com/haskell/xhtml.git
+testsuite testsuite testsuite.git -
+nofib nofib nofib.git -
+libraries/parallel extra packages/parallel.git -
+libraries/stm extra packages/stm.git -
+libraries/random dph - -
+libraries/primitive dph - http://git.haskell.org/darcs-mirrors/primitive.git
+libraries/vector dph - http://git.haskell.org/darcs-mirrors/vector.git
+libraries/dph dph packages/dph.git -
+. - ghc.git - \ No newline at end of file
diff --git a/rts/Capability.c b/rts/Capability.c
index 811df582a8..5988d4205c 100644
--- a/rts/Capability.c
+++ b/rts/Capability.c
@@ -35,7 +35,13 @@ Capability MainCapability;
nat n_capabilities = 0;
nat enabled_capabilities = 0;
-Capability *capabilities = NULL;
+
+// The array of Capabilities. It's important that when we need
+// to allocate more Capabilities we don't have to move the existing
+// Capabilities, because there may be pointers to them in use
+// (e.g. threads in waitForReturnCapability(), see #8209), so this is
+// an array of Capability* rather than an array of Capability.
+Capability **capabilities = NULL;
// Holds the Capability which last became free. This is used so that
// an in-call has a chance of quickly finding a free Capability.
@@ -126,7 +132,7 @@ findSpark (Capability *cap)
/* visit cap.s 0..n-1 in sequence until a theft succeeds. We could
start at a random place instead of 0 as well. */
for ( i=0 ; i < n_capabilities ; i++ ) {
- robbed = &capabilities[i];
+ robbed = capabilities[i];
if (cap == robbed) // ourselves...
continue;
@@ -169,7 +175,7 @@ anySparks (void)
nat i;
for (i=0; i < n_capabilities; i++) {
- if (!emptySparkPoolCap(&capabilities[i])) {
+ if (!emptySparkPoolCap(capabilities[i])) {
return rtsTrue;
}
}
@@ -323,7 +329,8 @@ initCapabilities( void )
#else /* !THREADED_RTS */
n_capabilities = 1;
- capabilities = &MainCapability;
+ capabilities = stgMallocBytes(sizeof(Capability*), "initCapabilities");
+ capabilities[0] = &MainCapability;
initCapability(&MainCapability, 0);
#endif
@@ -333,46 +340,40 @@ initCapabilities( void )
// There are no free capabilities to begin with. We will start
// a worker Task to each Capability, which will quickly put the
// Capability on the free list when it finds nothing to do.
- last_free_capability = &capabilities[0];
+ last_free_capability = capabilities[0];
}
-Capability *
+void
moreCapabilities (nat from USED_IF_THREADS, nat to USED_IF_THREADS)
{
#if defined(THREADED_RTS)
nat i;
- Capability *old_capabilities = capabilities;
+ Capability **old_capabilities = capabilities;
+
+ capabilities = stgMallocBytes(to * sizeof(Capability*), "moreCapabilities");
if (to == 1) {
// THREADED_RTS must work on builds that don't have a mutable
// BaseReg (eg. unregisterised), so in this case
// capabilities[0] must coincide with &MainCapability.
- capabilities = &MainCapability;
- } else {
- capabilities = stgMallocBytes(to * sizeof(Capability),
- "moreCapabilities");
-
- if (from > 0) {
- memcpy(capabilities, old_capabilities, from * sizeof(Capability));
- }
+ capabilities[0] = &MainCapability;
}
- for (i = from; i < to; i++) {
- initCapability(&capabilities[i], i);
+ for (i = 0; i < to; i++) {
+ if (i < from) {
+ capabilities[i] = old_capabilities[i];
+ } else {
+ capabilities[i] = stgMallocBytes(sizeof(Capability),
+ "moreCapabilities");
+ initCapability(capabilities[i], i);
+ }
}
- last_free_capability = &capabilities[0];
-
debugTrace(DEBUG_sched, "allocated %d more capabilities", to - from);
- // Return the old array to free later.
- if (from > 1) {
- return old_capabilities;
- } else {
- return NULL;
+ if (old_capabilities != NULL) {
+ stgFree(old_capabilities);
}
-#else
- return NULL;
#endif
}
@@ -385,7 +386,7 @@ void contextSwitchAllCapabilities(void)
{
nat i;
for (i=0; i < n_capabilities; i++) {
- contextSwitchCapability(&capabilities[i]);
+ contextSwitchCapability(capabilities[i]);
}
}
@@ -393,7 +394,7 @@ void interruptAllCapabilities(void)
{
nat i;
for (i=0; i < n_capabilities; i++) {
- interruptCapability(&capabilities[i]);
+ interruptCapability(capabilities[i]);
}
}
@@ -606,8 +607,8 @@ waitForReturnCapability (Capability **pCap, Task *task)
// otherwise, search for a free capability
cap = NULL;
for (i = 0; i < n_capabilities; i++) {
- if (!capabilities[i].running_task) {
- cap = &capabilities[i];
+ if (!capabilities[i]->running_task) {
+ cap = capabilities[i];
break;
}
}
@@ -955,7 +956,7 @@ shutdownCapabilities(Task *task, rtsBool safe)
nat i;
for (i=0; i < n_capabilities; i++) {
ASSERT(task->incall->tso == NULL);
- shutdownCapability(&capabilities[i], task, safe);
+ shutdownCapability(capabilities[i], task, safe);
}
#if defined(THREADED_RTS)
ASSERT(checkSparkCountInvariant());
@@ -981,11 +982,13 @@ freeCapabilities (void)
#if defined(THREADED_RTS)
nat i;
for (i=0; i < n_capabilities; i++) {
- freeCapability(&capabilities[i]);
+ freeCapability(capabilities[i]);
+ stgFree(capabilities[i]);
}
#else
freeCapability(&MainCapability);
#endif
+ stgFree(capabilities);
traceCapsetDelete(CAPSET_OSPROCESS_DEFAULT);
traceCapsetDelete(CAPSET_CLOCKDOMAIN_DEFAULT);
}
@@ -1032,7 +1035,7 @@ markCapabilities (evac_fn evac, void *user)
{
nat n;
for (n = 0; n < n_capabilities; n++) {
- markCapability(evac, user, &capabilities[n], rtsFalse);
+ markCapability(evac, user, capabilities[n], rtsFalse);
}
}
@@ -1044,13 +1047,13 @@ rtsBool checkSparkCountInvariant (void)
nat i;
for (i = 0; i < n_capabilities; i++) {
- sparks.created += capabilities[i].spark_stats.created;
- sparks.dud += capabilities[i].spark_stats.dud;
- sparks.overflowed+= capabilities[i].spark_stats.overflowed;
- sparks.converted += capabilities[i].spark_stats.converted;
- sparks.gcd += capabilities[i].spark_stats.gcd;
- sparks.fizzled += capabilities[i].spark_stats.fizzled;
- remaining += sparkPoolSize(capabilities[i].sparks);
+ sparks.created += capabilities[i]->spark_stats.created;
+ sparks.dud += capabilities[i]->spark_stats.dud;
+ sparks.overflowed+= capabilities[i]->spark_stats.overflowed;
+ sparks.converted += capabilities[i]->spark_stats.converted;
+ sparks.gcd += capabilities[i]->spark_stats.gcd;
+ sparks.fizzled += capabilities[i]->spark_stats.fizzled;
+ remaining += sparkPoolSize(capabilities[i]->sparks);
}
/* The invariant is
diff --git a/rts/Capability.h b/rts/Capability.h
index 3348f88e4d..9de47357c4 100644
--- a/rts/Capability.h
+++ b/rts/Capability.h
@@ -132,8 +132,8 @@ struct Capability_ {
StgTRecHeader *free_trec_headers;
nat transaction_tokens;
} // typedef Capability is defined in RtsAPI.h
- // Capabilities are stored in an array, so make sure that adjacent
- // Capabilities don't share any cache-lines:
+ // We never want a Capability to overlap a cache line with anything
+ // else, so round it up to a cache line size:
#ifndef mingw32_HOST_OS
ATTRIBUTE_ALIGNED(64)
#endif
@@ -181,7 +181,7 @@ void initCapabilities (void);
// Add and initialise more Capabilities
//
-Capability * moreCapabilities (nat from, nat to);
+void moreCapabilities (nat from, nat to);
// Release a capability. This is called by a Task that is exiting
// Haskell to make a foreign call, or in various other cases when we
@@ -211,7 +211,7 @@ INLINE_HEADER void releaseCapability_ (Capability* cap STG_UNUSED,
// Array of all the capabilities
//
-extern Capability *capabilities;
+extern Capability **capabilities;
// The Capability that was last free. Used as a good guess for where
// to assign new threads.
diff --git a/rts/CheckUnload.c b/rts/CheckUnload.c
index a758b06db3..d3fb8934b5 100644
--- a/rts/CheckUnload.c
+++ b/rts/CheckUnload.c
@@ -246,7 +246,7 @@ void checkUnload (StgClosure *static_objects)
HashTable *addrs;
StgClosure* p;
const StgInfoTable *info;
- ObjectCode *oc, *prev;
+ ObjectCode *oc, *prev, *next;
gen_workspace *ws;
StgClosure* link;
@@ -254,7 +254,7 @@ void checkUnload (StgClosure *static_objects)
// Mark every unloadable object as unreferenced initially
for (oc = unloaded_objects; oc; oc = oc->next) {
- IF_DEBUG(linker, debugBelch("Checking whether to unload %s\n",
+ IF_DEBUG(linker, debugBelch("Checking whether to unload %" PATH_FMT "\n",
oc->fileName));
oc->referenced = rtsFalse;
}
@@ -283,19 +283,20 @@ void checkUnload (StgClosure *static_objects)
// marked as unreferenced can be physically unloaded, because we
// have no references to it.
prev = NULL;
- for (oc = unloaded_objects; oc; prev = oc, oc = oc->next) {
+ for (oc = unloaded_objects; oc; prev = oc, oc = next) {
+ next = oc->next;
if (oc->referenced == 0) {
if (prev == NULL) {
unloaded_objects = oc->next;
} else {
prev->next = oc->next;
}
- IF_DEBUG(linker, debugBelch("Unloading object file %s\n",
+ IF_DEBUG(linker, debugBelch("Unloading object file %" PATH_FMT "\n",
oc->fileName));
freeObjectCode(oc);
} else {
- IF_DEBUG(linker, debugBelch("Object file still in use: %s\n",
- oc->fileName));
+ IF_DEBUG(linker, debugBelch("Object file still in use: %"
+ PATH_FMT "\n", oc->fileName));
}
}
diff --git a/rts/Linker.c b/rts/Linker.c
index 4961ecf053..c8451b0425 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -169,7 +169,6 @@ static ObjectCode* mkOc( pathchar *path, char *image, int imageSize,
#define struct_stat struct _stat
#define open wopen
#define WSTR(s) L##s
-#define PATH_FMT "S"
#else
#define pathcmp strcmp
#define pathlen strlen
@@ -177,7 +176,6 @@ static ObjectCode* mkOc( pathchar *path, char *image, int imageSize,
#define pathstat stat
#define struct_stat struct stat
#define WSTR(s) s
-#define PATH_FMT "s"
#endif
static pathchar* pathdup(pathchar *path)
@@ -1140,8 +1138,11 @@ typedef struct _RtsSymbolVal {
SymI_HasProto(stg_labelThreadzh) \
SymI_HasProto(stg_newArrayzh) \
SymI_HasProto(stg_newArrayArrayzh) \
+ SymI_HasProto(stg_casArrayzh) \
SymI_HasProto(stg_newBCOzh) \
SymI_HasProto(stg_newByteArrayzh) \
+ SymI_HasProto(stg_casIntArrayzh) \
+ SymI_HasProto(stg_fetchAddIntArrayzh) \
SymI_HasProto_redirect(newCAF, newDynCAF) \
SymI_HasProto(stg_newMVarzh) \
SymI_HasProto(stg_newMutVarzh) \
diff --git a/rts/PrimOps.cmm b/rts/PrimOps.cmm
index d8acaef77b..3cfec94b72 100644
--- a/rts/PrimOps.cmm
+++ b/rts/PrimOps.cmm
@@ -137,6 +137,34 @@ stg_newAlignedPinnedByteArrayzh ( W_ n, W_ alignment )
return (p);
}
+// RRN: This one does not use the "ticketing" approach because it
+// deals in unboxed scalars, not heap pointers.
+stg_casIntArrayzh( gcptr arr, W_ ind, W_ old, W_ new )
+/* MutableByteArray# s -> Int# -> Int# -> Int# -> State# s -> (# State# s, Int# #) */
+{
+ gcptr p;
+ W_ h;
+
+ p = arr + SIZEOF_StgArrWords + WDS(ind);
+ (h) = ccall cas(p, old, new);
+
+ return(h);
+}
+
+
+stg_fetchAddIntArrayzh( gcptr arr, W_ ind, W_ incr )
+/* MutableByteArray# s -> Int# -> Int# -> State# s -> (# State# s, Int# #) */
+{
+ gcptr p;
+ W_ h;
+
+ p = arr + SIZEOF_StgArrWords + WDS(ind);
+ (h) = ccall atomic_inc(p, incr);
+
+ return(h);
+}
+
+
stg_newArrayzh ( W_ n /* words */, gcptr init )
{
W_ words, size;
@@ -206,6 +234,29 @@ stg_unsafeThawArrayzh ( gcptr arr )
}
}
+// RRN: Uses the ticketed approach; see casMutVar
+stg_casArrayzh ( gcptr arr, W_ ind, gcptr old, gcptr new )
+/* MutableArray# s a -> Int# -> a -> a -> State# s -> (# State# s, Int#, Any a #) */
+{
+ gcptr p, h;
+ W_ len;
+
+ p = arr + SIZEOF_StgMutArrPtrs + WDS(ind);
+ (h) = ccall cas(p, old, new);
+
+ if (h != old) {
+ // Failure, return what was there instead of 'old':
+ return (1,h);
+ } else {
+ // Compare and Swap Succeeded:
+ SET_HDR(arr, stg_MUT_ARR_PTRS_DIRTY_info, CCCS);
+ len = StgMutArrPtrs_ptrs(arr);
+ // The write barrier. We must write a byte into the mark table:
+ I8[arr + SIZEOF_StgMutArrPtrs + WDS(len) + (ind >> MUT_ARR_PTRS_CARD_BITS )] = 1;
+ return (0,new);
+ }
+}
+
stg_newArrayArrayzh ( W_ n /* words */ )
{
W_ words, size;
@@ -262,8 +313,13 @@ stg_newMutVarzh ( gcptr init )
return (mv);
}
+// RRN: To support the "ticketed" approach, we return the NEW rather
+// than old value if the CAS is successful. This is received in an
+// opaque form in the Haskell code, preventing the compiler from
+// changing its pointer identity. The ticket can then be safely used
+// in future CAS operations.
stg_casMutVarzh ( gcptr mv, gcptr old, gcptr new )
- /* MutVar# s a -> a -> a -> State# s -> (# State#, Int#, a #) */
+ /* MutVar# s a -> a -> a -> State# s -> (# State#, Int#, Any a #) */
{
gcptr h;
@@ -275,7 +331,7 @@ stg_casMutVarzh ( gcptr mv, gcptr old, gcptr new )
if (GET_INFO(mv) == stg_MUT_VAR_CLEAN_info) {
ccall dirty_MUT_VAR(BaseReg "ptr", mv "ptr");
}
- return (0,h);
+ return (0,new);
}
}
diff --git a/rts/Profiling.c b/rts/Profiling.c
index ec38c927c2..0c673261dc 100644
--- a/rts/Profiling.c
+++ b/rts/Profiling.c
@@ -149,7 +149,7 @@ initProfiling1 (void)
{
nat n;
for (n=0; n < n_capabilities; n++) {
- capabilities[n].r.rCCCS = CCS_SYSTEM;
+ capabilities[n]->r.rCCCS = CCS_SYSTEM;
}
}
diff --git a/rts/Proftimer.c b/rts/Proftimer.c
index 7ee32f835c..6458f6e095 100644
--- a/rts/Proftimer.c
+++ b/rts/Proftimer.c
@@ -76,7 +76,7 @@ handleProfTick(void)
if (do_prof_ticks) {
nat n;
for (n=0; n < n_capabilities; n++) {
- capabilities[n].r.rCCCS->time_ticks++;
+ capabilities[n]->r.rCCCS->time_ticks++;
}
}
#endif
diff --git a/rts/RetainerProfile.c b/rts/RetainerProfile.c
index dc21149d98..8cf88487f2 100644
--- a/rts/RetainerProfile.c
+++ b/rts/RetainerProfile.c
@@ -1789,7 +1789,7 @@ computeRetainerSet( void )
// because we can find MUT_VAR objects which have not been
// visited during retainer profiling.
for (n = 0; n < n_capabilities; n++) {
- for (bd = capabilities[n].mut_lists[g]; bd != NULL; bd = bd->link) {
+ for (bd = capabilities[n]->mut_lists[g]; bd != NULL; bd = bd->link) {
for (ml = bd->start; ml < bd->free; ml++) {
maybeInitRetainerSet((StgClosure *)*ml);
diff --git a/rts/Schedule.c b/rts/Schedule.c
index 408146f195..07ebec62b1 100644
--- a/rts/Schedule.c
+++ b/rts/Schedule.c
@@ -376,7 +376,7 @@ schedule (Capability *initialCapability, Task *task)
// it was originally on.
#ifdef THREADED_RTS
if (cap->disabled && !t->bound) {
- Capability *dest_cap = &capabilities[cap->no % enabled_capabilities];
+ Capability *dest_cap = capabilities[cap->no % enabled_capabilities];
migrateThread(cap, t, dest_cap);
continue;
}
@@ -716,7 +716,7 @@ schedulePushWork(Capability *cap USED_IF_THREADS,
// First grab as many free Capabilities as we can.
for (i=0, n_free_caps=0; i < n_capabilities; i++) {
- cap0 = &capabilities[i];
+ cap0 = capabilities[i];
if (cap != cap0 && !cap0->disabled && tryGrabCapability(cap0,task)) {
if (!emptyRunQueue(cap0)
|| cap0->returning_tasks_hd != NULL
@@ -1395,7 +1395,7 @@ static void acquireAllCapabilities(Capability *cap, Task *task)
for (i=0; i < n_capabilities; i++) {
debugTrace(DEBUG_sched, "grabbing all the capabilies (%d/%d)", i, n_capabilities);
- tmpcap = &capabilities[i];
+ tmpcap = capabilities[i];
if (tmpcap != cap) {
// we better hope this task doesn't get migrated to
// another Capability while we're waiting for this one.
@@ -1418,8 +1418,8 @@ static void releaseAllCapabilities(nat n, Capability *cap, Task *task)
for (i = 0; i < n; i++) {
if (cap->no != i) {
- task->cap = &capabilities[i];
- releaseCapability(&capabilities[i]);
+ task->cap = capabilities[i];
+ releaseCapability(capabilities[i]);
}
}
task->cap = cap;
@@ -1540,21 +1540,21 @@ scheduleDoGC (Capability **pcap, Task *task USED_IF_THREADS,
|| (RtsFlags.ParFlags.parGcLoadBalancingEnabled &&
collect_gen >= RtsFlags.ParFlags.parGcLoadBalancingGen)) {
for (i=0; i < n_capabilities; i++) {
- if (capabilities[i].disabled) {
- idle_cap[i] = tryGrabCapability(&capabilities[i], task);
+ if (capabilities[i]->disabled) {
+ idle_cap[i] = tryGrabCapability(capabilities[i], task);
} else {
idle_cap[i] = rtsFalse;
}
}
} else {
for (i=0; i < n_capabilities; i++) {
- if (capabilities[i].disabled) {
- idle_cap[i] = tryGrabCapability(&capabilities[i], task);
+ if (capabilities[i]->disabled) {
+ idle_cap[i] = tryGrabCapability(capabilities[i], task);
} else if (i == cap->no ||
- capabilities[i].idle < RtsFlags.ParFlags.parGcNoSyncWithIdle) {
+ capabilities[i]->idle < RtsFlags.ParFlags.parGcNoSyncWithIdle) {
idle_cap[i] = rtsFalse;
} else {
- idle_cap[i] = tryGrabCapability(&capabilities[i], task);
+ idle_cap[i] = tryGrabCapability(capabilities[i], task);
if (!idle_cap[i]) {
n_failed_trygrab_idles++;
} else {
@@ -1575,7 +1575,7 @@ scheduleDoGC (Capability **pcap, Task *task USED_IF_THREADS,
for (i=0; i < n_capabilities; i++) {
gc_threads[i]->idle = idle_cap[i];
- capabilities[i].idle++;
+ capabilities[i]->idle++;
}
// For all capabilities participating in this GC, wait until
@@ -1606,10 +1606,10 @@ delete_threads_and_gc:
// threads. It just avoids the GC having to do any work to
// figure out that any remaining sparks are garbage.
for (i = 0; i < n_capabilities; i++) {
- capabilities[i].spark_stats.gcd +=
- sparkPoolSize(capabilities[i].sparks);
+ capabilities[i]->spark_stats.gcd +=
+ sparkPoolSize(capabilities[i]->sparks);
// No race here since all Caps are stopped.
- discardSparksCap(&capabilities[i]);
+ discardSparksCap(capabilities[i]);
}
#endif
sched_state = SCHED_SHUTTING_DOWN;
@@ -1625,10 +1625,10 @@ delete_threads_and_gc:
#if defined(THREADED_RTS)
for (i = enabled_capabilities; i < n_capabilities; i++) {
Capability *tmp_cap, *dest_cap;
- tmp_cap = &capabilities[i];
+ tmp_cap = capabilities[i];
ASSERT(tmp_cap->disabled);
if (i != cap->no) {
- dest_cap = &capabilities[i % enabled_capabilities];
+ dest_cap = capabilities[i % enabled_capabilities];
while (!emptyRunQueue(tmp_cap)) {
tso = popRunQueue(tmp_cap);
migrateThread(tmp_cap, tso, dest_cap);
@@ -1703,11 +1703,11 @@ delete_threads_and_gc:
for (i = 0; i < n_capabilities; i++) {
if (i != cap->no) {
if (idle_cap[i]) {
- ASSERT(capabilities[i].running_task == task);
- task->cap = &capabilities[i];
- releaseCapability(&capabilities[i]);
+ ASSERT(capabilities[i]->running_task == task);
+ task->cap = capabilities[i];
+ releaseCapability(capabilities[i]);
} else {
- ASSERT(capabilities[i].running_task != task);
+ ASSERT(capabilities[i]->running_task != task);
}
}
}
@@ -1799,7 +1799,7 @@ forkProcess(HsStablePtr *entry
ACQUIRE_LOCK(&task->lock);
for (i=0; i < n_capabilities; i++) {
- ACQUIRE_LOCK(&capabilities[i].lock);
+ ACQUIRE_LOCK(&capabilities[i]->lock);
}
stopTimer(); // See #4074
@@ -1820,8 +1820,8 @@ forkProcess(HsStablePtr *entry
RELEASE_LOCK(&task->lock);
for (i=0; i < n_capabilities; i++) {
- releaseCapability_(&capabilities[i],rtsFalse);
- RELEASE_LOCK(&capabilities[i].lock);
+ releaseCapability_(capabilities[i],rtsFalse);
+ RELEASE_LOCK(&capabilities[i]->lock);
}
boundTaskExiting(task);
@@ -1837,7 +1837,7 @@ forkProcess(HsStablePtr *entry
initMutex(&task->lock);
for (i=0; i < n_capabilities; i++) {
- initMutex(&capabilities[i].lock);
+ initMutex(&capabilities[i]->lock);
}
#endif
@@ -1871,7 +1871,7 @@ forkProcess(HsStablePtr *entry
discardTasksExcept(task);
for (i=0; i < n_capabilities; i++) {
- cap = &capabilities[i];
+ cap = capabilities[i];
// Empty the run queue. It seems tempting to let all the
// killed threads stay on the run queue as zombies to be
@@ -1900,7 +1900,7 @@ forkProcess(HsStablePtr *entry
releaseCapability(cap);
}
}
- cap = &capabilities[0];
+ cap = capabilities[0];
task->cap = cap;
// Empty the threads lists. Otherwise, the garbage
@@ -1965,8 +1965,7 @@ setNumCapabilities (nat new_n_capabilities USED_IF_THREADS)
Task *task;
Capability *cap;
nat sync;
- StgTSO* t;
- nat g, n;
+ nat n;
Capability *old_capabilities = NULL;
nat old_n_capabilities = n_capabilities;
@@ -2013,8 +2012,8 @@ setNumCapabilities (nat new_n_capabilities USED_IF_THREADS)
// structures, the nursery, etc.
//
for (n = new_n_capabilities; n < enabled_capabilities; n++) {
- capabilities[n].disabled = rtsTrue;
- traceCapDisable(&capabilities[n]);
+ capabilities[n]->disabled = rtsTrue;
+ traceCapDisable(capabilities[n]);
}
enabled_capabilities = new_n_capabilities;
}
@@ -2025,8 +2024,8 @@ setNumCapabilities (nat new_n_capabilities USED_IF_THREADS)
// enable any disabled capabilities, up to the required number
for (n = enabled_capabilities;
n < new_n_capabilities && n < n_capabilities; n++) {
- capabilities[n].disabled = rtsFalse;
- traceCapEnable(&capabilities[n]);
+ capabilities[n]->disabled = rtsFalse;
+ traceCapEnable(capabilities[n]);
}
enabled_capabilities = n;
@@ -2042,23 +2041,10 @@ setNumCapabilities (nat new_n_capabilities USED_IF_THREADS)
// Resize the capabilities array
// NB. after this, capabilities points somewhere new. Any pointers
// of type (Capability *) are now invalid.
- old_capabilities = moreCapabilities(n_capabilities, new_n_capabilities);
-
- // update our own cap pointer
- cap = &capabilities[cap->no];
+ moreCapabilities(n_capabilities, new_n_capabilities);
// Resize and update storage manager data structures
storageAddCapabilities(n_capabilities, new_n_capabilities);
-
- // Update (Capability *) refs in the Task manager.
- updateCapabilityRefs();
-
- // Update (Capability *) refs from TSOs
- for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
- for (t = generations[g].threads; t != END_TSO_QUEUE; t = t->global_link) {
- t->cap = &capabilities[t->cap->no];
- }
- }
}
}
@@ -2324,7 +2310,7 @@ scheduleThreadOn(Capability *cap, StgWord cpu USED_IF_THREADS, StgTSO *tso)
if (cpu == cap->no) {
appendToRunQueue(cap,tso);
} else {
- migrateThread(cap, tso, &capabilities[cpu]);
+ migrateThread(cap, tso, capabilities[cpu]);
}
#else
appendToRunQueue(cap,tso);
@@ -2407,7 +2393,7 @@ startWorkerTasks (nat from USED_IF_THREADS, nat to USED_IF_THREADS)
Capability *cap;
for (i = from; i < to; i++) {
- cap = &capabilities[i];
+ cap = capabilities[i];
ACQUIRE_LOCK(&cap->lock);
startWorkerTask(cap);
RELEASE_LOCK(&cap->lock);
@@ -2506,9 +2492,6 @@ freeScheduler( void )
// Capability).
if (still_running == 0) {
freeCapabilities();
- if (n_capabilities != 1) {
- stgFree(capabilities);
- }
}
RELEASE_LOCK(&sched_mutex);
#if defined(THREADED_RTS)
diff --git a/rts/Stats.c b/rts/Stats.c
index 3dc1ebe0fb..c19f23c59d 100644
--- a/rts/Stats.c
+++ b/rts/Stats.c
@@ -346,10 +346,10 @@ calcTotalAllocated(void)
W_ tot_alloc = 0;
W_ n;
for (n = 0; n < n_capabilities; n++) {
- tot_alloc += capabilities[n].total_allocated;
- traceEventHeapAllocated(&capabilities[n],
+ tot_alloc += capabilities[n]->total_allocated;
+ traceEventHeapAllocated(capabilities[n],
CAPSET_HEAP_DEFAULT,
- capabilities[n].total_allocated * sizeof(W_));
+ capabilities[n]->total_allocated * sizeof(W_));
}
return tot_alloc;
@@ -730,12 +730,12 @@ stat_exit (void)
nat i;
SparkCounters sparks = { 0, 0, 0, 0, 0, 0};
for (i = 0; i < n_capabilities; i++) {
- sparks.created += capabilities[i].spark_stats.created;
- sparks.dud += capabilities[i].spark_stats.dud;
- sparks.overflowed+= capabilities[i].spark_stats.overflowed;
- sparks.converted += capabilities[i].spark_stats.converted;
- sparks.gcd += capabilities[i].spark_stats.gcd;
- sparks.fizzled += capabilities[i].spark_stats.fizzled;
+ sparks.created += capabilities[i]->spark_stats.created;
+ sparks.dud += capabilities[i]->spark_stats.dud;
+ sparks.overflowed+= capabilities[i]->spark_stats.overflowed;
+ sparks.converted += capabilities[i]->spark_stats.converted;
+ sparks.gcd += capabilities[i]->spark_stats.gcd;
+ sparks.fizzled += capabilities[i]->spark_stats.fizzled;
}
statsPrintf(" SPARKS: %" FMT_Word " (%" FMT_Word " converted, %" FMT_Word " overflowed, %" FMT_Word " dud, %" FMT_Word " GC'd, %" FMT_Word " fizzled)\n\n",
@@ -900,10 +900,10 @@ statDescribeGens(void)
mut = 0;
for (i = 0; i < n_capabilities; i++) {
- mut += countOccupied(capabilities[i].mut_lists[g]);
+ mut += countOccupied(capabilities[i]->mut_lists[g]);
// Add the pinned object block.
- bd = capabilities[i].pinned_object_block;
+ bd = capabilities[i]->pinned_object_block;
if (bd != NULL) {
gen_live += bd->free - bd->start;
gen_blocks += bd->blocks;
@@ -999,12 +999,12 @@ extern void getSparkStats( SparkCounters *s ) {
s->gcd = 0;
s->fizzled = 0;
for (i = 0; i < n_capabilities; i++) {
- s->created += capabilities[i].spark_stats.created;
- s->dud += capabilities[i].spark_stats.dud;
- s->overflowed+= capabilities[i].spark_stats.overflowed;
- s->converted += capabilities[i].spark_stats.converted;
- s->gcd += capabilities[i].spark_stats.gcd;
- s->fizzled += capabilities[i].spark_stats.fizzled;
+ s->created += capabilities[i]->spark_stats.created;
+ s->dud += capabilities[i]->spark_stats.dud;
+ s->overflowed+= capabilities[i]->spark_stats.overflowed;
+ s->converted += capabilities[i]->spark_stats.converted;
+ s->gcd += capabilities[i]->spark_stats.gcd;
+ s->fizzled += capabilities[i]->spark_stats.fizzled;
}
}
#endif
diff --git a/rts/Task.c b/rts/Task.c
index e6781a17ff..a044bc3672 100644
--- a/rts/Task.c
+++ b/rts/Task.c
@@ -326,34 +326,6 @@ discardTasksExcept (Task *keep)
RELEASE_LOCK(&all_tasks_mutex);
}
-//
-// After the capabilities[] array has moved, we have to adjust all
-// (Capability *) pointers to point to the new array. The old array
-// is still valid at this point.
-//
-void updateCapabilityRefs (void)
-{
- Task *task;
- InCall *incall;
-
- ACQUIRE_LOCK(&all_tasks_mutex);
-
- for (task = all_tasks; task != NULL; task=task->all_next) {
- if (task->cap != NULL) {
- task->cap = &capabilities[task->cap->no];
- }
-
- for (incall = task->incall; incall != NULL; incall = incall->prev_stack) {
- if (incall->suspended_cap != NULL) {
- incall->suspended_cap = &capabilities[incall->suspended_cap->no];
- }
- }
- }
-
- RELEASE_LOCK(&all_tasks_mutex);
-}
-
-
#if defined(THREADED_RTS)
void
diff --git a/rts/Task.h b/rts/Task.h
index f18f154117..052647b327 100644
--- a/rts/Task.h
+++ b/rts/Task.h
@@ -213,11 +213,6 @@ void interruptWorkerTask (Task *task);
#endif /* THREADED_RTS */
-// Update any (Capability *) pointers belonging to Tasks after the
-// Capability array is moved/resized.
-//
-void updateCapabilityRefs (void);
-
// For stats
extern nat taskCount;
extern nat workerCount;
diff --git a/rts/Threads.c b/rts/Threads.c
index f2b800512e..14fb7e872c 100644
--- a/rts/Threads.c
+++ b/rts/Threads.c
@@ -801,7 +801,7 @@ printAllThreads(void)
debugBelch("all threads:\n");
for (i = 0; i < n_capabilities; i++) {
- cap = &capabilities[i];
+ cap = capabilities[i];
debugBelch("threads on capability %d:\n", cap->no);
for (t = cap->run_queue_hd; t != END_TSO_QUEUE; t = t->_link) {
printThreadStatus(t);
diff --git a/rts/Timer.c b/rts/Timer.c
index aa4b8d8fd7..b7762f985c 100644
--- a/rts/Timer.c
+++ b/rts/Timer.c
@@ -119,7 +119,7 @@ startTimer(void)
void
stopTimer(void)
{
- if (atomic_inc(&timer_disabled) == 1) {
+ if (atomic_inc(&timer_disabled, 1) == 1) {
if (RtsFlags.MiscFlags.tickInterval != 0) {
stopTicker();
}
diff --git a/rts/sm/Compact.c b/rts/sm/Compact.c
index 247f1a01c6..375aeea2f2 100644
--- a/rts/sm/Compact.c
+++ b/rts/sm/Compact.c
@@ -933,7 +933,7 @@ compact(StgClosure *static_objects)
bdescr *bd;
StgPtr p;
for (n = 0; n < n_capabilities; n++) {
- for (bd = capabilities[n].mut_lists[g];
+ for (bd = capabilities[n]->mut_lists[g];
bd != NULL; bd = bd->link) {
for (p = bd->start; p < bd->free; p++) {
thread((StgClosure **)p);
diff --git a/rts/sm/GC.c b/rts/sm/GC.c
index 1b2cb12212..6fd3b1b1c9 100644
--- a/rts/sm/GC.c
+++ b/rts/sm/GC.c
@@ -236,8 +236,8 @@ GarbageCollect (nat collect_gen,
// attribute any costs to CCS_GC
#ifdef PROFILING
for (n = 0; n < n_capabilities; n++) {
- save_CCS[n] = capabilities[n].r.rCCCS;
- capabilities[n].r.rCCCS = CCS_GC;
+ save_CCS[n] = capabilities[n]->r.rCCCS;
+ capabilities[n]->r.rCCCS = CCS_GC;
}
#endif
@@ -339,18 +339,18 @@ GarbageCollect (nat collect_gen,
if (n_gc_threads == 1) {
for (n = 0; n < n_capabilities; n++) {
#if defined(THREADED_RTS)
- scavenge_capability_mut_Lists1(&capabilities[n]);
+ scavenge_capability_mut_Lists1(capabilities[n]);
#else
- scavenge_capability_mut_lists(&capabilities[n]);
+ scavenge_capability_mut_lists(capabilities[n]);
#endif
}
} else {
scavenge_capability_mut_lists(gct->cap);
for (n = 0; n < n_capabilities; n++) {
if (gc_threads[n]->idle) {
- markCapability(mark_root, gct, &capabilities[n],
+ markCapability(mark_root, gct, capabilities[n],
rtsTrue/*don't mark sparks*/);
- scavenge_capability_mut_lists(&capabilities[n]);
+ scavenge_capability_mut_lists(capabilities[n]);
}
}
}
@@ -363,7 +363,7 @@ GarbageCollect (nat collect_gen,
gct->evac_gen_no = 0;
if (n_gc_threads == 1) {
for (n = 0; n < n_capabilities; n++) {
- markCapability(mark_root, gct, &capabilities[n],
+ markCapability(mark_root, gct, capabilities[n],
rtsTrue/*don't mark sparks*/);
}
} else {
@@ -417,12 +417,12 @@ GarbageCollect (nat collect_gen,
#ifdef THREADED_RTS
if (n_gc_threads == 1) {
for (n = 0; n < n_capabilities; n++) {
- pruneSparkQueue(&capabilities[n]);
+ pruneSparkQueue(capabilities[n]);
}
} else {
for (n = 0; n < n_capabilities; n++) {
if (n == cap->no || gc_threads[n]->idle) {
- pruneSparkQueue(&capabilities[n]);
+ pruneSparkQueue(capabilities[n]);
}
}
}
@@ -495,7 +495,7 @@ GarbageCollect (nat collect_gen,
if (g > 0) {
W_ mut_list_size = 0;
for (n = 0; n < n_capabilities; n++) {
- mut_list_size += countOccupied(capabilities[n].mut_lists[g]);
+ mut_list_size += countOccupied(capabilities[n]->mut_lists[g]);
}
copied += mut_list_size;
@@ -646,14 +646,14 @@ GarbageCollect (nat collect_gen,
// Reset the nursery: make the blocks empty
if (DEBUG_IS_ON || n_gc_threads == 1) {
for (n = 0; n < n_capabilities; n++) {
- clearNursery(&capabilities[n]);
+ clearNursery(capabilities[n]);
}
} else {
// When doing parallel GC, clearNursery() is called by the
// worker threads
for (n = 0; n < n_capabilities; n++) {
if (gc_threads[n]->idle) {
- clearNursery(&capabilities[n]);
+ clearNursery(capabilities[n]);
}
}
}
@@ -753,7 +753,7 @@ GarbageCollect (nat collect_gen,
// restore enclosing cost centre
#ifdef PROFILING
for (n = 0; n < n_capabilities; n++) {
- capabilities[n].r.rCCCS = save_CCS[n];
+ capabilities[n]->r.rCCCS = save_CCS[n];
}
#endif
@@ -794,7 +794,7 @@ new_gc_thread (nat n, gc_thread *t)
nat g;
gen_workspace *ws;
- t->cap = &capabilities[n];
+ t->cap = capabilities[n];
#ifdef THREADED_RTS
t->id = 0;
@@ -866,12 +866,6 @@ initGcThreads (nat from USED_IF_THREADS, nat to USED_IF_THREADS)
"initGcThreads");
}
- // We have to update the gct->cap pointers to point to the new
- // Capability array now.
- for (i = 0; i < from; i++) {
- gc_threads[i]->cap = &capabilities[gc_threads[i]->cap->no];
- }
-
for (i = from; i < to; i++) {
gc_threads[i] =
stgMallocBytes(sizeof(gc_thread) +
@@ -924,7 +918,7 @@ static StgWord
inc_running (void)
{
StgWord new;
- new = atomic_inc(&gc_running_threads);
+ new = atomic_inc(&gc_running_threads, 1);
ASSERT(new <= n_gc_threads);
return new;
}
@@ -1124,7 +1118,7 @@ waitForGcThreads (Capability *cap USED_IF_THREADS)
for (i=0; i < n_threads; i++) {
if (i == me || gc_threads[i]->idle) continue;
if (gc_threads[i]->wakeup != GC_THREAD_STANDING_BY) {
- prodCapability(&capabilities[i], cap->running_task);
+ prodCapability(capabilities[i], cap->running_task);
}
}
for (j=0; j < 10; j++) {
@@ -1132,7 +1126,7 @@ waitForGcThreads (Capability *cap USED_IF_THREADS)
for (i=0; i < n_threads; i++) {
if (i == me || gc_threads[i]->idle) continue;
write_barrier();
- interruptCapability(&capabilities[i]);
+ interruptCapability(capabilities[i]);
if (gc_threads[i]->wakeup != GC_THREAD_STANDING_BY) {
retry = rtsTrue;
}
@@ -1228,8 +1222,8 @@ prepare_collected_gen (generation *gen)
g = gen->no;
if (g != 0) {
for (i = 0; i < n_capabilities; i++) {
- freeChain(capabilities[i].mut_lists[g]);
- capabilities[i].mut_lists[g] = allocBlock();
+ freeChain(capabilities[i]->mut_lists[g]);
+ capabilities[i]->mut_lists[g] = allocBlock();
}
}
@@ -1360,7 +1354,7 @@ prepare_uncollected_gen (generation *gen)
// allocate a fresh block for each one. We'll traverse these
// mutable lists as roots early on in the GC.
for (i = 0; i < n_capabilities; i++) {
- stash_mut_list(&capabilities[i], gen->no);
+ stash_mut_list(capabilities[i], gen->no);
}
ASSERT(gen->scavenged_large_objects == NULL);
@@ -1429,7 +1423,7 @@ collect_pinned_object_blocks (void)
for (n = 0; n < n_capabilities; n++) {
prev = NULL;
- for (bd = capabilities[n].pinned_object_blocks; bd != NULL; bd = bd->link) {
+ for (bd = capabilities[n]->pinned_object_blocks; bd != NULL; bd = bd->link) {
prev = bd;
}
if (prev != NULL) {
@@ -1437,8 +1431,8 @@ collect_pinned_object_blocks (void)
if (g0->large_objects != NULL) {
g0->large_objects->u.back = prev;
}
- g0->large_objects = capabilities[n].pinned_object_blocks;
- capabilities[n].pinned_object_blocks = 0;
+ g0->large_objects = capabilities[n]->pinned_object_blocks;
+ capabilities[n]->pinned_object_blocks = 0;
}
}
}
diff --git a/rts/sm/Sanity.c b/rts/sm/Sanity.c
index 9b579abbbc..0d48ba2724 100644
--- a/rts/sm/Sanity.c
+++ b/rts/sm/Sanity.c
@@ -615,7 +615,7 @@ checkLocalMutableLists (nat cap_no)
{
nat g;
for (g = 1; g < RtsFlags.GcFlags.generations; g++) {
- checkMutableList(capabilities[cap_no].mut_lists[g], g);
+ checkMutableList(capabilities[cap_no]->mut_lists[g], g);
}
}
@@ -756,7 +756,7 @@ findMemoryLeak (void)
nat g, i;
for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
for (i = 0; i < n_capabilities; i++) {
- markBlocks(capabilities[i].mut_lists[g]);
+ markBlocks(capabilities[i]->mut_lists[g]);
markBlocks(gc_threads[i]->gens[g].part_list);
markBlocks(gc_threads[i]->gens[g].scavd_list);
markBlocks(gc_threads[i]->gens[g].todo_bd);
@@ -767,7 +767,7 @@ findMemoryLeak (void)
for (i = 0; i < n_capabilities; i++) {
markBlocks(nurseries[i].blocks);
- markBlocks(capabilities[i].pinned_object_block);
+ markBlocks(capabilities[i]->pinned_object_block);
}
#ifdef PROFILING
@@ -847,7 +847,7 @@ memInventory (rtsBool show)
for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
gen_blocks[g] = 0;
for (i = 0; i < n_capabilities; i++) {
- gen_blocks[g] += countBlocks(capabilities[i].mut_lists[g]);
+ gen_blocks[g] += countBlocks(capabilities[i]->mut_lists[g]);
gen_blocks[g] += countBlocks(gc_threads[i]->gens[g].part_list);
gen_blocks[g] += countBlocks(gc_threads[i]->gens[g].scavd_list);
gen_blocks[g] += countBlocks(gc_threads[i]->gens[g].todo_bd);
@@ -859,10 +859,10 @@ memInventory (rtsBool show)
for (i = 0; i < n_capabilities; i++) {
ASSERT(countBlocks(nurseries[i].blocks) == nurseries[i].n_blocks);
nursery_blocks += nurseries[i].n_blocks;
- if (capabilities[i].pinned_object_block != NULL) {
- nursery_blocks += capabilities[i].pinned_object_block->blocks;
+ if (capabilities[i]->pinned_object_block != NULL) {
+ nursery_blocks += capabilities[i]->pinned_object_block->blocks;
}
- nursery_blocks += countBlocks(capabilities[i].pinned_object_blocks);
+ nursery_blocks += countBlocks(capabilities[i]->pinned_object_blocks);
}
retainer_blocks = 0;
diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c
index a5337bc5b2..b575fc3e52 100644
--- a/rts/sm/Storage.c
+++ b/rts/sm/Storage.c
@@ -215,7 +215,7 @@ void storageAddCapabilities (nat from, nat to)
// we've moved the nurseries, so we have to update the rNursery
// pointers from the Capabilities.
for (i = 0; i < to; i++) {
- capabilities[i].r.rNursery = &nurseries[i];
+ capabilities[i]->r.rNursery = &nurseries[i];
}
/* The allocation area. Policy: keep the allocation area
@@ -229,7 +229,7 @@ void storageAddCapabilities (nat from, nat to)
// allocate a block for each mut list
for (n = from; n < to; n++) {
for (g = 1; g < RtsFlags.GcFlags.generations; g++) {
- capabilities[n].mut_lists[g] = allocBlock();
+ capabilities[n]->mut_lists[g] = allocBlock();
}
}
@@ -493,8 +493,8 @@ assignNurseriesToCapabilities (nat from, nat to)
nat i;
for (i = from; i < to; i++) {
- capabilities[i].r.rCurrentNursery = nurseries[i].blocks;
- capabilities[i].r.rCurrentAlloc = NULL;
+ capabilities[i]->r.rCurrentNursery = nurseries[i].blocks;
+ capabilities[i]->r.rCurrentAlloc = NULL;
}
}
@@ -939,7 +939,7 @@ void updateNurseriesStats (void)
nat i;
for (i = 0; i < n_capabilities; i++) {
- capabilities[i].total_allocated += countOccupied(nurseries[i].blocks);
+ capabilities[i]->total_allocated += countOccupied(nurseries[i].blocks);
}
}
diff --git a/rules/shell-wrapper.mk b/rules/shell-wrapper.mk
index b23e385035..5672f36877 100644
--- a/rules/shell-wrapper.mk
+++ b/rules/shell-wrapper.mk
@@ -62,7 +62,7 @@ ifeq "$$($1_$2_INSTALL_SHELL_WRAPPER_NAME)" ""
$1_$2_INSTALL_SHELL_WRAPPER_NAME = $$($1_$2_PROG)
endif
-# Install the binary in $(libexecdir), and install a shell wrapper in $(bindir)
+# Install the binary in $(ghclibexecdir), and install a shell wrapper in $(bindir)
INSTALL_LIBEXECS += $1/$2/build/tmp/$$($1_$2_PROG)
BINDIST_WRAPPERS += $$($1_$2_SHELL_WRAPPER_NAME)
diff --git a/sync-all b/sync-all
index 85a697af52..f37c37996c 100755
--- a/sync-all
+++ b/sync-all
@@ -50,11 +50,12 @@ sub parsePackages {
foreach (@repos) {
chomp;
$lineNum++;
- if (/^([^# ]+) +([^ ]+) +([^ ]+)$/) {
+ if (/^([^# ]+) +([^ ]+) +([^ ]+) +([^ ]+)$/) {
my %line;
$line{"localpath"} = $1;
$line{"tag"} = $2;
$line{"remotepath"} = $3;
+ $line{"upstreamurl"}= $4;
push @packages, \%line;
$tags{$2} = 0;
diff --git a/utils/hp2ps/Axes.c b/utils/hp2ps/Axes.c
index 4c2e4f5e95..adc3c45146 100644
--- a/utils/hp2ps/Axes.c
+++ b/utils/hp2ps/Axes.c
@@ -203,14 +203,18 @@ Round(floatish y)
int i;
if (y > 10.0) {
- for (i = 0; y > 10.0; y /= 10.0, i++) ;
+ for (i = 0; y > 10.0; y /= 10.0, i++)
+ ;
y = OneTwoFive(y);
- for ( ; i > 0; y = y * 10.0, i--) ;
+ for ( ; i > 0; y = y * 10.0, i--)
+ ;
} else if (y < 1.0) {
- for (i = 0; y < 1.0; y *= 10.0, i++) ;
+ for (i = 0; y < 1.0; y *= 10.0, i++)
+ ;
y = OneTwoFive(y);
- for ( ; i > 0; y = y / 10.0, i--) ;
+ for ( ; i > 0; y = y / 10.0, i--)
+ ;
} else {
y = OneTwoFive(y);
diff --git a/validate b/validate
index 170bb2db25..95425d3770 100755
--- a/validate
+++ b/validate
@@ -1,21 +1,37 @@
#!/bin/sh
-# Flags:
-# --no-clean: don't make clean first, just carry on from
-# a previous interrupted validation run
-# --testsuite-only: don't build the compiler, just run
-# the test suite
-# --hpc: build stage2 with -fhpc, and see how much of the
-# compiler the test suite covers.
-# 2008-07-01: 63% slower than the default.
-# HTML generated here: testsuite/hpc_output/hpc_index.html
-# --normal: Default settings
-# --fast: Omit dyn way, omit binary distribution
-# --slow: Build stage2 with -DDEBUG.
-# 2008-07-01: 14% slower than the default.
-
set -e
+show_help () {
+ cat <<EOF
+Usage: $0 [FLAGS]...
+
+Validate GHC source tree against testsuite; see
+http://ghc.haskell.org/trac/ghc/wiki/TestingPatches for more
+information.
+
+Flags:
+ --no-clean don't make clean first, just carry on from
+ a previous interrupted validation run
+ --testsuite-only don't build the compiler, just run the test suite
+ --hpc build stage2 with -fhpc, and see how much of the
+ compiler the test suite covers.
+ 2008-07-01: 63% slower than the default.
+ HTML generated here: testsuite/hpc_output/hpc_index.html
+ --normal Default settings
+ --fast Omit dyn way, omit binary distribution
+ --slow Build stage2 with -DDEBUG.
+ 2008-07-01: 14% slower than the default.
+ --help shows this usage help.
+
+ Set environment variable 'CPUS' to number of cores, to exploit
+ multiple cpu cores, e.g.
+
+ CPUS=8 ./validate
+
+EOF
+}
+
no_clean=0
testsuite_only=0
hpc=NO
@@ -42,8 +58,12 @@ do
--normal)
speed=NORMAL
;;
+ --help)
+ show_help
+ exit 0;;
*)
- echo "Bad argument: $1" >&2
+ echo "$0: unrecognized argument '$1'" >&2
+ echo "Try '$0 --help' for more information." >&2
exit 1;;
esac
shift