summaryrefslogtreecommitdiff
path: root/compiler/iface/BinIface.hs
diff options
context:
space:
mode:
authorMatthew Pickering <matthew.pickering@tweag.io>2018-06-04 02:05:46 +0000
committerMatthew Pickering <matthew.pickering@tweag.io>2018-06-04 02:06:03 +0000
commit554bc7fcca30b1b6ffb6a2daca684ea74eb83ad8 (patch)
tree622414d95ac9fe351718c471e98f2033038cee15 /compiler/iface/BinIface.hs
parent4dd1895bf8bbe5aac7a8e80f18ba76e78520be18 (diff)
downloadhaskell-554bc7fcca30b1b6ffb6a2daca684ea74eb83ad8.tar.gz
Provide `getWithUserData` and `putWithUserData`
Summary: This makes it possible to serialise Names and FastStrings in user programs, for example, when writing a source plugin. When writing my first source plugin, I wanted to serialise names but it wasn't possible easily without exporting additional constructors. This interface is sufficient and abstracts nicely over the symbol table and dictionary. Reviewers: alpmestan, bgamari Reviewed By: alpmestan Subscribers: rwbarton, thomie, carter GHC Trac Issues: #15223 Differential Revision: https://phabricator.haskell.org/D4782
Diffstat (limited to 'compiler/iface/BinIface.hs')
-rw-r--r--compiler/iface/BinIface.hs33
1 files changed, 26 insertions, 7 deletions
diff --git a/compiler/iface/BinIface.hs b/compiler/iface/BinIface.hs
index 2a4696a541..b8b4bb0370 100644
--- a/compiler/iface/BinIface.hs
+++ b/compiler/iface/BinIface.hs
@@ -15,7 +15,10 @@ module BinIface (
getSymtabName,
getDictFastString,
CheckHiWay(..),
- TraceBinIFaceReading(..)
+ TraceBinIFaceReading(..),
+ getWithUserData,
+ putWithUserData
+
) where
#include "HsVersions.h"
@@ -134,7 +137,14 @@ readBinIface_ dflags checkHiWay traceBinIFaceReading hi_path ncu = do
wantedGot "Way" way_descr check_way
when (checkHiWay == CheckHiWay) $
errorOnMismatch "mismatched interface file ways" way_descr check_way
+ getWithUserData ncu bh
+
+-- | This performs a get action after reading the dictionary and symbol
+-- table. It is necessary to run this before trying to deserialise any
+-- Names or FastStrings.
+getWithUserData :: Binary a => NameCacheUpdater -> BinHandle -> IO a
+getWithUserData ncu bh = do
-- Read the dictionary
-- The next word in the file is a pointer to where the dictionary is
-- (probably at the end of the file)
@@ -179,6 +189,17 @@ writeBinIface dflags hi_path mod_iface = do
let way_descr = getWayDescr dflags
put_ bh way_descr
+
+ putWithUserData (debugTraceMsg dflags 3) bh mod_iface
+ -- And send the result to the file
+ writeBinMem bh hi_path
+
+-- | Put a piece of data with an initialised `UserData` field. This
+-- is necessary if you want to serialise Names or FastStrings.
+-- It also writes a symbol table and the dictionary.
+-- This segment should be read using `getWithUserData`.
+putWithUserData :: Binary a => (SDoc -> IO ()) -> BinHandle -> a -> IO ()
+putWithUserData log_action bh payload = do
-- Remember where the dictionary pointer will go
dict_p_p <- tellBin bh
-- Placeholder for ptr to dictionary
@@ -187,7 +208,6 @@ writeBinIface dflags hi_path mod_iface = do
-- Remember where the symbol table pointer will go
symtab_p_p <- tellBin bh
put_ bh symtab_p_p
-
-- Make some intial state
symtab_next <- newFastMutInt
writeFastMutInt symtab_next 0
@@ -206,7 +226,7 @@ writeBinIface dflags hi_path mod_iface = do
bh <- return $ setUserData bh $ newWriteState (putName bin_dict bin_symtab)
(putName bin_dict bin_symtab)
(putFastString bin_dict)
- put_ bh mod_iface
+ put_ bh payload
-- Write the symtab pointer at the front of the file
symtab_p <- tellBin bh -- This is where the symtab will start
@@ -217,7 +237,7 @@ writeBinIface dflags hi_path mod_iface = do
symtab_next <- readFastMutInt symtab_next
symtab_map <- readIORef symtab_map
putSymbolTable bh symtab_next symtab_map
- debugTraceMsg dflags 3 (text "writeBinIface:" <+> int symtab_next
+ log_action (text "writeBinIface:" <+> int symtab_next
<+> text "Names")
-- NB. write the dictionary after the symbol table, because
@@ -232,11 +252,10 @@ writeBinIface dflags hi_path mod_iface = do
dict_next <- readFastMutInt dict_next_ref
dict_map <- readIORef dict_map_ref
putDictionary bh dict_next dict_map
- debugTraceMsg dflags 3 (text "writeBinIface:" <+> int dict_next
+ log_action (text "writeBinIface:" <+> int dict_next
<+> text "dict entries")
- -- And send the result to the file
- writeBinMem bh hi_path
+
-- | Initial ram buffer to allocate for writing interface files
initBinMemSize :: Int