PageRenderTime 43ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/compiler/llvmGen/LlvmCodeGen/Base.hs

https://bitbucket.org/khibino/ghc-hack
Haskell | 242 lines | 125 code | 52 blank | 65 comment | 1 complexity | fa7dd1436ce9f4cda1b6131adb16c670 MD5 | raw file
Possible License(s): BSD-3-Clause, BSD-2-Clause, LGPL-3.0
  1. -- ----------------------------------------------------------------------------
  2. -- | Base LLVM Code Generation module
  3. --
  4. -- Contains functions useful through out the code generator.
  5. --
  6. module LlvmCodeGen.Base (
  7. LlvmCmmDecl, LlvmBasicBlock,
  8. LlvmUnresData, LlvmData, UnresLabel, UnresStatic,
  9. LlvmVersion, defaultLlvmVersion,
  10. LlvmEnv, initLlvmEnv, clearVars, varLookup, varInsert,
  11. funLookup, funInsert, getLlvmVer, setLlvmVer, getLlvmPlatform,
  12. ghcInternalFunctions,
  13. cmmToLlvmType, widthToLlvmFloat, widthToLlvmInt, llvmFunTy,
  14. llvmFunSig, llvmStdFunAttrs, llvmFunAlign, llvmInfAlign,
  15. llvmPtrBits, mkLlvmFunc, tysToParams,
  16. strCLabel_llvm, genCmmLabelRef, genStringLabelRef
  17. ) where
  18. #include "HsVersions.h"
  19. import Llvm
  20. import LlvmCodeGen.Regs
  21. import CLabel
  22. import CgUtils ( activeStgRegs )
  23. import Config
  24. import Constants
  25. import FastString
  26. import OldCmm
  27. import qualified Outputable as Outp
  28. import Platform
  29. import UniqFM
  30. import Unique
  31. -- ----------------------------------------------------------------------------
  32. -- * Some Data Types
  33. --
  34. type LlvmCmmDecl = GenCmmDecl [LlvmData] (Maybe CmmStatics) (ListGraph LlvmStatement)
  35. type LlvmBasicBlock = GenBasicBlock LlvmStatement
  36. -- | Unresolved code.
  37. -- Of the form: (data label, data type, unresolved data)
  38. type LlvmUnresData = (CLabel, Section, LlvmType, [UnresStatic])
  39. -- | Top level LLVM Data (globals and type aliases)
  40. type LlvmData = ([LMGlobal], [LlvmType])
  41. -- | An unresolved Label.
  42. --
  43. -- Labels are unresolved when we haven't yet determined if they are defined in
  44. -- the module we are currently compiling, or an external one.
  45. type UnresLabel = CmmLit
  46. type UnresStatic = Either UnresLabel LlvmStatic
  47. -- ----------------------------------------------------------------------------
  48. -- * Type translations
  49. --
  50. -- | Translate a basic CmmType to an LlvmType.
  51. cmmToLlvmType :: CmmType -> LlvmType
  52. cmmToLlvmType ty | isFloatType ty = widthToLlvmFloat $ typeWidth ty
  53. | otherwise = widthToLlvmInt $ typeWidth ty
  54. -- | Translate a Cmm Float Width to a LlvmType.
  55. widthToLlvmFloat :: Width -> LlvmType
  56. widthToLlvmFloat W32 = LMFloat
  57. widthToLlvmFloat W64 = LMDouble
  58. widthToLlvmFloat W80 = LMFloat80
  59. widthToLlvmFloat W128 = LMFloat128
  60. widthToLlvmFloat w = panic $ "widthToLlvmFloat: Bad float size: " ++ show w
  61. -- | Translate a Cmm Bit Width to a LlvmType.
  62. widthToLlvmInt :: Width -> LlvmType
  63. widthToLlvmInt w = LMInt $ widthInBits w
  64. -- | GHC Call Convention for LLVM
  65. llvmGhcCC :: LlvmCallConvention
  66. llvmGhcCC | cGhcUnregisterised == "NO" = CC_Ncc 10
  67. | otherwise = CC_Ccc
  68. -- | Llvm Function type for Cmm function
  69. llvmFunTy :: LlvmType
  70. llvmFunTy = LMFunction $ llvmFunSig' (fsLit "a") ExternallyVisible
  71. -- | Llvm Function signature
  72. llvmFunSig :: LlvmEnv -> CLabel -> LlvmLinkageType -> LlvmFunctionDecl
  73. llvmFunSig env lbl link = llvmFunSig' (strCLabel_llvm env lbl) link
  74. llvmFunSig' :: LMString -> LlvmLinkageType -> LlvmFunctionDecl
  75. llvmFunSig' lbl link
  76. = let toParams x | isPointer x = (x, [NoAlias, NoCapture])
  77. | otherwise = (x, [])
  78. in LlvmFunctionDecl lbl link llvmGhcCC LMVoid FixedArgs
  79. (map (toParams . getVarType) llvmFunArgs) llvmFunAlign
  80. -- | Create a Haskell function in LLVM.
  81. mkLlvmFunc :: LlvmEnv -> CLabel -> LlvmLinkageType -> LMSection -> LlvmBlocks
  82. -> LlvmFunction
  83. mkLlvmFunc env lbl link sec blks
  84. = let funDec = llvmFunSig env lbl link
  85. funArgs = map (fsLit . getPlainName) llvmFunArgs
  86. in LlvmFunction funDec funArgs llvmStdFunAttrs sec blks
  87. -- | Alignment to use for functions
  88. llvmFunAlign :: LMAlign
  89. llvmFunAlign = Just wORD_SIZE
  90. -- | Alignment to use for into tables
  91. llvmInfAlign :: LMAlign
  92. llvmInfAlign = Just wORD_SIZE
  93. -- | A Function's arguments
  94. llvmFunArgs :: [LlvmVar]
  95. llvmFunArgs = map lmGlobalRegArg activeStgRegs
  96. -- | Llvm standard fun attributes
  97. llvmStdFunAttrs :: [LlvmFuncAttr]
  98. llvmStdFunAttrs = [NoUnwind]
  99. -- | Convert a list of types to a list of function parameters
  100. -- (each with no parameter attributes)
  101. tysToParams :: [LlvmType] -> [LlvmParameter]
  102. tysToParams = map (\ty -> (ty, []))
  103. -- | Pointer width
  104. llvmPtrBits :: Int
  105. llvmPtrBits = widthInBits $ typeWidth gcWord
  106. -- ----------------------------------------------------------------------------
  107. -- * Llvm Version
  108. --
  109. -- | LLVM Version Number
  110. type LlvmVersion = Int
  111. -- | The LLVM Version we assume if we don't know
  112. defaultLlvmVersion :: LlvmVersion
  113. defaultLlvmVersion = 28
  114. -- ----------------------------------------------------------------------------
  115. -- * Environment Handling
  116. --
  117. -- two maps, one for functions and one for local vars.
  118. newtype LlvmEnv = LlvmEnv (LlvmEnvMap, LlvmEnvMap, LlvmVersion, Platform)
  119. type LlvmEnvMap = UniqFM LlvmType
  120. -- | Get initial Llvm environment.
  121. initLlvmEnv :: Platform -> LlvmEnv
  122. initLlvmEnv platform = LlvmEnv (initFuncs, emptyUFM, defaultLlvmVersion, platform)
  123. where initFuncs = listToUFM $ [ (n, LMFunction ty) | (n, ty) <- ghcInternalFunctions ]
  124. -- | Here we pre-initialise some functions that are used internally by GHC
  125. -- so as to make sure they have the most general type in the case that
  126. -- user code also uses these functions but with a different type than GHC
  127. -- internally. (Main offender is treating return type as 'void' instead of
  128. -- 'void *'. Fixes trac #5486.
  129. ghcInternalFunctions :: [(LMString, LlvmFunctionDecl)]
  130. ghcInternalFunctions =
  131. [ mk "memcpy" i8Ptr [i8Ptr, i8Ptr, llvmWord]
  132. , mk "memmove" i8Ptr [i8Ptr, i8Ptr, llvmWord]
  133. , mk "memset" i8Ptr [i8Ptr, llvmWord, llvmWord]
  134. , mk "newSpark" llvmWord [i8Ptr, i8Ptr]
  135. ]
  136. where
  137. mk n ret args =
  138. let n' = fsLit n
  139. in (n', LlvmFunctionDecl n' ExternallyVisible CC_Ccc ret
  140. FixedArgs (tysToParams args) Nothing)
  141. -- | Clear variables from the environment.
  142. clearVars :: LlvmEnv -> LlvmEnv
  143. clearVars (LlvmEnv (e1, _, n, p)) = {-# SCC "llvm_env_clear" #-}
  144. LlvmEnv (e1, emptyUFM, n, p)
  145. -- | Insert local variables into the environment.
  146. varInsert :: Uniquable key => key -> LlvmType -> LlvmEnv -> LlvmEnv
  147. varInsert s t (LlvmEnv (e1, e2, n, p)) = {-# SCC "llvm_env_vinsert" #-}
  148. LlvmEnv (e1, addToUFM e2 s t, n, p)
  149. -- | Insert functions into the environment.
  150. funInsert :: Uniquable key => key -> LlvmType -> LlvmEnv -> LlvmEnv
  151. funInsert s t (LlvmEnv (e1, e2, n, p)) = {-# SCC "llvm_env_finsert" #-}
  152. LlvmEnv (addToUFM e1 s t, e2, n, p)
  153. -- | Lookup local variables in the environment.
  154. varLookup :: Uniquable key => key -> LlvmEnv -> Maybe LlvmType
  155. varLookup s (LlvmEnv (_, e2, _, _)) = {-# SCC "llvm_env_vlookup" #-}
  156. lookupUFM e2 s
  157. -- | Lookup functions in the environment.
  158. funLookup :: Uniquable key => key -> LlvmEnv -> Maybe LlvmType
  159. funLookup s (LlvmEnv (e1, _, _, _)) = {-# SCC "llvm_env_flookup" #-}
  160. lookupUFM e1 s
  161. -- | Get the LLVM version we are generating code for
  162. getLlvmVer :: LlvmEnv -> LlvmVersion
  163. getLlvmVer (LlvmEnv (_, _, n, _)) = n
  164. -- | Set the LLVM version we are generating code for
  165. setLlvmVer :: LlvmVersion -> LlvmEnv -> LlvmEnv
  166. setLlvmVer n (LlvmEnv (e1, e2, _, p)) = LlvmEnv (e1, e2, n, p)
  167. -- | Get the platform we are generating code for
  168. getLlvmPlatform :: LlvmEnv -> Platform
  169. getLlvmPlatform (LlvmEnv (_, _, _, p)) = p
  170. -- ----------------------------------------------------------------------------
  171. -- * Label handling
  172. --
  173. -- | Pretty print a 'CLabel'.
  174. strCLabel_llvm :: LlvmEnv -> CLabel -> LMString
  175. strCLabel_llvm env l = {-# SCC "llvm_strCLabel" #-}
  176. (fsLit . show . llvmSDoc . pprCLabel (getLlvmPlatform env)) l
  177. -- | Create an external definition for a 'CLabel' defined in another module.
  178. genCmmLabelRef :: LlvmEnv -> CLabel -> LMGlobal
  179. genCmmLabelRef env = genStringLabelRef . strCLabel_llvm env
  180. -- | As above ('genCmmLabelRef') but taking a 'LMString', not 'CLabel'.
  181. genStringLabelRef :: LMString -> LMGlobal
  182. genStringLabelRef cl
  183. = let ty = LMPointer $ LMArray 0 llvmWord
  184. in (LMGlobalVar cl ty External Nothing Nothing False, Nothing)
  185. -- ----------------------------------------------------------------------------
  186. -- * Misc
  187. --
  188. -- | Error function
  189. panic :: String -> a
  190. panic s = Outp.panic $ "LlvmCodeGen.Base." ++ s