[GHC] #11487: stg_ap_pp_fast doesn't pass the argument in the arity=1 case

GHC ghc-devs at haskell.org
Mon Jan 25 02:53:08 UTC 2016


#11487: stg_ap_pp_fast doesn't pass the argument in the arity=1 case
--------------------------------------+----------------------------------
           Reporter:  rwbarton        |             Owner:
               Type:  bug             |            Status:  new
           Priority:  high            |         Milestone:  8.0.1
          Component:  Runtime System  |           Version:  8.0.1-rc1
           Keywords:                  |  Operating System:  Linux
       Architecture:  arm             |   Type of failure:  Runtime crash
          Test Case:                  |        Blocked By:
           Blocking:                  |   Related Tickets:
Differential Rev(s):                  |         Wiki Page:
--------------------------------------+----------------------------------
 The body of `stg_ap_pp_fast` looks like
 {{{
             arity = TO_W_(StgFunInfoExtra_arity(%GET_FUN_INFO(R1)));
             ASSERT(arity > 0);
             if (arity == 1) {
                 Sp_adj(-2);
                 W_[Sp+WDS(1)] = R3;
                 W_[Sp+WDS(0)] = stg_ap_p_info;
                 R1 = R1 + 1;
                 jump_SAVE_CCCS(%GET_ENTRY(UNTAG(R1)));
             }
             if (arity == 2) {
                 Sp_adj(0);
                 R1 = R1 + 2;
                 jump %GET_ENTRY(UNTAG(R1)) [R1,R2,R3];
             } else {
                 Sp_adj(-3);
                 W_[Sp+WDS(2)] = R3;
                 W_[Sp+WDS(1)] = R2;
                 if (arity < 4) {
                   R1 = R1 + arity;
                 }
                 BUILD_PAP(2,2,stg_ap_pp_info,FUN);
             }
 }}}
 where
 {{{
 // Jump to target, saving CCCS and restoring it on return
 #if defined(PROFILING)
 #define jump_SAVE_CCCS(target)                  \
     Sp(-1) = CCCS;                              \
     Sp(-2) = stg_restore_cccs_info;             \
     Sp_adj(-2);                                 \
     jump (target) [R1]
 #else
 #define jump_SAVE_CCCS(target) jump (target) [R1]
 #endif
 }}}

 So in the arity=1 case the jump amounts to
 {{{
                 jump (%GET_ENTRY(UNTAG(R1))) [R1]
 }}}
 R1 is the function to apply, but we don't pass its argument, R2!

 Now, possibly by design, the calling convention of `stg_ap_pp_fast` is
 such that the first argument to apply is in R2, which is the same register
 that the function R1 will expect to find its argument in. So if nothing
 happens to disturb R2 (and possibly this is always the case with the NCG),
 then everything is fine. However, it's definitely not fine for the LLVM
 backend, which quite reasonably passes `undef` for the R2, R3, and R4
 arguments when doing the jump. On arm/Android, LLVM decided to clobber
 `r8` (the physical register for R2) in the body of `stg_ap_pp_fast`.

 This caused a crash for the following program:
 {{{
 main = print (read "3"::Int)
 }}}

 This appears to have been broken by commit
 f9265dd369b9e269349930012c25e670248f2a09 which changed the argument list
 for `jump_SAVE_CCCS` from `[*]` to `[R1]`.

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11487>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list