{-# LANGUAGE CPP              #-}
{-# LANGUAGE FlexibleContexts #-}
{-# OPTIONS_GHC -funbox-strict-fields #-}
--
--  (c) The University of Glasgow 2002-2006
--

-- | Bytecode instruction definitions
module GHC.ByteCode.Instr (
        BCInstr(..), ProtoBCO(..), bciStackUse, LocalLabel(..)
  ) where

#include "HsVersions.h"

import GHC.Prelude

import GHC.ByteCode.Types
import GHCi.RemoteTypes
import GHCi.FFI (C_ffi_cif)
import GHC.StgToCmm.Layout     ( ArgRep(..) )
import GHC.Utils.Outputable
import GHC.Types.Name
import GHC.Types.Unique
import GHC.Types.Literal
import GHC.Core.DataCon
import GHC.Builtin.PrimOps
import GHC.Runtime.Heap.Layout

import Data.Word
import GHC.Stack.CCS (CostCentre)

import GHC.Stg.Syntax

-- ----------------------------------------------------------------------------
-- Bytecode instructions

data ProtoBCO a
   = ProtoBCO {
        forall a. ProtoBCO a -> a
protoBCOName       :: a,          -- name, in some sense
        forall a. ProtoBCO a -> [BCInstr]
protoBCOInstrs     :: [BCInstr],  -- instrs
        -- arity and GC info
        forall a. ProtoBCO a -> [StgWord]
protoBCOBitmap     :: [StgWord],
        forall a. ProtoBCO a -> Word16
protoBCOBitmapSize :: Word16,
        forall a. ProtoBCO a -> Int
protoBCOArity      :: Int,
        -- what the BCO came from, for debugging only
        forall a. ProtoBCO a -> Either [CgStgAlt] CgStgRhs
protoBCOExpr       :: Either [CgStgAlt] CgStgRhs,
        -- malloc'd pointers
        forall a. ProtoBCO a -> [FFIInfo]
protoBCOFFIs       :: [FFIInfo]
   }

-- | A local block label (e.g. identifying a case alternative).
newtype LocalLabel = LocalLabel { LocalLabel -> Word32
getLocalLabel :: Word32 }
  deriving (LocalLabel -> LocalLabel -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LocalLabel -> LocalLabel -> Bool
$c/= :: LocalLabel -> LocalLabel -> Bool
== :: LocalLabel -> LocalLabel -> Bool
$c== :: LocalLabel -> LocalLabel -> Bool
Eq, Eq LocalLabel
LocalLabel -> LocalLabel -> Bool
LocalLabel -> LocalLabel -> Ordering
LocalLabel -> LocalLabel -> LocalLabel
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: LocalLabel -> LocalLabel -> LocalLabel
$cmin :: LocalLabel -> LocalLabel -> LocalLabel
max :: LocalLabel -> LocalLabel -> LocalLabel
$cmax :: LocalLabel -> LocalLabel -> LocalLabel
>= :: LocalLabel -> LocalLabel -> Bool
$c>= :: LocalLabel -> LocalLabel -> Bool
> :: LocalLabel -> LocalLabel -> Bool
$c> :: LocalLabel -> LocalLabel -> Bool
<= :: LocalLabel -> LocalLabel -> Bool
$c<= :: LocalLabel -> LocalLabel -> Bool
< :: LocalLabel -> LocalLabel -> Bool
$c< :: LocalLabel -> LocalLabel -> Bool
compare :: LocalLabel -> LocalLabel -> Ordering
$ccompare :: LocalLabel -> LocalLabel -> Ordering
Ord)

instance Outputable LocalLabel where
  ppr :: LocalLabel -> SDoc
ppr (LocalLabel Word32
lbl) = String -> SDoc
text String
"lbl:" SDoc -> SDoc -> SDoc
<> forall a. Outputable a => a -> SDoc
ppr Word32
lbl

data BCInstr
   -- Messing with the stack
   = STKCHECK  Word

   -- Push locals (existing bits of the stack)
   | PUSH_L    !Word16{-offset-}
   | PUSH_LL   !Word16 !Word16{-2 offsets-}
   | PUSH_LLL  !Word16 !Word16 !Word16{-3 offsets-}

   -- Push the specified local as a 8, 16, 32 bit value onto the stack. (i.e.,
   -- the stack will grow by 8, 16 or 32 bits)
   | PUSH8  !Word16
   | PUSH16 !Word16
   | PUSH32 !Word16

   -- Push the specifiec local as a 8, 16, 32 bit value onto the stack, but the
   -- value will take the whole word on the stack (i.e., the stack will grow by
   -- a word)
   -- This is useful when extracting a packed constructor field for further use.
   -- Currently we expect all values on the stack to take full words, except for
   -- the ones used for PACK (i.e., actually constracting new data types, in
   -- which case we use PUSH{8,16,32})
   | PUSH8_W  !Word16
   | PUSH16_W !Word16
   | PUSH32_W !Word16

   -- Push a ptr  (these all map to PUSH_G really)
   | PUSH_G       Name
   | PUSH_PRIMOP  PrimOp
   | PUSH_BCO     (ProtoBCO Name)

   -- Push an alt continuation
   | PUSH_ALTS          (ProtoBCO Name)
   | PUSH_ALTS_UNLIFTED (ProtoBCO Name) ArgRep
   | PUSH_ALTS_TUPLE    (ProtoBCO Name) -- continuation
                        !TupleInfo
                        (ProtoBCO Name) -- tuple return BCO

   -- Pushing 8, 16 and 32 bits of padding (for constructors).
   | PUSH_PAD8
   | PUSH_PAD16
   | PUSH_PAD32

   -- Pushing literals
   | PUSH_UBX8  Literal
   | PUSH_UBX16 Literal
   | PUSH_UBX32 Literal
   | PUSH_UBX   Literal Word16
        -- push this int/float/double/addr, on the stack. Word16
        -- is # of words to copy from literal pool.  Eitherness reflects
        -- the difficulty of dealing with MachAddr here, mostly due to
        -- the excessive (and unnecessary) restrictions imposed by the
        -- designers of the new Foreign library.  In particular it is
        -- quite impossible to convert an Addr to any other integral
        -- type, and it appears impossible to get hold of the bits of
        -- an addr, even though we need to assemble BCOs.

   -- various kinds of application
   | PUSH_APPLY_N
   | PUSH_APPLY_V
   | PUSH_APPLY_F
   | PUSH_APPLY_D
   | PUSH_APPLY_L
   | PUSH_APPLY_P
   | PUSH_APPLY_PP
   | PUSH_APPLY_PPP
   | PUSH_APPLY_PPPP
   | PUSH_APPLY_PPPPP
   | PUSH_APPLY_PPPPPP

   | SLIDE     Word16{-this many-} Word16{-down by this much-}

   -- To do with the heap
   | ALLOC_AP  !Word16 -- make an AP with this many payload words
   | ALLOC_AP_NOUPD !Word16 -- make an AP_NOUPD with this many payload words
   | ALLOC_PAP !Word16 !Word16 -- make a PAP with this arity / payload words
   | MKAP      !Word16{-ptr to AP is this far down stack-} !Word16{-number of words-}
   | MKPAP     !Word16{-ptr to PAP is this far down stack-} !Word16{-number of words-}
   | UNPACK    !Word16 -- unpack N words from t.o.s Constr
   | PACK      DataCon !Word16
                        -- after assembly, the DataCon is an index into the
                        -- itbl array
   -- For doing case trees
   | LABEL     LocalLabel
   | TESTLT_I  Int    LocalLabel
   | TESTEQ_I  Int    LocalLabel
   | TESTLT_W  Word   LocalLabel
   | TESTEQ_W  Word   LocalLabel
   | TESTLT_F  Float  LocalLabel
   | TESTEQ_F  Float  LocalLabel
   | TESTLT_D  Double LocalLabel
   | TESTEQ_D  Double LocalLabel

   -- The Word16 value is a constructor number and therefore
   -- stored in the insn stream rather than as an offset into
   -- the literal pool.
   | TESTLT_P  Word16 LocalLabel
   | TESTEQ_P  Word16 LocalLabel

   | CASEFAIL
   | JMP              LocalLabel

   -- For doing calls to C (via glue code generated by libffi)
   | CCALL            Word16    -- stack frame size
                      (RemotePtr C_ffi_cif) -- addr of the glue code
                      Word16    -- flags.
                                --
                                -- 0x1: call is interruptible
                                -- 0x2: call is unsafe
                                --
                                -- (XXX: inefficient, but I don't know
                                -- what the alignment constraints are.)

   -- For doing magic ByteArray passing to foreign calls
   | SWIZZLE          Word16 -- to the ptr N words down the stack,
                      Word16 -- add M (interpreted as a signed 16-bit entity)

   -- To Infinity And Beyond
   | ENTER
   | RETURN                 -- return a lifted value
   | RETURN_UNLIFTED ArgRep -- return an unlifted value, here's its rep
   | RETURN_TUPLE           -- return an unboxed tuple (info already on stack)

   -- Breakpoints
   | BRK_FUN          Word16 Unique (RemotePtr CostCentre)

-- -----------------------------------------------------------------------------
-- Printing bytecode instructions

instance Outputable a => Outputable (ProtoBCO a) where
   ppr :: ProtoBCO a -> SDoc
ppr (ProtoBCO { protoBCOName :: forall a. ProtoBCO a -> a
protoBCOName       = a
name
                 , protoBCOInstrs :: forall a. ProtoBCO a -> [BCInstr]
protoBCOInstrs     = [BCInstr]
instrs
                 , protoBCOBitmap :: forall a. ProtoBCO a -> [StgWord]
protoBCOBitmap     = [StgWord]
bitmap
                 , protoBCOBitmapSize :: forall a. ProtoBCO a -> Word16
protoBCOBitmapSize = Word16
bsize
                 , protoBCOArity :: forall a. ProtoBCO a -> Int
protoBCOArity      = Int
arity
                 , protoBCOExpr :: forall a. ProtoBCO a -> Either [CgStgAlt] CgStgRhs
protoBCOExpr       = Either [CgStgAlt] CgStgRhs
origin
                 , protoBCOFFIs :: forall a. ProtoBCO a -> [FFIInfo]
protoBCOFFIs       = [FFIInfo]
ffis })
      = (String -> SDoc
text String
"ProtoBCO" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr a
name SDoc -> SDoc -> SDoc
<> Char -> SDoc
char Char
'#' SDoc -> SDoc -> SDoc
<> Int -> SDoc
int Int
arity
                SDoc -> SDoc -> SDoc
<+> String -> SDoc
text (forall a. Show a => a -> String
show [FFIInfo]
ffis) SDoc -> SDoc -> SDoc
<> SDoc
colon)
        SDoc -> SDoc -> SDoc
$$ Int -> SDoc -> SDoc
nest Int
3 (case Either [CgStgAlt] CgStgRhs
origin of
                      Left [CgStgAlt]
alts ->
                        [SDoc] -> SDoc
vcat (forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith SDoc -> SDoc -> SDoc
(<+>) (Char -> SDoc
char Char
'{' forall a. a -> [a] -> [a]
: forall a. a -> [a]
repeat (Char -> SDoc
char Char
';'))
                             (forall a b. (a -> b) -> [a] -> [b]
map (forall (pass :: StgPass).
OutputablePass pass =>
StgPprOpts -> GenStgAlt pass -> SDoc
pprStgAltShort StgPprOpts
shortStgPprOpts) [CgStgAlt]
alts))
                      Right CgStgRhs
rhs ->
                        forall (pass :: StgPass).
OutputablePass pass =>
StgPprOpts -> GenStgRhs pass -> SDoc
pprStgRhsShort StgPprOpts
shortStgPprOpts CgStgRhs
rhs
                  )
        SDoc -> SDoc -> SDoc
$$ Int -> SDoc -> SDoc
nest Int
3 (String -> SDoc
text String
"bitmap: " SDoc -> SDoc -> SDoc
<+> String -> SDoc
text (forall a. Show a => a -> String
show Word16
bsize) SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr [StgWord]
bitmap)
        SDoc -> SDoc -> SDoc
$$ Int -> SDoc -> SDoc
nest Int
3 ([SDoc] -> SDoc
vcat (forall a b. (a -> b) -> [a] -> [b]
map forall a. Outputable a => a -> SDoc
ppr [BCInstr]
instrs))

-- Print enough of the STG expression to enable the reader to find
-- the expression in the -ddump-stg output.  That is, we need to
-- include at least a binder.

pprStgExprShort :: OutputablePass pass => StgPprOpts -> GenStgExpr pass -> SDoc
pprStgExprShort :: forall (pass :: StgPass).
OutputablePass pass =>
StgPprOpts -> GenStgExpr pass -> SDoc
pprStgExprShort StgPprOpts
_ (StgCase GenStgExpr pass
_expr BinderP pass
var AltType
_ty [GenStgAlt pass]
_alts) =
  String -> SDoc
text String
"case of" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr BinderP pass
var
pprStgExprShort StgPprOpts
_ (StgLet XLet pass
_ GenStgBinding pass
bnd GenStgExpr pass
_) =
  String -> SDoc
text String
"let" SDoc -> SDoc -> SDoc
<+> forall (pass :: StgPass).
OutputablePass pass =>
GenStgBinding pass -> SDoc
pprStgBindShort GenStgBinding pass
bnd SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"in ..."
pprStgExprShort StgPprOpts
_ (StgLetNoEscape XLetNoEscape pass
_ GenStgBinding pass
bnd GenStgExpr pass
_) =
  String -> SDoc
text String
"let-no-escape" SDoc -> SDoc -> SDoc
<+> forall (pass :: StgPass).
OutputablePass pass =>
GenStgBinding pass -> SDoc
pprStgBindShort GenStgBinding pass
bnd SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"in ..."
pprStgExprShort StgPprOpts
opts (StgTick StgTickish
t GenStgExpr pass
e) = forall a. Outputable a => a -> SDoc
ppr StgTickish
t SDoc -> SDoc -> SDoc
<+> forall (pass :: StgPass).
OutputablePass pass =>
StgPprOpts -> GenStgExpr pass -> SDoc
pprStgExprShort StgPprOpts
opts GenStgExpr pass
e
pprStgExprShort StgPprOpts
opts GenStgExpr pass
e = forall (pass :: StgPass).
OutputablePass pass =>
StgPprOpts -> GenStgExpr pass -> SDoc
pprStgExpr StgPprOpts
opts GenStgExpr pass
e

pprStgBindShort :: OutputablePass pass => GenStgBinding pass -> SDoc
pprStgBindShort :: forall (pass :: StgPass).
OutputablePass pass =>
GenStgBinding pass -> SDoc
pprStgBindShort (StgNonRec BinderP pass
x GenStgRhs pass
_) =
  forall a. Outputable a => a -> SDoc
ppr BinderP pass
x SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"= ..."
pprStgBindShort (StgRec [(BinderP pass, GenStgRhs pass)]
bs) =
  Char -> SDoc
char Char
'{' SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr (forall a b. (a, b) -> a
fst (forall a. [a] -> a
head [(BinderP pass, GenStgRhs pass)]
bs)) SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"= ...; ... }"

pprStgAltShort :: OutputablePass pass => StgPprOpts -> GenStgAlt pass -> SDoc
pprStgAltShort :: forall (pass :: StgPass).
OutputablePass pass =>
StgPprOpts -> GenStgAlt pass -> SDoc
pprStgAltShort StgPprOpts
opts (AltCon
con, [BinderP pass]
args, GenStgExpr pass
expr) =
  forall a. Outputable a => a -> SDoc
ppr AltCon
con SDoc -> SDoc -> SDoc
<+> [SDoc] -> SDoc
sep (forall a b. (a -> b) -> [a] -> [b]
map forall a. Outputable a => a -> SDoc
ppr [BinderP pass]
args) SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"->" SDoc -> SDoc -> SDoc
<+> forall (pass :: StgPass).
OutputablePass pass =>
StgPprOpts -> GenStgExpr pass -> SDoc
pprStgExprShort StgPprOpts
opts GenStgExpr pass
expr

pprStgRhsShort :: OutputablePass pass => StgPprOpts -> GenStgRhs pass -> SDoc
pprStgRhsShort :: forall (pass :: StgPass).
OutputablePass pass =>
StgPprOpts -> GenStgRhs pass -> SDoc
pprStgRhsShort StgPprOpts
opts (StgRhsClosure XRhsClosure pass
_ext CostCentreStack
_cc UpdateFlag
upd_flag [BinderP pass]
args GenStgExpr pass
body) =
  SDoc -> Int -> SDoc -> SDoc
hang ([SDoc] -> SDoc
hsep [ Char -> SDoc
char Char
'\\' SDoc -> SDoc -> SDoc
<> forall a. Outputable a => a -> SDoc
ppr UpdateFlag
upd_flag, SDoc -> SDoc
brackets (forall a. Outputable a => [a] -> SDoc
interppSP [BinderP pass]
args) ])
       Int
4 (forall (pass :: StgPass).
OutputablePass pass =>
StgPprOpts -> GenStgExpr pass -> SDoc
pprStgExprShort StgPprOpts
opts GenStgExpr pass
body)
pprStgRhsShort StgPprOpts
opts GenStgRhs pass
rhs = forall (pass :: StgPass).
OutputablePass pass =>
StgPprOpts -> GenStgRhs pass -> SDoc
pprStgRhs StgPprOpts
opts GenStgRhs pass
rhs


instance Outputable BCInstr where
   ppr :: BCInstr -> SDoc
ppr (STKCHECK Word
n)          = String -> SDoc
text String
"STKCHECK" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word
n
   ppr (PUSH_L Word16
offset)       = String -> SDoc
text String
"PUSH_L  " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
offset
   ppr (PUSH_LL Word16
o1 Word16
o2)       = String -> SDoc
text String
"PUSH_LL " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
o1 SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
o2
   ppr (PUSH_LLL Word16
o1 Word16
o2 Word16
o3)   = String -> SDoc
text String
"PUSH_LLL" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
o1 SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
o2 SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
o3
   ppr (PUSH8  Word16
offset)       = String -> SDoc
text String
"PUSH8  " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
offset
   ppr (PUSH16 Word16
offset)       = String -> SDoc
text String
"PUSH16  " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
offset
   ppr (PUSH32 Word16
offset)       = String -> SDoc
text String
"PUSH32  " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
offset
   ppr (PUSH8_W  Word16
offset)     = String -> SDoc
text String
"PUSH8_W  " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
offset
   ppr (PUSH16_W Word16
offset)     = String -> SDoc
text String
"PUSH16_W  " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
offset
   ppr (PUSH32_W Word16
offset)     = String -> SDoc
text String
"PUSH32_W  " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
offset
   ppr (PUSH_G Name
nm)           = String -> SDoc
text String
"PUSH_G  " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Name
nm
   ppr (PUSH_PRIMOP PrimOp
op)      = String -> SDoc
text String
"PUSH_G  " SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"GHC.PrimopWrappers."
                                               SDoc -> SDoc -> SDoc
<> forall a. Outputable a => a -> SDoc
ppr PrimOp
op
   ppr (PUSH_BCO ProtoBCO Name
bco)        = SDoc -> Int -> SDoc -> SDoc
hang (String -> SDoc
text String
"PUSH_BCO") Int
2 (forall a. Outputable a => a -> SDoc
ppr ProtoBCO Name
bco)

   ppr (PUSH_ALTS ProtoBCO Name
bco)       = SDoc -> Int -> SDoc -> SDoc
hang (String -> SDoc
text String
"PUSH_ALTS") Int
2 (forall a. Outputable a => a -> SDoc
ppr ProtoBCO Name
bco)
   ppr (PUSH_ALTS_UNLIFTED ProtoBCO Name
bco ArgRep
pk) = SDoc -> Int -> SDoc -> SDoc
hang (String -> SDoc
text String
"PUSH_ALTS_UNLIFTED" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr ArgRep
pk) Int
2 (forall a. Outputable a => a -> SDoc
ppr ProtoBCO Name
bco)
   ppr (PUSH_ALTS_TUPLE ProtoBCO Name
bco TupleInfo
tuple_info ProtoBCO Name
tuple_bco) =
                               SDoc -> Int -> SDoc -> SDoc
hang (String -> SDoc
text String
"PUSH_ALTS_TUPLE" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr TupleInfo
tuple_info)
                                    Int
2
                                    (forall a. Outputable a => a -> SDoc
ppr ProtoBCO Name
tuple_bco SDoc -> SDoc -> SDoc
$+$ forall a. Outputable a => a -> SDoc
ppr ProtoBCO Name
bco)

   ppr BCInstr
PUSH_PAD8             = String -> SDoc
text String
"PUSH_PAD8"
   ppr BCInstr
PUSH_PAD16            = String -> SDoc
text String
"PUSH_PAD16"
   ppr BCInstr
PUSH_PAD32            = String -> SDoc
text String
"PUSH_PAD32"

   ppr (PUSH_UBX8  Literal
lit)      = String -> SDoc
text String
"PUSH_UBX8" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Literal
lit
   ppr (PUSH_UBX16 Literal
lit)      = String -> SDoc
text String
"PUSH_UBX16" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Literal
lit
   ppr (PUSH_UBX32 Literal
lit)      = String -> SDoc
text String
"PUSH_UBX32" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Literal
lit
   ppr (PUSH_UBX Literal
lit Word16
nw)     = String -> SDoc
text String
"PUSH_UBX" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
parens (forall a. Outputable a => a -> SDoc
ppr Word16
nw) SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Literal
lit
   ppr BCInstr
PUSH_APPLY_N          = String -> SDoc
text String
"PUSH_APPLY_N"
   ppr BCInstr
PUSH_APPLY_V          = String -> SDoc
text String
"PUSH_APPLY_V"
   ppr BCInstr
PUSH_APPLY_F          = String -> SDoc
text String
"PUSH_APPLY_F"
   ppr BCInstr
PUSH_APPLY_D          = String -> SDoc
text String
"PUSH_APPLY_D"
   ppr BCInstr
PUSH_APPLY_L          = String -> SDoc
text String
"PUSH_APPLY_L"
   ppr BCInstr
PUSH_APPLY_P          = String -> SDoc
text String
"PUSH_APPLY_P"
   ppr BCInstr
PUSH_APPLY_PP         = String -> SDoc
text String
"PUSH_APPLY_PP"
   ppr BCInstr
PUSH_APPLY_PPP        = String -> SDoc
text String
"PUSH_APPLY_PPP"
   ppr BCInstr
PUSH_APPLY_PPPP       = String -> SDoc
text String
"PUSH_APPLY_PPPP"
   ppr BCInstr
PUSH_APPLY_PPPPP      = String -> SDoc
text String
"PUSH_APPLY_PPPPP"
   ppr BCInstr
PUSH_APPLY_PPPPPP     = String -> SDoc
text String
"PUSH_APPLY_PPPPPP"

   ppr (SLIDE Word16
n Word16
d)           = String -> SDoc
text String
"SLIDE   " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
n SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
d
   ppr (ALLOC_AP Word16
sz)         = String -> SDoc
text String
"ALLOC_AP   " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
sz
   ppr (ALLOC_AP_NOUPD Word16
sz)   = String -> SDoc
text String
"ALLOC_AP_NOUPD   " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
sz
   ppr (ALLOC_PAP Word16
arity Word16
sz)  = String -> SDoc
text String
"ALLOC_PAP   " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
arity SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
sz
   ppr (MKAP Word16
offset Word16
sz)      = String -> SDoc
text String
"MKAP    " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
sz SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"words,"
                                               SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
offset SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"stkoff"
   ppr (MKPAP Word16
offset Word16
sz)     = String -> SDoc
text String
"MKPAP   " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
sz SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"words,"
                                               SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
offset SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"stkoff"
   ppr (UNPACK Word16
sz)           = String -> SDoc
text String
"UNPACK  " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
sz
   ppr (PACK DataCon
dcon Word16
sz)        = String -> SDoc
text String
"PACK    " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr DataCon
dcon SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
sz
   ppr (LABEL     LocalLabel
lab)       = String -> SDoc
text String
"__"       SDoc -> SDoc -> SDoc
<> forall a. Outputable a => a -> SDoc
ppr LocalLabel
lab SDoc -> SDoc -> SDoc
<> SDoc
colon
   ppr (TESTLT_I  Int
i LocalLabel
lab)     = String -> SDoc
text String
"TESTLT_I" SDoc -> SDoc -> SDoc
<+> Int -> SDoc
int Int
i SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"__" SDoc -> SDoc -> SDoc
<> forall a. Outputable a => a -> SDoc
ppr LocalLabel
lab
   ppr (TESTEQ_I  Int
i LocalLabel
lab)     = String -> SDoc
text String
"TESTEQ_I" SDoc -> SDoc -> SDoc
<+> Int -> SDoc
int Int
i SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"__" SDoc -> SDoc -> SDoc
<> forall a. Outputable a => a -> SDoc
ppr LocalLabel
lab
   ppr (TESTLT_W  Word
i LocalLabel
lab)     = String -> SDoc
text String
"TESTLT_W" SDoc -> SDoc -> SDoc
<+> Int -> SDoc
int (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
i) SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"__" SDoc -> SDoc -> SDoc
<> forall a. Outputable a => a -> SDoc
ppr LocalLabel
lab
   ppr (TESTEQ_W  Word
i LocalLabel
lab)     = String -> SDoc
text String
"TESTEQ_W" SDoc -> SDoc -> SDoc
<+> Int -> SDoc
int (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
i) SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"__" SDoc -> SDoc -> SDoc
<> forall a. Outputable a => a -> SDoc
ppr LocalLabel
lab
   ppr (TESTLT_F  Float
f LocalLabel
lab)     = String -> SDoc
text String
"TESTLT_F" SDoc -> SDoc -> SDoc
<+> Float -> SDoc
float Float
f SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"__" SDoc -> SDoc -> SDoc
<> forall a. Outputable a => a -> SDoc
ppr LocalLabel
lab
   ppr (TESTEQ_F  Float
f LocalLabel
lab)     = String -> SDoc
text String
"TESTEQ_F" SDoc -> SDoc -> SDoc
<+> Float -> SDoc
float Float
f SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"__" SDoc -> SDoc -> SDoc
<> forall a. Outputable a => a -> SDoc
ppr LocalLabel
lab
   ppr (TESTLT_D  Double
d LocalLabel
lab)     = String -> SDoc
text String
"TESTLT_D" SDoc -> SDoc -> SDoc
<+> Double -> SDoc
double Double
d SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"__" SDoc -> SDoc -> SDoc
<> forall a. Outputable a => a -> SDoc
ppr LocalLabel
lab
   ppr (TESTEQ_D  Double
d LocalLabel
lab)     = String -> SDoc
text String
"TESTEQ_D" SDoc -> SDoc -> SDoc
<+> Double -> SDoc
double Double
d SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"__" SDoc -> SDoc -> SDoc
<> forall a. Outputable a => a -> SDoc
ppr LocalLabel
lab
   ppr (TESTLT_P  Word16
i LocalLabel
lab)     = String -> SDoc
text String
"TESTLT_P" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
i SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"__" SDoc -> SDoc -> SDoc
<> forall a. Outputable a => a -> SDoc
ppr LocalLabel
lab
   ppr (TESTEQ_P  Word16
i LocalLabel
lab)     = String -> SDoc
text String
"TESTEQ_P" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
i SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"__" SDoc -> SDoc -> SDoc
<> forall a. Outputable a => a -> SDoc
ppr LocalLabel
lab
   ppr BCInstr
CASEFAIL              = String -> SDoc
text String
"CASEFAIL"
   ppr (JMP LocalLabel
lab)             = String -> SDoc
text String
"JMP"      SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr LocalLabel
lab
   ppr (CCALL Word16
off RemotePtr C_ffi_cif
marshall_addr Word16
flags) = String -> SDoc
text String
"CCALL   " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
off
                                                SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"marshall code at"
                                               SDoc -> SDoc -> SDoc
<+> String -> SDoc
text (forall a. Show a => a -> String
show RemotePtr C_ffi_cif
marshall_addr)
                                               SDoc -> SDoc -> SDoc
<+> (case Word16
flags of
                                                      Word16
0x1 -> String -> SDoc
text String
"(interruptible)"
                                                      Word16
0x2 -> String -> SDoc
text String
"(unsafe)"
                                                      Word16
_   -> SDoc
empty)
   ppr (SWIZZLE Word16
stkoff Word16
n)    = String -> SDoc
text String
"SWIZZLE " SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"stkoff" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
stkoff
                                               SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"by" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
n
   ppr BCInstr
ENTER                 = String -> SDoc
text String
"ENTER"
   ppr BCInstr
RETURN                = String -> SDoc
text String
"RETURN"
   ppr (RETURN_UNLIFTED ArgRep
pk)  = String -> SDoc
text String
"RETURN_UNLIFTED  " SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr ArgRep
pk
   ppr (BCInstr
RETURN_TUPLE)        = String -> SDoc
text String
"RETURN_TUPLE"
   ppr (BRK_FUN Word16
index Unique
uniq RemotePtr CostCentre
_cc) = String -> SDoc
text String
"BRK_FUN" SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Word16
index SDoc -> SDoc -> SDoc
<+> forall a. Outputable a => a -> SDoc
ppr Unique
uniq SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"<cc>"



-- -----------------------------------------------------------------------------
-- The stack use, in words, of each bytecode insn.  These _must_ be
-- correct, or overestimates of reality, to be safe.

-- NOTE: we aggregate the stack use from case alternatives too, so that
-- we can do a single stack check at the beginning of a function only.

-- This could all be made more accurate by keeping track of a proper
-- stack high water mark, but it doesn't seem worth the hassle.

protoBCOStackUse :: ProtoBCO a -> Word
protoBCOStackUse :: forall a. ProtoBCO a -> Word
protoBCOStackUse ProtoBCO a
bco = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum (forall a b. (a -> b) -> [a] -> [b]
map BCInstr -> Word
bciStackUse (forall a. ProtoBCO a -> [BCInstr]
protoBCOInstrs ProtoBCO a
bco))

bciStackUse :: BCInstr -> Word
bciStackUse :: BCInstr -> Word
bciStackUse STKCHECK{}            = Word
0
bciStackUse PUSH_L{}              = Word
1
bciStackUse PUSH_LL{}             = Word
2
bciStackUse PUSH_LLL{}            = Word
3
bciStackUse PUSH8{}               = Word
1  -- overapproximation
bciStackUse PUSH16{}              = Word
1  -- overapproximation
bciStackUse PUSH32{}              = Word
1  -- overapproximation on 64bit arch
bciStackUse PUSH8_W{}             = Word
1  -- takes exactly 1 word
bciStackUse PUSH16_W{}            = Word
1  -- takes exactly 1 word
bciStackUse PUSH32_W{}            = Word
1  -- takes exactly 1 word
bciStackUse PUSH_G{}              = Word
1
bciStackUse PUSH_PRIMOP{}         = Word
1
bciStackUse PUSH_BCO{}            = Word
1
bciStackUse (PUSH_ALTS ProtoBCO Name
bco)       = Word
2 {- profiling only, restore CCCS -} forall a. Num a => a -> a -> a
+
                                    Word
3 forall a. Num a => a -> a -> a
+ forall a. ProtoBCO a -> Word
protoBCOStackUse ProtoBCO Name
bco
bciStackUse (PUSH_ALTS_UNLIFTED ProtoBCO Name
bco ArgRep
_) = Word
2 {- profiling only, restore CCCS -} forall a. Num a => a -> a -> a
+
                                         Word
4 forall a. Num a => a -> a -> a
+ forall a. ProtoBCO a -> Word
protoBCOStackUse ProtoBCO Name
bco
bciStackUse (PUSH_ALTS_TUPLE ProtoBCO Name
bco TupleInfo
info ProtoBCO Name
_) =
   -- (tuple_bco, tuple_info word, cont_bco, stg_ctoi_t)
   -- tuple
   -- (tuple_info, tuple_bco, stg_ret_t)
   Word
1 {- profiling only -} forall a. Num a => a -> a -> a
+
   Word
7 forall a. Num a => a -> a -> a
+ forall a b. (Integral a, Num b) => a -> b
fromIntegral (TupleInfo -> WordOff
tupleSize TupleInfo
info) forall a. Num a => a -> a -> a
+ forall a. ProtoBCO a -> Word
protoBCOStackUse ProtoBCO Name
bco
bciStackUse (BCInstr
PUSH_PAD8)           = Word
1  -- overapproximation
bciStackUse (BCInstr
PUSH_PAD16)          = Word
1  -- overapproximation
bciStackUse (BCInstr
PUSH_PAD32)          = Word
1  -- overapproximation on 64bit arch
bciStackUse (PUSH_UBX8 Literal
_)         = Word
1  -- overapproximation
bciStackUse (PUSH_UBX16 Literal
_)        = Word
1  -- overapproximation
bciStackUse (PUSH_UBX32 Literal
_)        = Word
1  -- overapproximation on 64bit arch
bciStackUse (PUSH_UBX Literal
_ Word16
nw)       = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
nw
bciStackUse PUSH_APPLY_N{}        = Word
1
bciStackUse PUSH_APPLY_V{}        = Word
1
bciStackUse PUSH_APPLY_F{}        = Word
1
bciStackUse PUSH_APPLY_D{}        = Word
1
bciStackUse PUSH_APPLY_L{}        = Word
1
bciStackUse PUSH_APPLY_P{}        = Word
1
bciStackUse PUSH_APPLY_PP{}       = Word
1
bciStackUse PUSH_APPLY_PPP{}      = Word
1
bciStackUse PUSH_APPLY_PPPP{}     = Word
1
bciStackUse PUSH_APPLY_PPPPP{}    = Word
1
bciStackUse PUSH_APPLY_PPPPPP{}   = Word
1
bciStackUse ALLOC_AP{}            = Word
1
bciStackUse ALLOC_AP_NOUPD{}      = Word
1
bciStackUse ALLOC_PAP{}           = Word
1
bciStackUse (UNPACK Word16
sz)           = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
sz
bciStackUse LABEL{}               = Word
0
bciStackUse TESTLT_I{}            = Word
0
bciStackUse TESTEQ_I{}            = Word
0
bciStackUse TESTLT_W{}            = Word
0
bciStackUse TESTEQ_W{}            = Word
0
bciStackUse TESTLT_F{}            = Word
0
bciStackUse TESTEQ_F{}            = Word
0
bciStackUse TESTLT_D{}            = Word
0
bciStackUse TESTEQ_D{}            = Word
0
bciStackUse TESTLT_P{}            = Word
0
bciStackUse TESTEQ_P{}            = Word
0
bciStackUse CASEFAIL{}            = Word
0
bciStackUse JMP{}                 = Word
0
bciStackUse ENTER{}               = Word
0
bciStackUse RETURN{}              = Word
0
bciStackUse RETURN_UNLIFTED{}     = Word
1 -- pushes stg_ret_X for some X
bciStackUse RETURN_TUPLE{}        = Word
1 -- pushes stg_ret_t header
bciStackUse CCALL{}               = Word
0
bciStackUse SWIZZLE{}             = Word
0
bciStackUse BRK_FUN{}             = Word
0

-- These insns actually reduce stack use, but we need the high-tide level,
-- so can't use this info.  Not that it matters much.
bciStackUse SLIDE{}               = Word
0
bciStackUse MKAP{}                = Word
0
bciStackUse MKPAP{}               = Word
0
bciStackUse PACK{}                = Word
1 -- worst case is PACK 0 words