PageRenderTime 65ms CodeModel.GetById 35ms RepoModel.GetById 1ms app.codeStats 0ms

/compiler/codeGen/CgExtCode.hs

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