summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2011-08-22 13:56:17 +0100
committerSimon Marlow <marlowsd@gmail.com>2011-08-25 11:12:30 +0100
commit5b167f5edad7d3268de20452da7af05c38972f7c (patch)
tree36a14e64b510ede91e4e334f3e44d865321adcde
parent3108accd634a521b25471df19f063c2061d6d3ee (diff)
downloadhaskell-5b167f5edad7d3268de20452da7af05c38972f7c.tar.gz
Snapshot of codegen refactoring to share with simonpj
-rw-r--r--compiler/cmm/CLabel.hs10
-rw-r--r--compiler/cmm/Cmm.hs284
-rw-r--r--compiler/cmm/CmmBuildInfoTables.hs52
-rw-r--r--compiler/cmm/CmmCommonBlockElim.hs2
-rw-r--r--compiler/cmm/CmmContFlowOpt.hs13
-rw-r--r--compiler/cmm/CmmCvt.hs74
-rw-r--r--compiler/cmm/CmmDecl.hs139
-rw-r--r--compiler/cmm/CmmInfo.hs353
-rw-r--r--compiler/cmm/CmmLint.hs4
-rw-r--r--compiler/cmm/CmmLive.hs2
-rw-r--r--compiler/cmm/CmmNode.hs23
-rw-r--r--compiler/cmm/CmmParse.y116
-rw-r--r--compiler/cmm/CmmPipeline.hs29
-rw-r--r--compiler/cmm/CmmProcPoint.hs9
-rw-r--r--compiler/cmm/CmmRewriteAssignments.hs2
-rw-r--r--compiler/cmm/CmmSpillReload.hs2
-rw-r--r--compiler/cmm/CmmStackLayout.hs2
-rw-r--r--compiler/cmm/CmmUtils.hs392
-rw-r--r--compiler/cmm/MkGraph.hs6
-rw-r--r--compiler/cmm/OldCmm.hs31
-rw-r--r--compiler/cmm/OldPprCmm.hs8
-rw-r--r--compiler/cmm/PprC.hs8
-rw-r--r--compiler/cmm/PprCmm.hs3
-rw-r--r--compiler/cmm/PprCmmDecl.hs85
-rw-r--r--compiler/cmm/cmm-notes57
-rw-r--r--compiler/codeGen/CgCallConv.hs74
-rw-r--r--compiler/codeGen/CgCon.lhs4
-rw-r--r--compiler/codeGen/CgExtCode.hs20
-rw-r--r--compiler/codeGen/CgForeignCall.hs1
-rw-r--r--compiler/codeGen/CgInfoTbls.hs76
-rw-r--r--compiler/codeGen/CgMonad.lhs22
-rw-r--r--compiler/codeGen/CgProf.hs4
-rw-r--r--compiler/codeGen/CgTicky.hs20
-rw-r--r--compiler/codeGen/CgUtils.hs154
-rw-r--r--compiler/codeGen/ClosureInfo.lhs174
-rw-r--r--compiler/codeGen/CodeGen.lhs6
-rw-r--r--compiler/codeGen/SMRep.lhs310
-rw-r--r--compiler/codeGen/StgCmm.hs26
-rw-r--r--compiler/codeGen/StgCmmBind.hs12
-rw-r--r--compiler/codeGen/StgCmmClosure.hs325
-rw-r--r--compiler/codeGen/StgCmmCon.hs18
-rw-r--r--compiler/codeGen/StgCmmEnv.hs32
-rw-r--r--compiler/codeGen/StgCmmExpr.hs2
-rw-r--r--compiler/codeGen/StgCmmForeign.hs3
-rw-r--r--compiler/codeGen/StgCmmHeap.hs40
-rw-r--r--compiler/codeGen/StgCmmLayout.hs165
-rw-r--r--compiler/codeGen/StgCmmMonad.hs18
-rw-r--r--compiler/codeGen/StgCmmPrim.hs3
-rw-r--r--compiler/codeGen/StgCmmProf.hs7
-rw-r--r--compiler/codeGen/StgCmmTicky.hs24
-rw-r--r--compiler/codeGen/StgCmmUtils.hs191
-rw-r--r--compiler/ghc.cabal.in1
-rw-r--r--compiler/llvmGen/LlvmCodeGen.hs6
-rw-r--r--compiler/main/CodeOutput.lhs10
-rw-r--r--compiler/main/DynFlags.hs2
-rw-r--r--compiler/main/HscMain.lhs45
-rw-r--r--compiler/nativeGen/AsmCodeGen.lhs8
-rw-r--r--compiler/nativeGen/Instruction.hs2
-rw-r--r--compiler/utils/FastString.lhs1
-rw-r--r--includes/rts/storage/InfoTables.h8
60 files changed, 1541 insertions, 1979 deletions
diff --git a/compiler/cmm/CLabel.hs b/compiler/cmm/CLabel.hs
index fdab13264f..68f13c937e 100644
--- a/compiler/cmm/CLabel.hs
+++ b/compiler/cmm/CLabel.hs
@@ -22,7 +22,7 @@ module CLabel (
mkSRTLabel,
mkInfoTableLabel,
mkEntryLabel,
- mkSlowEntryLabel,
+ mkSlowEntryLabel, slowEntryFromInfoLabel,
mkConEntryLabel,
mkStaticConEntryLabel,
mkRednCountsLabel,
@@ -354,8 +354,10 @@ data DynamicLinkerLabelInfo
-- Constructing IdLabels
-- These are always local:
+mkSlowEntryLabel name c = IdLabel name c Slow
+slowEntryFromInfoLabel (IdLabel n c _) = IdLabel n c Slow
+
mkSRTLabel name c = IdLabel name c SRT
-mkSlowEntryLabel name c = IdLabel name c Slow
mkRednCountsLabel name c = IdLabel name c RednCounts
-- These have local & (possibly) external variants:
@@ -372,8 +374,8 @@ mkLocalConInfoTableLabel c con = IdLabel con c ConInfoTable
mkLocalConEntryLabel c con = IdLabel con c ConEntry
mkLocalStaticInfoTableLabel c con = IdLabel con c StaticInfoTable
mkLocalStaticConEntryLabel c con = IdLabel con c StaticConEntry
-mkConInfoTableLabel name c = IdLabel name c ConInfoTable
-mkStaticInfoTableLabel name c = IdLabel name c StaticInfoTable
+mkConInfoTableLabel name c = IdLabel name c ConInfoTable
+mkStaticInfoTableLabel name c = IdLabel name c StaticInfoTable
mkConEntryLabel name c = IdLabel name c ConEntry
mkStaticConEntryLabel name c = IdLabel name c StaticConEntry
diff --git a/compiler/cmm/Cmm.hs b/compiler/cmm/Cmm.hs
index 49ea6dd461..93ac141ac7 100644
--- a/compiler/cmm/Cmm.hs
+++ b/compiler/cmm/Cmm.hs
@@ -8,39 +8,84 @@
{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
#endif
-module Cmm
- ( CmmGraph, GenCmmGraph(..), CmmBlock
- , CmmStackInfo(..), CmmTopInfo(..), Cmm, CmmTop
- , CmmReplGraph, GenCmmReplGraph, CmmFwdRewrite, CmmBwdRewrite
-
- , modifyGraph
- , lastNode, replaceLastNode, insertBetween
- , ofBlockMap, toBlockMap, insertBlock
- , ofBlockList, toBlockList, bodyToBlockList
- , foldGraphBlocks, mapGraphNodes, postorderDfs
-
- , analFwd, analBwd, analRewFwd, analRewBwd
- , dataflowPassFwd, dataflowPassBwd
- , module CmmNode
- )
-where
-
+module Cmm (
+ -- * Cmm top-level datatypes
+ CmmPgm, GenCmmPgm,
+ CmmTop, GenCmmTop(..),
+ CmmGraph, GenCmmGraph(..),
+ CmmBlock,
+ Section(..), CmmStatics(..), CmmStatic(..),
+
+ -- * Cmm graphs
+ CmmReplGraph, GenCmmReplGraph, CmmFwdRewrite, CmmBwdRewrite,
+
+ -- * Info Tables
+ CmmTopInfo(..), CmmStackInfo(..), CmmInfoTable(..),
+ ClosureTypeInfo(..),
+ C_SRT(..), needsSRT,
+ ProfilingInfo(..), ConstrDescription,
+
+ -- * Statements, expressions and types
+ module CmmNode,
+ module CmmExpr,
+ ) where
+
+import CLabel
import BlockId
-import CmmDecl
import CmmNode
import OptimizationFuel as F
import SMRep
-import UniqSupply
-
+import CmmExpr
import Compiler.Hoopl
-import Control.Monad
-import Data.Maybe
-import Panic
+
+import Data.Word ( Word8 )
#include "HsVersions.h"
--------------------------------------------------
--- CmmBlock, CmmGraph and Cmm
+-----------------------------------------------------------------------------
+-- Cmm, GenCmm
+-----------------------------------------------------------------------------
+
+-- A file is a list of top-level chunks. These may be arbitrarily
+-- re-orderd during code generation.
+
+-- GenCmm is abstracted over
+-- d, the type of static data elements in CmmData
+-- h, the static info preceding the code of a CmmProc
+-- g, the control-flow graph of a CmmProc
+--
+-- We expect there to be two main instances of this type:
+-- (a) C--, i.e. populated with various C-- constructs
+-- (Cmm and RawCmm in OldCmm.hs)
+-- (b) Native code, populated with data/instructions
+--
+-- A second family of instances based on Hoopl is in Cmm.hs.
+--
+type GenCmmPgm d h g = [GenCmmTop d h g]
+
+type CmmPgm = GenCmmPgm CmmStatics CmmTopInfo CmmGraph
+
+-----------------------------------------------------------------------------
+-- CmmTop, GenCmmTop
+-----------------------------------------------------------------------------
+
+-- | A top-level chunk, abstracted over the type of the contents of
+-- the basic blocks (Cmm or instructions are the likely instantiations).
+data GenCmmTop d h g
+ = CmmProc -- A procedure
+ h -- Extra header such as the info table
+ CLabel -- Entry label
+ g -- Control-flow graph for the procedure's code
+
+ | CmmData -- Static data
+ Section
+ d
+
+type CmmTop = GenCmmTop CmmStatics CmmTopInfo CmmGraph
+
+-----------------------------------------------------------------------------
+-- Graphs
+-----------------------------------------------------------------------------
type CmmGraph = GenCmmGraph CmmNode
data GenCmmGraph n = CmmGraph { g_entry :: BlockId, g_graph :: Graph n C C }
@@ -51,131 +96,66 @@ type GenCmmReplGraph n e x = FuelUniqSM (Maybe (Graph n e x))
type CmmFwdRewrite f = FwdRewrite FuelUniqSM CmmNode f
type CmmBwdRewrite f = BwdRewrite FuelUniqSM CmmNode f
-data CmmStackInfo = StackInfo {arg_space :: ByteOff, updfr_space :: Maybe ByteOff}
+-----------------------------------------------------------------------------
+-- Info Tables
+-----------------------------------------------------------------------------
+
data CmmTopInfo = TopInfo {info_tbl :: CmmInfoTable, stack_info :: CmmStackInfo}
-type Cmm = GenCmm CmmStatics CmmTopInfo CmmGraph
-type CmmTop = GenCmmTop CmmStatics CmmTopInfo CmmGraph
-
--------------------------------------------------
--- Manipulating CmmGraphs
-
-modifyGraph :: (Graph n C C -> Graph n' C C) -> GenCmmGraph n -> GenCmmGraph n'
-modifyGraph f g = CmmGraph {g_entry=g_entry g, g_graph=f (g_graph g)}
-
-toBlockMap :: CmmGraph -> LabelMap CmmBlock
-toBlockMap (CmmGraph {g_graph=GMany NothingO body NothingO}) = body
-
-ofBlockMap :: BlockId -> LabelMap CmmBlock -> CmmGraph
-ofBlockMap entry bodyMap = CmmGraph {g_entry=entry, g_graph=GMany NothingO bodyMap NothingO}
-
-insertBlock :: CmmBlock -> LabelMap CmmBlock -> LabelMap CmmBlock
-insertBlock block map =
- ASSERT (isNothing $ mapLookup id map)
- mapInsert id block map
- where id = entryLabel block
-
-toBlockList :: CmmGraph -> [CmmBlock]
-toBlockList g = mapElems $ toBlockMap g
-
-ofBlockList :: BlockId -> [CmmBlock] -> CmmGraph
-ofBlockList entry blocks = CmmGraph {g_entry=entry, g_graph=GMany NothingO body NothingO}
- where body = foldr addBlock emptyBody blocks
-
-bodyToBlockList :: Body CmmNode -> [CmmBlock]
-bodyToBlockList body = mapElems body
-
-mapGraphNodes :: ( CmmNode C O -> CmmNode C O
- , CmmNode O O -> CmmNode O O
- , CmmNode O C -> CmmNode O C)
- -> CmmGraph -> CmmGraph
-mapGraphNodes funs@(mf,_,_) g =
- ofBlockMap (entryLabel $ mf $ CmmEntry $ g_entry g) $ mapMap (blockMapNodes3 funs) $ toBlockMap g
-
-foldGraphBlocks :: (CmmBlock -> a -> a) -> a -> CmmGraph -> a
-foldGraphBlocks k z g = mapFold k z $ toBlockMap g
-
-postorderDfs :: CmmGraph -> [CmmBlock]
-postorderDfs g = postorder_dfs_from (toBlockMap g) (g_entry g)
-
--------------------------------------------------
--- Manipulating CmmBlocks
-
-lastNode :: CmmBlock -> CmmNode O C
-lastNode block = foldBlockNodesF3 (nothing, nothing, const) block ()
- where nothing :: a -> b -> ()
- nothing _ _ = ()
-
-replaceLastNode :: Block CmmNode e C -> CmmNode O C -> Block CmmNode e C
-replaceLastNode block last = blockOfNodeList (first, middle, JustC last)
- where (first, middle, _) = blockToNodeList block
-
-----------------------------------------------------------------------
------ Splicing between blocks
--- Given a middle node, a block, and a successor BlockId,
--- we can insert the middle node between the block and the successor.
--- We return the updated block and a list of new blocks that must be added
--- to the graph.
--- The semantics is a bit tricky. We consider cases on the last node:
--- o For a branch, we can just insert before the branch,
--- but sometimes the optimizer does better if we actually insert
--- a fresh basic block, enabling some common blockification.
--- o For a conditional branch, switch statement, or call, we must insert
--- a new basic block.
--- o For a jump or return, this operation is impossible.
-
-insertBetween :: MonadUnique m => CmmBlock -> [CmmNode O O] -> BlockId -> m (CmmBlock, [CmmBlock])
-insertBetween b ms succId = insert $ lastNode b
- where insert :: MonadUnique m => CmmNode O C -> m (CmmBlock, [CmmBlock])
- insert (CmmBranch bid) =
- if bid == succId then
- do (bid', bs) <- newBlocks
- return (replaceLastNode b (CmmBranch bid'), bs)
- else panic "tried invalid block insertBetween"
- insert (CmmCondBranch c t f) =
- do (t', tbs) <- if t == succId then newBlocks else return $ (t, [])
- (f', fbs) <- if f == succId then newBlocks else return $ (f, [])
- return (replaceLastNode b (CmmCondBranch c t' f'), tbs ++ fbs)
- insert (CmmSwitch e ks) =
- do (ids, bs) <- mapAndUnzipM mbNewBlocks ks
- return (replaceLastNode b (CmmSwitch e ids), join bs)
- insert (CmmCall {}) =
- panic "unimp: insertBetween after a call -- probably not a good idea"
- insert (CmmForeignCall {}) =
- panic "unimp: insertBetween after a foreign call -- probably not a good idea"
-
- newBlocks :: MonadUnique m => m (BlockId, [CmmBlock])
- newBlocks = do id <- liftM mkBlockId $ getUniqueM
- return $ (id, [blockOfNodeList (JustC (CmmEntry id), ms, JustC (CmmBranch succId))])
- mbNewBlocks :: MonadUnique m => Maybe BlockId -> m (Maybe BlockId, [CmmBlock])
- mbNewBlocks (Just k) = if k == succId then liftM fstJust newBlocks
- else return (Just k, [])
- mbNewBlocks Nothing = return (Nothing, [])
- fstJust (id, bs) = (Just id, bs)
-
--------------------------------------------------
--- Running dataflow analysis and/or rewrites
-
--- Constructing forward and backward analysis-only pass
-analFwd :: Monad m => DataflowLattice f -> FwdTransfer n f -> FwdPass m n f
-analBwd :: Monad m => DataflowLattice f -> BwdTransfer n f -> BwdPass m n f
-
-analFwd lat xfer = analRewFwd lat xfer noFwdRewrite
-analBwd lat xfer = analRewBwd lat xfer noBwdRewrite
-
--- Constructing forward and backward analysis + rewrite pass
-analRewFwd :: Monad m => DataflowLattice f -> FwdTransfer n f -> FwdRewrite m n f -> FwdPass m n f
-analRewBwd :: Monad m => DataflowLattice f -> BwdTransfer n f -> BwdRewrite m n f -> BwdPass m n f
-
-analRewFwd lat xfer rew = FwdPass {fp_lattice = lat, fp_transfer = xfer, fp_rewrite = rew}
-analRewBwd lat xfer rew = BwdPass {bp_lattice = lat, bp_transfer = xfer, bp_rewrite = rew}
-
--- Running forward and backward dataflow analysis + optional rewrite
-dataflowPassFwd :: NonLocal n => GenCmmGraph n -> [(BlockId, f)] -> FwdPass FuelUniqSM n f -> FuelUniqSM (GenCmmGraph n, BlockEnv f)
-dataflowPassFwd (CmmGraph {g_entry=entry, g_graph=graph}) facts fwd = do
- (graph, facts, NothingO) <- analyzeAndRewriteFwd fwd (JustC [entry]) graph (mkFactBase (fp_lattice fwd) facts)
- return (CmmGraph {g_entry=entry, g_graph=graph}, facts)
-
-dataflowPassBwd :: NonLocal n => GenCmmGraph n -> [(BlockId, f)] -> BwdPass FuelUniqSM n f -> FuelUniqSM (GenCmmGraph n, BlockEnv f)
-dataflowPassBwd (CmmGraph {g_entry=entry, g_graph=graph}) facts bwd = do
- (graph, facts, NothingO) <- analyzeAndRewriteBwd bwd (JustC [entry]) graph (mkFactBase (bp_lattice bwd) facts)
- return (CmmGraph {g_entry=entry, g_graph=graph}, facts)
+
+data CmmStackInfo
+ = StackInfo {
+ arg_space :: ByteOff, -- XXX: comment?
+ updfr_space :: Maybe ByteOff -- XXX: comment?
+ }
+
+-- | Info table as a haskell data type
+data CmmInfoTable
+ = CmmInfoTable {
+ cit_lbl :: CLabel, -- Info table label
+ cit_rep :: SMRep,
+ cit_prof :: ProfilingInfo,
+ cit_srt :: C_SRT
+ }
+ | CmmNonInfoTable -- Procedure doesn't need an info table
+
+data ProfilingInfo
+ = NoProfilingInfo
+ | ProfilingInfo [Word8] [Word8] -- closure_type, closure_desc
+
+-- C_SRT is what StgSyn.SRT gets translated to...
+-- we add a label for the table, and expect only the 'offset/length' form
+
+data C_SRT = NoC_SRT
+ | C_SRT !CLabel !WordOff !StgHalfWord {-bitmap or escape-}
+ deriving (Eq)
+
+needsSRT :: C_SRT -> Bool
+needsSRT NoC_SRT = False
+needsSRT (C_SRT _ _ _) = True
+
+-----------------------------------------------------------------------------
+-- Static Data
+-----------------------------------------------------------------------------
+
+data Section
+ = Text
+ | Data
+ | ReadOnlyData
+ | RelocatableReadOnlyData
+ | UninitialisedData
+ | ReadOnlyData16 -- .rodata.cst16 on x86_64, 16-byte aligned
+ | OtherSection String
+
+data CmmStatic
+ = CmmStaticLit CmmLit
+ -- a literal value, size given by cmmLitRep of the literal.
+ | CmmUninitialised Int
+ -- uninitialised data, N bytes long
+ | CmmString [Word8]
+ -- string of 8-bit values only, not zero terminated.
+
+data CmmStatics
+ = Statics
+ CLabel -- Label of statics
+ [CmmStatic] -- The static data itself
+
diff --git a/compiler/cmm/CmmBuildInfoTables.hs b/compiler/cmm/CmmBuildInfoTables.hs
index e74e502727..baf4f8dac3 100644
--- a/compiler/cmm/CmmBuildInfoTables.hs
+++ b/compiler/cmm/CmmBuildInfoTables.hs
@@ -11,11 +11,16 @@ module CmmBuildInfoTables
, TopSRT, emptySRT, srtToData
, bundleCAFs
, lowerSafeForeignCalls
- , cafTransfers, liveSlotTransfers)
+ , cafTransfers, liveSlotTransfers
+ , mkLiveness )
where
#include "HsVersions.h"
+-- These should not be imported here!
+import StgCmmForeign
+import StgCmmUtils
+
import Constants
import Digraph
import qualified Prelude as P
@@ -26,8 +31,7 @@ import BlockId
import Bitmap
import CLabel
import Cmm
-import CmmDecl
-import CmmExpr
+import CmmUtils
import CmmStackLayout
import Module
import FastString
@@ -41,9 +45,6 @@ import Name
import OptimizationFuel
import Outputable
import SMRep
-import StgCmmClosure
-import StgCmmForeign
-import StgCmmUtils
import UniqSupply
import Compiler.Hoopl
@@ -87,13 +88,14 @@ type RegSlotInfo
, LocalReg -- The register
, Int) -- Width of the register
-live_ptrs :: ByteOff -> BlockEnv SubAreaSet -> AreaMap -> BlockId -> [Maybe LocalReg]
+live_ptrs :: ByteOff -> BlockEnv SubAreaSet -> AreaMap -> BlockId -> StackLayout
live_ptrs oldByte slotEnv areaMap bid =
-- pprTrace "live_ptrs for" (ppr bid <+> text (show oldByte ++ "-" ++ show youngByte) <+>
-- ppr liveSlots) $
-- pprTrace ("stack layout for " ++ show bid ++ ": ") (ppr res) $ res
res
- where res = reverse $ slotsToList youngByte liveSlots []
+ where
+ res = mkLiveness (reverse $ slotsToList youngByte liveSlots [])
slotsToList :: Int -> [RegSlotInfo] -> [Maybe LocalReg] -> [Maybe LocalReg]
-- n starts at youngByte and is decremented down to oldByte
@@ -160,8 +162,9 @@ live_ptrs oldByte slotEnv areaMap bid =
-- is not the successor of a call.
setInfoTableStackMap :: SlotEnv -> AreaMap -> CmmTop -> CmmTop
setInfoTableStackMap slotEnv areaMap
- t@(CmmProc (TopInfo {stack_info=StackInfo {updfr_space = Just updfr_off}}) _ (CmmGraph {g_entry = eid})) =
- updInfo (const (live_ptrs updfr_off slotEnv areaMap eid)) id t
+ t@(CmmProc (TopInfo {stack_info=StackInfo {updfr_space = Just updfr_off}}) _
+ (CmmGraph {g_entry = eid}))
+ = updInfo (const (live_ptrs updfr_off slotEnv areaMap eid)) id t
setInfoTableStackMap _ _ t = t
@@ -237,8 +240,8 @@ addCAF caf srt =
, elt_map = Map.insert caf last (elt_map srt) }
where last = next_elt srt
-srtToData :: TopSRT -> Cmm
-srtToData srt = Cmm [CmmData RelocatableReadOnlyData (Statics (lbl srt) tbl)]
+srtToData :: TopSRT -> CmmPgm
+srtToData srt = [CmmData RelocatableReadOnlyData (Statics (lbl srt) tbl)]
where tbl = map (CmmStaticLit . CmmLabel) (reverse (rev_elts srt))
-- Once we have found the CAFs, we need to do two things:
@@ -336,9 +339,10 @@ localCAFInfo :: CAFEnv -> CmmTop -> Maybe (CLabel, CAFSet)
localCAFInfo _ (CmmData _ _) = Nothing
localCAFInfo cafEnv (CmmProc top_info top_l (CmmGraph {g_entry=entry})) =
case info_tbl top_info of
- CmmInfoTable _ False _ _ _ ->
- Just (cvtToClosureLbl top_l,
- expectJust "maybeBindCAFs" $ mapLookup entry cafEnv)
+ CmmInfoTable { cit_rep = rep }
+ | not (isStaticRep rep)
+ -> Just (cvtToClosureLbl top_l,
+ expectJust "maybeBindCAFs" $ mapLookup entry cafEnv)
_ -> Nothing
-- Once we have the local CAF sets for some (possibly) mutually
@@ -368,8 +372,6 @@ mkTopCAFInfo localCAFs = foldl addToTop Map.empty g
g = stronglyConnCompFromEdgedVertices
(map (\n@(l, cafs) -> (n, l, Map.keys cafs)) localCAFs)
-type StackLayout = [Maybe LocalReg]
-
-- Bundle the CAFs used at a procpoint.
bundleCAFs :: CAFEnv -> CmmTop -> (CAFSet, CmmTop)
bundleCAFs cafEnv t@(CmmProc _ _ (CmmGraph {g_entry=entry})) =
@@ -391,20 +393,19 @@ setSRT cafs topCAFMap topSRT t =
Just tbl -> return (topSRT, [t', tbl])
Nothing -> return (topSRT, [t'])
+type StackLayout = Liveness
+
updInfo :: (StackLayout -> StackLayout) -> (C_SRT -> C_SRT) -> CmmTop -> CmmTop
updInfo toVars toSrt (CmmProc top_info top_l g) =
CmmProc (top_info {info_tbl=updInfoTbl toVars toSrt (info_tbl top_info)}) top_l g
updInfo _ _ t = t
updInfoTbl :: (StackLayout -> StackLayout) -> (C_SRT -> C_SRT) -> CmmInfoTable -> CmmInfoTable
-updInfoTbl toVars toSrt (CmmInfoTable l s p t typeinfo)
- = CmmInfoTable l s p t typeinfo'
- where typeinfo' = case typeinfo of
- t@(ConstrInfo _ _ _) -> t
- (FunInfo c s a d e) -> FunInfo c (toSrt s) a d e
- (ThunkInfo c s) -> ThunkInfo c (toSrt s)
- (ThunkSelectorInfo x s) -> ThunkSelectorInfo x (toSrt s)
- (ContInfo v s) -> ContInfo (toVars v) (toSrt s)
+updInfoTbl toVars toSrt info_tbl@(CmmInfoTable {})
+ = info_tbl { cit_srt = toSrt (cit_srt info_tbl)
+ , cit_rep = case cit_rep info_tbl of
+ StackRep ls -> StackRep (toVars ls)
+ other -> other }
updInfoTbl _ _ t@CmmNonInfoTable = t
----------------------------------------------------------------
@@ -493,3 +494,4 @@ lowerSafeForeignCall entry areaMap blocks bid m
resume <**> saveRetVals <**> M.mkLast jump
return $ blocks `mapUnion` toBlockMap graph'
lowerSafeForeignCall _ _ _ _ _ _ = panic "lowerSafeForeignCall was passed something else"
+
diff --git a/compiler/cmm/CmmCommonBlockElim.hs b/compiler/cmm/CmmCommonBlockElim.hs
index c0761fce6a..af60815c6e 100644
--- a/compiler/cmm/CmmCommonBlockElim.hs
+++ b/compiler/cmm/CmmCommonBlockElim.hs
@@ -11,7 +11,7 @@ where
import BlockId
import Cmm
-import CmmExpr
+import CmmUtils
import Prelude hiding (iterate, succ, unzip, zip)
import Compiler.Hoopl
diff --git a/compiler/cmm/CmmContFlowOpt.hs b/compiler/cmm/CmmContFlowOpt.hs
index 42fc239e28..a04b3a43e1 100644
--- a/compiler/cmm/CmmContFlowOpt.hs
+++ b/compiler/cmm/CmmContFlowOpt.hs
@@ -10,8 +10,7 @@ where
import BlockId
import Cmm
-import CmmDecl
-import CmmExpr
+import CmmUtils
import qualified OldCmm as Old
import Maybes
@@ -22,7 +21,7 @@ import Prelude hiding (succ, unzip, zip)
import Util
------------------------------------
-runCmmContFlowOpts :: Cmm -> Cmm
+runCmmContFlowOpts :: CmmPgm -> CmmPgm
runCmmContFlowOpts prog = runCmmOpts cmmCfgOpts prog
oldCmmCfgOpts :: Old.ListGraph Old.CmmStmt -> Old.ListGraph Old.CmmStmt
@@ -34,18 +33,14 @@ cmmCfgOpts =
-- Here branchChainElim can ultimately be replaced
-- with a more exciting combination of optimisations
-runCmmOpts :: (g -> g) -> GenCmm d h g -> GenCmm d h g
+runCmmOpts :: (g -> g) -> GenCmmPgm d h g -> GenCmmPgm d h g
-- Lifts a transformer on a single graph to one on the whole program
-runCmmOpts opt = mapProcs (optProc opt)
+runCmmOpts opt = map (optProc opt)
optProc :: (g -> g) -> GenCmmTop d h g -> GenCmmTop d h g
optProc _ top@(CmmData {}) = top
optProc opt (CmmProc info lbl g) = CmmProc info lbl (opt g)
-------------------------------------
-mapProcs :: (GenCmmTop d h s -> GenCmmTop d h s) -> GenCmm d h s -> GenCmm d h s
-mapProcs f (Cmm tops) = Cmm (map f tops)
-
----------------------------------------------------------------
oldBranchChainElim :: Old.ListGraph Old.CmmStmt -> Old.ListGraph Old.CmmStmt
-- If L is not captured in an instruction, we can remove any
diff --git a/compiler/cmm/CmmCvt.hs b/compiler/cmm/CmmCvt.hs
index fcb220d74c..c0f715d211 100644
--- a/compiler/cmm/CmmCvt.hs
+++ b/compiler/cmm/CmmCvt.hs
@@ -3,91 +3,25 @@
{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}
module CmmCvt
- ( cmmToZgraph, cmmOfZgraph )
+ ( cmmOfZgraph )
where
import BlockId
import Cmm
-import CmmDecl
-import CmmExpr
-import MkGraph
+import CmmUtils
import qualified OldCmm as Old
import OldPprCmm ()
-import Platform
import Compiler.Hoopl hiding ((<*>), mkLabel, mkBranch)
-import Control.Monad
import Data.Maybe
import Maybes
import Outputable
-import UniqSupply
-cmmToZgraph :: Platform -> Old.Cmm -> UniqSM Cmm
-cmmOfZgraph :: Cmm -> Old.Cmm
-
-cmmToZgraph platform (Cmm tops) = liftM Cmm $ mapM mapTop tops
- where mapTop (CmmProc (Old.CmmInfo _ _ info_tbl) l g) =
- do (stack_info, g) <- toZgraph platform (showSDoc $ ppr l) g
- return $ CmmProc (TopInfo {info_tbl=info_tbl, stack_info=stack_info}) l g
- mapTop (CmmData s ds) = return $ CmmData s ds
-cmmOfZgraph (Cmm tops) = Cmm $ map mapTop tops
+cmmOfZgraph :: CmmPgm -> Old.CmmPgm
+cmmOfZgraph tops = map mapTop tops
where mapTop (CmmProc h l g) = CmmProc (Old.CmmInfo Nothing Nothing (info_tbl h)) l (ofZgraph g)
mapTop (CmmData s ds) = CmmData s ds
-toZgraph :: Platform -> String -> Old.ListGraph Old.CmmStmt -> UniqSM (CmmStackInfo, CmmGraph)
-toZgraph _ _ (Old.ListGraph []) =
- do g <- lgraphOfAGraph emptyAGraph
- return (StackInfo {arg_space=0, updfr_space=Nothing}, g)
-toZgraph platform fun_name g@(Old.ListGraph (Old.BasicBlock id ss : other_blocks)) =
- let (offset, entry) = mkCallEntry NativeNodeCall [] in
- do g <- labelAGraph id $
- entry <*> mkStmts ss <*> foldr addBlock emptyAGraph other_blocks
- return (StackInfo {arg_space = offset, updfr_space = Nothing}, g)
- where addBlock (Old.BasicBlock id ss) g =
- mkLabel id <*> mkStmts ss <*> g
- updfr_sz = 0 -- panic "upd frame size lost in cmm conversion"
- mkStmts (Old.CmmNop : ss) = mkNop <*> mkStmts ss
- mkStmts (Old.CmmComment s : ss) = mkComment s <*> mkStmts ss
- mkStmts (Old.CmmAssign l r : ss) = mkAssign l r <*> mkStmts ss
- mkStmts (Old.CmmStore l r : ss) = mkStore l r <*> mkStmts ss
- mkStmts (Old.CmmCall (Old.CmmCallee f conv) res args (Old.CmmSafe _) Old.CmmMayReturn : ss) =
- mkCall f (conv', conv') (map Old.hintlessCmm res) (map Old.hintlessCmm args) updfr_sz
- <*> mkStmts ss
- where conv' = Foreign (ForeignConvention conv [] []) -- JD: DUBIOUS
- mkStmts (Old.CmmCall (Old.CmmPrim {}) _ _ (Old.CmmSafe _) _ : _) =
- panic "safe call to a primitive CmmPrim CallishMachOp"
- mkStmts (Old.CmmCall f res args Old.CmmUnsafe Old.CmmMayReturn : ss) =
- mkUnsafeCall (convert_target f res args)
- (strip_hints res) (strip_hints args)
- <*> mkStmts ss
- mkStmts (Old.CmmCondBranch e l : fbranch) =
- mkCmmIfThenElse e (mkBranch l) (mkStmts fbranch)
- mkStmts (last : []) = mkLast last
- mkStmts [] = bad "fell off end"
- mkStmts (_ : _ : _) = bad "last node not at end"
- bad msg = pprPanic (msg ++ " in function " ++ fun_name) (pprPlatform platform g)
- mkLast (Old.CmmCall (Old.CmmCallee f conv) [] args _ Old.CmmNeverReturns) =
- mkFinalCall f conv (map Old.hintlessCmm args) updfr_sz
- mkLast (Old.CmmCall (Old.CmmPrim {}) _ _ _ Old.CmmNeverReturns) =
- panic "Call to CmmPrim never returns?!"
- mkLast (Old.CmmSwitch scrutinee table) = mkSwitch scrutinee table
- -- SURELY, THESE HINTLESS ARGS ARE WRONG AND WILL BE FIXED WHEN CALLING
- -- CONVENTIONS ARE HONORED?
- mkLast (Old.CmmJump tgt args) = mkJump tgt (map Old.hintlessCmm args) updfr_sz
- mkLast (Old.CmmReturn ress) =
- mkReturnSimple (map Old.hintlessCmm ress) updfr_sz
- mkLast (Old.CmmBranch tgt) = mkBranch tgt
- mkLast (Old.CmmCall _f (_:_) _args _ Old.CmmNeverReturns) =
- panic "Call never returns but has results?!"
- mkLast _ = panic "fell off end of block"
-
-strip_hints :: [Old.CmmHinted a] -> [a]
-strip_hints = map Old.hintlessCmm
-
-convert_target :: Old.CmmCallTarget -> [Old.HintedCmmFormal] -> [Old.HintedCmmActual] -> ForeignTarget
-convert_target (Old.CmmCallee e cc) ress args = ForeignTarget e (ForeignConvention cc (map Old.cmmHint args) (map Old.cmmHint ress))
-convert_target (Old.CmmPrim op) _ress _args = PrimTarget op
-
data ValueDirection = Arguments | Results
add_hints :: Convention -> ValueDirection -> [a] -> [Old.CmmHinted a]
diff --git a/compiler/cmm/CmmDecl.hs b/compiler/cmm/CmmDecl.hs
deleted file mode 100644
index 552878e7bb..0000000000
--- a/compiler/cmm/CmmDecl.hs
+++ /dev/null
@@ -1,139 +0,0 @@
------------------------------------------------------------------------------
---
--- Cmm data types
---
--- (c) The University of Glasgow 2004-2006
---
------------------------------------------------------------------------------
-
-module CmmDecl (
- GenCmm(..), GenCmmTop(..),
- CmmInfoTable(..), HasStaticClosure, ClosureTypeInfo(..), ConstrDescription,
- ProfilingInfo(..), ClosureTypeTag,
- CmmActual, CmmFormal, ForeignHint(..),
- CmmStatics(..), CmmStatic(..), Section(..),
- ) where
-
-#include "HsVersions.h"
-
-import CmmExpr
-import CLabel
-import SMRep
-import ClosureInfo
-
-import Data.Word
-
-
--- A [[BlockId]] is a local label.
--- Local labels must be unique within an entire compilation unit, not
--- just a single top-level item, because local labels map one-to-one
--- with assembly-language labels.
-
------------------------------------------------------------------------------
--- GenCmm, GenCmmTop
------------------------------------------------------------------------------
-
--- A file is a list of top-level chunks. These may be arbitrarily
--- re-orderd during code generation.
-
--- GenCmm is abstracted over
--- d, the type of static data elements in CmmData
--- h, the static info preceding the code of a CmmProc
--- g, the control-flow graph of a CmmProc
---
--- We expect there to be two main instances of this type:
--- (a) C--, i.e. populated with various C-- constructs
--- (Cmm and RawCmm in OldCmm.hs)
--- (b) Native code, populated with data/instructions
---
--- A second family of instances based on Hoopl is in Cmm.hs.
---
-newtype GenCmm d h g = Cmm [GenCmmTop d h g]
-
--- | A top-level chunk, abstracted over the type of the contents of
--- the basic blocks (Cmm or instructions are the likely instantiations).
-data GenCmmTop d h g
- = CmmProc -- A procedure
- h -- Extra header such as the info table
- CLabel -- Entry label
- g -- Control-flow graph for the procedure's code
-
- | CmmData -- Static data
- Section
- d
-
-
------------------------------------------------------------------------------
--- Info Tables
------------------------------------------------------------------------------
-
--- Info table as a haskell data type
-data CmmInfoTable
- = CmmInfoTable
- CLabel -- Info table label
- HasStaticClosure
- ProfilingInfo
- ClosureTypeTag -- Int
- ClosureTypeInfo
- | CmmNonInfoTable -- Procedure doesn't need an info table
-
-type HasStaticClosure = Bool
-
--- TODO: The GC target shouldn't really be part of CmmInfo
--- as it doesn't appear in the resulting info table.
--- It should be factored out.
-
-data ClosureTypeInfo
- = ConstrInfo ClosureLayout ConstrTag ConstrDescription
- | FunInfo ClosureLayout C_SRT FunArity ArgDescr SlowEntry
- | ThunkInfo ClosureLayout C_SRT
- | ThunkSelectorInfo SelectorOffset C_SRT
- | ContInfo
- [Maybe LocalReg] -- Stack layout: Just x, an item x
- -- Nothing: a 1-word gap
- -- Start of list is the *young* end
- C_SRT
-
--- TODO: These types may need refinement
-data ProfilingInfo = ProfilingInfo CmmLit CmmLit -- closure_type, closure_desc
-type ClosureTypeTag = StgHalfWord
-type ClosureLayout = (StgHalfWord, StgHalfWord) -- ptrs, nptrs
-type ConstrTag = StgHalfWord
-type ConstrDescription = CmmLit
-type FunArity = StgHalfWord
-type SlowEntry = CmmLit
- -- We would like this to be a CLabel but
- -- for now the parser sets this to zero on an INFO_TABLE_FUN.
-type SelectorOffset = StgWord
-
-type CmmActual = CmmExpr
-type CmmFormal = LocalReg
-
-data ForeignHint
- = NoHint | AddrHint | SignedHint
- deriving( Eq )
- -- Used to give extra per-argument or per-result
- -- information needed by foreign calling conventions
-
------------------------------------------------------------------------------
--- Static Data
------------------------------------------------------------------------------
-
-data Section
- = Text
- | Data
- | ReadOnlyData
- | RelocatableReadOnlyData
- | UninitialisedData
- | ReadOnlyData16 -- .rodata.cst16 on x86_64, 16-byte aligned
- | OtherSection String
-
-data CmmStatic
- = CmmStaticLit CmmLit
- -- a literal value, size given by cmmLitRep of the literal.
- | CmmUninitialised Int
- -- uninitialised data, N bytes long
- | CmmString [Word8]
- -- string of 8-bit values only, not zero terminated.
-
-data CmmStatics = Statics CLabel {- Label of statics -} [CmmStatic] {- The static data itself -}
diff --git a/compiler/cmm/CmmInfo.hs b/compiler/cmm/CmmInfo.hs
index e463b3619f..4e2d976826 100644
--- a/compiler/cmm/CmmInfo.hs
+++ b/compiler/cmm/CmmInfo.hs
@@ -6,39 +6,34 @@ module CmmInfo (
#include "HsVersions.h"
-import OldCmm
-import CmmUtils
+import OldCmm as Old
+import CmmUtils
import CLabel
-
-import Bitmap
-import ClosureInfo
-import CgInfoTbls
-import CgCallConv
-import CgUtils
import SMRep
+import Bitmap
+import Maybes
import Constants
import Panic
import StaticFlags
-import Unique
import UniqSupply
-
+import MonadUtils
import Data.Bits
+import Data.Word
-- When we split at proc points, we need an empty info table.
mkEmptyContInfoTable :: CLabel -> CmmInfoTable
-mkEmptyContInfoTable info_lbl = CmmInfoTable info_lbl False (ProfilingInfo zero zero) rET_SMALL
- (ContInfo [] NoC_SRT)
- where zero = CmmInt 0 wordWidth
-
-cmmToRawCmm :: [Cmm] -> IO [RawCmm]
-cmmToRawCmm cmm = do
- info_tbl_uniques <- mkSplitUniqSupply 'i'
- return $ zipWith raw_cmm (listSplitUniqSupply info_tbl_uniques) cmm
- where
- raw_cmm uniq_supply (Cmm procs) =
- Cmm $ concat $ zipWith mkInfoTable (uniqsFromSupply uniq_supply) procs
+mkEmptyContInfoTable info_lbl
+ = CmmInfoTable { cit_lbl = info_lbl
+ , cit_rep = mkStackRep []
+ , cit_prof = NoProfilingInfo
+ , cit_srt = NoC_SRT }
+
+cmmToRawCmm :: [Old.CmmPgm] -> IO [Old.RawCmmPgm]
+cmmToRawCmm cmms
+ = do { uniqs <- mkSplitUniqSupply 'i'
+ ; return (initUs_ uniqs (mapM (concatMapM mkInfoTable) cmms)) }
-- Make a concrete info table, represented as a list of CmmStatic
-- (it can't be simply a list of Word, because the SRT field is
@@ -73,105 +68,165 @@ cmmToRawCmm cmm = do
--
-- * The SRT slot is only there if there is SRT info to record
-mkInfoTable :: Unique -> CmmTop -> [RawCmmTop]
-mkInfoTable _ (CmmData sec dat) = [CmmData sec dat]
-mkInfoTable uniq (CmmProc (CmmInfo _ _ info) entry_label blocks) =
- case info of
- -- Code without an info table. Easy.
- CmmNonInfoTable -> [CmmProc Nothing entry_label blocks]
-
- CmmInfoTable info_label _ (ProfilingInfo ty_prof cl_prof) type_tag type_info ->
- let ty_prof' = makeRelativeRefTo info_label ty_prof
- cl_prof' = makeRelativeRefTo info_label cl_prof
- in case type_info of
- -- A function entry point.
- FunInfo (ptrs, nptrs) srt fun_arity pap_bitmap slow_entry ->
- mkInfoTableAndCode info_label std_info fun_extra_bits entry_label
- blocks
- where
- fun_type = argDescrType pap_bitmap
- fun_extra_bits =
- [packHalfWordsCLit fun_type fun_arity] ++
- case pap_bitmap of
- ArgGen liveness ->
- (if null srt_label then [mkIntCLit 0] else srt_label) ++
- [makeRelativeRefTo info_label $ mkLivenessCLit liveness,
- makeRelativeRefTo info_label slow_entry]
- _ -> srt_label
- std_info = mkStdInfoTable ty_prof' cl_prof' type_tag srt_bitmap
- layout
- (srt_label, srt_bitmap) = mkSRTLit info_label srt
- layout = packHalfWordsCLit ptrs nptrs
-
- -- A constructor.
- ConstrInfo (ptrs, nptrs) con_tag descr ->
- mkInfoTableAndCode info_label std_info [con_name] entry_label
- blocks
- where
- std_info = mkStdInfoTable ty_prof' cl_prof' type_tag con_tag layout
- con_name = makeRelativeRefTo info_label descr
- layout = packHalfWordsCLit ptrs nptrs
- -- A thunk.
- ThunkInfo (ptrs, nptrs) srt ->
- mkInfoTableAndCode info_label std_info srt_label entry_label
- blocks
- where
- std_info = mkStdInfoTable ty_prof' cl_prof' type_tag srt_bitmap layout
- (srt_label, srt_bitmap) = mkSRTLit info_label srt
- layout = packHalfWordsCLit ptrs nptrs
-
- -- A selector thunk.
- ThunkSelectorInfo offset _srt ->
- mkInfoTableAndCode info_label std_info [{- no SRT -}] entry_label
- blocks
- where
- std_info = mkStdInfoTable ty_prof' cl_prof' type_tag 0 (mkWordCLit offset)
-
- -- A continuation/return-point.
- ContInfo stack_layout srt ->
- liveness_data ++
- mkInfoTableAndCode info_label std_info srt_label entry_label
- blocks
- where
- std_info = mkStdInfoTable ty_prof' cl_prof' maybe_big_type_tag srt_bitmap
- (makeRelativeRefTo info_label liveness_lit)
- (liveness_lit, liveness_data, liveness_tag) =
- mkLiveness uniq stack_layout
- maybe_big_type_tag = if type_tag == rET_SMALL
- then liveness_tag
- else type_tag
- (srt_label, srt_bitmap) = mkSRTLit info_label srt
-
--- Handle the differences between tables-next-to-code
--- and not tables-next-to-code
-mkInfoTableAndCode :: CLabel
- -> [CmmLit]
- -> [CmmLit]
- -> CLabel
- -> ListGraph CmmStmt
+mkInfoTable :: CmmTop -> UniqSM [RawCmmTop]
+mkInfoTable (CmmData sec dat)
+ = return [CmmData sec dat]
+
+mkInfoTable (CmmProc (CmmInfo _ _ info) entry_label blocks)
+ | CmmNonInfoTable <- info -- Code without an info table. Easy.
+ = return [CmmProc Nothing entry_label blocks]
+
+ | CmmInfoTable { cit_lbl = info_lbl } <- info
+ = do { (top_decls, info_cts) <- mkInfoTableContents info
+ ; return (top_decls ++
+ mkInfoTableAndCode info_lbl info_cts
+ entry_label blocks) }
+ | otherwise = panic "mkInfoTable" -- Patern match overlap check not clever enough
+
+-----------------------------------------------------
+type InfoTableContents = ( [CmmLit] -- The standard part
+ , [CmmLit] ) -- The "extra bits"
+-- These Lits have *not* had mkRelativeTo applied to them
+
+mkInfoTableContents :: CmmInfoTable
+ -> UniqSM ([RawCmmTop], -- Auxiliary top decls
+ InfoTableContents) -- Info tbl + extra bits
+mkInfoTableContents (CmmInfoTable { cit_lbl = info_lbl
+ , cit_rep = smrep
+ , cit_prof = prof, cit_srt = srt })
+ | StackRep frame <- smrep
+ = do { (prof_lits, prof_data) <- mkProfLits prof
+ ; (liveness_lit, liveness_data) <- mkLivenessBits frame
+ ; let (extra_bits, srt_bitmap) = mkSRTLit srt
+ std_info = mkStdInfoTable prof_lits rts_tag srt_bitmap liveness_lit
+ rts_tag | null liveness_data = rET_SMALL -- Fits in extra_bits
+ | otherwise = rET_BIG -- Does not; extra_bits is
+ -- a label
+ ; return (prof_data ++ liveness_data, (std_info, extra_bits)) }
+
+ | HeapRep _ ptrs nonptrs closure_type <- smrep
+ = do { let rts_tag = rtsClosureType smrep
+ layout = packHalfWordsCLit ptrs nonptrs
+ (srt_label, srt_bitmap) = mkSRTLit srt
+
+ ; (prof_lits, prof_data) <- mkProfLits prof
+ ; (mb_srt_field, mb_layout, extra_bits, ct_data)
+ <- mk_pieces closure_type srt_label
+ ; let std_info = mkStdInfoTable prof_lits rts_tag
+ (mb_srt_field `orElse` srt_bitmap)
+ (mb_layout `orElse` layout)
+ ; return (prof_data ++ ct_data, (std_info, extra_bits)) }
+ where
+ mk_pieces :: ClosureTypeInfo -> [CmmLit]
+ -> UniqSM ( Maybe StgHalfWord -- Override the SRT field with this
+ , Maybe CmmLit -- Override the layout field with this
+ , [CmmLit] -- "Extra bits" for info table
+ , [RawCmmTop]) -- Auxiliary data decls
+ mk_pieces (Constr con_tag con_descr) _no_srt -- A data constructor
+ = do { (descr_lit, decl) <- newStringLit con_descr
+ ; return (Just con_tag, Nothing, [descr_lit], [decl]) }
+
+ mk_pieces Thunk srt_label
+ = return (Nothing, Nothing, srt_label, [])
+
+ mk_pieces (ThunkSelector offset) _no_srt
+ = return (Just 0, Just (mkWordCLit offset), [], [])
+ -- Layout known (one free var); we use the layout field for offset
+
+ mk_pieces (Fun arity (ArgSpec fun_type)) srt_label
+ = do { let extra_bits = packHalfWordsCLit fun_type arity : srt_label
+ ; return (Nothing, Nothing, extra_bits, []) }
+
+ mk_pieces (Fun arity (ArgGen arg_bits)) srt_label
+ = do { (liveness_lit, liveness_data) <- mkLivenessBits arg_bits
+ ; let fun_type | null liveness_data = aRG_GEN
+ | otherwise = aRG_GEN_BIG
+ extra_bits = [ packHalfWordsCLit fun_type arity
+ , srt_lit, liveness_lit, slow_entry ]
+ ; return (Nothing, Nothing, extra_bits, liveness_data) }
+ where
+ slow_entry = CmmLabel (slowEntryFromInfoLabel info_lbl)
+ srt_lit = case srt_label of
+ [] -> mkIntCLit 0
+ (lit:_rest) -> ASSERT( null _rest ) lit
+
+ mk_pieces BlackHole _ = panic "mk_pieces: BlackHole"
+
+mkInfoTableContents _ = panic "mkInfoTableContents" -- NonInfoTable dealt with earlier
+
+mkSRTLit :: C_SRT
+ -> ([CmmLit], -- srt_label, if any
+ StgHalfWord) -- srt_bitmap
+mkSRTLit NoC_SRT = ([], 0)
+mkSRTLit (C_SRT lbl off bitmap) = ([cmmLabelOffW lbl off], bitmap)
+
+
+-------------------------------------------------------------------------
+--
+-- Lay out the info table and handle relative offsets
+--
+-------------------------------------------------------------------------
+
+-- This function takes
+-- * the standard info table portion (StgInfoTable)
+-- * the "extra bits" (StgFunInfoExtraRev etc.)
+-- * the entry label
+-- * the code
+-- and lays them out in memory, producing a list of RawCmmTop
+
+-- The value of tablesNextToCode determines the relative positioning
+-- of the extra bits and the standard info table, and whether the
+-- former is reversed or not. It also decides whether pointers in the
+-- info table should be expressed as offsets relative to the info
+-- pointer or not (see "Position Independent Code" below.
+
+mkInfoTableAndCode :: CLabel -- Info table label
+ -> InfoTableContents
+ -> CLabel -- Entry label
+ -> ListGraph CmmStmt -- Entry code
-> [RawCmmTop]
-mkInfoTableAndCode info_lbl std_info extra_bits entry_lbl blocks
+mkInfoTableAndCode info_lbl (std_info, extra_bits) entry_lbl blocks
| tablesNextToCode -- Reverse the extra_bits; and emit the top-level proc
- = [CmmProc (Just (Statics info_lbl $ map CmmStaticLit (reverse extra_bits ++ std_info)))
+ = [CmmProc (Just $ Statics info_lbl $ map CmmStaticLit $
+ reverse rel_extra_bits ++ rel_std_info)
entry_lbl blocks]
| ListGraph [] <- blocks -- No code; only the info table is significant
= -- Use a zero place-holder in place of the
-- entry-label in the info table
- [mkRODataLits info_lbl (zeroCLit : std_info ++ extra_bits)]
+ [mkRODataLits info_lbl (zeroCLit : rel_std_info ++ rel_extra_bits)]
| otherwise -- Separately emit info table (with the function entry
= -- point as first entry) and the entry code
[CmmProc Nothing entry_lbl blocks,
- mkDataLits info_lbl (CmmLabel entry_lbl : std_info ++ extra_bits)]
+ mkDataLits Data info_lbl (CmmLabel entry_lbl : rel_std_info ++ rel_extra_bits)]
+ where
+ rel_std_info = map (makeRelativeRefTo info_lbl) std_info
+ rel_extra_bits = map (makeRelativeRefTo info_lbl) extra_bits
+
+-------------------------------------------------------------------------
+--
+-- Position independent code
+--
+-------------------------------------------------------------------------
+-- In order to support position independent code, we mustn't put absolute
+-- references into read-only space. Info tables in the tablesNextToCode
+-- case must be in .text, which is read-only, so we doctor the CmmLits
+-- to use relative offsets instead.
+
+-- Note that this is done even when the -fPIC flag is not specified,
+-- as we want to keep binary compatibility between PIC and non-PIC.
+
+makeRelativeRefTo :: CLabel -> CmmLit -> CmmLit
+
+makeRelativeRefTo info_lbl (CmmLabel lbl)
+ | tablesNextToCode
+ = CmmLabelDiffOff lbl info_lbl 0
+makeRelativeRefTo info_lbl (CmmLabelOff lbl off)
+ | tablesNextToCode
+ = CmmLabelDiffOff lbl info_lbl off
+makeRelativeRefTo _ lit = lit
-mkSRTLit :: CLabel
- -> C_SRT
- -> ([CmmLit], -- srt_label
- StgHalfWord) -- srt_bitmap
-mkSRTLit _ NoC_SRT = ([], 0)
-mkSRTLit info_label (C_SRT lbl off bitmap) =
- ([makeRelativeRefTo info_label (cmmLabelOffW lbl off)], bitmap)
-------------------------------------------------------------------------
--
@@ -193,50 +248,36 @@ mkSRTLit info_label (C_SRT lbl off bitmap) =
-- The head of the stack layout is the top of the stack and
-- the least-significant bit.
--- TODO: refactor to use utility functions
--- TODO: combine with CgCallConv.mkLiveness (see comment there)
-mkLiveness :: Unique
- -> [Maybe LocalReg]
- -> (CmmLit, [RawCmmTop], ClosureTypeTag)
+mkLivenessBits :: Liveness -> UniqSM (CmmLit, [RawCmmTop])
-- ^ Returns:
-- 1. The bitmap (literal value or label)
-- 2. Large bitmap CmmData if needed
- -- 3. rET_SMALL or rET_BIG
-mkLiveness uniq live =
- if length bits > mAX_SMALL_BITMAP_SIZE
- -- does not fit in one word
- then (CmmLabel big_liveness, [data_lits], rET_BIG)
- -- fits in one word
- else (mkWordCLit small_liveness, [], rET_SMALL)
- where
- mkBits [] = []
- mkBits (reg:regs) = take sizeW bits ++ mkBits regs where
- sizeW = case reg of
- Nothing -> 1
- Just r -> (widthInBytes (typeWidth (localRegType r)) + wORD_SIZE - 1)
- `quot` wORD_SIZE
- -- number of words, rounded up
- bits = repeat $ is_non_ptr reg -- True <=> Non Ptr
- is_non_ptr Nothing = True
- is_non_ptr (Just reg) = not $ isGcPtrType (localRegType reg)
+mkLivenessBits liveness
+ | n_bits > mAX_SMALL_BITMAP_SIZE -- does not fit in one word
+ = do { uniq <- getUniqueUs
+ ; let bitmap_lbl = mkBitmapLabel uniq
+ ; return (CmmLabel bitmap_lbl,
+ [mkRODataLits bitmap_lbl lits]) }
- bits :: [Bool]
- bits = mkBits live
+ | otherwise -- Fits in one word
+ = return (mkWordCLit bitmap_word, [])
+ where
+ n_bits = length liveness
bitmap :: Bitmap
- bitmap = mkBitmap bits
+ bitmap = mkBitmap liveness
small_bitmap = case bitmap of
- [] -> 0
- [b] -> b
- _ -> panic "mkLiveness"
- small_liveness =
- fromIntegral (length bits) .|. (small_bitmap `shiftL` bITMAP_BITS_SHIFT)
+ [] -> 0
+ [b] -> b
+ _ -> panic "mkLiveness"
+ bitmap_word = fromIntegral n_bits
+ .|. (small_bitmap `shiftL` bITMAP_BITS_SHIFT)
- big_liveness = mkBitmapLabel uniq
- lits = mkWordCLit (fromIntegral (length bits)) : map mkWordCLit bitmap
- data_lits = mkRODataLits big_liveness lits
+ lits = mkWordCLit (fromIntegral n_bits) : map mkWordCLit bitmap
+ -- The first word is the size. The structure must match
+ -- StgLargeBitmap in includes/rts/storage/InfoTable.h
-------------------------------------------------------------------------
--
@@ -245,20 +286,20 @@ mkLiveness uniq live =
-------------------------------------------------------------------------
-- The standard bits of an info table. This part of the info table
--- corresponds to the StgInfoTable type defined in InfoTables.h.
+-- corresponds to the StgInfoTable type defined in
+-- includes/rts/storage/InfoTables.h.
--
-- Its shape varies with ticky/profiling/tables next to code etc
-- so we can't use constant offsets from Constants
mkStdInfoTable
- :: CmmLit -- closure type descr (profiling)
- -> CmmLit -- closure descr (profiling)
- -> StgHalfWord -- closure type
+ :: (CmmLit,CmmLit) -- Closure type descr and closure descr (profiling)
+ -> StgHalfWord -- Closure RTS tag
-> StgHalfWord -- SRT length
-> CmmLit -- layout field
-> [CmmLit]
-mkStdInfoTable type_descr closure_descr cl_type srt_len layout_lit
+mkStdInfoTable (type_descr, closure_descr) cl_type srt_len layout_lit
= -- Parallel revertible-black hole field
prof_info
-- Ticky info (none at present)
@@ -272,3 +313,21 @@ mkStdInfoTable type_descr closure_descr cl_type srt_len layout_lit
type_lit = packHalfWordsCLit cl_type srt_len
+-------------------------------------------------------------------------
+--
+-- Making string literals
+--
+-------------------------------------------------------------------------
+
+mkProfLits :: ProfilingInfo -> UniqSM ((CmmLit,CmmLit), [RawCmmTop])
+mkProfLits NoProfilingInfo = return ((zeroCLit, zeroCLit), [])
+mkProfLits (ProfilingInfo td cd)
+ = do { (td_lit, td_decl) <- newStringLit td
+ ; (cd_lit, cd_decl) <- newStringLit cd
+ ; return ((td_lit,cd_lit), [td_decl,cd_decl]) }
+
+newStringLit :: [Word8] -> UniqSM (CmmLit, GenCmmTop CmmStatics info stmt)
+newStringLit bytes
+ = do { uniq <- getUniqueUs
+ ; return (mkByteStringCLit uniq bytes) }
+
diff --git a/compiler/cmm/CmmLint.hs b/compiler/cmm/CmmLint.hs
index 15357ecb94..dd47c4433e 100644
--- a/compiler/cmm/CmmLint.hs
+++ b/compiler/cmm/CmmLint.hs
@@ -31,8 +31,8 @@ import Data.Maybe
-- Exported entry points:
cmmLint :: (Outputable d, Outputable h)
- => Platform -> GenCmm d h (ListGraph CmmStmt) -> Maybe SDoc
-cmmLint platform (Cmm tops) = runCmmLint platform (mapM_ lintCmmTop) tops
+ => Platform -> GenCmmPgm d h (ListGraph CmmStmt) -> Maybe SDoc
+cmmLint platform tops = runCmmLint platform (mapM_ lintCmmTop) tops
cmmLintTop :: (Outputable d, Outputable h)
=> Platform -> GenCmmTop d h (ListGraph CmmStmt) -> Maybe SDoc
diff --git a/compiler/cmm/CmmLive.hs b/compiler/cmm/CmmLive.hs
index ca3ab095ed..9a5bb2d5ae 100644
--- a/compiler/cmm/CmmLive.hs
+++ b/compiler/cmm/CmmLive.hs
@@ -13,7 +13,7 @@ where
import BlockId
import Cmm
-import CmmExpr
+import CmmUtils
import Control.Monad
import OptimizationFuel
import PprCmmExpr ()
diff --git a/compiler/cmm/CmmNode.hs b/compiler/cmm/CmmNode.hs
index f5a88cebb8..e9b84b568a 100644
--- a/compiler/cmm/CmmNode.hs
+++ b/compiler/cmm/CmmNode.hs
@@ -7,16 +7,14 @@
{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
#endif
-module CmmNode
- ( CmmNode(..)
- , UpdFrameOffset, Convention(..), ForeignConvention(..), ForeignTarget(..)
- , mapExp, mapExpDeep, wrapRecExp, foldExp, foldExpDeep, wrapRecExpf
- , mapExpM, mapExpDeepM, wrapRecExpM
- )
-where
+module CmmNode (
+ CmmNode(..), ForeignHint(..), CmmFormal, CmmActual,
+ UpdFrameOffset, Convention(..), ForeignConvention(..), ForeignTarget(..),
+ mapExp, mapExpDeep, wrapRecExp, foldExp, foldExpDeep, wrapRecExpf,
+ mapExpM, mapExpDeepM, wrapRecExpM
+ ) where
import CmmExpr
-import CmmDecl
import FastString
import ForeignCall
import SMRep
@@ -200,6 +198,9 @@ instance HooplNode CmmNode where
--------------------------------------------------
-- Various helper types
+type CmmActual = CmmExpr
+type CmmFormal = LocalReg
+
type UpdFrameOffset = ByteOff
data Convention
@@ -235,6 +236,12 @@ data ForeignTarget -- The target of a foreign call
CallishMachOp -- Which one
deriving Eq
+data ForeignHint
+ = NoHint | AddrHint | SignedHint
+ deriving( Eq )
+ -- Used to give extra per-argument or per-result
+ -- information needed by foreign calling conventions
+
--------------------------------------------------
-- Instances of register and slot users / definers
diff --git a/compiler/cmm/CmmParse.y b/compiler/cmm/CmmParse.y
index 9d9136e18b..cd0c021db6 100644
--- a/compiler/cmm/CmmParse.y
+++ b/compiler/cmm/CmmParse.y
@@ -191,7 +191,7 @@ cmmdata :: { ExtCode }
: 'section' STRING '{' data_label statics '}'
{ do lbl <- $4;
ss <- sequence $5;
- code (emitData (section $2) (Statics lbl $ concat ss)) }
+ code (emitDecl (CmmData (section $2) (Statics lbl $ concat ss))) }
data_label :: { ExtFCode CLabel }
: NAME ':'
@@ -264,23 +264,28 @@ info :: { ExtFCode (CLabel, CmmInfoTable, [Maybe LocalReg]) }
: 'INFO_TABLE' '(' NAME ',' INT ',' INT ',' INT ',' STRING ',' STRING ')'
-- ptrs, nptrs, closure type, description, type
{% withThisPackage $ \pkg ->
- do prof <- profilingInfo $11 $13
+ do let prof = profilingInfo $11 $13
+ rep = mkHeapRep False (fromIntegral $5) (fromIntegral $7) Thunk
+ -- ToDo: Type tag $9 redundant
return (mkCmmEntryLabel pkg $3,
- CmmInfoTable (mkCmmInfoLabel pkg $3) False prof (fromIntegral $9)
- (ThunkInfo (fromIntegral $5, fromIntegral $7) NoC_SRT),
- []) }
+ CmmInfoTable { cit_lbl = mkCmmInfoLabel pkg $3
+ , cit_rep = rep
+ , cit_prof = prof, cit_srt = NoC_SRT },
+ []) }
| 'INFO_TABLE_FUN' '(' NAME ',' INT ',' INT ',' INT ',' STRING ',' STRING ',' INT ')'
-- ptrs, nptrs, closure type, description, type, fun type
{% withThisPackage $ \pkg ->
- do prof <- profilingInfo $11 $13
+ do let prof = profilingInfo $11 $13
+ rep = mkHeapRep False (fromIntegral $5) (fromIntegral $7) ty
+ ty = Fun 0 -- Arity zero
+ (ArgSpec (fromIntegral $15))
+ -- ToDo: Type tag $9 redundant
return (mkCmmEntryLabel pkg $3,
- CmmInfoTable (mkCmmInfoLabel pkg $3) False prof (fromIntegral $9)
- (FunInfo (fromIntegral $5, fromIntegral $7) NoC_SRT
- 0 -- Arity zero
- (ArgSpec (fromIntegral $15))
- zeroCLit),
- []) }
+ CmmInfoTable { cit_lbl = mkCmmInfoLabel pkg $3
+ , cit_rep = rep
+ , cit_prof = prof, cit_srt = NoC_SRT },
+ []) }
-- we leave most of the fields zero here. This is only used
-- to generate the BCO info table in the RTS at the moment.
@@ -288,54 +293,73 @@ info :: { ExtFCode (CLabel, CmmInfoTable, [Maybe LocalReg]) }
| 'INFO_TABLE_FUN' '(' NAME ',' INT ',' INT ',' INT ',' STRING ',' STRING ',' INT ',' INT ')'
-- ptrs, nptrs, closure type, description, type, fun type, arity
{% withThisPackage $ \pkg ->
- do prof <- profilingInfo $11 $13
+ do let prof = profilingInfo $11 $13
+ rep = mkHeapRep False (fromIntegral $5) (fromIntegral $7) ty
+ ty = Fun (fromIntegral $17) -- Arity
+ (ArgSpec (fromIntegral $15))
+ -- ToDo: Type tag $9 redundant
return (mkCmmEntryLabel pkg $3,
- CmmInfoTable (mkCmmInfoLabel pkg $3) False prof (fromIntegral $9)
- (FunInfo (fromIntegral $5, fromIntegral $7) NoC_SRT (fromIntegral $17)
- (ArgSpec (fromIntegral $15))
- zeroCLit),
- []) }
+ CmmInfoTable { cit_lbl = mkCmmInfoLabel pkg $3
+ , cit_rep = rep
+ , cit_prof = prof, cit_srt = NoC_SRT },
+ []) }
-- we leave most of the fields zero here. This is only used
-- to generate the BCO info table in the RTS at the moment.
| 'INFO_TABLE_CONSTR' '(' NAME ',' INT ',' INT ',' INT ',' INT ',' STRING ',' STRING ')'
-- ptrs, nptrs, tag, closure type, description, type
{% withThisPackage $ \pkg ->
- do prof <- profilingInfo $13 $15
+ do let prof = profilingInfo $13 $15
+ rep = mkHeapRep False (fromIntegral $5) (fromIntegral $7) ty
+ ty = Constr (fromIntegral $9) -- Tag
+ (stringToWord8s $13)
+ -- ToDo: Type tag $11 redundant
+ return (mkCmmEntryLabel pkg $3,
+ CmmInfoTable { cit_lbl = mkCmmInfoLabel pkg $3
+ , cit_rep = rep
+ , cit_prof = prof, cit_srt = NoC_SRT },
+ []) }
+
-- If profiling is on, this string gets duplicated,
-- but that's the way the old code did it we can fix it some other time.
- desc_lit <- code $ mkStringCLit $13
- return (mkCmmEntryLabel pkg $3,
- CmmInfoTable (mkCmmInfoLabel pkg $3) False prof (fromIntegral $11)
- (ConstrInfo (fromIntegral $5, fromIntegral $7) (fromIntegral $9) desc_lit),
- []) }
| 'INFO_TABLE_SELECTOR' '(' NAME ',' INT ',' INT ',' STRING ',' STRING ')'
-- selector, closure type, description, type
{% withThisPackage $ \pkg ->
- do prof <- profilingInfo $9 $11
+ do let prof = profilingInfo $9 $11
+ rep = mkHeapRep False (fromIntegral $5) (fromIntegral $7) ty
+ ty = ThunkSelector (fromIntegral $5)
+ -- ToDo: Type tag $7 redundant
return (mkCmmEntryLabel pkg $3,
- CmmInfoTable (mkCmmInfoLabel pkg $3) False prof (fromIntegral $7)
- (ThunkSelectorInfo (fromIntegral $5) NoC_SRT),
- []) }
+ CmmInfoTable { cit_lbl = mkCmmInfoLabel pkg $3
+ , cit_rep = rep
+ , cit_prof = prof, cit_srt = NoC_SRT },
+ []) }
| 'INFO_TABLE_RET' '(' NAME ',' INT ')'
-- closure type (no live regs)
{% withThisPackage $ \pkg ->
- do let infoLabel = mkCmmInfoLabel pkg $3
+ do let prof = NoProfilingInfo
+ rep = mkStackRep []
+ -- ToDo: Type tag $5 redundant
return (mkCmmRetLabel pkg $3,
- CmmInfoTable (mkCmmInfoLabel pkg $3) False (ProfilingInfo zeroCLit zeroCLit) (fromIntegral $5)
- (ContInfo [] NoC_SRT),
- []) }
+ CmmInfoTable { cit_lbl = mkCmmInfoLabel pkg $3
+ , cit_rep = rep
+ , cit_prof = prof, cit_srt = NoC_SRT },
+ []) }
| 'INFO_TABLE_RET' '(' NAME ',' INT ',' formals_without_hints0 ')'
-- closure type, live regs
{% withThisPackage $ \pkg ->
do live <- sequence (map (liftM Just) $7)
+ let prof = NoProfilingInfo
+ rep = mkStackRep []
+ -- ToDo: Type tag $5 redundant
return (mkCmmRetLabel pkg $3,
- CmmInfoTable (mkCmmInfoLabel pkg $3) False (ProfilingInfo zeroCLit zeroCLit) (fromIntegral $5)
- (ContInfo live NoC_SRT),
- live) }
+ CmmInfoTable { cit_lbl = mkCmmInfoLabel pkg $3
+ , cit_rep = rep
+ , cit_prof = prof, cit_srt = NoC_SRT },
+ []) }
body :: { ExtCode }
: {- empty -} { return () }
@@ -499,7 +523,7 @@ expr :: { ExtFCode CmmExpr }
expr0 :: { ExtFCode CmmExpr }
: INT maybe_ty { return (CmmLit (CmmInt $1 (typeWidth $2))) }
| FLOAT maybe_ty { return (CmmLit (CmmFloat $1 (typeWidth $2))) }
- | STRING { do s <- code (mkStringCLit $1);
+ | STRING { do s <- code (newStringCLit $1);
return (CmmLit s) }
| reg { $1 }
| type '[' expr ']' { do e <- $3; return (CmmLoad e $1) }
@@ -828,16 +852,10 @@ stmtMacros = listToUFM [
]
-
-profilingInfo desc_str ty_str = do
- lit1 <- if opt_SccProfilingOn
- then code $ mkStringCLit desc_str
- else return (mkIntCLit 0)
- lit2 <- if opt_SccProfilingOn
- then code $ mkStringCLit ty_str
- else return (mkIntCLit 0)
- return (ProfilingInfo lit1 lit2)
-
+profilingInfo desc_str ty_str
+ | not opt_SccProfilingOn = NoProfilingInfo
+ | otherwise = ProfilingInfo (stringToWord8s desc_str)
+ (stringToWord8s ty_str)
staticClosure :: PackageId -> FastString -> FastString -> [CmmLit] -> ExtCode
staticClosure pkg cl_label info payload
@@ -1051,12 +1069,12 @@ doSwitch mb_range scrut arms deflt
initEnv :: Env
initEnv = listToUFM [
( fsLit "SIZEOF_StgHeader",
- Var (CmmLit (CmmInt (fromIntegral (fixedHdrSize * wORD_SIZE)) wordWidth) )),
+ VarN (CmmLit (CmmInt (fromIntegral (fixedHdrSize * wORD_SIZE)) wordWidth) )),
( fsLit "SIZEOF_StgInfoTable",
- Var (CmmLit (CmmInt (fromIntegral stdInfoTableSizeB) wordWidth) ))
+ VarN (CmmLit (CmmInt (fromIntegral stdInfoTableSizeB) wordWidth) ))
]
-parseCmmFile :: DynFlags -> FilePath -> IO (Messages, Maybe Cmm)
+parseCmmFile :: DynFlags -> FilePath -> IO (Messages, Maybe CmmPgm)
parseCmmFile dflags filename = do
showPass dflags "ParseCmm"
buf <- hGetStringBuffer filename
diff --git a/compiler/cmm/CmmPipeline.hs b/compiler/cmm/CmmPipeline.hs
index 5effa6ca77..8c6e0a765f 100644
--- a/compiler/cmm/CmmPipeline.hs
+++ b/compiler/cmm/CmmPipeline.hs
@@ -11,7 +11,6 @@ module CmmPipeline (
import CLabel
import Cmm
-import CmmDecl
import CmmLive
import CmmBuildInfoTables
import CmmCommonBlockElim
@@ -54,21 +53,31 @@ import StaticFlags
-- we actually need to do the initial pass.
cmmPipeline :: HscEnv -- Compilation env including
-- dynamic flags: -dcmm-lint -ddump-cps-cmm
- -> (TopSRT, [Cmm]) -- SRT table and accumulating list of compiled procs
- -> Cmm -- Input C-- with Procedures
- -> IO (TopSRT, [Cmm]) -- Output CPS transformed C--
+ -> (TopSRT, [CmmPgm]) -- SRT table and accumulating list of compiled procs
+ -> CmmPgm -- Input C-- with Procedures
+ -> IO (TopSRT, [CmmPgm]) -- Output CPS transformed C--
cmmPipeline hsc_env (topSRT, rst) prog =
do let dflags = hsc_dflags hsc_env
- (Cmm tops) = runCmmContFlowOpts prog
+ --
showPass dflags "CPSZ"
+
+ let tops = runCmmContFlowOpts prog
(cafEnvs, tops) <- liftM unzip $ mapM (cpsTop hsc_env) tops
+ -- tops :: [[(CmmTop,CAFSet]] (one list per group)
+
let topCAFEnv = mkTopCAFInfo (concat cafEnvs)
+
+ -- folding over the groups
(topSRT, tops) <- foldM (toTops hsc_env topCAFEnv) (topSRT, []) tops
- let cmms = Cmm (reverse (concat tops))
+
+ let cmms = reverse (concat tops)
+
dumpIfSet_dyn dflags Opt_D_dump_cps_cmm "Post CPS Cmm" (pprPlatform (targetPlatform dflags) cmms)
+
-- SRT is not affected by control flow optimization pass
- let prog' = map runCmmContFlowOpts (cmms : rst)
- return (topSRT, prog')
+ let prog' = runCmmContFlowOpts cmms
+
+ return (topSRT, prog' : rst)
{- [Note global fuel]
~~~~~~~~~~~~~~~~~~~~~
@@ -152,6 +161,10 @@ cpsTop hsc_env (CmmProc h@(TopInfo {stack_info=StackInfo {arg_space=entry_off}})
gs <- return $ map (bundleCAFs cafEnv) gs
mapM_ (dumpPlatform platform Opt_D_dump_cmmz_cafs "after bundleCAFs") gs
return (localCAFs, gs)
+
+ -- gs :: [ (CAFSet, CmmTop) ]
+ -- localCAFs :: [ (CLabel, CAFSet) ] -- statics filtered out(?)
+
where dflags = hsc_dflags hsc_env
platform = targetPlatform dflags
mbpprTrace x y z = if dopt Opt_D_dump_cmmz dflags then pprTrace x y z else z
diff --git a/compiler/cmm/CmmProcPoint.hs b/compiler/cmm/CmmProcPoint.hs
index c063f639af..884846678a 100644
--- a/compiler/cmm/CmmProcPoint.hs
+++ b/compiler/cmm/CmmProcPoint.hs
@@ -13,8 +13,8 @@ import Prelude hiding (last, unzip, succ, zip)
import BlockId
import CLabel
import Cmm
-import CmmDecl
import CmmExpr
+import CmmUtils
import CmmContFlowOpt
import CmmInfo
import CmmLive
@@ -408,10 +408,9 @@ splitAtProcPoints entry_label callPPs procPoints procMap
-- Due to common blockification, we may overestimate the set of procpoints.
let add_label map pp = Map.insert pp lbls map
where lbls | pp == entry = (entry_label, Just entry_info_lbl)
- | otherwise = (blockLbl pp, guard (setMember pp callPPs) >> Just (infoTblLbl pp))
- entry_info_lbl = case info_tbl of
- CmmInfoTable entry_info_label _ _ _ _ -> entry_info_label
- CmmNonInfoTable -> pprPanic "splitAtProcPoints: looked at info label for entry without info table" (ppr pp)
+ | otherwise = (blockLbl pp, guard (setMember pp callPPs) >>
+ Just (infoTblLbl pp))
+ entry_info_lbl = cit_lbl info_tbl
procLabels = foldl add_label Map.empty
(filter (flip mapMember (toBlockMap g)) (setElems procPoints))
-- For each procpoint, we need to know the SP offset on entry.
diff --git a/compiler/cmm/CmmRewriteAssignments.hs b/compiler/cmm/CmmRewriteAssignments.hs
index c0b7510349..c9ac12a6ef 100644
--- a/compiler/cmm/CmmRewriteAssignments.hs
+++ b/compiler/cmm/CmmRewriteAssignments.hs
@@ -16,7 +16,7 @@ module CmmRewriteAssignments
) where
import Cmm
-import CmmExpr
+import CmmUtils
import CmmOpt
import OptimizationFuel
import StgCmmUtils
diff --git a/compiler/cmm/CmmSpillReload.hs b/compiler/cmm/CmmSpillReload.hs
index 3033e7b421..9e762fe48a 100644
--- a/compiler/cmm/CmmSpillReload.hs
+++ b/compiler/cmm/CmmSpillReload.hs
@@ -14,7 +14,7 @@ where
import BlockId
import Cmm
-import CmmExpr
+import CmmUtils
import CmmLive
import OptimizationFuel
diff --git a/compiler/cmm/CmmStackLayout.hs b/compiler/cmm/CmmStackLayout.hs
index 4c01a1a752..85e4af03be 100644
--- a/compiler/cmm/CmmStackLayout.hs
+++ b/compiler/cmm/CmmStackLayout.hs
@@ -22,7 +22,7 @@ import Prelude hiding (succ, zip, unzip, last)
import BlockId
import Cmm
-import CmmExpr
+import CmmUtils
import CmmProcPoint
import Maybes
import MkGraph (stackStubExpr)
diff --git a/compiler/cmm/CmmUtils.hs b/compiler/cmm/CmmUtils.hs
index 35f2471361..2dcf5497c8 100644
--- a/compiler/cmm/CmmUtils.hs
+++ b/compiler/cmm/CmmUtils.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE GADTs #-}
-----------------------------------------------------------------------------
--
-- Cmm utilities.
@@ -7,17 +8,49 @@
-----------------------------------------------------------------------------
module CmmUtils(
+ -- CmmType
primRepCmmType, primRepForeignHint,
typeCmmType, typeForeignHint,
+ -- CmmLit
+ zeroCLit, mkIntCLit,
+ mkWordCLit, packHalfWordsCLit,
+ mkByteStringCLit,
+ mkDataLits, mkRODataLits,
+
+ -- CmmExpr
+ mkLblExpr,
+ cmmRegOff, cmmOffset, cmmLabelOff, cmmOffsetLit, cmmOffsetExpr,
+ cmmRegOffB, cmmOffsetB, cmmLabelOffB, cmmOffsetLitB, cmmOffsetExprB,
+ cmmRegOffW, cmmOffsetW, cmmLabelOffW, cmmOffsetLitW, cmmOffsetExprW,
+ cmmIndex, cmmIndexExpr, cmmLoadIndex, cmmLoadIndexW,
+ cmmNegate,
+ cmmULtWord, cmmUGeWord, cmmUGtWord, cmmSubWord,
+ cmmNeWord, cmmEqWord, cmmOrWord, cmmAndWord,
+ cmmUShrWord, cmmAddWord, cmmMulWord,
+
isTrivialCmmExpr, hasNoGlobalRegs,
+
+ -- Statics
+ blankWord,
- cmmRegOff, cmmLabelOff, cmmOffset, cmmOffsetLit, cmmIndex,
- cmmOffsetExpr, cmmIndexExpr, cmmLoadIndex,
+ -- Tagging
+ cmmTagMask, cmmPointerMask, cmmUntag, cmmGetTag, cmmIsTagged,
+ cmmConstrTag, cmmConstrTag1,
- mkIntCLit, zeroCLit,
+ -- Liveness and bitmaps
+ mkLiveness,
- mkLblExpr,
+ -- * Operations that probably don't belong here
+ modifyGraph,
+
+ lastNode, replaceLastNode, insertBetween,
+ ofBlockMap, toBlockMap, insertBlock,
+ ofBlockList, toBlockList, bodyToBlockList,
+ foldGraphBlocks, mapGraphNodes, postorderDfs,
+
+ analFwd, analBwd, analRewFwd, analRewBwd,
+ dataflowPassFwd, dataflowPassBwd
) where
#include "HsVersions.h"
@@ -25,10 +58,21 @@ module CmmUtils(
import TyCon ( PrimRep(..) )
import Type ( Type, typePrimRep )
+import SMRep
+import Cmm
+import BlockId
import CLabel
-import CmmDecl
-import CmmExpr
import Outputable
+import OptimizationFuel as F
+import Unique
+import UniqSupply
+import Constants( wORD_SIZE, tAG_MASK )
+
+import Data.Word
+import Data.Maybe
+import Data.Bits
+import Control.Monad
+import Compiler.Hoopl hiding ( Unique )
---------------------------------------------------
--
@@ -64,35 +108,68 @@ primRepForeignHint DoubleRep = NoHint
typeForeignHint :: Type -> ForeignHint
typeForeignHint = primRepForeignHint . typePrimRep
-
---------------------------------------------------
--
--- CmmExpr
+-- CmmLit
--
---------------------------------------------------
-isTrivialCmmExpr :: CmmExpr -> Bool
-isTrivialCmmExpr (CmmLoad _ _) = False
-isTrivialCmmExpr (CmmMachOp _ _) = False
-isTrivialCmmExpr (CmmLit _) = True
-isTrivialCmmExpr (CmmReg _) = True
-isTrivialCmmExpr (CmmRegOff _ _) = True
-isTrivialCmmExpr (CmmStackSlot _ _) = panic "isTrivialCmmExpr CmmStackSlot"
+mkIntCLit :: Int -> CmmLit
+mkIntCLit i = CmmInt (toInteger i) wordWidth
-hasNoGlobalRegs :: CmmExpr -> Bool
-hasNoGlobalRegs (CmmLoad e _) = hasNoGlobalRegs e
-hasNoGlobalRegs (CmmMachOp _ es) = all hasNoGlobalRegs es
-hasNoGlobalRegs (CmmLit _) = True
-hasNoGlobalRegs (CmmReg (CmmLocal _)) = True
-hasNoGlobalRegs (CmmRegOff (CmmLocal _) _) = True
-hasNoGlobalRegs _ = False
+zeroCLit :: CmmLit
+zeroCLit = CmmInt 0 wordWidth
+
+mkByteStringCLit :: Unique -> [Word8] -> (CmmLit, GenCmmTop CmmStatics info stmt)
+-- We have to make a top-level decl for the string,
+-- and return a literal pointing to it
+mkByteStringCLit uniq bytes
+ = (CmmLabel lbl, CmmData ReadOnlyData $ Statics lbl [CmmString bytes])
+ where
+ lbl = mkStringLitLabel uniq
+mkDataLits :: Section -> CLabel -> [CmmLit] -> GenCmmTop CmmStatics info stmt
+-- Build a data-segment data block
+mkDataLits section lbl lits
+ = CmmData section (Statics lbl $ map CmmStaticLit lits)
+
+mkRODataLits :: CLabel -> [CmmLit] -> GenCmmTop CmmStatics info stmt
+-- Build a read-only data block
+mkRODataLits lbl lits
+ = mkDataLits section lbl lits
+ where
+ section | any needsRelocation lits = RelocatableReadOnlyData
+ | otherwise = ReadOnlyData
+ needsRelocation (CmmLabel _) = True
+ needsRelocation (CmmLabelOff _ _) = True
+ needsRelocation _ = False
+
+mkWordCLit :: StgWord -> CmmLit
+mkWordCLit wd = CmmInt (fromIntegral wd) wordWidth
+
+packHalfWordsCLit :: (Integral a, Integral b) => a -> b -> CmmLit
+-- Make a single word literal in which the lower_half_word is
+-- at the lower address, and the upper_half_word is at the
+-- higher address
+-- ToDo: consider using half-word lits instead
+-- but be careful: that's vulnerable when reversed
+packHalfWordsCLit lower_half_word upper_half_word
+#ifdef WORDS_BIGENDIAN
+ = mkWordCLit ((fromIntegral lower_half_word `shiftL` hALF_WORD_SIZE_IN_BITS)
+ .|. fromIntegral upper_half_word)
+#else
+ = mkWordCLit ((fromIntegral lower_half_word)
+ .|. (fromIntegral upper_half_word `shiftL` hALF_WORD_SIZE_IN_BITS))
+#endif
---------------------------------------------------
--
--- Expr Construction helpers
+-- CmmExpr
--
---------------------------------------------------
+mkLblExpr :: CLabel -> CmmExpr
+mkLblExpr lbl = CmmLit (CmmLabel lbl)
+
cmmOffsetExpr :: CmmExpr -> CmmExpr -> CmmExpr
-- assumes base and offset have the same CmmType
cmmOffsetExpr e (CmmLit (CmmInt n _)) = cmmOffset e (fromInteger n)
@@ -156,17 +233,272 @@ cmmIndexExpr width base idx =
cmmLoadIndex :: CmmType -> CmmExpr -> Int -> CmmExpr
cmmLoadIndex ty expr ix = CmmLoad (cmmIndex (typeWidth ty) expr ix) ty
+-- The "B" variants take byte offsets
+cmmRegOffB :: CmmReg -> ByteOff -> CmmExpr
+cmmRegOffB = cmmRegOff
+
+cmmOffsetB :: CmmExpr -> ByteOff -> CmmExpr
+cmmOffsetB = cmmOffset
+
+cmmOffsetExprB :: CmmExpr -> CmmExpr -> CmmExpr
+cmmOffsetExprB = cmmOffsetExpr
+
+cmmLabelOffB :: CLabel -> ByteOff -> CmmLit
+cmmLabelOffB = cmmLabelOff
+
+cmmOffsetLitB :: CmmLit -> ByteOff -> CmmLit
+cmmOffsetLitB = cmmOffsetLit
+
+-----------------------
+-- The "W" variants take word offsets
+cmmOffsetExprW :: CmmExpr -> CmmExpr -> CmmExpr
+-- The second arg is a *word* offset; need to change it to bytes
+cmmOffsetExprW e (CmmLit (CmmInt n _)) = cmmOffsetW e (fromInteger n)
+cmmOffsetExprW e wd_off = cmmIndexExpr wordWidth e wd_off
+
+cmmOffsetW :: CmmExpr -> WordOff -> CmmExpr
+cmmOffsetW e n = cmmOffsetB e (wORD_SIZE * n)
+
+cmmRegOffW :: CmmReg -> WordOff -> CmmExpr
+cmmRegOffW reg wd_off = cmmRegOffB reg (wd_off * wORD_SIZE)
+
+cmmOffsetLitW :: CmmLit -> WordOff -> CmmLit
+cmmOffsetLitW lit wd_off = cmmOffsetLitB lit (wORD_SIZE * wd_off)
+
+cmmLabelOffW :: CLabel -> WordOff -> CmmLit
+cmmLabelOffW lbl wd_off = cmmLabelOffB lbl (wORD_SIZE * wd_off)
+
+cmmLoadIndexW :: CmmExpr -> Int -> CmmType -> CmmExpr
+cmmLoadIndexW base off ty = CmmLoad (cmmOffsetW base off) ty
+
+-----------------------
+cmmULtWord, cmmUGeWord, cmmUGtWord, cmmSubWord,
+ cmmNeWord, cmmEqWord, cmmOrWord, cmmAndWord,
+ cmmUShrWord, cmmAddWord, cmmMulWord
+ :: CmmExpr -> CmmExpr -> CmmExpr
+cmmOrWord e1 e2 = CmmMachOp mo_wordOr [e1, e2]
+cmmAndWord e1 e2 = CmmMachOp mo_wordAnd [e1, e2]
+cmmNeWord e1 e2 = CmmMachOp mo_wordNe [e1, e2]
+cmmEqWord e1 e2 = CmmMachOp mo_wordEq [e1, e2]
+cmmULtWord e1 e2 = CmmMachOp mo_wordULt [e1, e2]
+cmmUGeWord e1 e2 = CmmMachOp mo_wordUGe [e1, e2]
+cmmUGtWord e1 e2 = CmmMachOp mo_wordUGt [e1, e2]
+--cmmShlWord e1 e2 = CmmMachOp mo_wordShl [e1, e2]
+cmmUShrWord e1 e2 = CmmMachOp mo_wordUShr [e1, e2]
+cmmAddWord e1 e2 = CmmMachOp mo_wordAdd [e1, e2]
+cmmSubWord e1 e2 = CmmMachOp mo_wordSub [e1, e2]
+cmmMulWord e1 e2 = CmmMachOp mo_wordMul [e1, e2]
+
+cmmNegate :: CmmExpr -> CmmExpr
+cmmNegate (CmmLit (CmmInt n rep)) = CmmLit (CmmInt (-n) rep)
+cmmNegate e = CmmMachOp (MO_S_Neg (cmmExprWidth e)) [e]
+
+blankWord :: CmmStatic
+blankWord = CmmUninitialised wORD_SIZE
+
---------------------------------------------------
--
--- Literal construction functions
+-- CmmExpr predicates
--
---------------------------------------------------
-mkIntCLit :: Int -> CmmLit
-mkIntCLit i = CmmInt (toInteger i) wordWidth
+isTrivialCmmExpr :: CmmExpr -> Bool
+isTrivialCmmExpr (CmmLoad _ _) = False
+isTrivialCmmExpr (CmmMachOp _ _) = False
+isTrivialCmmExpr (CmmLit _) = True
+isTrivialCmmExpr (CmmReg _) = True
+isTrivialCmmExpr (CmmRegOff _ _) = True
+isTrivialCmmExpr (CmmStackSlot _ _) = panic "isTrivialCmmExpr CmmStackSlot"
-zeroCLit :: CmmLit
-zeroCLit = CmmInt 0 wordWidth
+hasNoGlobalRegs :: CmmExpr -> Bool
+hasNoGlobalRegs (CmmLoad e _) = hasNoGlobalRegs e
+hasNoGlobalRegs (CmmMachOp _ es) = all hasNoGlobalRegs es
+hasNoGlobalRegs (CmmLit _) = True
+hasNoGlobalRegs (CmmReg (CmmLocal _)) = True
+hasNoGlobalRegs (CmmRegOff (CmmLocal _) _) = True
+hasNoGlobalRegs _ = False
-mkLblExpr :: CLabel -> CmmExpr
-mkLblExpr lbl = CmmLit (CmmLabel lbl)
+---------------------------------------------------
+--
+-- Tagging
+--
+---------------------------------------------------
+
+-- Tag bits mask
+--cmmTagBits = CmmLit (mkIntCLit tAG_BITS)
+cmmTagMask, cmmPointerMask :: CmmExpr
+cmmTagMask = CmmLit (mkIntCLit tAG_MASK)
+cmmPointerMask = CmmLit (mkIntCLit (complement tAG_MASK))
+
+-- Used to untag a possibly tagged pointer
+-- A static label need not be untagged
+cmmUntag, cmmGetTag :: CmmExpr -> CmmExpr
+cmmUntag e@(CmmLit (CmmLabel _)) = e
+-- Default case
+cmmUntag e = (e `cmmAndWord` cmmPointerMask)
+
+cmmGetTag e = (e `cmmAndWord` cmmTagMask)
+
+-- Test if a closure pointer is untagged
+cmmIsTagged :: CmmExpr -> CmmExpr
+cmmIsTagged e = (e `cmmAndWord` cmmTagMask)
+ `cmmNeWord` CmmLit zeroCLit
+
+cmmConstrTag, cmmConstrTag1 :: CmmExpr -> CmmExpr
+cmmConstrTag e = (e `cmmAndWord` cmmTagMask) `cmmSubWord` (CmmLit (mkIntCLit 1))
+-- Get constructor tag, but one based.
+cmmConstrTag1 e = e `cmmAndWord` cmmTagMask
+
+
+--------------------------------------------
+--
+-- mkLiveness
+--
+---------------------------------------------
+
+mkLiveness :: [Maybe LocalReg] -> Liveness
+mkLiveness [] = []
+mkLiveness (reg:regs)
+ = take sizeW bits ++ mkLiveness regs
+ where
+ sizeW = case reg of
+ Nothing -> 1
+ Just r -> (widthInBytes (typeWidth (localRegType r)) + wORD_SIZE - 1)
+ `quot` wORD_SIZE
+ -- number of words, rounded up
+ bits = repeat $ is_non_ptr reg -- True <=> Non Ptr
+
+ is_non_ptr Nothing = True
+ is_non_ptr (Just reg) = not $ isGcPtrType (localRegType reg)
+
+
+-- ============================================== -
+-- ============================================== -
+-- ============================================== -
+
+---------------------------------------------------
+--
+-- Manipulating CmmGraphs
+--
+---------------------------------------------------
+
+modifyGraph :: (Graph n C C -> Graph n' C C) -> GenCmmGraph n -> GenCmmGraph n'
+modifyGraph f g = CmmGraph {g_entry=g_entry g, g_graph=f (g_graph g)}
+
+toBlockMap :: CmmGraph -> LabelMap CmmBlock
+toBlockMap (CmmGraph {g_graph=GMany NothingO body NothingO}) = body
+
+ofBlockMap :: BlockId -> LabelMap CmmBlock -> CmmGraph
+ofBlockMap entry bodyMap = CmmGraph {g_entry=entry, g_graph=GMany NothingO bodyMap NothingO}
+
+insertBlock :: CmmBlock -> LabelMap CmmBlock -> LabelMap CmmBlock
+insertBlock block map =
+ ASSERT (isNothing $ mapLookup id map)
+ mapInsert id block map
+ where id = entryLabel block
+
+toBlockList :: CmmGraph -> [CmmBlock]
+toBlockList g = mapElems $ toBlockMap g
+
+ofBlockList :: BlockId -> [CmmBlock] -> CmmGraph
+ofBlockList entry blocks = CmmGraph {g_entry=entry, g_graph=GMany NothingO body NothingO}
+ where body = foldr addBlock emptyBody blocks
+
+bodyToBlockList :: Body CmmNode -> [CmmBlock]
+bodyToBlockList body = mapElems body
+
+mapGraphNodes :: ( CmmNode C O -> CmmNode C O
+ , CmmNode O O -> CmmNode O O
+ , CmmNode O C -> CmmNode O C)
+ -> CmmGraph -> CmmGraph
+mapGraphNodes funs@(mf,_,_) g =
+ ofBlockMap (entryLabel $ mf $ CmmEntry $ g_entry g) $ mapMap (blockMapNodes3 funs) $ toBlockMap g
+
+foldGraphBlocks :: (CmmBlock -> a -> a) -> a -> CmmGraph -> a
+foldGraphBlocks k z g = mapFold k z $ toBlockMap g
+
+postorderDfs :: CmmGraph -> [CmmBlock]
+postorderDfs g = postorder_dfs_from (toBlockMap g) (g_entry g)
+
+-------------------------------------------------
+-- Manipulating CmmBlocks
+
+lastNode :: CmmBlock -> CmmNode O C
+lastNode block = foldBlockNodesF3 (nothing, nothing, const) block ()
+ where nothing :: a -> b -> ()
+ nothing _ _ = ()
+
+replaceLastNode :: Block CmmNode e C -> CmmNode O C -> Block CmmNode e C
+replaceLastNode block last = blockOfNodeList (first, middle, JustC last)
+ where (first, middle, _) = blockToNodeList block
+
+----------------------------------------------------------------------
+----- Splicing between blocks
+-- Given a middle node, a block, and a successor BlockId,
+-- we can insert the middle node between the block and the successor.
+-- We return the updated block and a list of new blocks that must be added
+-- to the graph.
+-- The semantics is a bit tricky. We consider cases on the last node:
+-- o For a branch, we can just insert before the branch,
+-- but sometimes the optimizer does better if we actually insert
+-- a fresh basic block, enabling some common blockification.
+-- o For a conditional branch, switch statement, or call, we must insert
+-- a new basic block.
+-- o For a jump or return, this operation is impossible.
+
+insertBetween :: MonadUnique m => CmmBlock -> [CmmNode O O] -> BlockId -> m (CmmBlock, [CmmBlock])
+insertBetween b ms succId = insert $ lastNode b
+ where insert :: MonadUnique m => CmmNode O C -> m (CmmBlock, [CmmBlock])
+ insert (CmmBranch bid) =
+ if bid == succId then
+ do (bid', bs) <- newBlocks
+ return (replaceLastNode b (CmmBranch bid'), bs)
+ else panic "tried invalid block insertBetween"
+ insert (CmmCondBranch c t f) =
+ do (t', tbs) <- if t == succId then newBlocks else return $ (t, [])
+ (f', fbs) <- if f == succId then newBlocks else return $ (f, [])
+ return (replaceLastNode b (CmmCondBranch c t' f'), tbs ++ fbs)
+ insert (CmmSwitch e ks) =
+ do (ids, bs) <- mapAndUnzipM mbNewBlocks ks
+ return (replaceLastNode b (CmmSwitch e ids), join bs)
+ insert (CmmCall {}) =
+ panic "unimp: insertBetween after a call -- probably not a good idea"
+ insert (CmmForeignCall {}) =
+ panic "unimp: insertBetween after a foreign call -- probably not a good idea"
+
+ newBlocks :: MonadUnique m => m (BlockId, [CmmBlock])
+ newBlocks = do id <- liftM mkBlockId $ getUniqueM
+ return $ (id, [blockOfNodeList (JustC (CmmEntry id), ms, JustC (CmmBranch succId))])
+ mbNewBlocks :: MonadUnique m => Maybe BlockId -> m (Maybe BlockId, [CmmBlock])
+ mbNewBlocks (Just k) = if k == succId then liftM fstJust newBlocks
+ else return (Just k, [])
+ mbNewBlocks Nothing = return (Nothing, [])
+ fstJust (id, bs) = (Just id, bs)
+
+-------------------------------------------------
+-- Running dataflow analysis and/or rewrites
+
+-- Constructing forward and backward analysis-only pass
+analFwd :: Monad m => DataflowLattice f -> FwdTransfer n f -> FwdPass m n f
+analBwd :: Monad m => DataflowLattice f -> BwdTransfer n f -> BwdPass m n f
+
+analFwd lat xfer = analRewFwd lat xfer noFwdRewrite
+analBwd lat xfer = analRewBwd lat xfer noBwdRewrite
+
+-- Constructing forward and backward analysis + rewrite pass
+analRewFwd :: Monad m => DataflowLattice f -> FwdTransfer n f -> FwdRewrite m n f -> FwdPass m n f
+analRewBwd :: Monad m => DataflowLattice f -> BwdTransfer n f -> BwdRewrite m n f -> BwdPass m n f
+
+analRewFwd lat xfer rew = FwdPass {fp_lattice = lat, fp_transfer = xfer, fp_rewrite = rew}
+analRewBwd lat xfer rew = BwdPass {bp_lattice = lat, bp_transfer = xfer, bp_rewrite = rew}
+
+-- Running forward and backward dataflow analysis + optional rewrite
+dataflowPassFwd :: NonLocal n => GenCmmGraph n -> [(BlockId, f)] -> FwdPass FuelUniqSM n f -> FuelUniqSM (GenCmmGraph n, BlockEnv f)
+dataflowPassFwd (CmmGraph {g_entry=entry, g_graph=graph}) facts fwd = do
+ (graph, facts, NothingO) <- analyzeAndRewriteFwd fwd (JustC [entry]) graph (mkFactBase (fp_lattice fwd) facts)
+ return (CmmGraph {g_entry=entry, g_graph=graph}, facts)
+
+dataflowPassBwd :: NonLocal n => GenCmmGraph n -> [(BlockId, f)] -> BwdPass FuelUniqSM n f -> FuelUniqSM (GenCmmGraph n, BlockEnv f)
+dataflowPassBwd (CmmGraph {g_entry=entry, g_graph=graph}) facts bwd = do
+ (graph, facts, NothingO) <- analyzeAndRewriteBwd bwd (JustC [entry]) graph (mkFactBase (bp_lattice bwd) facts)
+ return (CmmGraph {g_entry=entry, g_graph=graph}, facts)
diff --git a/compiler/cmm/MkGraph.hs b/compiler/cmm/MkGraph.hs
index d1ac5712ab..bc2e4112d9 100644
--- a/compiler/cmm/MkGraph.hs
+++ b/compiler/cmm/MkGraph.hs
@@ -22,17 +22,11 @@ module MkGraph
, mkReturn, mkReturnSimple, mkComment, mkCallEntry
, mkBranch, mkCmmIfThenElse, mkCmmIfThen, mkCmmWhileDo
, copyInOflow, copyInSlot, copyOutOflow, copyOutSlot
- -- Reexport of needed Cmm stuff
- , Convention(..), ForeignConvention(..), ForeignTarget(..)
- , CmmStackInfo(..), CmmTopInfo(..), CmmGraph, GenCmmGraph(..)
- , Cmm, CmmTop
)
where
import BlockId
import Cmm
-import CmmDecl
-import CmmExpr
import CmmCallConv (assignArgumentsPos, ParamLocation(..))
import Compiler.Hoopl hiding (Unique, (<*>), mkFirst, mkMiddle, mkLast, mkLabel, mkBranch, Shape(..))
diff --git a/compiler/cmm/OldCmm.hs b/compiler/cmm/OldCmm.hs
index f691183038..2827d04cfd 100644
--- a/compiler/cmm/OldCmm.hs
+++ b/compiler/cmm/OldCmm.hs
@@ -7,26 +7,33 @@
-----------------------------------------------------------------------------
module OldCmm (
- Cmm, RawCmm, CmmTop, RawCmmTop,
+ CmmPgm, GenCmmPgm, RawCmmPgm, CmmTop, RawCmmTop,
ListGraph(..),
- CmmInfo(..), UpdateFrame(..),
+ CmmInfo(..), UpdateFrame(..), CmmInfoTable(..), ClosureTypeInfo(..),
+ CmmStatic(..), CmmStatics(..), CmmFormal, CmmActual,
cmmMapGraph, cmmTopMapGraph,
cmmMapGraphM, cmmTopMapGraphM,
GenBasicBlock(..), CmmBasicBlock, blockId, blockStmts, mapBlockStmts,
CmmStmt(..), CmmReturnInfo(..), CmmHinted(..),
HintedCmmFormal, HintedCmmActual,
CmmSafety(..), CmmCallTarget(..),
- module CmmDecl,
+ New.GenCmmTop(..),
+ New.ForeignHint(..),
module CmmExpr,
+ Section(..),
+ ProfilingInfo(..), C_SRT(..)
) where
#include "HsVersions.h"
+import qualified Cmm as New
+import Cmm ( CmmInfoTable(..), GenCmmPgm, CmmStatics(..), GenCmmTop(..),
+ CmmFormal, CmmActual, Section(..), CmmStatic(..),
+ ProfilingInfo(..), ClosureTypeInfo(..) )
+
import BlockId
-import CmmDecl
import CmmExpr
import ForeignCall
-
import ClosureInfo
import Outputable
import FastString
@@ -73,14 +80,14 @@ newtype ListGraph i = ListGraph [GenBasicBlock i]
-- across a whole compilation unit.
-- | Cmm with the info table as a data type
-type Cmm = GenCmm CmmStatics CmmInfo (ListGraph CmmStmt)
+type CmmPgm = GenCmmPgm CmmStatics CmmInfo (ListGraph CmmStmt)
type CmmTop = GenCmmTop CmmStatics CmmInfo (ListGraph CmmStmt)
-- | Cmm with the info tables converted to a list of 'CmmStatic' along with the info
-- table label. If we are building without tables-next-to-code there will be no statics
--
-- INVARIANT: if there is an info table, it has at least one CmmStatic
-type RawCmm = GenCmm CmmStatics (Maybe CmmStatics) (ListGraph CmmStmt)
+type RawCmmPgm = GenCmmPgm CmmStatics (Maybe CmmStatics) (ListGraph CmmStmt)
type RawCmmTop = GenCmmTop CmmStatics (Maybe CmmStatics) (ListGraph CmmStmt)
@@ -111,17 +118,17 @@ mapBlockStmts f (BasicBlock id bs) = BasicBlock id (map f bs)
-- graph maps
----------------------------------------------------------------
-cmmMapGraph :: (g -> g') -> GenCmm d h g -> GenCmm d h g'
+cmmMapGraph :: (g -> g') -> GenCmmPgm d h g -> GenCmmPgm d h g'
cmmTopMapGraph :: (g -> g') -> GenCmmTop d h g -> GenCmmTop d h g'
-cmmMapGraphM :: Monad m => (String -> g -> m g') -> GenCmm d h g -> m (GenCmm d h g')
+cmmMapGraphM :: Monad m => (String -> g -> m g') -> GenCmmPgm d h g -> m (GenCmmPgm d h g')
cmmTopMapGraphM :: Monad m => (String -> g -> m g') -> GenCmmTop d h g -> m (GenCmmTop d h g')
-cmmMapGraph f (Cmm tops) = Cmm $ map (cmmTopMapGraph f) tops
+cmmMapGraph f tops = map (cmmTopMapGraph f) tops
cmmTopMapGraph f (CmmProc h l g) = CmmProc h l (f g)
cmmTopMapGraph _ (CmmData s ds) = CmmData s ds
-cmmMapGraphM f (Cmm tops) = mapM (cmmTopMapGraphM f) tops >>= return . Cmm
+cmmMapGraphM f tops = mapM (cmmTopMapGraphM f) tops
cmmTopMapGraphM f (CmmProc h l g) =
f (showSDoc $ ppr l) g >>= return . CmmProc h l
cmmTopMapGraphM _ (CmmData s ds) = return $ CmmData s ds
@@ -172,7 +179,7 @@ data CmmStmt -- Old-style
| CmmReturn -- Return from a native C-- function,
[HintedCmmActual] -- with these return values. (parameters never used)
-data CmmHinted a = CmmHinted { hintlessCmm :: a, cmmHint :: ForeignHint }
+data CmmHinted a = CmmHinted { hintlessCmm :: a, cmmHint :: New.ForeignHint }
deriving( Eq )
type HintedCmmFormal = CmmHinted CmmFormal
diff --git a/compiler/cmm/OldPprCmm.hs b/compiler/cmm/OldPprCmm.hs
index 4050359710..b31cc96dbc 100644
--- a/compiler/cmm/OldPprCmm.hs
+++ b/compiler/cmm/OldPprCmm.hs
@@ -86,19 +86,13 @@ instance Outputable CmmSafety where
-- style of C--'s 'stackdata' declaration, just inside the proc body,
-- and were labelled with the procedure name ++ "_info".
pprInfo :: CmmInfo -> SDoc
-pprInfo (CmmInfo _gc_target update_frame CmmNonInfoTable) =
- vcat [{-ptext (sLit "gc_target: ") <>
- maybe (ptext (sLit "<none>")) ppr gc_target,-}
- ptext (sLit "update_frame: ") <>
- maybe (ptext (sLit "<none>")) pprUpdateFrame update_frame]
-pprInfo (CmmInfo _gc_target update_frame info_table@(CmmInfoTable _ _ _ _ _)) =
+pprInfo (CmmInfo _gc_target update_frame info_table) =
vcat [{-ptext (sLit "gc_target: ") <>
maybe (ptext (sLit "<none>")) ppr gc_target,-}
ptext (sLit "update_frame: ") <>
maybe (ptext (sLit "<none>")) pprUpdateFrame update_frame,
ppr info_table]
-
-- --------------------------------------------------------------------------
-- Basic blocks look like assembly blocks.
-- lbl: stmt ; stmt ; ..
diff --git a/compiler/cmm/PprC.hs b/compiler/cmm/PprC.hs
index 51b0031ad3..80135503ff 100644
--- a/compiler/cmm/PprC.hs
+++ b/compiler/cmm/PprC.hs
@@ -65,7 +65,7 @@ import Control.Monad.ST
-- --------------------------------------------------------------------------
-- Top level
-pprCs :: DynFlags -> [RawCmm] -> SDoc
+pprCs :: DynFlags -> [RawCmmPgm] -> SDoc
pprCs dflags cmms
= pprCode CStyle (vcat $ map (\c -> split_marker $$ pprC c) cmms)
where
@@ -73,7 +73,7 @@ pprCs dflags cmms
| dopt Opt_SplitObjs dflags = ptext (sLit "__STG_SPLIT_MARKER")
| otherwise = empty
-writeCs :: DynFlags -> Handle -> [RawCmm] -> IO ()
+writeCs :: DynFlags -> Handle -> [RawCmmPgm] -> IO ()
writeCs dflags handle cmms
= printForC handle (pprCs dflags cmms)
@@ -83,8 +83,8 @@ writeCs dflags handle cmms
-- for fun, we could call cmmToCmm over the tops...
--
-pprC :: RawCmm -> SDoc
-pprC (Cmm tops) = vcat $ intersperse blankLine $ map pprTop tops
+pprC :: RawCmmPgm -> SDoc
+pprC tops = vcat $ intersperse blankLine $ map pprTop tops
--
-- top level procs
diff --git a/compiler/cmm/PprCmm.hs b/compiler/cmm/PprCmm.hs
index 43e1c5bb2f..521ab059b7 100644
--- a/compiler/cmm/PprCmm.hs
+++ b/compiler/cmm/PprCmm.hs
@@ -40,8 +40,7 @@ where
import BlockId ()
import CLabel
import Cmm
-import CmmExpr
-import CmmUtils (isTrivialCmmExpr)
+import CmmUtils
import FastString
import Outputable
import PprCmmDecl
diff --git a/compiler/cmm/PprCmmDecl.hs b/compiler/cmm/PprCmmDecl.hs
index f688f211fb..c973f2d2f0 100644
--- a/compiler/cmm/PprCmmDecl.hs
+++ b/compiler/cmm/PprCmmDecl.hs
@@ -33,14 +33,13 @@
--
module PprCmmDecl
- ( writeCmms, pprCmms, pprCmm, pprSection, pprStatic
+ ( writeCmms, pprCmms, pprCmmPgm, pprSection, pprStatic
)
where
-import CmmDecl
import CLabel
import PprCmmExpr
-
+import Cmm
import Outputable
import Platform
@@ -51,26 +50,21 @@ import System.IO
-- Temp Jan08
import SMRep
-import ClosureInfo
#include "../includes/rts/storage/FunTypes.h"
pprCmms :: (Outputable info, PlatformOutputable g)
- => Platform -> [GenCmm CmmStatics info g] -> SDoc
+ => Platform -> [GenCmmPgm CmmStatics info g] -> SDoc
pprCmms platform cmms = pprCode CStyle (vcat (intersperse separator $ map (pprPlatform platform) cmms))
where
separator = space $$ ptext (sLit "-------------------") $$ space
writeCmms :: (Outputable info, PlatformOutputable g)
- => Platform -> Handle -> [GenCmm CmmStatics info g] -> IO ()
+ => Platform -> Handle -> [GenCmmPgm CmmStatics info g] -> IO ()
writeCmms platform handle cmms = printForC handle (pprCmms platform cmms)
-----------------------------------------------------------------------------
-instance (Outputable d, Outputable info, PlatformOutputable g)
- => PlatformOutputable (GenCmm d info g) where
- pprPlatform platform c = pprCmm platform c
-
instance (Outputable d, Outputable info, PlatformOutputable i)
=> PlatformOutputable (GenCmmTop d info i) where
pprPlatform platform t = pprTop platform t
@@ -87,9 +81,9 @@ instance Outputable CmmInfoTable where
-----------------------------------------------------------------------------
-pprCmm :: (Outputable d, Outputable info, PlatformOutputable g)
- => Platform -> GenCmm d info g -> SDoc
-pprCmm platform (Cmm tops)
+pprCmmPgm :: (Outputable d, Outputable info, PlatformOutputable g)
+ => Platform -> GenCmmPgm d info g -> SDoc
+pprCmmPgm platform tops
= vcat $ intersperse blankLine $ map (pprTop platform) tops
-- --------------------------------------------------------------------------
@@ -118,55 +112,22 @@ pprTop _ (CmmData section ds) =
-- Info tables.
pprInfoTable :: CmmInfoTable -> SDoc
-pprInfoTable CmmNonInfoTable = empty
-pprInfoTable (CmmInfoTable is_local stat_clos (ProfilingInfo closure_type closure_desc) tag info) =
- vcat [ptext (sLit "is local: ") <> ppr is_local <+>
- ptext (sLit "has static closure: ") <> ppr stat_clos <+>
- ptext (sLit "type: ") <> pprLit closure_type,
- ptext (sLit "desc: ") <> pprLit closure_desc,
- ptext (sLit "tag: ") <> integer (toInteger tag),
- pprTypeInfo info]
-
-pprTypeInfo :: ClosureTypeInfo -> SDoc
-pprTypeInfo (ConstrInfo layout constr descr) =
- vcat [ptext (sLit "ptrs: ") <> integer (toInteger (fst layout)),
- ptext (sLit "nptrs: ") <> integer (toInteger (snd layout)),
- ptext (sLit "constructor: ") <> integer (toInteger constr),
- pprLit descr]
-pprTypeInfo (FunInfo layout srt arity _args slow_entry) =
- vcat [ptext (sLit "ptrs: ") <> integer (toInteger (fst layout)),
- ptext (sLit "nptrs: ") <> integer (toInteger (snd layout)),
- ptext (sLit "srt: ") <> ppr srt,
--- Temp Jan08
- ptext (sLit ("fun_type: ")) <> integer (toInteger (argDescrType _args)),
-
- ptext (sLit "arity: ") <> integer (toInteger arity),
- --ptext (sLit "args: ") <> ppr args, -- TODO: needs to be printed
- ptext (sLit "slow: ") <> pprLit slow_entry
- ]
-pprTypeInfo (ThunkInfo layout srt) =
- vcat [ptext (sLit "ptrs: ") <> integer (toInteger (fst layout)),
- ptext (sLit "nptrs: ") <> integer (toInteger (snd layout)),
- ptext (sLit "srt: ") <> ppr srt]
-pprTypeInfo (ThunkSelectorInfo offset srt) =
- vcat [ptext (sLit "ptrs: ") <> integer (toInteger offset),
- ptext (sLit "srt: ") <> ppr srt]
-pprTypeInfo (ContInfo stack srt) =
- vcat [ptext (sLit "stack: ") <> ppr stack,
- ptext (sLit "srt: ") <> ppr srt]
-
--- Temp Jan08
-argDescrType :: ArgDescr -> StgHalfWord
--- The "argument type" RTS field type
-argDescrType (ArgSpec n) = n
-argDescrType (ArgGen liveness)
- | isBigLiveness liveness = ARG_GEN_BIG
- | otherwise = ARG_GEN
-
--- Temp Jan08
-isBigLiveness :: Liveness -> Bool
-isBigLiveness (BigLiveness _) = True
-isBigLiveness (SmallLiveness _) = False
+pprInfoTable CmmNonInfoTable
+ = empty
+pprInfoTable (CmmInfoTable { cit_lbl = lbl, cit_rep = rep
+ , cit_prof = prof_info
+ , cit_srt = _srt })
+ = vcat [ ptext (sLit "label:") <+> ppr lbl
+ , ptext (sLit "rep:") <> ppr rep
+ , case prof_info of
+ NoProfilingInfo -> empty
+ ProfilingInfo ct cd -> vcat [ ptext (sLit "type:") <+> pprWord8String ct
+ , ptext (sLit "desc: ") <> pprWord8String cd ] ]
+
+instance Outputable C_SRT where
+ ppr (NoC_SRT) = ptext (sLit "_no_srt_")
+ ppr (C_SRT label off bitmap) = parens (ppr label <> comma <> ppr off <> comma
+ <> text (show bitmap))
instance Outputable ForeignHint where
ppr NoHint = empty
diff --git a/compiler/cmm/cmm-notes b/compiler/cmm/cmm-notes
index 5cfd5f2788..e9a6a60b5f 100644
--- a/compiler/cmm/cmm-notes
+++ b/compiler/cmm/cmm-notes
@@ -17,6 +17,9 @@ Things we did
More notes (June 11)
~~~~~~~~~~~~~~~~~~~~
+* Check in ClosureInfo:
+ -- NB: Results here should line up with the results of SMRep.rtsClosureType
+
* Possible refactoring: Nuke AGraph in favour of
mkIfThenElse :: Expr -> Graph -> Graph -> FCode Graph
or even
@@ -248,6 +251,60 @@ Things to do:
(guided by the procpoint set)
----------------------------------------------------
+ Modules in codeGen/
+----------------------------------------------------
+
+
+------- Shared ---------
+Bitmap.hs
+SMRep.lhs
+
+CmmParse.y
+CgExtCode.hs used in CmmParse.y
+
+------- New codegen ---------
+
+StgCmm.hs
+StgCmmBind.hs
+StgCmmClosure.hs (corresponds to old ClosureInfo)
+StgCmmCon.hs
+StgCmmEnv.hs
+StgCmmExpr.hs
+StgCmmForeign.hs
+StgCmmGran.hs
+StgCmmHeap.hs
+StgCmmHpc.hs
+StgCmmLayout.hs
+StgCmmMonad.hs
+StgCmmPrim.hs
+StgCmmProf.hs
+StgCmmTicky.hs
+StgCmmUtils.hs
+
+------- Old codegen (moribund) ---------
+CodeGen.lhs
+CgBindery.lhs
+CgCallConv.hs
+CgCase.lhs
+CgClosure.lhs
+CgCon.lhs
+CgExpr.lhs
+CgLetNoEscape.lhs
+CgForeignCall.hs
+CgHeapery.lhs
+CgHpc.hs
+CgInfoTbls.hs
+CgMonad.lhs
+CgParallel.hs
+CgPrimOp.hs
+CgProf.hs
+CgStackery.lhs
+CgTailCall.lhs
+CgTicky.hs
+CgUtils.hs
+ClosureInfo.lhs
+
+----------------------------------------------------
Modules in cmm/
----------------------------------------------------
diff --git a/compiler/codeGen/CgCallConv.hs b/compiler/codeGen/CgCallConv.hs
index f3013cd5a6..1001969592 100644
--- a/compiler/codeGen/CgCallConv.hs
+++ b/compiler/codeGen/CgCallConv.hs
@@ -11,11 +11,10 @@
module CgCallConv (
-- Argument descriptors
- mkArgDescr, argDescrType,
+ mkArgDescr,
-- Liveness
- isBigLiveness, mkRegLiveness,
- smallLiveness, mkLivenessCLit,
+ mkRegLiveness,
-- Register assignment
assignCallRegs, assignReturnRegs, assignPrimOpCallRegs,
@@ -28,7 +27,6 @@ module CgCallConv (
getSequelAmode
) where
-import CgUtils
import CgMonad
import SMRep
@@ -36,20 +34,16 @@ import OldCmm
import CLabel
import Constants
-import ClosureInfo
import CgStackery
import OldCmmUtils
import Maybes
import Id
import Name
-import Bitmap
import Util
import StaticFlags
import Module
import FastString
import Outputable
-import Unique
-
import Data.Bits
-------------------------------------------------------------------------
@@ -68,28 +62,16 @@ import Data.Bits
#include "../includes/rts/storage/FunTypes.h"
-------------------------
-argDescrType :: ArgDescr -> StgHalfWord
--- The "argument type" RTS field type
-argDescrType (ArgSpec n) = n
-argDescrType (ArgGen liveness)
- | isBigLiveness liveness = ARG_GEN_BIG
- | otherwise = ARG_GEN
-
-
mkArgDescr :: Name -> [Id] -> FCode ArgDescr
-mkArgDescr nm args
+mkArgDescr _nm args
= case stdPattern arg_reps of
Just spec_id -> return (ArgSpec spec_id)
- Nothing -> do { liveness <- mkLiveness nm size bitmap
- ; return (ArgGen liveness) }
+ Nothing -> return (ArgGen arg_bits)
where
+ arg_bits = argBits arg_reps
arg_reps = filter nonVoidArg (map idCgRep args)
-- Getting rid of voids eases matching of standard patterns
- bitmap = mkBitmap arg_bits
- arg_bits = argBits arg_reps
- size = length arg_bits
-
argBits :: [CgRep] -> [Bool] -- True for non-ptr, False for ptr
argBits [] = []
argBits (PtrArg : args) = False : argBits args
@@ -126,52 +108,6 @@ stdPattern _ = Nothing
-------------------------------------------------------------------------
--
--- Liveness info
---
--------------------------------------------------------------------------
-
--- TODO: This along with 'mkArgDescr' should be unified
--- with 'CmmInfo.mkLiveness'. However that would require
--- potentially invasive changes to the 'ClosureInfo' type.
--- For now, 'CmmInfo.mkLiveness' handles only continuations and
--- this one handles liveness everything else. Another distinction
--- between these two is that 'CmmInfo.mkLiveness' information
--- about the stack layout, and this one is information about
--- the heap layout of PAPs.
-mkLiveness :: Name -> Int -> Bitmap -> FCode Liveness
-mkLiveness name size bits
- | size > mAX_SMALL_BITMAP_SIZE -- Bitmap does not fit in one word
- = do { let lbl = mkBitmapLabel (getUnique name)
- ; emitRODataLits "mkLiveness" lbl ( mkWordCLit (fromIntegral size)
- : map mkWordCLit bits)
- ; return (BigLiveness lbl) }
-
- | otherwise -- Bitmap fits in one word
- = let
- small_bits = case bits of
- [] -> 0
- [b] -> b
- _ -> panic "livenessToAddrMode"
- in
- return (smallLiveness size small_bits)
-
-smallLiveness :: Int -> StgWord -> Liveness
-smallLiveness size small_bits = SmallLiveness bits
- where bits = fromIntegral size .|. (small_bits `shiftL` bITMAP_BITS_SHIFT)
-
--------------------
-isBigLiveness :: Liveness -> Bool
-isBigLiveness (BigLiveness _) = True
-isBigLiveness (SmallLiveness _) = False
-
--------------------
-mkLivenessCLit :: Liveness -> CmmLit
-mkLivenessCLit (BigLiveness lbl) = CmmLabel lbl
-mkLivenessCLit (SmallLiveness bits) = mkWordCLit bits
-
-
--------------------------------------------------------------------------
---
-- Bitmap describing register liveness
-- across GC when doing a "generic" heap check
-- (a RET_DYN stack frame).
diff --git a/compiler/codeGen/CgCon.lhs b/compiler/codeGen/CgCon.lhs
index 8768008776..33fedfd01b 100644
--- a/compiler/codeGen/CgCon.lhs
+++ b/compiler/codeGen/CgCon.lhs
@@ -402,7 +402,7 @@ For charlike and intlike closures there is a fixed array of static
closures predeclared.
\begin{code}
-cgTyCon :: TyCon -> FCode [Cmm] -- each constructor gets a separate Cmm
+cgTyCon :: TyCon -> FCode CmmPgm -- each constructor gets a separate CmmPgm
cgTyCon tycon
= do { constrs <- mapM (getCmm . cgDataCon) (tyConDataCons tycon)
@@ -423,7 +423,7 @@ cgTyCon tycon
else
return []
- ; return (extra ++ constrs)
+ ; return (concat (extra ++ constrs))
}
\end{code}
diff --git a/compiler/codeGen/CgExtCode.hs b/compiler/codeGen/CgExtCode.hs
index 12efa03da0..5c56ee0bd5 100644
--- a/compiler/codeGen/CgExtCode.hs
+++ b/compiler/codeGen/CgExtCode.hs
@@ -39,7 +39,7 @@ where
import CgMonad
import CLabel
-import OldCmm
+import OldCmm hiding( ClosureTypeInfo(..) )
-- import BasicTypes
import BlockId
@@ -51,11 +51,11 @@ import Unique
-- | The environment contains variable definitions or blockids.
data Named
- = Var CmmExpr -- ^ Holds CmmLit(CmmLabel ..) which gives the label type,
+ = VarN CmmExpr -- ^ Holds CmmLit(CmmLabel ..) which gives the label type,
-- eg, RtsLabel, ForeignLabel, CmmLabel etc.
- | Fun PackageId -- ^ A function name from this package
- | Label BlockId -- ^ A blockid of some code or data.
+ | FunN PackageId -- ^ A function name from this package
+ | LabelN BlockId -- ^ A blockid of some code or data.
-- | An environment of named things.
type Env = UniqFM Named
@@ -103,12 +103,12 @@ getEnv = EC $ \e s -> return (s, e)
-- The CmmExpr says where the value is stored.
addVarDecl :: FastString -> CmmExpr -> ExtCode
addVarDecl var expr
- = EC $ \_ s -> return ((var, Var expr):s, ())
+ = EC $ \_ s -> return ((var, VarN expr):s, ())
-- | Add a new label to the list of local declarations.
addLabel :: FastString -> BlockId -> ExtCode
addLabel name block_id
- = EC $ \_ s -> return ((name, Label block_id):s, ())
+ = EC $ \_ s -> return ((name, LabelN block_id):s, ())
-- | Create a fresh local variable of a given type.
@@ -139,7 +139,7 @@ newFunctionName
-> ExtCode
newFunctionName name pkg
- = EC $ \_ s -> return ((name, Fun pkg):s, ())
+ = EC $ \_ s -> return ((name, FunN pkg):s, ())
-- | Add an imported foreign label to the list of local declarations.
@@ -161,7 +161,7 @@ lookupLabel name = do
env <- getEnv
return $
case lookupUFM env name of
- Just (Label l) -> l
+ Just (LabelN l) -> l
_other -> mkBlockId (newTagUnique (getUnique name) 'L')
@@ -174,8 +174,8 @@ lookupName name = do
env <- getEnv
return $
case lookupUFM env name of
- Just (Var e) -> e
- Just (Fun pkg) -> CmmLit (CmmLabel (mkCmmCodeLabel pkg name))
+ Just (VarN e) -> e
+ Just (FunN pkg) -> CmmLit (CmmLabel (mkCmmCodeLabel pkg name))
_other -> CmmLit (CmmLabel (mkCmmCodeLabel rtsPackageId name))
diff --git a/compiler/codeGen/CgForeignCall.hs b/compiler/codeGen/CgForeignCall.hs
index fff21af8cb..73db412bbe 100644
--- a/compiler/codeGen/CgForeignCall.hs
+++ b/compiler/codeGen/CgForeignCall.hs
@@ -29,7 +29,6 @@ import OldCmm
import OldCmmUtils
import SMRep
import ForeignCall
-import ClosureInfo
import Constants
import StaticFlags
import Outputable
diff --git a/compiler/codeGen/CgInfoTbls.hs b/compiler/codeGen/CgInfoTbls.hs
index dbd22f3906..92db95eba8 100644
--- a/compiler/codeGen/CgInfoTbls.hs
+++ b/compiler/codeGen/CgInfoTbls.hs
@@ -9,7 +9,6 @@
module CgInfoTbls (
emitClosureCodeAndInfoTable,
emitInfoTableAndCode,
- dataConTagZ,
emitReturnTarget, emitAlgReturnTarget,
emitReturnInstr,
stdInfoTableSizeB,
@@ -30,12 +29,11 @@ import CgBindery
import CgCallConv
import CgUtils
import CgMonad
+import CmmBuildInfoTables
-import OldCmmUtils
import OldCmm
import CLabel
import Name
-import DataCon
import Unique
import StaticFlags
@@ -59,58 +57,20 @@ emitClosureCodeAndInfoTable cl_info args body
; info <- mkCmmInfo cl_info
; emitInfoTableAndCode (entryLabelFromCI cl_info) info args blks }
--- We keep the *zero-indexed* tag in the srt_len field of the info
--- table of a data constructor.
-dataConTagZ :: DataCon -> ConTagZ
-dataConTagZ con = dataConTag con - fIRST_TAG
-
-- Convert from 'ClosureInfo' to 'CmmInfo'.
-- Not used for return points. (The 'smRepClosureTypeInt' call would panic.)
mkCmmInfo :: ClosureInfo -> FCode CmmInfo
-mkCmmInfo cl_info = do
- prof <-
- if opt_SccProfilingOn
- then do ty_descr_lit <- mkStringCLit (closureTypeDescr cl_info)
- cl_descr_lit <- mkStringCLit (closureValDescr cl_info)
- return $ ProfilingInfo ty_descr_lit cl_descr_lit
- else return $ ProfilingInfo (mkIntCLit 0) (mkIntCLit 0)
-
- case cl_info of
- ConInfo { closureCon = con } -> do
- cstr <- mkByteStringCLit $ dataConIdentity con
- let conName = makeRelativeRefTo info_lbl cstr
- info = ConstrInfo (ptrs, nptrs)
- (fromIntegral (dataConTagZ con))
- conName
- return $ CmmInfo gc_target Nothing (CmmInfoTable (infoTableLabelFromCI cl_info) False prof cl_type info)
-
- ClosureInfo { closureName = name,
- closureLFInfo = lf_info,
- closureSRT = srt } ->
- return $ CmmInfo gc_target Nothing (CmmInfoTable (infoTableLabelFromCI cl_info) False prof cl_type info)
- where
- info =
- case lf_info of
- LFReEntrant _ arity _ arg_descr ->
- FunInfo (ptrs, nptrs)
- srt
- (fromIntegral arity)
- arg_descr
- (CmmLabel (mkSlowEntryLabel name has_caf_refs))
- LFThunk _ _ _ (SelectorThunk offset) _ ->
- ThunkSelectorInfo (fromIntegral offset) srt
- LFThunk _ _ _ _ _ ->
- ThunkInfo (ptrs, nptrs) srt
- _ -> panic "unexpected lambda form in mkCmmInfo"
+mkCmmInfo cl_info
+ = return (CmmInfo gc_target Nothing $
+ CmmInfoTable { cit_lbl = infoTableLabelFromCI cl_info,
+ cit_rep = closureSMRep cl_info,
+ cit_prof = prof,
+ cit_srt = closureSRT cl_info })
where
- info_lbl = infoTableLabelFromCI cl_info
- has_caf_refs = clHasCafRefs cl_info
-
- cl_type = smRepClosureTypeInt (closureSMRep cl_info)
-
- ptrs = fromIntegral $ closurePtrsSize cl_info
- size = fromIntegral $ closureNonHdrSize cl_info
- nptrs = size - ptrs
+ prof | not opt_SccProfilingOn = NoProfilingInfo
+ | otherwise = ProfilingInfo ty_descr_w8 val_descr_w8
+ ty_descr_w8 = stringToWord8s (closureTypeDescr cl_info)
+ val_descr_w8 = stringToWord8s (closureValDescr cl_info)
-- The gc_target is to inform the CPS pass when it inserts a stack check.
-- Since that pass isn't used yet we'll punt for now.
@@ -137,13 +97,12 @@ emitReturnTarget name stmts
= do { srt_info <- getSRTInfo
; blks <- cgStmtsToBlocks stmts
; frame <- mkStackLayout
- ; let info = CmmInfo
- gc_target
- Nothing
- (CmmInfoTable info_lbl False
- (ProfilingInfo zeroCLit zeroCLit)
- rET_SMALL -- cmmToRawCmm may convert it to rET_BIG
- (ContInfo frame srt_info))
+ ; let smrep = mkStackRep (mkLiveness frame)
+ info = CmmInfo gc_target Nothing info_tbl
+ info_tbl = CmmInfoTable { cit_lbl = info_lbl
+ , cit_prof = NoProfilingInfo
+ , cit_rep = smrep
+ , cit_srt = srt_info }
; emitInfoTableAndCode entry_lbl info args blks
; return info_lbl }
where
@@ -160,7 +119,6 @@ emitReturnTarget name stmts
-- and stack checks (from the CPS pass).
gc_target = panic "TODO: gc_target"
-
-- Build stack layout information from the state of the 'FCode' monad.
-- Should go away once 'codeGen' starts using the CPS conversion
-- pass to handle the stack. Until then, this is really just
diff --git a/compiler/codeGen/CgMonad.lhs b/compiler/codeGen/CgMonad.lhs
index 273c1bf16e..6ee9581087 100644
--- a/compiler/codeGen/CgMonad.lhs
+++ b/compiler/codeGen/CgMonad.lhs
@@ -8,6 +8,7 @@ See the beginning of the top-level @CodeGen@ module, to see how this
monadic stuff fits into the Big Picture.
\begin{code}
+{-# LANGUAGE BangPatterns #-}
module CgMonad (
Code, -- type
FCode, -- type
@@ -22,7 +23,7 @@ module CgMonad (
noCgStmts, oneCgStmt, consCgStmt,
getCmm,
- emitData, emitProc, emitSimpleProc,
+ emitDecl, emitProc, emitSimpleProc,
forkLabelledCode,
forkClosureBody, forkStatics, forkAlts, forkEval,
@@ -67,6 +68,7 @@ import OldCmm
import OldCmmUtils
import CLabel
import StgSyn (SRT)
+import ClosureInfo( ConTagZ )
import SMRep
import Module
import Id
@@ -179,8 +181,6 @@ type SemiTaggingStuff
([(ConTagZ, CmmLit)], -- Alternatives
CmmLit) -- Default (will be a can't happen RTS label if can't happen)
-type ConTagZ = Int -- A *zero-indexed* contructor tag
-
-- The case branch is executed only from a successful semitagging
-- venture, when a case has looked at a variable, found that it's
-- evaluated, and wants to load up the contents and go to the join
@@ -415,8 +415,8 @@ thenFC :: FCode a -> (a -> FCode c) -> FCode c
thenFC (FCode m) k = FCode (
\info_down state ->
let
- (m_result, new_state) = m info_down state
- (FCode kcode) = k m_result
+ (m_result, new_state) = m info_down state
+ (FCode kcode) = k m_result
in
kcode info_down new_state
)
@@ -736,12 +736,10 @@ emitCgStmt stmt
; setState $ state { cgs_stmts = cgs_stmts state `snocOL` stmt }
}
-emitData :: Section -> CmmStatics -> Code
-emitData sect lits
+emitDecl :: CmmTop -> Code
+emitDecl decl
= do { state <- getState
- ; setState $ state { cgs_tops = cgs_tops state `snocOL` data_block } }
- where
- data_block = CmmData sect lits
+ ; setState $ state { cgs_tops = cgs_tops state `snocOL` decl } }
emitProc :: CmmInfo -> CLabel -> [CmmFormal] -> [CmmBasicBlock] -> Code
emitProc info lbl [] blocks
@@ -757,7 +755,7 @@ emitSimpleProc lbl code
; blks <- cgStmtsToBlocks stmts
; emitProc (CmmInfo Nothing Nothing CmmNonInfoTable) lbl [] blks }
-getCmm :: Code -> FCode Cmm
+getCmm :: Code -> FCode CmmPgm
-- Get all the CmmTops (there should be no stmts)
-- Return a single Cmm which may be split from other Cmms by
-- object splitting (at a later stage)
@@ -765,7 +763,7 @@ getCmm code
= do { state1 <- getState
; ((), state2) <- withState code (state1 { cgs_tops = nilOL })
; setState $ state2 { cgs_tops = cgs_tops state1 }
- ; return (Cmm (fromOL (cgs_tops state2)))
+ ; return (fromOL (cgs_tops state2))
}
-- ----------------------------------------------------------------------------
diff --git a/compiler/codeGen/CgProf.hs b/compiler/codeGen/CgProf.hs
index 243aa1d89a..b58fbb4238 100644
--- a/compiler/codeGen/CgProf.hs
+++ b/compiler/codeGen/CgProf.hs
@@ -294,8 +294,8 @@ emitCostCentreDecl
:: CostCentre
-> Code
emitCostCentreDecl cc = do
- { label <- mkStringCLit (costCentreUserName cc)
- ; modl <- mkStringCLit (Module.moduleNameString
+ { label <- newStringCLit (costCentreUserName cc)
+ ; modl <- newStringCLit (Module.moduleNameString
(Module.moduleName (cc_mod cc)))
-- All cost centres will be in the main package, since we
-- don't normally use -auto-all or add SCCs to other packages.
diff --git a/compiler/codeGen/CgTicky.hs b/compiler/codeGen/CgTicky.hs
index 629754fcb5..daeba9274b 100644
--- a/compiler/codeGen/CgTicky.hs
+++ b/compiler/codeGen/CgTicky.hs
@@ -85,8 +85,8 @@ emitTickyCounter :: ClosureInfo -> [Id] -> Int -> Code
emitTickyCounter cl_info args on_stk
= ifTicky $
do { mod_name <- getModuleName
- ; fun_descr_lit <- mkStringCLit (fun_descr mod_name)
- ; arg_descr_lit <- mkStringCLit arg_descr
+ ; fun_descr_lit <- newStringCLit (fun_descr mod_name)
+ ; arg_descr_lit <- newStringCLit arg_descr
; emitDataLits ticky_ctr_label -- Must match layout of StgEntCounter
-- krc: note that all the fields are I32 now; some were I16 before,
-- but the code generator wasn't handling that properly and it led to chaos,
@@ -246,18 +246,16 @@ tickyDynAlloc :: ClosureInfo -> Code
-- Called when doing a dynamic heap allocation
tickyDynAlloc cl_info
= ifTicky $
- case smRepClosureType (closureSMRep cl_info) of
- Just Constr -> tick_alloc_con
- Just ConstrNoCaf -> tick_alloc_con
- Just Fun -> tick_alloc_fun
- Just Thunk -> tick_alloc_thk
- Just ThunkSelector -> tick_alloc_thk
+ case closureLFInfo cl_info of
+ LFCon {} -> tick_alloc_con
+ LFReEntrant {} -> tick_alloc_fun
+ LFThunk {} -> tick_alloc_thk
-- black hole
- Nothing -> return ()
+ _ -> return ()
where
-- will be needed when we fill in stubs
- _cl_size = closureSize cl_info
- _slop_size = slopSize cl_info
+ _cl_size = closureSize cl_info
+-- _slop_size = slopSize cl_info
tick_alloc_thk
| closureUpdReqd cl_info = tick_alloc_up_thk
diff --git a/compiler/codeGen/CgUtils.hs b/compiler/codeGen/CgUtils.hs
index 1d2902188c..77f88470a5 100644
--- a/compiler/codeGen/CgUtils.hs
+++ b/compiler/codeGen/CgUtils.hs
@@ -43,7 +43,7 @@ module CgUtils (
addToMem, addToMemE,
mkWordCLit,
- mkStringCLit, mkByteStringCLit,
+ newStringCLit, newByteStringCLit,
packHalfWordsCLit,
blankWord,
@@ -98,7 +98,7 @@ addIdReps ids = [(idCgRep id, id) | id <- ids]
-------------------------------------------------------------------------
cgLit :: Literal -> FCode CmmLit
-cgLit (MachStr s) = mkByteStringCLit (bytesFS s)
+cgLit (MachStr s) = newByteStringCLit (bytesFS s)
-- not unpackFS; we want the UTF-8 byte stream.
cgLit other_lit = return (mkSimpleLit other_lit)
@@ -131,88 +131,7 @@ mkLtOp lit = MO_U_Lt (typeWidth (cmmLitType (mkSimpleLit lit)))
--
---------------------------------------------------
------------------------
--- The "B" variants take byte offsets
-cmmRegOffB :: CmmReg -> ByteOff -> CmmExpr
-cmmRegOffB = cmmRegOff
-
-cmmOffsetB :: CmmExpr -> ByteOff -> CmmExpr
-cmmOffsetB = cmmOffset
-
-cmmOffsetExprB :: CmmExpr -> CmmExpr -> CmmExpr
-cmmOffsetExprB = cmmOffsetExpr
-
-cmmLabelOffB :: CLabel -> ByteOff -> CmmLit
-cmmLabelOffB = cmmLabelOff
-
-cmmOffsetLitB :: CmmLit -> ByteOff -> CmmLit
-cmmOffsetLitB = cmmOffsetLit
-
------------------------
--- The "W" variants take word offsets
-cmmOffsetExprW :: CmmExpr -> CmmExpr -> CmmExpr
--- The second arg is a *word* offset; need to change it to bytes
-cmmOffsetExprW e (CmmLit (CmmInt n _)) = cmmOffsetW e (fromInteger n)
-cmmOffsetExprW e wd_off = cmmIndexExpr wordWidth e wd_off
-
-cmmOffsetW :: CmmExpr -> WordOff -> CmmExpr
-cmmOffsetW e n = cmmOffsetB e (wORD_SIZE * n)
-
-cmmRegOffW :: CmmReg -> WordOff -> CmmExpr
-cmmRegOffW reg wd_off = cmmRegOffB reg (wd_off * wORD_SIZE)
-
-cmmOffsetLitW :: CmmLit -> WordOff -> CmmLit
-cmmOffsetLitW lit wd_off = cmmOffsetLitB lit (wORD_SIZE * wd_off)
-
-cmmLabelOffW :: CLabel -> WordOff -> CmmLit
-cmmLabelOffW lbl wd_off = cmmLabelOffB lbl (wORD_SIZE * wd_off)
-
-cmmLoadIndexW :: CmmExpr -> Int -> CmmType -> CmmExpr
-cmmLoadIndexW base off ty = CmmLoad (cmmOffsetW base off) ty
-
------------------------
-cmmNeWord, cmmEqWord, cmmOrWord, cmmAndWord :: CmmExpr -> CmmExpr -> CmmExpr
-cmmOrWord e1 e2 = CmmMachOp mo_wordOr [e1, e2]
-cmmAndWord e1 e2 = CmmMachOp mo_wordAnd [e1, e2]
-cmmNeWord e1 e2 = CmmMachOp mo_wordNe [e1, e2]
-cmmEqWord e1 e2 = CmmMachOp mo_wordEq [e1, e2]
-cmmULtWord e1 e2 = CmmMachOp mo_wordULt [e1, e2]
-cmmUGeWord e1 e2 = CmmMachOp mo_wordUGe [e1, e2]
-cmmUGtWord e1 e2 = CmmMachOp mo_wordUGt [e1, e2]
---cmmShlWord e1 e2 = CmmMachOp mo_wordShl [e1, e2]
-cmmUShrWord e1 e2 = CmmMachOp mo_wordUShr [e1, e2]
-cmmAddWord e1 e2 = CmmMachOp mo_wordAdd [e1, e2]
-cmmSubWord e1 e2 = CmmMachOp mo_wordSub [e1, e2]
-cmmMulWord e1 e2 = CmmMachOp mo_wordMul [e1, e2]
-
-cmmNegate :: CmmExpr -> CmmExpr
-cmmNegate (CmmLit (CmmInt n rep)) = CmmLit (CmmInt (-n) rep)
-cmmNegate e = CmmMachOp (MO_S_Neg (cmmExprWidth e)) [e]
-
-blankWord :: CmmStatic
-blankWord = CmmUninitialised wORD_SIZE
-
--- Tagging --
--- Tag bits mask
---cmmTagBits = CmmLit (mkIntCLit tAG_BITS)
-cmmTagMask = CmmLit (mkIntCLit tAG_MASK)
-cmmPointerMask = CmmLit (mkIntCLit (complement tAG_MASK))
-
--- Used to untag a possibly tagged pointer
--- A static label need not be untagged
-cmmUntag e@(CmmLit (CmmLabel _)) = e
--- Default case
-cmmUntag e = (e `cmmAndWord` cmmPointerMask)
-
-cmmGetTag e = (e `cmmAndWord` cmmTagMask)
-
--- Test if a closure pointer is untagged
-cmmIsTagged e = (e `cmmAndWord` cmmTagMask)
- `cmmNeWord` CmmLit zeroCLit
-
-cmmConstrTag e = (e `cmmAndWord` cmmTagMask) `cmmSubWord` (CmmLit (mkIntCLit 1))
--- Get constructor tag, but one based.
-cmmConstrTag1 e = e `cmmAndWord` cmmTagMask
+
{-
The family size of a data type (the number of constructors)
@@ -237,33 +156,6 @@ tagForCon con = tag
--Tag an expression, to do: refactor, this appears in some other module.
tagCons con expr = cmmOffsetB expr (tagForCon con)
--- Copied from CgInfoTbls.hs
--- We keep the *zero-indexed* tag in the srt_len field of the info
--- table of a data constructor.
-dataConTagZ :: DataCon -> ConTagZ
-dataConTagZ con = dataConTag con - fIRST_TAG
-
------------------------
--- Making literals
-
-mkWordCLit :: StgWord -> CmmLit
-mkWordCLit wd = CmmInt (fromIntegral wd) wordWidth
-
-packHalfWordsCLit :: (Integral a, Integral b) => a -> b -> CmmLit
--- Make a single word literal in which the lower_half_word is
--- at the lower address, and the upper_half_word is at the
--- higher address
--- ToDo: consider using half-word lits instead
--- but be careful: that's vulnerable when reversed
-packHalfWordsCLit lower_half_word upper_half_word
-#ifdef WORDS_BIGENDIAN
- = mkWordCLit ((fromIntegral lower_half_word `shiftL` hALF_WORD_SIZE_IN_BITS)
- .|. fromIntegral upper_half_word)
-#else
- = mkWordCLit ((fromIntegral lower_half_word)
- .|. (fromIntegral upper_half_word `shiftL` hALF_WORD_SIZE_IN_BITS))
-#endif
-
--------------------------------------------------------------------------
--
-- Incrementing a memory location
@@ -544,44 +436,24 @@ baseRegOffset _ = panic "baseRegOffset:other"
emitDataLits :: CLabel -> [CmmLit] -> Code
-- Emit a data-segment data block
-emitDataLits lbl lits
- = emitData Data (Statics lbl $ map CmmStaticLit lits)
-
-mkDataLits :: CLabel -> [CmmLit] -> GenCmmTop CmmStatics info graph
--- Emit a data-segment data block
-mkDataLits lbl lits
- = CmmData Data (Statics lbl $ map CmmStaticLit lits)
+emitDataLits lbl lits = emitDecl (mkDataLits Data lbl lits)
emitRODataLits :: String -> CLabel -> [CmmLit] -> Code
-- Emit a read-only data block
emitRODataLits caller lbl lits
- = emitData section (Statics lbl $ map CmmStaticLit lits)
- where section | any needsRelocation lits = RelocatableReadOnlyData
- | otherwise = ReadOnlyData
- needsRelocation (CmmLabel _) = True
- needsRelocation (CmmLabelOff _ _) = True
- needsRelocation _ = False
-
-mkRODataLits :: CLabel -> [CmmLit] -> GenCmmTop CmmStatics info graph
-mkRODataLits lbl lits
- = CmmData section (Statics lbl $ map CmmStaticLit lits)
- where section | any needsRelocation lits = RelocatableReadOnlyData
- | otherwise = ReadOnlyData
- needsRelocation (CmmLabel _) = True
- needsRelocation (CmmLabelOff _ _) = True
- needsRelocation _ = False
-
-mkStringCLit :: String -> FCode CmmLit
+ = emitDecl (mkRODataLits lbl lits)
+
+newStringCLit :: String -> FCode CmmLit
-- Make a global definition for the string,
-- and return its label
-mkStringCLit str = mkByteStringCLit (map (fromIntegral.ord) str)
+newStringCLit str = newByteStringCLit (map (fromIntegral.ord) str)
-mkByteStringCLit :: [Word8] -> FCode CmmLit
-mkByteStringCLit bytes
+newByteStringCLit :: [Word8] -> FCode CmmLit
+newByteStringCLit bytes
= do { uniq <- newUnique
- ; let lbl = mkStringLitLabel uniq
- ; emitData ReadOnlyData $ Statics lbl [CmmString bytes]
- ; return (CmmLabel lbl) }
+ ; let (lit, decl) = mkByteStringCLit uniq bytes
+ ; emitDecl decl
+ ; return lit }
-------------------------------------------------------------------------
--
diff --git a/compiler/codeGen/ClosureInfo.lhs b/compiler/codeGen/ClosureInfo.lhs
index 8bfbfed0bc..443e0ccf89 100644
--- a/compiler/codeGen/ClosureInfo.lhs
+++ b/compiler/codeGen/ClosureInfo.lhs
@@ -17,17 +17,16 @@ module ClosureInfo (
StandardFormInfo(..), -- mkCmmInfo looks inside
SMRep,
- ArgDescr(..), Liveness(..),
+ ArgDescr(..), Liveness,
C_SRT(..), needsSRT,
mkLFThunk, mkLFReEntrant, mkConLFInfo, mkSelectorLFInfo,
mkApLFInfo, mkLFImported, mkLFArgument, mkLFLetNoEscape,
mkClosureInfo, mkConInfo, maybeIsLFCon,
+ closureSize,
- closureSize, closureNonHdrSize,
- closureGoodStuffSize, closurePtrsSize,
- slopSize,
+ ConTagZ, dataConTagZ,
infoTableLabelFromCI, entryLabelFromCI,
closureLabelFromCI,
@@ -45,7 +44,6 @@ module ClosureInfo (
blackHoleOnEntry,
staticClosureRequired,
- getClosureType,
isToplevClosure,
closureValDescr, closureTypeDescr, -- profiling
@@ -63,7 +61,7 @@ import StgSyn
import SMRep
import CLabel
-
+import Cmm
import Unique
import StaticFlags
import Var
@@ -76,7 +74,6 @@ import TypeRep
import TcType
import TyCon
import BasicTypes
-import FastString
import Outputable
import Constants
import DynFlags
@@ -120,21 +117,6 @@ data ClosureInfo
closureCon :: !DataCon,
closureSMRep :: !SMRep
}
-
--- C_SRT is what StgSyn.SRT gets translated to...
--- we add a label for the table, and expect only the 'offset/length' form
-
-data C_SRT = NoC_SRT
- | C_SRT !CLabel !WordOff !StgHalfWord {-bitmap or escape-}
- deriving (Eq)
-
-needsSRT :: C_SRT -> Bool
-needsSRT NoC_SRT = False
-needsSRT (C_SRT _ _ _) = True
-
-instance Outputable C_SRT where
- ppr (NoC_SRT) = ptext (sLit "_no_srt_")
- ppr (C_SRT label off bitmap) = parens (ppr label <> comma <> ppr off <> comma <> text (show bitmap))
\end{code}
%************************************************************************
@@ -186,33 +168,6 @@ data LambdaFormInfo
-- be in the heap, so we make a black hole to hold it.
--------------------------
--- An ArgDsecr describes the argument pattern of a function
-
-data ArgDescr
- = ArgSpec -- Fits one of the standard patterns
- !StgHalfWord -- RTS type identifier ARG_P, ARG_N, ...
-
- | ArgGen -- General case
- Liveness -- Details about the arguments
-
-
--------------------------
--- We represent liveness bitmaps as a Bitmap (whose internal
--- representation really is a bitmap). These are pinned onto case return
--- vectors to indicate the state of the stack for the garbage collector.
---
--- In the compiled program, liveness bitmaps that fit inside a single
--- word (StgWord) are stored as a single word, while larger bitmaps are
--- stored as a pointer to an array of words.
-
-data Liveness
- = SmallLiveness -- Liveness info that fits in one word
- StgWord -- Here's the bitmap
-
- | BigLiveness -- Liveness info witha a multi-word bitmap
- CLabel -- Label for the bitmap
-
-------------------------
-- StandardFormInfo tells whether this thunk has one of
@@ -320,6 +275,16 @@ isLFThunk LFBlackHole = True
isLFThunk _ = False
\end{code}
+\begin{code}
+-- We keep the *zero-indexed* tag in the srt_len field of the info
+-- table of a data constructor.
+type ConTagZ = Int -- A *zero-indexed* contructor tag
+
+dataConTagZ :: DataCon -> ConTagZ
+dataConTagZ con = dataConTag con - fIRST_TAG
+\end{code}
+
+
%************************************************************************
%* *
Building ClosureInfos
@@ -348,7 +313,8 @@ mkClosureInfo is_static id lf_info tot_wds ptr_wds srt_info descr
-- anything else gets eta expanded.
where
name = idName id
- sm_rep = chooseSMRep is_static lf_info tot_wds ptr_wds
+ sm_rep = mkHeapRep is_static ptr_wds nonptr_wds (lfClosureType lf_info)
+ nonptr_wds = tot_wds - ptr_wds
mkConInfo :: Bool -- Is static
-> DataCon
@@ -358,7 +324,9 @@ mkConInfo is_static data_con tot_wds ptr_wds
= ConInfo { closureSMRep = sm_rep,
closureCon = data_con }
where
- sm_rep = chooseSMRep is_static (mkConLFInfo data_con) tot_wds ptr_wds
+ sm_rep = mkHeapRep is_static ptr_wds nonptr_wds (lfClosureType lf_info)
+ lf_info = mkConLFInfo data_con
+ nonptr_wds = tot_wds - ptr_wds
\end{code}
%************************************************************************
@@ -369,56 +337,10 @@ mkConInfo is_static data_con tot_wds ptr_wds
\begin{code}
closureSize :: ClosureInfo -> WordOff
-closureSize cl_info = hdr_size + closureNonHdrSize cl_info
- where hdr_size | closureIsThunk cl_info = thunkHdrSize
- | otherwise = fixedHdrSize
- -- All thunks use thunkHdrSize, even if they are non-updatable.
- -- this is because we don't have separate closure types for
- -- updatable vs. non-updatable thunks, so the GC can't tell the
- -- difference. If we ever have significant numbers of non-
- -- updatable thunks, it might be worth fixing this.
-
-closureNonHdrSize :: ClosureInfo -> WordOff
-closureNonHdrSize cl_info
- = tot_wds + computeSlopSize tot_wds cl_info
- where
- tot_wds = closureGoodStuffSize cl_info
-
-closureGoodStuffSize :: ClosureInfo -> WordOff
-closureGoodStuffSize cl_info
- = let (ptrs, nonptrs) = sizes_from_SMRep (closureSMRep cl_info)
- in ptrs + nonptrs
-
-closurePtrsSize :: ClosureInfo -> WordOff
-closurePtrsSize cl_info
- = let (ptrs, _) = sizes_from_SMRep (closureSMRep cl_info)
- in ptrs
-
--- not exported:
-sizes_from_SMRep :: SMRep -> (WordOff,WordOff)
-sizes_from_SMRep (GenericRep _ ptrs nonptrs _) = (ptrs, nonptrs)
-sizes_from_SMRep BlackHoleRep = (0, 0)
+closureSize cl_info = heapClosureSize (closureSMRep cl_info)
\end{code}
-Computing slop size. WARNING: this looks dodgy --- it has deep
-knowledge of what the storage manager does with the various
-representations...
-
-Slop Requirements: every thunk gets an extra padding word in the
-header, which takes the the updated value.
-
\begin{code}
-slopSize :: ClosureInfo -> WordOff
-slopSize cl_info = computeSlopSize payload_size cl_info
- where payload_size = closureGoodStuffSize cl_info
-
-computeSlopSize :: WordOff -> ClosureInfo -> WordOff
-computeSlopSize payload_size cl_info
- = max 0 (minPayloadSize smrep updatable - payload_size)
- where
- smrep = closureSMRep cl_info
- updatable = closureNeedsUpdSpace cl_info
-
-- we leave space for an update if either (a) the closure is updatable
-- or (b) it is a static thunk. This is because a static thunk needs
-- a static link field in a predictable place (after the slop), regardless
@@ -427,21 +349,6 @@ closureNeedsUpdSpace :: ClosureInfo -> Bool
closureNeedsUpdSpace (ClosureInfo { closureLFInfo =
LFThunk TopLevel _ _ _ _ }) = True
closureNeedsUpdSpace cl_info = closureUpdReqd cl_info
-
-minPayloadSize :: SMRep -> Bool -> WordOff
-minPayloadSize smrep updatable
- = case smrep of
- BlackHoleRep -> min_upd_size
- GenericRep _ _ _ _ | updatable -> min_upd_size
- GenericRep True _ _ _ -> 0 -- static
- GenericRep False _ _ _ -> mIN_PAYLOAD_SIZE
- -- ^^^^^___ dynamic
- where
- min_upd_size =
- ASSERT(mIN_PAYLOAD_SIZE <= sIZEOF_StgSMPThunkHeader)
- 0 -- check that we already have enough
- -- room for mIN_SIZE_NonUpdHeapObject,
- -- due to the extra header word in SMP
\end{code}
%************************************************************************
@@ -451,33 +358,21 @@ minPayloadSize smrep updatable
%************************************************************************
\begin{code}
-chooseSMRep
- :: Bool -- True <=> static closure
- -> LambdaFormInfo
- -> WordOff -> WordOff -- Tot wds, ptr wds
- -> SMRep
+lfClosureType :: LambdaFormInfo -> ClosureTypeInfo
+lfClosureType (LFReEntrant _ arity _ argd) = Fun (fromIntegral arity) argd
+lfClosureType (LFCon con) = Constr (fromIntegral (dataConTagZ con))
+ (dataConIdentity con)
+lfClosureType (LFThunk _ _ _ is_sel _) = thunkClosureType is_sel
+lfClosureType _ = panic "lfClosureType"
-chooseSMRep is_static lf_info tot_wds ptr_wds
- = let
- nonptr_wds = tot_wds - ptr_wds
- closure_type = getClosureType is_static ptr_wds lf_info
- in
- GenericRep is_static ptr_wds nonptr_wds closure_type
+thunkClosureType :: StandardFormInfo -> ClosureTypeInfo
+thunkClosureType (SelectorThunk off) = ThunkSelector (fromIntegral off)
+thunkClosureType _ = Thunk
-- We *do* get non-updatable top-level thunks sometimes. eg. f = g
-- gets compiled to a jump to g (if g has non-zero arity), instead of
-- messing around with update frames and PAPs. We set the closure type
-- to FUN_STATIC in this case.
-
-getClosureType :: Bool -> WordOff -> LambdaFormInfo -> ClosureType
-getClosureType is_static ptr_wds lf_info
- = case lf_info of
- LFCon _ | is_static && ptr_wds == 0 -> ConstrNoCaf
- | otherwise -> Constr
- LFReEntrant _ _ _ _ -> Fun
- LFThunk _ _ _ (SelectorThunk _) _ -> ThunkSelector
- LFThunk _ _ _ _ _ -> Thunk
- _ -> panic "getClosureType"
\end{code}
%************************************************************************
@@ -730,13 +625,8 @@ staticClosureNeedsLink :: ClosureInfo -> Bool
-- of the SRT.
staticClosureNeedsLink (ClosureInfo { closureSRT = srt })
= needsSRT srt
-staticClosureNeedsLink (ConInfo { closureSMRep = sm_rep, closureCon = con })
- = not (isNullaryRepDataCon con) && not_nocaf_constr
- where
- not_nocaf_constr =
- case sm_rep of
- GenericRep _ _ _ ConstrNoCaf -> False
- _other -> True
+staticClosureNeedsLink (ConInfo { closureSMRep = rep })
+ = not (isStaticNoCafCon rep)
\end{code}
Note [Entering error thunks]
@@ -1020,7 +910,7 @@ cafBlackHoleClosureInfo (ClosureInfo { closureName = nm,
closureType = ty })
= ClosureInfo { closureName = nm,
closureLFInfo = LFBlackHole,
- closureSMRep = BlackHoleRep,
+ closureSMRep = blackHoleRep,
closureSRT = NoC_SRT,
closureType = ty,
closureDescr = "",
diff --git a/compiler/codeGen/CodeGen.lhs b/compiler/codeGen/CodeGen.lhs
index 42c4bd24fc..b22e6ed64d 100644
--- a/compiler/codeGen/CodeGen.lhs
+++ b/compiler/codeGen/CodeGen.lhs
@@ -53,7 +53,7 @@ codeGen :: DynFlags
-> CollectedCCs -- (Local/global) cost-centres needing declaring/registering.
-> [(StgBinding,[(Id,[Id])])] -- Bindings to convert, with SRTs
-> HpcInfo
- -> IO [Cmm] -- Output
+ -> IO [CmmPgm] -- Output
-- N.B. returning '[Cmm]' and not 'Cmm' here makes it
-- possible for object splitting to split up the
@@ -71,7 +71,7 @@ codeGen dflags this_mod data_tycons cost_centre_info stg_binds hpc_info
; cmm_tycons <- mapM cgTyCon data_tycons
; cmm_init <- getCmm (mkModuleInit dflags cost_centre_info
this_mod hpc_info)
- ; return (cmm_init : cmm_binds ++ concat cmm_tycons)
+ ; return (cmm_init : cmm_binds ++ cmm_tycons)
}
-- Put datatype_stuff after code_stuff, because the
-- datatype closure table (for enumeration types) to
@@ -105,7 +105,7 @@ mkModuleInit dflags cost_centre_info this_mod hpc_info
-- For backwards compatibility: user code may refer to this
-- label for calling hs_add_root().
- ; emitData Data $ Statics (mkPlainModuleInitLabel this_mod) []
+ ; emitDecl (CmmData Data (Statics (mkPlainModuleInitLabel this_mod) []))
; whenC (this_mod == mainModIs dflags) $
emitSimpleProc (mkPlainModuleInitLabel rOOT_MAIN) $ return ()
diff --git a/compiler/codeGen/SMRep.lhs b/compiler/codeGen/SMRep.lhs
index f35118d1c9..fea9e4b2fc 100644
--- a/compiler/codeGen/SMRep.lhs
+++ b/compiler/codeGen/SMRep.lhs
@@ -28,15 +28,25 @@ module SMRep (
typeCgRep, idCgRep, tyConCgRep,
-- Closure repesentation
- SMRep(..), ClosureType(..),
- isStaticRep,
- fixedHdrSize, arrWordsHdrSize, arrPtrsHdrSize,
- profHdrSize, thunkHdrSize,
- smRepClosureType, smRepClosureTypeInt,
-
- rET_SMALL, rET_BIG
+ SMRep(..), -- CmmInfo sees the rep; no one else does
+ IsStatic,
+ ClosureTypeInfo(..), ArgDescr(..), Liveness,
+ ConstrDescription,
+ mkHeapRep, blackHoleRep, mkStackRep,
+
+ isStaticRep, isStaticNoCafCon,
+ heapClosureSize,
+ fixedHdrSize, arrWordsHdrSize, arrPtrsHdrSize,
+ profHdrSize, thunkHdrSize, nonHdrSize,
+
+ rtsClosureType, rET_SMALL, rET_BIG,
+ aRG_GEN, aRG_GEN_BIG,
+
+ -- Operations over [Word8] strings
+ pprWord8String, stringToWord8s
) where
+#include "../HsVersions.h"
#include "../includes/MachDeps.h"
import CmmType
@@ -48,6 +58,7 @@ import Constants
import Outputable
import FastString
+import Data.Char( ord )
import Data.Word
\end{code}
@@ -234,36 +245,102 @@ retAddrSizeW = 1 -- One word
%************************************************************************
\begin{code}
+-- | A description of the layout of a closure. Corresponds directly
+-- to the closure types in includes/rts/storage/ClosureTypes.h.
data SMRep
- -- static closure have an extra static link field at the end.
- = GenericRep -- GC routines consult sizes in info tbl
- Bool -- True <=> This is a static closure. Affects how
- -- we garbage-collect it
- !Int -- # ptr words
- !Int -- # non-ptr words
- ClosureType -- closure type
-
- | BlackHoleRep
-
-data ClosureType -- Corresponds 1-1 with the varieties of closures
- -- implemented by the RTS. Compare with includes/rts/storage/ClosureTypes.h
- = Constr
- | ConstrNoCaf
- | Fun
- | Thunk
- | ThunkSelector
-\end{code}
+ = HeapRep -- GC routines consult sizes in info tbl
+ IsStatic
+ !WordOff -- # ptr words
+ !WordOff -- # non-ptr words INCLUDING SLOP (see mkHeapRep below)
+ ClosureTypeInfo -- type-specific info
+
+ | StackRep -- Stack frame (RET_SMALL or RET_BIG)
+ Liveness
+
+-- | True <=> This is a static closure. Affects how we garbage-collect it.
+-- Static closure have an extra static link field at the end.
+type IsStatic = Bool
+
+-- From an SMRep you can get to the closure type defined in
+-- includes/rts/storage/ClosureTypes.h. Described by the function
+-- rtsClosureType below.
+
+data ClosureTypeInfo
+ = Constr ConstrTag ConstrDescription
+ | Fun FunArity ArgDescr
+ | Thunk
+ | ThunkSelector SelectorOffset
+ | BlackHole
+
+type ConstrTag = StgHalfWord
+type ConstrDescription = [Word8] -- result of dataConIdentity
+type FunArity = StgHalfWord
+type SelectorOffset = StgWord
+
+-------------------------
+-- We represent liveness bitmaps as a Bitmap (whose internal
+-- representation really is a bitmap). These are pinned onto case return
+-- vectors to indicate the state of the stack for the garbage collector.
+--
+-- In the compiled program, liveness bitmaps that fit inside a single
+-- word (StgWord) are stored as a single word, while larger bitmaps are
+-- stored as a pointer to an array of words.
+
+type Liveness = [Bool] -- One Bool per word; True <=> non-ptr or dead
+ -- False <=> ptr
+
+-------------------------
+-- An ArgDescr describes the argument pattern of a function
+
+data ArgDescr
+ = ArgSpec -- Fits one of the standard patterns
+ !StgHalfWord -- RTS type identifier ARG_P, ARG_N, ...
+
+ | ArgGen -- General case
+ Liveness -- Details about the arguments
+
+
+-----------------------------------------------------------------------------
+-- Construction
+
+mkHeapRep :: IsStatic -> WordOff -> WordOff -> ClosureTypeInfo -> SMRep
+mkHeapRep is_static ptr_wds nonptr_wds cl_type_info
+ = HeapRep is_static
+ ptr_wds
+ (nonptr_wds + slop_wds)
+ cl_type_info
+ where
+ slop_wds
+ | is_static = 0
+ | otherwise = max 0 (minClosureSize - (hdr_size + payload_size))
-Size of a closure header.
+ hdr_size = closureTypeHdrSize cl_type_info
+ payload_size = ptr_wds + nonptr_wds
-\begin{code}
+
+mkStackRep :: [Bool] -> SMRep
+mkStackRep = StackRep
+
+blackHoleRep :: SMRep
+blackHoleRep = HeapRep False 0 0 BlackHole
+
+-----------------------------------------------------------------------------
+-- Size-related things
+
+-- | Size of a closure header (StgHeader in includes/rts/storage/Closures.h)
fixedHdrSize :: WordOff
fixedHdrSize = sTD_HDR_SIZE + profHdrSize
+-- | Size of the profiling part of a closure header
+-- (StgProfHeader in includes/rts/storage/Closures.h)
profHdrSize :: WordOff
profHdrSize | opt_SccProfilingOn = pROF_HDR_SIZE
| otherwise = 0
+-- | The garbage collector requires that every closure is at least as big as this.
+minClosureSize :: WordOff
+minClosureSize = fixedHdrSize + mIN_PAYLOAD_SIZE
+
arrWordsHdrSize :: ByteOff
arrWordsHdrSize = fixedHdrSize*wORD_SIZE + sIZEOF_StgArrWords_NoHdr
@@ -275,61 +352,150 @@ arrPtrsHdrSize = fixedHdrSize*wORD_SIZE + sIZEOF_StgMutArrPtrs_NoHdr
thunkHdrSize :: WordOff
thunkHdrSize = fixedHdrSize + smp_hdr
where smp_hdr = sIZEOF_StgSMPThunkHeader `quot` wORD_SIZE
-\end{code}
-\begin{code}
-isStaticRep :: SMRep -> Bool
-isStaticRep (GenericRep is_static _ _ _) = is_static
-isStaticRep BlackHoleRep = False
-\end{code}
-\begin{code}
-#include "../includes/rts/storage/ClosureTypes.h"
--- Defines CONSTR, CONSTR_1_0 etc
+isStaticRep :: SMRep -> IsStatic
+isStaticRep (HeapRep is_static _ _ _) = is_static
+isStaticRep (StackRep {}) = False
--- krc: only called by tickyDynAlloc in CgTicky; return
--- Nothing for a black hole so we can at least make something work.
-smRepClosureType :: SMRep -> Maybe ClosureType
-smRepClosureType (GenericRep _ _ _ ty) = Just ty
-smRepClosureType BlackHoleRep = Nothing
+nonHdrSize :: SMRep -> WordOff
+nonHdrSize (HeapRep _ p np _) = p + np
+nonHdrSize (StackRep bs) = length bs
-smRepClosureTypeInt :: SMRep -> StgHalfWord
-smRepClosureTypeInt (GenericRep False 1 0 Constr) = CONSTR_1_0
-smRepClosureTypeInt (GenericRep False 0 1 Constr) = CONSTR_0_1
-smRepClosureTypeInt (GenericRep False 2 0 Constr) = CONSTR_2_0
-smRepClosureTypeInt (GenericRep False 1 1 Constr) = CONSTR_1_1
-smRepClosureTypeInt (GenericRep False 0 2 Constr) = CONSTR_0_2
-smRepClosureTypeInt (GenericRep False _ _ Constr) = CONSTR
+heapClosureSize :: SMRep -> WordOff
+heapClosureSize (HeapRep _ p np ty) = closureTypeHdrSize ty + p + np
+heapClosureSize _ = panic "SMRep.heapClosureSize"
-smRepClosureTypeInt (GenericRep False 1 0 Fun) = FUN_1_0
-smRepClosureTypeInt (GenericRep False 0 1 Fun) = FUN_0_1
-smRepClosureTypeInt (GenericRep False 2 0 Fun) = FUN_2_0
-smRepClosureTypeInt (GenericRep False 1 1 Fun) = FUN_1_1
-smRepClosureTypeInt (GenericRep False 0 2 Fun) = FUN_0_2
-smRepClosureTypeInt (GenericRep False _ _ Fun) = FUN
+closureTypeHdrSize :: ClosureTypeInfo -> WordOff
+closureTypeHdrSize ty = case ty of
+ Thunk{} -> thunkHdrSize
+ ThunkSelector{} -> thunkHdrSize
+ BlackHole{} -> thunkHdrSize
+ _ -> fixedHdrSize
+ -- All thunks use thunkHdrSize, even if they are non-updatable.
+ -- this is because we don't have separate closure types for
+ -- updatable vs. non-updatable thunks, so the GC can't tell the
+ -- difference. If we ever have significant numbers of non-
+ -- updatable thunks, it might be worth fixing this.
-smRepClosureTypeInt (GenericRep False 1 0 Thunk) = THUNK_1_0
-smRepClosureTypeInt (GenericRep False 0 1 Thunk) = THUNK_0_1
-smRepClosureTypeInt (GenericRep False 2 0 Thunk) = THUNK_2_0
-smRepClosureTypeInt (GenericRep False 1 1 Thunk) = THUNK_1_1
-smRepClosureTypeInt (GenericRep False 0 2 Thunk) = THUNK_0_2
-smRepClosureTypeInt (GenericRep False _ _ Thunk) = THUNK
+-----------------------------------------------------------------------------
+-- deriving the RTS closure type from an SMRep
-smRepClosureTypeInt (GenericRep False _ _ ThunkSelector) = THUNK_SELECTOR
+#include "../includes/rts/storage/ClosureTypes.h"
+#include "../includes/rts/storage/FunTypes.h"
+-- Defines CONSTR, CONSTR_1_0 etc
-smRepClosureTypeInt (GenericRep True _ _ Constr) = CONSTR_STATIC
-smRepClosureTypeInt (GenericRep True _ _ ConstrNoCaf) = CONSTR_NOCAF_STATIC
-smRepClosureTypeInt (GenericRep True _ _ Fun) = FUN_STATIC
-smRepClosureTypeInt (GenericRep True _ _ Thunk) = THUNK_STATIC
+-- | Derives the RTS closure type from an 'SMRep'
+rtsClosureType :: SMRep -> StgHalfWord
+rtsClosureType (HeapRep False 1 0 Constr{}) = CONSTR_1_0
+rtsClosureType (HeapRep False 0 1 Constr{}) = CONSTR_0_1
+rtsClosureType (HeapRep False 2 0 Constr{}) = CONSTR_2_0
+rtsClosureType (HeapRep False 1 1 Constr{}) = CONSTR_1_1
+rtsClosureType (HeapRep False 0 2 Constr{}) = CONSTR_0_2
+rtsClosureType (HeapRep False _ _ Constr{}) = CONSTR
+
+rtsClosureType (HeapRep False 1 0 Fun{}) = FUN_1_0
+rtsClosureType (HeapRep False 0 1 Fun{}) = FUN_0_1
+rtsClosureType (HeapRep False 2 0 Fun{}) = FUN_2_0
+rtsClosureType (HeapRep False 1 1 Fun{}) = FUN_1_1
+rtsClosureType (HeapRep False 0 2 Fun{}) = FUN_0_2
+rtsClosureType (HeapRep False _ _ Fun{}) = FUN
+
+rtsClosureType (HeapRep False 1 0 Thunk{}) = THUNK_1_0
+rtsClosureType (HeapRep False 0 1 Thunk{}) = THUNK_0_1
+rtsClosureType (HeapRep False 2 0 Thunk{}) = THUNK_2_0
+rtsClosureType (HeapRep False 1 1 Thunk{}) = THUNK_1_1
+rtsClosureType (HeapRep False 0 2 Thunk{}) = THUNK_0_2
+rtsClosureType (HeapRep False _ _ Thunk{}) = THUNK
+
+rtsClosureType (HeapRep False _ _ ThunkSelector{}) = THUNK_SELECTOR
+
+-- Approximation: we use the CONSTR_NOCAF_STATIC type for static constructors
+-- that have no pointer words only.
+rtsClosureType (HeapRep True 0 _ Constr{}) = CONSTR_NOCAF_STATIC -- See isStaticNoCafCon below
+rtsClosureType (HeapRep True _ _ Constr{}) = CONSTR_STATIC
+rtsClosureType (HeapRep True _ _ Fun{}) = FUN_STATIC
+rtsClosureType (HeapRep True _ _ Thunk{}) = THUNK_STATIC
+
+rtsClosureType (HeapRep False _ _ BlackHole{}) = BLACKHOLE
+
+rtsClosureType _ = panic "rtsClosureType"
+
+isStaticNoCafCon :: SMRep -> Bool
+-- This should line up exactly with CONSTR_NOCAF_STATIC above
+-- See Note [Static NoCaf constructors]
+isStaticNoCafCon (HeapRep True 0 _ Constr{}) = True
+isStaticNoCafCon _ = False
-smRepClosureTypeInt BlackHoleRep = BLACKHOLE
+-- We export these ones
+rET_SMALL, rET_BIG, aRG_GEN, aRG_GEN_BIG :: StgHalfWord
+rET_SMALL = RET_SMALL
+rET_BIG = RET_BIG
+aRG_GEN = ARG_GEN
+aRG_GEN_BIG = ARG_GEN_BIG
+\end{code}
-smRepClosureTypeInt _ = panic "smRepClosuretypeint"
+Note [Static NoCaf constructors]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+If we know that a top-level binding 'x' is not Caffy (ie no CAFs are
+reachable from 'x'), then a statically allocated constructor (Just x)
+is also not Caffy, and the garbage collector need not follow its
+argument fields. Exploiting this would require two static info tables
+for Just, for the two cases where the argument was Caffy or non-Caffy.
+Currently we don't do this; instead we treat nullary constructors
+as non-Caffy, and the others as potentially Caffy.
--- We export these ones
-rET_SMALL, rET_BIG :: StgHalfWord
-rET_SMALL = RET_SMALL
-rET_BIG = RET_BIG
-\end{code}
+%************************************************************************
+%* *
+ Pretty printing of SMRep and friends
+%* *
+%************************************************************************
+
+\begin{code}
+instance Outputable ClosureTypeInfo where
+ ppr = pprTypeInfo
+
+instance Outputable SMRep where
+ ppr (HeapRep static ps nps tyinfo)
+ = hang (header <+> lbrace) 2 (ppr tyinfo <+> rbrace)
+ where
+ header = ptext (sLit "HeapRep")
+ <+> if static then ptext (sLit "static") else empty
+ <+> pp_n "ptrs" ps <+> pp_n "nonptrs" nps
+ pp_n :: String -> Int -> SDoc
+ pp_n _ 0 = empty
+ pp_n s n = int n <+> text s
+
+ ppr (StackRep bs) = ptext (sLit "StackRep") <+> ppr bs
+
+instance Outputable ArgDescr where
+ ppr (ArgSpec n) = ptext (sLit "ArgSpec") <+> integer (toInteger n)
+ ppr (ArgGen ls) = ptext (sLit "ArgGen") <+> ppr ls
+
+pprTypeInfo :: ClosureTypeInfo -> SDoc
+pprTypeInfo (Constr tag descr)
+ = ptext (sLit "Con") <+>
+ braces (sep [ ptext (sLit "tag:") <+> integer (toInteger tag)
+ , ptext (sLit "descr:") <> text (show descr) ])
+
+pprTypeInfo (Fun arity args)
+ = ptext (sLit "Fun") <+>
+ braces (sep [ ptext (sLit "arity:") <+> integer (toInteger arity)
+ , ptext (sLit ("fun_type:")) <+> ppr args ])
+
+pprTypeInfo (ThunkSelector offset)
+ = ptext (sLit "ThunkSel") <+> integer (toInteger offset)
+
+pprTypeInfo Thunk = ptext (sLit "Thunk")
+pprTypeInfo BlackHole = ptext (sLit "BlackHole")
+
+
+stringToWord8s :: String -> [Word8]
+stringToWord8s s = map (fromIntegral . ord) s
+
+pprWord8String :: [Word8] -> SDoc
+-- Debug printing. Not very clever right now.
+pprWord8String ws = text (show ws)
+\end{code}
diff --git a/compiler/codeGen/StgCmm.hs b/compiler/codeGen/StgCmm.hs
index 29a254fafc..6f404f04a0 100644
--- a/compiler/codeGen/StgCmm.hs
+++ b/compiler/codeGen/StgCmm.hs
@@ -17,15 +17,12 @@ import StgCmmEnv
import StgCmmBind
import StgCmmCon
import StgCmmLayout
-import StgCmmHeap
import StgCmmUtils
import StgCmmClosure
import StgCmmHpc
import StgCmmTicky
-import MkGraph
-import CmmExpr
-import CmmDecl
+import Cmm
import CLabel
import PprCmm
@@ -50,7 +47,7 @@ codeGen :: DynFlags
-> CollectedCCs -- (Local/global) cost-centres needing declaring/registering.
-> [(StgBinding,[(Id,[Id])])] -- Bindings to convert, with SRTs
-> HpcInfo
- -> IO [Cmm] -- Output
+ -> IO [CmmPgm] -- Output
codeGen dflags this_mod data_tycons
cost_centre_info stg_binds hpc_info
@@ -64,7 +61,7 @@ codeGen dflags this_mod data_tycons
; cmm_tycons <- mapM cgTyCon data_tycons
; cmm_init <- getCmm (mkModuleInit cost_centre_info
this_mod hpc_info)
- ; return (cmm_init : cmm_binds ++ concat cmm_tycons)
+ ; return (cmm_init : cmm_binds ++ cmm_tycons)
}
-- Put datatype_stuff after code_stuff, because the
-- datatype closure table (for enumeration types) to
@@ -182,7 +179,7 @@ mkModuleInit cost_centre_info this_mod hpc_info
; initCostCentres cost_centre_info
-- For backwards compatibility: user code may refer to this
-- label for calling hs_add_root().
- ; emitData Data $ Statics (mkPlainModuleInitLabel this_mod) []
+ ; emitDecl (CmmData Data (Statics (mkPlainModuleInitLabel this_mod) []))
}
---------------------------------------------------------------
@@ -216,7 +213,7 @@ For charlike and intlike closures there is a fixed array of static
closures predeclared.
-}
-cgTyCon :: TyCon -> FCode [Cmm] -- All constructors merged together
+cgTyCon :: TyCon -> FCode CmmPgm -- All constructors merged together
cgTyCon tycon
= do { constrs <- mapM (getCmm . cgDataCon) (tyConDataCons tycon)
@@ -230,10 +227,10 @@ cgTyCon tycon
-- code puts it before --- NR 16 Aug 2007
; extra <- cgEnumerationTyCon tycon
- ; return (extra ++ constrs)
+ ; return (concat (extra ++ constrs))
}
-cgEnumerationTyCon :: TyCon -> FCode [Cmm]
+cgEnumerationTyCon :: TyCon -> FCode [CmmPgm]
cgEnumerationTyCon tycon
| isEnumerationTyCon tycon
= do { tbl <- getCmm $
@@ -254,8 +251,13 @@ cgDataCon data_con
-- static data structures (ie those built at compile
-- time), we take care that info-table contains the
-- information we need.
- (static_cl_info, _) = layOutStaticConstr data_con arg_reps
- (dyn_cl_info, arg_things) = layOutDynConstr data_con arg_reps
+ static_cl_info = mkConInfo True no_cafs data_con tot_wds ptr_wds
+ dyn_cl_info = mkConInfo False NoCafRefs data_con tot_wds ptr_wds
+ no_cafs = pprPanic "cgDataCon: CAF field should not be reqd" (ppr data_con)
+
+ (tot_wds, -- #ptr_wds + #nonptr_wds
+ ptr_wds, -- #ptr_wds
+ arg_things) = mkVirtConstrOffsets arg_reps
emit_info cl_info ticky_code
= emitClosureAndInfoTable cl_info NativeDirectCall []
diff --git a/compiler/codeGen/StgCmmBind.hs b/compiler/codeGen/StgCmmBind.hs
index 2947d33042..ef432ae6d2 100644
--- a/compiler/codeGen/StgCmmBind.hs
+++ b/compiler/codeGen/StgCmmBind.hs
@@ -31,8 +31,7 @@ import StgCmmForeign (emitPrimCall)
import MkGraph
import CoreSyn ( AltCon(..) )
import SMRep
-import CmmDecl
-import CmmExpr
+import Cmm
import CmmUtils
import CLabel
import StgSyn
@@ -75,7 +74,8 @@ cgTopRhsClosure id ccs _ upd_flag srt args body = do
closure_info = mkClosureInfo True id lf_info 0 0 srt_info descr
closure_label = mkLocalClosureLabel name (idCafInfo id)
cg_id_info = litIdInfo id lf_info (CmmLabel closure_label)
- closure_rep = mkStaticClosureFields closure_info ccs True []
+ caffy = idCafInfo id
+ closure_rep = mkStaticClosureFields closure_info ccs caffy []
-- BUILD THE OBJECT, AND GENERATE INFO TABLE (IF NECESSARY)
; emitDataLits closure_label closure_rep
@@ -209,7 +209,7 @@ mkRhsClosure bndr cc bi
body@(StgCase (StgApp scrutinee [{-no args-}])
_ _ _ _ -- ignore uniq, etc.
(AlgAlt _)
- [(DataAlt con, params, _use_mask,
+ [(DataAlt _, params, _use_mask,
(StgApp selectee [{-no args-}]))])
| the_fv == scrutinee -- Scrutinee is the only free variable
&& maybeToBool maybe_offset -- Selectee is a component of the tuple
@@ -226,8 +226,8 @@ mkRhsClosure bndr cc bi
where
lf_info = mkSelectorLFInfo bndr offset_into_int
(isUpdatable upd_flag)
- (_, params_w_offsets) = layOutDynConstr con (addIdReps params)
- -- Just want the layout
+ (_, _, params_w_offsets) = mkVirtConstrOffsets (addIdReps params)
+ -- Just want the layout
maybe_offset = assocMaybe params_w_offsets (NonVoid selectee)
Just the_offset = maybe_offset
offset_into_int = the_offset - fixedHdrSize
diff --git a/compiler/codeGen/StgCmmClosure.hs b/compiler/codeGen/StgCmmClosure.hs
index daaf021f03..88d1498728 100644
--- a/compiler/codeGen/StgCmmClosure.hs
+++ b/compiler/codeGen/StgCmmClosure.hs
@@ -16,29 +16,28 @@ module StgCmmClosure (
DynTag, tagForCon, isSmallFamily,
ConTagZ, dataConTagZ,
- ArgDescr(..), Liveness(..),
+ ArgDescr(..), Liveness,
C_SRT(..), needsSRT,
isVoidRep, isGcPtrRep, addIdReps, addArgReps,
argPrimRep,
+ -----------------------------------
LambdaFormInfo, -- Abstract
StandardFormInfo, -- ...ditto...
mkLFThunk, mkLFReEntrant, mkConLFInfo, mkSelectorLFInfo,
mkApLFInfo, mkLFImported, mkLFArgument, mkLFLetNoEscape,
lfDynTag,
+ maybeIsLFCon, isLFThunk, isLFReEntrant,
+ -----------------------------------
ClosureInfo,
- mkClosureInfo, mkConInfo, maybeIsLFCon,
+ mkClosureInfo, mkConInfo,
- closureSize, closureNonHdrSize,
- closureGoodStuffSize, closurePtrsSize,
- slopSize,
-
- closureName, infoTableLabelFromCI, entryLabelFromCI,
- closureLabelFromCI,
- closureTypeInfo,
- closureLFInfo, isLFThunk,closureSMRep, closureUpdReqd,
+ closureSize,
+ closureName, infoTableLabelFromCI, entryLabelFromCI,
+ closureLabelFromCI, closureProf, closureSRT,
+ closureLFInfo, closureSMRep, closureUpdReqd,
closureNeedsUpdSpace, closureIsThunk,
closureSingleEntry, closureReEntrant, isConstrClosure_maybe,
closureFunInfo, isStandardFormThunk, isKnownFun,
@@ -51,11 +50,7 @@ module StgCmmClosure (
blackHoleOnEntry,
- getClosureType,
-
isToplevClosure,
- closureValDescr, closureTypeDescr, -- profiling
-
isStaticClosure,
cafBlackHoleClosureInfo,
@@ -67,13 +62,9 @@ module StgCmmClosure (
#define FAST_STRING_NOT_NEEDED
#include "HsVersions.h"
-import ClosureInfo (ArgDescr(..), C_SRT(..), Liveness(..))
- -- XXX temporary becuase FunInfo needs this one
-
import StgSyn
import SMRep
-import CmmDecl ( ClosureTypeInfo(..), ConstrDescription )
-import CmmExpr
+import Cmm
import CLabel
import StaticFlags
@@ -352,13 +343,16 @@ maybeIsLFCon _ = Nothing
------------
isLFThunk :: LambdaFormInfo -> Bool
-isLFThunk (LFThunk _ _ _ _ _) = True
-isLFThunk LFBlackHole = True
+isLFThunk (LFThunk {}) = True
+isLFThunk LFBlackHole = True
-- return True for a blackhole: this function is used to determine
-- whether to use the thunk header in SMP mode, and a blackhole
-- must have one.
isLFThunk _ = False
+isLFReEntrant :: LambdaFormInfo -> Bool
+isLFReEntrant (LFReEntrant {}) = True
+isLFReEntrant _ = False
-----------------------------------------------------------------------------
-- Choosing SM reps
@@ -371,28 +365,26 @@ chooseSMRep
-> SMRep
chooseSMRep is_static lf_info tot_wds ptr_wds
- = let
- nonptr_wds = tot_wds - ptr_wds
- closure_type = getClosureType is_static ptr_wds lf_info
- in
- GenericRep is_static ptr_wds nonptr_wds closure_type
+ = mkHeapRep is_static ptr_wds nonptr_wds (lfClosureType lf_info)
+ where
+ nonptr_wds = tot_wds - ptr_wds
+
+lfClosureType :: LambdaFormInfo -> ClosureTypeInfo
+lfClosureType (LFReEntrant _ arity _ argd) = Fun (fromIntegral arity) argd
+lfClosureType (LFCon con) = Constr (fromIntegral (dataConTagZ con))
+ (dataConIdentity con)
+lfClosureType (LFThunk _ _ _ is_sel _) = thunkClosureType is_sel
+lfClosureType _ = panic "lfClosureType"
+
+thunkClosureType :: StandardFormInfo -> ClosureTypeInfo
+thunkClosureType (SelectorThunk off) = ThunkSelector (fromIntegral off)
+thunkClosureType _ = Thunk
-- We *do* get non-updatable top-level thunks sometimes. eg. f = g
-- gets compiled to a jump to g (if g has non-zero arity), instead of
-- messing around with update frames and PAPs. We set the closure type
-- to FUN_STATIC in this case.
-getClosureType :: Bool -> WordOff -> LambdaFormInfo -> ClosureType
-getClosureType is_static ptr_wds lf_info
- = case lf_info of
- LFCon {} | is_static && ptr_wds == 0 -> ConstrNoCaf
- | otherwise -> Constr
- LFReEntrant {} -> Fun
- LFThunk _ _ _ (SelectorThunk {}) _ -> ThunkSelector
- LFThunk {} -> Thunk
- _ -> panic "getClosureType"
-
-
-----------------------------------------------------------------------------
-- nodeMustPointToIt
-----------------------------------------------------------------------------
@@ -668,6 +660,15 @@ We make a ClosureInfo for
- each let binding (both top level and not)
- each data constructor (for its shared static and
dynamic info tables)
+
+Note [Closure CAF info]
+~~~~~~~~~~~~~~~~~~~~~~~
+The closureCafs field is relevant for *static closures only*. It records
+ * For an ordinary closure, whether a CAF is reachable from
+ the code for the closure
+ * For a constructor closure, whether a CAF is reachable
+ from the fields of the constructor
+It is initialised simply from the idCafInfo of the Id.
-}
data ClosureInfo
@@ -676,36 +677,22 @@ data ClosureInfo
closureLFInfo :: !LambdaFormInfo, -- NOTE: not an LFCon (see below)
closureSMRep :: !SMRep, -- representation used by storage mgr
closureSRT :: !C_SRT, -- What SRT applies to this closure
- closureType :: !Type, -- Type of closure (ToDo: remove)
- closureDescr :: !String, -- closure description (for profiling)
- closureCafs :: !CafInfo, -- whether the closure may have CAFs
- closureInfLcl :: Bool -- can the info pointer be a local symbol?
+ closureProf :: !ProfilingInfo,
+ closureCafs :: !CafInfo, -- See Note [Closure CAF info]
+ closureInfLcl :: Bool -- Can the info pointer be a local symbol?
}
-- Constructor closures don't have a unique info table label (they use
-- the constructor's info table), and they don't have an SRT.
| ConInfo {
- closureCon :: !DataCon,
- closureSMRep :: !SMRep
+ closureCon :: !DataCon,
+ closureSMRep :: !SMRep,
+ closureCafs :: !CafInfo -- See Note [Closure CAF info]
}
-{- XXX temp imported from old ClosureInfo
--- C_SRT is what StgSyn.SRT gets translated to...
--- we add a label for the table, and expect only the 'offset/length' form
-
-data C_SRT = NoC_SRT
- | C_SRT !CLabel !WordOff !StgHalfWord {-bitmap or escape-}
- deriving (Eq)
-
-instance Outputable C_SRT where
- ppr (NoC_SRT) = ptext SLIT("_no_srt_")
- ppr (C_SRT label off bitmap) = parens (ppr label <> comma <> ppr off <> comma <> text (show bitmap))
--}
-
-needsSRT :: C_SRT -> Bool
-needsSRT NoC_SRT = False
-needsSRT (C_SRT _ _ _) = True
-
+clHasCafRefs :: ClosureInfo -> CafInfo
+-- Backward compatibility; remove
+clHasCafRefs = closureCafs
--------------------------------------
-- Building ClosureInfos
@@ -718,13 +705,12 @@ mkClosureInfo :: Bool -- Is static
-> C_SRT
-> String -- String descriptor
-> ClosureInfo
-mkClosureInfo is_static id lf_info tot_wds ptr_wds srt_info descr
+mkClosureInfo is_static id lf_info tot_wds ptr_wds srt_info val_descr
= ClosureInfo { closureName = name,
closureLFInfo = lf_info,
closureSMRep = sm_rep,
closureSRT = srt_info,
- closureType = idType id,
- closureDescr = descr,
+ closureProf = prof,
closureCafs = idCafInfo id,
closureInfLcl = isDataConWorkId id }
-- Make the _info pointer for the implicit datacon worker binding
@@ -733,18 +719,23 @@ mkClosureInfo is_static id lf_info tot_wds ptr_wds srt_info descr
-- anything else gets eta expanded.
where
name = idName id
- sm_rep = chooseSMRep is_static lf_info tot_wds ptr_wds
+ sm_rep = mkHeapRep is_static ptr_wds nonptr_wds (lfClosureType lf_info)
+ prof = mkProfilingInfo id val_descr
+ nonptr_wds = tot_wds - ptr_wds
mkConInfo :: Bool -- Is static
+ -> CafInfo
-> DataCon
-> Int -> Int -- Total and pointer words
-> ClosureInfo
-mkConInfo is_static data_con tot_wds ptr_wds
- = ConInfo { closureSMRep = sm_rep,
- closureCon = data_con }
+mkConInfo is_static cafs data_con tot_wds ptr_wds
+ = ConInfo { closureSMRep = sm_rep
+ , closureCafs = cafs
+ , closureCon = data_con }
where
- sm_rep = chooseSMRep is_static (mkConLFInfo data_con) tot_wds ptr_wds
-
+ sm_rep = mkHeapRep is_static ptr_wds nonptr_wds (lfClosureType lf_info)
+ lf_info = mkConLFInfo data_con
+ nonptr_wds = tot_wds - ptr_wds
-- We need a black-hole closure info to pass to @allocDynClosure@ when we
-- want to allocate the black hole on entry to a CAF. These are the only
@@ -752,119 +743,20 @@ mkConInfo is_static data_con tot_wds ptr_wds
-- is a black hole and not something else.
cafBlackHoleClosureInfo :: ClosureInfo -> ClosureInfo
-cafBlackHoleClosureInfo (ClosureInfo { closureName = nm,
- closureType = ty,
- closureCafs = cafs })
- = ClosureInfo { closureName = nm,
- closureLFInfo = LFBlackHole,
- closureSMRep = BlackHoleRep,
- closureSRT = NoC_SRT,
- closureType = ty,
- closureDescr = "",
- closureCafs = cafs,
- closureInfLcl = False }
-cafBlackHoleClosureInfo _ = panic "cafBlackHoleClosureInfo"
-
+cafBlackHoleClosureInfo cl_info@(ClosureInfo {})
+ = cl_info { closureLFInfo = LFBlackHole
+ , closureSMRep = blackHoleRep
+ , closureSRT = NoC_SRT
+ , closureInfLcl = False }
+cafBlackHoleClosureInfo (ConInfo {}) = panic "cafBlackHoleClosureInfo"
---------------------------------------
--- Extracting ClosureTypeInfo
---------------------------------------
-
--- JD: I've added the continuation arguments not for fun but because
--- I don't want to pipe the monad in here (circular module dependencies),
--- and I don't want to pull this code out of this module, which would
--- require us to expose a bunch of abstract types.
-
-closureTypeInfo ::
- ClosureInfo -> ((ConstrDescription -> ClosureTypeInfo) -> DataCon -> CLabel -> a) ->
- (ClosureTypeInfo -> a) -> a
-closureTypeInfo cl_info k_with_con_name k_simple
- = case cl_info of
- ConInfo { closureCon = con }
- -> k_with_con_name (ConstrInfo (ptrs, nptrs)
- (fromIntegral (dataConTagZ con))) con info_lbl
- where
- --con_name = panic "closureTypeInfo"
- -- Was:
- -- cstr <- mkByteStringCLit $ dataConIdentity con
- -- con_name = makeRelativeRefTo info_lbl cstr
-
- ClosureInfo { closureName = name,
- closureLFInfo = LFReEntrant _ arity _ arg_descr,
- closureSRT = srt }
- -> k_simple $ FunInfo (ptrs, nptrs)
- srt
- (fromIntegral arity)
- arg_descr
- (CmmLabel (mkSlowEntryLabel name (clHasCafRefs cl_info)))
-
- ClosureInfo { closureLFInfo = LFThunk _ _ _ (SelectorThunk offset) _,
- closureSRT = srt }
- -> k_simple $ ThunkSelectorInfo (fromIntegral offset) srt
-
- ClosureInfo { closureLFInfo = LFThunk {},
- closureSRT = srt }
- -> k_simple $ ThunkInfo (ptrs, nptrs) srt
-
- _ -> panic "unexpected lambda form in mkCmmInfo"
- where
- info_lbl = infoTableLabelFromCI cl_info
- ptrs = fromIntegral $ closurePtrsSize cl_info
- size = fromIntegral $ closureNonHdrSize cl_info
- nptrs = size - ptrs
--------------------------------------
-- Functions about closure *sizes*
--------------------------------------
closureSize :: ClosureInfo -> WordOff
-closureSize cl_info = hdr_size + closureNonHdrSize cl_info
- where hdr_size | closureIsThunk cl_info = thunkHdrSize
- | otherwise = fixedHdrSize
- -- All thunks use thunkHdrSize, even if they are non-updatable.
- -- this is because we don't have separate closure types for
- -- updatable vs. non-updatable thunks, so the GC can't tell the
- -- difference. If we ever have significant numbers of non-
- -- updatable thunks, it might be worth fixing this.
-
-closureNonHdrSize :: ClosureInfo -> WordOff
-closureNonHdrSize cl_info
- = tot_wds + computeSlopSize tot_wds cl_info
- where
- tot_wds = closureGoodStuffSize cl_info
-
-closureGoodStuffSize :: ClosureInfo -> WordOff
-closureGoodStuffSize cl_info
- = let (ptrs, nonptrs) = sizes_from_SMRep (closureSMRep cl_info)
- in ptrs + nonptrs
-
-closurePtrsSize :: ClosureInfo -> WordOff
-closurePtrsSize cl_info
- = let (ptrs, _) = sizes_from_SMRep (closureSMRep cl_info)
- in ptrs
-
--- not exported:
-sizes_from_SMRep :: SMRep -> (WordOff,WordOff)
-sizes_from_SMRep (GenericRep _ ptrs nonptrs _) = (ptrs, nonptrs)
-sizes_from_SMRep BlackHoleRep = (0, 0)
-
--- Computing slop size. WARNING: this looks dodgy --- it has deep
--- knowledge of what the storage manager does with the various
--- representations...
---
--- Slop Requirements: every thunk gets an extra padding word in the
--- header, which takes the the updated value.
-
-slopSize :: ClosureInfo -> WordOff
-slopSize cl_info = computeSlopSize payload_size cl_info
- where payload_size = closureGoodStuffSize cl_info
-
-computeSlopSize :: WordOff -> ClosureInfo -> WordOff
-computeSlopSize payload_size cl_info
- = max 0 (minPayloadSize smrep updatable - payload_size)
- where
- smrep = closureSMRep cl_info
- updatable = closureNeedsUpdSpace cl_info
+closureSize cl_info = heapClosureSize (closureSMRep cl_info)
closureNeedsUpdSpace :: ClosureInfo -> Bool
-- We leave space for an update if either (a) the closure is updatable
@@ -875,21 +767,6 @@ closureNeedsUpdSpace (ClosureInfo { closureLFInfo =
LFThunk TopLevel _ _ _ _ }) = True
closureNeedsUpdSpace cl_info = closureUpdReqd cl_info
-minPayloadSize :: SMRep -> Bool -> WordOff
-minPayloadSize smrep updatable
- = case smrep of
- BlackHoleRep -> min_upd_size
- GenericRep _ _ _ _ | updatable -> min_upd_size
- GenericRep True _ _ _ -> 0 -- static
- GenericRep False _ _ _ -> mIN_PAYLOAD_SIZE
- -- ^^^^^___ dynamic
- where
- min_upd_size =
- ASSERT(mIN_PAYLOAD_SIZE <= sIZEOF_StgSMPThunkHeader)
- 0 -- check that we already have enough
- -- room for mIN_SIZE_NonUpdHeapObject,
- -- due to the extra header word in SMP
-
--------------------------------------
-- Other functions over ClosureInfo
--------------------------------------
@@ -929,13 +806,8 @@ staticClosureNeedsLink :: ClosureInfo -> Bool
-- of the SRT.
staticClosureNeedsLink (ClosureInfo { closureSRT = srt })
= needsSRT srt
-staticClosureNeedsLink (ConInfo { closureSMRep = sm_rep, closureCon = con })
- = not (isNullaryRepDataCon con) && not_nocaf_constr
- where
- not_nocaf_constr =
- case sm_rep of
- GenericRep _ _ _ ConstrNoCaf -> False
- _other -> True
+staticClosureNeedsLink (ConInfo { closureSMRep = rep })
+ = not (isStaticNoCafCon rep)
isStaticClosure :: ClosureInfo -> Bool
isStaticClosure cl_info = isStaticRep (closureSMRep cl_info)
@@ -998,28 +870,32 @@ entryLabelFromCI :: ClosureInfo -> CLabel
entryLabelFromCI = snd . labelsFromCI
labelsFromCI :: ClosureInfo -> (CLabel, CLabel) -- (Info, Entry)
-labelsFromCI cl@(ClosureInfo { closureName = name,
- closureLFInfo = lf_info,
- closureInfLcl = is_lcl })
+labelsFromCI (ClosureInfo { closureName = name,
+ closureLFInfo = lf_info,
+ closureCafs = cafs,
+ closureInfLcl = is_lcl })
= case lf_info of
LFBlackHole -> (mkCAFBlackHoleInfoTableLabel, mkCAFBlackHoleEntryLabel)
- LFThunk _ _ upd_flag (SelectorThunk offset) _ ->
- bothL (mkSelectorInfoLabel, mkSelectorEntryLabel) upd_flag offset
-
- LFThunk _ _ upd_flag (ApThunk arity) _ ->
- bothL (mkApInfoTableLabel, mkApEntryLabel) upd_flag arity
+ LFThunk _ _ upd_flag (SelectorThunk offset) _
+ -> bothL (mkSelectorInfoLabel, mkSelectorEntryLabel) upd_flag offset
- LFThunk{} -> bothL std_mk_lbls name $ clHasCafRefs cl
+ LFThunk _ _ upd_flag (ApThunk arity) _
+ -> bothL (mkApInfoTableLabel, mkApEntryLabel) upd_flag arity
- LFReEntrant _ _ _ _ -> bothL std_mk_lbls name $ clHasCafRefs cl
+ LFThunk{} -> bothL std_mk_lbls name cafs
+ LFReEntrant{} -> bothL std_mk_lbls name cafs
+ _other -> panic "labelsFromCI"
- _other -> panic "labelsFromCI"
- where std_mk_lbls = if is_lcl then (mkLocalInfoTableLabel, mkLocalEntryLabel) else (mkInfoTableLabel, mkEntryLabel)
+ where
+ std_mk_lbls | is_lcl = (mkLocalInfoTableLabel, mkLocalEntryLabel)
+ | otherwise = (mkInfoTableLabel, mkEntryLabel)
-labelsFromCI cl@(ConInfo { closureCon = con, closureSMRep = rep })
- | isStaticRep rep = bothL (mkStaticInfoTableLabel, mkStaticConEntryLabel) name $ clHasCafRefs cl
- | otherwise = bothL (mkConInfoTableLabel, mkConEntryLabel) name $ clHasCafRefs cl
+labelsFromCI (ConInfo { closureCon = con, closureSMRep = rep, closureCafs = cafs })
+ | isStaticRep rep
+ = bothL (mkStaticInfoTableLabel, mkStaticConEntryLabel) name cafs
+ | otherwise
+ = bothL (mkConInfoTableLabel, mkConEntryLabel) name cafs
where
name = dataConName con
@@ -1076,16 +952,13 @@ enterLocalIdLabel id c
-- The type is determined from the type information stored with the @Id@
-- in the closure info using @closureTypeDescr@.
-closureValDescr, closureTypeDescr :: ClosureInfo -> String
-closureValDescr (ClosureInfo {closureDescr = descr})
- = descr
-closureValDescr (ConInfo {closureCon = con})
- = occNameString (getOccName con)
-
-closureTypeDescr (ClosureInfo { closureType = ty })
- = getTyDescription ty
-closureTypeDescr (ConInfo { closureCon = data_con })
- = occNameString (getOccName (dataConTyCon data_con))
+mkProfilingInfo :: Id -> String -> ProfilingInfo
+mkProfilingInfo id val_descr
+ | not opt_SccProfilingOn = NoProfilingInfo
+ | otherwise = ProfilingInfo ty_descr_w8 val_descr_w8
+ where
+ ty_descr_w8 = stringToWord8s (getTyDescription (idType id))
+ val_descr_w8 = stringToWord8s val_descr
getTyDescription :: Type -> String
getTyDescription ty
@@ -1107,11 +980,3 @@ getPredTyDescription (ClassP cl _) = getOccString cl
getPredTyDescription (IParam ip _) = getOccString (ipNameName ip)
getPredTyDescription (EqPred {}) = "Type equality"
---------------------------------------
--- SRTs/CAFs
---------------------------------------
-
--- We need to know whether a closure may have CAFs.
-clHasCafRefs :: ClosureInfo -> CafInfo
-clHasCafRefs (ClosureInfo {closureCafs = cafs}) = cafs
-clHasCafRefs (ConInfo {}) = NoCafRefs
diff --git a/compiler/codeGen/StgCmmCon.hs b/compiler/codeGen/StgCmmCon.hs
index 368bc53483..724490c133 100644
--- a/compiler/codeGen/StgCmmCon.hs
+++ b/compiler/codeGen/StgCmmCon.hs
@@ -34,6 +34,7 @@ import Module
import Constants
import DataCon
import FastString
+import IdInfo( CafInfo(..) )
import Id
import Literal
import PrelInfo
@@ -68,10 +69,13 @@ cgTopRhsCon id con args
; let
name = idName id
lf_info = mkConLFInfo con
- closure_label = mkClosureLabel name $ idCafInfo id
- caffy = any stgArgHasCafRefs args
- (closure_info, nv_args_w_offsets)
- = layOutStaticConstr con (addArgReps args)
+ closure_label = mkClosureLabel name caffy
+ caffy = idCafInfo id -- any stgArgHasCafRefs args
+
+ (tot_wds, -- #ptr_wds + #nonptr_wds
+ ptr_wds, -- #ptr_wds
+ nv_args_w_offsets) = mkVirtConstrOffsets (addArgReps args)
+ closure_info = mkConInfo False caffy con tot_wds ptr_wds
get_lit (arg, _offset) = do { CmmLit lit <- getArgAmode arg
; return lit }
@@ -190,8 +194,10 @@ buildDynCon binder _cc con [arg]
-------- buildDynCon: the general case -----------
buildDynCon binder ccs con args
- = do { let (cl_info, args_w_offsets) = layOutDynConstr con (addArgReps args)
+ = do { let (tot_wds, ptr_wds, args_w_offsets)
+ = mkVirtConstrOffsets (addArgReps args)
-- No void args in args_w_offsets
+ cl_info = mkConInfo False NoCafRefs con tot_wds ptr_wds
; (tmp, init) <- allocDynClosure cl_info use_cc blame_cc args_w_offsets
; regIdInfo binder lf_info tmp init }
where
@@ -217,7 +223,7 @@ bindConArgs (DataAlt con) base args
= ASSERT(not (isUnboxedTupleCon con))
mapM bind_arg args_w_offsets
where
- (_, args_w_offsets) = layOutDynConstr con (addIdReps args)
+ (_, _, args_w_offsets) = mkVirtConstrOffsets (addIdReps args)
tag = tagForCon con
diff --git a/compiler/codeGen/StgCmmEnv.hs b/compiler/codeGen/StgCmmEnv.hs
index 369e1993aa..25bbe8f63f 100644
--- a/compiler/codeGen/StgCmmEnv.hs
+++ b/compiler/codeGen/StgCmmEnv.hs
@@ -70,33 +70,39 @@ nonVoidIds ids = [NonVoid id | id <- ids, not (isVoidRep (idPrimRep id))]
mkCgIdInfo :: Id -> LambdaFormInfo -> CmmExpr -> CgIdInfo
mkCgIdInfo id lf expr
- = CgIdInfo { cg_id = id, cg_loc = CmmLoc expr,
- cg_lf = lf, cg_rep = idPrimRep id,
+ = CgIdInfo { cg_id = id, cg_rep = idPrimRep id, cg_lf = lf
+ , cg_loc = CmmLoc expr,
cg_tag = lfDynTag lf }
+litIdInfo :: Id -> LambdaFormInfo -> CmmLit -> CgIdInfo
+litIdInfo id lf lit
+ = CgIdInfo { cg_id = id, cg_rep = idPrimRep id, cg_lf = lf
+ , cg_loc = CmmLoc (addDynTag (CmmLit lit) tag)
+ , cg_tag = tag }
+ where
+ tag = lfDynTag lf
+
lneIdInfo :: Id -> [LocalReg] -> CgIdInfo
lneIdInfo id regs
- = CgIdInfo { cg_id = id, cg_loc = LneLoc blk_id regs,
- cg_lf = lf, cg_rep = idPrimRep id,
- cg_tag = lfDynTag lf }
+ = CgIdInfo { cg_id = id, cg_rep = idPrimRep id, cg_lf = lf
+ , cg_loc = LneLoc blk_id regs
+ , cg_tag = lfDynTag lf }
where
lf = mkLFLetNoEscape
blk_id = mkBlockId (idUnique id)
-litIdInfo :: Id -> LambdaFormInfo -> CmmLit -> CgIdInfo
-litIdInfo id lf_info lit = --mkCgIdInfo id lf_info (CmmLit lit)
- mkCgIdInfo id lf_info (addDynTag (CmmLit lit) (lfDynTag lf_info))
-
-- Because the register may be spilled to the stack in untagged form, we
-- modify the initialization code 'init' to immediately tag the
-- register, and store a plain register in the CgIdInfo. We allocate
-- a new register in order to keep single-assignment and help out the
-- inliner. -- EZY
regIdInfo :: Id -> LambdaFormInfo -> LocalReg -> CmmAGraph -> FCode (CgIdInfo, CmmAGraph)
-regIdInfo id lf_info reg init = do
- reg' <- newTemp (localRegType reg)
- let init' = init <*> mkAssign (CmmLocal reg') (addDynTag (CmmReg (CmmLocal reg)) (lfDynTag lf_info))
- return (mkCgIdInfo id lf_info (CmmReg (CmmLocal reg')), init')
+regIdInfo id lf_info reg init
+ = do { reg' <- newTemp (localRegType reg)
+ ; let init' = init <*> mkAssign (CmmLocal reg')
+ (addDynTag (CmmReg (CmmLocal reg))
+ (lfDynTag lf_info))
+ ; return (mkCgIdInfo id lf_info (CmmReg (CmmLocal reg')), init') }
idInfoToAmode :: CgIdInfo -> CmmExpr
-- Returns a CmmExpr for the *tagged* pointer
diff --git a/compiler/codeGen/StgCmmExpr.hs b/compiler/codeGen/StgCmmExpr.hs
index fa16b2a7f5..d9ae62e206 100644
--- a/compiler/codeGen/StgCmmExpr.hs
+++ b/compiler/codeGen/StgCmmExpr.hs
@@ -29,7 +29,7 @@ import StgSyn
import MkGraph
import BlockId
-import CmmExpr
+import Cmm
import CoreSyn
import DataCon
import ForeignCall
diff --git a/compiler/codeGen/StgCmmForeign.hs b/compiler/codeGen/StgCmmForeign.hs
index b9e9224fd5..54a0214bcb 100644
--- a/compiler/codeGen/StgCmmForeign.hs
+++ b/compiler/codeGen/StgCmmForeign.hs
@@ -24,8 +24,7 @@ import StgCmmUtils
import StgCmmClosure
import BlockId
-import CmmDecl
-import CmmExpr
+import Cmm
import CmmUtils
import OldCmm ( CmmReturnInfo(..) )
import MkGraph
diff --git a/compiler/codeGen/StgCmmHeap.hs b/compiler/codeGen/StgCmmHeap.hs
index 0015da1cac..050ea10083 100644
--- a/compiler/codeGen/StgCmmHeap.hs
+++ b/compiler/codeGen/StgCmmHeap.hs
@@ -12,8 +12,8 @@ module StgCmmHeap (
entryHeapCheck, altHeapCheck,
- layOutDynConstr, layOutStaticConstr,
- mkVirtHeapOffsets, mkStaticClosureFields, mkStaticClosure,
+ mkVirtHeapOffsets, mkVirtConstrOffsets,
+ mkStaticClosureFields, mkStaticClosure,
allocDynClosure, allocDynClosureCmm, emitSetDynHdr
) where
@@ -35,40 +35,16 @@ import StgCmmEnv
import MkGraph
import SMRep
-import CmmExpr
+import Cmm
import CmmUtils
-import DataCon
-import TyCon
import CostCentre
import Outputable
+import IdInfo( CafInfo(..), mayHaveCafRefs )
import Module
import FastString( mkFastString, fsLit )
import Constants
-----------------------------------------------------------
--- Layout of heap objects
------------------------------------------------------------
-
-layOutDynConstr, layOutStaticConstr
- :: DataCon -> [(PrimRep, a)]
- -> (ClosureInfo, [(NonVoid a, VirtualHpOffset)])
- -- No Void arguments in result
-
-layOutDynConstr = layOutConstr False
-layOutStaticConstr = layOutConstr True
-
-layOutConstr :: Bool -> DataCon -> [(PrimRep, a)]
- -> (ClosureInfo, [(NonVoid a, VirtualHpOffset)])
-layOutConstr is_static data_con args
- = (mkConInfo is_static data_con tot_wds ptr_wds,
- things_w_offsets)
- where
- (tot_wds, -- #ptr_wds + #nonptr_wds
- ptr_wds, -- #ptr_wds
- things_w_offsets) = mkVirtHeapOffsets False{-not a thunk-} args
-
-
------------------------------------------------------------
-- Initialise dynamic heap objects
-----------------------------------------------------------
@@ -175,7 +151,7 @@ hpStore base vals offs
mkStaticClosureFields
:: ClosureInfo
-> CostCentreStack
- -> Bool -- Has CAF refs
+ -> CafInfo
-> [CmmLit] -- Payload
-> [CmmLit] -- The full closure
mkStaticClosureFields cl_info ccs caf_refs payload
@@ -210,12 +186,12 @@ mkStaticClosureFields cl_info ccs caf_refs payload
| is_caf = [mkIntCLit 0]
| otherwise = []
- -- for a static constructor which has NoCafRefs, we set the
+ -- For a static constructor which has NoCafRefs, we set the
-- static link field to a non-zero value so the garbage
-- collector will ignore it.
static_link_value
- | caf_refs = mkIntCLit 0
- | otherwise = mkIntCLit 1
+ | mayHaveCafRefs caf_refs = mkIntCLit 0
+ | otherwise = mkIntCLit 1 -- No CAF refs
mkStaticClosure :: CLabel -> CostCentreStack -> [CmmLit]
diff --git a/compiler/codeGen/StgCmmLayout.hs b/compiler/codeGen/StgCmmLayout.hs
index 63fc840845..e9f7394b8b 100644
--- a/compiler/codeGen/StgCmmLayout.hs
+++ b/compiler/codeGen/StgCmmLayout.hs
@@ -15,7 +15,7 @@ module StgCmmLayout (
slowCall, directCall,
- mkVirtHeapOffsets, getHpRelOffset, hpRel,
+ mkVirtHeapOffsets, mkVirtConstrOffsets, getHpRelOffset, hpRel,
stdInfoTableSizeB,
entryCode, closureInfoPtr,
@@ -23,7 +23,7 @@ module StgCmmLayout (
cmmGetClosureType,
infoTable, infoTableClosureType,
infoTablePtrs, infoTableNonPtrs,
- funInfoTable, makeRelativeRefTo
+ funInfoTable
) where
@@ -32,27 +32,21 @@ module StgCmmLayout (
import StgCmmClosure
import StgCmmEnv
import StgCmmTicky
-import StgCmmUtils
import StgCmmMonad
+import StgCmmUtils
import MkGraph
import SMRep
-import CmmDecl
-import CmmExpr
+import Cmm
import CmmUtils
import CLabel
import StgSyn
-import DataCon
import Id
import Name
import TyCon ( PrimRep(..) )
-import Unique
import BasicTypes ( Arity )
import StaticFlags
-import Bitmap
-import Data.Bits
-
import Constants
import Util
import Data.List
@@ -293,6 +287,10 @@ mkVirtHeapOffsets is_thunk things
= (wds_so_far + lRepSizeW (toLRep rep),
(NonVoid thing, hdr_size + wds_so_far))
+mkVirtConstrOffsets :: [(PrimRep,a)] -> (WordOff, WordOff, [(NonVoid a, VirtualHpOffset)])
+-- Just like mkVirtHeapOffsets, but for constructors
+mkVirtConstrOffsets = mkVirtHeapOffsets False
+
-------------------------------------------------------------------------
--
@@ -309,29 +307,16 @@ mkVirtHeapOffsets is_thunk things
-- bring in ARG_P, ARG_N, etc.
#include "../includes/rts/storage/FunTypes.h"
--------------------------
--- argDescrType :: ArgDescr -> StgHalfWord
--- -- The "argument type" RTS field type
--- argDescrType (ArgSpec n) = n
--- argDescrType (ArgGen liveness)
--- | isBigLiveness liveness = ARG_GEN_BIG
--- | otherwise = ARG_GEN
-
-
mkArgDescr :: Name -> [Id] -> FCode ArgDescr
-mkArgDescr nm args
+mkArgDescr _nm args
= case stdPattern arg_reps of
Just spec_id -> return (ArgSpec spec_id)
- Nothing -> do { liveness <- mkLiveness nm size bitmap
- ; return (ArgGen liveness) }
+ Nothing -> return (ArgGen arg_bits)
where
+ arg_bits = argBits arg_reps
arg_reps = filter isNonV (map (toLRep . idPrimRep) args)
-- Getting rid of voids eases matching of standard patterns
- bitmap = mkBitmap arg_bits
- arg_bits = argBits arg_reps
- size = length arg_bits
-
argBits :: [LRep] -> [Bool] -- True for non-ptr, False for ptr
argBits [] = []
argBits (P : args) = False : argBits args
@@ -370,78 +355,6 @@ stdPattern reps
-------------------------------------------------------------------------
--
--- Liveness info
---
--------------------------------------------------------------------------
-
--- TODO: This along with 'mkArgDescr' should be unified
--- with 'CmmInfo.mkLiveness'. However that would require
--- potentially invasive changes to the 'ClosureInfo' type.
--- For now, 'CmmInfo.mkLiveness' handles only continuations and
--- this one handles liveness everything else. Another distinction
--- between these two is that 'CmmInfo.mkLiveness' information
--- about the stack layout, and this one is information about
--- the heap layout of PAPs.
-mkLiveness :: Name -> Int -> Bitmap -> FCode Liveness
-mkLiveness name size bits
- | size > mAX_SMALL_BITMAP_SIZE -- Bitmap does not fit in one word
- = do { let lbl = mkBitmapLabel (getUnique name)
- ; emitRODataLits lbl ( mkWordCLit (fromIntegral size)
- : map mkWordCLit bits)
- ; return (BigLiveness lbl) }
-
- | otherwise -- Bitmap fits in one word
- = let
- small_bits = case bits of
- [] -> 0
- [b] -> b
- _ -> panic "livenessToAddrMode"
- in
- return (smallLiveness size small_bits)
-
-smallLiveness :: Int -> StgWord -> Liveness
-smallLiveness size small_bits = SmallLiveness bits
- where bits = fromIntegral size .|. (small_bits `shiftL` bITMAP_BITS_SHIFT)
-
--------------------
--- isBigLiveness :: Liveness -> Bool
--- isBigLiveness (BigLiveness _) = True
--- isBigLiveness (SmallLiveness _) = False
-
--------------------
--- mkLivenessCLit :: Liveness -> CmmLit
--- mkLivenessCLit (BigLiveness lbl) = CmmLabel lbl
--- mkLivenessCLit (SmallLiveness bits) = mkWordCLit bits
-
-
--------------------------------------------------------------------------
---
--- Bitmap describing register liveness
--- across GC when doing a "generic" heap check
--- (a RET_DYN stack frame).
---
--- NB. Must agree with these macros (currently in StgMacros.h):
--- GET_NON_PTRS(), GET_PTRS(), GET_LIVENESS().
--------------------------------------------------------------------------
-
-{- Not used in new code gen
-mkRegLiveness :: [(Id, GlobalReg)] -> Int -> Int -> StgWord
-mkRegLiveness regs ptrs nptrs
- = (fromIntegral nptrs `shiftL` 16) .|.
- (fromIntegral ptrs `shiftL` 24) .|.
- all_non_ptrs `xor` reg_bits regs
- where
- all_non_ptrs = 0xff
-
- reg_bits [] = 0
- reg_bits ((id, VanillaReg i) : regs) | isGcPtrRep (idPrimRep id)
- = (1 `shiftL` (i - 1)) .|. reg_bits regs
- reg_bits (_ : regs)
- = reg_bits regs
--}
-
--------------------------------------------------------------------------
---
-- Generating the info table and code for a closure
--
-------------------------------------------------------------------------
@@ -479,27 +392,19 @@ emitClosureProcAndInfoTable top_lvl bndr cl_info args body
emitClosureAndInfoTable ::
ClosureInfo -> Convention -> [LocalReg] -> FCode () -> FCode ()
emitClosureAndInfoTable cl_info conv args body
- = do { info <- mkCmmInfo cl_info
+ = do { let info = mkCmmInfo cl_info
; blks <- getCode body
; emitProcWithConvention conv info (entryLabelFromCI cl_info) args blks
}
-- Convert from 'ClosureInfo' to 'CmmInfoTable'.
--- Not used for return points. (The 'smRepClosureTypeInt' call would panic.)
-mkCmmInfo :: ClosureInfo -> FCode CmmInfoTable
+-- Not used for return points.
+mkCmmInfo :: ClosureInfo -> CmmInfoTable
mkCmmInfo cl_info
- = do { info <- closureTypeInfo cl_info k_with_con_name return
- ; prof <- if opt_SccProfilingOn then
- do fd_lit <- mkStringCLit (closureTypeDescr cl_info)
- ad_lit <- mkStringCLit (closureValDescr cl_info)
- return $ ProfilingInfo fd_lit ad_lit
- else return $ ProfilingInfo (mkIntCLit 0) (mkIntCLit 0)
- ; return (CmmInfoTable (infoTableLabelFromCI cl_info) (isStaticClosure cl_info) prof cl_type info) }
- where
- k_with_con_name con_info con info_lbl =
- do cstr <- mkByteStringCLit $ dataConIdentity con
- return $ con_info $ makeRelativeRefTo info_lbl cstr
- cl_type = smRepClosureTypeInt (closureSMRep cl_info)
+ = CmmInfoTable { cit_lbl = infoTableLabelFromCI cl_info,
+ cit_rep = closureSMRep cl_info,
+ cit_prof = closureProf cl_info,
+ cit_srt = closureSRT cl_info }
-----------------------------------------------------------------------------
--
@@ -612,37 +517,3 @@ funInfoTable info_ptr
= cmmOffsetW info_ptr (1 + stdInfoTableSizeW)
-- Past the entry code pointer
--------------------------------------------------------------------------
---
--- Static reference tables
---
--------------------------------------------------------------------------
-
--- srtLabelAndLength :: C_SRT -> CLabel -> (CmmLit, StgHalfWord)
--- srtLabelAndLength NoC_SRT _
--- = (zeroCLit, 0)
--- srtLabelAndLength (C_SRT lbl off bitmap) info_lbl
--- = (makeRelativeRefTo info_lbl $ cmmLabelOffW lbl off, bitmap)
-
--------------------------------------------------------------------------
---
--- Position independent code
---
--------------------------------------------------------------------------
--- In order to support position independent code, we mustn't put absolute
--- references into read-only space. Info tables in the tablesNextToCode
--- case must be in .text, which is read-only, so we doctor the CmmLits
--- to use relative offsets instead.
-
--- Note that this is done even when the -fPIC flag is not specified,
--- as we want to keep binary compatibility between PIC and non-PIC.
-
-makeRelativeRefTo :: CLabel -> CmmLit -> CmmLit
-
-makeRelativeRefTo info_lbl (CmmLabel lbl)
- | tablesNextToCode
- = CmmLabelDiffOff lbl info_lbl 0
-makeRelativeRefTo info_lbl (CmmLabelOff lbl off)
- | tablesNextToCode
- = CmmLabelDiffOff lbl info_lbl off
-makeRelativeRefTo _ lit = lit
diff --git a/compiler/codeGen/StgCmmMonad.hs b/compiler/codeGen/StgCmmMonad.hs
index d06b581f26..c8da75003a 100644
--- a/compiler/codeGen/StgCmmMonad.hs
+++ b/compiler/codeGen/StgCmmMonad.hs
@@ -13,7 +13,7 @@ module StgCmmMonad (
returnFC, fixC, fixC_, nopC, whenC,
newUnique, newUniqSupply,
- emit, emitData, emitProc, emitProcWithConvention, emitSimpleProc,
+ emit, emitDecl, emitProc, emitProcWithConvention, emitSimpleProc,
getCmm, cgStmtsToBlocks,
getCodeR, getCode, getHeapUsage,
@@ -49,13 +49,11 @@ module StgCmmMonad (
#include "HsVersions.h"
+import Cmm
import StgCmmClosure
import DynFlags
import MkGraph
import BlockId
-import CmmDecl
-import CmmExpr
-import CmmNode (UpdFrameOffset)
import CLabel
import TyCon ( PrimRep )
import SMRep
@@ -593,12 +591,10 @@ emit ag
= do { state <- getState
; setState $ state { cgs_stmts = cgs_stmts state <*> ag } }
-emitData :: Section -> CmmStatics -> FCode ()
-emitData sect lits
+emitDecl :: CmmTop -> FCode ()
+emitDecl decl
= do { state <- getState
- ; setState $ state { cgs_tops = cgs_tops state `snocOL` data_block } }
- where
- data_block = CmmData sect lits
+ ; setState $ state { cgs_tops = cgs_tops state `snocOL` decl } }
emitProcWithConvention :: Convention -> CmmInfoTable -> CLabel -> [CmmFormal] ->
CmmAGraph -> FCode ()
@@ -618,7 +614,7 @@ emitSimpleProc :: CLabel -> CmmAGraph -> FCode ()
emitSimpleProc lbl code =
emitProc CmmNonInfoTable lbl [] code
-getCmm :: FCode () -> FCode Cmm
+getCmm :: FCode () -> FCode CmmPgm
-- Get all the CmmTops (there should be no stmts)
-- Return a single Cmm which may be split from other Cmms by
-- object splitting (at a later stage)
@@ -626,7 +622,7 @@ getCmm code
= do { state1 <- getState
; ((), state2) <- withState code (state1 { cgs_tops = nilOL })
; setState $ state2 { cgs_tops = cgs_tops state1 }
- ; return (Cmm (fromOL (cgs_tops state2))) }
+ ; return (fromOL (cgs_tops state2)) }
-- ----------------------------------------------------------------------------
-- CgStmts
diff --git a/compiler/codeGen/StgCmmPrim.hs b/compiler/codeGen/StgCmmPrim.hs
index b68bb601eb..103929c3b7 100644
--- a/compiler/codeGen/StgCmmPrim.hs
+++ b/compiler/codeGen/StgCmmPrim.hs
@@ -24,8 +24,7 @@ import StgCmmProf
import BasicTypes
import MkGraph
import StgSyn
-import CmmDecl
-import CmmExpr
+import Cmm
import Type ( Type, tyConAppTyCon )
import TyCon
import CLabel
diff --git a/compiler/codeGen/StgCmmProf.hs b/compiler/codeGen/StgCmmProf.hs
index 08bf52952c..ca116f2218 100644
--- a/compiler/codeGen/StgCmmProf.hs
+++ b/compiler/codeGen/StgCmmProf.hs
@@ -39,8 +39,7 @@ import StgCmmMonad
import SMRep
import MkGraph
-import CmmExpr
-import CmmDecl
+import Cmm
import CmmUtils
import CLabel
@@ -358,8 +357,8 @@ initCostCentres (local_CCs, ___extern_CCs, singleton_CCSs)
emitCostCentreDecl :: CostCentre -> FCode ()
emitCostCentreDecl cc = do
- { label <- mkStringCLit (costCentreUserName cc)
- ; modl <- mkStringCLit (Module.moduleNameString
+ { label <- newStringCLit (costCentreUserName cc)
+ ; modl <- newStringCLit (Module.moduleNameString
(Module.moduleName (cc_mod cc)))
-- All cost centres will be in the main package, since we
-- don't normally use -auto-all or add SCCs to other packages.
diff --git a/compiler/codeGen/StgCmmTicky.hs b/compiler/codeGen/StgCmmTicky.hs
index a02a698410..8db4d3e829 100644
--- a/compiler/codeGen/StgCmmTicky.hs
+++ b/compiler/codeGen/StgCmmTicky.hs
@@ -45,7 +45,6 @@ module StgCmmTicky (
import StgCmmClosure
import StgCmmUtils
import StgCmmMonad
-import SMRep
import StgSyn
import CmmExpr
@@ -89,8 +88,8 @@ emitTickyCounter :: ClosureInfo -> [Id] -> FCode ()
emitTickyCounter cl_info args
= ifTicky $
do { mod_name <- getModuleName
- ; fun_descr_lit <- mkStringCLit (fun_descr mod_name)
- ; arg_descr_lit <- mkStringCLit arg_descr
+ ; fun_descr_lit <- newStringCLit (fun_descr mod_name)
+ ; arg_descr_lit <- newStringCLit arg_descr
; emitDataLits ticky_ctr_label -- Must match layout of StgEntCounter
-- krc: note that all the fields are I32 now; some were I16 before,
-- but the code generator wasn't handling that properly and it led to chaos,
@@ -270,18 +269,17 @@ tickyDynAlloc :: ClosureInfo -> FCode ()
-- Called when doing a dynamic heap allocation
tickyDynAlloc cl_info
= ifTicky $
- case smRepClosureType (closureSMRep cl_info) of
- Just Constr -> tick_alloc_con
- Just ConstrNoCaf -> tick_alloc_con
- Just Fun -> tick_alloc_fun
- Just Thunk -> tick_alloc_thk
- Just ThunkSelector -> tick_alloc_thk
- -- black hole
- Nothing -> return ()
+ case () of
+ _ | Just _ <- maybeIsLFCon lf -> tick_alloc_con
+ | isLFThunk lf -> tick_alloc_thk
+ | isLFReEntrant lf -> tick_alloc_fun
+ | otherwise -> return ()
where
+ lf = closureLFInfo cl_info
+
-- will be needed when we fill in stubs
- _cl_size = closureSize cl_info
- _slop_size = slopSize cl_info
+ _cl_size = closureSize cl_info
+-- _slop_size = slopSize cl_info
tick_alloc_thk
| closureUpdReqd cl_info = tick_alloc_up_thk
diff --git a/compiler/codeGen/StgCmmUtils.hs b/compiler/codeGen/StgCmmUtils.hs
index 74da7317d4..4575a0384e 100644
--- a/compiler/codeGen/StgCmmUtils.hs
+++ b/compiler/codeGen/StgCmmUtils.hs
@@ -36,7 +36,7 @@ module StgCmmUtils (
addToMem, addToMemE, addToMemLbl,
mkWordCLit,
- mkStringCLit, mkByteStringCLit,
+ newStringCLit, newByteStringCLit,
packHalfWordsCLit,
blankWord,
@@ -48,9 +48,8 @@ module StgCmmUtils (
import StgCmmMonad
import StgCmmClosure
+import Cmm
import BlockId
-import CmmDecl
-import CmmExpr hiding (regUsedIn)
import MkGraph
import CLabel
import CmmUtils
@@ -73,7 +72,6 @@ import FastString
import Outputable
import Data.Char
-import Data.Bits
import Data.Word
import Data.Maybe
@@ -85,10 +83,18 @@ import Data.Maybe
-------------------------------------------------------------------------
cgLit :: Literal -> FCode CmmLit
-cgLit (MachStr s) = mkByteStringCLit (bytesFS s)
+cgLit (MachStr s) = newByteStringCLit (bytesFS s)
-- not unpackFS; we want the UTF-8 byte stream.
cgLit other_lit = return (mkSimpleLit other_lit)
+mkLtOp :: Literal -> MachOp
+-- On signed literals we must do a signed comparison
+mkLtOp (MachInt _) = MO_S_Lt wordWidth
+mkLtOp (MachFloat _) = MO_F_Lt W32
+mkLtOp (MachDouble _) = MO_F_Lt W64
+mkLtOp lit = MO_U_Lt (typeWidth (cmmLitType (mkSimpleLit lit)))
+ -- ToDo: seems terribly indirect!
+
mkSimpleLit :: Literal -> CmmLit
mkSimpleLit (MachChar c) = CmmInt (fromIntegral (ord c)) wordWidth
mkSimpleLit MachNullAddr = zeroCLit
@@ -105,131 +111,6 @@ mkSimpleLit (MachLabel fs ms fod)
labelSrc = ForeignLabelInThisPackage
mkSimpleLit other = pprPanic "mkSimpleLit" (ppr other)
-mkLtOp :: Literal -> MachOp
--- On signed literals we must do a signed comparison
-mkLtOp (MachInt _) = MO_S_Lt wordWidth
-mkLtOp (MachFloat _) = MO_F_Lt W32
-mkLtOp (MachDouble _) = MO_F_Lt W64
-mkLtOp lit = MO_U_Lt (typeWidth (cmmLitType (mkSimpleLit lit)))
- -- ToDo: seems terribly indirect!
-
-
----------------------------------------------------
---
--- Cmm data type functions
---
----------------------------------------------------
-
--- The "B" variants take byte offsets
-cmmRegOffB :: CmmReg -> ByteOff -> CmmExpr
-cmmRegOffB = cmmRegOff
-
-cmmOffsetB :: CmmExpr -> ByteOff -> CmmExpr
-cmmOffsetB = cmmOffset
-
-cmmOffsetExprB :: CmmExpr -> CmmExpr -> CmmExpr
-cmmOffsetExprB = cmmOffsetExpr
-
-cmmLabelOffB :: CLabel -> ByteOff -> CmmLit
-cmmLabelOffB = cmmLabelOff
-
-cmmOffsetLitB :: CmmLit -> ByteOff -> CmmLit
-cmmOffsetLitB = cmmOffsetLit
-
------------------------
--- The "W" variants take word offsets
-cmmOffsetExprW :: CmmExpr -> CmmExpr -> CmmExpr
--- The second arg is a *word* offset; need to change it to bytes
-cmmOffsetExprW e (CmmLit (CmmInt n _)) = cmmOffsetW e (fromInteger n)
-cmmOffsetExprW e wd_off = cmmIndexExpr wordWidth e wd_off
-
-cmmOffsetW :: CmmExpr -> WordOff -> CmmExpr
-cmmOffsetW e n = cmmOffsetB e (wORD_SIZE * n)
-
-cmmRegOffW :: CmmReg -> WordOff -> CmmExpr
-cmmRegOffW reg wd_off = cmmRegOffB reg (wd_off * wORD_SIZE)
-
-cmmOffsetLitW :: CmmLit -> WordOff -> CmmLit
-cmmOffsetLitW lit wd_off = cmmOffsetLitB lit (wORD_SIZE * wd_off)
-
-cmmLabelOffW :: CLabel -> WordOff -> CmmLit
-cmmLabelOffW lbl wd_off = cmmLabelOffB lbl (wORD_SIZE * wd_off)
-
-cmmLoadIndexW :: CmmExpr -> Int -> CmmType -> CmmExpr
-cmmLoadIndexW base off ty = CmmLoad (cmmOffsetW base off) ty
-
------------------------
-cmmULtWord, cmmUGeWord, cmmUGtWord, cmmSubWord,
- cmmNeWord, cmmEqWord, cmmOrWord, cmmAndWord,
- cmmUShrWord, cmmAddWord, cmmMulWord
- :: CmmExpr -> CmmExpr -> CmmExpr
-cmmOrWord e1 e2 = CmmMachOp mo_wordOr [e1, e2]
-cmmAndWord e1 e2 = CmmMachOp mo_wordAnd [e1, e2]
-cmmNeWord e1 e2 = CmmMachOp mo_wordNe [e1, e2]
-cmmEqWord e1 e2 = CmmMachOp mo_wordEq [e1, e2]
-cmmULtWord e1 e2 = CmmMachOp mo_wordULt [e1, e2]
-cmmUGeWord e1 e2 = CmmMachOp mo_wordUGe [e1, e2]
-cmmUGtWord e1 e2 = CmmMachOp mo_wordUGt [e1, e2]
---cmmShlWord e1 e2 = CmmMachOp mo_wordShl [e1, e2]
-cmmUShrWord e1 e2 = CmmMachOp mo_wordUShr [e1, e2]
-cmmAddWord e1 e2 = CmmMachOp mo_wordAdd [e1, e2]
-cmmSubWord e1 e2 = CmmMachOp mo_wordSub [e1, e2]
-cmmMulWord e1 e2 = CmmMachOp mo_wordMul [e1, e2]
-
-cmmNegate :: CmmExpr -> CmmExpr
-cmmNegate (CmmLit (CmmInt n rep)) = CmmLit (CmmInt (-n) rep)
-cmmNegate e = CmmMachOp (MO_S_Neg (cmmExprWidth e)) [e]
-
-blankWord :: CmmStatic
-blankWord = CmmUninitialised wORD_SIZE
-
--- Tagging --
--- Tag bits mask
---cmmTagBits = CmmLit (mkIntCLit tAG_BITS)
-cmmTagMask, cmmPointerMask :: CmmExpr
-cmmTagMask = CmmLit (mkIntCLit tAG_MASK)
-cmmPointerMask = CmmLit (mkIntCLit (complement tAG_MASK))
-
--- Used to untag a possibly tagged pointer
--- A static label need not be untagged
-cmmUntag, cmmGetTag :: CmmExpr -> CmmExpr
-cmmUntag e@(CmmLit (CmmLabel _)) = e
--- Default case
-cmmUntag e = (e `cmmAndWord` cmmPointerMask)
-
-cmmGetTag e = (e `cmmAndWord` cmmTagMask)
-
--- Test if a closure pointer is untagged
-cmmIsTagged :: CmmExpr -> CmmExpr
-cmmIsTagged e = (e `cmmAndWord` cmmTagMask)
- `cmmNeWord` CmmLit zeroCLit
-
-cmmConstrTag, cmmConstrTag1 :: CmmExpr -> CmmExpr
-cmmConstrTag e = (e `cmmAndWord` cmmTagMask) `cmmSubWord` (CmmLit (mkIntCLit 1))
--- Get constructor tag, but one based.
-cmmConstrTag1 e = e `cmmAndWord` cmmTagMask
-
------------------------
--- Making literals
-
-mkWordCLit :: StgWord -> CmmLit
-mkWordCLit wd = CmmInt (fromIntegral wd) wordWidth
-
-packHalfWordsCLit :: (Integral a, Integral b) => a -> b -> CmmLit
--- Make a single word literal in which the lower_half_word is
--- at the lower address, and the upper_half_word is at the
--- higher address
--- ToDo: consider using half-word lits instead
--- but be careful: that's vulnerable when reversed
-packHalfWordsCLit lower_half_word upper_half_word
-#ifdef WORDS_BIGENDIAN
- = mkWordCLit ((fromIntegral lower_half_word `shiftL` hALF_WORD_SIZE_IN_BITS)
- .|. fromIntegral upper_half_word)
-#else
- = mkWordCLit ((fromIntegral lower_half_word)
- .|. (fromIntegral upper_half_word `shiftL` hALF_WORD_SIZE_IN_BITS))
-#endif
-
--------------------------------------------------------------------------
--
-- Incrementing a memory location
@@ -507,44 +388,23 @@ baseRegOffset reg = pprPanic "baseRegOffset:" (ppr reg)
emitDataLits :: CLabel -> [CmmLit] -> FCode ()
-- Emit a data-segment data block
-emitDataLits lbl lits
- = emitData Data (Statics lbl $ map CmmStaticLit lits)
-
-mkDataLits :: CLabel -> [CmmLit] -> GenCmmTop CmmStatics info stmt
--- Emit a data-segment data block
-mkDataLits lbl lits
- = CmmData Data (Statics lbl $ map CmmStaticLit lits)
+emitDataLits lbl lits = emitDecl (mkDataLits Data lbl lits)
emitRODataLits :: CLabel -> [CmmLit] -> FCode ()
-- Emit a read-only data block
-emitRODataLits lbl lits
- = emitData section (Statics lbl $ map CmmStaticLit lits)
- where section | any needsRelocation lits = RelocatableReadOnlyData
- | otherwise = ReadOnlyData
- needsRelocation (CmmLabel _) = True
- needsRelocation (CmmLabelOff _ _) = True
- needsRelocation _ = False
-
-mkRODataLits :: CLabel -> [CmmLit] -> GenCmmTop CmmStatics info stmt
-mkRODataLits lbl lits
- = CmmData section (Statics lbl $ map CmmStaticLit lits)
- where section | any needsRelocation lits = RelocatableReadOnlyData
- | otherwise = ReadOnlyData
- needsRelocation (CmmLabel _) = True
- needsRelocation (CmmLabelOff _ _) = True
- needsRelocation _ = False
-
-mkStringCLit :: String -> FCode CmmLit
+emitRODataLits lbl lits = emitDecl (mkRODataLits lbl lits)
+
+newStringCLit :: String -> FCode CmmLit
-- Make a global definition for the string,
-- and return its label
-mkStringCLit str = mkByteStringCLit (map (fromIntegral . ord) str)
+newStringCLit str = newByteStringCLit (map (fromIntegral . ord) str)
-mkByteStringCLit :: [Word8] -> FCode CmmLit
-mkByteStringCLit bytes
+newByteStringCLit :: [Word8] -> FCode CmmLit
+newByteStringCLit bytes
= do { uniq <- newUnique
- ; let lbl = mkStringLitLabel uniq
- ; emitData ReadOnlyData $ Statics lbl [CmmString bytes]
- ; return (CmmLabel lbl) }
+ ; let (lit, decl) = mkByteStringCLit uniq bytes
+ ; emitDecl decl
+ ; return lit }
-------------------------------------------------------------------------
--
@@ -658,14 +518,7 @@ unscramble vertices
mk_graph (reg, rhs) = mkAssign (CmmLocal reg) rhs
mustFollow :: Stmt -> Stmt -> Bool
-(reg, _) `mustFollow` (_, rhs) = reg `regUsedIn` rhs
-
-regUsedIn :: LocalReg -> CmmExpr -> Bool
-reg `regUsedIn` CmmLoad e _ = reg `regUsedIn` e
-reg `regUsedIn` CmmReg (CmmLocal reg') = reg == reg'
-reg `regUsedIn` CmmRegOff (CmmLocal reg') _ = reg == reg'
-reg `regUsedIn` CmmMachOp _ es = any (reg `regUsedIn`) es
-_reg `regUsedIn` _other = False -- The CmmGlobal cases
+(reg, _) `mustFollow` (_, rhs) = CmmLocal reg `regUsedIn` rhs
-------------------------------------------------------------------------
-- mkSwitch
diff --git a/compiler/ghc.cabal.in b/compiler/ghc.cabal.in
index e393bb7e7f..d553e5d63c 100644
--- a/compiler/ghc.cabal.in
+++ b/compiler/ghc.cabal.in
@@ -187,7 +187,6 @@ Library
CmmCommonBlockElim
CmmContFlowOpt
CmmCvt
- CmmDecl
CmmExpr
CmmInfo
CmmLex
diff --git a/compiler/llvmGen/LlvmCodeGen.hs b/compiler/llvmGen/LlvmCodeGen.hs
index be5c79cf64..e9c50b25ef 100644
--- a/compiler/llvmGen/LlvmCodeGen.hs
+++ b/compiler/llvmGen/LlvmCodeGen.hs
@@ -33,9 +33,9 @@ import System.IO
-- -----------------------------------------------------------------------------
-- | Top-level of the LLVM Code generator
--
-llvmCodeGen :: DynFlags -> Handle -> UniqSupply -> [RawCmm] -> IO ()
+llvmCodeGen :: DynFlags -> Handle -> UniqSupply -> [RawCmmPgm] -> IO ()
llvmCodeGen dflags h us cmms
- = let cmm = concat $ map (\(Cmm top) -> top) cmms
+ = let cmm = concat cmms
(cdata,env) = foldr split ([],initLlvmEnv) cmm
split (CmmData s d' ) (d,e) = ((s,d'):d,e)
split (CmmProc i l _) (d,e) =
@@ -115,7 +115,7 @@ cmmLlvmGen dflags us env cmm = do
let fixed_cmm = fixStgRegisters cmm
dumpIfSet_dyn dflags Opt_D_dump_opt_cmm "Optimised Cmm"
- (pprCmm (targetPlatform dflags) $ Cmm [fixed_cmm])
+ (pprCmmPgm (targetPlatform dflags) [fixed_cmm])
-- generate llvm code from cmm
let ((env', llvmBC), usGen) = initUs us $ genLlvmProc env fixed_cmm
diff --git a/compiler/main/CodeOutput.lhs b/compiler/main/CodeOutput.lhs
index 3ff35b6b92..597f9621d3 100644
--- a/compiler/main/CodeOutput.lhs
+++ b/compiler/main/CodeOutput.lhs
@@ -18,7 +18,7 @@ import PprC ( writeCs )
import CmmLint ( cmmLint )
import Packages
import Util
-import OldCmm ( RawCmm )
+import OldCmm ( RawCmmPgm )
import HscTypes
import DynFlags
import Config
@@ -48,7 +48,7 @@ codeOutput :: DynFlags
-> ModLocation
-> ForeignStubs
-> [PackageId]
- -> [RawCmm] -- Compiled C--
+ -> [RawCmmPgm] -- Compiled C--
-> IO (Bool{-stub_h_exists-}, Maybe FilePath{-stub_c_exists-})
codeOutput dflags this_mod location foreign_stubs pkg_deps flat_abstractC
@@ -96,7 +96,7 @@ doOutput filenm io_action = bracket (openFile filenm WriteMode) hClose io_action
\begin{code}
outputC :: DynFlags
-> FilePath
- -> [RawCmm]
+ -> [RawCmmPgm]
-> [PackageId]
-> IO ()
@@ -134,7 +134,7 @@ outputC dflags filenm flat_absC packages
%************************************************************************
\begin{code}
-outputAsm :: DynFlags -> FilePath -> [RawCmm] -> IO ()
+outputAsm :: DynFlags -> FilePath -> [RawCmmPgm] -> IO ()
outputAsm dflags filenm flat_absC
| cGhcWithNativeCodeGen == "YES"
= do ncg_uniqs <- mkSplitUniqSupply 'n'
@@ -155,7 +155,7 @@ outputAsm dflags filenm flat_absC
%************************************************************************
\begin{code}
-outputLlvm :: DynFlags -> FilePath -> [RawCmm] -> IO ()
+outputLlvm :: DynFlags -> FilePath -> [RawCmmPgm] -> IO ()
outputLlvm dflags filenm flat_absC
= do ncg_uniqs <- mkSplitUniqSupply 'n'
doOutput filenm $ \f -> llvmCodeGen dflags f ncg_uniqs flat_absC
diff --git a/compiler/main/DynFlags.hs b/compiler/main/DynFlags.hs
index 5b23876b36..03530b1e54 100644
--- a/compiler/main/DynFlags.hs
+++ b/compiler/main/DynFlags.hs
@@ -283,7 +283,6 @@ data DynFlag
-- temporary flags
| Opt_RunCPS
| Opt_RunCPSZ
- | Opt_ConvertToZipCfgAndBack
| Opt_AutoLinkPackages
| Opt_ImplicitImportQualified
| Opt_TryNewCodeGen
@@ -1734,7 +1733,6 @@ fFlags = [
( "run-cps", AlwaysAllowed, Opt_RunCPS, nop ),
( "run-cpsz", AlwaysAllowed, Opt_RunCPSZ, nop ),
( "new-codegen", AlwaysAllowed, Opt_TryNewCodeGen, nop ),
- ( "convert-to-zipper-and-back", AlwaysAllowed, Opt_ConvertToZipCfgAndBack, nop ),
( "vectorise", AlwaysAllowed, Opt_Vectorise, nop ),
( "regs-graph", AlwaysAllowed, Opt_RegsGraph, nop ),
( "regs-iterative", AlwaysAllowed, Opt_RegsIterative, nop ),
diff --git a/compiler/main/HscMain.lhs b/compiler/main/HscMain.lhs
index ae858fde28..c43c396c64 100644
--- a/compiler/main/HscMain.lhs
+++ b/compiler/main/HscMain.lhs
@@ -115,7 +115,7 @@ import TyCon ( TyCon, isDataTyCon )
import Name ( Name, NamedThing(..) )
import SimplStg ( stg2stg )
import CodeGen ( codeGen )
-import OldCmm ( Cmm )
+import OldCmm as Old ( CmmPgm )
import PprCmm ( pprCmms )
import CmmParse ( parseCmmFile )
import CmmBuildInfoTables
@@ -123,7 +123,6 @@ import CmmPipeline
import CmmInfo
import OptimizationFuel ( initOptFuelState )
import CmmCvt
-import CmmContFlowOpt ( runCmmContFlowOpts )
import CodeOutput
import NameEnv ( emptyNameEnv )
import NameSet ( emptyNameSet )
@@ -1114,17 +1113,14 @@ hscGenHardCode cgguts mod_summary
------------------ Code generation ------------------
cmms <- if dopt Opt_TryNewCodeGen dflags
- then do cmms <- tryNewCodeGen hsc_env this_mod data_tycons
+ then tryNewCodeGen hsc_env this_mod data_tycons
cost_centre_info
stg_binds hpc_info
- return cmms
else {-# SCC "CodeGen" #-}
codeGen dflags this_mod data_tycons
cost_centre_info
stg_binds hpc_info
- --- Optionally run experimental Cmm transformations ---
- cmms <- optionallyConvertAndOrCPS hsc_env cmms
-- unless certain dflags are on, the identity function
------------------ Code output -----------------------
rawcmms <- cmmToRawCmm cmms
@@ -1179,8 +1175,7 @@ hscCompileCmmFile hsc_env filename
let dflags = hsc_dflags hsc_env
cmm <- ioMsgMaybe $ parseCmmFile dflags filename
liftIO $ do
- cmms <- optionallyConvertAndOrCPS hsc_env [cmm]
- rawCmms <- cmmToRawCmm cmms
+ rawCmms <- cmmToRawCmm [cmm]
_ <- codeOutput dflags no_mod no_loc NoStubs [] rawCmms
return ()
where
@@ -1195,7 +1190,7 @@ tryNewCodeGen :: HscEnv -> Module -> [TyCon]
-> CollectedCCs
-> [(StgBinding,[(Id,[Id])])]
-> HpcInfo
- -> IO [Cmm]
+ -> IO [Old.CmmPgm]
tryNewCodeGen hsc_env this_mod data_tycons
cost_centre_info stg_binds hpc_info =
do { let dflags = hsc_dflags hsc_env
@@ -1216,38 +1211,6 @@ tryNewCodeGen hsc_env this_mod data_tycons
; return prog' }
-optionallyConvertAndOrCPS :: HscEnv -> [Cmm] -> IO [Cmm]
-optionallyConvertAndOrCPS hsc_env cmms =
- do let dflags = hsc_dflags hsc_env
- -------- Optionally convert to and from zipper ------
- cmms <- if dopt Opt_ConvertToZipCfgAndBack dflags
- then mapM (testCmmConversion hsc_env) cmms
- else return cmms
- return cmms
-
-
-testCmmConversion :: HscEnv -> Cmm -> IO Cmm
-testCmmConversion hsc_env cmm =
- do let dflags = hsc_dflags hsc_env
- platform = targetPlatform dflags
- showPass dflags "CmmToCmm"
- dumpIfSet_dyn dflags Opt_D_dump_cvt_cmm "C-- pre-conversion" (pprPlatform platform cmm)
- --continuationC <- cmmCPS dflags abstractC >>= cmmToRawCmm
- us <- mkSplitUniqSupply 'C'
- let zgraph = initUs_ us (cmmToZgraph platform cmm)
- chosen_graph <-
- if dopt Opt_RunCPSZ dflags
- then do us <- mkSplitUniqSupply 'S'
- let topSRT = initUs_ us emptySRT
- (_, [zgraph]) <- cmmPipeline hsc_env (topSRT, []) zgraph
- return zgraph
- else return (runCmmContFlowOpts zgraph)
- dumpIfSet_dyn dflags Opt_D_dump_cmmz "C-- Zipper Graph" (pprPlatform platform chosen_graph)
- showPass dflags "Convert from Z back to Cmm"
- let cvt = cmmOfZgraph chosen_graph
- dumpIfSet_dyn dflags Opt_D_dump_cvt_cmm "C-- post-conversion" (pprPlatform platform cvt)
- return cvt
-
myCoreToStg :: DynFlags -> Module -> [CoreBind]
-> IO ( [(StgBinding,[(Id,[Id])])] -- output program
, CollectedCCs) -- cost centre info (declared and used)
diff --git a/compiler/nativeGen/AsmCodeGen.lhs b/compiler/nativeGen/AsmCodeGen.lhs
index 350f533d85..aabe39af85 100644
--- a/compiler/nativeGen/AsmCodeGen.lhs
+++ b/compiler/nativeGen/AsmCodeGen.lhs
@@ -148,7 +148,7 @@ data NcgImpl statics instr jumpDest = NcgImpl {
}
--------------------
-nativeCodeGen :: DynFlags -> Handle -> UniqSupply -> [RawCmm] -> IO ()
+nativeCodeGen :: DynFlags -> Handle -> UniqSupply -> [RawCmmPgm] -> IO ()
nativeCodeGen dflags h us cmms
= let nCG' :: (Outputable statics, PlatformOutputable instr, Instruction instr) => NcgImpl statics instr jumpDest -> IO ()
nCG' ncgImpl = nativeCodeGen' dflags ncgImpl h us cmms
@@ -209,7 +209,7 @@ nativeCodeGen dflags h us cmms
nativeCodeGen' :: (Outputable statics, PlatformOutputable instr, Instruction instr)
=> DynFlags
-> NcgImpl statics instr jumpDest
- -> Handle -> UniqSupply -> [RawCmm] -> IO ()
+ -> Handle -> UniqSupply -> [RawCmmPgm] -> IO ()
nativeCodeGen' dflags ncgImpl h us cmms
= do
let platform = targetPlatform dflags
@@ -264,7 +264,7 @@ nativeCodeGen' dflags ncgImpl h us cmms
return ()
- where add_split (Cmm tops)
+ where add_split tops
| dopt Opt_SplitObjs dflags = split_marker : tops
| otherwise = tops
@@ -356,7 +356,7 @@ cmmNativeGen dflags ncgImpl us cmm count
dumpIfSet_dyn dflags
Opt_D_dump_opt_cmm "Optimised Cmm"
- (pprCmm platform $ Cmm [opt_cmm])
+ (pprCmmPgm platform [opt_cmm])
-- generate native code from cmm
let ((native, lastMinuteImports), usGen) =
diff --git a/compiler/nativeGen/Instruction.hs b/compiler/nativeGen/Instruction.hs
index b2db2ef206..31827b9088 100644
--- a/compiler/nativeGen/Instruction.hs
+++ b/compiler/nativeGen/Instruction.hs
@@ -37,7 +37,7 @@ noUsage = RU [] []
-- Our flavours of the Cmm types
-- Type synonyms for Cmm populated with native code
type NatCmm instr
- = GenCmm
+ = GenCmmPgm
CmmStatics
(Maybe CmmStatics)
(ListGraph instr)
diff --git a/compiler/utils/FastString.lhs b/compiler/utils/FastString.lhs
index 35d4387dd3..c37fc26f72 100644
--- a/compiler/utils/FastString.lhs
+++ b/compiler/utils/FastString.lhs
@@ -434,6 +434,7 @@ unpackFS (FastString _ n_bytes _ buf enc) =
ZEncoded -> peekCAStringLen (castPtr ptr,n_bytes)
UTF8Encoded _ -> utf8DecodeString ptr n_bytes
+-- | Gives the UTF-8 encoded bytes corresponding to a 'FastString'
bytesFS :: FastString -> [Word8]
bytesFS (FastString _ n_bytes _ buf _) =
inlinePerformIO $ withForeignPtr buf $ \ptr ->
diff --git a/includes/rts/storage/InfoTables.h b/includes/rts/storage/InfoTables.h
index cbfb0327c2..4b0c40bbce 100644
--- a/includes/rts/storage/InfoTables.h
+++ b/includes/rts/storage/InfoTables.h
@@ -214,7 +214,7 @@ typedef union {
*/
typedef struct StgInfoTable_ {
-#ifndef TABLES_NEXT_TO_CODE
+#if !defined(TABLES_NEXT_TO_CODE)
StgFunPtr entry; /* pointer to the entry code */
#endif
@@ -344,11 +344,11 @@ typedef struct StgConInfoTable_ {
StgInfoTable i;
#endif
-#ifndef TABLES_NEXT_TO_CODE
- char *con_desc;
-#else
+#if defined(TABLES_NEXT_TO_CODE)
OFFSET_FIELD(con_desc) // the name of the data constructor
// as: Package:Module.Name
+#else
+ char *con_desc;
#endif
#if defined(TABLES_NEXT_TO_CODE)