Improved file structure

This commit is contained in:
Eduard Urbach 2024-06-05 15:51:05 +02:00
parent 453b4d8956
commit 42a212a3f4
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
18 changed files with 106 additions and 378 deletions

17
src/arch/arm64/Syscall.go Normal file
View File

@ -0,0 +1,17 @@
package register
import "git.akyoto.dev/cli/q/src/register"
const (
SyscallNumber = register.R8
SyscallReturn = register.R0
)
var SyscallArgs = []register.ID{
register.R0,
register.R1,
register.R2,
register.R3,
register.R4,
register.R5,
}

22
src/arch/x64/Syscall.go Normal file
View File

@ -0,0 +1,22 @@
package x64
import "git.akyoto.dev/cli/q/src/register"
const (
SyscallNumber = register.R0 // rax
SyscallReturn = register.R0 // rax
)
var SyscallArgs = []register.ID{
register.R7, // rdi
register.R6, // rsi
register.R2, // rdx
register.R10,
register.R8,
register.R9,
}
// Syscall is the primary way to communicate with the OS kernel.
func Syscall(code []byte) []byte {
return append(code, 0x0f, 0x05)
}

16
src/arch/x64/x64_test.go Normal file
View File

@ -0,0 +1,16 @@
package x64_test
import (
"testing"
"git.akyoto.dev/cli/q/src/arch/x64"
"git.akyoto.dev/go/assert"
)
func TestX64(t *testing.T) {
assert.DeepEqual(t, x64.Call([]byte{}, 1), []byte{0xe8, 0x01, 0x00, 0x00, 0x00})
assert.DeepEqual(t, x64.MoveRegNum32([]byte{}, 0, 1), []byte{0xb8, 0x01, 0x00, 0x00, 0x00})
assert.DeepEqual(t, x64.MoveRegNum32([]byte{}, 1, 1), []byte{0xb9, 0x01, 0x00, 0x00, 0x00})
assert.DeepEqual(t, x64.Return([]byte{}), []byte{0xc3})
assert.DeepEqual(t, x64.Syscall([]byte{}), []byte{0x0f, 0x05})
}

View File

@ -3,10 +3,10 @@ package asm
import ( import (
"encoding/binary" "encoding/binary"
"git.akyoto.dev/cli/q/src/arch/x64"
"git.akyoto.dev/cli/q/src/config" "git.akyoto.dev/cli/q/src/config"
"git.akyoto.dev/cli/q/src/log" "git.akyoto.dev/cli/q/src/log"
"git.akyoto.dev/cli/q/src/register" "git.akyoto.dev/cli/q/src/register"
"git.akyoto.dev/cli/q/src/x64"
) )
// Assembler contains a list of instructions. // Assembler contains a list of instructions.

View File

@ -3,9 +3,9 @@ package asm_test
import ( import (
"testing" "testing"
"git.akyoto.dev/cli/q/src/arch/x64"
"git.akyoto.dev/cli/q/src/asm" "git.akyoto.dev/cli/q/src/asm"
"git.akyoto.dev/cli/q/src/linux" "git.akyoto.dev/cli/q/src/os/linux"
"git.akyoto.dev/cli/q/src/register"
"git.akyoto.dev/go/assert" "git.akyoto.dev/go/assert"
) )
@ -13,14 +13,14 @@ func TestHello(t *testing.T) {
a := asm.New() a := asm.New()
hello := []byte("Hello\n") hello := []byte("Hello\n")
a.MoveRegisterNumber(register.Syscall0, linux.Write) a.MoveRegisterNumber(x64.SyscallNumber, linux.Write)
a.MoveRegisterNumber(register.Syscall1, 1) a.MoveRegisterNumber(x64.SyscallArgs[0], 1)
a.MoveRegisterData(register.Syscall2, hello) a.MoveRegisterData(x64.SyscallArgs[1], hello)
a.MoveRegisterNumber(register.Syscall3, uint64(len(hello))) a.MoveRegisterNumber(x64.SyscallArgs[2], uint64(len(hello)))
a.Syscall() a.Syscall()
a.MoveRegisterNumber(register.Syscall0, linux.Exit) a.MoveRegisterNumber(x64.SyscallNumber, linux.Exit)
a.MoveRegisterNumber(register.Syscall1, 0) a.MoveRegisterNumber(x64.SyscallArgs[0], 0)
a.Syscall() a.Syscall()
code, data := a.Finalize() code, data := a.Finalize()

View File

@ -1,9 +1,9 @@
package compiler package compiler
import ( import (
"git.akyoto.dev/cli/q/src/arch/x64"
"git.akyoto.dev/cli/q/src/asm" "git.akyoto.dev/cli/q/src/asm"
"git.akyoto.dev/cli/q/src/linux" "git.akyoto.dev/cli/q/src/os/linux"
"git.akyoto.dev/cli/q/src/register"
) )
// Finalize generates the final machine code. // Finalize generates the final machine code.
@ -14,8 +14,8 @@ func Finalize(functions map[string]*Function) ([]byte, []byte) {
a.Merge(&f.Assembler) a.Merge(&f.Assembler)
} }
a.MoveRegisterNumber(register.Syscall0, linux.Exit) a.MoveRegisterNumber(x64.SyscallNumber, linux.Exit)
a.MoveRegisterNumber(register.Syscall1, 0) a.MoveRegisterNumber(x64.SyscallArgs[0], 0)
a.Syscall() a.Syscall()
code, data := a.Finalize() code, data := a.Finalize()

