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

-- | Bytecode instruction definitions
module GHC.ByteCode.Instr (
        BCInstr(..), ProtoBCO(..), bciStackUse,
  ) 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.Core.Ppr
import GHC.Utils.Outputable
import GHC.Data.FastString
import GHC.Types.Name
import GHC.Types.Unique
import GHC.Types.Id
import GHC.Core
import GHC.Types.Literal
import GHC.Core.DataCon
import GHC.Types.Var.Set
import GHC.Builtin.PrimOps
import GHC.Runtime.Heap.Layout

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

-- ----------------------------------------------------------------------------
-- 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 [AnnAlt CoreBndr DVarSet] (AnnExpr CoreBndr DVarSet)
protoBCOExpr       :: Either  [AnnAlt Id DVarSet] (AnnExpr Id DVarSet),
        -- malloc'd pointers
        forall a. ProtoBCO a -> [FFIInfo]
protoBCOFFIs       :: [FFIInfo]
   }

type LocalLabel = Word16

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

   -- 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_UBX ArgRep -- return an unlifted value, here's its rep

   -- 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 [AnnAlt CoreBndr DVarSet] (AnnExpr CoreBndr DVarSet)
protoBCOExpr       = Either [AnnAlt CoreBndr DVarSet] (AnnExpr CoreBndr DVarSet)
origin
                 , protoBCOFFIs :: forall a. ProtoBCO a -> [FFIInfo]
