1 -- -----------------------------------------------------------------------------
2 -- | This is the top-level module in the LLVM code generator.
5 module LlvmCodeGen ( llvmCodeGen ) where
7 #include "HsVersions.h"
11 import LlvmCodeGen.Base
12 import LlvmCodeGen.CodeGen
13 import LlvmCodeGen.Data
14 import LlvmCodeGen.Ppr
18 import CgUtils ( fixStgRegisters )
26 import qualified Pretty as Prt
32 -- -----------------------------------------------------------------------------
33 -- | Top-level of the llvm codegen
35 llvmCodeGen :: DynFlags -> Handle -> UniqSupply -> [RawCmm] -> IO ()
36 llvmCodeGen dflags h us cmms
38 bufh <- newBufHandle h
40 Prt.bufLeftRender bufh $ pprLlvmHeader
42 env' <- cmmDataLlvmGens dflags bufh env cdata []
43 cmmProcLlvmGens dflags bufh us env' cmm 1 []
49 cmm = concat $ map (\(Cmm top) -> top) cmms
51 (cdata,env) = foldr split ([],initLlvmEnv) cmm
53 split (CmmData _ d' ) (d,e) = (d':d,e)
54 split (CmmProc i l _ _) (d,e) =
55 let lbl = strCLabel_llvm $ if not (null i)
56 then entryLblToInfoLbl l
58 env' = funInsert lbl llvmFunTy e
62 -- -----------------------------------------------------------------------------
63 -- | Do llvm code generation on all these cmms data sections.
65 cmmDataLlvmGens :: DynFlags -> BufHandle -> LlvmEnv -> [[CmmStatic]]
66 -> [LlvmUnresData] -> IO ( LlvmEnv )
68 cmmDataLlvmGens dflags h env [] lmdata
69 = let (env', lmdata') = resolveLlvmDatas env lmdata []
70 lmdoc = Prt.vcat $ map pprLlvmData lmdata'
72 dumpIfSet_dyn dflags Opt_D_dump_llvm "LLVM Code" $ docToSDoc lmdoc
73 Prt.bufLeftRender h lmdoc
76 cmmDataLlvmGens dflags h env (cmm:cmms) lmdata
77 = let lmdata'@(l, ty, _) = genLlvmData cmm
78 env' = funInsert (strCLabel_llvm l) ty env
79 in cmmDataLlvmGens dflags h env' cmms (lmdata ++ [lmdata'])
82 -- -----------------------------------------------------------------------------
83 -- | Do llvm code generation on all these cmms procs.
85 cmmProcLlvmGens :: DynFlags -> BufHandle -> UniqSupply -> LlvmEnv -> [RawCmmTop]
86 -> Int -- ^ count, used for generating unique subsections
87 -> [LlvmVar] -- ^ info tables that need to be marked as 'used'
90 cmmProcLlvmGens _ _ _ _ [] _ []
93 cmmProcLlvmGens _ h _ _ [] _ ivars
94 = let cast x = LMBitc (LMStaticPointer (pVarLift x)) i8Ptr
95 ty = (LMArray (length ivars) i8Ptr)
96 usedArray = LMStaticArray (map cast ivars) ty
97 lmUsed = (LMGlobalVar (fsLit "llvm.used") ty Appending
98 (Just $ fsLit "llvm.metadata") Nothing, Just usedArray)
100 Prt.bufLeftRender h $ pprLlvmData ([lmUsed], [])
102 cmmProcLlvmGens dflags h us env (cmm : cmms) count ivars
104 (us', env', llvm) <- cmmLlvmGen dflags us (clearVars env) cmm
106 let (docs, ivar) = mapAndUnzip (pprLlvmCmmTop env' count) llvm
107 Prt.bufLeftRender h $ Prt.vcat docs
109 cmmProcLlvmGens dflags h us' env' cmms (count + 2) (concat ivar ++ ivars)
112 -- | Complete llvm code generation phase for a single top-level chunk of Cmm.
113 cmmLlvmGen :: DynFlags -> UniqSupply -> LlvmEnv -> RawCmmTop
114 -> IO ( UniqSupply, LlvmEnv, [LlvmCmmTop] )
116 cmmLlvmGen dflags us env cmm
118 -- rewrite assignments to global regs
119 let fixed_cmm = fixStgRegisters cmm
121 dumpIfSet_dyn dflags Opt_D_dump_opt_cmm "Optimised Cmm"
122 (pprCmm $ Cmm [fixed_cmm])
124 -- generate llvm code from cmm
125 let ((env', llvmBC), usGen) = initUs us $ genLlvmCode env fixed_cmm
127 dumpIfSet_dyn dflags Opt_D_dump_llvm "LLVM Code"
128 (vcat $ map (docToSDoc . fst . pprLlvmCmmTop env' 0) llvmBC)
130 return (usGen, env', llvmBC)
133 -- -----------------------------------------------------------------------------
134 -- | Instruction selection
136 genLlvmCode :: LlvmEnv -> RawCmmTop
137 -> UniqSM (LlvmEnv, [LlvmCmmTop])
138 genLlvmCode env (CmmData _ _ ) = return (env, [])
139 genLlvmCode env (CmmProc _ _ _ (ListGraph [])) = return (env, [])
140 genLlvmCode env cp@(CmmProc _ _ _ _ ) = genLlvmProc env cp