View File

@ -1,9 +1,9 @@
package compiler package compiler
import ( import (
"git.akyoto.dev/cli/q/src/arch/x64"
"git.akyoto.dev/cli/q/src/asm" "git.akyoto.dev/cli/q/src/asm"
"git.akyoto.dev/cli/q/src/linux" "git.akyoto.dev/cli/q/src/os/linux"
"git.akyoto.dev/cli/q/src/register"
"git.akyoto.dev/cli/q/src/token" "git.akyoto.dev/cli/q/src/token"
) )
@ -20,10 +20,10 @@ func (f *Function) Compile() {
for i, t := range f.Body { for i, t := range f.Body {
if t.Kind == token.Identifier && t.String() == "print" { if t.Kind == token.Identifier && t.String() == "print" {
message := f.Body[i+2].Bytes message := f.Body[i+2].Bytes
f.Assembler.MoveRegisterNumber(register.Syscall0, linux.Write) f.Assembler.MoveRegisterNumber(x64.SyscallNumber, linux.Write)
f.Assembler.MoveRegisterNumber(register.Syscall1, 1) f.Assembler.MoveRegisterNumber(x64.SyscallArgs[0], 1)
f.Assembler.MoveRegisterData(register.Syscall2, message) f.Assembler.MoveRegisterData(x64.SyscallArgs[1], message)
f.Assembler.MoveRegisterNumber(register.Syscall3, uint64(len(message))) f.Assembler.MoveRegisterNumber(x64.SyscallArgs[2], uint64(len(message)))
f.Assembler.Syscall() f.Assembler.Syscall()
} }
} }

View File

@ -1,6 +0,0 @@
package keywords
// All defines the keywords used in the language.
var All = map[string]bool{
"return": true,
}

View File

@ -1,333 +0,0 @@
package linux
const (
Read = iota
Write
Open
Close
Stat
Fstat
Lstat
Poll
Lseek
Mmap
Mprotect
Munmap
Brk
Rt_sigaction
Rt_sigprocmask
Rt_sigreturn
Ioctl
Pread64
Pwrite64
Readv
Writev
Access
Pipe
Select
Sched_yield
Mremap
Msync
Mincore
Madvise
Shmget
Shmat
Shmctl
Dup
Dup2
Pause
Nanosleep
Getitimer
Alarm
Setitimer
Getpid
Sendfile
Socket
Connect
Accept
Sendto
Recvfrom
Sendmsg
Recvmsg
Shutdown
Bind
Listen
Getsockname
Getpeername
Socketpair
Setsockopt
Getsockopt
Clone
Fork
Vfork
Execve
Exit
Wait4
Kill
Uname
Semget
Semop
Semctl
Shmdt
Msgget
Msgsnd
Msgrcv
Msgctl
Fcntl
Flock
Fsync
Fdatasync
Truncate
Ftruncate
Getdents
Getcwd
Chdir
Fchdir
Rename
Mkdir
Rmdir
Creat
Link
Unlink
Symlink
Readlink
Chmod
Fchmod
Chown
Fchown
Lchown
Umask
Gettimeofday
Getrlimit
Getrusage
Sysinfo
Times
Ptrace
Getuid
Syslog
Getgid
Setuid
Setgid
Geteuid
Getegid
Setpgid
Getppid
Getpgrp
Setsid
Setreuid
Setregid
Getgroups
Setgroups
Setresuid
Getresuid
Setresgid
Getresgid
Getpgid
Setfsuid
Setfsgid
Getsid
Capget
Capset
Rt_sigpending
Rt_sigtimedwait
Rt_sigqueueinfo
Rt_sigsuspend
Sigaltstack
Utime
Mknod
Uselib
Personality
Ustat
Statfs
Fstatfs
Sysfs
Getpriority
Setpriority
Sched_setparam
Sched_getparam
Sched_setscheduler
Sched_getscheduler
Sched_get_priority_max
Sched_get_priority_min
Sched_rr_get_interval
Mlock
Munlock
Mlockall
Munlockall
Vhangup
Modify_ldt
Pivot_root
Sysctl
Prctl
Arch_prctl
Adjtimex
Setrlimit
Chroot
Sync
Acct
Settimeofday
Mount
Umount2
Swapon
Swapoff
Reboot
Sethostname
Setdomainname
Iopl
Ioperm
Create_module
Init_module
Delete_module
Get_kernel_syms
Query_module
Quotactl
Nfsservctl
Getpmsg
Putpmsg
Afs_syscall
Tuxcall
Security
Gettid
Readahead
Setxattr
Lsetxattr
Fsetxattr
Getxattr
Lgetxattr
Fgetxattr
Listxattr
Llistxattr
Flistxattr
Removexattr
Lremovexattr
Fremovexattr
Tkill
Time
Futex
Sched_setaffinity
Sched_getaffinity
Set_thread_area
Io_setup
Io_destroy
Io_getevents
Io_submit
Io_cancel
Get_thread_area
Lookup_dcookie
Epoll_create
Epoll_ctl_old
Epoll_wait_old
Remap_file_pages
Getdents64
Set_tid_address
Restart_syscall
Semtimedop
Fadvise64
Timer_create
Timer_settime
Timer_gettime
Timer_getoverrun
Timer_delete
Clock_settime
Clock_gettime
Clock_getres
Clock_nanosleep
Exit_group
Epoll_wait
Epoll_ctl
Tgkill
Utimes
Vserver
Mbind
Set_mempolicy
Get_mempolicy
Mq_open
Mq_unlink
Mq_timedsend
Mq_timedreceive
Mq_notify
Mq_getsetattr
Kexec_load
Waitid
Add_key
Request_key
Keyctl
Ioprio_set
Ioprio_get
Inotify_init
Inotify_add_watch
Inotify_rm_watch
Migrate_pages
Openat
Mkdirat
Mknodat
Fchownat
Futimesat
Newfstatat
Unlinkat
Renameat
Linkat
Symlinkat
Readlinkat
Fchmodat
Faccessat
Pselect6
Ppoll
Unshare
Set_robust_list
Get_robust_list
Splice
Tee
Sync_file_range
Vmsplice
Move_pages
Utimensat
Epoll_pwait
Signalfd
Timerfd_create
Eventfd
Fallocate
Timerfd_settime
Timerfd_gettime
Accept4
Signalfd4
Eventfd2
Epoll_create1
Dup3
Pipe2
Inotify_init1
Preadv
Pwritev
Rt_tgsigqueueinfo
Perf_event_open
Recvmmsg
Fanotify_init
Fanotify_mark
Prlimit64
Name_to_handle_at
Open_by_handle_at
Clock_adjtime
Syncfs
Sendmmsg
Setns
Getcpu
Process_vm_readv
Process_vm_writev
Kcmp
Finit_module
Sched_setattr
Sched_getattr
Renameat2
Seccomp
Getrandom
Memfd_create
Kexec_file_load
Bpf
Stub_execveat
Userfaultfd
Membarrier
Mlock2
Copy_file_range
Preadv2
Pwritev2
)

10
src/os/linux/Syscall.go Normal file
View File

@ -0,0 +1,10 @@
package linux
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/entry/syscalls/syscall_64.tbl
const (
Read = 0
Write = 1
Open = 2
Close = 3
Exit = 60
)

View File

@ -22,6 +22,21 @@ const (
R13 R13
R14 R14
R15 R15
R16
R17
R18
R19
R20
R21
R22
R23
R24
R25
R26
R27
R28
R29
R30
) )
func (r ID) String() string { func (r ID) String() string {

View File

@ -1,11 +0,0 @@
package register
const (
Syscall0 = R0
Syscall1 = R7
Syscall2 = R6
Syscall3 = R2
Syscall4 = R10
Syscall5 = R8
Syscall6 = R9
)

6
src/token/Keywords.go Normal file
View File

@ -0,0 +1,6 @@
package token
// Keywords defines the keywords used in the language.
var Keywords = map[string]bool{
"return": true,
}

View File

@ -1,7 +1,5 @@
package token package token
import "git.akyoto.dev/cli/q/src/keywords"
// Pre-allocate these byte buffers so we can re-use them // Pre-allocate these byte buffers so we can re-use them
// instead of allocating a new buffer every time. // instead of allocating a new buffer every time.
var ( var (
@ -87,7 +85,7 @@ func Tokenize(buffer []byte) List {
buffer[position:i], buffer[position:i],
} }
if keywords.All[string(token.Bytes)] { if Keywords[string(token.Bytes)] {
token.Kind = Keyword token.Kind = Keyword
} }

View File

@ -1,6 +0,0 @@
package x64
// Syscall is the primary way to communicate with the OS kernel.
func Syscall(code []byte) []byte {
return append(code, 0x0f, 0x05)
}