PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/compiler/codeGen/StgCmmExtCode.hs

https://github.com/crdueck/ghc
Haskell | 225 lines | 130 code | 56 blank | 39 comment | 0 complexity | 470f005d72760e2dc96823942fd885e9 MD5 | raw file
  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 StgCmmExtCode (
  10. CmmParse, unEC,
  11. Named(..), Env,
  12. loopDecls,
  13. getEnv,
  14. newLocal,
  15. newLabel,
  16. newBlockId,
  17. newFunctionName,
  18. newImport,
  19. lookupLabel,
  20. lookupName,
  21. code,
  22. emit, emitLabel, emitAssign, emitStore,
  23. getCode, getCodeR,
  24. emitOutOfLine,
  25. withUpdFrameOff, getUpdFrameOff
  26. )
  27. where
  28. import qualified StgCmmMonad as F
  29. import StgCmmMonad (FCode, newUnique)
  30. import Cmm
  31. import CLabel
  32. import MkGraph
  33. -- import BasicTypes
  34. import BlockId
  35. import DynFlags
  36. import FastString
  37. import Module
  38. import UniqFM
  39. import Unique
  40. -- | The environment contains variable definitions or blockids.
  41. data Named
  42. = VarN CmmExpr -- ^ Holds CmmLit(CmmLabel ..) which gives the label type,
  43. -- eg, RtsLabel, ForeignLabel, CmmLabel etc.
  44. | FunN PackageId -- ^ A function name from this package
  45. | LabelN 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 CmmParse a
  53. = EC { unEC :: Env -> Decls -> FCode (Decls, a) }
  54. type ExtCode = CmmParse ()
  55. returnExtFC :: a -> CmmParse a
  56. returnExtFC a = EC $ \_ s -> return (s, a)
  57. thenExtFC :: CmmParse a -> (a -> CmmParse b) -> CmmParse b
  58. thenExtFC (EC m) k = EC $ \e s -> do (s',r) <- m e s; unEC (k r) e s'
  59. instance Monad CmmParse where
  60. (>>=) = thenExtFC
  61. return = returnExtFC
  62. instance HasDynFlags CmmParse where
  63. getDynFlags = EC (\_ d -> do dflags <- getDynFlags
  64. return (d, dflags))
  65. -- | Takes the variable decarations and imports from the monad
  66. -- and makes an environment, which is looped back into the computation.
  67. -- In this way, we can have embedded declarations that scope over the whole
  68. -- procedure, and imports that scope over the entire module.
  69. -- Discards the local declaration contained within decl'
  70. --
  71. loopDecls :: CmmParse a -> CmmParse a
  72. loopDecls (EC fcode) =
  73. EC $ \e globalDecls -> do
  74. (_, a) <- F.fixC (\ ~(decls, _) -> fcode (addListToUFM e decls) globalDecls)
  75. return (globalDecls, a)
  76. -- | Get the current environment from the monad.
  77. getEnv :: CmmParse Env
  78. getEnv = EC $ \e s -> return (s, e)
  79. addDecl :: FastString -> Named -> ExtCode
  80. addDecl name named = EC $ \_ s -> return ((name, named) : s, ())
  81. -- | Add a new variable to the list of local declarations.
  82. -- The CmmExpr says where the value is stored.
  83. addVarDecl :: FastString -> CmmExpr -> ExtCode
  84. addVarDecl var expr = addDecl var (VarN expr)
  85. -- | Add a new label to the list of local declarations.
  86. addLabel :: FastString -> BlockId -> ExtCode
  87. addLabel name block_id = addDecl name (LabelN block_id)
  88. -- | Create a fresh local variable of a given type.
  89. newLocal
  90. :: CmmType -- ^ data type
  91. -> FastString -- ^ name of variable
  92. -> CmmParse LocalReg -- ^ register holding the value
  93. newLocal ty name = do
  94. u <- code newUnique
  95. let reg = LocalReg u ty
  96. addVarDecl name (CmmReg (CmmLocal reg))
  97. return reg
  98. -- | Allocate a fresh label.
  99. newLabel :: FastString -> CmmParse BlockId
  100. newLabel name = do
  101. u <- code newUnique
  102. addLabel name (mkBlockId u)
  103. return (mkBlockId u)
  104. newBlockId :: CmmParse BlockId
  105. newBlockId = code F.newLabelC
  106. -- | Add add a local function to the environment.
  107. newFunctionName
  108. :: FastString -- ^ name of the function
  109. -> PackageId -- ^ package of the current module
  110. -> ExtCode
  111. newFunctionName name pkg = addDecl name (FunN pkg)
  112. -- | Add an imported foreign label to the list of local declarations.
  113. -- If this is done at the start of the module the declaration will scope
  114. -- over the whole module.
  115. newImport
  116. :: (FastString, CLabel)
  117. -> CmmParse ()
  118. newImport (name, cmmLabel)
  119. = addVarDecl name (CmmLit (CmmLabel cmmLabel))
  120. -- | Lookup the BlockId bound to the label with this name.
  121. -- If one hasn't been bound yet, create a fresh one based on the
  122. -- Unique of the name.
  123. lookupLabel :: FastString -> CmmParse BlockId
  124. lookupLabel name = do
  125. env <- getEnv
  126. return $
  127. case lookupUFM env name of
  128. Just (LabelN l) -> l
  129. _other -> mkBlockId (newTagUnique (getUnique name) 'L')
  130. -- | Lookup the location of a named variable.
  131. -- Unknown names are treated as if they had been 'import'ed from the runtime system.
  132. -- This saves us a lot of bother in the RTS sources, at the expense of
  133. -- deferring some errors to link time.
  134. lookupName :: FastString -> CmmParse CmmExpr
  135. lookupName name = do
  136. env <- getEnv
  137. return $
  138. case lookupUFM env name of
  139. Just (VarN e) -> e
  140. Just (FunN pkg) -> CmmLit (CmmLabel (mkCmmCodeLabel pkg name))
  141. _other -> CmmLit (CmmLabel (mkCmmCodeLabel rtsPackageId name))
  142. -- | Lift an FCode computation into the CmmParse monad
  143. code :: FCode a -> CmmParse a
  144. code fc = EC $ \_ s -> do
  145. r <- fc
  146. return (s, r)
  147. emit :: CmmAGraph -> CmmParse ()
  148. emit = code . F.emit
  149. emitLabel :: BlockId -> CmmParse ()
  150. emitLabel = code. F.emitLabel
  151. emitAssign :: CmmReg -> CmmExpr -> CmmParse ()
  152. emitAssign l r = code (F.emitAssign l r)
  153. emitStore :: CmmExpr -> CmmExpr -> CmmParse ()
  154. emitStore l r = code (F.emitStore l r)
  155. getCode :: CmmParse a -> CmmParse CmmAGraph
  156. getCode (EC ec) = EC $ \e s -> do
  157. ((s',_), gr) <- F.getCodeR (ec e s)
  158. return (s', gr)
  159. getCodeR :: CmmParse a -> CmmParse (a, CmmAGraph)
  160. getCodeR (EC ec) = EC $ \e s -> do
  161. ((s', r), gr) <- F.getCodeR (ec e s)
  162. return (s', (r,gr))
  163. emitOutOfLine :: BlockId -> CmmAGraph -> CmmParse ()
  164. emitOutOfLine l g = code (F.emitOutOfLine l g)
  165. withUpdFrameOff :: UpdFrameOffset -> CmmParse () -> CmmParse ()
  166. withUpdFrameOff size inner
  167. = EC $ \e s -> F.withUpdFrameOff size $ (unEC inner) e s
  168. getUpdFrameOff :: CmmParse UpdFrameOffset
  169. getUpdFrameOff = code $ F.getUpdFrameOff