Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC

Commits:

6 changed files:

Changes:

  • libraries/ghc-internal/cbits/Stack.cmm
    ... ... @@ -8,9 +8,11 @@
    8 8
     // developed.
    
    9 9
     #if defined(StgStack_marking)
    
    10 10
     
    
    11
    -// Returns the next stackframe's StgStack* and offset in it. And, an indicator
    
    12
    -// if this frame is the last one (`hasNext` bit.)
    
    13
    -// (StgStack*, StgWord, StgWord) advanceStackFrameLocationzh(StgStack* stack, StgWord offsetWords)
    
    11
    +// Returns the next stackframe location as
    
    12
    +//   (# (# #) | (# StgStack*, StgWord #) #)
    
    13
    +// flattened to its runtime representation:
    
    14
    +//   (tag, StgStack*, StgWord)
    
    15
    +// where tag 1 means no next frame and tag 2 means the payload is present.
    
    14 16
     advanceStackFrameLocationzh (P_ stack, W_ offsetWords) {
    
    15 17
       W_ frameSize;
    
    16 18
       (frameSize) = ccall stackFrameSize(stack, offsetWords);
    
    ... ... @@ -27,27 +29,30 @@ advanceStackFrameLocationzh (P_ stack, W_ offsetWords) {
    27 29
       stackSizeInBytes = WDS(stackSize);
    
    28 30
       stackBottom = stackSizeInBytes + stackArrayPtr;
    
    29 31
     
    
    32
    +  W_ tag, newOffsetWords;
    
    30 33
       P_ newStack;
    
    31
    -  W_ newOffsetWords, hasNext;
    
    32 34
       if(nextClosurePtr < stackBottom) (likely: True) {
    
    35
    +    tag = 2;
    
    33 36
         newStack = stack;
    
    34 37
         newOffsetWords = offsetWords + frameSize;
    
    35
    -    hasNext = 1;
    
    36 38
       } else {
    
    37 39
         P_ underflowFrameStack;
    
    38 40
         (underflowFrameStack) = ccall getUnderflowFrameStack(stack, offsetWords);
    
    39 41
         if (underflowFrameStack == NULL) (likely: True) {
    
    40
    -      newStack = NULL;
    
    41
    -      newOffsetWords = NULL;
    
    42
    -      hasNext = NULL;
    
    42
    +      // The empty alternative still has dead payload slots in the flattened
    
    43
    +      // sum representation, so the pointer field must contain a valid closure
    
    44
    +      // pointer rather than NULL.
    
    45
    +      tag = 1;
    
    46
    +      newStack = stack;
    
    47
    +      newOffsetWords = 0;
    
    43 48
         } else {
    
    49
    +      tag = 2;
    
    44 50
           newStack = underflowFrameStack;
    
    45
    -      newOffsetWords = NULL;
    
    46
    -      hasNext = 1;
    
    51
    +      newOffsetWords = 0;
    
    47 52
         }
    
    48 53
       }
    
    49 54
     
    
    50
    -  return (newStack, newOffsetWords, hasNext);
    
    55
    +  return (tag, newStack, newOffsetWords);
    
    51 56
     }
    
    52 57
     
    
    53 58
     // (StgWord, StgWord) getSmallBitmapzh(StgStack* stack, StgWord offsetWords)
    

  • libraries/ghc-internal/src/GHC/Internal/Stack/Decode.hs
    ... ... @@ -11,6 +11,7 @@
    11 11
     {-# LANGUAGE TypeFamilies #-}
    
    12 12
     {-# LANGUAGE TypeInType #-}
    
    13 13
     {-# LANGUAGE UnboxedTuples #-}
    
    14
    +{-# LANGUAGE UnboxedSums #-}
    
    14 15
     {-# LANGUAGE UnliftedFFITypes #-}
    
    15 16
     
    
    16 17
     module GHC.Internal.Stack.Decode (
    
    ... ... @@ -214,21 +215,19 @@ getStackFields stackSnapshot# =
    214 215
     stackHead :: StackSnapshot# -> StackFrameLocation
    
    215 216
     stackHead s# = (StackSnapshot s#, 0) -- GHC stacks are never empty
    
    216 217
     
    
    217
    --- | Advance to the next stack frame (if any)
    
    218
    ---
    
    219
    --- The last `Int#` in the result tuple is meant to be treated as bool
    
    220
    --- (has_next).
    
    218
    +-- | Advance to the next stack frame (if any).
    
    221 219
     foreign import prim "advanceStackFrameLocationzh"
    
    222 220
       advanceStackFrameLocation# ::
    
    223
    -    StackSnapshot# -> Word# -> (# StackSnapshot#, Word#, Int# #)
    
    221
    +    StackSnapshot# -> Word# -> (# (# #) | (# StackSnapshot#, Word# #) #)
    
    224 222
     
    
    225 223
     -- | Advance to the next stack frame (if any)
    
    226 224
     advanceStackFrameLocation :: StackFrameLocation -> Maybe StackFrameLocation
    
    227 225
     advanceStackFrameLocation ((StackSnapshot stackSnapshot#), index) =
    
    228
    -  let !(# s', i', hasNext #) = advanceStackFrameLocation# stackSnapshot# (wordOffsetToWord# index)
    
    229
    -   in if I# hasNext > 0
    
    230
    -        then Just (StackSnapshot s', primWordToWordOffset i')
    
    231
    -        else Nothing
    
    226
    +  case advanceStackFrameLocation# stackSnapshot# (wordOffsetToWord# index) of
    
    227
    +    (# (# #) | #) ->
    
    228
    +      Nothing
    
    229
    +    (# | (# s', i' #) #) ->
    
    230
    +      Just (StackSnapshot s', primWordToWordOffset i')
    
    232 231
       where
    
    233 232
         primWordToWordOffset :: Word# -> WordOffset
    
    234 233
         primWordToWordOffset w# = fromIntegral (W# w#)
    

  • testsuite/tests/ffi/should_run/PrimFFIUnboxedSum.hs
    1
    +{-# LANGUAGE GHCForeignImportPrim #-}
    
    2
    +{-# LANGUAGE MagicHash #-}
    
    3
    +{-# LANGUAGE UnboxedTuples #-}
    
    4
    +{-# LANGUAGE UnboxedSums #-}
    
    5
    +{-# LANGUAGE UnliftedFFITypes #-}
    
    6
    +
    
    7
    +module Main where
    
    8
    +
    
    9
    +import GHC.Exts
    
    10
    +import GHC.Word
    
    11
    +
    
    12
    +foreign import prim "sumWord"
    
    13
    +  sumWord# :: Word# -> (# (# #) | Word# #)
    
    14
    +
    
    15
    +render :: Word# -> String
    
    16
    +render w# =
    
    17
    +  case sumWord# w# of
    
    18
    +    (# (# #) | #) -> "none"
    
    19
    +    (# | r# #) -> "some " ++ show (W# r#)
    
    20
    +
    
    21
    +main :: IO ()
    
    22
    +main = do
    
    23
    +  putStrLn (render 0##)
    
    24
    +  putStrLn (render 5##)

  • testsuite/tests/ffi/should_run/PrimFFIUnboxedSum.stdout
    1
    +none
    
    2
    +some 6

  • testsuite/tests/ffi/should_run/PrimFFIUnboxedSum_cmm.cmm
    1
    +#include "Cmm.h"
    
    2
    +
    
    3
    +sumWord(W_ w) {
    
    4
    +  if (w == 0) {
    
    5
    +    return (1, 0);
    
    6
    +  } else {
    
    7
    +    return (2, w + 1);
    
    8
    +  }
    
    9
    +}

  • testsuite/tests/ffi/should_run/all.T
    ... ... @@ -225,6 +225,8 @@ test('PrimFFIInt32', [req_c], compile_and_run, ['PrimFFIInt32_c.c'])
    225 225
     
    
    226 226
     test('PrimFFIWord32', [req_c], compile_and_run, ['PrimFFIWord32_c.c'])
    
    227 227
     
    
    228
    +test('PrimFFIUnboxedSum', req_cmm, compile_and_run, ['PrimFFIUnboxedSum_cmm.cmm'])
    
    229
    +
    
    228 230
     test('T493', [ req_c], compile_and_run, ['T493_c.c'])
    
    229 231
     
    
    230 232
     test('UnliftedNewtypesByteArrayOffset', [req_c], compile_and_run, ['UnliftedNewtypesByteArrayOffset_c.c'])