summaryrefslogtreecommitdiff
path: root/compiler/codeGen/StgCmmExpr.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/codeGen/StgCmmExpr.hs')
-rw-r--r--compiler/codeGen/StgCmmExpr.hs78
1 files changed, 55 insertions, 23 deletions
diff --git a/compiler/codeGen/StgCmmExpr.hs b/compiler/codeGen/StgCmmExpr.hs
index 480cc3329a..7d2ef78620 100644
--- a/compiler/codeGen/StgCmmExpr.hs
+++ b/compiler/codeGen/StgCmmExpr.hs
@@ -355,30 +355,59 @@ of Bool-returning primops was that tagToEnum# was added implicitly in the
codegen and then optimized away. Now the call to tagToEnum# is explicit
in the source code, which allows to optimize it away at the earlier stages
of compilation (i.e. at the Core level).
+
+Note [Scrutinising VoidRep]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Suppose we have this STG code:
+ f = \[s : State# RealWorld] ->
+ case s of _ -> blah
+This is very odd. Why are we scrutinising a state token? But it
+can arise with bizarre NOINLINE pragmas (Trac #9964)
+ crash :: IO ()
+ crash = IO (\s -> let {-# NOINLINE s' #-}
+ s' = s
+ in (# s', () #))
+
+Now the trouble is that 's' has VoidRep, and we do not bind void
+arguments in the environment; they don't live anywhere. See the
+calls to nonVoidIds in various places. So we must not look up
+'s' in the environment. Instead, just evaluate the RHS! Simple.
+
+Note [Dodgy unsafeCoerce 1]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider
+ case (x :: MutVar# Int) |> co of (y :: HValue)
+ DEFAULT -> ...
+We want to gnerate an assignment
+ y := x
+We want to allow this assignment to be generated in the case when the
+types are compatible, because this allows some slightly-dodgy but
+occasionally-useful casts to be used, such as in RtClosureInspect
+where we cast an HValue to a MutVar# so we can print out the contents
+of the MutVar#. If instead we generate code that enters the HValue,
+then we'll get a runtime panic, because the HValue really is a
+MutVar#. The types are compatible though, so we can just generate an
+assignment.
+
+Note [Dodgy unsafeCoerce 2]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Note [ticket #3132]: we might be looking at a case of a lifted Id that
+was cast to an unlifted type. The Id will always be bottom, but we
+don't want the code generator to fall over here. If we just emit an
+assignment here, the assignment will be type-incorrect Cmm. Hence, we
+emit the usual enter/return code, (and because bottom must be
+untagged, it will be entered and the program will crash). The Sequel
+is a type-correct assignment, albeit bogus. The (dead) continuation
+loops; it would be better to invoke some kind of panic function here.
-}
+cgCase (StgApp v []) _ (PrimAlt _) alts
+ | isVoidRep (idPrimRep v) -- See Note [Scrutinising VoidRep]
+ , [(DEFAULT, _, _, rhs)] <- alts
+ = cgExpr rhs
- -- Note [ticket #3132]: we might be looking at a case of a lifted Id
- -- that was cast to an unlifted type. The Id will always be bottom,
- -- but we don't want the code generator to fall over here. If we
- -- just emit an assignment here, the assignment will be
- -- type-incorrect Cmm. Hence, we emit the usual enter/return code,
- -- (and because bottom must be untagged, it will be entered and the
- -- program will crash).
- -- The Sequel is a type-correct assignment, albeit bogus.
- -- The (dead) continuation loops; it would be better to invoke some kind
- -- of panic function here.
- --
- -- However, we also want to allow an assignment to be generated
- -- in the case when the types are compatible, because this allows
- -- some slightly-dodgy but occasionally-useful casts to be used,
- -- such as in RtClosureInspect where we cast an HValue to a MutVar#
- -- so we can print out the contents of the MutVar#. If we generate
- -- code that enters the HValue, then we'll get a runtime panic, because
- -- the HValue really is a MutVar#. The types are compatible though,
- -- so we can just generate an assignment.
cgCase (StgApp v []) bndr alt_type@(PrimAlt _) alts
- | isUnLiftedType (idType v)
+ | isUnLiftedType (idType v) -- Note [Dodgy unsafeCoerce 1]
|| reps_compatible
= -- assignment suffices for unlifted types
do { dflags <- getDynFlags
@@ -392,7 +421,7 @@ cgCase (StgApp v []) bndr alt_type@(PrimAlt _) alts
reps_compatible = idPrimRep v == idPrimRep bndr
cgCase scrut@(StgApp v []) _ (PrimAlt _) _
- = -- fail at run-time, not compile-time
+ = -- See Note [Dodgy unsafeCoerce 2]
do { dflags <- getDynFlags
; mb_cc <- maybeSaveCostCentre True
; _ <- withSequel (AssignTo [idToReg dflags (NonVoid v)] False) (cgExpr scrut)
@@ -403,7 +432,9 @@ cgCase scrut@(StgApp v []) _ (PrimAlt _) _
; emit (mkBranch l)
; return AssignedDirectly
}
-{-
+
+{- Note [Handle seq#]
+~~~~~~~~~~~~~~~~~~~~~
case seq# a s of v
(# s', a' #) -> e
@@ -417,7 +448,8 @@ is the same as the return convention for just 'a')
-}
cgCase (StgOpApp (StgPrimOp SeqOp) [StgVarArg a, _] _) bndr alt_type alts
- = -- handle seq#, same return convention as vanilla 'a'.
+ = -- Note [Handle seq#]
+ -- Use the same return convention as vanilla 'a'.
cgCase (StgApp a []) bndr alt_type alts
cgCase scrut bndr alt_type alts