module ByteCodeLink (
ClosureEnv, emptyClosureEnv, extendClosureEnv,
linkBCO, lookupStaticPtr,
lookupIE,
nameToCLabel, linkFail
) where
#include "HsVersions.h"
import GHCi.RemoteTypes
import GHCi.ResolvedBCO
import GHCi.InfoTable
import GHCi.BreakArray
import SizedSeq
import GHCi
import ByteCodeTypes
import HscTypes
import DynFlags
import Name
import NameEnv
import PrimOp
import Module
import FastString
import Panic
import Outputable
import Util
import Data.Array.Unboxed
import Data.Array.Base
import Data.Word
import Foreign.Ptr
import GHC.IO ( IO(..) )
import GHC.Exts
type ClosureEnv = NameEnv (Name, ForeignHValue)
emptyClosureEnv :: ClosureEnv
emptyClosureEnv = emptyNameEnv
extendClosureEnv :: ClosureEnv -> [(Name,ForeignHValue)] -> ClosureEnv
extendClosureEnv cl_env pairs
= extendNameEnvList cl_env [ (n, (n,v)) | (n,v) <- pairs]
linkBCO
:: HscEnv -> ItblEnv -> ClosureEnv -> NameEnv Int -> RemoteRef BreakArray
-> UnlinkedBCO
-> IO ResolvedBCO
linkBCO hsc_env ie ce bco_ix breakarray
(UnlinkedBCO _ arity insns bitmap lits0 ptrs0) = do
lits <- mapM (lookupLiteral hsc_env ie) (ssElts lits0)
ptrs <- mapM (resolvePtr hsc_env ie ce bco_ix breakarray) (ssElts ptrs0)
let dflags = hsc_dflags hsc_env
return (ResolvedBCO arity (toWordArray dflags insns) bitmap
(listArray (0, fromIntegral (sizeSS lits0)1) lits)
(addListToSS emptySS ptrs))
toWordArray :: DynFlags -> UArray Int Word16 -> UArray Int Word
toWordArray dflags (UArray _ _ n arr) = UArray 0 (n'1) n' arr
where n' = (n + w16s_per_word 1) `quot` w16s_per_word
w16s_per_word = wORD_SIZE dflags `quot` 2
lookupLiteral :: HscEnv -> ItblEnv -> BCONPtr -> IO Word
lookupLiteral _ _ (BCONPtrWord lit) = return lit
lookupLiteral hsc_env _ (BCONPtrLbl sym) = do
Ptr a# <- lookupStaticPtr hsc_env sym
return (W# (int2Word# (addr2Int# a#)))
lookupLiteral hsc_env ie (BCONPtrItbl nm) = do
Ptr a# <- lookupIE hsc_env ie nm
return (W# (int2Word# (addr2Int# a#)))
lookupLiteral _ _ (BCONPtrStr _) =
panic "lookupLiteral: BCONPtrStr"
lookupStaticPtr :: HscEnv -> FastString -> IO (Ptr ())
lookupStaticPtr hsc_env addr_of_label_string = do
m <- lookupSymbol hsc_env addr_of_label_string
case m of
Just ptr -> return ptr
Nothing -> linkFail "ByteCodeLink: can't find label"
(unpackFS addr_of_label_string)
lookupIE :: HscEnv -> ItblEnv -> Name -> IO (Ptr ())
lookupIE hsc_env ie con_nm =
case lookupNameEnv ie con_nm of
Just (_, ItblPtr a) -> return (conInfoPtr (fromRemotePtr (castRemotePtr a)))
Nothing -> do
let sym_to_find1 = nameToCLabel con_nm "con_info"
m <- lookupSymbol hsc_env sym_to_find1
case m of
Just addr -> return addr
Nothing
-> do
let sym_to_find2 = nameToCLabel con_nm "static_info"
n <- lookupSymbol hsc_env sym_to_find2
case n of
Just addr -> return addr
Nothing -> linkFail "ByteCodeLink.lookupIE"
(unpackFS sym_to_find1 ++ " or " ++
unpackFS sym_to_find2)
lookupPrimOp :: HscEnv -> PrimOp -> IO (RemotePtr ())
lookupPrimOp hsc_env primop = do
let sym_to_find = primopToCLabel primop "closure"
m <- lookupSymbol hsc_env (mkFastString sym_to_find)
case m of
Just p -> return (toRemotePtr p)
Nothing -> linkFail "ByteCodeLink.lookupCE(primop)" sym_to_find
resolvePtr
:: HscEnv -> ItblEnv -> ClosureEnv -> NameEnv Int -> RemoteRef BreakArray
-> BCOPtr
-> IO ResolvedBCOPtr
resolvePtr hsc_env _ie ce bco_ix _ (BCOPtrName nm)
| Just ix <- lookupNameEnv bco_ix nm =
return (ResolvedBCORef ix)
| Just (_, rhv) <- lookupNameEnv ce nm =
return (ResolvedBCOPtr (unsafeForeignRefToRemoteRef rhv))
| otherwise =
ASSERT2(isExternalName nm, ppr nm)
do let sym_to_find = nameToCLabel nm "closure"
m <- lookupSymbol hsc_env sym_to_find
case m of
Just p -> return (ResolvedBCOStaticPtr (toRemotePtr p))
Nothing -> linkFail "ByteCodeLink.lookupCE" (unpackFS sym_to_find)
resolvePtr hsc_env _ _ _ _ (BCOPtrPrimOp op) =
ResolvedBCOStaticPtr <$> lookupPrimOp hsc_env op
resolvePtr hsc_env ie ce bco_ix breakarray (BCOPtrBCO bco) =
ResolvedBCOPtrBCO <$> linkBCO hsc_env ie ce bco_ix breakarray bco
resolvePtr _ _ _ _ breakarray BCOPtrBreakArray =
return (ResolvedBCOPtrBreakArray breakarray)
linkFail :: String -> String -> IO a
linkFail who what
= throwGhcExceptionIO (ProgramError $
unlines [ "",who
, "During interactive linking, GHCi couldn't find the following symbol:"
, ' ' : ' ' : what
, "This may be due to you not asking GHCi to load extra object files,"
, "archives or DLLs needed by your current session. Restart GHCi, specifying"
, "the missing library using the -L/path/to/object/dir and -lmissinglibname"
, "flags, or simply by naming the relevant files on the GHCi command line."
, "Alternatively, this link failure might indicate a bug in GHCi."
, "If you suspect the latter, please send a bug report to:"
, " [email protected]"
])
nameToCLabel :: Name -> String -> FastString
nameToCLabel n suffix = mkFastString label
where
encodeZ = zString . zEncodeFS
(Module pkgKey modName) = ASSERT( isExternalName n ) nameModule n
packagePart = encodeZ (unitIdFS pkgKey)
modulePart = encodeZ (moduleNameFS modName)
occPart = encodeZ (occNameFS (nameOccName n))
label = concat
[ if pkgKey == mainUnitId then "" else packagePart ++ "_"
, modulePart
, '_':occPart
, '_':suffix
]
primopToCLabel :: PrimOp -> String -> String
primopToCLabel primop suffix = concat
[ "ghczmprim_GHCziPrimopWrappers_"
, zString (zEncodeFS (occNameFS (primOpOcc primop)))
, '_':suffix
]