Made a simple code generator that outputs to LLVM IR
This commit is contained in:
parent
defe409d78
commit
819f4c9406
6 changed files with 123 additions and 154 deletions
|
|
@ -12,6 +12,7 @@ build-type: Simple
|
||||||
|
|
||||||
extra-doc-files: CHANGELOG.md
|
extra-doc-files: CHANGELOG.md
|
||||||
|
|
||||||
|
|
||||||
extra-source-files:
|
extra-source-files:
|
||||||
Grammar.cf
|
Grammar.cf
|
||||||
|
|
||||||
|
|
@ -38,11 +39,12 @@ executable language
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
|
|
||||||
build-depends:
|
build-depends:
|
||||||
base ^>=4.17.0.0
|
base >=4.16.0.0
|
||||||
, mtl
|
, mtl
|
||||||
, containers
|
, containers
|
||||||
, either
|
, either
|
||||||
, array
|
, array
|
||||||
, template-haskell
|
, template-haskell
|
||||||
|
--, llvm-tf
|
||||||
|
|
||||||
default-language: GHC2021
|
default-language: GHC2021
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,18 @@
|
||||||
module Compiler.Compiler where
|
module Compiler.Compiler where
|
||||||
|
|
||||||
|
import Compiler.StandardLLVMLibrary (standardLLVMLibrary)
|
||||||
import Control.Applicative (Applicative)
|
import Control.Applicative (Applicative)
|
||||||
import Control.Monad.Except (Except, MonadError (throwError),
|
import Control.Monad.Except (Except, MonadError (throwError),
|
||||||
liftEither)
|
liftEither)
|
||||||
|
import Control.Monad.State
|
||||||
import Data.Either.Combinators (maybeToRight)
|
import Data.Either.Combinators (maybeToRight)
|
||||||
import Data.Map (Map)
|
import Data.List (intercalate)
|
||||||
import qualified Data.Map as Map
|
import Data.Set (Set)
|
||||||
|
import Data.Set as Set
|
||||||
import Grammar.Abs
|
import Grammar.Abs
|
||||||
import Grammar.Print (printTree)
|
|
||||||
import Grammar.Par (myLexer, pProgram)
|
import Grammar.Par (myLexer, pProgram)
|
||||||
import System.Exit (exitFailure)
|
import System.Exit (exitFailure)
|
||||||
|
--import LLVM.AST
|
||||||
|
|
||||||
compileFile :: String -> IO ()
|
compileFile :: String -> IO ()
|
||||||
compileFile file = do
|
compileFile file = do
|
||||||
|
|
@ -19,16 +22,105 @@ compileFile file = do
|
||||||
putStrLn "SYNTAX ERROR"
|
putStrLn "SYNTAX ERROR"
|
||||||
putStrLn err
|
putStrLn err
|
||||||
exitFailure
|
exitFailure
|
||||||
Right cor -> do
|
Right cor -> compile cor
|
||||||
putStrLn $ printTree cor
|
|
||||||
compile cor
|
|
||||||
|
|
||||||
-- data Compiler = Compiler
|
data Type = I8 | I32 | I64 | Ptr | Ref Type | Array Integer Type
|
||||||
-- { data :: [LLVMIr] }
|
instance Show Type where
|
||||||
--
|
show :: Type -> String
|
||||||
-- data LLVMIr = LLVMIr
|
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 :: 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
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
declare i64 @llvm.abs.i64(i64, i1 immarg)
|
declare i64 @llvm.abs.i64(i64, i1 immarg)
|
||||||
|
declare i32 @puts(i8* nocapture) nounwind
|
||||||
|
|
||||||
|
|
||||||
define [21 x i8] @i64ToString(i64 %val_org) {
|
define [21 x i8] @i64ToString(i64 %val_org) {
|
||||||
|
|
|
||||||
10
src/Main.hs
10
src/Main.hs
|
|
@ -1,6 +1,7 @@
|
||||||
{-# LANGUAGE LambdaCase #-}
|
{-# LANGUAGE LambdaCase #-}
|
||||||
module Main where
|
module Main where
|
||||||
|
|
||||||
|
import Compiler.Compiler (compile)
|
||||||
import Control.Monad.Except (runExcept)
|
import Control.Monad.Except (runExcept)
|
||||||
import Grammar.Par (myLexer, pProgram)
|
import Grammar.Par (myLexer, pProgram)
|
||||||
import Interpreter (interpret)
|
import Interpreter (interpret)
|
||||||
|
|
@ -17,14 +18,7 @@ main = getArgs >>= \case
|
||||||
putStrLn "SYNTAX ERROR"
|
putStrLn "SYNTAX ERROR"
|
||||||
putStrLn err
|
putStrLn err
|
||||||
exitFailure
|
exitFailure
|
||||||
Right prg -> case runExcept $ interpret prg of
|
Right prg -> compile prg
|
||||||
Left err -> do
|
|
||||||
putStrLn "INTERPRETER ERROR"
|
|
||||||
putStrLn err
|
|
||||||
exitFailure
|
|
||||||
Right i -> do
|
|
||||||
print i
|
|
||||||
exitSuccess
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,4 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
main = -12321
|
main = 451512
|
||||||
|
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
||||||
.text
|
|
||||||
.file "simple_goal.ll"
|
|
||||||
.globl i64ToString # -- Begin function i64ToString
|
|
||||||
.p2align 4, 0x90
|
|
||||||
.type i64ToString,@function
|
|
||||||
i64ToString: # @i64ToString
|
|
||||||
.cfi_startproc
|
|
||||||
# %bb.0:
|
|
||||||
pushq %rbp
|
|
||||||
.cfi_def_cfa_offset 16
|
|
||||||
pushq %r15
|
|
||||||
.cfi_def_cfa_offset 24
|
|
||||||
pushq %r14
|
|
||||||
.cfi_def_cfa_offset 32
|
|
||||||
pushq %r13
|
|
||||||
.cfi_def_cfa_offset 40
|
|
||||||
pushq %r12
|
|
||||||
.cfi_def_cfa_offset 48
|
|
||||||
pushq %rbx
|
|
||||||
.cfi_def_cfa_offset 56
|
|
||||||
subq $40, %rsp
|
|
||||||
.cfi_def_cfa_offset 96
|
|
||||||
.cfi_offset %rbx, -56
|
|
||||||
.cfi_offset %r12, -48
|
|
||||||
.cfi_offset %r13, -40
|
|
||||||
.cfi_offset %r14, -32
|
|
||||||
.cfi_offset %r15, -24
|
|
||||||
.cfi_offset %rbp, -16
|
|
||||||
movq %rsi, %r12
|
|
||||||
movq %rdi, %r14
|
|
||||||
movabsq $7810763617093968238, %rax # imm = 0x6C656820656E616E
|
|
||||||
movq %rax, 22(%rsp)
|
|
||||||
movabsq $7017206772232710740, %rax # imm = 0x616220616E656A54
|
|
||||||
movq %rax, 14(%rsp)
|
|
||||||
movw $10, 34(%rsp)
|
|
||||||
movl $1634955116, 30(%rsp) # imm = 0x61736F6C
|
|
||||||
movl $0, 36(%rsp)
|
|
||||||
leaq 14(%rsp), %rax
|
|
||||||
testq %rsi, %rsi
|
|
||||||
js .LBB0_1
|
|
||||||
# %bb.2: # %negative_check_false
|
|
||||||
movb $43, (%rax)
|
|
||||||
jmp .LBB0_3
|
|
||||||
.LBB0_1: # %negative_check_true
|
|
||||||
movb $45, (%rax)
|
|
||||||
.LBB0_3: # %negative_check_done
|
|
||||||
movabsq $7378697629483820647, %r13 # imm = 0x6666666666666667
|
|
||||||
leaq 14(%rsp), %r15
|
|
||||||
.p2align 4, 0x90
|
|
||||||
.LBB0_4: # %while_point
|
|
||||||
# =>This Inner Loop Header: Depth=1
|
|
||||||
movq %r12, %rax
|
|
||||||
imulq %r13
|
|
||||||
movq %rdx, %rbx
|
|
||||||
movq %rdx, %rbp
|
|
||||||
shrq $63, %rbp
|
|
||||||
sarq $2, %rbx
|
|
||||||
movq %r15, %rdi
|
|
||||||
callq puts@PLT
|
|
||||||
addq %rbp, %rbx
|
|
||||||
jne .LBB0_4
|
|
||||||
# %bb.5: # %while_break
|
|
||||||
movq 14(%rsp), %rax
|
|
||||||
movq 22(%rsp), %rcx
|
|
||||||
movl 30(%rsp), %edx
|
|
||||||
movzwl 34(%rsp), %esi
|
|
||||||
movw %si, 20(%r14)
|
|
||||||
movl %edx, 16(%r14)
|
|
||||||
movq %rcx, 8(%r14)
|
|
||||||
movq %rax, (%r14)
|
|
||||||
movq %r14, %rax
|
|
||||||
addq $40, %rsp
|
|
||||||
.cfi_def_cfa_offset 56
|
|
||||||
popq %rbx
|
|
||||||
.cfi_def_cfa_offset 48
|
|
||||||
popq %r12
|
|
||||||
.cfi_def_cfa_offset 40
|
|
||||||
popq %r13
|
|
||||||
.cfi_def_cfa_offset 32
|
|
||||||
popq %r14
|
|
||||||
.cfi_def_cfa_offset 24
|
|
||||||
popq %r15
|
|
||||||
.cfi_def_cfa_offset 16
|
|
||||||
popq %rbp
|
|
||||||
.cfi_def_cfa_offset 8
|
|
||||||
retq
|
|
||||||
.Lfunc_end0:
|
|
||||||
.size i64ToString, .Lfunc_end0-i64ToString
|
|
||||||
.cfi_endproc
|
|
||||||
# -- End function
|
|
||||||
.globl main # -- Begin function main
|
|
||||||
.p2align 4, 0x90
|
|
||||||
.type main,@function
|
|
||||||
main: # @main
|
|
||||||
.cfi_startproc
|
|
||||||
# %bb.0:
|
|
||||||
subq $56, %rsp
|
|
||||||
.cfi_def_cfa_offset 64
|
|
||||||
leaq 12(%rsp), %rdi
|
|
||||||
movl $200, %esi
|
|
||||||
callq i64ToString@PLT
|
|
||||||
movzwl 32(%rsp), %eax
|
|
||||||
movl 28(%rsp), %ecx
|
|
||||||
movq 12(%rsp), %rdx
|
|
||||||
movq 20(%rsp), %rsi
|
|
||||||
movq %rdx, 34(%rsp)
|
|
||||||
movq %rsi, 42(%rsp)
|
|
||||||
movl %ecx, 50(%rsp)
|
|
||||||
movw %ax, 54(%rsp)
|
|
||||||
leaq 34(%rsp), %rdi
|
|
||||||
callq puts@PLT
|
|
||||||
xorl %eax, %eax
|
|
||||||
addq $56, %rsp
|
|
||||||
.cfi_def_cfa_offset 8
|
|
||||||
retq
|
|
||||||
.Lfunc_end1:
|
|
||||||
.size main, .Lfunc_end1-main
|
|
||||||
.cfi_endproc
|
|
||||||
# -- End function
|
|
||||||
.section ".note.GNU-stack","",@progbits
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue