/compiler/llvmGen/LlvmCodeGen/Base.hs

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