1+ {-# LANGUAGE OverloadedStrings #-}
2+ {-# LANGUAGE GeneralizedNewtypeDeriving #-}
3+
4+ module CodeGen where
5+
6+ import LLVM.Module
7+ import LLVM.Context
8+
9+ import qualified LLVM.AST as AST
10+ import qualified LLVM.AST.Constant as C
11+ import qualified LLVM.AST.Float as F
12+ import qualified LLVM.AST.FloatingPointPredicate as FP
13+
14+ import Data.Word
15+ import Data.String
16+ import Data.List
17+ import Data.Function
18+ import Data.Int
19+ import Control.Monad.Except
20+ import qualified Data.Map as Map
21+
22+ import Control.Monad.State
23+ import Control.Applicative
24+
25+ import qualified AST as ASTp
26+
27+ import LLVM.AST
28+ import qualified LLVM.AST as AST
29+ import LLVM.AST.Global
30+ import LLVM.Context
31+ import LLVM.Module
32+ import qualified LLVM.AST.Type as TypeQ
33+ import qualified LLVM.AST.Global as GLB
34+ import qualified LLVM.AST.Linkage as Linkage
35+
36+
37+ -- -- 1. Variable Declaration Done
38+ -- var = GLB.globalVariableDefaults { name = "Var1", GLB.type' = int }
39+
40+ -- | Utility Functions for Working on Module
41+ newtype LLVM a = LLVM (State AST. Module a )
42+ deriving (Functor , Applicative , Monad , MonadState AST.Module )
43+
44+ addDef :: Definition -> LLVM ()
45+ addDef def = do
46+ prev <- gets moduleDefinitions
47+ modify $ \ s -> s { moduleDefinitions = def: prev }
48+
49+
50+ -- | BackEnd
51+ -- From Parsed AST to LLVM Definitions
52+ getDef :: ASTp. Func -> Definition
53+ getDef (ASTp. Func fname farg fret fbody ) = GlobalDefinition $ functionDefaults {
54+ name = Name fname,
55+ parameters = ([Parameter (getType tp) (getName nm) [] | (tp, nm) <- farg], False ),
56+ returnType = (getType fret)
57+ -- basicBlocks = getBlk fbody
58+ }
59+
60+ getExtern :: ASTp. Declaration -> Definition
61+ getExtern (ASTp. ExternDecl fname fargs fret) =
62+ let (GlobalDefinition func) = (getDef (ASTp. Func fname fargs fret [] ))
63+ in (GlobalDefinition $ func {
64+ linkage = Linkage. External
65+ })
66+
67+
68+ getType :: ASTp. Type -> TypeQ. Type
69+ getType ASTp. IntC = IntegerType 32
70+
71+ getName :: ASTp. Name -> AST. Name
72+ getName = AST. Name
73+
74+ -- getBlk :: [ASTp.Expr] -> [GLB.BasicBlock]
75+ -- getBlk
76+
77+ type Names = Map. Map String Int
78+
79+
80+ -- Takes a name and check if present in names and then checks if the name already there or not.
81+ -- returns updated map and prev. name if any otherwise the name itself.
82+ -- Can be used to ask if this name is avaible and if so then use it otherwise it returns you
83+ -- an updated name that can be used.
84+ unikName :: String -> Names -> (String , Names )
85+ unikName name mapping = case Map. lookup name mapping of
86+ Nothing -> (name, Map. insert name 1 mapping)
87+ Just idx -> (name ++ (show idx) , Map. insert name (idx+ 1 ) mapping)
88+
89+ type SymbolTable = [(String , AST. Operand )]
90+
91+
92+
93+
94+ data ModuleState
95+ = ModuleState {
96+ crntBlk :: AST. Name ,
97+ funcs :: Map. Map AST. Name FuncState ,
98+ funcCount :: Int ,
99+ symTab :: SymbolTable ,
100+ count :: Word ,
101+ names :: Names
102+ } deriving (Show )
103+
104+ data FuncState
105+ = FuncState {
106+ idx :: Int ,
107+ insts :: [Named Instruction ],
108+ term :: Maybe (Named Terminator )
109+ } deriving (Show )
110+
111+
112+ newtype CodeGen a = CodeGen { runCodeGen :: State ModuleState a }
113+ deriving (Functor , Applicative , Monad , MonadState ModuleState )
114+
115+
116+ sortBlocks :: [(Name , FuncState )] -> [(Name , FuncState )]
117+ sortBlocks = sortBy (compare `on` (idx . snd ))
118+
119+ createBlocks :: ModuleState -> [BasicBlock ]
120+ createBlocks m = map makeBlock $ sortBlocks $ Map. toList (funcs m)
121+
122+ makeBlock :: (Name , FuncState ) -> BasicBlock
123+ makeBlock (l, (FuncState _ s t)) = BasicBlock l (reverse s) (maketerm t)
124+ where
125+ maketerm (Just x) = x
126+ maketerm Nothing = error $ " Block has no terminator: " ++ (show l)
127+
128+ entryBlockName :: String
129+ entryBlockName = " entry"
130+
131+ emptyBlock :: Int -> FuncState
132+ emptyBlock i = FuncState i [] Nothing
133+
134+ emptyCodegen :: ModuleState
135+ emptyCodegen = ModuleState (Name entryBlockName) Map. empty 1 [] 0 Map. empty
136+
137+ execCodegen :: CodeGen a -> ModuleState
138+ execCodegen m = execState (runCodeGen m) emptyCodegen
139+
140+
141+ -- int :: Type
142+ -- int = IntegerType 32
143+
144+ -- defAdd :: Definition
145+ -- defAdd = GlobalDefinition functionDefaults
146+ -- { name = Name "add"
147+ -- , parameters =
148+ -- ( [ Parameter int (Name "a") []
149+ -- , Parameter int (Name "b") [] ]
150+ -- , False )
151+ -- , returnType = int
152+ -- , basicBlocks = [body]
153+ -- }
154+ -- where
155+ -- body = BasicBlock
156+ -- (Name "entry")
157+ -- [ Name "a" :=
158+ -- Add False -- no signed wrap
159+ -- False -- no unsigned wrap
160+ -- (LocalReference int (Name "a"))
161+ -- (LocalReference int (Name "b"))
162+ -- []]
163+ -- (Do $ Ret (Just (LocalReference int (Name "a"))) [])
164+
165+ -- -- literalStmtCodegen :: AST.Module -> AST.Module
166+ -- -- literalStmtCodegen =
167+ -- -- declInt :: AST.Module -> AST.Module
168+ -- -- declInt obj =
169+
170+ -- -- mainDef :: Definition
171+ -- -- mainDef =
172+
173+ -- module_ :: AST.Module
174+ -- module_ = defaultModule
175+ -- { moduleName = "basic"
176+ -- , moduleDefinitions = [defAdd]
177+ -- }
178+
179+
180+
181+ -- toLLVM :: AST.Module -> IO AST.Module
182+ -- toLLVM mod = withContext $ \ctx -> do
183+ -- liftError $ withModuleFromAST ctx mod ultimate
184+ -- return mod
185+ -- where
186+ -- ultimate = \m -> do
187+ -- llstr <- moduleLLVMAssembly m
188+ -- putStrLn llstr
189+ -- return m
190+ -- -- BS.putStrLn llvm
191+
192+ -- liftError :: ExceptT String IO a -> IO a
193+ -- liftError = runExceptT >=> either fail return
194+
195+ -- exec :: IO AST.Module
196+ -- exec = toLLVM module_
197+
198+
199+
200+
201+
202+
203+
204+
205+
206+
207+
208+
209+
210+
211+
212+
213+
214+
215+
216+
217+
218+
219+
220+
221+
222+
223+
224+
225+ -- import Data.ByteString.Char8 as BS
226+
227+ -- module_ :: AST.Module
228+ -- module_ = AST.defaultModule {
229+ -- AST.moduleName = "Main-Module",
230+ -- AST.moduleDefinitions = []
231+ -- }
232+
233+ -- toFound = withModuleFromAST
234+ -- runner :: AST.Module -> IO ()
235+ -- runner mod = withContext $ \ctx -> do
236+ -- llvm <- withModuleFromAST ctx mod moduleLLVMAssembly
237+ -- BS.putStrLn llvm
238+
239+ -- toLLVM :: AST.Module -> IO ()
240+ -- toLLVM mod = withContext $ \ctx -> do
241+ -- llvm <- withModuleFromAST ctx mod moduleLLVMAssembly
242+ -- BS.putStrLn llvm
243+
244+ -- toLLVM :: AST.Module -> IO AST.Module
245+ -- toLLVM mod = withContext $ \ctx -> do
246+ -- liftError $ withModuleFromAST ctx mod ultimate
247+ -- return mod
248+ -- where
249+ -- ultimate = \m -> do
250+ -- llstr <- moduleLLVMAssembly m
251+ -- BS.putStrLn llstr
252+ -- return m
253+ -- -- BS.putStrLn llvm
254+
255+ -- liftError :: ExceptT String IO a -> IO a
256+ -- liftError = runExceptT >=> either fail return
0 commit comments