summaryrefslogtreecommitdiff
path: root/compiler/GHC/Runtime
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/Runtime')
-rw-r--r--compiler/GHC/Runtime/Context.hs389
-rw-r--r--compiler/GHC/Runtime/Debugger.hs31
-rw-r--r--compiler/GHC/Runtime/Eval.hs68
-rw-r--r--compiler/GHC/Runtime/Eval/Types.hs2
-rw-r--r--compiler/GHC/Runtime/Heap/Inspect.hs2
-rw-r--r--compiler/GHC/Runtime/Interpreter.hs32
-rw-r--r--compiler/GHC/Runtime/Linker.hs61
-rw-r--r--compiler/GHC/Runtime/Linker/Types.hs71
-rw-r--r--compiler/GHC/Runtime/Loader.hs29
9 files changed, 584 insertions, 101 deletions
diff --git a/compiler/GHC/Runtime/Context.hs b/compiler/GHC/Runtime/Context.hs
new file mode 100644
index 0000000000..7220dea503
--- /dev/null
+++ b/compiler/GHC/Runtime/Context.hs
@@ -0,0 +1,389 @@
+module GHC.Runtime.Context
+ ( InteractiveContext (..)
+ , InteractiveImport (..)
+ , emptyInteractiveContext
+ , extendInteractiveContext
+ , extendInteractiveContextWithIds
+ , setInteractivePrintName
+ , substInteractiveContext
+ , icExtendGblRdrEnv
+ , icInteractiveModule
+ , icInScopeTTs
+ , icPrintUnqual
+ )
+where
+
+import GHC.Prelude
+
+import GHC.Hs
+
+import GHC.Driver.Session
+
+import GHC.Runtime.Eval.Types ( Resume )
+
+import GHC.Unit
+
+import GHC.Core.FamInstEnv
+import GHC.Core.InstEnv ( ClsInst, identicalClsInstHead )
+import GHC.Core.Type
+
+import GHC.Types.Avail
+import GHC.Types.Fixity.Env
+import GHC.Types.Id.Info ( IdDetails(..) )
+import GHC.Types.Name
+import GHC.Types.Name.Env
+import GHC.Types.Name.Reader
+import GHC.Types.Name.Ppr
+import GHC.Types.TyThing
+import GHC.Types.Var
+
+import GHC.Builtin.Names ( ioTyConName, printName, mkInteractiveModule )
+
+import GHC.Utils.Outputable
+import GHC.Utils.Misc
+
+{-
+Note [The interactive package]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Type, class, and value declarations at the command prompt are treated
+as if they were defined in modules
+ interactive:Ghci1
+ interactive:Ghci2
+ ...etc...
+with each bunch of declarations using a new module, all sharing a
+common package 'interactive' (see Module.interactiveUnitId, and
+GHC.Builtin.Names.mkInteractiveModule).
+
+This scheme deals well with shadowing. For example:
+
+ ghci> data T = A
+ ghci> data T = B
+ ghci> :i A
+ data Ghci1.T = A -- Defined at <interactive>:2:10
+
+Here we must display info about constructor A, but its type T has been
+shadowed by the second declaration. But it has a respectable
+qualified name (Ghci1.T), and its source location says where it was
+defined.
+
+So the main invariant continues to hold, that in any session an
+original name M.T only refers to one unique thing. (In a previous
+iteration both the T's above were called :Interactive.T, albeit with
+different uniques, which gave rise to all sorts of trouble.)
+
+The details are a bit tricky though:
+
+ * The field ic_mod_index counts which Ghci module we've got up to.
+ It is incremented when extending ic_tythings
+
+ * ic_tythings contains only things from the 'interactive' package.
+
+ * Module from the 'interactive' package (Ghci1, Ghci2 etc) never go
+ in the Home Package Table (HPT). When you say :load, that's when we
+ extend the HPT.
+
+ * The 'homeUnitId' field of DynFlags is *not* set to 'interactive'.
+ It stays as 'main' (or whatever -this-unit-id says), and is the
+ package to which :load'ed modules are added to.
+
+ * So how do we arrange that declarations at the command prompt get to
+ be in the 'interactive' package? Simply by setting the tcg_mod
+ field of the TcGblEnv to "interactive:Ghci1". This is done by the
+ call to initTc in initTcInteractive, which in turn get the module
+ from it 'icInteractiveModule' field of the interactive context.
+
+ The 'homeUnitId' field stays as 'main' (or whatever -this-unit-id says.
+
+ * The main trickiness is that the type environment (tcg_type_env) and
+ fixity envt (tcg_fix_env), now contain entities from all the
+ interactive-package modules (Ghci1, Ghci2, ...) together, rather
+ than just a single module as is usually the case. So you can't use
+ "nameIsLocalOrFrom" to decide whether to look in the TcGblEnv vs
+ the HPT/PTE. This is a change, but not a problem provided you
+ know.
+
+* However, the tcg_binds, tcg_sigs, tcg_insts, tcg_fam_insts, etc fields
+ of the TcGblEnv, which collect "things defined in this module", all
+ refer to stuff define in a single GHCi command, *not* all the commands
+ so far.
+
+ In contrast, tcg_inst_env, tcg_fam_inst_env, have instances from
+ all GhciN modules, which makes sense -- they are all "home package"
+ modules.
+
+
+Note [Interactively-bound Ids in GHCi]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The Ids bound by previous Stmts in GHCi are currently
+ a) GlobalIds, with
+ b) An External Name, like Ghci4.foo
+ See Note [The interactive package] above
+ c) A tidied type
+
+ (a) They must be GlobalIds (not LocalIds) otherwise when we come to
+ compile an expression using these ids later, the byte code
+ generator will consider the occurrences to be free rather than
+ global.
+
+ (b) Having an External Name is important because of Note
+ [GlobalRdrEnv shadowing] in GHC.Types.Names.RdrName
+
+ (c) Their types are tidied. This is important, because :info may ask
+ to look at them, and :info expects the things it looks up to have
+ tidy types
+
+Where do interactively-bound Ids come from?
+
+ - GHCi REPL Stmts e.g.
+ ghci> let foo x = x+1
+ These start with an Internal Name because a Stmt is a local
+ construct, so the renamer naturally builds an Internal name for
+ each of its binders. Then in tcRnStmt they are externalised via
+ GHC.Tc.Module.externaliseAndTidyId, so they get Names like Ghic4.foo.
+
+ - Ids bound by the debugger etc have Names constructed by
+ GHC.Iface.Env.newInteractiveBinder; at the call sites it is followed by
+ mkVanillaGlobal or mkVanillaGlobalWithInfo. So again, they are
+ all Global, External.
+
+ - TyCons, Classes, and Ids bound by other top-level declarations in
+ GHCi (eg foreign import, record selectors) also get External
+ Names, with Ghci9 (or 8, or 7, etc) as the module name.
+
+
+Note [ic_tythings]
+~~~~~~~~~~~~~~~~~~
+The ic_tythings field contains
+ * The TyThings declared by the user at the command prompt
+ (eg Ids, TyCons, Classes)
+
+ * The user-visible Ids that arise from such things, which
+ *don't* come from 'implicitTyThings', notably:
+ - record selectors
+ - class ops
+ The implicitTyThings are readily obtained from the TyThings
+ but record selectors etc are not
+
+It does *not* contain
+ * DFunIds (they can be gotten from ic_instances)
+ * CoAxioms (ditto)
+
+See also Note [Interactively-bound Ids in GHCi]
+
+Note [Override identical instances in GHCi]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+If you declare a new instance in GHCi that is identical to a previous one,
+we simply override the previous one; we don't regard it as overlapping.
+e.g. Prelude> data T = A | B
+ Prelude> instance Eq T where ...
+ Prelude> instance Eq T where ... -- This one overrides
+
+It's exactly the same for type-family instances. See #7102
+-}
+
+-- | Interactive context, recording information about the state of the
+-- context in which statements are executed in a GHCi session.
+data InteractiveContext
+ = InteractiveContext {
+ ic_dflags :: DynFlags,
+ -- ^ The 'DynFlags' used to evaluate interactive expressions
+ -- and statements.
+
+ ic_mod_index :: Int,
+ -- ^ Each GHCi stmt or declaration brings some new things into
+ -- scope. We give them names like interactive:Ghci9.T,
+ -- where the ic_index is the '9'. The ic_mod_index is
+ -- incremented whenever we add something to ic_tythings
+ -- See Note [The interactive package]
+
+ ic_imports :: [InteractiveImport],
+ -- ^ The GHCi top-level scope (ic_rn_gbl_env) is extended with
+ -- these imports
+ --
+ -- This field is only stored here so that the client
+ -- can retrieve it with GHC.getContext. GHC itself doesn't
+ -- use it, but does reset it to empty sometimes (such
+ -- as before a GHC.load). The context is set with GHC.setContext.
+
+ ic_tythings :: [TyThing],
+ -- ^ TyThings defined by the user, in reverse order of
+ -- definition (ie most recent at the front)
+ -- See Note [ic_tythings]
+
+ ic_rn_gbl_env :: GlobalRdrEnv,
+ -- ^ The cached 'GlobalRdrEnv', built by
+ -- 'GHC.Runtime.Eval.setContext' and updated regularly
+ -- It contains everything in scope at the command line,
+ -- including everything in ic_tythings
+
+ ic_instances :: ([ClsInst], [FamInst]),
+ -- ^ All instances and family instances created during
+ -- this session. These are grabbed en masse after each
+ -- update to be sure that proper overlapping is retained.
+ -- That is, rather than re-check the overlapping each
+ -- time we update the context, we just take the results
+ -- from the instance code that already does that.
+
+ ic_fix_env :: FixityEnv,
+ -- ^ Fixities declared in let statements
+
+ ic_default :: Maybe [Type],
+ -- ^ The current default types, set by a 'default' declaration
+
+ ic_resume :: [Resume],
+ -- ^ The stack of breakpoint contexts
+
+ ic_monad :: Name,
+ -- ^ The monad that GHCi is executing in
+
+ ic_int_print :: Name,
+ -- ^ The function that is used for printing results
+ -- of expressions in ghci and -e mode.
+
+ ic_cwd :: Maybe FilePath
+ -- virtual CWD of the program
+ }
+
+data InteractiveImport
+ = IIDecl (ImportDecl GhcPs)
+ -- ^ Bring the exports of a particular module
+ -- (filtered by an import decl) into scope
+
+ | IIModule ModuleName
+ -- ^ Bring into scope the entire top-level envt of
+ -- of this module, including the things imported
+ -- into it.
+
+
+-- | Constructs an empty InteractiveContext.
+emptyInteractiveContext :: DynFlags -> InteractiveContext
+emptyInteractiveContext dflags
+ = InteractiveContext {
+ ic_dflags = dflags,
+ ic_imports = [],
+ ic_rn_gbl_env = emptyGlobalRdrEnv,
+ ic_mod_index = 1,
+ ic_tythings = [],
+ ic_instances = ([],[]),
+ ic_fix_env = emptyNameEnv,
+ ic_monad = ioTyConName, -- IO monad by default
+ ic_int_print = printName, -- System.IO.print by default
+ ic_default = Nothing,
+ ic_resume = [],
+ ic_cwd = Nothing }
+
+icInteractiveModule :: InteractiveContext -> Module
+icInteractiveModule (InteractiveContext { ic_mod_index = index })
+ = mkInteractiveModule index
+
+-- | This function returns the list of visible TyThings (useful for
+-- e.g. showBindings)
+icInScopeTTs :: InteractiveContext -> [TyThing]
+icInScopeTTs = ic_tythings
+
+-- | Get the PrintUnqualified function based on the flags and this InteractiveContext
+icPrintUnqual :: UnitState -> HomeUnit -> InteractiveContext -> PrintUnqualified
+icPrintUnqual unit_state home_unit InteractiveContext{ ic_rn_gbl_env = grenv } =
+ mkPrintUnqualified unit_state home_unit grenv
+
+-- | extendInteractiveContext is called with new TyThings recently defined to update the
+-- InteractiveContext to include them. Ids are easily removed when shadowed,
+-- but Classes and TyCons are not. Some work could be done to determine
+-- whether they are entirely shadowed, but as you could still have references
+-- to them (e.g. instances for classes or values of the type for TyCons), it's
+-- not clear whether removing them is even the appropriate behavior.
+extendInteractiveContext :: InteractiveContext
+ -> [TyThing]
+ -> [ClsInst] -> [FamInst]
+ -> Maybe [Type]
+ -> FixityEnv
+ -> InteractiveContext
+extendInteractiveContext ictxt new_tythings new_cls_insts new_fam_insts defaults fix_env
+ = ictxt { ic_mod_index = ic_mod_index ictxt + 1
+ -- Always bump this; even instances should create
+ -- a new mod_index (#9426)
+ , ic_tythings = new_tythings ++ old_tythings
+ , ic_rn_gbl_env = ic_rn_gbl_env ictxt `icExtendGblRdrEnv` new_tythings
+ , ic_instances = ( new_cls_insts ++ old_cls_insts
+ , new_fam_insts ++ fam_insts )
+ -- we don't shadow old family instances (#7102),
+ -- so don't need to remove them here
+ , ic_default = defaults
+ , ic_fix_env = fix_env -- See Note [Fixity declarations in GHCi]
+ }
+ where
+ new_ids = [id | AnId id <- new_tythings]
+ old_tythings = filterOut (shadowed_by new_ids) (ic_tythings ictxt)
+
+ -- Discard old instances that have been fully overridden
+ -- See Note [Override identical instances in GHCi]
+ (cls_insts, fam_insts) = ic_instances ictxt
+ old_cls_insts = filterOut (\i -> any (identicalClsInstHead i) new_cls_insts) cls_insts
+
+extendInteractiveContextWithIds :: InteractiveContext -> [Id] -> InteractiveContext
+-- Just a specialised version
+extendInteractiveContextWithIds ictxt new_ids
+ | null new_ids = ictxt
+ | otherwise = ictxt { ic_mod_index = ic_mod_index ictxt + 1
+ , ic_tythings = new_tythings ++ old_tythings
+ , ic_rn_gbl_env = ic_rn_gbl_env ictxt `icExtendGblRdrEnv` new_tythings }
+ where
+ new_tythings = map AnId new_ids
+ old_tythings = filterOut (shadowed_by new_ids) (ic_tythings ictxt)
+
+shadowed_by :: [Id] -> TyThing -> Bool
+shadowed_by ids = shadowed
+ where
+ shadowed id = getOccName id `elemOccSet` new_occs
+ new_occs = mkOccSet (map getOccName ids)
+
+setInteractivePrintName :: InteractiveContext -> Name -> InteractiveContext
+setInteractivePrintName ic n = ic{ic_int_print = n}
+
+ -- ToDo: should not add Ids to the gbl env here
+
+-- | Add TyThings to the GlobalRdrEnv, earlier ones in the list shadowing
+-- later ones, and shadowing existing entries in the GlobalRdrEnv.
+icExtendGblRdrEnv :: GlobalRdrEnv -> [TyThing] -> GlobalRdrEnv
+icExtendGblRdrEnv env tythings
+ = foldr add env tythings -- Foldr makes things in the front of
+ -- the list shadow things at the back
+ where
+ -- One at a time, to ensure each shadows the previous ones
+ add thing env
+ | is_sub_bndr thing
+ = env
+ | otherwise
+ = foldl' extendGlobalRdrEnv env1 (concatMap localGREsFromAvail avail)
+ where
+ env1 = shadowNames env (concatMap availNames avail)
+ avail = tyThingAvailInfo thing
+
+ -- Ugh! The new_tythings may include record selectors, since they
+ -- are not implicit-ids, and must appear in the TypeEnv. But they
+ -- will also be brought into scope by the corresponding (ATyCon
+ -- tc). And we want the latter, because that has the correct
+ -- parent (#10520)
+ is_sub_bndr (AnId f) = case idDetails f of
+ RecSelId {} -> True
+ ClassOpId {} -> True
+ _ -> False
+ is_sub_bndr _ = False
+
+substInteractiveContext :: InteractiveContext -> TCvSubst -> InteractiveContext
+substInteractiveContext ictxt@InteractiveContext{ ic_tythings = tts } subst
+ | isEmptyTCvSubst subst = ictxt
+ | otherwise = ictxt { ic_tythings = map subst_ty tts }
+ where
+ subst_ty (AnId id)
+ = AnId $ updateIdTypeAndMult (substTyAddInScope subst) id
+ -- Variables in the interactive context *can* mention free type variables
+ -- because of the runtime debugger. Otherwise you'd expect all
+ -- variables bound in the interactive context to be closed.
+ subst_ty tt
+ = tt
+
+instance Outputable InteractiveImport where
+ ppr (IIModule m) = char '*' <> ppr m
+ ppr (IIDecl d) = ppr d
+
diff --git a/compiler/GHC/Runtime/Debugger.hs b/compiler/GHC/Runtime/Debugger.hs
index 3def133bea..e86357a0ea 100644
--- a/compiler/GHC/Runtime/Debugger.hs
+++ b/compiler/GHC/Runtime/Debugger.hs
@@ -14,30 +14,35 @@ module GHC.Runtime.Debugger (pprintClosureCommand, showTerm, pprTypeAndContents)
import GHC.Prelude
+import GHC
+
+import GHC.Driver.Session
+import GHC.Driver.Ppr
+import GHC.Driver.Monad
+import GHC.Driver.Env
+
import GHC.Runtime.Linker
import GHC.Runtime.Heap.Inspect
-
import GHC.Runtime.Interpreter
-import GHCi.RemoteTypes
-import GHC.Driver.Monad
-import GHC.Driver.Types
-import GHC.Types.Id
+import GHC.Runtime.Context
+
import GHC.Iface.Syntax ( showToHeader )
import GHC.Iface.Env ( newInteractiveBinder )
-import GHC.Types.Name
-import GHC.Types.Var hiding ( varName )
-import GHC.Types.Var.Set
-import GHC.Types.Unique.Set
import GHC.Core.Type
-import GHC
+
import GHC.Utils.Outputable
-import GHC.Core.Ppr.TyThing
import GHC.Utils.Error
import GHC.Utils.Monad
-import GHC.Driver.Session
-import GHC.Driver.Ppr
import GHC.Utils.Exception
+import GHC.Types.Id
+import GHC.Types.Name
+import GHC.Types.Var hiding ( varName )
+import GHC.Types.Var.Set
+import GHC.Types.Unique.Set
+import GHC.Types.TyThing.Ppr
+import GHC.Types.TyThing
+
import Control.Monad
import Control.Monad.Catch as MC
import Data.List ( (\\) )
diff --git a/compiler/GHC/Runtime/Eval.hs b/compiler/GHC/Runtime/Eval.hs
index 68d2908dbb..337cd24d80 100644
--- a/compiler/GHC/Runtime/Eval.hs
+++ b/compiler/GHC/Runtime/Eval.hs
@@ -48,28 +48,57 @@ module GHC.Runtime.Eval (
import GHC.Prelude
-import GHC.Runtime.Eval.Types
+import GHC.Driver.Monad
+import GHC.Driver.Main
+import GHC.Driver.Env
+import GHC.Driver.Session
+import GHC.Driver.Ppr
+import GHC.Runtime.Eval.Types
import GHC.Runtime.Interpreter as GHCi
import GHC.Runtime.Interpreter.Types
+import GHC.Runtime.Linker as Linker
+import GHC.Runtime.Linker.Types
+import GHC.Runtime.Heap.Inspect
+import GHC.Runtime.Context
import GHCi.Message
import GHCi.RemoteTypes
-import GHC.Driver.Monad
-import GHC.Driver.Main
+import GHC.ByteCode.Types
+
import GHC.Hs
-import GHC.Driver.Types
+
+import GHC.Core.Predicate
import GHC.Core.InstEnv
-import GHC.Iface.Env ( newInteractiveBinder )
import GHC.Core.FamInstEnv ( FamInst )
import GHC.Core.FVs ( orphNamesOfFamInst )
import GHC.Core.TyCon
import GHC.Core.Type hiding( typeKind )
import qualified GHC.Core.Type as Type
-import GHC.Types.RepType
+
+import GHC.Iface.Env ( newInteractiveBinder )
import GHC.Tc.Utils.TcType
import GHC.Tc.Types.Constraint
import GHC.Tc.Types.Origin
-import GHC.Core.Predicate
+
+import GHC.Builtin.Names ( toDynName, pretendNameIsInScope )
+import GHC.Builtin.Types ( isCTupleTyConName )
+
+import GHC.Data.Maybe
+import GHC.Data.FastString
+import GHC.Data.Bag
+
+import GHC.Utils.Monad
+import GHC.Utils.Panic
+import GHC.Utils.Error
+import GHC.Utils.Outputable
+import GHC.Utils.Misc
+
+import qualified GHC.Parser.Lexer as Lexer (P (..), ParseResult(..), unP, initParserState)
+import GHC.Parser.Lexer (ParserOpts)
+import qualified GHC.Parser as Parser (parseStmt, parseModule, parseDeclaration, parseImport)
+
+import GHC.Types.RepType
+import GHC.Types.Fixity.Env
import GHC.Types.Var
import GHC.Types.Id as Id
import GHC.Types.Name hiding ( varName )
@@ -77,28 +106,15 @@ import GHC.Types.Name.Set
import GHC.Types.Avail
import GHC.Types.Name.Reader
import GHC.Types.Var.Env
-import GHC.ByteCode.Types
-import GHC.Runtime.Linker as Linker
-import GHC.Driver.Session
-import GHC.Driver.Ppr
+import GHC.Types.SrcLoc
import GHC.Types.Unique
import GHC.Types.Unique.Supply
-import GHC.Utils.Monad
+import GHC.Types.TyThing
+
import GHC.Unit
-import GHC.Builtin.Names ( toDynName, pretendNameIsInScope )
-import GHC.Builtin.Types ( isCTupleTyConName )
-import GHC.Utils.Panic
-import GHC.Data.Maybe
-import GHC.Utils.Error
-import GHC.Types.SrcLoc
-import GHC.Runtime.Heap.Inspect
-import GHC.Utils.Outputable
-import GHC.Data.FastString
-import GHC.Data.Bag
-import GHC.Utils.Misc
-import qualified GHC.Parser.Lexer as Lexer (P (..), ParseResult(..), unP, initParserState)
-import GHC.Parser.Lexer (ParserOpts)
-import qualified GHC.Parser as Parser (parseStmt, parseModule, parseDeclaration, parseImport)
+import GHC.Unit.Module.ModIface
+import GHC.Unit.Module.ModSummary
+import GHC.Unit.Home.ModInfo
import System.Directory
import Data.Dynamic
diff --git a/compiler/GHC/Runtime/Eval/Types.hs b/compiler/GHC/Runtime/Eval/Types.hs
index 9586947742..c72c5c89ff 100644
--- a/compiler/GHC/Runtime/Eval/Types.hs
+++ b/compiler/GHC/Runtime/Eval/Types.hs
@@ -18,9 +18,9 @@ import GHCi.RemoteTypes
import GHCi.Message (EvalExpr, ResumeContext)
import GHC.Types.Id
import GHC.Types.Name
+import GHC.Types.TyThing
import GHC.Unit.Module
import GHC.Types.Name.Reader
-import GHC.Core.Type
import GHC.Types.SrcLoc
import GHC.Utils.Exception
diff --git a/compiler/GHC/Runtime/Heap/Inspect.hs b/compiler/GHC/Runtime/Heap/Inspect.hs
index 7bcb1a364c..34c55760ac 100644
--- a/compiler/GHC/Runtime/Heap/Inspect.hs
+++ b/compiler/GHC/Runtime/Heap/Inspect.hs
@@ -30,7 +30,7 @@ import GHC.Platform
import GHC.Runtime.Interpreter as GHCi
import GHCi.RemoteTypes
-import GHC.Driver.Types
+import GHC.Driver.Env
import GHCi.Message ( fromSerializableException )
import GHC.Core.DataCon
diff --git a/compiler/GHC/Runtime/Interpreter.hs b/compiler/GHC/Runtime/Interpreter.hs
index bcfd34ee15..b2df09f35f 100644
--- a/compiler/GHC/Runtime/Interpreter.hs
+++ b/compiler/GHC/Runtime/Interpreter.hs
@@ -55,28 +55,36 @@ module GHC.Runtime.Interpreter
import GHC.Prelude
+import GHC.Driver.Ppr (showSDoc)
+import GHC.Driver.Env
+import GHC.Driver.Session
+
import GHC.Runtime.Interpreter.Types
import GHCi.Message
import GHCi.RemoteTypes
import GHCi.ResolvedBCO
import GHCi.BreakArray (BreakArray)
-import GHC.Utils.Fingerprint
-import GHC.Driver.Types
+import GHC.Runtime.Eval.Types(BreakInfo(..))
+import GHC.Runtime.Linker.Types
+import GHC.ByteCode.Types
+
+import GHC.Data.Maybe
+import GHC.Data.FastString
+
+import GHC.Types.Unique
+import GHC.Types.SrcLoc
import GHC.Types.Unique.FM
+import GHC.Types.Basic
+
import GHC.Utils.Panic
-import GHC.Driver.Session
import GHC.Utils.Exception as Ex
-import GHC.Types.Basic
-import GHC.Data.FastString
-import GHC.Utils.Misc
-import GHC.Runtime.Eval.Types(BreakInfo(..))
import GHC.Utils.Outputable(brackets, ppr)
-import GHC.Driver.Ppr (showSDoc)
-import GHC.Types.SrcLoc
-import GHC.Data.Maybe
+import GHC.Utils.Fingerprint
+import GHC.Utils.Misc
+
import GHC.Unit.Module
-import GHC.ByteCode.Types
-import GHC.Types.Unique
+import GHC.Unit.Module.ModIface
+import GHC.Unit.Home.ModInfo
#if defined(HAVE_INTERNAL_INTERPRETER)
import GHCi.Run
diff --git a/compiler/GHC/Runtime/Linker.hs b/compiler/GHC/Runtime/Linker.hs
index 4477a0ad2f..4203f741c6 100644
--- a/compiler/GHC/Runtime/Linker.hs
+++ b/compiler/GHC/Runtime/Linker.hs
@@ -31,40 +31,53 @@ where
import GHC.Prelude
+import GHC.Platform
+import GHC.Platform.Ways
+
+import GHC.Driver.Phases
+import GHC.Driver.Env
+import GHC.Driver.Session
+import GHC.Driver.Ppr
+
+import GHC.Tc.Utils.Monad
+
import GHC.Runtime.Interpreter
import GHC.Runtime.Interpreter.Types
+import GHC.Runtime.Linker.Types
import GHCi.RemoteTypes
+
import GHC.Iface.Load
+
import GHC.ByteCode.Linker
import GHC.ByteCode.Asm
import GHC.ByteCode.Types
-import GHC.Tc.Utils.Monad
-import GHC.Unit.State as Packages
-import GHC.Driver.Phases
-import GHC.Driver.Finder
-import GHC.Driver.Types
-import GHC.Platform.Ways
+
+import GHC.SysTools
+import GHC.SysTools.FileCleanup
+
+import GHC.Types.Basic
import GHC.Types.Name
import GHC.Types.Name.Env
-import GHC.Unit.Module
-import GHC.Unit.Home
-import GHC.Data.List.SetOps
-import GHC.Runtime.Linker.Types (DynLinker(..), PersistentLinkerState(..))
-import GHC.Driver.Session
-import GHC.Driver.Ppr
-import GHC.Types.Basic
+import GHC.Types.SrcLoc
+import GHC.Types.Unique.DSet
+
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Utils.Misc
import GHC.Utils.Error
-import GHC.Types.SrcLoc
+
+import GHC.Unit.Finder
+import GHC.Unit.Module
+import GHC.Unit.Module.ModIface
+import GHC.Unit.Module.Deps
+import GHC.Unit.Home
+import GHC.Unit.Home.ModInfo
+import GHC.Unit.State as Packages
+
+import qualified GHC.Data.ShortText as ST
import qualified GHC.Data.Maybe as Maybes
-import GHC.Types.Unique.DSet
import GHC.Data.FastString
-import qualified GHC.Data.ShortText as ST
-import GHC.Platform
-import GHC.SysTools
-import GHC.SysTools.FileCleanup
+import GHC.Data.List.SetOps
-- Standard libraries
import Control.Monad
@@ -446,7 +459,7 @@ preloadLib hsc_env lib_paths framework_paths pls lib_spec = do
return pls
DLL dll_unadorned -> do
- maybe_errstr <- loadDLL hsc_env (mkSOName platform dll_unadorned)
+ maybe_errstr <- loadDLL hsc_env (platformSOName platform dll_unadorned)
case maybe_errstr of
Nothing -> maybePutStrLn dflags "done"
Just mm | platformOS platform /= OSDarwin ->
@@ -918,7 +931,7 @@ dynLoadObjs hsc_env pls@PersistentLinkerState{..} objs = do
let minus_ls = [ lib | Option ('-':'l':lib) <- ldInputs dflags ]
let minus_big_ls = [ lib | Option ('-':'L':lib) <- ldInputs dflags ]
(soFile, libPath , libName) <-
- newTempLibName dflags TFL_CurrentModule (soExt platform)
+ newTempLibName dflags TFL_CurrentModule (platformSOExt platform)
let
dflags2 = dflags {
-- We don't want the original ldInputs in
@@ -1342,7 +1355,7 @@ linkPackage hsc_env pkg
mapM_ (load_dyn hsc_env True) known_dlls
-- For remaining `dlls` crash early only when there is surely
-- no package's DLL around ... (not is_dyn)
- mapM_ (load_dyn hsc_env (not is_dyn) . mkSOName platform) dlls
+ mapM_ (load_dyn hsc_env (not is_dyn) . platformSOName platform) dlls
#endif
-- After loading all the DLLs, we can load the static objects.
-- Ordering isn't important here, because we do one final link
@@ -1528,9 +1541,9 @@ locateLib hsc_env is_hs lib_dirs gcc_dirs lib
]
hs_dyn_lib_name = lib ++ '-':programName dflags ++ projectVersion dflags
- hs_dyn_lib_file = mkHsSOName platform hs_dyn_lib_name
+ hs_dyn_lib_file = platformHsSOName platform hs_dyn_lib_name
- so_name = mkSOName platform lib
+ so_name = platformSOName platform lib
lib_so_name = "lib" ++ so_name
dyn_lib_file = case (arch, os) of
(ArchX86_64, OSSolaris2) -> "64" </> so_name
diff --git a/compiler/GHC/Runtime/Linker/Types.hs b/compiler/GHC/Runtime/Linker/Types.hs
index 7899feae9e..e40de2b55e 100644
--- a/compiler/GHC/Runtime/Linker/Types.hs
+++ b/compiler/GHC/Runtime/Linker/Types.hs
@@ -6,26 +6,35 @@
--
-----------------------------------------------------------------------------
-module GHC.Runtime.Linker.Types (
- DynLinker(..),
- PersistentLinkerState(..),
- Linkable(..),
- Unlinked(..),
- SptEntry(..)
- ) where
-
-import GHC.Prelude ( FilePath, String, show )
+module GHC.Runtime.Linker.Types
+ ( DynLinker(..)
+ , PersistentLinkerState(..)
+ , Linkable(..)
+ , Unlinked(..)
+ , SptEntry(..)
+ , isObjectLinkable
+ , linkableObjs
+ , isObject
+ , nameOfObject
+ , isInterpretable
+ , byteCodeOfObject
+ )
+where
+
+import GHC.Prelude
import Data.Time ( UTCTime )
-import Data.Maybe ( Maybe )
import Control.Concurrent.MVar ( MVar )
import GHC.Unit ( UnitId, Module )
import GHC.ByteCode.Types ( ItblEnv, CompiledByteCode )
-import GHC.Utils.Outputable
-import GHC.Types.Var ( Id )
import GHC.Fingerprint.Type ( Fingerprint )
+import GHCi.RemoteTypes ( ForeignHValue )
+
+import GHC.Types.Var ( Id )
import GHC.Types.Name.Env ( NameEnv )
import GHC.Types.Name ( Name )
-import GHCi.RemoteTypes ( ForeignHValue )
+
+import GHC.Utils.Outputable
+import GHC.Utils.Panic
type ClosureEnv = NameEnv (Name, ForeignHValue)
@@ -106,3 +115,39 @@ data SptEntry = SptEntry Id Fingerprint
instance Outputable SptEntry where
ppr (SptEntry id fpr) = ppr id <> colon <+> ppr fpr
+
+isObjectLinkable :: Linkable -> Bool
+isObjectLinkable l = not (null unlinked) && all isObject unlinked
+ where unlinked = linkableUnlinked l
+ -- A linkable with no Unlinked's is treated as a BCO. We can
+ -- generate a linkable with no Unlinked's as a result of
+ -- compiling a module in NoBackend mode, and this choice
+ -- happens to work well with checkStability in module GHC.
+
+linkableObjs :: Linkable -> [FilePath]
+linkableObjs l = [ f | DotO f <- linkableUnlinked l ]
+
+-------------------------------------------
+
+-- | Is this an actual file on disk we can link in somehow?
+isObject :: Unlinked -> Bool
+isObject (DotO _) = True
+isObject (DotA _) = True
+isObject (DotDLL _) = True
+isObject _ = False
+
+-- | Is this a bytecode linkable with no file on disk?
+isInterpretable :: Unlinked -> Bool
+isInterpretable = not . isObject
+
+-- | Retrieve the filename of the linkable if possible. Panic if it is a byte-code object
+nameOfObject :: Unlinked -> FilePath
+nameOfObject (DotO fn) = fn
+nameOfObject (DotA fn) = fn
+nameOfObject (DotDLL fn) = fn
+nameOfObject other = pprPanic "nameOfObject" (ppr other)
+
+-- | Retrieve the compiled byte-code if possible. Panic if it is a file-based linkable
+byteCodeOfObject :: Unlinked -> CompiledByteCode
+byteCodeOfObject (BCOs bc _) = bc
+byteCodeOfObject other = pprPanic "byteCodeOfObject" (ppr other)
diff --git a/compiler/GHC/Runtime/Loader.hs b/compiler/GHC/Runtime/Loader.hs
index be89d86192..2a97e24edd 100644
--- a/compiler/GHC/Runtime/Loader.hs
+++ b/compiler/GHC/Runtime/Loader.hs
@@ -21,38 +21,45 @@ module GHC.Runtime.Loader (
) where
import GHC.Prelude
+
import GHC.Driver.Session
import GHC.Driver.Ppr
+import GHC.Driver.Hooks
+import GHC.Driver.Plugins
import GHC.Runtime.Linker ( linkModule, getHValue )
import GHC.Runtime.Interpreter ( wormhole, withInterp )
import GHC.Runtime.Interpreter.Types
-import GHC.Types.SrcLoc ( noSrcSpan )
-import GHC.Driver.Finder ( findPluginModule, cannotFindModule )
+
import GHC.Tc.Utils.Monad ( initTcInteractive, initIfaceTcRn )
import GHC.Iface.Load ( loadPluginInterface )
-import GHC.Types.Name.Reader ( RdrName, ImportSpec(..), ImpDeclSpec(..)
- , ImpItemSpec(..), mkGlobalRdrEnv, lookupGRE_RdrName
- , gre_name, mkRdrQual )
-import GHC.Types.Name.Occurrence ( OccName, mkVarOcc )
import GHC.Rename.Names ( gresFromAvails )
-import GHC.Driver.Plugins
import GHC.Builtin.Names ( pluginTyConName, frontendPluginTyConName )
-import GHC.Driver.Types
+import GHC.Driver.Env
import GHCi.RemoteTypes ( HValue )
import GHC.Core.Type ( Type, eqType, mkTyConTy )
-import GHC.Core.TyCo.Ppr ( pprTyThingCategory )
import GHC.Core.TyCon ( TyCon )
+
+import GHC.Types.SrcLoc ( noSrcSpan )
import GHC.Types.Name ( Name, nameModule_maybe )
import GHC.Types.Id ( idType )
+import GHC.Types.TyThing
+import GHC.Types.Name.Occurrence ( OccName, mkVarOcc )
+import GHC.Types.Name.Reader ( RdrName, ImportSpec(..), ImpDeclSpec(..)
+ , ImpItemSpec(..), mkGlobalRdrEnv, lookupGRE_RdrName
+ , gre_name, mkRdrQual )
+
+import GHC.Unit.Finder ( findPluginModule, cannotFindModule, FindResult(..) )
import GHC.Unit.Module ( Module, ModuleName )
+import GHC.Unit.Module.ModIface
+
import GHC.Utils.Panic
-import GHC.Data.FastString
import GHC.Utils.Error
import GHC.Utils.Outputable
import GHC.Utils.Exception
-import GHC.Driver.Hooks
+
+import GHC.Data.FastString
import Control.Monad ( unless )
import Data.Maybe ( mapMaybe )