Hi all,

Following a short chat in #ghc last week, I did a first attempt of
reusing existing Iface logic to implement serialization for
codegen-related Core. The implementation is included in the attached
patch (~100 loc). As a quick and dirty validation of whether it works,
I also modified the codegen pipeline logic to do a roundtrip: after
CorePrep, the Core bits are converted to Iface, then we immediately
convert it back and use it for later compiling.

With the patch applied, stage-1 GHC would produce a "missing hi file"
error like:

: Bad interface file: _build/stage1/libraries/ghc-prim/build/GHC/Types.hi
      _build/stage1/libraries/ghc-prim/build/GHC/Types.hi:
openBinaryFile: does not exist (No such file or directory)

The error surprises me, since by the time we perform the Core-to-Core
roundtrip, the .hi file should already have been written to disk. Is
there anything obviously wrong with the implementation? I'd appreciate
any pointers or further questions, thanks a lot!

Best regards,
Cheng
diff --git a/compiler/ExtCore.hs b/compiler/ExtCore.hs
new file mode 100644
index 0000000000..48f7792cf3
--- /dev/null
+++ b/compiler/ExtCore.hs
@@ -0,0 +1,82 @@
+{-# OPTIONS_GHC -Wall #-}
+
+module ExtCore where
+
+import Data.Traversable
+import qualified GHC.CoreToIface as GHC
+import qualified GHC.Iface.Syntax as GHC
+import qualified GHC.IfaceToCore as GHC
+import qualified GHC.Plugins as GHC
+import GHC.Prelude
+import qualified GHC.Tc.Utils.Monad as GHC
+import qualified GHC.Utils.Binary as GHC
+
+data ExtCoreBind
+  = NonRec GHC.IfExtName GHC.IfaceExpr
+  | Rec [(GHC.IfExtName, GHC.IfaceExpr)]
+
+instance GHC.Binary ExtCoreBind where
+  put_ bh (NonRec bndr rhs) =
+    GHC.putByte bh 0 *> GHC.put_ bh bndr *> GHC.put_ bh rhs
+  put_ bh (Rec pairs) = GHC.putByte bh 1 *> GHC.put_ bh pairs
+
+  get bh = do
+    h <- GHC.getByte bh
+    case h of
+      0 -> NonRec <$> GHC.get bh <*> GHC.get bh
+      1 -> Rec <$> GHC.get bh
+      _ -> fail "instance Binary ExtCoreBind"
+
+toExtCoreBinds :: GHC.CoreProgram -> [ExtCoreBind]
+toExtCoreBinds = map toExtCoreBind
+
+toExtCoreBind :: GHC.CoreBind -> ExtCoreBind
+toExtCoreBind (GHC.NonRec b r) =
+  NonRec (unIfaceExt $ GHC.toIfaceVar b) (GHC.toIfaceExpr r)
+toExtCoreBind (GHC.Rec prs) =
+  Rec [(unIfaceExt $ GHC.toIfaceVar b, GHC.toIfaceExpr r) | (b, r) <- prs]
+
+tcExtCoreBindsDriver ::
+  GHC.HscEnv -> GHC.Module -> [ExtCoreBind] -> IO GHC.CoreProgram
+tcExtCoreBindsDriver hsc_env this_mod ext_core_binds = do
+  (_, maybe_result) <-
+    GHC.initTc hsc_env GHC.HsSrcFile False this_mod (error "lazy RealSrcSpan") $
+      initIfaceExtCore $
+        tcExtCoreBinds ext_core_binds
+  case maybe_result of
+    Just r -> pure r
+    _ -> fail "tcExtCoreBindsDriver"
+
+tcExtCoreBinds :: [ExtCoreBind] -> GHC.IfL GHC.CoreProgram
+tcExtCoreBinds = traverse tcExtCoreBind
+
+tcExtCoreBind :: ExtCoreBind -> GHC.IfL GHC.CoreBind
+tcExtCoreBind (NonRec bndr rhs) = do
+  bndr' <- fmap unCoreVar $ GHC.tcIfaceExpr $ GHC.IfaceExt bndr
+  rhs' <- GHC.tcIfaceExpr rhs
+  pure $ GHC.NonRec bndr' rhs'
+tcExtCoreBind (Rec pairs) = do
+  let (bndrs, rhss) = unzip pairs
+  bndrs' <- for bndrs $ fmap unCoreVar . GHC.tcIfaceExpr . GHC.IfaceExt
+  rhss' <- for rhss GHC.tcIfaceExpr
+  pure $ GHC.Rec $ zip bndrs' rhss'
+
+initIfaceExtCore :: GHC.IfL a -> GHC.TcRn a
+initIfaceExtCore thing_inside = do
+  tcg_env <- GHC.getGblEnv
+  let this_mod = GHC.tcg_mod tcg_env
+      if_env =
+        GHC.IfGblEnv
+          { GHC.if_doc = GHC.empty,
+            GHC.if_rec_types = Just (this_mod, pure (GHC.tcg_type_env tcg_env))
+          }
+      if_lenv = GHC.mkIfLclEnv this_mod GHC.empty GHC.NotBoot
+  GHC.setEnvs (if_env, if_lenv) thing_inside
+
+unIfaceExt :: GHC.IfaceExpr -> GHC.IfExtName
+unIfaceExt (GHC.IfaceExt bndr) = bndr
+unIfaceExt _ = error "unIfaceExt"
+
+unCoreVar :: GHC.CoreExpr -> GHC.CoreBndr
+unCoreVar (GHC.Var bndr) = bndr
+unCoreVar _ = error "unCoreVar"
diff --git a/compiler/GHC/Driver/Main.hs b/compiler/GHC/Driver/Main.hs
index 90a07d7490..61bfc96693 100644
--- a/compiler/GHC/Driver/Main.hs
+++ b/compiler/GHC/Driver/Main.hs
@@ -183,6 +183,8 @@ import GHC.Iface.Ext.Types  ( getAsts, hie_asts, hie_module )
 import GHC.Iface.Ext.Binary ( readHieFile, writeHieFile , hie_file_result, NameCacheUpdater(..))
 import GHC.Iface.Ext.Debug  ( diffFile, validateScopes )
 
+import ExtCore
+
 #include "HsVersions.h"
 
 
@@ -1409,9 +1411,12 @@ hscGenHardCode hsc_env cgguts location output_filename = do
         -------------------
         -- PREPARE FOR CODE GENERATION
         -- Do saturation and convert to A-normal form
-        (prepd_binds, local_ccs) <- {-# SCC "CorePrep" #-}
+        (prepd_binds', local_ccs) <- {-# SCC "CorePrep" #-}
                        corePrepPgm hsc_env this_mod location
                                    core_binds data_tycons
+
+        prepd_binds <- tcExtCoreBindsDriver hsc_env this_mod $ toExtCoreBinds prepd_binds'
+
         -----------------  Convert to STG ------------------
         (stg_binds, (caf_ccs, caf_cc_stacks))
             <- {-# SCC "CoreToStg" #-}
diff --git a/compiler/ghc.cabal.in b/compiler/ghc.cabal.in
index d469a85926..0bb2524a2b 100644
--- a/compiler/ghc.cabal.in
+++ b/compiler/ghc.cabal.in
@@ -663,3 +663,4 @@ Library
             GHC.Runtime.Heap.Inspect
             GHC.Runtime.Interpreter
             GHC.Runtime.Interpreter.Types
+            ExtCore
_______________________________________________
ghc-devs mailing list
ghc-devs@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

Reply via email to