
#15570: Core transformations generate bad indexCharOffAddr# call
-------------------------------------+-------------------------------------
Reporter: alpmestan | Owner: alpmestan
Type: bug | Status: new
Priority: normal | Milestone: 8.6.1
Component: Compiler | Version: 8.5
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: None/Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by simonpj):
No I can repro, I can return to the OP.
I'm deeply puzzled about the case-match on `GHC.Real.even3`. But leaving
that aside,
I'm not so sure that the Core shown in the Description is wrong. After
all, suppose
we made the call
{{{
f -9223372036854775808
}}}
Then we'd get into the `n<62` branch, so we'd call `chooseChar62` of that
ridiculous number.
So semantically, while the code is very strange, it's not actually wrong.
'''So why do you get a link error'''? I think that is a bug all by
itself.
If I write
{{{
x = C# (indexCharOffAddr# "foo"# -9223372036854775808#)
}}}
that might seg-fault at runtime, but it should not cause a link error.
-------------------
How can stupid code like this arise? Consider
{{{
h :: Int# -> Int#
h x = let !t = case x of
-1000# -> 4#
_ -> x
in
t +# indexIntOffAddr# "foo"# x)
}}}
Notice that `h` unconditionally indexes the string with `x` (just like `f`
does in the
Description); presumably the caller is going to guaranteed that `x` is in
bounds.
That turns into
{{{
h x = case (case x of { -1000 -> 4#; _ -> x }) of
t -> t +# indexIntOffAddr# "foo"# x
}}}
Now case-of-case produces
{{{
h x = case x of
-1000 -> 4# +# indexIntOffAddr# "foo#" x
_ -> x +# indexIntOffAddr# "foo#" x
}}}
But in the top branch we know that `x` is `-1000`, so we finally get
{{{
h x = case x of
-1000 -> 4# +# indexIntOffAddr# "foo#" -1000
_ -> x +# indexIntOffAddr# "foo#" x
}}}
This is, in essence, what is happening in the Description. And it should
jolly well
be fine.
Of course, if the caller never calls the function with `-1000` as the
argument,
the top branch will never be executed.
------------------
So my claim so far is: the code is correct; and it's a bug that we get a
linker error.
However the code, while correct, is TERRIBLE. For this function (similar
to Description, slightly simplified)
{{{
go :: Int -> [Char] -> [Char]
go n cs | n < 62
= let !c = chooseChar62 n in c : cs
| otherwise
= go q cs
where
!(q, _) = quotRem n 62
}}}
HEAD produces the very civilised result
{{{
Bug.$wgo [InlPrag=NOUSERINLINE[2], Occ=LoopBreaker]
:: Int# -> [Char] -> (# Char, [Char] #)
[GblId, Arity=2, Caf=NoCafRefs, Str=