PageRenderTime 26ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/ghc-7.0.4/compiler/codeGen/CgExtCode.hs

http://picorec.googlecode.com/
Haskell | 229 lines | 123 code | 60 blank | 46 comment | 0 complexity | 2179b62b0392a5a072f224e0801ab3e6 MD5 | raw file
Possible License(s): BSD-3-Clause, BSD-2-Clause
  1. -- | Our extended FCode monad.
  2. -- We add a mapping from names to CmmExpr, to support local variable names in
  3. -- the concrete C-- code. The unique supply of the underlying FCode monad
  4. -- is used to grab a new unique for each local variable.
  5. -- In C--, a local variable can be declared anywhere within a proc,
  6. -- and it scopes from the beginning of the proc to the end. Hence, we have
  7. -- to collect declarations as we parse the proc, and feed the environment
  8. -- back in circularly (to avoid a two-pass algorithm).
  9. module CgExtCode (
  10. ExtFCode(..),
  11. ExtCode,
  12. Named(..), Env,
  13. loopDecls,
  14. getEnv,
  15. newLocal,
  16. newLabel,
  17. newFunctionName,
  18. newImport,
  19. lookupLabel,
  20. lookupName,
  21. code,
  22. code2,
  23. nopEC,
  24. stmtEC,
  25. stmtsEC,
  26. getCgStmtsEC,
  27. getCgStmtsEC',
  28. forkLabelledCodeEC
  29. )
  30. where
  31. import CgMonad
  32. import CLabel
  33. import Cmm
  34. -- import BasicTypes
  35. import BlockId
  36. import FastString
  37. import Module
  38. import UniqFM
  39. import Unique
  40. -- | The environment contains variable definitions or blockids.
  41. data Named
  42. = Var CmmExpr -- ^ Holds CmmLit(CmmLabel ..) which gives the label type,
  43. -- eg, RtsLabel, ForeignLabel, CmmLabel etc.
  44. | Fun PackageId -- ^ A function name from this package
  45. | Label BlockId -- ^ A blockid of some code or data.
  46. -- | An environment of named things.
  47. type Env = UniqFM Named
  48. -- | Local declarations that are in scope during code generation.
  49. type Decls = [(FastString,Named)]
  50. -- | Does a computation in the FCode monad, with a current environment
  51. -- and a list of local declarations. Returns the resulting list of declarations.
  52. newtype ExtFCode a
  53. = EC { unEC :: Env -> Decls -> FCode (Decls, a) }
  54. type ExtCode = ExtFCode ()
  55. returnExtFC :: a -> ExtFCode a
  56. returnExtFC a = EC $ \_ s -> return (s, a)
  57. thenExtFC :: ExtFCode a -> (a -> ExtFCode b) -> ExtFCode b
  58. thenExtFC (EC m) k = EC $ \e s -> do (s',r) <- m e s; unEC (k r) e s'
  59. instance Monad ExtFCode where
  60. (>>=) = thenExtFC
  61. return = returnExtFC
  62. -- | Takes the variable decarations and imports from the monad
  63. -- and makes an environment, which is looped back into the computation.
  64. -- In this way, we can have embedded declarations that scope over the whole
  65. -- procedure, and imports that scope over the entire module.
  66. -- Discards the local declaration contained within decl'
  67. --
  68. loopDecls :: ExtFCode a -> ExtFCode a
  69. loopDecls (EC fcode) =
  70. EC $ \e globalDecls -> do
  71. (_, a) <- fixC (\ ~(decls, _) -> fcode (addListToUFM e (decls ++ globalDecls)) globalDecls)
  72. return (globalDecls, a)
  73. -- | Get the current environment from the monad.
  74. getEnv :: ExtFCode Env
  75. getEnv = EC $ \e s -> return (s, e)
  76. -- | Add a new variable to the list of local declarations.
  77. -- The CmmExpr says where the value is stored.
  78. addVarDecl :: FastString -> CmmExpr -> ExtCode
  79. addVarDecl var expr
  80. = EC $ \_ s -> return ((var, Var expr):s, ())
  81. -- | Add a new label to the list of local declarations.
  82. addLabel :: FastString -> BlockId -> ExtCode
  83. addLabel name block_id
  84. = EC $ \_ s -> return ((name, Label block_id):s, ())
  85. -- | Create a fresh local variable of a given type.
  86. newLocal
  87. :: CmmType -- ^ data type
  88. -> FastString -- ^ name of variable
  89. -> ExtFCode LocalReg -- ^ register holding the value
  90. newLocal ty name = do
  91. u <- code newUnique
  92. let reg = LocalReg u ty
  93. addVarDecl name (CmmReg (CmmLocal reg))
  94. return reg
  95. -- | Allocate a fresh label.
  96. newLabel :: FastString -> ExtFCode BlockId
  97. newLabel name = do
  98. u <- code newUnique
  99. addLabel name (BlockId u)
  100. return (BlockId u)
  101. -- | Add add a local function to the environment.
  102. newFunctionName
  103. :: FastString -- ^ name of the function
  104. -> PackageId -- ^ package of the current module
  105. -> ExtCode
  106. newFunctionName name pkg
  107. = EC $ \_ s -> return ((name, Fun pkg):s, ())
  108. -- | Add an imported foreign label to the list of local declarations.
  109. -- If this is done at the start of the module the declaration will scope
  110. -- over the whole module.
  111. newImport
  112. :: (FastString, CLabel)
  113. -> ExtFCode ()
  114. newImport (name, cmmLabel)
  115. = addVarDecl name (CmmLit (CmmLabel cmmLabel))
  116. -- | Lookup the BlockId bound to the label with this name.
  117. -- If one hasn't been bound yet, create a fresh one based on the
  118. -- Unique of the name.
  119. lookupLabel :: FastString -> ExtFCode BlockId
  120. lookupLabel name = do
  121. env <- getEnv
  122. return $
  123. case lookupUFM env name of
  124. Just (Label l) -> l
  125. _other -> BlockId (newTagUnique (getUnique name) 'L')
  126. -- | Lookup the location of a named variable.
  127. -- Unknown names are treated as if they had been 'import'ed from the runtime system.
  128. -- This saves us a lot of bother in the RTS sources, at the expense of
  129. -- deferring some errors to link time.
  130. lookupName :: FastString -> ExtFCode CmmExpr
  131. lookupName name = do
  132. env <- getEnv
  133. return $
  134. case lookupUFM env name of
  135. Just (Var e) -> e
  136. Just (Fun pkg) -> CmmLit (CmmLabel (mkCmmCodeLabel pkg name))
  137. _other -> CmmLit (CmmLabel (mkCmmCodeLabel rtsPackageId name))
  138. -- | Lift an FCode computation into the ExtFCode monad
  139. code :: FCode a -> ExtFCode a
  140. code fc = EC $ \_ s -> do
  141. r <- fc
  142. return (s, r)
  143. code2 :: (FCode (Decls,b) -> FCode ((Decls,b),c)) -> ExtFCode b -> ExtFCode c
  144. code2 f (EC ec)
  145. = EC $ \e s -> do
  146. ((s', _),c) <- f (ec e s)
  147. return (s',c)
  148. -- | Do nothing in the ExtFCode monad.
  149. nopEC :: ExtFCode ()
  150. nopEC = code nopC
  151. -- | Accumulate a CmmStmt into the monad state.
  152. stmtEC :: CmmStmt -> ExtFCode ()
  153. stmtEC stmt = code (stmtC stmt)
  154. -- | Accumulate some CmmStmts into the monad state.
  155. stmtsEC :: [CmmStmt] -> ExtFCode ()
  156. stmtsEC stmts = code (stmtsC stmts)
  157. -- | Get the generated statements out of the monad state.
  158. getCgStmtsEC :: ExtFCode a -> ExtFCode CgStmts
  159. getCgStmtsEC = code2 getCgStmts'
  160. -- | Get the generated statements, and the return value out of the monad state.
  161. getCgStmtsEC' :: ExtFCode a -> ExtFCode (a, CgStmts)
  162. getCgStmtsEC' = code2 (\m -> getCgStmts' m >>= f)
  163. where f ((decl, b), c) = return ((decl, b), (b, c))
  164. -- | Emit a chunk of code outside the instruction stream,
  165. -- and return its block id.
  166. forkLabelledCodeEC :: ExtFCode a -> ExtFCode BlockId
  167. forkLabelledCodeEC ec = do
  168. stmts <- getCgStmtsEC ec
  169. code (forkCgStmts stmts)