Made a simple code generator that outputs to LLVM IR

This commit is contained in:
Samuel Hammersberg 2023-02-03 16:59:36 +01:00
parent defe409d78
commit 819f4c9406
6 changed files with 123 additions and 154 deletions

View file

@ -1,34 +1,126 @@
module Compiler.Compiler where
import Control.Applicative (Applicative)
import Control.Monad.Except (Except, MonadError (throwError),
liftEither)
import Data.Either.Combinators (maybeToRight)
import Data.Map (Map)
import qualified Data.Map as Map
import Compiler.StandardLLVMLibrary (standardLLVMLibrary)
import Control.Applicative (Applicative)
import Control.Monad.Except (Except, MonadError (throwError),
liftEither)
import Control.Monad.State
import Data.Either.Combinators (maybeToRight)
import Data.List (intercalate)
import Data.Set (Set)
import Data.Set as Set
import Grammar.Abs
import Grammar.Print (printTree)
import Grammar.Par (myLexer,pProgram)
import System.Exit (exitFailure)
import Grammar.Par (myLexer, pProgram)
import System.Exit (exitFailure)
--import LLVM.AST
compileFile :: String -> IO ()
compileFile file = do
compileFile file = do
input <- readFile file
case pProgram (myLexer input) of
case pProgram (myLexer input) of
Left err -> do
putStrLn "SYNTAX ERROR"
putStrLn err
exitFailure
Right cor -> do
putStrLn $ printTree cor
compile cor
Right cor -> compile cor
-- data Compiler = Compiler
-- { data :: [LLVMIr] }
--
-- data LLVMIr = LLVMIr
data Type = I8 | I32 | I64 | Ptr | Ref Type | Array Integer Type
instance Show Type where
show :: Type -> String
show t = case t of
I8 -> "i8"
I32 -> "i32"
I64 -> "i64"
Ptr -> "ptr"
Ref ty -> show ty <> "*"
Array n ty -> concat ["[", show n, " x ", show ty, "]"]
type Params = [Type]
type Args = [(Type, Value)]
data Value = VInteger Integer | VIdent Ident | VConstant String
instance Show Value where
show :: Value -> String
show v = case v of
VInteger i -> show i
VIdent (Ident i) -> "%" <> i
VConstant s -> "c" <> show s
data CodeGenerator = CodeGenerator
{ instructions :: [LLVMIr]
, methods :: [Ident]
, blocks :: [Set Ident]
, variableCount :: Integer }
deriving Show
defaultCodeGenerator :: CodeGenerator
defaultCodeGenerator = CodeGenerator {instructions=[], methods=[], blocks=[], variableCount=0}
data LLVMIr = Define Type Ident Params
| DefineEnd
| Declare Type Ident Params
| Variable Ident
| Add Type Value Value
| Call Type Ident Args
| Alloca Type
| Store Type Ident Type Ident
| Bitcast Type Ident Type
| Ret Type Value
| UnsafeRaw String
deriving (Show)
printLLVMIr :: LLVMIr -> String
printLLVMIr (Define t (Ident i) params) = concat ["define ", show t, " @", i, "(", intercalate "," (fmap show params),") {\n"]
printLLVMIr DefineEnd = "}\n"
printLLVMIr (Declare t (Ident i) params) = undefined
printLLVMIr (Variable (Ident i)) = concat ["%", i, " = "]
printLLVMIr (Add t v1 v2) = concat ["add ", show t, " ", show v1, ", ", show v2, "\n"]
printLLVMIr (Call t (Ident i) arg) = concat ["call ", show t, " @", i, "("
, concatMap (\(x,y) -> show x <> " " <> show y) arg
, ")\n"]
printLLVMIr (Alloca t) = unwords ["alloca", show t, "\n"]
printLLVMIr (Store t1 (Ident id1) t2 (Ident id2)) = concat ["store ", show t1, " %", id1
, ", ", show t2, " %", id2, "\n"]
printLLVMIr (Bitcast t1 (Ident i) t2) = concat ["bitcast ", show t1, " %", i, " to ", show t2, "\n"]
printLLVMIr (Ret t v) = concat ["ret ", show t, " ", show v, "\n"]
printLLVMIr (UnsafeRaw s) = s
emit :: LLVMIr -> State CodeGenerator ()
emit l = modify (\t -> t {instructions = instructions t ++ [l]})
increaseVarCount :: State CodeGenerator ()
increaseVarCount = modify (\t -> t {variableCount = variableCount t + 1})
compile :: Program -> IO ()
compile p = print "hej"
compile (Program e) = do
--Asp
let s = defaultCodeGenerator {instructions = [
UnsafeRaw $ standardLLVMLibrary <> "\n",
--UnsafeRaw "declare i32 @puts(i8* nocapture) nounwind\n",
--UnsafeRaw "declare [21 x i8] @i64ToString(i64)\n",
Define I32 (Ident "main") []
]}
let fin = execState (go e) s
let ins = instructions fin
let var = variableCount fin
putStrLn $ concatMap printLLVMIr (ins ++
[ Variable (Ident "print_res")
, Call (Array 21 I8) (Ident "i64ToString") [(I64, VIdent $ Ident $ show var)]
, Variable (Ident "print_ptr"), Alloca (Array 21 I8)
, Store (Array 21 I8) (Ident "print_res") (Ref (Array 21 I8)) (Ident "print_ptr")
, Variable (Ident "printable"), Bitcast (Ref (Array 21 I8)) (Ident "print_ptr") (Ref I8)
, Call I32 (Ident "puts") [(Ref I8, VIdent (Ident "printable"))]
, Ret I32 (VInteger 0)
, DefineEnd
])
where
go :: Exp -> State CodeGenerator ()
go (EId id) = undefined
go (EInt int) = do
increaseVarCount
varCount <- gets variableCount
emit $ Variable $ Ident (show varCount)
emit $ Add I64 (VInteger int) (VInteger 0)
go (EApp e1 e2) = undefined
go (EAdd e1 e2) = undefined
go (EAbs id e) = undefined