/compiler/llvmGen/LlvmCodeGen/Base.hs

https://github.com/mzero/ghc · Haskell · 212 lines · 104 code · 50 blank · 58 comment · 1 complexity · a34685f8835d7380b9f618c385a1db9b MD5 · raw file

  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. cmmToLlvmType, widthToLlvmFloat, widthToLlvmInt, llvmFunTy,
  13. llvmFunSig, llvmStdFunAttrs, llvmFunAlign, llvmInfAlign,
  14. llvmPtrBits, mkLlvmFunc, tysToParams,
  15. strCLabel_llvm, genCmmLabelRef, genStringLabelRef
  16. ) where
  17. #include "HsVersions.h"
  18. import Llvm
  19. import LlvmCodeGen.Regs
  20. import CLabel
  21. import CgUtils ( activeStgRegs )
  22. import Config
  23. import Constants
  24. import FastString
  25. import OldCmm
  26. import qualified Outputable as Outp
  27. import Platform
  28. import UniqFM
  29. import Unique
  30. -- ----------------------------------------------------------------------------
  31. -- * Some Data Types
  32. --
  33. type LlvmCmmDecl = GenCmmDecl [LlvmData] (Maybe CmmStatics) (ListGraph LlvmStatement)
  34. type LlvmBasicBlock = GenBasicBlock LlvmStatement
  35. -- | Unresolved code.
  36. -- Of the form: (data label, data type, unresolved data)
  37. type LlvmUnresData = (CLabel, Section, LlvmType, [UnresStatic])
  38. -- | Top level LLVM Data (globals and type aliases)
  39. type LlvmData = ([LMGlobal], [LlvmType])
  40. -- | An unresolved Label.
  41. --
  42. -- Labels are unresolved when we haven't yet determined if they are defined in
  43. -- the module we are currently compiling, or an external one.
  44. type UnresLabel = CmmLit
  45. type UnresStatic = Either UnresLabel LlvmStatic
  46. -- ----------------------------------------------------------------------------
  47. -- * Type translations
  48. --
  49. -- | Translate a basic CmmType to an LlvmType.
  50. cmmToLlvmType :: CmmType -> LlvmType
  51. cmmToLlvmType ty | isFloatType ty = widthToLlvmFloat $ typeWidth ty
  52. | otherwise = widthToLlvmInt $ typeWidth ty
  53. -- | Translate a Cmm Float Width to a LlvmType.
  54. widthToLlvmFloat :: Width -> LlvmType
  55. widthToLlvmFloat W32 = LMFloat
  56. widthToLlvmFloat W64 = LMDouble
  57. widthToLlvmFloat W80 = LMFloat80
  58. widthToLlvmFloat W128 = LMFloat128
  59. widthToLlvmFloat w = panic $ "widthToLlvmFloat: Bad float size: " ++ show w
  60. -- | Translate a Cmm Bit Width to a LlvmType.
  61. widthToLlvmInt :: Width -> LlvmType
  62. widthToLlvmInt w = LMInt $ widthInBits w
  63. -- | GHC Call Convention for LLVM
  64. llvmGhcCC :: LlvmCallConvention
  65. llvmGhcCC | cGhcUnregisterised == "NO" = CC_Ncc 10
  66. | otherwise = CC_Ccc
  67. -- | Llvm Function type for Cmm function
  68. llvmFunTy :: LlvmType
  69. llvmFunTy = LMFunction $ llvmFunSig' (fsLit "a") ExternallyVisible
  70. -- | Llvm Function signature
  71. llvmFunSig :: LlvmEnv -> CLabel -> LlvmLinkageType -> LlvmFunctionDecl
  72. llvmFunSig env lbl link = llvmFunSig' (strCLabel_llvm env lbl) link
  73. llvmFunSig' :: LMString -> LlvmLinkageType -> LlvmFunctionDecl
  74. llvmFunSig' lbl link
  75. = let toParams x | isPointer x = (x, [NoAlias, NoCapture])
  76. | otherwise = (x, [])
  77. in LlvmFunctionDecl lbl link llvmGhcCC LMVoid FixedArgs
  78. (map (toParams . getVarType) llvmFunArgs) llvmFunAlign
  79. -- | Create a Haskell function in LLVM.
  80. mkLlvmFunc :: LlvmEnv -> CLabel -> LlvmLinkageType -> LMSection -> LlvmBlocks
  81. -> LlvmFunction
  82. mkLlvmFunc env lbl link sec blks
  83. = let funDec = llvmFunSig env lbl link
  84. funArgs = map (fsLit . getPlainName) llvmFunArgs
  85. in LlvmFunction funDec funArgs llvmStdFunAttrs sec blks
  86. -- | Alignment to use for functions
  87. llvmFunAlign :: LMAlign
  88. llvmFunAlign = Just wORD_SIZE
  89. -- | Alignment to use for into tables
  90. llvmInfAlign :: LMAlign
  91. llvmInfAlign = Just wORD_SIZE
  92. -- | A Function's arguments
  93. llvmFunArgs :: [LlvmVar]
  94. llvmFunArgs = map lmGlobalRegArg activeStgRegs
  95. -- | Llvm standard fun attributes
  96. llvmStdFunAttrs :: [LlvmFuncAttr]
  97. llvmStdFunAttrs = [NoUnwind]
  98. -- | Convert a list of types to a list of function parameters
  99. -- (each with no parameter attributes)
  100. tysToParams :: [LlvmType] -> [LlvmParameter]
  101. tysToParams = map (\ty -> (ty, []))
  102. -- | Pointer width
  103. llvmPtrBits :: Int
  104. llvmPtrBits = widthInBits $ typeWidth gcWord
  105. -- ----------------------------------------------------------------------------
  106. -- * Llvm Version
  107. --
  108. -- | LLVM Version Number
  109. type LlvmVersion = Int
  110. -- | The LLVM Version we assume if we don't know
  111. defaultLlvmVersion :: LlvmVersion
  112. defaultLlvmVersion = 28
  113. -- ----------------------------------------------------------------------------
  114. -- * Environment Handling
  115. --
  116. -- two maps, one for functions and one for local vars.
  117. newtype LlvmEnv = LlvmEnv (LlvmEnvMap, LlvmEnvMap, LlvmVersion, Platform)
  118. type LlvmEnvMap = UniqFM LlvmType
  119. -- | Get initial Llvm environment.
  120. initLlvmEnv :: Platform -> LlvmEnv
  121. initLlvmEnv platform = LlvmEnv (emptyUFM, emptyUFM, defaultLlvmVersion, platform)
  122. -- | Clear variables from the environment.
  123. clearVars :: LlvmEnv -> LlvmEnv
  124. clearVars (LlvmEnv (e1, _, n, p)) = LlvmEnv (e1, emptyUFM, n, p)
  125. -- | Insert functions into the environment.
  126. varInsert, funInsert :: Uniquable key => key -> LlvmType -> LlvmEnv -> LlvmEnv
  127. varInsert s t (LlvmEnv (e1, e2, n, p)) = LlvmEnv (e1, addToUFM e2 s t, n, p)
  128. funInsert s t (LlvmEnv (e1, e2, n, p)) = LlvmEnv (addToUFM e1 s t, e2, n, p)
  129. -- | Lookup functions in the environment.
  130. varLookup, funLookup :: Uniquable key => key -> LlvmEnv -> Maybe LlvmType
  131. varLookup s (LlvmEnv (_, e2, _, _)) = lookupUFM e2 s
  132. funLookup s (LlvmEnv (e1, _, _, _)) = lookupUFM e1 s
  133. -- | Get the LLVM version we are generating code for
  134. getLlvmVer :: LlvmEnv -> LlvmVersion
  135. getLlvmVer (LlvmEnv (_, _, n, _)) = n
  136. -- | Set the LLVM version we are generating code for
  137. setLlvmVer :: LlvmVersion -> LlvmEnv -> LlvmEnv
  138. setLlvmVer n (LlvmEnv (e1, e2, _, p)) = LlvmEnv (e1, e2, n, p)
  139. -- | Get the platform we are generating code for
  140. getLlvmPlatform :: LlvmEnv -> Platform
  141. getLlvmPlatform (LlvmEnv (_, _, _, p)) = p
  142. -- ----------------------------------------------------------------------------
  143. -- * Label handling
  144. --
  145. -- | Pretty print a 'CLabel'.
  146. strCLabel_llvm :: LlvmEnv -> CLabel -> LMString
  147. strCLabel_llvm env l
  148. = (fsLit . show . llvmSDoc . pprCLabel (getLlvmPlatform env)) l
  149. -- | Create an external definition for a 'CLabel' defined in another module.
  150. genCmmLabelRef :: LlvmEnv -> CLabel -> LMGlobal
  151. genCmmLabelRef env = genStringLabelRef . strCLabel_llvm env
  152. -- | As above ('genCmmLabelRef') but taking a 'LMString', not 'CLabel'.
  153. genStringLabelRef :: LMString -> LMGlobal
  154. genStringLabelRef cl
  155. = let ty = LMPointer $ LMArray 0 llvmWord
  156. in (LMGlobalVar cl ty External Nothing Nothing False, Nothing)
  157. -- ----------------------------------------------------------------------------
  158. -- * Misc
  159. --
  160. -- | Error function
  161. panic :: String -> a
  162. panic s = Outp.panic $ "LlvmCodeGen.Base." ++ s