#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=<S,U><L,U>, Unf=OtherCon []] Bug.$wgo = \ (ww_s2Ag :: Int#) (w_s2Ad :: [Char]) -> case quotRemInt# ww_s2Ag 62# of { (# ipv_a2yf, ipv1_a2yg #) -> case <# ww_s2Ag 62# of { __DEFAULT -> Bug.$wgo ipv_a2yf w_s2Ad; 1# -> case indexCharOffAddr# lvl_r2Bs ww_s2Ag of wild_X4 { __DEFAULT -> (# GHC.Types.C# wild_X4, w_s2Ad #) } } } }}} while the Hadrian build produces the horrible code similar to that above. I'll look at that next. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/15570#comment:9> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler