Interpreter 1.0 Compiler 1.0 JIT 0.0

This commit is contained in:
Dario48 2026-03-02 15:53:52 +01:00
commit ac4f235592
14 changed files with 674 additions and 0 deletions

46
IR/IR.hs Normal file
View file

@ -0,0 +1,46 @@
{-# LANGUAGE TemplateHaskell #-}
module IR (setup, main_start, index_inc, index_dec, val_inc, val_dec, point, comma, paren_opening, paren_close, main_end) where
import Data.FileEmbed (embedStringFile)
import Data.String (IsString)
setup :: (IsString a) => a
setup = $(embedStringFile "IR/setup.ll")
main_start :: String
main_start = "define void @main() {\n"
index_inc :: String
index_inc = "call void @index_inc()\n"
index_dec :: String
index_dec = "call void @index_dec()\n"
val_inc :: String
val_inc = "call void @val_inc()\n"
val_dec :: String
val_dec = "call void @val_dec()\n"
point :: String
point = "call void @point()\n"
comma :: String
comma = "call void @comma()\n"
paren :: String
paren = "call i1 @paren()\n"
paren_opening :: (Num a, Show a) => a -> String
paren_opening n = "br label %paren.start" ++ num ++ "\nparen.start" ++ num ++ ":\n%paren.cond" ++ num ++ " = " ++ paren ++ "\nbr i1 %paren.cond" ++ num ++ ", label %paren.body" ++ num ++ ", label %paren.end" ++ num ++ "\nparen.body" ++ num ++ ":\n"
where
num = show n
paren_close :: (Num a, Show a) => a -> String
paren_close n = "br label %paren.start" ++ num ++ "\nparen.end" ++ num ++ ":\n"
where
num = show n
main_end :: String
main_end = "ret void\n}\n"

127
IR/setup.ll Normal file
View file

@ -0,0 +1,127 @@
define i64 @syscall(i64 %call, i64 %rdi, i64 %rsi, i64 %rdx, i64 %r10, i64 %r8, i64 %r9) alwaysinline {
%rax = call i64 asm sideeffect inteldialect
"syscall",
"={rax},{rax},{rdi},{rsi},{rdx},{r10},{r8},{r9},~{rcx},~{r11},~{memory}"
(i64 %call, i64 %rdi, i64 %rsi, i64 %rdx, i64 %r10, i64 %r8, i64 %r9)
ret i64 %rax
}
define void @exit(i64 %exitcode) alwaysinline noreturn {
call i64 @syscall(i64 60, i64 %exitcode, i64 undef,i64 undef,i64 undef,i64 undef,i64 undef)
call void asm sideeffect "hlt", ""() noreturn
unreachable
}
define i8 @read() alwaysinline{
%buf = alloca i8
%ret = call i64 @syscall(i64 0, i64 0, ptr %buf, i64 1, i64 undef,i64 undef,i64 undef)
%ret.bool = trunc i64 %ret to i1
br i1 %ret.bool, label %normal, label %error
error:
call void @exit(i64 1)
ret i8 0
normal:
%char = load i8, ptr %buf
ret i8 %char
}
define i1 @write(i8 %char) alwaysinline {
%buf = alloca i8
store i8 %char, ptr %buf
%nwrite = call i64 @syscall(i64 1, i64 1, ptr %buf, i64 1, i64 undef,i64 undef,i64 undef)
%wrote = trunc i64 %nwrite to i1
ret i1 %wrote
}
define void @_start() naked {
; clear %rbp
call void asm sideeffect "", "{rbp}"(i64 0)
; read rsp
%rsp = call ptr asm "", "={rsp},{rsp}"(ptr undef)
call void @main()
call void @exit(i64 0)
ret void
}
@arr = global [30000 x i16] zeroinitializer
@index = global i16 0
define void @index_inc() alwaysinline {
%i = load i16, ptr @index
%i.i = add i16 %i, 1
%i.final = urem i16 %i.i, 30000
store i16 %i.final, ptr @index
ret void
}
define void @index_dec() alwaysinline {
%i = load i16, ptr @index
%i.i = sub i16 %i, 1
%i.final = urem i16 %i.i, 30000
store i16 %i.final, ptr @index
ret void
}
define void @val_inc() alwaysinline {
%index = load i16, ptr @index
%index.ext = sext i16 %index to i64
%val.ptr = getelementptr inbounds [30000 x i8], ptr @arr, i64 0, i64 %index.ext
%val = load i8, ptr %val.ptr
%val.final = add i8 %val, 1
store i8 %val.final, ptr %val.ptr
ret void
}
define void @val_dec() alwaysinline {
%index = load i16, ptr @index
%index.ext = sext i16 %index to i64
%val.ptr = getelementptr inbounds [30000 x i8], ptr @arr, i64 0, i64 %index.ext
%val = load i8, ptr %val.ptr
%val.final = sub i8 %val, 1
store i8 %val.final, ptr %val.ptr
ret void
}
define void @point() alwaysinline {
%index = load i16, ptr @index
%index.ext = sext i16 %index to i64
%char.ptr = getelementptr inbounds [30000 x i8], ptr @arr, i64 0, i64 %index.ext
%char = load i8, ptr %char.ptr
br label %loop
loop:
%wrote = call i1 @write(i8 %char)
%res = xor i1 %wrote, true
br i1 %res, label %loop, label %exit
exit:
ret void
}
define void @comma() alwaysinline {
%char = call i8 @read()
%index = load i16, ptr @index
%index.ext = sext i16 %index to i64
%char.dest = getelementptr inbounds [30000 x i8], ptr @arr, i64 0, i64 %index.ext
store i8 %char, ptr %char.dest
ret void
}
define i1 @paren() alwaysinline {
%index = load i16, ptr @index
%index.ext = sext i16 %index to i64
%val.ptr = getelementptr inbounds [30000 x i8], ptr @arr, i64 0, i64 %index.ext
%val = load i8, ptr %val.ptr
%eql = icmp ne i8 %val, 0
ret i1 %eql
}