ghc-9.10.1: GHC/HsToCore/Foreign/Utils.hs
{-# LANGUAGE MultiWayIf #-}
module GHC.HsToCore.Foreign.Utils
( Binding
, getPrimTyOf
, primTyDescChar
, ppPrimTyConStgType
)
where
import GHC.Prelude
import GHC.Platform
import GHC.Tc.Utils.TcType
import GHC.Core (CoreExpr)
import GHC.Core.DataCon
import GHC.Core.TyCon
import GHC.Core.TyCo.Rep
import GHC.Types.Id
import GHC.Types.RepType
import GHC.Builtin.Types
import GHC.Builtin.Types.Prim
import GHC.Utils.Outputable
import GHC.Utils.Panic
type Binding = (Id, CoreExpr) -- No rec/nonrec structure;
-- the occurrence analyser will sort it all out
-- This function returns the primitive type associated with the boxed
-- type argument to a foreign export (eg. Int ==> Int#).
getPrimTyOf :: Type -> UnaryType
getPrimTyOf ty
| isBoolTy rep_ty = intPrimTy
-- Except for Bool, the types we are interested in have a single constructor
-- with a single primitive-typed argument (see TcType.legalFEArgTyCon).
| otherwise =
case splitDataProductType_maybe rep_ty of
Just (_, _, data_con, [Scaled _ prim_ty]) ->
assert (dataConSourceArity data_con == 1) $
assertPpr (isUnliftedType prim_ty) (ppr prim_ty)
-- NB: it's OK to call isUnliftedType here, as we don't allow
-- representation-polymorphic types in foreign import/export declarations
prim_ty
_other -> pprPanic "getPrimTyOf" (ppr ty)
where
rep_ty = unwrapType ty
-- represent a primitive type as a Char, for building a string that
-- described the foreign function type. The types are size-dependent,
-- e.g. 'W' is a signed 32-bit integer.
primTyDescChar :: Platform -> Type -> Char
primTyDescChar !platform ty
| ty `eqType` unitTy = 'v'
| otherwise
= case typePrimRepU (getPrimTyOf ty) of
IntRep -> signed_word
WordRep -> unsigned_word
Int8Rep -> 'B'
Word8Rep -> 'b'
Int16Rep -> 'S'
Word16Rep -> 's'
Int32Rep -> 'W'
Word32Rep -> 'w'
Int64Rep -> 'L'
Word64Rep -> 'l'
AddrRep -> 'p'
FloatRep -> 'f'
DoubleRep -> 'd'
_ -> pprPanic "primTyDescChar" (ppr ty)
where
(signed_word, unsigned_word) = case platformWordSize platform of
PW4 -> ('W','w')
PW8 -> ('L','l')
-- | Printed C Type to be used with CAPI calling convention
ppPrimTyConStgType :: TyCon -> Maybe String
ppPrimTyConStgType tc =
if | tc == charPrimTyCon -> Just "StgChar"
| tc == intPrimTyCon -> Just "StgInt"
| tc == int8PrimTyCon -> Just "StgInt8"
| tc == int16PrimTyCon -> Just "StgInt16"
| tc == int32PrimTyCon -> Just "StgInt32"
| tc == int64PrimTyCon -> Just "StgInt64"
| tc == wordPrimTyCon -> Just "StgWord"
| tc == word8PrimTyCon -> Just "StgWord8"
| tc == word16PrimTyCon -> Just "StgWord16"
| tc == word32PrimTyCon -> Just "StgWord32"
| tc == word64PrimTyCon -> Just "StgWord64"
| tc == floatPrimTyCon -> Just "StgFloat"
| tc == doublePrimTyCon -> Just "StgDouble"
| tc == addrPrimTyCon -> Just "StgAddr"
| tc == stablePtrPrimTyCon -> Just "StgStablePtr"
| tc == arrayPrimTyCon -> Just "const StgAddr"
| tc == mutableArrayPrimTyCon -> Just "StgAddr"
| tc == byteArrayPrimTyCon -> Just "const StgAddr"
| tc == mutableByteArrayPrimTyCon -> Just "StgAddr"
| tc == smallArrayPrimTyCon -> Just "const StgAddr"
| tc == smallMutableArrayPrimTyCon -> Just "StgAddr"
| otherwise -> Nothing