Cheng Shao pushed to branch wip/ghci-messages-no-string at Glasgow Haskell Compiler / GHC
Commits:
-
502e6ffe
by Andrew Lelechenko at 2026-04-07T04:47:21-04:00
-
b21bd52e
by Simon Peyton Jones at 2026-04-07T04:48:07-04:00
-
4b999500
by Cheng Shao at 2026-04-07T08:57:36+00:00
-
475642de
by Cheng Shao at 2026-04-07T08:57:39+00:00
22 changed files:
- compiler/GHC/ByteCode/Breakpoints.hs
- compiler/GHC/Driver/Plugins.hs
- compiler/GHC/HsToCore/Breakpoints.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Runtime/Interpreter.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Types/ErrCtxt.hs
- compiler/GHC/Tc/Utils/TcType.hs
- compiler/GHC/Tc/Zonk/TcType.hs
- libraries/base/changelog.md
- libraries/base/tests/enum01.stdout
- libraries/base/tests/enum01.stdout-alpha-dec-osf3
- libraries/base/tests/enum01.stdout-ws-64
- libraries/ghc-internal/src/GHC/Internal/Char.hs
- libraries/ghci/GHCi/Message.hs
- libraries/ghci/GHCi/ObjLink.hs
- libraries/ghci/GHCi/Run.hs
- testsuite/tests/driver/linkwhole/Main.hs
- testsuite/tests/ghci/should_run/T18064.script
- testsuite/tests/rts/KeepCafsMain.hs
- utils/jsffi/dyld.mjs
Changes:
| ... | ... | @@ -37,6 +37,7 @@ import GHC.Prelude |
| 37 | 37 | import GHC.Types.SrcLoc
|
| 38 | 38 | import GHC.Types.Name.Occurrence
|
| 39 | 39 | import Control.DeepSeq
|
| 40 | +import qualified Data.ByteString.Short as SBS
|
|
| 40 | 41 | import Data.IntMap.Strict (IntMap)
|
| 41 | 42 | import qualified Data.IntMap.Strict as IM
|
| 42 | 43 | |
| ... | ... | @@ -235,8 +236,8 @@ getBreakVars = getBreakXXX modBreaks_vars |
| 235 | 236 | getBreakDecls :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO [String]
|
| 236 | 237 | getBreakDecls = getBreakXXX modBreaks_decls
|
| 237 | 238 | |
| 238 | --- | Get the decls for this breakpoint
|
|
| 239 | -getBreakCCS :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO ((String, String))
|
|
| 239 | +-- | Get the cost centre info for this breakpoint
|
|
| 240 | +getBreakCCS :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO (SBS.ShortByteString, SBS.ShortByteString)
|
|
| 240 | 241 | getBreakCCS = getBreakXXX modBreaks_ccs
|
| 241 | 242 | |
| 242 | 243 | -- | Internal utility to access a ModBreaks field at a particular breakpoint index
|
| ... | ... | @@ -405,7 +405,7 @@ loadExternalPlugins ps = do |
| 405 | 405 | symbol
|
| 406 | 406 | | null unit = ztmp
|
| 407 | 407 | | otherwise = zEncodeString unit ++ "_" ++ ztmp
|
| 408 | - plugin <- lookupSymbol symbol >>= \case
|
|
| 408 | + plugin <- lookupSymbol (utf8EncodeShortByteString symbol) >>= \case
|
|
| 409 | 409 | Nothing -> pprPanic "loadExternalPlugins"
|
| 410 | 410 | (vcat [ text "Symbol not found"
|
| 411 | 411 | , text " Library path: " <> text path
|
| ... | ... | @@ -23,6 +23,7 @@ module GHC.HsToCore.Breakpoints |
| 23 | 23 | |
| 24 | 24 | import GHC.Prelude
|
| 25 | 25 | import Data.Array
|
| 26 | +import qualified Data.ByteString.Short as SBS
|
|
| 26 | 27 | |
| 27 | 28 | import GHC.HsToCore.Ticks (Tick (..))
|
| 28 | 29 | import GHC.Data.SizedSeq
|
| ... | ... | @@ -31,6 +32,7 @@ import GHC.Types.Name (OccName) |
| 31 | 32 | import GHC.Types.Tickish (BreakTickIndex, BreakpointId(..))
|
| 32 | 33 | import GHC.Unit.Module (Module)
|
| 33 | 34 | import GHC.Utils.Binary
|
| 35 | +import GHC.Utils.Encoding (utf8EncodeShortByteString)
|
|
| 34 | 36 | import GHC.Utils.Outputable
|
| 35 | 37 | import Data.List (intersperse)
|
| 36 | 38 | import Data.Coerce
|
| ... | ... | @@ -59,7 +61,7 @@ data ModBreaks |
| 59 | 61 | , modBreaks_decls :: !(Array BreakTickIndex [String])
|
| 60 | 62 | -- ^ An array giving the names of the declarations enclosing each breakpoint.
|
| 61 | 63 | -- See Note [Field modBreaks_decls]
|
| 62 | - , modBreaks_ccs :: !(Array BreakTickIndex (String, String))
|
|
| 64 | + , modBreaks_ccs :: !(Array BreakTickIndex (SBS.ShortByteString, SBS.ShortByteString))
|
|
| 63 | 65 | -- ^ Array pointing to cost centre info for each breakpoint;
|
| 64 | 66 | -- actual 'CostCentre' allocation is done at link-time.
|
| 65 | 67 | , modBreaks_module :: !Module
|
| ... | ... | @@ -89,8 +91,8 @@ mkModBreaks interpreterProfiled modl extendedMixEntries |
| 89 | 91 | | interpreterProfiled =
|
| 90 | 92 | listArray
|
| 91 | 93 | (0, count - 1)
|
| 92 | - [ ( concat $ intersperse "." $ tick_path t,
|
|
| 93 | - renderWithContext defaultSDocContext $ ppr $ tick_loc t
|
|
| 94 | + [ ( utf8EncodeShortByteString $ concat $ intersperse "." $ tick_path t,
|
|
| 95 | + utf8EncodeShortByteString $ renderWithContext defaultSDocContext $ ppr $ tick_loc t
|
|
| 94 | 96 | )
|
| 95 | 97 | | t <- entries
|
| 96 | 98 | ]
|
| ... | ... | @@ -1846,7 +1846,7 @@ allocateCCS interp ce mbss |
| 1846 | 1846 | ccs <- {- one ccs ptr per tick index -}
|
| 1847 | 1847 | mkCostCentres
|
| 1848 | 1848 | interp
|
| 1849 | - (moduleNameString $ moduleName modBreaks_module)
|
|
| 1849 | + (moduleNameFS $ moduleName modBreaks_module)
|
|
| 1850 | 1850 | (elems modBreaks_ccs)
|
| 1851 | 1851 | return $ M.fromList $
|
| 1852 | 1852 | zipWith (\el ix -> (BreakpointId modBreaks_module ix, el)) ccs [0..]
|
| ... | ... | @@ -107,6 +107,7 @@ import Control.Monad.IO.Class |
| 107 | 107 | import Control.Monad.Catch as MC (mask)
|
| 108 | 108 | import Data.Binary
|
| 109 | 109 | import Data.ByteString (ByteString)
|
| 110 | +import qualified Data.ByteString.Short as SBS
|
|
| 110 | 111 | import Foreign hiding (void)
|
| 111 | 112 | import qualified GHC.Exts.Heap as Heap
|
| 112 | 113 | import GHC.Stack.CCS (CostCentre,CostCentreStack)
|
| ... | ... | @@ -352,9 +353,15 @@ evalStringToIOString interp fhv str = |
| 352 | 353 | mallocData :: Interp -> ByteString -> IO (RemotePtr ())
|
| 353 | 354 | mallocData interp bs = interpCmd interp (MallocData bs)
|
| 354 | 355 | |
| 355 | -mkCostCentres :: Interp -> String -> [(String,String)] -> IO [RemotePtr CostCentre]
|
|
| 356 | -mkCostCentres interp mod ccs =
|
|
| 357 | - interpCmd interp (MkCostCentres mod ccs)
|
|
| 356 | +mkCostCentres :: Interp -> FastString -> [(SBS.ShortByteString, SBS.ShortByteString)] -> IO [RemotePtr CostCentre]
|
|
| 357 | +mkCostCentres interp mod ccs = do
|
|
| 358 | + rp <- modifyMVar (interpStringCache interp) $ \fs_env ->
|
|
| 359 | + case lookupFsEnv fs_env mod of
|
|
| 360 | + Just rp -> pure (fs_env, rp)
|
|
| 361 | + Nothing -> do
|
|
| 362 | + rp <- fmap head $ interpCmd interp $ MallocStrings [bytesFS mod]
|
|
| 363 | + pure (extendFsEnv fs_env mod rp, rp)
|
|
| 364 | + interpCmd interp $ MkCostCentres rp ccs
|
|
| 358 | 365 | |
| 359 | 366 | -- | Create a set of BCOs that may be mutually recursive.
|
| 360 | 367 | createBCOs :: Interp -> [ResolvedBCO] -> IO [HValueRef]
|
| ... | ... | @@ -413,7 +420,7 @@ evalBreakpointToId :: EvalBreakpoint -> InternalBreakpointId |
| 413 | 420 | evalBreakpointToId eval_break =
|
| 414 | 421 | let
|
| 415 | 422 | mkUnitId u = fsToUnit $ mkFastStringShortByteString u
|
| 416 | - toModule u n = mkModule (mkUnitId u) (mkModuleName n)
|
|
| 423 | + toModule u n = mkModule (mkUnitId u) (mkModuleNameFS (mkFastStringShortByteString n))
|
|
| 417 | 424 | in
|
| 418 | 425 | InternalBreakpointId
|
| 419 | 426 | { ibi_info_mod = toModule (eb_info_mod_unit eval_break) (eb_info_mod eval_break)
|
| ... | ... | @@ -465,27 +472,27 @@ lookupSymbol :: Interp -> InterpSymbol s -> IO (Maybe (Ptr ())) |
| 465 | 472 | lookupSymbol interp str = withSymbolCache interp str $
|
| 466 | 473 | case interpInstance interp of
|
| 467 | 474 | #if defined(HAVE_INTERNAL_INTERPRETER)
|
| 468 | - InternalInterp -> fmap fromRemotePtr <$> run (LookupSymbol (unpackFS (interpSymbolToCLabel str)))
|
|
| 475 | + InternalInterp -> fmap fromRemotePtr <$> run (LookupSymbol (fastStringToShortByteString (interpSymbolToCLabel str)))
|
|
| 469 | 476 | #endif
|
| 470 | 477 | ExternalInterp ext -> case ext of
|
| 471 | 478 | ExtIServ i -> withIServ i $ \inst -> fmap fromRemotePtr <$> do
|
| 472 | 479 | uninterruptibleMask_ $
|
| 473 | - sendMessage inst (LookupSymbol (unpackFS (interpSymbolToCLabel str)))
|
|
| 480 | + sendMessage inst (LookupSymbol (fastStringToShortByteString (interpSymbolToCLabel str)))
|
|
| 474 | 481 | ExtJS {} -> pprPanic "lookupSymbol not supported by the JS interpreter" (ppr str)
|
| 475 | 482 | ExtWasm i -> withWasmInterp i $ \inst -> fmap fromRemotePtr <$> do
|
| 476 | 483 | uninterruptibleMask_ $
|
| 477 | - sendMessage inst (LookupSymbol (unpackFS (interpSymbolToCLabel str)))
|
|
| 484 | + sendMessage inst (LookupSymbol (fastStringToShortByteString (interpSymbolToCLabel str)))
|
|
| 478 | 485 | |
| 479 | 486 | lookupSymbolInDLL :: Interp -> RemotePtr LoadedDLL -> InterpSymbol s -> IO (Maybe (Ptr ()))
|
| 480 | 487 | lookupSymbolInDLL interp dll str = withSymbolCache interp str $
|
| 481 | 488 | case interpInstance interp of
|
| 482 | 489 | #if defined(HAVE_INTERNAL_INTERPRETER)
|
| 483 | - InternalInterp -> fmap fromRemotePtr <$> run (LookupSymbolInDLL dll (unpackFS (interpSymbolToCLabel str)))
|
|
| 490 | + InternalInterp -> fmap fromRemotePtr <$> run (LookupSymbolInDLL dll (fastStringToShortByteString (interpSymbolToCLabel str)))
|
|
| 484 | 491 | #endif
|
| 485 | 492 | ExternalInterp ext -> case ext of
|
| 486 | 493 | ExtIServ i -> withIServ i $ \inst -> fmap fromRemotePtr <$> do
|
| 487 | 494 | uninterruptibleMask_ $
|
| 488 | - sendMessage inst (LookupSymbolInDLL dll (unpackFS (interpSymbolToCLabel str)))
|
|
| 495 | + sendMessage inst (LookupSymbolInDLL dll (fastStringToShortByteString (interpSymbolToCLabel str)))
|
|
| 489 | 496 | ExtJS {} -> pprPanic "lookupSymbol not supported by the JS interpreter" (ppr str)
|
| 490 | 497 | -- wasm dyld doesn't track which symbol comes from which .so
|
| 491 | 498 | ExtWasm {} -> lookupSymbol interp str
|
| ... | ... | @@ -519,7 +526,7 @@ interpSymbolToCLabel s = eliminateInterpSymbol s interpretedInterpSymbol $ \is - |
| 519 | 526 | |
| 520 | 527 | lookupClosure :: Interp -> InterpSymbol s -> IO (Maybe HValueRef)
|
| 521 | 528 | lookupClosure interp str =
|
| 522 | - interpCmd interp (LookupClosure (unpackFS (interpSymbolToCLabel str)))
|
|
| 529 | + interpCmd interp (LookupClosure (fastStringToShortByteString (interpSymbolToCLabel str)))
|
|
| 523 | 530 | |
| 524 | 531 | -- | 'withSymbolCache' tries to find a symbol in the 'interpLookupSymbolCache'
|
| 525 | 532 | -- which maps symbols to the address where they are loaded.
|
| ... | ... | @@ -7710,12 +7710,8 @@ pprHsCtxt = \case |
| 7710 | 7710 | PatSigErrCtxt sig_ty res_ty ->
|
| 7711 | 7711 | vcat [ hang (text "When checking that the pattern signature:")
|
| 7712 | 7712 | 4 (ppr sig_ty)
|
| 7713 | - , nest 2 (hang (text "fits the type of its context:") 2 pp_res_ty) ]
|
|
| 7714 | - where
|
|
| 7715 | - -- Zonking will have turned Infer into Check
|
|
| 7716 | - pp_res_ty = case res_ty of
|
|
| 7717 | - Check ty -> ppr ty
|
|
| 7718 | - Infer ir -> text "OOPS" <+> ppr ir
|
|
| 7713 | + , nest 2 (hang (text "fits the type of its context:")
|
|
| 7714 | + 2 (ppr (getCheckExpType res_ty))) ]
|
|
| 7719 | 7715 | |
| 7720 | 7716 | PatCtxt pat ->
|
| 7721 | 7717 | hang (text "In the pattern:") 2 (ppr pat)
|
| ... | ... | @@ -7777,7 +7773,7 @@ pprHsCtxt = \case |
| 7777 | 7773 | full_herald = pprExpectedFunTyHerald herald
|
| 7778 | 7774 | <+> speakNOf n_vis_args_in_call (text "visible argument")
|
| 7779 | 7775 | -- What are "visible" arguments? See Note [Visibility and arity] in GHC.Types.Basic
|
| 7780 | - FunResCtxt fun n_val_args res_fun res_env n_fun n_env
|
|
| 7776 | + FunResCtxt fun n_val_args fun_res_ty env_ty
|
|
| 7781 | 7777 | | -- Check for too few args
|
| 7782 | 7778 | -- fun_tau = a -> b, res_tau = Int
|
| 7783 | 7779 | n_fun > n_env
|
| ... | ... | @@ -7801,6 +7797,18 @@ pprHsCtxt = \case |
| 7801 | 7797 | -> empty
|
| 7802 | 7798 | -- text "Debug" <+> vcat [ppr fun, ppr n_val_args, ppr res_fun, ppr res_env, ppr n_fun, ppr n_env]
|
| 7803 | 7799 | where
|
| 7800 | + -- See Note [Splitting nested sigma types in mismatched
|
|
| 7801 | + -- function types]
|
|
| 7802 | + -- env_ty is an ExpRhoTy, but with simple subsumption it
|
|
| 7803 | + -- is not /deeply/ skolemised, so still use tcSplitNestedSigmaTys
|
|
| 7804 | + |
|
| 7805 | + (_,_,fun_tau) = tcSplitNestedSigmaTys fun_res_ty
|
|
| 7806 | + (_, _, env_tau) = tcSplitNestedSigmaTys (getCheckExpType env_ty)
|
|
| 7807 | + (args_fun, res_fun) = tcSplitFunTys fun_tau
|
|
| 7808 | + (args_env, res_env) = tcSplitFunTys env_tau
|
|
| 7809 | + n_fun = length args_fun
|
|
| 7810 | + n_env = length args_env
|
|
| 7811 | + |
|
| 7804 | 7812 | not_fun ty -- ty is definitely not an arrow type,
|
| 7805 | 7813 | -- and cannot conceivably become one
|
| 7806 | 7814 | = case tcSplitTyConApp_maybe ty of
|
| ... | ... | @@ -68,7 +68,6 @@ import GHC.Builtin.Names |
| 68 | 68 | import GHC.Driver.DynFlags
|
| 69 | 69 | import GHC.Utils.Misc
|
| 70 | 70 | import GHC.Utils.Outputable as Outputable
|
| 71 | -import GHC.Utils.Panic
|
|
| 72 | 71 | |
| 73 | 72 | import GHC.Data.Maybe
|
| 74 | 73 | |
| ... | ... | @@ -961,7 +960,8 @@ See Note [-fno-code mode]. |
| 961 | 960 | * *
|
| 962 | 961 | ********************************************************************* -}
|
| 963 | 962 | |
| 964 | -addFunResCtxt :: HsExpr GhcTc -> [HsExprArg p]
|
|
| 963 | +addFunResCtxt :: HasDebugCallStack
|
|
| 964 | + => HsExpr GhcTc -> [HsExprArg p]
|
|
| 965 | 965 | -> TcType -> ExpRhoType
|
| 966 | 966 | -> TcM a -> TcM a
|
| 967 | 967 | -- When we have a mis-match in the return type of a function
|
| ... | ... | @@ -969,33 +969,10 @@ addFunResCtxt :: HsExpr GhcTc -> [HsExprArg p] |
| 969 | 969 | -- But not in generated code, where we don't want
|
| 970 | 970 | -- to mention internal (rebindable syntax) function names
|
| 971 | 971 | addFunResCtxt fun args fun_res_ty env_ty thing_inside
|
| 972 | - = do { env_tv <- newFlexiTyVarTy liftedTypeKind
|
|
| 973 | - ; dumping <- doptM Opt_D_dump_tc_trace
|
|
| 974 | - ; msg <- mk_msg dumping env_tv
|
|
| 975 | - ; addErrCtxt msg thing_inside }
|
|
| 972 | + = addErrCtxt (FunResCtxt fun (count isValArg args) fun_res_ty env_ty) $
|
|
| 973 | + thing_inside
|
|
| 976 | 974 | -- NB: use a landmark error context, so that an empty context
|
| 977 | 975 | -- doesn't suppress some more useful context
|
| 978 | - where
|
|
| 979 | - mk_msg dumping env_tv
|
|
| 980 | - = do { mb_env_ty <- readExpType_maybe env_ty
|
|
| 981 | - -- by the time the message is rendered, the ExpType
|
|
| 982 | - -- will be filled in (except if we're debugging)
|
|
| 983 | - ; env' <- case mb_env_ty of
|
|
| 984 | - Just env_ty -> return env_ty
|
|
| 985 | - Nothing -> do { massert dumping; return env_tv }
|
|
| 986 | - ; let -- See Note [Splitting nested sigma types in mismatched
|
|
| 987 | - -- function types]
|
|
| 988 | - (_, _, fun_tau) = tcSplitNestedSigmaTys fun_res_ty
|
|
| 989 | - (_, _, env_tau) = tcSplitNestedSigmaTys env'
|
|
| 990 | - -- env_ty is an ExpRhoTy, but with simple subsumption it
|
|
| 991 | - -- is not deeply skolemised, so still use tcSplitNestedSigmaTys
|
|
| 992 | - (args_fun, res_fun) = tcSplitFunTys fun_tau
|
|
| 993 | - (args_env, res_env) = tcSplitFunTys env_tau
|
|
| 994 | - info =
|
|
| 995 | - FunResCtxt fun (count isValArg args) res_fun res_env
|
|
| 996 | - (length args_fun) (length args_env)
|
|
| 997 | - ; return info }
|
|
| 998 | - |
|
| 999 | 976 | |
| 1000 | 977 | {-
|
| 1001 | 978 | Note [Splitting nested sigma types in mismatched function types]
|
| ... | ... | @@ -251,7 +251,10 @@ data HsCtxt |
| 251 | 251 | -- | In the instance type signature of a class method.
|
| 252 | 252 | | MethSigCtxt !Name !TcType !TcType
|
| 253 | 253 | -- | In a pattern type signature.
|
| 254 | + |
|
| 254 | 255 | | PatSigErrCtxt !TcType !ExpType
|
| 256 | + -- ExpType: see Note [ExpType in HsCtxt]
|
|
| 257 | + |
|
| 255 | 258 | -- | In a pattern.
|
| 256 | 259 | | PatCtxt !(Pat GhcRn)
|
| 257 | 260 | -- | In a pattern synonym declaration.
|
| ... | ... | @@ -268,7 +271,10 @@ data HsCtxt |
| 268 | 271 | -- | In a function call.
|
| 269 | 272 | | FunTysCtxt !ExpectedFunTyCtxt !Type !Int !Int
|
| 270 | 273 | -- | In the result of a function call.
|
| 271 | - | FunResCtxt !(HsExpr GhcTc) !Int !Type !Type !Int !Int
|
|
| 274 | + |
|
| 275 | + | FunResCtxt !(HsExpr GhcTc) !Int !TcType !ExpType
|
|
| 276 | + -- ExpType: see Note [ExpType in HsCtxt]
|
|
| 277 | + |
|
| 272 | 278 | -- | In the declaration of a type constructor.
|
| 273 | 279 | | TyConDeclCtxt !Name !(TyConFlavour TyCon)
|
| 274 | 280 | -- | In a type or data family instance (or default instance).
|
| ... | ... | @@ -377,3 +383,14 @@ isHsCtxtLandmark (DerivBindCtxt{}) = True |
| 377 | 383 | isHsCtxtLandmark (FunResCtxt{}) = True
|
| 378 | 384 | isHsCtxtLandmark (VDQWarningCtxt{}) = True
|
| 379 | 385 | isHsCtxtLandmark _ = False
|
| 386 | + |
|
| 387 | +{- Note [ExpType in HsCtxt]
|
|
| 388 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 389 | +A couple of HsCtxt constructors have ExpTypes in them. When zonking the
|
|
| 390 | +Infer{} case we read the hole, which should be filled in by now, and zonk
|
|
| 391 | +that type. Now we want to put it back: we use (Check ty') for this, so that
|
|
| 392 | +clients of a zonked HsCtxt don't need to be monadic.
|
|
| 393 | + |
|
| 394 | +Result: after zonking, these ExpTypes are always (Check ty). It woudl be nice
|
|
| 395 | +to guarantee this statically, but it's hard to do so.
|
|
| 396 | +-} |
| ... | ... | @@ -28,7 +28,7 @@ module GHC.Tc.Utils.TcType ( |
| 28 | 28 | ExpType(..), ExpKind, InferResult(..), InferInstFlag(..), InferFRRFlag(..),
|
| 29 | 29 | ExpTypeFRR, ExpSigmaType, ExpSigmaTypeFRR,
|
| 30 | 30 | ExpRhoType, ExpRhoTypeFRR,
|
| 31 | - mkCheckExpType,
|
|
| 31 | + mkCheckExpType, getCheckExpType,
|
|
| 32 | 32 | checkingExpType_maybe, checkingExpType,
|
| 33 | 33 | |
| 34 | 34 | ExpPatType(..), mkCheckExpFunPatTy, mkInvisExpPatType,
|
| ... | ... | @@ -440,11 +440,12 @@ data InferInstFlag -- Specifies whether the inference should return an uninstan |
| 440 | 440 | |
| 441 | 441 | | IIF_ShallowRho -- Trying to infer a shallow RhoType (no foralls or => at the top)
|
| 442 | 442 | -- Top-instantiate (only, regardless of DeepSubsumption) before filling the hole
|
| 443 | - -- Typically used when inferring the type of an expression
|
|
| 443 | + -- Used only for view patterns; see Note [View patterns and polymorphism]
|
|
| 444 | 444 | |
| 445 | 445 | | IIF_DeepRho -- Trying to infer a possibly-deep RhoType (depending on DeepSubsumption)
|
| 446 | 446 | -- If DeepSubsumption is off, same as IIF_ShallowRho
|
| 447 | 447 | -- If DeepSubsumption is on, instantiate deeply before filling the hole
|
| 448 | + -- Typically used when inferring the type of an expression
|
|
| 448 | 449 | |
| 449 | 450 | type ExpSigmaType = ExpType
|
| 450 | 451 | type ExpRhoType = ExpType
|
| ... | ... | @@ -490,6 +491,12 @@ instance Outputable InferResult where |
| 490 | 491 | mkCheckExpType :: TcType -> ExpType
|
| 491 | 492 | mkCheckExpType = Check
|
| 492 | 493 | |
| 494 | +getCheckExpType :: HasDebugCallStack => ExpType -> TcType
|
|
| 495 | +-- Expect a (Check ty).
|
|
| 496 | +-- See Note [ExpType in HsCtxt] in GHC.Tc.Types.ErrCtxt
|
|
| 497 | +getCheckExpType (Check ty) = ty
|
|
| 498 | +getCheckExpType (Infer ir) = pprPanic "getCheckExpType" (ppr ir)
|
|
| 499 | + |
|
| 493 | 500 | -- | Returns the expected type when in checking mode.
|
| 494 | 501 | checkingExpType_maybe :: ExpType -> Maybe TcType
|
| 495 | 502 | checkingExpType_maybe (Check ty) = Just ty
|
| ... | ... | @@ -818,19 +818,26 @@ zonkTidyHsCtxt env e@(FunAppCtxt{}) = return (env, e) |
| 818 | 818 | zonkTidyHsCtxt env (FunTysCtxt ctxt ty i1 i2) = do
|
| 819 | 819 | (env', ty') <- zonkTidyTcType env ty
|
| 820 | 820 | return $ (env', FunTysCtxt ctxt ty' i1 i2)
|
| 821 | -zonkTidyHsCtxt env (FunResCtxt e i1 ty1 ty2 i2 i3) = do
|
|
| 822 | - (env', ty1') <- zonkTidyTcType env ty1
|
|
| 823 | - (env', ty2') <- zonkTidyTcType env' ty2
|
|
| 824 | - return $ (env', FunResCtxt e i1 ty1' ty2' i2 i3)
|
|
| 821 | +zonkTidyHsCtxt env (FunResCtxt e n ty1 env_ty) = do
|
|
| 822 | + (env', ty1') <- zonkTidyTcType env ty1
|
|
| 823 | + (env', env_ty') <- zonkExpType env' env_ty
|
|
| 824 | + return $ (env', FunResCtxt e n ty1' env_ty')
|
|
| 825 | 825 | zonkTidyHsCtxt env (PatSigErrCtxt sig_ty res_ty) = do
|
| 826 | 826 | (env', sig_ty') <- zonkTidyTcType env sig_ty
|
| 827 | - (env', res_ty') <-
|
|
| 828 | - case res_ty of
|
|
| 829 | - Check ty -> zonkTidyTcType env' ty
|
|
| 830 | - Infer (IR {ir_ref = ref}) -> do -- inlining readExpTyp_maybe to avoid module dep loops
|
|
| 831 | - mb_ty <- liftIO $ readIORef ref
|
|
| 832 | - case mb_ty of
|
|
| 833 | - Nothing -> error "zonkTidyHsCtxt PatSigErrCtxt"
|
|
| 834 | - Just ty -> zonkTidyTcType env' ty
|
|
| 835 | - return (env', PatSigErrCtxt sig_ty' (Check res_ty'))
|
|
| 827 | + (env', res_ty') <- zonkExpType env' res_ty
|
|
| 828 | + return (env', PatSigErrCtxt sig_ty' res_ty')
|
|
| 836 | 829 | zonkTidyHsCtxt env p = return (env, p)
|
| 830 | + |
|
| 831 | +zonkExpType :: TidyEnv -> ExpType -> ZonkM (TidyEnv, ExpType)
|
|
| 832 | +-- Zonk Infer{} to Check. The hole should have been filled in by now
|
|
| 833 | +zonkExpType env (Check ty)
|
|
| 834 | + = do { (env', ty') <- zonkTidyTcType env ty
|
|
| 835 | + ; return (env', Check ty') }
|
|
| 836 | +zonkExpType env (Infer ir@(IR { ir_ref = ref }))
|
|
| 837 | + = do { -- inlining readExpTyp_maybe to avoid module dep loops
|
|
| 838 | + ; mb_ty <- liftIO $ readIORef ref
|
|
| 839 | + ; case mb_ty of
|
|
| 840 | + Nothing -> pprPanic "zonkTidyHsCtxt PatSigErrCtxt" (ppr ir)
|
|
| 841 | + Just ty -> do { (env', ty') <- zonkTidyTcType env ty
|
|
| 842 | + ; return (env', Check ty') } }
|
|
| 843 | + |
| ... | ... | @@ -28,6 +28,7 @@ |
| 28 | 28 | * Hide implementation details when throwing exceptions in throw and throwSTM. ([CLC proposal #387](https://github.com/haskell/core-libraries-committee/issues/387))
|
| 29 | 29 | * Change `hIsReadable` and `hIsWritable` such that they always throw a respective exception when encountering a closed or semi-closed handle, not just in the case of a file handle. ([CLC proposal #371](github.com/haskell/core-libraries-committee/issues/371))
|
| 30 | 30 | * Annotate `onException` continuation with `WhileHandling`. ([CLC Proposal #397](https://github.com/haskell/core-libraries-committee/issues/397))
|
| 31 | + * Improve error message for `Data.Char.chr`. ([CLC Proposal #384](https://github.com/haskell/core-libraries-committee/issues/384))
|
|
| 31 | 32 | |
| 32 | 33 | ## 4.22.0.0 *TBA*
|
| 33 | 34 | * Shipped with GHC 9.14.1
|
| ... | ... | @@ -81,7 +81,7 @@ Testing Enum Char: |
| 81 | 81 | pred (maxBound::Char) = '\1114110'
|
| 82 | 82 | pred (minBound::Char) = error "Prelude.Enum.Char.pred: bad argument"
|
| 83 | 83 | (map (toEnum::Int->Char) [123,ord (minBound::Char), ord(maxBound::Char)]) = "{\NUL\1114111"
|
| 84 | - (toEnum::Int->Char) (minBound::Int) = error "Prelude.chr: bad argument: (-2147483648)"
|
|
| 84 | + (toEnum::Int->Char) (minBound::Int) = error "Data.Char.chr: argument outside Unicode range: 0..1114111: (-2147483648)"
|
|
| 85 | 85 | (map fromEnum ['X',minBound,maxBound]) = [88,0,1114111]
|
| 86 | 86 | (take 7 ['\NUL' .. ]) = "\NUL\SOH\STX\ETX\EOT\ENQ\ACK"
|
| 87 | 87 | (take 7 ['\250' .. ]) = "\250\251\252\253\254\255\256"
|
| ... | ... | @@ -65,7 +65,7 @@ Testing Enum Char: |
| 65 | 65 | pred (maxBound::Char) = '\1114110'
|
| 66 | 66 | pred (minBound::Char) = error "Prelude.Enum.Char.pred: bad argument"
|
| 67 | 67 | (map (toEnum::Int->Char) [123,ord (minBound::Char), ord(maxBound::Char)]) = "{\NUL\1114111"
|
| 68 | - (toEnum::Int->Char) (minBound::Int) = error "Prelude.chr: bad argument"
|
|
| 68 | + (toEnum::Int->Char) (minBound::Int) = error "Data.Char.chr: argument outside Unicode range: 0..1114111:"
|
|
| 69 | 69 | (map fromEnum ['X',minBound,maxBound]) = [88,0,1114111]
|
| 70 | 70 | (take 7 ['\NUL' .. ]) = "\NUL\SOH\STX\ETX\EOT\ENQ\ACK"
|
| 71 | 71 | (take 7 ['\250' .. ]) = "\250\251\252\253\254\255\256"
|
| ... | ... | @@ -81,7 +81,7 @@ Testing Enum Char: |
| 81 | 81 | pred (maxBound::Char) = '\1114110'
|
| 82 | 82 | pred (minBound::Char) = error "Prelude.Enum.Char.pred: bad argument"
|
| 83 | 83 | (map (toEnum::Int->Char) [123,ord (minBound::Char), ord(maxBound::Char)]) = "{\NUL\1114111"
|
| 84 | - (toEnum::Int->Char) (minBound::Int) = error "Prelude.chr: bad argument: (-9223372036854775808)"
|
|
| 84 | + (toEnum::Int->Char) (minBound::Int) = error "Data.Char.chr: argument outside Unicode range: 0..1114111: (-9223372036854775808)"
|
|
| 85 | 85 | (map fromEnum ['X',minBound,maxBound]) = [88,0,1114111]
|
| 86 | 86 | (take 7 ['\NUL' .. ]) = "\NUL\SOH\STX\ETX\EOT\ENQ\ACK"
|
| 87 | 87 | (take 7 ['\250' .. ]) = "\250\251\252\253\254\255\256"
|
| ... | ... | @@ -12,7 +12,7 @@ module GHC.Internal.Char |
| 12 | 12 | |
| 13 | 13 | import GHC.Internal.Classes (eqChar, neChar)
|
| 14 | 14 | import GHC.Internal.Base (otherwise, (++))
|
| 15 | -import GHC.Internal.Err (errorWithoutStackTrace)
|
|
| 15 | +import GHC.Internal.Err (error)
|
|
| 16 | 16 | import GHC.Internal.Show
|
| 17 | 17 | import GHC.Internal.Prim (chr#, int2Word#, leWord#, Int#, Char#)
|
| 18 | 18 | import GHC.Internal.Types (Char(..), Int(..), isTrue#)
|
| ... | ... | @@ -29,4 +29,7 @@ safe_chr# i# |
| 29 | 29 | |
| 30 | 30 | {-# NOINLINE chr_error #-}
|
| 31 | 31 | chr_error :: Int# -> Char#
|
| 32 | -chr_error i# = errorWithoutStackTrace ("Prelude.chr: bad argument: " ++ showSignedInt (I# 9#) (I# i#) "") |
|
| 32 | +chr_error i# = error ("Data.Char.chr: argument outside Unicode range: 0..1114111: " ++ showSignedInt (I# 9#) (I# i#) "")
|
|
| 33 | +-- It's not really "Data.Char", but we assume that
|
|
| 34 | +-- the majority of users will import it from "base:Data.Char"
|
|
| 35 | +-- and not from "ghc-internal:GHC.Internal.Char". |
| ... | ... | @@ -86,9 +86,9 @@ data Message a where |
| 86 | 86 | |
| 87 | 87 | -- These all invoke the corresponding functions in the RTS Linker API.
|
| 88 | 88 | InitLinker :: Message ()
|
| 89 | - LookupSymbol :: String -> Message (Maybe (RemotePtr ()))
|
|
| 90 | - LookupSymbolInDLL :: RemotePtr LoadedDLL -> String -> Message (Maybe (RemotePtr ()))
|
|
| 91 | - LookupClosure :: String -> Message (Maybe HValueRef)
|
|
| 89 | + LookupSymbol :: !BS.ShortByteString -> Message (Maybe (RemotePtr ()))
|
|
| 90 | + LookupSymbolInDLL :: !(RemotePtr LoadedDLL) -> !BS.ShortByteString -> Message (Maybe (RemotePtr ()))
|
|
| 91 | + LookupClosure :: !BS.ShortByteString -> Message (Maybe HValueRef)
|
|
| 92 | 92 | LoadDLLs :: [String] -> Message (Either String [RemotePtr LoadedDLL])
|
| 93 | 93 | LoadArchive :: String -> Message () -- error?
|
| 94 | 94 | LoadObj :: String -> Message () -- error?
|
| ... | ... | @@ -162,8 +162,8 @@ data Message a where |
| 162 | 162 | |
| 163 | 163 | -- | Create a set of CostCentres with the same module name
|
| 164 | 164 | MkCostCentres
|
| 165 | - :: String -- module, RemotePtr so it can be shared
|
|
| 166 | - -> [(String,String)] -- (name, SrcSpan)
|
|
| 165 | + :: !(RemotePtr ()) -- ModuleName
|
|
| 166 | + -> ![(BS.ShortByteString, BS.ShortByteString)] -- (name, SrcSpan)
|
|
| 167 | 167 | -> Message [RemotePtr CostCentre]
|
| 168 | 168 | |
| 169 | 169 | -- | Show a 'CostCentreStack' as a @[String]@
|
| ... | ... | @@ -430,7 +430,7 @@ data EvalStatus_ a b |
| 430 | 430 | instance Binary a => Binary (EvalStatus_ a b)
|
| 431 | 431 | |
| 432 | 432 | data EvalBreakpoint = EvalBreakpoint
|
| 433 | - { eb_info_mod :: String -- ^ Breakpoint info module
|
|
| 433 | + { eb_info_mod :: !BS.ShortByteString -- ^ Breakpoint info module
|
|
| 434 | 434 | , eb_info_mod_unit :: BS.ShortByteString -- ^ Breakpoint tick module unit id
|
| 435 | 435 | , eb_info_index :: Int -- ^ Breakpoint info index
|
| 436 | 436 | }
|
| ... | ... | @@ -31,6 +31,8 @@ import GHCi.RemoteTypes |
| 31 | 31 | import GHCi.Message (LoadedDLL)
|
| 32 | 32 | import Control.Exception (throwIO, ErrorCall(..))
|
| 33 | 33 | import Control.Monad ( when )
|
| 34 | +import qualified Data.ByteString.Short as BS
|
|
| 35 | +import Data.Char (ord)
|
|
| 34 | 36 | import Data.Foldable
|
| 35 | 37 | import Foreign.C
|
| 36 | 38 | import Foreign.Marshal.Alloc ( alloca, free )
|
| ... | ... | @@ -104,15 +106,15 @@ unloadObj f = throwIO $ ErrorCall $ "unloadObj: unsupported on wasm for " <> f |
| 104 | 106 | purgeObj :: String -> IO ()
|
| 105 | 107 | purgeObj f = throwIO $ ErrorCall $ "purgeObj: unsupported on wasm for " <> f
|
| 106 | 108 | |
| 107 | -lookupSymbol :: String -> IO (Maybe (Ptr a))
|
|
| 108 | -lookupSymbol sym = do
|
|
| 109 | - r <- js_lookupSymbol $ toJSString sym
|
|
| 109 | +lookupSymbol :: BS.ShortByteString -> IO (Maybe (Ptr a))
|
|
| 110 | +lookupSymbol sym@(BS.SBS ba#) = do
|
|
| 111 | + r <- js_lookupSymbolPtr ba# (BS.length sym)
|
|
| 110 | 112 | evaluate $ if r == nullPtr then Nothing else Just r
|
| 111 | 113 | |
| 112 | -foreign import javascript unsafe "__ghc_wasm_jsffi_dyld.lookupSymbol($1)"
|
|
| 113 | - js_lookupSymbol :: JSString -> IO (Ptr a)
|
|
| 114 | +foreign import javascript unsafe "__ghc_wasm_jsffi_dyld.lookupSymbolPtr($1,$2)"
|
|
| 115 | + js_lookupSymbolPtr :: ByteArray# -> Int -> IO (Ptr a)
|
|
| 114 | 116 | |
| 115 | -lookupSymbolInDLL :: Ptr LoadedDLL -> String -> IO (Maybe (Ptr a))
|
|
| 117 | +lookupSymbolInDLL :: Ptr LoadedDLL -> BS.ShortByteString -> IO (Maybe (Ptr a))
|
|
| 116 | 118 | lookupSymbolInDLL _ _ = pure Nothing
|
| 117 | 119 | |
| 118 | 120 | resolveObjs :: IO Bool
|
| ... | ... | @@ -149,27 +151,27 @@ initObjLinker :: ShouldRetainCAFs -> IO () |
| 149 | 151 | initObjLinker RetainCAFs = c_initLinker_ 1
|
| 150 | 152 | initObjLinker _ = c_initLinker_ 0
|
| 151 | 153 | |
| 152 | -lookupSymbol :: String -> IO (Maybe (Ptr a))
|
|
| 154 | +lookupSymbol :: BS.ShortByteString -> IO (Maybe (Ptr a))
|
|
| 153 | 155 | lookupSymbol str_in = do
|
| 154 | 156 | let str = prefixUnderscore str_in
|
| 155 | - withCAString str $ \c_str -> do
|
|
| 157 | + BS.useAsCString str $ \c_str -> do
|
|
| 156 | 158 | addr <- c_lookupSymbol c_str
|
| 157 | 159 | if addr == nullPtr
|
| 158 | 160 | then return Nothing
|
| 159 | 161 | else return (Just addr)
|
| 160 | 162 | |
| 161 | -lookupSymbolInDLL :: Ptr LoadedDLL -> String -> IO (Maybe (Ptr a))
|
|
| 163 | +lookupSymbolInDLL :: Ptr LoadedDLL -> BS.ShortByteString -> IO (Maybe (Ptr a))
|
|
| 162 | 164 | lookupSymbolInDLL dll str_in = do
|
| 163 | 165 | let str = prefixUnderscore str_in
|
| 164 | - withCAString str $ \c_str -> do
|
|
| 166 | + BS.useAsCString str $ \c_str -> do
|
|
| 165 | 167 | addr <- c_lookupSymbolInNativeObj dll c_str
|
| 166 | 168 | if addr == nullPtr
|
| 167 | 169 | then return Nothing
|
| 168 | 170 | else return (Just addr)
|
| 169 | 171 | |
| 170 | -prefixUnderscore :: String -> String
|
|
| 172 | +prefixUnderscore :: BS.ShortByteString -> BS.ShortByteString
|
|
| 171 | 173 | prefixUnderscore
|
| 172 | - | cLeadingUnderscore = ('_':)
|
|
| 174 | + | cLeadingUnderscore = BS.cons (fromIntegral (ord '_'))
|
|
| 173 | 175 | | otherwise = id
|
| 174 | 176 | |
| 175 | 177 | -- | loadDLL loads a dynamic library using the OS's native linker
|
| ... | ... | @@ -298,7 +300,7 @@ isWindowsHost = False |
| 298 | 300 | |
| 299 | 301 | #endif
|
| 300 | 302 | |
| 301 | -lookupClosure :: String -> IO (Maybe HValueRef)
|
|
| 303 | +lookupClosure :: BS.ShortByteString -> IO (Maybe HValueRef)
|
|
| 302 | 304 | lookupClosure str = do
|
| 303 | 305 | m <- lookupSymbol str
|
| 304 | 306 | case m of
|
| ... | ... | @@ -34,7 +34,7 @@ import Control.DeepSeq |
| 34 | 34 | import Control.Exception
|
| 35 | 35 | import Control.Monad
|
| 36 | 36 | import Data.ByteString (ByteString)
|
| 37 | -import qualified Data.ByteString.Short as BS
|
|
| 37 | +import qualified Data.ByteString.Short.Internal as BS
|
|
| 38 | 38 | import qualified Data.ByteString.Unsafe as B
|
| 39 | 39 | import GHC.Exts
|
| 40 | 40 | import qualified GHC.Exts.Heap as Heap
|
| ... | ... | @@ -135,12 +135,12 @@ foreign import javascript "((ptr,off) => globalThis.h$loadJS(h$decodeUtf8z(ptr,o |
| 135 | 135 | |
| 136 | 136 | foreign import javascript "((ptr,off) => globalThis.h$lookupClosure(h$decodeUtf8z(ptr,off)))" lookupJSClosure# :: CString -> State# RealWorld -> (# State# RealWorld, Int# #)
|
| 137 | 137 | |
| 138 | -lookupJSClosure' :: String -> IO Int
|
|
| 139 | -lookupJSClosure' str = withCString str $ \cstr -> IO (\s ->
|
|
| 138 | +lookupJSClosure' :: BS.ShortByteString -> IO Int
|
|
| 139 | +lookupJSClosure' str = BS.useAsCString str $ \cstr -> IO (\s ->
|
|
| 140 | 140 | case lookupJSClosure# cstr s of
|
| 141 | 141 | (# s', r #) -> (# s', I# r #))
|
| 142 | 142 | |
| 143 | -lookupJSClosure :: String -> IO (Maybe HValueRef)
|
|
| 143 | +lookupJSClosure :: BS.ShortByteString -> IO (Maybe HValueRef)
|
|
| 144 | 144 | lookupJSClosure str = lookupJSClosure' str >>= \case
|
| 145 | 145 | 0 -> pure Nothing
|
| 146 | 146 | r -> pure (Just (RemoteRef (RemotePtr (fromIntegral r))))
|
| ... | ... | @@ -359,7 +359,7 @@ withBreakAction opts breakMVar statusMVar mtid act |
| 359 | 359 | if is_exception
|
| 360 | 360 | then pure Nothing
|
| 361 | 361 | else do
|
| 362 | - info_mod <- peekCString (Ptr info_mod#)
|
|
| 362 | + info_mod <- BS.packCString (Ptr info_mod#)
|
|
| 363 | 363 | info_mod_uid <- BS.packCString (Ptr info_mod_uid#)
|
| 364 | 364 | pure (Just (EvalBreakpoint info_mod info_mod_uid (I# infox#)))
|
| 365 | 365 | putMVar statusMVar $ EvalBreak apStack_r breakpoint resume_r ccs
|
| ... | ... | @@ -434,17 +434,24 @@ mkString0 bs = B.unsafeUseAsCStringLen bs $ \(cstr,len) -> do |
| 434 | 434 | pokeElemOff (ptr :: Ptr CChar) len 0
|
| 435 | 435 | return (castRemotePtr (toRemotePtr ptr))
|
| 436 | 436 | |
| 437 | -mkCostCentres :: String -> [(String,String)] -> IO [RemotePtr CostCentre]
|
|
| 437 | +mkCostCentres :: RemotePtr () -> [(BS.ShortByteString, BS.ShortByteString)] -> IO [RemotePtr CostCentre]
|
|
| 438 | 438 | #if defined(PROFILING)
|
| 439 | 439 | mkCostCentres mod ccs = do
|
| 440 | - c_module <- newCString mod
|
|
| 440 | + let c_module = fromRemotePtr $ castRemotePtr mod
|
|
| 441 | 441 | mapM (mk_one c_module) ccs
|
| 442 | 442 | where
|
| 443 | 443 | mk_one c_module (decl_path,srcspan) = do
|
| 444 | - c_name <- newCString decl_path
|
|
| 445 | - c_srcspan <- newCString srcspan
|
|
| 444 | + c_name <- newCStringFromSBS decl_path
|
|
| 445 | + c_srcspan <- newCStringFromSBS srcspan
|
|
| 446 | 446 | toRemotePtr <$> c_mkCostCentre c_name c_module c_srcspan
|
| 447 | 447 | |
| 448 | + newCStringFromSBS sbs = do
|
|
| 449 | + let len = BS.length sbs
|
|
| 450 | + buf <- mallocBytes $ len + 1
|
|
| 451 | + BS.copyToPtr sbs 0 buf (fromIntegral len)
|
|
| 452 | + pokeByteOff buf len (0 :: Word8)
|
|
| 453 | + pure buf
|
|
| 454 | + |
|
| 448 | 455 | foreign import ccall unsafe "mkCostCentre"
|
| 449 | 456 | c_mkCostCentre :: Ptr CChar -> Ptr CChar -> Ptr CChar -> IO (Ptr CostCentre)
|
| 450 | 457 | #else
|
| 1 | +{-# LANGUAGE OverloadedStrings #-}
|
|
| 1 | 2 | {-# LANGUAGE RecordWildCards #-}
|
| 2 | 3 | |
| 3 | 4 | module Main (main) where
|
| 4 | 5 | |
| 5 | 6 | import Control.Exception
|
| 6 | 7 | import Control.Monad
|
| 8 | +import Data.ByteString.Short (ShortByteString)
|
|
| 7 | 9 | |
| 8 | 10 | import Foreign
|
| 9 | 11 | |
| ... | ... | @@ -15,7 +17,7 @@ import GHCi.ObjLink |
| 15 | 17 | |
| 16 | 18 | rotateSO
|
| 17 | 19 | :: (FunPtr (IO (StablePtr a)) -> (IO (StablePtr a)))
|
| 18 | - -> String
|
|
| 20 | + -> ShortByteString
|
|
| 19 | 21 | -> (Maybe FilePath, FilePath)
|
| 20 | 22 | -> IO a
|
| 21 | 23 | rotateSO dynamicCall symName (old, newDLL) = do
|
| 1 | +:set -XOverloadedStrings
|
|
| 1 | 2 | import GHCi.ObjLink
|
| 2 | 3 | lookupClosure "blah" |
| 1 | +{-# LANGUAGE OverloadedStrings #-}
|
|
| 2 | + |
|
| 1 | 3 | module Main (main) where
|
| 2 | 4 | |
| 3 | 5 | import Foreign
|
| ... | ... | @@ -1334,6 +1334,13 @@ class DyLD { |
| 1334 | 1334 | }
|
| 1335 | 1335 | return 0;
|
| 1336 | 1336 | }
|
| 1337 | + |
|
| 1338 | + lookupSymbolPtr(symPtr, symLen) {
|
|
| 1339 | + const sym = new TextDecoder("utf-8", { fatal: true }).decode(
|
|
| 1340 | + new Uint8Array(this.#memory.buffer, symPtr, symLen)
|
|
| 1341 | + );
|
|
| 1342 | + return this.lookupSymbol(sym);
|
|
| 1343 | + }
|
|
| 1337 | 1344 | }
|
| 1338 | 1345 | |
| 1339 | 1346 | // The main entry point of dyld that may be run on node/browser, and
|