protoBCOFFIs       = [FFIInfo]
ffis })
      = (String -> SDoc
text String
"ProtoBCO" SDoc -> SDoc -> SDoc
<+> a -> 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 ([FFIInfo] -> String
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 [AnnAlt CoreBndr DVarSet] (AnnExpr CoreBndr DVarSet)
origin of
                      Left [AnnAlt CoreBndr DVarSet]
alts -> [SDoc] -> SDoc
vcat ((SDoc -> SDoc -> SDoc) -> [SDoc] -> [SDoc] -> [SDoc]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith SDoc -> SDoc -> SDoc
(<+>) (Char -> SDoc
char Char
'{' SDoc -> [SDoc] -> [SDoc]
forall a. a -> [a] -> [a]
: SDoc -> [SDoc]
forall a. a -> [a]
repeat (Char -> SDoc
char Char
';'))
                                                       ((AnnAlt CoreBndr DVarSet -> SDoc)
-> [AnnAlt CoreBndr DVarSet] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map (CoreAlt -> SDoc
pprCoreAltShort(CoreAlt -> SDoc)
-> (AnnAlt CoreBndr DVarSet -> CoreAlt)
-> AnnAlt CoreBndr DVarSet
-> SDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
.AnnAlt CoreBndr DVarSet -> CoreAlt
forall bndr annot. AnnAlt bndr annot -> Alt bndr
deAnnAlt) [AnnAlt CoreBndr DVarSet]
alts)) SDoc -> SDoc -> SDoc
<+> Char -> SDoc
char Char
'}'
                      Right AnnExpr CoreBndr DVarSet
rhs -> CoreExpr -> SDoc
pprCoreExprShort (AnnExpr CoreBndr DVarSet -> CoreExpr
forall bndr annot. AnnExpr bndr annot -> Expr bndr
deAnnotate AnnExpr CoreBndr DVarSet
rhs))
        SDoc -> SDoc -> SDoc
$$ Int -> SDoc -> SDoc
nest Int
3 (String -> SDoc
text String
"bitmap: " SDoc -> SDoc -> SDoc
<+> String -> SDoc
text (Word16 -> String
forall a. Show a => a -> String
show Word16
bsize) SDoc -> SDoc -> SDoc
<+> [StgWord] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [StgWord]
bitmap)
        SDoc -> SDoc -> SDoc
$$ Int -> SDoc -> SDoc
nest Int
3 ([SDoc] -> SDoc
vcat ((BCInstr -> SDoc) -> [BCInstr] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map BCInstr -> SDoc
forall a. Outputable a => a -> SDoc
ppr [BCInstr]
instrs))

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

pprCoreExprShort :: CoreExpr -> SDoc
pprCoreExprShort :: CoreExpr -> SDoc
pprCoreExprShort expr :: CoreExpr
expr@(Lam CoreBndr
_ CoreExpr
_)
  = let
        ([CoreBndr]
bndrs, CoreExpr
_) = CoreExpr -> ([CoreBndr], CoreExpr)
forall b. Expr b -> ([b], Expr b)
collectBinders CoreExpr
expr
    in
    Char -> SDoc
char Char
'\\' SDoc -> SDoc -> SDoc
<+> [SDoc] -> SDoc
sep ((CoreBndr -> SDoc) -> [CoreBndr] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map (BindingSite -> CoreBndr -> SDoc
forall a. OutputableBndr a => BindingSite -> a -> SDoc
pprBndr BindingSite
LambdaBind) [CoreBndr]
bndrs) SDoc -> SDoc -> SDoc
<+> SDoc
arrow SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"..."

pprCoreExprShort (Case CoreExpr
_expr CoreBndr
var Type
_ty [CoreAlt]
_alts)
 = String -> SDoc
text String
"case of" SDoc -> SDoc -> SDoc
<+> CoreBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreBndr
var

pprCoreExprShort (Let (NonRec CoreBndr
x CoreExpr
_) CoreExpr
_) = String -> SDoc
text String
"let" SDoc -> SDoc -> SDoc
<+> CoreBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreBndr
x SDoc -> SDoc -> SDoc
<+> PtrString -> SDoc
ptext (String -> PtrString
sLit (String
"= ... in ..."))
pprCoreExprShort (Let (Rec [(CoreBndr, CoreExpr)]
bs) CoreExpr
_) = String -> SDoc
text String
"let {" SDoc -> SDoc -> SDoc
<+> CoreBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr ((CoreBndr, CoreExpr) -> CoreBndr
forall a b. (a, b) -> a
fst ([(CoreBndr, CoreExpr)] -> (CoreBndr, CoreExpr)
forall a. [a] -> a
head [(CoreBndr, CoreExpr)]
bs)) SDoc -> SDoc -> SDoc
<+> PtrString -> SDoc
ptext (String -> PtrString
sLit (String
"= ...; ... } in ..."))

pprCoreExprShort (Tick Tickish CoreBndr
t CoreExpr
e) = Tickish CoreBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr Tickish CoreBndr
t SDoc -> SDoc -> SDoc
<+> CoreExpr -> SDoc
pprCoreExprShort CoreExpr
e
pprCoreExprShort (Cast CoreExpr
e CoercionR
_) = CoreExpr -> SDoc
pprCoreExprShort CoreExpr
e SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"`cast` T"

pprCoreExprShort CoreExpr
e = CoreExpr -> SDoc
forall b. OutputableBndr b => Expr b -> SDoc
pprCoreExpr CoreExpr
e

pprCoreAltShort :: CoreAlt -> SDoc
pprCoreAltShort :: CoreAlt -> SDoc
pprCoreAltShort (AltCon
con, [CoreBndr]
args, CoreExpr
expr) = AltCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr AltCon
con SDoc -> SDoc -> SDoc
<+> [SDoc] -> SDoc
sep ((CoreBndr -> SDoc) -> [CoreBndr] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map CoreBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr [CoreBndr]
args) SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"->" SDoc -> SDoc -> SDoc
<+> CoreExpr -> SDoc
pprCoreExprShort CoreExpr
expr

instance Outputable BCInstr where
   ppr :: BCInstr -> SDoc
ppr (STKCHECK Word
n)          = String -> SDoc
text String
"STKCHECK" SDoc -> SDoc -> SDoc
<+> Word -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word
n
   ppr (PUSH_L Word16
offset)       = String -> SDoc
text String
"PUSH_L  " SDoc -> SDoc -> SDoc
<+> Word16 -> 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
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
o1 SDoc -> SDoc -> SDoc
<+> Word16 -> 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
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
o1 SDoc -> SDoc -> SDoc
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
o2 SDoc -> SDoc -> SDoc
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
o3
   ppr (PUSH8  Word16
offset)       = String -> SDoc
text String
"PUSH8  " SDoc -> SDoc -> SDoc
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
offset
   ppr (PUSH16 Word16
offset)       = String -> SDoc
text String
"PUSH16  " SDoc -> SDoc -> SDoc
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
offset
   ppr (PUSH32 Word16
offset)       = String -> SDoc
text String
"PUSH32  " SDoc -> SDoc -> SDoc
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
offset
   ppr (PUSH8_W  Word16
offset)     = String -> SDoc
text String
"PUSH8_W  " SDoc -> SDoc -> SDoc
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
offset
   ppr (PUSH16_W Word16
offset)     = String -> SDoc
text String
"PUSH16_W  " SDoc -> SDoc -> SDoc
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
offset
   ppr (PUSH32_W Word16
offset)     = String -> SDoc
text String
"PUSH32_W  " SDoc -> SDoc -> SDoc
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
offset
   ppr (PUSH_G Name
nm)           = String -> SDoc
text String
"PUSH_G  " SDoc -> SDoc -> SDoc
<+> Name -> 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
<> PrimOp -> 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 (ProtoBCO Name -> SDoc
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 (ProtoBCO Name -> SDoc
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
<+> ArgRep -> SDoc
forall a. Outputable a => a -> SDoc
ppr ArgRep
pk) Int
2 (ProtoBCO Name -> 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
<+> Literal -> SDoc
forall a. Outputable a => a -> SDoc
ppr Literal
lit
   ppr (PUSH_UBX16 Literal
lit)      = String -> SDoc
text String
"PUSH_UBX16" SDoc -> SDoc -> SDoc
<+> Literal -> SDoc
forall a. Outputable a => a -> SDoc
ppr Literal
lit
   ppr (PUSH_UBX32 Literal
lit)      = String -> SDoc
text String
"PUSH_UBX32" SDoc -> SDoc -> SDoc
<+> Literal -> 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 (Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
nw) SDoc -> SDoc -> SDoc
<+> Literal -> 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
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
n SDoc -> SDoc -> SDoc
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
d
   ppr (ALLOC_AP Word16
sz)         = String -> SDoc
text String
"ALLOC_AP   " SDoc -> SDoc -> SDoc
<+> Word16 -> 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
<+> Word16 -> 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
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
arity SDoc -> SDoc -> SDoc
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
sz
   ppr (MKAP Word16
offset Word16
sz)      = String -> SDoc
text String
"MKAP    " SDoc -> SDoc -> SDoc
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
sz SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"words,"
                                               SDoc -> SDoc -> SDoc
<+> Word16 -> 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
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
sz SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"words,"
                                               SDoc -> SDoc -> SDoc
<+> Word16 -> 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
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
sz
   ppr (PACK DataCon
dcon Word16
sz)        = String -> SDoc
text String
"PACK    " SDoc -> SDoc -> SDoc
<+> DataCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr DataCon
dcon SDoc -> SDoc -> SDoc
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
sz
   ppr (LABEL     Word16
lab)       = String -> SDoc
text String
"__"       SDoc -> SDoc -> SDoc
<> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
lab SDoc -> SDoc -> SDoc
<> SDoc
colon
   ppr (TESTLT_I  Int
i Word16
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
<> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
lab
   ppr (TESTEQ_I  Int
i Word16
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
<> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
lab
   ppr (TESTLT_W  Word
i Word16
lab)     = String -> SDoc
text String
"TESTLT_W" SDoc -> SDoc -> SDoc
<+> Int -> SDoc
int (Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
i) SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"__" SDoc -> SDoc -> SDoc
<> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
lab
   ppr (TESTEQ_W  Word
i Word16
lab)     = String -> SDoc
text String
"TESTEQ_W" SDoc -> SDoc -> SDoc
<+> Int -> SDoc
int (Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
i) SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"__" SDoc -> SDoc -> SDoc
<> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
lab
   ppr (TESTLT_F  Float
f Word16
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
<> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
lab
   ppr (TESTEQ_F  Float
f Word16
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
<> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
lab
   ppr (TESTLT_D  Double
d Word16
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
<> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
lab
   ppr (TESTEQ_D  Double
d Word16
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
<> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
lab
   ppr (TESTLT_P  Word16
i Word16
lab)     = String -> SDoc
text String
"TESTLT_P" SDoc -> SDoc -> SDoc
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
i SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"__" SDoc -> SDoc -> SDoc
<> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
lab
   ppr (TESTEQ_P  Word16
i Word16
lab)     = String -> SDoc
text String
"TESTEQ_P" SDoc -> SDoc -> SDoc
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
i SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"__" SDoc -> SDoc -> SDoc
<> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
lab
   ppr BCInstr
CASEFAIL              = String -> SDoc
text String
"CASEFAIL"
   ppr (JMP Word16
lab)             = String -> SDoc
text String
"JMP"      SDoc -> SDoc -> SDoc
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
lab
   ppr (CCALL Word16
off RemotePtr C_ffi_cif
marshall_addr Word16
flags) = String -> SDoc
text String
"CCALL   " SDoc -> SDoc -> SDoc
<+> Word16 -> 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 (RemotePtr C_ffi_cif -> String
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
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
stkoff
                                               SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"by" SDoc -> SDoc -> SDoc
<+> Word16 -> 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_UBX ArgRep
pk)       = String -> SDoc
text String
"RETURN_UBX  " SDoc -> SDoc -> SDoc
<+> ArgRep -> SDoc
forall a. Outputable a => a -> SDoc
ppr ArgRep
pk
   ppr (BRK_FUN Word16
index Unique
uniq RemotePtr CostCentre
_cc) = String -> SDoc
text String
"BRK_FUN" SDoc -> SDoc -> SDoc
<+> Word16 -> SDoc
forall a. Outputable a => a -> SDoc
ppr Word16
index SDoc -> SDoc -> SDoc
<+> Unique -> 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 = [Word] -> Word
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((BCInstr -> Word) -> [BCInstr] -> [Word]
forall a b. (a -> b) -> [a] -> [b]
map BCInstr -> Word
bciStackUse (ProtoBCO a -> [BCInstr]
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 Word -> Word -> Word
forall a. Num a => a -> a -> a
+ ProtoBCO Name -> Word
forall a. ProtoBCO a -> Word
protoBCOStackUse ProtoBCO Name
bco
bciStackUse (PUSH_ALTS_UNLIFTED ProtoBCO Name
bco ArgRep
_) = Word
2 Word -> Word -> Word
forall a. Num a => a -> a -> a
+ ProtoBCO Name -> Word
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)       = Word16 -> Word
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)           = Word16 -> Word
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_UBX{}          = Word
1
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