Improved file structure
This commit is contained in:
parent
453b4d8956
commit
42a212a3f4
17
src/arch/arm64/Syscall.go
Normal file
17
src/arch/arm64/Syscall.go
Normal 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
22
src/arch/x64/Syscall.go
Normal 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
16
src/arch/x64/x64_test.go
Normal 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})
|
||||||
|
}
|
@ -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.
|
||||||
|
@ -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()
|
||||||
|
@ -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()
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
package keywords
|
|
||||||
|
|
||||||
// All defines the keywords used in the language.
|
|
||||||
var All = map[string]bool{
|
|
||||||
"return": true,
|
|
||||||
}
|
|
@ -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
10
src/os/linux/Syscall.go
Normal 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
|
||||||
|
)
|
@ -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 {
|
||||||
|
@ -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
6
src/token/Keywords.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package token
|
||||||
|
|
||||||
|
// Keywords defines the keywords used in the language.
|
||||||
|
var Keywords = map[string]bool{
|
||||||
|
"return": true,
|
||||||
|
}
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user