diff options
author | Takano Akio <tak@anoak.io> | 2017-01-18 18:26:47 -0500 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2017-01-20 14:36:29 -0500 |
commit | d49b2bb21691892ca6ac8f2403e31f2a5e53feb3 (patch) | |
tree | cc8488acf59467899e4d3279a340577eec95310f /compiler/codeGen | |
parent | a2a67b77c3048713541d1ed96ec0b95fb2542f9a (diff) | |
download | haskell-d49b2bb21691892ca6ac8f2403e31f2a5e53feb3.tar.gz |
Allow top-level string literals in Core (#8472)
This commits relaxes the invariants of the Core syntax so that a
top-level variable can be bound to a primitive string literal of type
Addr#.
This commit:
* Relaxes the invatiants of the Core, and allows top-level bindings whose
type is Addr# as long as their RHS is either a primitive string literal or
another variable.
* Allows the simplifier and the full-laziness transformer to float out
primitive string literals to the top leve.
* Introduces the new StgGenTopBinding type to accomodate top-level Addr#
bindings.
* Introduces a new type of labels in the object code, with the suffix "_bytes",
for exported top-level Addr# bindings.
* Makes some built-in rules more robust. This was necessary to keep them
functional after the above changes.
This is a continuation of D2554.
Rebasing notes:
This had two slightly suspicious performance regressions:
* T12425: bytes allocated regressed by roughly 5%
* T4029: bytes allocated regressed by a bit over 1%
* T13035: bytes allocated regressed by a bit over 5%
These deserve additional investigation.
Rebased by: bgamari.
Test Plan: ./validate --slow
Reviewers: goldfire, trofi, simonmar, simonpj, austin, hvr, bgamari
Reviewed By: trofi, simonpj, bgamari
Subscribers: trofi, simonpj, gridaphobe, thomie
Differential Revision: https://phabricator.haskell.org/D2605
GHC Trac Issues: #8472
Diffstat (limited to 'compiler/codeGen')
-rw-r--r-- | compiler/codeGen/StgCmm.hs | 17 | ||||
-rw-r--r-- | compiler/codeGen/StgCmmClosure.hs | 5 | ||||
-rw-r--r-- | compiler/codeGen/StgCmmEnv.hs | 14 | ||||
-rw-r--r-- | compiler/codeGen/StgCmmUtils.hs | 2 |
4 files changed, 31 insertions, 7 deletions
diff --git a/compiler/codeGen/StgCmm.hs b/compiler/codeGen/StgCmm.hs index bb82da265e..a420677625 100644 --- a/compiler/codeGen/StgCmm.hs +++ b/compiler/codeGen/StgCmm.hs @@ -24,6 +24,7 @@ import StgCmmHpc import StgCmmTicky import Cmm +import CmmUtils import CLabel import StgSyn @@ -45,6 +46,7 @@ import BasicTypes import OrdList import MkGraph +import qualified Data.ByteString as BS import Data.IORef import Control.Monad (when,void) import Util @@ -53,7 +55,7 @@ codeGen :: DynFlags -> Module -> [TyCon] -> CollectedCCs -- (Local/global) cost-centres needing declaring/registering. - -> [StgBinding] -- Bindings to convert + -> [StgTopBinding] -- Bindings to convert -> HpcInfo -> Stream IO CmmGroup () -- Output as a stream, so codegen can -- be interleaved with output @@ -113,8 +115,8 @@ This is so that we can write the top level processing in a compositional style, with the increasing static environment being plumbed as a state variable. -} -cgTopBinding :: DynFlags -> StgBinding -> FCode () -cgTopBinding dflags (StgNonRec id rhs) +cgTopBinding :: DynFlags -> StgTopBinding -> FCode () +cgTopBinding dflags (StgTopLifted (StgNonRec id rhs)) = do { id' <- maybeExternaliseId dflags id ; let (info, fcode) = cgTopRhs dflags NonRecursive id' rhs ; fcode @@ -122,7 +124,7 @@ cgTopBinding dflags (StgNonRec id rhs) -- so we find it when we look up occurrences } -cgTopBinding dflags (StgRec pairs) +cgTopBinding dflags (StgTopLifted (StgRec pairs)) = do { let (bndrs, rhss) = unzip pairs ; bndrs' <- Prelude.mapM (maybeExternaliseId dflags) bndrs ; let pairs' = zip bndrs' rhss @@ -132,6 +134,13 @@ cgTopBinding dflags (StgRec pairs) ; sequence_ fcodes } +cgTopBinding dflags (StgTopStringLit id str) + = do { id' <- maybeExternaliseId dflags id + ; let label = mkBytesLabel (idName id') + ; let (lit, decl) = mkByteStringCLit label (BS.unpack str) + ; emitDecl decl + ; addBindC (litIdInfo dflags id' mkLFStringLit lit) + } cgTopRhs :: DynFlags -> RecFlag -> Id -> StgRhs -> (CgIdInfo, FCode ()) -- The Id is passed along for setting up a binding... diff --git a/compiler/codeGen/StgCmmClosure.hs b/compiler/codeGen/StgCmmClosure.hs index 3cc0af0669..e799ea6639 100644 --- a/compiler/codeGen/StgCmmClosure.hs +++ b/compiler/codeGen/StgCmmClosure.hs @@ -26,6 +26,7 @@ module StgCmmClosure ( StandardFormInfo, -- ...ditto... mkLFThunk, mkLFReEntrant, mkConLFInfo, mkSelectorLFInfo, mkApLFInfo, mkLFImported, mkLFArgument, mkLFLetNoEscape, + mkLFStringLit, lfDynTag, maybeIsLFCon, isLFThunk, isLFReEntrant, lfUpdatable, @@ -332,6 +333,10 @@ mkLFImported id where arity = idFunRepArity id +------------- +mkLFStringLit :: LambdaFormInfo +mkLFStringLit = LFUnlifted + ----------------------------------------------------- -- Dynamic pointer tagging ----------------------------------------------------- diff --git a/compiler/codeGen/StgCmmEnv.hs b/compiler/codeGen/StgCmmEnv.hs index ba093fee88..3061fb351b 100644 --- a/compiler/codeGen/StgCmmEnv.hs +++ b/compiler/codeGen/StgCmmEnv.hs @@ -40,7 +40,10 @@ import MkGraph import Name import Outputable import StgSyn +import Type +import TysPrim import UniqFM +import Util import VarEnv ------------------------------------- @@ -125,8 +128,15 @@ getCgIdInfo id -- Should be imported; make up a CgIdInfo for it let name = idName id ; if isExternalName name then - let ext_lbl = CmmLabel (mkClosureLabel name $ idCafInfo id) - in return (litIdInfo dflags id (mkLFImported id) ext_lbl) + let ext_lbl + | isUnliftedType (idType id) = + -- An unlifted external Id must refer to a top-level + -- string literal. See Note [Bytes label] in CLabel. + ASSERT( idType id `eqType` addrPrimTy ) + mkBytesLabel name + | otherwise = mkClosureLabel name $ idCafInfo id + in return $ + litIdInfo dflags id (mkLFImported id) (CmmLabel ext_lbl) else cgLookupPanic id -- Bug }}} diff --git a/compiler/codeGen/StgCmmUtils.hs b/compiler/codeGen/StgCmmUtils.hs index 4a976e68af..295ac15a85 100644 --- a/compiler/codeGen/StgCmmUtils.hs +++ b/compiler/codeGen/StgCmmUtils.hs @@ -322,7 +322,7 @@ newStringCLit str = newByteStringCLit (map (fromIntegral . ord) str) newByteStringCLit :: [Word8] -> FCode CmmLit newByteStringCLit bytes = do { uniq <- newUnique - ; let (lit, decl) = mkByteStringCLit uniq bytes + ; let (lit, decl) = mkByteStringCLit (mkStringLitLabel uniq) bytes ; emitDecl decl ; return lit } |