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

/compiler/llvmGen/LlvmCodeGen/Base.hs

http://github.com/ghc/ghc
Haskell | 551 lines | 299 code | 90 blank | 162 comment | 3 complexity | 626ef9bc08f97066c5bc5c659140bc95 MD5 | raw file
Possible License(s): MIT, BSD-3-Clause, GPL-3.0
  1. {-# LANGUAGE CPP #-}
  2. -- ----------------------------------------------------------------------------
  3. -- | Base LLVM Code Generation module
  4. --
  5. -- Contains functions useful through out the code generator.
  6. --
  7. module LlvmCodeGen.Base (
  8. LlvmCmmDecl, LlvmBasicBlock,
  9. LiveGlobalRegs,
  10. LlvmUnresData, LlvmData, UnresLabel, UnresStatic,
  11. LlvmVersion, supportedLlvmVersion, llvmVersionStr,
  12. LlvmM,
  13. runLlvm, liftStream, withClearVars, varLookup, varInsert,
  14. markStackReg, checkStackReg,
  15. funLookup, funInsert, getLlvmVer, getDynFlags, getDynFlag, getLlvmPlatform,
  16. dumpIfSetLlvm, renderLlvm, markUsedVar, getUsedVars,
  17. ghcInternalFunctions,
  18. getMetaUniqueId,
  19. setUniqMeta, getUniqMeta,
  20. cmmToLlvmType, widthToLlvmFloat, widthToLlvmInt, llvmFunTy,
  21. llvmFunSig, llvmFunArgs, llvmStdFunAttrs, llvmFunAlign, llvmInfAlign,
  22. llvmPtrBits, tysToParams, llvmFunSection,
  23. strCLabel_llvm, strDisplayName_llvm, strProcedureName_llvm,
  24. getGlobalPtr, generateExternDecls,
  25. aliasify,
  26. ) where
  27. #include "HsVersions.h"
  28. #include "ghcautoconf.h"
  29. import Llvm
  30. import LlvmCodeGen.Regs
  31. import CLabel
  32. import CodeGen.Platform ( activeStgRegs )
  33. import DynFlags
  34. import FastString
  35. import Cmm hiding ( succ )
  36. import Outputable as Outp
  37. import qualified Pretty as Prt
  38. import Platform
  39. import UniqFM
  40. import Unique
  41. import BufWrite ( BufHandle )
  42. import UniqSet
  43. import UniqSupply
  44. import ErrUtils
  45. import qualified Stream
  46. import Control.Monad (ap)
  47. -- ----------------------------------------------------------------------------
  48. -- * Some Data Types
  49. --
  50. type LlvmCmmDecl = GenCmmDecl [LlvmData] (Maybe CmmStatics) (ListGraph LlvmStatement)
  51. type LlvmBasicBlock = GenBasicBlock LlvmStatement
  52. -- | Global registers live on proc entry
  53. type LiveGlobalRegs = [GlobalReg]
  54. -- | Unresolved code.
  55. -- Of the form: (data label, data type, unresolved data)
  56. type LlvmUnresData = (CLabel, Section, LlvmType, [UnresStatic])
  57. -- | Top level LLVM Data (globals and type aliases)
  58. type LlvmData = ([LMGlobal], [LlvmType])
  59. -- | An unresolved Label.
  60. --
  61. -- Labels are unresolved when we haven't yet determined if they are defined in
  62. -- the module we are currently compiling, or an external one.
  63. type UnresLabel = CmmLit
  64. type UnresStatic = Either UnresLabel LlvmStatic
  65. -- ----------------------------------------------------------------------------
  66. -- * Type translations
  67. --
  68. -- | Translate a basic CmmType to an LlvmType.
  69. cmmToLlvmType :: CmmType -> LlvmType
  70. cmmToLlvmType ty | isVecType ty = LMVector (vecLength ty) (cmmToLlvmType (vecElemType ty))
  71. | isFloatType ty = widthToLlvmFloat $ typeWidth ty
  72. | otherwise = widthToLlvmInt $ typeWidth ty
  73. -- | Translate a Cmm Float Width to a LlvmType.
  74. widthToLlvmFloat :: Width -> LlvmType
  75. widthToLlvmFloat W32 = LMFloat
  76. widthToLlvmFloat W64 = LMDouble
  77. widthToLlvmFloat W80 = LMFloat80
  78. widthToLlvmFloat W128 = LMFloat128
  79. widthToLlvmFloat w = panic $ "widthToLlvmFloat: Bad float size: " ++ show w
  80. -- | Translate a Cmm Bit Width to a LlvmType.
  81. widthToLlvmInt :: Width -> LlvmType
  82. widthToLlvmInt w = LMInt $ widthInBits w
  83. -- | GHC Call Convention for LLVM
  84. llvmGhcCC :: DynFlags -> LlvmCallConvention
  85. llvmGhcCC dflags
  86. | platformUnregisterised (targetPlatform dflags) = CC_Ccc
  87. | otherwise = CC_Ghc
  88. -- | Llvm Function type for Cmm function
  89. llvmFunTy :: LiveGlobalRegs -> LlvmM LlvmType
  90. llvmFunTy live = return . LMFunction =<< llvmFunSig' live (fsLit "a") ExternallyVisible
  91. -- | Llvm Function signature
  92. llvmFunSig :: LiveGlobalRegs -> CLabel -> LlvmLinkageType -> LlvmM LlvmFunctionDecl
  93. llvmFunSig live lbl link = do
  94. lbl' <- strCLabel_llvm lbl
  95. llvmFunSig' live lbl' link
  96. llvmFunSig' :: LiveGlobalRegs -> LMString -> LlvmLinkageType -> LlvmM LlvmFunctionDecl
  97. llvmFunSig' live lbl link
  98. = do let toParams x | isPointer x = (x, [NoAlias, NoCapture])
  99. | otherwise = (x, [])
  100. dflags <- getDynFlags
  101. return $ LlvmFunctionDecl lbl link (llvmGhcCC dflags) LMVoid FixedArgs
  102. (map (toParams . getVarType) (llvmFunArgs dflags live))
  103. (llvmFunAlign dflags)
  104. -- | Alignment to use for functions
  105. llvmFunAlign :: DynFlags -> LMAlign
  106. llvmFunAlign dflags = Just (wORD_SIZE dflags)
  107. -- | Alignment to use for into tables
  108. llvmInfAlign :: DynFlags -> LMAlign
  109. llvmInfAlign dflags = Just (wORD_SIZE dflags)
  110. -- | Section to use for a function
  111. llvmFunSection :: DynFlags -> LMString -> LMSection
  112. llvmFunSection dflags lbl
  113. | gopt Opt_SplitSections dflags = Just (concatFS [fsLit ".text.", lbl])
  114. | otherwise = Nothing
  115. -- | A Function's arguments
  116. llvmFunArgs :: DynFlags -> LiveGlobalRegs -> [LlvmVar]
  117. llvmFunArgs dflags live =
  118. map (lmGlobalRegArg dflags) (filter isPassed (activeStgRegs platform))
  119. where platform = targetPlatform dflags
  120. isLive r = not (isSSE r) || r `elem` alwaysLive || r `elem` live
  121. isPassed r = not (isSSE r) || isLive r
  122. isSSE (FloatReg _) = True
  123. isSSE (DoubleReg _) = True
  124. isSSE (XmmReg _) = True
  125. isSSE (YmmReg _) = True
  126. isSSE (ZmmReg _) = True
  127. isSSE _ = False
  128. -- | Llvm standard fun attributes
  129. llvmStdFunAttrs :: [LlvmFuncAttr]
  130. llvmStdFunAttrs = [NoUnwind]
  131. -- | Convert a list of types to a list of function parameters
  132. -- (each with no parameter attributes)
  133. tysToParams :: [LlvmType] -> [LlvmParameter]
  134. tysToParams = map (\ty -> (ty, []))
  135. -- | Pointer width
  136. llvmPtrBits :: DynFlags -> Int
  137. llvmPtrBits dflags = widthInBits $ typeWidth $ gcWord dflags
  138. -- ----------------------------------------------------------------------------
  139. -- * Llvm Version
  140. --
  141. -- | LLVM Version Number
  142. type LlvmVersion = (Int, Int)
  143. -- | The LLVM Version that is currently supported.
  144. supportedLlvmVersion :: LlvmVersion
  145. supportedLlvmVersion = sUPPORTED_LLVM_VERSION
  146. llvmVersionStr :: LlvmVersion -> String
  147. llvmVersionStr (major, minor) = show major ++ "." ++ show minor
  148. -- ----------------------------------------------------------------------------
  149. -- * Environment Handling
  150. --
  151. data LlvmEnv = LlvmEnv
  152. { envVersion :: LlvmVersion -- ^ LLVM version
  153. , envDynFlags :: DynFlags -- ^ Dynamic flags
  154. , envOutput :: BufHandle -- ^ Output buffer
  155. , envUniq :: UniqSupply -- ^ Supply of unique values
  156. , envFreshMeta :: MetaId -- ^ Supply of fresh metadata IDs
  157. , envUniqMeta :: UniqFM MetaId -- ^ Global metadata nodes
  158. , envFunMap :: LlvmEnvMap -- ^ Global functions so far, with type
  159. , envAliases :: UniqSet LMString -- ^ Globals that we had to alias, see [Llvm Forward References]
  160. , envUsedVars :: [LlvmVar] -- ^ Pointers to be added to llvm.used (see @cmmUsedLlvmGens@)
  161. -- the following get cleared for every function (see @withClearVars@)
  162. , envVarMap :: LlvmEnvMap -- ^ Local variables so far, with type
  163. , envStackRegs :: [GlobalReg] -- ^ Non-constant registers (alloca'd in the function prelude)
  164. }
  165. type LlvmEnvMap = UniqFM LlvmType
  166. -- | The Llvm monad. Wraps @LlvmEnv@ state as well as the @IO@ monad
  167. newtype LlvmM a = LlvmM { runLlvmM :: LlvmEnv -> IO (a, LlvmEnv) }
  168. instance Functor LlvmM where
  169. fmap f m = LlvmM $ \env -> do (x, env') <- runLlvmM m env
  170. return (f x, env')
  171. instance Applicative LlvmM where
  172. pure x = LlvmM $ \env -> return (x, env)
  173. (<*>) = ap
  174. instance Monad LlvmM where
  175. m >>= f = LlvmM $ \env -> do (x, env') <- runLlvmM m env
  176. runLlvmM (f x) env'
  177. instance HasDynFlags LlvmM where
  178. getDynFlags = LlvmM $ \env -> return (envDynFlags env, env)
  179. instance MonadUnique LlvmM where
  180. getUniqueSupplyM = do
  181. us <- getEnv envUniq
  182. let (us1, us2) = splitUniqSupply us
  183. modifyEnv (\s -> s { envUniq = us2 })
  184. return us1
  185. getUniqueM = do
  186. us <- getEnv envUniq
  187. let (u,us') = takeUniqFromSupply us
  188. modifyEnv (\s -> s { envUniq = us' })
  189. return u
  190. -- | Lifting of IO actions. Not exported, as we want to encapsulate IO.
  191. liftIO :: IO a -> LlvmM a
  192. liftIO m = LlvmM $ \env -> do x <- m
  193. return (x, env)
  194. -- | Get initial Llvm environment.
  195. runLlvm :: DynFlags -> LlvmVersion -> BufHandle -> UniqSupply -> LlvmM () -> IO ()
  196. runLlvm dflags ver out us m = do
  197. _ <- runLlvmM m env
  198. return ()
  199. where env = LlvmEnv { envFunMap = emptyUFM
  200. , envVarMap = emptyUFM
  201. , envStackRegs = []
  202. , envUsedVars = []
  203. , envAliases = emptyUniqSet
  204. , envVersion = ver
  205. , envDynFlags = dflags
  206. , envOutput = out
  207. , envUniq = us
  208. , envFreshMeta = MetaId 0
  209. , envUniqMeta = emptyUFM
  210. }
  211. -- | Get environment (internal)
  212. getEnv :: (LlvmEnv -> a) -> LlvmM a
  213. getEnv f = LlvmM (\env -> return (f env, env))
  214. -- | Modify environment (internal)
  215. modifyEnv :: (LlvmEnv -> LlvmEnv) -> LlvmM ()
  216. modifyEnv f = LlvmM (\env -> return ((), f env))
  217. -- | Lift a stream into the LlvmM monad
  218. liftStream :: Stream.Stream IO a x -> Stream.Stream LlvmM a x
  219. liftStream s = Stream.Stream $ do
  220. r <- liftIO $ Stream.runStream s
  221. case r of
  222. Left b -> return (Left b)
  223. Right (a, r2) -> return (Right (a, liftStream r2))
  224. -- | Clear variables from the environment for a subcomputation
  225. withClearVars :: LlvmM a -> LlvmM a
  226. withClearVars m = LlvmM $ \env -> do
  227. (x, env') <- runLlvmM m env { envVarMap = emptyUFM, envStackRegs = [] }
  228. return (x, env' { envVarMap = emptyUFM, envStackRegs = [] })
  229. -- | Insert variables or functions into the environment.
  230. varInsert, funInsert :: Uniquable key => key -> LlvmType -> LlvmM ()
  231. varInsert s t = modifyEnv $ \env -> env { envVarMap = addToUFM (envVarMap env) s t }
  232. funInsert s t = modifyEnv $ \env -> env { envFunMap = addToUFM (envFunMap env) s t }
  233. -- | Lookup variables or functions in the environment.
  234. varLookup, funLookup :: Uniquable key => key -> LlvmM (Maybe LlvmType)
  235. varLookup s = getEnv (flip lookupUFM s . envVarMap)
  236. funLookup s = getEnv (flip lookupUFM s . envFunMap)
  237. -- | Set a register as allocated on the stack
  238. markStackReg :: GlobalReg -> LlvmM ()
  239. markStackReg r = modifyEnv $ \env -> env { envStackRegs = r : envStackRegs env }
  240. -- | Check whether a register is allocated on the stack
  241. checkStackReg :: GlobalReg -> LlvmM Bool
  242. checkStackReg r = getEnv ((elem r) . envStackRegs)
  243. -- | Allocate a new global unnamed metadata identifier
  244. getMetaUniqueId :: LlvmM MetaId
  245. getMetaUniqueId = LlvmM $ \env ->
  246. return (envFreshMeta env, env { envFreshMeta = succ $ envFreshMeta env })
  247. -- | Get the LLVM version we are generating code for
  248. getLlvmVer :: LlvmM LlvmVersion
  249. getLlvmVer = getEnv envVersion
  250. -- | Get the platform we are generating code for
  251. getDynFlag :: (DynFlags -> a) -> LlvmM a
  252. getDynFlag f = getEnv (f . envDynFlags)
  253. -- | Get the platform we are generating code for
  254. getLlvmPlatform :: LlvmM Platform
  255. getLlvmPlatform = getDynFlag targetPlatform
  256. -- | Dumps the document if the corresponding flag has been set by the user
  257. dumpIfSetLlvm :: DumpFlag -> String -> Outp.SDoc -> LlvmM ()
  258. dumpIfSetLlvm flag hdr doc = do
  259. dflags <- getDynFlags
  260. liftIO $ dumpIfSet_dyn dflags flag hdr doc
  261. -- | Prints the given contents to the output handle
  262. renderLlvm :: Outp.SDoc -> LlvmM ()
  263. renderLlvm sdoc = do
  264. -- Write to output
  265. dflags <- getDynFlags
  266. out <- getEnv envOutput
  267. let doc = Outp.withPprStyleDoc dflags (Outp.mkCodeStyle Outp.CStyle) sdoc
  268. liftIO $ Prt.bufLeftRender out doc
  269. -- Dump, if requested
  270. dumpIfSetLlvm Opt_D_dump_llvm "LLVM Code" sdoc
  271. return ()
  272. -- | Marks a variable as "used"
  273. markUsedVar :: LlvmVar -> LlvmM ()
  274. markUsedVar v = modifyEnv $ \env -> env { envUsedVars = v : envUsedVars env }
  275. -- | Return all variables marked as "used" so far
  276. getUsedVars :: LlvmM [LlvmVar]
  277. getUsedVars = getEnv envUsedVars
  278. -- | Saves that at some point we didn't know the type of the label and
  279. -- generated a reference to a type variable instead
  280. saveAlias :: LMString -> LlvmM ()
  281. saveAlias lbl = modifyEnv $ \env -> env { envAliases = addOneToUniqSet (envAliases env) lbl }
  282. -- | Sets metadata node for a given unique
  283. setUniqMeta :: Unique -> MetaId -> LlvmM ()
  284. setUniqMeta f m = modifyEnv $ \env -> env { envUniqMeta = addToUFM (envUniqMeta env) f m }
  285. -- | Gets metadata node for given unique
  286. getUniqMeta :: Unique -> LlvmM (Maybe MetaId)
  287. getUniqMeta s = getEnv (flip lookupUFM s . envUniqMeta)
  288. -- ----------------------------------------------------------------------------
  289. -- * Internal functions
  290. --
  291. -- | Here we pre-initialise some functions that are used internally by GHC
  292. -- so as to make sure they have the most general type in the case that
  293. -- user code also uses these functions but with a different type than GHC
  294. -- internally. (Main offender is treating return type as 'void' instead of
  295. -- 'void *'). Fixes trac #5486.
  296. ghcInternalFunctions :: LlvmM ()
  297. ghcInternalFunctions = do
  298. dflags <- getDynFlags
  299. mk "memcpy" i8Ptr [i8Ptr, i8Ptr, llvmWord dflags]
  300. mk "memmove" i8Ptr [i8Ptr, i8Ptr, llvmWord dflags]
  301. mk "memset" i8Ptr [i8Ptr, llvmWord dflags, llvmWord dflags]
  302. mk "newSpark" (llvmWord dflags) [i8Ptr, i8Ptr]
  303. where
  304. mk n ret args = do
  305. let n' = fsLit n `appendFS` fsLit "$def"
  306. decl = LlvmFunctionDecl n' ExternallyVisible CC_Ccc ret
  307. FixedArgs (tysToParams args) Nothing
  308. renderLlvm $ ppLlvmFunctionDecl decl
  309. funInsert n' (LMFunction decl)
  310. -- ----------------------------------------------------------------------------
  311. -- * Label handling
  312. --
  313. -- | Pretty print a 'CLabel'.
  314. strCLabel_llvm :: CLabel -> LlvmM LMString
  315. strCLabel_llvm lbl = do
  316. platform <- getLlvmPlatform
  317. dflags <- getDynFlags
  318. let sdoc = pprCLabel platform lbl
  319. str = Outp.renderWithStyle dflags sdoc (Outp.mkCodeStyle Outp.CStyle)
  320. return (fsLit str)
  321. strDisplayName_llvm :: CLabel -> LlvmM LMString
  322. strDisplayName_llvm lbl = do
  323. platform <- getLlvmPlatform
  324. dflags <- getDynFlags
  325. let sdoc = pprCLabel platform lbl
  326. depth = Outp.PartWay 1
  327. style = Outp.mkUserStyle Outp.reallyAlwaysQualify depth
  328. str = Outp.renderWithStyle dflags sdoc style
  329. return (fsLit (dropInfoSuffix str))
  330. dropInfoSuffix :: String -> String
  331. dropInfoSuffix = go
  332. where go "_info" = []
  333. go "_static_info" = []
  334. go "_con_info" = []
  335. go (x:xs) = x:go xs
  336. go [] = []
  337. strProcedureName_llvm :: CLabel -> LlvmM LMString
  338. strProcedureName_llvm lbl = do
  339. platform <- getLlvmPlatform
  340. dflags <- getDynFlags
  341. let sdoc = pprCLabel platform lbl
  342. depth = Outp.PartWay 1
  343. style = Outp.mkUserStyle Outp.neverQualify depth
  344. str = Outp.renderWithStyle dflags sdoc style
  345. return (fsLit str)
  346. -- ----------------------------------------------------------------------------
  347. -- * Global variables / forward references
  348. --
  349. -- | Create/get a pointer to a global value. Might return an alias if
  350. -- the value in question hasn't been defined yet. We especially make
  351. -- no guarantees on the type of the returned pointer.
  352. getGlobalPtr :: LMString -> LlvmM LlvmVar
  353. getGlobalPtr llvmLbl = do
  354. m_ty <- funLookup llvmLbl
  355. let mkGlbVar lbl ty = LMGlobalVar lbl (LMPointer ty) Private Nothing Nothing
  356. case m_ty of
  357. -- Directly reference if we have seen it already
  358. Just ty -> return $ mkGlbVar (llvmLbl `appendFS` fsLit "$def") ty Global
  359. -- Otherwise use a forward alias of it
  360. Nothing -> do
  361. saveAlias llvmLbl
  362. return $ mkGlbVar llvmLbl i8 Alias
  363. -- | Generate definitions for aliases forward-referenced by @getGlobalPtr@.
  364. --
  365. -- Must be called at a point where we are sure that no new global definitions
  366. -- will be generated anymore!
  367. generateExternDecls :: LlvmM ([LMGlobal], [LlvmType])
  368. generateExternDecls = do
  369. delayed <- fmap nonDetEltsUFM $ getEnv envAliases
  370. -- This is non-deterministic but we do not
  371. -- currently support deterministic code-generation.
  372. -- See Note [Unique Determinism and code generation]
  373. defss <- flip mapM delayed $ \lbl -> do
  374. m_ty <- funLookup lbl
  375. case m_ty of
  376. -- If we have a definition we've already emitted the proper aliases
  377. -- when the symbol itself was emitted by @aliasify@
  378. Just _ -> return []
  379. -- If we don't have a definition this is an external symbol and we
  380. -- need to emit a declaration
  381. Nothing ->
  382. let var = LMGlobalVar lbl i8Ptr External Nothing Nothing Global
  383. in return [LMGlobal var Nothing]
  384. -- Reset forward list
  385. modifyEnv $ \env -> env { envAliases = emptyUniqSet }
  386. return (concat defss, [])
  387. -- | Here we take a global variable definition, rename it with a
  388. -- @$def@ suffix, and generate the appropriate alias.
  389. aliasify :: LMGlobal -> LlvmM [LMGlobal]
  390. aliasify (LMGlobal var val) = do
  391. let i8Ptr = LMPointer (LMInt 8)
  392. LMGlobalVar lbl ty link sect align const = var
  393. defLbl = lbl `appendFS` fsLit "$def"
  394. defVar = LMGlobalVar defLbl ty Internal sect align const
  395. defPtrVar = LMGlobalVar defLbl (LMPointer ty) link Nothing Nothing const
  396. aliasVar = LMGlobalVar lbl (LMPointer i8Ptr) link Nothing Nothing Alias
  397. aliasVal = LMBitc (LMStaticPointer defPtrVar) i8Ptr
  398. -- we need to mark the $def symbols as used so LLVM doesn't forget which
  399. -- section they need to go in. This will vanish once we switch away from
  400. -- mangling sections for TNTC.
  401. markUsedVar defVar
  402. return [ LMGlobal defVar val
  403. , LMGlobal aliasVar (Just aliasVal)
  404. ]
  405. -- Note [Llvm Forward References]
  406. --
  407. -- The issue here is that LLVM insists on being strongly typed at
  408. -- every corner, so the first time we mention something, we have to
  409. -- settle what type we assign to it. That makes things awkward, as Cmm
  410. -- will often reference things before their definition, and we have no
  411. -- idea what (LLVM) type it is going to be before that point.
  412. --
  413. -- Our work-around is to define "aliases" of a standard type (i8 *) in
  414. -- these kind of situations, which we later tell LLVM to be either
  415. -- references to their actual local definitions (involving a cast) or
  416. -- an external reference. This obviously only works for pointers.
  417. --
  418. -- In particular when we encounter a reference to a symbol in a chunk of
  419. -- C-- there are three possible scenarios,
  420. --
  421. -- 1. We have already seen a definition for the referenced symbol. This
  422. -- means we already know its type.
  423. --
  424. -- 2. We have not yet seen a definition but we will find one later in this
  425. -- compilation unit. Since we want to be a good consumer of the
  426. -- C-- streamed to us from upstream, we don't know the type of the
  427. -- symbol at the time when we must emit the reference.
  428. --
  429. -- 3. We have not yet seen a definition nor will we find one in this
  430. -- compilation unit. In this case the reference refers to an
  431. -- external symbol for which we do not know the type.
  432. --
  433. -- Let's consider case (2) for a moment: say we see a reference to
  434. -- the symbol @fooBar@ for which we have not seen a definition. As we
  435. -- do not know the symbol's type, we assume it is of type @i8*@ and emit
  436. -- the appropriate casts in @getSymbolPtr@. Later on, when we
  437. -- encounter the definition of @fooBar@ we emit it but with a modified
  438. -- name, @fooBar$def@ (which we'll call the definition symbol), to
  439. -- since we have already had to assume that the symbol @fooBar@
  440. -- is of type @i8*@. We then emit @fooBar@ itself as an alias
  441. -- of @fooBar$def@ with appropriate casts. This all happens in
  442. -- @aliasify@.
  443. --
  444. -- Case (3) is quite similar to (2): References are emitted assuming
  445. -- the referenced symbol is of type @i8*@. When we arrive at the end of
  446. -- the compilation unit and realize that the symbol is external, we emit
  447. -- an LLVM @external global@ declaration for the symbol @fooBar@
  448. -- (handled in @generateExternDecls@). This takes advantage of the
  449. -- fact that the aliases produced by @aliasify@ for exported symbols
  450. -- have external linkage and can therefore be used as normal symbols.
  451. --
  452. -- Historical note: As of release 3.5 LLVM does not allow aliases to
  453. -- refer to declarations. This the reason why aliases are produced at the
  454. -- point of definition instead of the point of usage, as was previously
  455. -- done. See #9142 for details.
  456. --
  457. -- Finally, case (1) is trival. As we already have a definition for
  458. -- and therefore know the type of the referenced symbol, we can do
  459. -- away with casting the alias to the desired type in @getSymbolPtr@
  460. -- and instead just emit a reference to the definition symbol directly.
  461. -- This is the @Just@ case in @getSymbolPtr@.