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