[GHC] #14430: lintUnfolding does not allow unfoldings to jump to enclosing join points
GHC
ghc-devs at haskell.org
Mon Nov 6 19:08:59 UTC 2017
#14430: lintUnfolding does not allow unfoldings to jump to enclosing join points
-------------------------------------+-------------------------------------
Reporter: nomeata | Owner: (none)
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.3
Keywords: | Operating System: Unknown/Multiple
Architecture: | Type of failure: None/Unknown
Unknown/Multiple |
Test Case: | Blocked By:
Blocking: | Related Tickets:
Differential Rev(s): | Wiki Page:
-------------------------------------+-------------------------------------
I am not sure why this does not show up in HEAD but it does show up in my
loopification branch. It does look like a bug in GHC to me.
With loopification, I get the following code in the interface of
`Foreign.C.String`:
{{{
d5fd65f7834390bebd0e80edc7b8f627
withCAStringLen1 ::
String
-> (CStringLen -> IO a)
-> State# RealWorld
-> (# State# RealWorld, a #)
{- Arity: 3, HasNoCafRefs,
Strictness: <S,U><C(C(S(SL))),C(C1(U(U,U)))><S,U>,
Unfolding: (\ @ a
(str :: String)
(f :: CStringLen -> IO a)
(eta :: State# RealWorld) ->
case lenAcc @ Char str newCAString2 of wild { I# x ->
case newAlignedPinnedByteArray#
@ RealWorld
x
1#
eta of ds2 { (#,#) ipv ipv1 ->
case unsafeFreezeByteArray#
@ RealWorld
ipv1
ipv of ds3 { (#,#) ipv2 ipv3 ->
let {
ptr :: Addr# = byteArrayContents# ipv3
} in
let {
$j :: State# RealWorld -> () -> (# State# RealWorld, a
#)
<join 2> {- Arity: 2, Strictness: <S,U><L,A>, Inline:
[0],
Unfolding: InlineRule (2, True, False)
(\ (w :: State# RealWorld) (w1
:: ()) ->
case (f (Ptr @ CChar ptr,
wild)) `cast` (N:IO[0] <a>_R)
w of ds4 { (#,#) ipv4
ipv5 ->
case touch#
@ 'UnliftedRep
@ ByteArray#
ipv3
ipv4 of s4 { DEFAULT
->
(# s4, ipv5 #) } }) -}
= \ (w :: State# RealWorld)[OneShot] (w1 ::
())[OneShot] ->
case (f (Ptr @ CChar ptr, wild)) `cast` (N:IO[0]
<a>_R)
w of ds4 { (#,#) ipv4 ipv5 ->
case touch#
@ 'UnliftedRep
@ ByteArray#
ipv3
ipv4 of s4 { DEFAULT ->
(# s4, ipv5 #) } }
} in
let {
go :: [Char]
-> Int -> State# RealWorld -> (# State#
RealWorld, a #)
<join 3> {- Arity: 3, Strictness:
<S,1*U><S(S),1*U(U)><S,U>,
Inline: [~],
Unfolding: InlineRule (3, True, False)
(\ (ds :: [Char])[OneShot]
(n :: Int)[OneShot]
(eta1 :: State#
RealWorld)[OneShot] ->
letrec {
go :: [Char]
-> Int
-> State# RealWorld
-> (# State#
RealWorld, a #)
<join 3> {- Arity: 3 -}
= \ (ds1 :: [Char])
(n1 :: Int)
(eta2 :: State#
RealWorld) ->
case ds1 of wild1 {
[] -> case n1 of n2 {
I# ipv4 -> $j eta2 () }
: c cs
-> case n1 of wild2 {
I# i ->
case c of wild3 { C#
c# ->
case
writeInt8OffAddr#
@ RealWorld
ptr
i
(narrow8Int#
(ord# c#))
eta2 of s2 {
DEFAULT ->
go cs (I# (+# i 1#))
s2 } } } }
} in
go ds n eta1) -}
= \ (ds :: [Char])[OneShot]
(n :: Int)[OneShot]
(eta1 :: State# RealWorld)[OneShot] ->
case n of ww { I# ww1 ->
let {
exit :: State# RealWorld -> (# State# RealWorld, a
#)
<join 1> {- Arity: 1, Strictness: <S,U> -}
= \ (w :: State# RealWorld)[OneShot] ->
case (f (Ptr @ CChar ptr, wild)) `cast` (N:IO[0]
<a>_R)
w of ds4 { (#,#) ipv4 ipv5 ->
case touch#
@ 'UnliftedRep
@ ByteArray#
ipv3
ipv4 of s4 { DEFAULT ->
(# s4, ipv5 #) } }
} in
letrec {
$wgo :: [Char]
-> Int# -> State# RealWorld -> (# State#
RealWorld, a #)
<join 3> {- Arity: 3, Strictness:
<S,1*U><L,U><S,U>, Inline: [0] -}
= \ (w :: [Char]) (ww2 :: Int#) (w1 :: State#
RealWorld) ->
case w of wild1 {
[] -> exit w1
: c cs
-> case c of wild2 { C# c# ->
case writeInt8OffAddr#
@ RealWorld
ptr
ww2
(narrow8Int# (ord# c#))
w1 of s2 { DEFAULT ->
$wgo cs (+# ww2 1#) s2 } } }
} in
$wgo ds ww1 eta1 }
} in
go str newCAString2 ipv2 } } }) -}
}}}
Note how `go` references `j` not only in its RHS, but also in its
unfolding.
When loading this interface, I get this error:
{{{
HC [stage 1] libraries/base/dist-install/build/System/Posix/Internals.o
ghc-stage1: panic! (the 'impossible' happened)
(GHC version 8.3.20171101 for x86_64-unknown-linux):
Iface Lint failure
In interface for Foreign.C.String
Unfolding of go_a6h7
<no location info>: warning:
In the expression: jump $j_a6gX eta2_a6hS ()
Invalid occurrence of a join variable: $j_a6gX
The binder is either not a join point, or not valid here
go_a6h7 = \ (ds_a6hM [OS=OneShot] :: [Char])
(n_a6hN [OS=OneShot] :: Int)
(eta1_a6hO [OS=OneShot] :: State# RealWorld) ->
joinrec {
go_a6hP
:: [Char]
-> Int -> State# RealWorld -> (# State# RealWorld,
a_a6gD #)
[LclId[JoinId(3)], Arity=3]
go_a6hP (ds1_a6hQ :: [Char])
(n1_a6hR :: Int)
(eta2_a6hS :: State# RealWorld)
= case ds1_a6hQ of wild1_a6hT {
[] ->
case n1_a6hR of n2_a6hW { I# ipv4_a6hY ->
jump $j_a6gX eta2_a6hS ()
};
: c_a6i1 cs_a6i2 ->
case n1_a6hR of wild2_a6i4 { I# i_a6i6 ->
case c_a6i1 of wild3_a6i8 { C# c#_a6ia ->
case writeInt8OffAddr#
@ RealWorld ptr_a6gT i_a6i6 (narrow8Int#
(ord# c#_a6ia)) eta2_a6hS
of s2_a6ic
{ __DEFAULT ->
jump go_a6hP cs_a6i2 (I# (+# i_a6i6 1#)) s2_a6ic
}
}
}
}; } in
jump go_a6hP ds_a6hM n_a6hN eta1_a6hO
Iface expr = \ (ds :: [Char])[OneShot]
(n :: Int)[OneShot]
(eta1 :: State# RealWorld)[OneShot] ->
letrec {
go :: [Char]
-> Int -> State# RealWorld -> (# State# RealWorld,
a #)
<join 3> {- Arity: 3 -}
= \ (ds1 :: [Char]) (n1 :: Int) (eta2 :: State#
RealWorld) ->
case ds1 of wild1 {
[] -> case n1 of n2 { I# ipv4 -> $j eta2 () }
: c cs
-> case n1 of wild2 { I# i ->
case c of wild3 { C# c# ->
case writeInt8OffAddr#
@ RealWorld
ptr
i
(narrow8Int# (ord# c#))
eta2 of s2 { DEFAULT ->
go cs (I# (+# i 1#)) s2 } } } }
} in
go ds n eta1
Call stack:
CallStack (from HasCallStack):
callStackDoc, called at compiler/utils/Outputable.hs:1147:37 in
ghc:Outputable
pprPanic, called at compiler/iface/TcIface.hs:1664:33 in
ghc:TcIface
}}}
When reading the code in `tcPragExpr` I see that it lints the unfolding of
`go` using `lintUnfolding`, which initializes the `LintM` with an empty
`le_joins`. But when linting `go`, the join `j` is valid, even in the
unfolding, isn't it?
Unless of course I just don’t see the problem with the above unfolding,
and am barking up the wrong tree.
Anyways, either there is a problem in how we lint the unfoldings, or there
is a secret invariant that I violated with my patch
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14430>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list