1 {-# LANGUAGE CPP, TypeFamilies #-}
3 -- -----------------------------------------------------------------------------
4 -- | This is the top-level module in the LLVM code generator.
6 module LlvmCodeGen
( llvmCodeGen
, llvmFixupAsm
) where
8 #include
"HsVersions.h"
11 import LlvmCodeGen
.Base
12 import LlvmCodeGen
.CodeGen
13 import LlvmCodeGen
.Data
14 import LlvmCodeGen
.Ppr
15 import LlvmCodeGen
.Regs
19 import CgUtils
( fixStgRegisters
)
31 import SysTools
( figureLlvmVersion
)
32 import qualified Stream
34 import Control
.Monad
( when )
35 import Data
.Maybe ( fromMaybe, catMaybes )
38 -- -----------------------------------------------------------------------------
39 -- | Top-level of the LLVM Code generator
41 llvmCodeGen
:: DynFlags
-> Handle -> UniqSupply
42 -> Stream
.Stream
IO RawCmmGroup
()
44 llvmCodeGen dflags h us cmm_stream
45 = withTiming
(pure dflags
) (text
"LLVM CodeGen") (const ()) $ do
46 bufh
<- newBufHandle h
49 showPass dflags
"LLVM CodeGen"
51 -- get llvm version, cache for later use
52 ver
<- (fromMaybe supportedLlvmVersion
) `
fmap` figureLlvmVersion dflags
54 -- warn if unsupported
55 debugTraceMsg dflags
2
56 (text
"Using LLVM version:" <+> text
(show ver
))
57 let doWarn
= wopt Opt_WarnUnsupportedLlvmVersion dflags
58 when (ver
/= supportedLlvmVersion
&& doWarn
) $
59 putMsg dflags
(text
"You are using an unsupported version of LLVM!"
60 $+$ text
("Currently only " ++
61 llvmVersionStr supportedLlvmVersion
++
63 $+$ text
"We will try though...")
65 -- run code generation
66 runLlvm dflags ver bufh us
$
67 llvmCodeGen
' (liftStream cmm_stream
)
71 llvmCodeGen
' :: Stream
.Stream LlvmM RawCmmGroup
() -> LlvmM
()
72 llvmCodeGen
' cmm_stream
74 renderLlvm pprLlvmHeader
79 let llvmStream
= Stream
.mapM llvmGroupLlvmGens cmm_stream
80 _
<- Stream
.collect llvmStream
82 -- Declare aliases for forward references
83 renderLlvm
. pprLlvmData
=<< generateExternDecls
88 llvmGroupLlvmGens
:: RawCmmGroup
-> LlvmM
()
89 llvmGroupLlvmGens cmm
= do
91 -- Insert functions into map, collect data
92 let split (CmmData s d
' ) = return $ Just
(s
, d
')
93 split (CmmProc h l live g
) = do
95 let l
' = case mapLookup
(g_entry g
) h
of
97 Just
(Statics info_lbl _
) -> info_lbl
98 lml
<- strCLabel_llvm l
'
99 funInsert lml
=<< llvmFunTy live
101 cdata
<- fmap catMaybes $ mapM split cmm
103 {-# SCC "llvm_datas_gen" #-}
104 cmmDataLlvmGens cdata
105 {-# SCC "llvm_procs_gen" #-}
108 -- -----------------------------------------------------------------------------
109 -- | Do LLVM code generation on all these Cmms data sections.
111 cmmDataLlvmGens
:: [(Section
,CmmStatics
)] -> LlvmM
()
113 cmmDataLlvmGens statics
114 = do lmdatas
<- mapM genLlvmData statics
116 let (gss
, tss
) = unzip lmdatas
118 let regGlobal
(LMGlobal
(LMGlobalVar l ty _ _ _ _
) _
)
120 regGlobal _
= return ()
121 mapM_ regGlobal
(concat gss
)
122 gss
' <- mapM aliasify
$ concat gss
124 renderLlvm
$ pprLlvmData
(concat gss
', concat tss
)
126 -- | LLVM can't handle entry blocks which loop back to themselves (could be
127 -- seen as an LLVM bug) so we rearrange the code to keep the original entry
128 -- label which branches to a newly generated second label that branches back
129 -- to itself. See: Trac #11649
130 fixBottom
:: RawCmmDecl
-> LlvmM RawCmmDecl
131 fixBottom cp
@(CmmProc hdr entry_lbl live g
) =
132 maybe (pure cp
) fix_block
$ mapLookup
(g_entry g
) blk_map
134 blk_map
= toBlockMap g
136 fix_block
:: CmmBlock
-> LlvmM RawCmmDecl
138 |
(CmmEntry e_lbl tickscp
, middle
, CmmBranch b_lbl
) <- blockSplit blk
139 , isEmptyBlock middle
140 , e_lbl
== b_lbl
= do
141 new_lbl
<- mkBlockId
<$> getUniqueM
144 BlockCC
(CmmEntry e_lbl tickscp
) BNil
(CmmBranch new_lbl
)
146 BlockCC
(CmmEntry new_lbl tickscp
) BNil
(CmmBranch new_lbl
)
148 pure
. CmmProc hdr entry_lbl live
. ofBlockMap
(g_entry g
)
149 $ mapFromList
[(e_lbl
, fst_blk
), (new_lbl
, snd_blk
)]
151 fix_block _
= pure cp
153 fixBottom rcd
= pure rcd
155 -- | Complete LLVM code generation phase for a single top-level chunk of Cmm.
156 cmmLlvmGen
::RawCmmDecl
-> LlvmM
()
157 cmmLlvmGen cmm
@CmmProc
{} = do
159 -- rewrite assignments to global regs
160 dflags
<- getDynFlag
id
161 fixed_cmm
<- fixBottom
$
162 {-# SCC "llvm_fix_regs" #-}
163 fixStgRegisters dflags cmm
165 dumpIfSetLlvm Opt_D_dump_opt_cmm
"Optimised Cmm" (pprCmmGroup
[fixed_cmm
])
167 -- generate llvm code from cmm
168 llvmBC
<- withClearVars
$ genLlvmProc fixed_cmm
171 (docs
, ivars
) <- fmap unzip $ mapM pprLlvmCmmDecl llvmBC
173 -- Output, note down used variables
174 renderLlvm
(vcat docs
)
175 mapM_ markUsedVar
$ concat ivars
177 cmmLlvmGen _
= return ()
179 -- -----------------------------------------------------------------------------
180 -- | Generate meta data nodes
183 cmmMetaLlvmPrelude
:: LlvmM
()
184 cmmMetaLlvmPrelude
= do
185 metas
<- flip mapM stgTBAA
$ \(uniq
, name
, parent
) -> do
186 -- Generate / lookup meta data IDs
187 tbaaId
<- getMetaUniqueId
188 setUniqMeta uniq tbaaId
189 parentId
<- maybe (return Nothing
) getUniqMeta parent
191 return $ MetaUnnamed tbaaId
$ MetaStruct
195 Nothing
-> MetaVar
$ LMLitVar
$ LMNullLit i8Ptr
197 renderLlvm
$ ppLlvmMetas metas
199 -- -----------------------------------------------------------------------------
200 -- | Marks variables as used where necessary
203 cmmUsedLlvmGens
:: LlvmM
()
206 -- LLVM would discard variables that are internal and not obviously
207 -- used if we didn't provide these hints. This will generate a
208 -- definition of the form
210 -- @llvm.used = appending global [42 x i8*] [i8* bitcast <var> to i8*, ...]
212 -- Which is the LLVM way of protecting them against getting removed.
214 let cast x
= LMBitc
(LMStaticPointer
(pVarLift x
)) i8Ptr
215 ty
= (LMArray
(length ivars
) i8Ptr
)
216 usedArray
= LMStaticArray
(map cast ivars
) ty
217 sectName
= Just
$ fsLit
"llvm.metadata"
218 lmUsedVar
= LMGlobalVar
(fsLit
"llvm.used") ty Appending sectName Nothing Constant
219 lmUsed
= LMGlobal lmUsedVar
(Just usedArray
)
222 else renderLlvm
$ pprLlvmData
([lmUsed
], [])