ghc-9.12.1: GHC/StgToJS/Literal.hs
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ViewPatterns #-}
module GHC.StgToJS.Literal
( genLit
, genStaticLit
)
where
import GHC.Prelude
import GHC.JS.JStg.Syntax
import GHC.JS.Make
import GHC.JS.Ident
import GHC.StgToJS.Ids
import GHC.StgToJS.Monad
import GHC.StgToJS.Symbols
import GHC.StgToJS.Types
import GHC.Data.FastString
import GHC.Types.Literal
import GHC.Types.Basic
import GHC.Types.RepType
import GHC.Utils.Misc
import GHC.Utils.Panic
import GHC.Utils.Outputable
import GHC.Float
import Data.Bits as Bits
import Data.Char (ord)
-- | Generate JS expressions for a Literal
--
-- Literals represented with 2 values:
-- * Addr# (Null and Strings): array and offset
-- * 64-bit values: high 32-bit, low 32-bit
-- * labels: call to h$mkFunctionPtr and 0, or function name and 0
genLit :: HasDebugCallStack => Literal -> G [JStgExpr]
genLit = \case
LitChar c -> return [ toJExpr (ord c) ]
LitString str ->
freshIdent >>= \strLit@(identFS -> strLitT) ->
freshIdent >>= \strOff@(identFS -> strOffT) -> do
emitStatic strLitT (StaticUnboxed (StaticUnboxedString str)) Nothing
emitStatic strOffT (StaticUnboxed (StaticUnboxedStringOffset str)) Nothing
return [ Var strLit, Var strOff ]
LitNullAddr -> return [ null_, ValExpr (JInt 0) ]
LitNumber nt v -> case nt of
LitNumInt -> return [ toJExpr v ]
LitNumInt8 -> return [ toJExpr v ]
LitNumInt16 -> return [ toJExpr v ]
LitNumInt32 -> return [ toJExpr v ]
LitNumInt64 -> return [ toJExpr (Bits.shiftR v 32), toU32Expr v ]
LitNumWord -> return [ toU32Expr v ]
LitNumWord8 -> return [ toU32Expr v ]
LitNumWord16 -> return [ toU32Expr v ]
LitNumWord32 -> return [ toU32Expr v ]
LitNumWord64 -> return [ toU32Expr (Bits.shiftR v 32), toU32Expr v ]
LitNumBigNat -> panic "genLit: unexpected BigNat that should have been removed in CorePrep"
LitFloat r -> return [ toJExpr (r2f r) ]
LitDouble r -> return [ toJExpr (r2d r) ]
LitLabel name fod
| fod == IsFunction -> return [ ApplExpr hdMkFunctionPtr
[global (mkRawSymbol True name)]
, ValExpr (JInt 0)
]
| otherwise -> return [ toJExpr (global (mkRawSymbol True name))
, ValExpr (JInt 0)
]
LitRubbish _ rr_ty ->
-- Generate appropriate rubbish literals, otherwise it might trip up the
-- code generator when a primop is applied to a rubbish literal (see #24664)
let reps = runtimeRepPrimRep (text "GHC.StgToJS.Literal.genLit") rr_ty
rub = \case
BoxedRep _ -> [ null_ ]
AddrRep -> [ null_, ValExpr (JInt 0) ]
WordRep -> [ ValExpr (JInt 0) ]
Word8Rep -> [ ValExpr (JInt 0) ]
Word16Rep -> [ ValExpr (JInt 0) ]
Word32Rep -> [ ValExpr (JInt 0) ]
Word64Rep -> [ ValExpr (JInt 0), ValExpr (JInt 0) ]
IntRep -> [ ValExpr (JInt 0) ]
Int8Rep -> [ ValExpr (JInt 0) ]
Int16Rep -> [ ValExpr (JInt 0) ]
Int32Rep -> [ ValExpr (JInt 0) ]
Int64Rep -> [ ValExpr (JInt 0), ValExpr (JInt 0) ]
DoubleRep -> [ ValExpr (JInt 0) ]
FloatRep -> [ ValExpr (JInt 0) ]
VecRep _ _ -> panic "GHC.StgToJS.Literal.genLit: VecRep unsupported"
in return (concatMap rub reps)
-- | generate a literal for the static init tables
genStaticLit :: Literal -> G [StaticLit]
genStaticLit = \case
LitChar c -> return [ IntLit (fromIntegral $ ord c) ]
LitString str
| True -> return [ StringLit (mkFastStringByteString str), IntLit 0]
-- \| invalid UTF8 -> return [ BinLit str, IntLit 0]
LitNullAddr -> return [ NullLit, IntLit 0 ]
LitNumber nt v -> case nt of
LitNumInt -> return [ IntLit v ]
LitNumInt8 -> return [ IntLit v ]
LitNumInt16 -> return [ IntLit v ]
LitNumInt32 -> return [ IntLit v ]
LitNumInt64 -> return [ IntLit (v `Bits.shiftR` 32), toU32Lit v ]
LitNumWord -> return [ toU32Lit v ]
LitNumWord8 -> return [ toU32Lit v ]
LitNumWord16 -> return [ toU32Lit v ]
LitNumWord32 -> return [ toU32Lit v ]
LitNumWord64 -> return [ toU32Lit (v `Bits.shiftR` 32), toU32Lit v ]
LitNumBigNat -> panic "genStaticLit: unexpected BigNat that should have been removed in CorePrep"
LitFloat r -> return [ DoubleLit . SaneDouble . r2f $ r ]
LitDouble r -> return [ DoubleLit . SaneDouble . r2d $ r ]
LitLabel name fod -> return [ LabelLit (fod == IsFunction) (mkRawSymbol True name)
, IntLit 0 ]
LitRubbish _ rep ->
let prim_reps = runtimeRepPrimRep (text "GHC.StgToJS.Literal.genStaticLit") rep
in case expectOnly "GHC.StgToJS.Literal.genStaticLit" prim_reps of -- Note [Post-unarisation invariants]
BoxedRep _ -> pure [ NullLit ]
AddrRep -> pure [ NullLit, IntLit 0 ]
IntRep -> pure [ IntLit 0 ]
Int8Rep -> pure [ IntLit 0 ]
Int16Rep -> pure [ IntLit 0 ]
Int32Rep -> pure [ IntLit 0 ]
Int64Rep -> pure [ IntLit 0, IntLit 0 ]
WordRep -> pure [ IntLit 0 ]
Word8Rep -> pure [ IntLit 0 ]
Word16Rep -> pure [ IntLit 0 ]
Word32Rep -> pure [ IntLit 0 ]
Word64Rep -> pure [ IntLit 0, IntLit 0 ]
FloatRep -> pure [ DoubleLit (SaneDouble 0) ]
DoubleRep -> pure [ DoubleLit (SaneDouble 0) ]
VecRep {} -> pprPanic "GHC.StgToJS.Literal.genStaticLit: LitRubbish(VecRep) isn't supported" (ppr rep)
-- make an unsigned 32 bit number from this unsigned one, lower 32 bits
toU32Expr :: Integer -> JStgExpr
toU32Expr i = Int (i Bits..&. 0xFFFFFFFF) .>>>. 0
-- make an unsigned 32 bit number from this unsigned one, lower 32 bits
toU32Lit :: Integer -> StaticLit
toU32Lit i = IntLit (i Bits..&. 0xFFFFFFFF)
r2d :: Rational -> Double
r2d = realToFrac
r2f :: Rational -> Double
r2f = float2Double . realToFrac