Splat LLVM Ir into its own file.
This commit is contained in:
parent
1637dcd495
commit
e7ef268c12
3 changed files with 97 additions and 92 deletions
|
|
@ -34,6 +34,7 @@ executable language
|
||||||
Compiler.Compiler
|
Compiler.Compiler
|
||||||
Compiler.StandardLLVMLibrary
|
Compiler.StandardLLVMLibrary
|
||||||
Compiler.TH
|
Compiler.TH
|
||||||
|
Compiler.LLVMIr
|
||||||
Interpreter
|
Interpreter
|
||||||
|
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,13 @@
|
||||||
{-# LANGUAGE LambdaCase #-}
|
|
||||||
module Compiler.Compiler where
|
module Compiler.Compiler where
|
||||||
|
|
||||||
import Compiler.StandardLLVMLibrary (standardLLVMLibrary)
|
import Compiler.StandardLLVMLibrary (standardLLVMLibrary)
|
||||||
import Control.Monad.State (State, execState, gets, modify)
|
import Control.Monad.State (State, execState, gets, modify)
|
||||||
import Data.List (intercalate)
|
|
||||||
import Data.Set as Set
|
import Data.Set as Set
|
||||||
import Grammar.Abs (Def (..), Exp (..), Ident (..),
|
import Grammar.Abs (Def (..), Exp (..), Ident (..)
|
||||||
Program (..), Type (..))
|
, Program (..), Type (..))
|
||||||
import Grammar.Print (printTree)
|
import Grammar.Print (printTree)
|
||||||
|
import Compiler.LLVMIr (LLVMIr(..), Value(..)
|
||||||
-- | A datatype which represents some basic LLVM types
|
, printLLVMIr, LLVMType(..))
|
||||||
data LLType = I1 | I8 | I32 | I64 | Ptr
|
|
||||||
| Ref LLType | Array Integer LLType | CustomType Ident
|
|
||||||
|
|
||||||
instance Show LLType where
|
|
||||||
show :: LLType -> String
|
|
||||||
show t = case t of
|
|
||||||
I1 -> "i1"
|
|
||||||
I8 -> "i8"
|
|
||||||
I32 -> "i32"
|
|
||||||
I64 -> "i64"
|
|
||||||
Ptr -> "ptr"
|
|
||||||
Ref ty -> show ty <> "*"
|
|
||||||
Array n ty -> concat ["[", show n, " x ", show ty, "]"]
|
|
||||||
CustomType (Ident ty) -> ty
|
|
||||||
|
|
||||||
type Params = [(LLType, Ident)]
|
|
||||||
type Args = [(LLType, Value)]
|
|
||||||
|
|
||||||
-- | Represents a LLVM "value", as in an integer, a register variable,
|
|
||||||
-- or a string contstant
|
|
||||||
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
|
|
||||||
|
|
||||||
-- | The record used as the code generator state
|
-- | The record used as the code generator state
|
||||||
data CodeGenerator = CodeGenerator
|
data CodeGenerator = CodeGenerator
|
||||||
|
|
@ -54,64 +25,6 @@ defaultCodeGenerator = CodeGenerator
|
||||||
, block = Set.empty
|
, block = Set.empty
|
||||||
, variableCount = 0 }
|
, variableCount = 0 }
|
||||||
|
|
||||||
-- | A datatype which represents different instructions in LLVM
|
|
||||||
data LLVMIr = Define LLType Ident Params
|
|
||||||
| DefineEnd
|
|
||||||
| Declare LLType Ident Params
|
|
||||||
| SetVariable Ident
|
|
||||||
| Add LLType Value Value
|
|
||||||
| Sub LLType Value Value
|
|
||||||
| Div LLType Value Value
|
|
||||||
| Mul LLType Value Value
|
|
||||||
| Srem LLType Value Value
|
|
||||||
| Call LLType Ident Args
|
|
||||||
| Alloca LLType
|
|
||||||
| Store LLType Ident LLType Ident
|
|
||||||
| Bitcast LLType Ident LLType
|
|
||||||
| Ret LLType Value
|
|
||||||
| Comment String
|
|
||||||
| UnsafeRaw String -- This should generally be avoided, and proper
|
|
||||||
-- instructions should be used in its place
|
|
||||||
deriving (Show)
|
|
||||||
|
|
||||||
-- | Converts a LLVM inststruction to a String, allowing for printing etc.
|
|
||||||
printLLVMIr :: LLVMIr -> String
|
|
||||||
printLLVMIr = \case
|
|
||||||
(Define t (Ident i) params) -> concat ["define ", show t, " @", i, "("
|
|
||||||
, intercalate "," (fmap (\(x,Ident y) -> unwords [show x, "%"<>y]) params)
|
|
||||||
,") {\n"]
|
|
||||||
DefineEnd -> "}\n"
|
|
||||||
(Declare _t (Ident _i) _params) -> undefined
|
|
||||||
(SetVariable (Ident i)) -> concat ["%", i, " = "]
|
|
||||||
(Add t v1 v2) -> concat ["add ", show t, " "
|
|
||||||
, show v1, ", ", show v2
|
|
||||||
, "\n"]
|
|
||||||
(Sub t v1 v2) -> concat ["sub ", show t, " "
|
|
||||||
, show v1, ", "
|
|
||||||
, show v2, "\n"]
|
|
||||||
(Div t v1 v2) -> concat ["sdiv ", show t, " "
|
|
||||||
, show v1, ", "
|
|
||||||
, show v2, "\n"]
|
|
||||||
(Mul t v1 v2) -> concat ["mul ", show t, " "
|
|
||||||
, show v1, ", "
|
|
||||||
, show v2, "\n"]
|
|
||||||
(Srem t v1 v2) -> concat ["srem ", show t, " "
|
|
||||||
, show v1, ", "
|
|
||||||
, show v2, "\n"]
|
|
||||||
(Call t (Ident i) arg) -> concat ["call ", show t, " @", i, "("
|
|
||||||
, intercalate ", " $ Prelude.map (\(x,y) -> show x <> " " <> show y) arg
|
|
||||||
, ")\n"]
|
|
||||||
(Alloca t) -> unwords ["alloca", show t, "\n"]
|
|
||||||
(Store t1 (Ident id1) t2 (Ident id2)) -> concat ["store ", show t1, " %"
|
|
||||||
, id1, ", ", show t2, " %"
|
|
||||||
, id2, "\n"]
|
|
||||||
(Bitcast t1 (Ident i) t2) -> concat ["bitcast ", show t1, " %"
|
|
||||||
, i, " to ", show t2, "\n"]
|
|
||||||
(Ret t v) -> concat ["ret ", show t
|
|
||||||
, " ", show v, "\n"]
|
|
||||||
(UnsafeRaw s) -> s
|
|
||||||
(Comment s) -> "; " <> s <> "\n"
|
|
||||||
|
|
||||||
-- | Adds a instruction to the CodeGenerator state
|
-- | Adds a instruction to the CodeGenerator state
|
||||||
emit :: LLVMIr -> CompilerState
|
emit :: LLVMIr -> CompilerState
|
||||||
emit l = modify (\t -> t {instructions = instructions t ++ [l]})
|
emit l = modify (\t -> t {instructions = instructions t ++ [l]})
|
||||||
|
|
@ -262,7 +175,7 @@ compile (Program prg) = do
|
||||||
|
|
||||||
-- | A pretty nasty function to flatten out function types,
|
-- | A pretty nasty function to flatten out function types,
|
||||||
-- as they are currently represented by a recursive data type.
|
-- as they are currently represented by a recursive data type.
|
||||||
flattenFuncType :: Type -> (LLType, [LLType])
|
flattenFuncType :: Type -> (LLVMType, [LLVMType])
|
||||||
flattenFuncType xs = do
|
flattenFuncType xs = do
|
||||||
let res = go xs
|
let res = go xs
|
||||||
(last res, init res)
|
(last res, init res)
|
||||||
|
|
|
||||||
91
src/Compiler/LLVMIr.hs
Normal file
91
src/Compiler/LLVMIr.hs
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
{-# LANGUAGE LambdaCase #-}
|
||||||
|
module Compiler.LLVMIr where
|
||||||
|
import Grammar.Abs (Ident (Ident))
|
||||||
|
import Data.List (intercalate)
|
||||||
|
|
||||||
|
-- | A datatype which represents some basic LLVM types
|
||||||
|
data LLVMType = I1 | I8 | I32 | I64 | Ptr
|
||||||
|
| Ref LLVMType | Array Integer LLVMType | CustomType Ident
|
||||||
|
|
||||||
|
instance Show LLVMType where
|
||||||
|
show :: LLVMType -> String
|
||||||
|
show t = case t of
|
||||||
|
I1 -> "i1"
|
||||||
|
I8 -> "i8"
|
||||||
|
I32 -> "i32"
|
||||||
|
I64 -> "i64"
|
||||||
|
Ptr -> "ptr"
|
||||||
|
Ref ty -> show ty <> "*"
|
||||||
|
Array n ty -> concat ["[", show n, " x ", show ty, "]"]
|
||||||
|
CustomType (Ident ty) -> ty
|
||||||
|
|
||||||
|
-- | Represents a LLVM "value", as in an integer, a register variable,
|
||||||
|
-- or a string contstant
|
||||||
|
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
|
||||||
|
|
||||||
|
type Params = [(LLVMType, Ident)]
|
||||||
|
type Args = [(LLVMType, Value)]
|
||||||
|
|
||||||
|
-- | A datatype which represents different instructions in LLVM
|
||||||
|
data LLVMIr = Define LLVMType Ident Params
|
||||||
|
| DefineEnd
|
||||||
|
| Declare LLVMType Ident Params
|
||||||
|
| SetVariable Ident
|
||||||
|
| Add LLVMType Value Value
|
||||||
|
| Sub LLVMType Value Value
|
||||||
|
| Div LLVMType Value Value
|
||||||
|
| Mul LLVMType Value Value
|
||||||
|
| Srem LLVMType Value Value
|
||||||
|
| Call LLVMType Ident Args
|
||||||
|
| Alloca LLVMType
|
||||||
|
| Store LLVMType Ident LLVMType Ident
|
||||||
|
| Bitcast LLVMType Ident LLVMType
|
||||||
|
| Ret LLVMType Value
|
||||||
|
| Comment String
|
||||||
|
| UnsafeRaw String -- This should generally be avoided, and proper
|
||||||
|
-- instructions should be used in its place
|
||||||
|
deriving (Show)
|
||||||
|
|
||||||
|
-- | Converts a LLVM inststruction to a String, allowing for printing etc.
|
||||||
|
printLLVMIr :: LLVMIr -> String
|
||||||
|
printLLVMIr = \case
|
||||||
|
(Define t (Ident i) params) -> concat ["define ", show t, " @", i, "("
|
||||||
|
, intercalate "," (fmap (\(x,Ident y) -> unwords [show x, "%"<>y]) params)
|
||||||
|
,") {\n"]
|
||||||
|
DefineEnd -> "}\n"
|
||||||
|
(Declare _t (Ident _i) _params) -> undefined
|
||||||
|
(SetVariable (Ident i)) -> concat ["%", i, " = "]
|
||||||
|
(Add t v1 v2) -> concat ["add ", show t, " "
|
||||||
|
, show v1, ", ", show v2
|
||||||
|
, "\n"]
|
||||||
|
(Sub t v1 v2) -> concat ["sub ", show t, " "
|
||||||
|
, show v1, ", "
|
||||||
|
, show v2, "\n"]
|
||||||
|
(Div t v1 v2) -> concat ["sdiv ", show t, " "
|
||||||
|
, show v1, ", "
|
||||||
|
, show v2, "\n"]
|
||||||
|
(Mul t v1 v2) -> concat ["mul ", show t, " "
|
||||||
|
, show v1, ", "
|
||||||
|
, show v2, "\n"]
|
||||||
|
(Srem t v1 v2) -> concat ["srem ", show t, " "
|
||||||
|
, show v1, ", "
|
||||||
|
, show v2, "\n"]
|
||||||
|
(Call t (Ident i) arg) -> concat ["call ", show t, " @", i, "("
|
||||||
|
, intercalate ", " $ Prelude.map (\(x,y) -> show x <> " " <> show y) arg
|
||||||
|
, ")\n"]
|
||||||
|
(Alloca t) -> unwords ["alloca", show t, "\n"]
|
||||||
|
(Store t1 (Ident id1) t2 (Ident id2)) -> concat ["store ", show t1, " %"
|
||||||
|
, id1, ", ", show t2, " %"
|
||||||
|
, id2, "\n"]
|
||||||
|
(Bitcast t1 (Ident i) t2) -> concat ["bitcast ", show t1, " %"
|
||||||
|
, i, " to ", show t2, "\n"]
|
||||||
|
(Ret t v) -> concat ["ret ", show t
|
||||||
|
, " ", show v, "\n"]
|
||||||
|
(UnsafeRaw s) -> s
|
||||||
|
(Comment s) -> "; " <> s <> "\n"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue