diff options
author | Simon Marlow <marlowsd@gmail.com> | 2012-10-03 09:30:56 +0100 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2012-10-08 09:04:40 +0100 |
commit | a7c0387d20c1c9994d1100b14fbb8fb4e28a259e (patch) | |
tree | b95d0a512f951a4a463f1aa5178b0cd5c4fdb410 /compiler/codeGen/CgExtCode.hs | |
parent | aed37acd4d157791381800d5de960a2461bcbef3 (diff) | |
download | haskell-a7c0387d20c1c9994d1100b14fbb8fb4e28a259e.tar.gz |
Produce new-style Cmm from the Cmm parser
The main change here is that the Cmm parser now allows high-level cmm
code with argument-passing and function calls. For example:
foo ( gcptr a, bits32 b )
{
if (b > 0) {
// we can make tail calls passing arguments:
jump stg_ap_0_fast(a);
}
return (x,y);
}
More details on the new cmm syntax are in Note [Syntax of .cmm files]
in CmmParse.y.
The old syntax is still more-or-less supported for those occasional
code fragments that really need to explicitly manipulate the stack.
However there are a couple of differences: it is now obligatory to
give a list of live GlobalRegs on every jump, e.g.
jump %ENTRY_CODE(Sp(0)) [R1];
Again, more details in Note [Syntax of .cmm files].
I have rewritten most of the .cmm files in the RTS into the new
syntax, except for AutoApply.cmm which is generated by the genapply
program: this file could be generated in the new syntax instead and
would probably be better off for it, but I ran out of enthusiasm.
Some other changes in this batch:
- The PrimOp calling convention is gone, primops now use the ordinary
NativeNodeCall convention. This means that primops and "foreign
import prim" code must be written in high-level cmm, but they can
now take more than 10 arguments.
- CmmSink now does constant-folding (should fix #7219)
- .cmm files now go through the cmmPipeline, and as a result we
generate better code in many cases. All the object files generated
for the RTS .cmm files are now smaller. Performance should be
better too, but I haven't measured it yet.
- RET_DYN frames are removed from the RTS, lots of code goes away
- we now have some more canned GC points to cover unboxed-tuples with
2-4 pointers, which will reduce code size a little.
Diffstat (limited to 'compiler/codeGen/CgExtCode.hs')
-rw-r--r-- | compiler/codeGen/CgExtCode.hs | 241 |
1 files changed, 0 insertions, 241 deletions
diff --git a/compiler/codeGen/CgExtCode.hs b/compiler/codeGen/CgExtCode.hs deleted file mode 100644 index a651319a49..0000000000 --- a/compiler/codeGen/CgExtCode.hs +++ /dev/null @@ -1,241 +0,0 @@ --- | Our extended FCode monad. - --- We add a mapping from names to CmmExpr, to support local variable names in --- the concrete C-- code. The unique supply of the underlying FCode monad --- is used to grab a new unique for each local variable. - --- In C--, a local variable can be declared anywhere within a proc, --- and it scopes from the beginning of the proc to the end. Hence, we have --- to collect declarations as we parse the proc, and feed the environment --- back in circularly (to avoid a two-pass algorithm). - -{-# OPTIONS -fno-warn-tabs #-} --- The above warning supression flag is a temporary kludge. --- While working on this module you are encouraged to remove it and --- detab the module (please do the detabbing in a separate patch). See --- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#TabsvsSpaces --- for details - -module CgExtCode ( - ExtFCode(..), - ExtCode, - Named(..), Env, - - loopDecls, - getEnv, - - newLocal, - newLabel, - newFunctionName, - newImport, - lookupLabel, - lookupName, - - code, - code2, - nopEC, - stmtEC, - stmtsEC, - getCgStmtsEC, - getCgStmtsEC', - forkLabelledCodeEC -) - -where - -import CgMonad - -import CLabel -import OldCmm hiding( ClosureTypeInfo(..) ) - --- import BasicTypes -import BlockId -import DynFlags -import FastString -import Module -import UniqFM -import Unique - - --- | The environment contains variable definitions or blockids. -data Named - = VarN CmmExpr -- ^ Holds CmmLit(CmmLabel ..) which gives the label type, - -- eg, RtsLabel, ForeignLabel, CmmLabel etc. - - | 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 - --- | Local declarations that are in scope during code generation. -type Decls = [(FastString,Named)] - --- | Does a computation in the FCode monad, with a current environment --- and a list of local declarations. Returns the resulting list of declarations. -newtype ExtFCode a - = EC { unEC :: Env -> Decls -> FCode (Decls, a) } - -type ExtCode = ExtFCode () - -returnExtFC :: a -> ExtFCode a -returnExtFC a = EC $ \_ s -> return (s, a) - -thenExtFC :: ExtFCode a -> (a -> ExtFCode b) -> ExtFCode b -thenExtFC (EC m) k = EC $ \e s -> do (s',r) <- m e s; unEC (k r) e s' - -instance Monad ExtFCode where - (>>=) = thenExtFC - return = returnExtFC - -instance HasDynFlags ExtFCode where - getDynFlags = EC (\_ d -> do dflags <- getDynFlags - return (d, dflags)) - - --- | Takes the variable decarations and imports from the monad --- and makes an environment, which is looped back into the computation. --- In this way, we can have embedded declarations that scope over the whole --- procedure, and imports that scope over the entire module. --- Discards the local declaration contained within decl' --- -loopDecls :: ExtFCode a -> ExtFCode a -loopDecls (EC fcode) = - EC $ \e globalDecls -> do - (_, a) <- fixC (\ ~(decls, _) -> fcode (addListToUFM e (decls ++ globalDecls)) globalDecls) - return (globalDecls, a) - - --- | Get the current environment from the monad. -getEnv :: ExtFCode Env -getEnv = EC $ \e s -> return (s, e) - - --- | Add a new variable to the list of local declarations. --- The CmmExpr says where the value is stored. -addVarDecl :: FastString -> CmmExpr -> ExtCode -addVarDecl var expr - = 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, LabelN block_id):s, ()) - - --- | Create a fresh local variable of a given type. -newLocal - :: CmmType -- ^ data type - -> FastString -- ^ name of variable - -> ExtFCode LocalReg -- ^ register holding the value - -newLocal ty name = do - u <- code newUnique - let reg = LocalReg u ty - addVarDecl name (CmmReg (CmmLocal reg)) - return reg - - --- | Allocate a fresh label. -newLabel :: FastString -> ExtFCode BlockId -newLabel name = do - u <- code newUnique - addLabel name (mkBlockId u) - return (mkBlockId u) - - --- | Add add a local function to the environment. -newFunctionName - :: FastString -- ^ name of the function - -> PackageId -- ^ package of the current module - -> ExtCode - -newFunctionName name pkg - = EC $ \_ s -> return ((name, FunN pkg):s, ()) - - --- | Add an imported foreign label to the list of local declarations. --- If this is done at the start of the module the declaration will scope --- over the whole module. -newImport - :: (FastString, CLabel) - -> ExtFCode () - -newImport (name, cmmLabel) - = addVarDecl name (CmmLit (CmmLabel cmmLabel)) - - --- | Lookup the BlockId bound to the label with this name. --- If one hasn't been bound yet, create a fresh one based on the --- Unique of the name. -lookupLabel :: FastString -> ExtFCode BlockId -lookupLabel name = do - env <- getEnv - return $ - case lookupUFM env name of - Just (LabelN l) -> l - _other -> mkBlockId (newTagUnique (getUnique name) 'L') - - --- | Lookup the location of a named variable. --- Unknown names are treated as if they had been 'import'ed from the runtime system. --- This saves us a lot of bother in the RTS sources, at the expense of --- deferring some errors to link time. -lookupName :: FastString -> ExtFCode CmmExpr -lookupName name = do - env <- getEnv - return $ - case lookupUFM env name of - Just (VarN e) -> e - Just (FunN pkg) -> CmmLit (CmmLabel (mkCmmCodeLabel pkg name)) - _other -> CmmLit (CmmLabel (mkCmmCodeLabel rtsPackageId name)) - - --- | Lift an FCode computation into the ExtFCode monad -code :: FCode a -> ExtFCode a -code fc = EC $ \_ s -> do - r <- fc - return (s, r) - - -code2 :: (FCode (Decls,b) -> FCode ((Decls,b),c)) -> ExtFCode b -> ExtFCode c -code2 f (EC ec) - = EC $ \e s -> do - ((s', _),c) <- f (ec e s) - return (s',c) - - --- | Do nothing in the ExtFCode monad. -nopEC :: ExtFCode () -nopEC = code nopC - - --- | Accumulate a CmmStmt into the monad state. -stmtEC :: CmmStmt -> ExtFCode () -stmtEC stmt = code (stmtC stmt) - - --- | Accumulate some CmmStmts into the monad state. -stmtsEC :: [CmmStmt] -> ExtFCode () -stmtsEC stmts = code (stmtsC stmts) - - --- | Get the generated statements out of the monad state. -getCgStmtsEC :: ExtFCode a -> ExtFCode CgStmts -getCgStmtsEC = code2 getCgStmts' - - --- | Get the generated statements, and the return value out of the monad state. -getCgStmtsEC' :: ExtFCode a -> ExtFCode (a, CgStmts) -getCgStmtsEC' = code2 (\m -> getCgStmts' m >>= f) - where f ((decl, b), c) = return ((decl, b), (b, c)) - - --- | Emit a chunk of code outside the instruction stream, --- and return its block id. -forkLabelledCodeEC :: ExtFCode a -> ExtFCode BlockId -forkLabelledCodeEC ec = do - stmts <- getCgStmtsEC ec - code (forkCgStmts stmts) - - |