...
This commit is contained in:
3
build.sh
3
build.sh
@@ -8,8 +8,9 @@ dotnet build src/lang/Nub.Lang.CLI
|
|||||||
nub example > out/out.qbe
|
nub example > out/out.qbe
|
||||||
|
|
||||||
nasm -g -felf64 src/runtime/runtime.asm -o out/runtime.o
|
nasm -g -felf64 src/runtime/runtime.asm -o out/runtime.o
|
||||||
|
nasm -g -felf64 src/runtime/core/syscall.asm -o out/syscall.o
|
||||||
|
|
||||||
qbe out/out.qbe > out/out.s
|
qbe out/out.qbe > out/out.s
|
||||||
|
|
||||||
gcc -c -g out/out.s -o out/out.o
|
gcc -c -g out/out.s -o out/out.o
|
||||||
gcc -nostartfiles -o out/program out/runtime.o out/out.o
|
gcc -nostartfiles -o out/program out/runtime.o out/syscall.o out/out.o
|
||||||
556
convert.py
Normal file
556
convert.py
Normal file
@@ -0,0 +1,556 @@
|
|||||||
|
import csv
|
||||||
|
import re
|
||||||
|
from typing import List, Dict, Tuple
|
||||||
|
|
||||||
|
def parse_type_and_name(param_str: str) -> Tuple[str, str]:
|
||||||
|
"""Parse a parameter string like 'const char *filename' or 'const char *const argv[]' into type and name."""
|
||||||
|
if not param_str.strip():
|
||||||
|
return "", ""
|
||||||
|
|
||||||
|
# Clean up the parameter string
|
||||||
|
param_str = param_str.strip()
|
||||||
|
|
||||||
|
# Handle array syntax like 'const char *const argv[]'
|
||||||
|
array_match = re.search(r'\[\]', param_str)
|
||||||
|
is_array = bool(array_match)
|
||||||
|
if is_array:
|
||||||
|
param_str = re.sub(r'\[\]', '', param_str).strip()
|
||||||
|
|
||||||
|
# Remove 'const' qualifiers for type mapping (but keep track of them)
|
||||||
|
cleaned_param = re.sub(r'\bconst\b\s*', '', param_str).strip()
|
||||||
|
|
||||||
|
# Handle pointer types like 'char *buf' or 'struct stat *statbuf'
|
||||||
|
if '*' in cleaned_param:
|
||||||
|
parts = cleaned_param.split('*')
|
||||||
|
base_type = parts[0].strip()
|
||||||
|
var_name = parts[1].strip()
|
||||||
|
|
||||||
|
# Handle struct types
|
||||||
|
if base_type.startswith('struct '):
|
||||||
|
return '^u8', var_name # Generic pointer for structs
|
||||||
|
elif base_type.startswith('union '):
|
||||||
|
return '^u8', var_name # Generic pointer for unions
|
||||||
|
elif 'void' in base_type:
|
||||||
|
return '^u8', var_name # void pointer becomes generic pointer
|
||||||
|
elif 'char' in base_type:
|
||||||
|
if is_array:
|
||||||
|
return '^cstring', var_name # Array of strings
|
||||||
|
else:
|
||||||
|
return '^u8', var_name # char pointer
|
||||||
|
else:
|
||||||
|
# For other pointer types, use the mapped base type with pointer
|
||||||
|
mapped_base = map_c_type_to_custom(base_type)
|
||||||
|
return f'^{mapped_base}', var_name
|
||||||
|
|
||||||
|
# Handle regular types like 'unsigned int fd', 'size_t count'
|
||||||
|
parts = cleaned_param.strip().split()
|
||||||
|
if len(parts) >= 2:
|
||||||
|
var_name = parts[-1]
|
||||||
|
type_parts = parts[:-1]
|
||||||
|
full_type = ' '.join(type_parts)
|
||||||
|
mapped_type = map_c_type_to_custom(full_type)
|
||||||
|
return mapped_type, var_name
|
||||||
|
elif len(parts) == 1:
|
||||||
|
# Single word - might be a type without variable name or variable without type
|
||||||
|
return "", parts[0]
|
||||||
|
|
||||||
|
return "", ""
|
||||||
|
|
||||||
|
def map_c_type_to_custom(c_type: str) -> str:
|
||||||
|
"""Map C types to custom type system."""
|
||||||
|
c_type = c_type.strip().lower()
|
||||||
|
|
||||||
|
# Handle common C types
|
||||||
|
if 'unsigned int' in c_type or c_type == 'int':
|
||||||
|
return 'u32'
|
||||||
|
elif 'unsigned long' in c_type or c_type == 'long':
|
||||||
|
return 'u64'
|
||||||
|
elif 'size_t' in c_type or 'ssize_t' in c_type:
|
||||||
|
return 'u64'
|
||||||
|
elif 'off_t' in c_type or 'loff_t' in c_type:
|
||||||
|
return 'u64'
|
||||||
|
elif 'pid_t' in c_type or 'uid_t' in c_type or 'gid_t' in c_type:
|
||||||
|
return 'u32'
|
||||||
|
elif 'mode_t' in c_type or 'umode_t' in c_type:
|
||||||
|
return 'u32'
|
||||||
|
elif 'time_t' in c_type:
|
||||||
|
return 'u64'
|
||||||
|
elif 'key_t' in c_type:
|
||||||
|
return 'u32'
|
||||||
|
elif 'mqd_t' in c_type:
|
||||||
|
return 'u32'
|
||||||
|
elif 'clockid_t' in c_type:
|
||||||
|
return 'u32'
|
||||||
|
elif 'timer_t' in c_type:
|
||||||
|
return 'u32'
|
||||||
|
elif 'qid_t' in c_type:
|
||||||
|
return 'u32'
|
||||||
|
elif 'aio_context_t' in c_type:
|
||||||
|
return 'u64'
|
||||||
|
elif c_type == 'char':
|
||||||
|
return 'u8'
|
||||||
|
elif c_type == 'unsigned char':
|
||||||
|
return 'u8'
|
||||||
|
elif c_type == 'short' or 'short int' in c_type:
|
||||||
|
return 'u16'
|
||||||
|
elif c_type == 'unsigned short':
|
||||||
|
return 'u16'
|
||||||
|
elif 'void' in c_type:
|
||||||
|
return 'u8' # void maps to u8 for generic data
|
||||||
|
elif c_type.startswith('struct') or c_type.startswith('union'):
|
||||||
|
return 'u8' # Structs/unions map to u8 for generic handling
|
||||||
|
elif 'u32' in c_type or 'u64' in c_type: # Already in target format
|
||||||
|
return c_type
|
||||||
|
else:
|
||||||
|
return 'u32' # Default fallback
|
||||||
|
|
||||||
|
def extract_function_name(syscall_name: str) -> str:
|
||||||
|
"""Extract function name from syscall name like 'sys_read' -> 'read'."""
|
||||||
|
if syscall_name.startswith('sys_'):
|
||||||
|
return syscall_name[4:]
|
||||||
|
elif syscall_name.startswith('stub_'):
|
||||||
|
return syscall_name[5:]
|
||||||
|
return syscall_name
|
||||||
|
|
||||||
|
def clean_syscall_name(syscall_name: str) -> str:
|
||||||
|
"""Clean syscall names that might have issues."""
|
||||||
|
# Handle special cases
|
||||||
|
if 'NOT IMPLEMENTED' in syscall_name or 'REMOVED' in syscall_name:
|
||||||
|
return ""
|
||||||
|
return syscall_name.strip()
|
||||||
|
|
||||||
|
def convert_csv_to_functions(csv_content: str) -> str:
|
||||||
|
"""Convert CSV content to function definitions."""
|
||||||
|
lines = csv_content.strip().split('\n')
|
||||||
|
|
||||||
|
# Parse header to understand column positions
|
||||||
|
header = [col.strip() for col in lines[0].split(',')]
|
||||||
|
|
||||||
|
# Find the positions of key columns
|
||||||
|
syscall_num_idx = 0 # %rax
|
||||||
|
syscall_name_idx = 1 # System call
|
||||||
|
param_indices = [i for i, col in enumerate(header) if col.startswith('%') and col != '%rax']
|
||||||
|
|
||||||
|
functions = []
|
||||||
|
|
||||||
|
for line_num, line in enumerate(lines[1:], 2): # Skip header, start from line 2
|
||||||
|
if not line.strip():
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Handle CSV parsing more carefully - some lines have trailing commas
|
||||||
|
cols = [col.strip() for col in line.split(',')]
|
||||||
|
|
||||||
|
# Ensure we have enough columns
|
||||||
|
while len(cols) < len(header):
|
||||||
|
cols.append('')
|
||||||
|
|
||||||
|
# Extract syscall number and name
|
||||||
|
syscall_num = cols[syscall_num_idx] if syscall_num_idx < len(cols) else ""
|
||||||
|
syscall_name = cols[syscall_name_idx] if syscall_name_idx < len(cols) else ""
|
||||||
|
|
||||||
|
# Clean and validate syscall name
|
||||||
|
syscall_name = clean_syscall_name(syscall_name)
|
||||||
|
if not syscall_num or not syscall_name or syscall_name in ['NOT IMPLEMENTED', 'REMOVED IN Linux 2.6']:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Extract function name
|
||||||
|
func_name = extract_function_name(syscall_name)
|
||||||
|
if not func_name:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Parse parameters
|
||||||
|
params = []
|
||||||
|
param_names = []
|
||||||
|
|
||||||
|
for param_idx in param_indices:
|
||||||
|
if param_idx < len(cols):
|
||||||
|
param_str = cols[param_idx]
|
||||||
|
if param_str.strip():
|
||||||
|
param_type, param_name = parse_type_and_name(param_str)
|
||||||
|
if param_type and param_name:
|
||||||
|
params.append(f"{param_name}: {param_type}")
|
||||||
|
param_names.append(param_name)
|
||||||
|
|
||||||
|
# Generate function definition
|
||||||
|
if params:
|
||||||
|
param_list = ", ".join(params)
|
||||||
|
else:
|
||||||
|
param_list = ""
|
||||||
|
|
||||||
|
call_params = ", ".join([syscall_num] + param_names)
|
||||||
|
|
||||||
|
# function_def = f"func {func_name}({param_list}) {{\n call({call_params})\n}}"
|
||||||
|
# functions.append(function_def)
|
||||||
|
functions.append(f"const {func_name}: i64 = {syscall_num}")
|
||||||
|
|
||||||
|
return "\n\n".join(functions)
|
||||||
|
|
||||||
|
# Test with a file if provided
|
||||||
|
def process_file(filename: str) -> str:
|
||||||
|
"""Process a CSV file and return the converted functions."""
|
||||||
|
try:
|
||||||
|
with open(filename, 'r') as f:
|
||||||
|
content = f.read()
|
||||||
|
return convert_csv_to_functions(content)
|
||||||
|
except FileNotFoundError:
|
||||||
|
return f"Error: File '{filename}' not found."
|
||||||
|
except Exception as e:
|
||||||
|
return f"Error processing file: {str(e)}"
|
||||||
|
|
||||||
|
# Example usage with file reading
|
||||||
|
def main():
|
||||||
|
# If running with the uploaded file
|
||||||
|
try:
|
||||||
|
# Try to read from the uploaded file
|
||||||
|
with open('paste.txt', 'r') as f:
|
||||||
|
csv_content = f.read()
|
||||||
|
result = convert_csv_to_functions(csv_content)
|
||||||
|
print("Generated functions from paste.txt:")
|
||||||
|
print("=" * 50)
|
||||||
|
print(result)
|
||||||
|
except FileNotFoundError:
|
||||||
|
# Fallback to sample data
|
||||||
|
sample_csv = """%rax, System call, %rdi, %rsi, %rdx, %r10, %r8, %r9
|
||||||
|
0, sys_read, unsigned int fd, char *buf, size_t count, , ,
|
||||||
|
1, sys_write, unsigned int fd, const char *buf, size_t count, , ,
|
||||||
|
2, sys_open, const char *filename, int flags, int mode, , ,
|
||||||
|
3, sys_close, unsigned int fd, , , , ,
|
||||||
|
4, sys_stat, const char *filename, struct stat *statbuf, , , ,
|
||||||
|
5, sys_fstat, unsigned int fd, struct stat *statbuf, , , ,
|
||||||
|
6, sys_lstat, fconst char *filename, struct stat *statbuf, , , ,
|
||||||
|
7, sys_poll, struct poll_fd *ufds, unsigned int nfds, long timeout_msecs, , ,
|
||||||
|
8, sys_lseek, unsigned int fd, off_t offset, unsigned int origin, , ,
|
||||||
|
9, sys_mmap, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off
|
||||||
|
10, sys_mprotect, unsigned long start, size_t len, unsigned long prot, , ,
|
||||||
|
11, sys_munmap, unsigned long addr, size_t len, , , ,
|
||||||
|
12, sys_brk, unsigned long brk, , , , ,
|
||||||
|
13, sys_rt_sigaction, int sig, const struct sigaction *act, struct sigaction *oact, size_t sigsetsize, ,
|
||||||
|
14, sys_rt_sigprocmask, int how, sigset_t *nset, sigset_t *oset, size_t sigsetsize, ,
|
||||||
|
15, sys_rt_sigreturn, unsigned long __unused, , , , ,
|
||||||
|
16, sys_ioctl, unsigned int fd, unsigned int cmd, unsigned long arg, , ,
|
||||||
|
17, sys_pread64, unsigned long fd, char *buf, size_t count, loff_t pos, ,
|
||||||
|
18, sys_pwrite64, unsigned int fd, const char *buf, size_t count, loff_t pos, ,
|
||||||
|
19, sys_readv, unsigned long fd, const struct iovec *vec, unsigned long vlen, , ,
|
||||||
|
20, sys_writev, unsigned long fd, const struct iovec *vec, unsigned long vlen, , ,
|
||||||
|
21, sys_access, const char *filename, int mode, , , ,
|
||||||
|
22, sys_pipe, int *filedes, , , , ,
|
||||||
|
23, sys_select, int n, fd_set *inp, fd_set *outp, fd_set*exp, struct timeval *tvp,
|
||||||
|
24, sys_sched_yield, , , , , ,
|
||||||
|
25, sys_mremap, unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr,
|
||||||
|
26, sys_msync, unsigned long start, size_t len, int flags, , ,
|
||||||
|
27, sys_mincore, unsigned long start, size_t len, unsigned char *vec, , ,
|
||||||
|
28, sys_madvise, unsigned long start, size_t len_in, int behavior, , ,
|
||||||
|
29, sys_shmget, key_t key, size_t size, int shmflg, , ,
|
||||||
|
30, sys_shmat, int shmid, char *shmaddr, int shmflg, , ,
|
||||||
|
31, sys_shmctl, int shmid, int cmd, struct shmid_ds *buf, , ,
|
||||||
|
32, sys_dup, unsigned int fildes, , , , ,
|
||||||
|
33, sys_dup2, unsigned int oldfd, unsigned int newfd, , , ,
|
||||||
|
34, sys_pause, , , , , ,
|
||||||
|
35, sys_nanosleep, struct timespec *rqtp, struct timespec *rmtp, , , ,
|
||||||
|
36, sys_getitimer, int which, struct itimerval *value, , , ,
|
||||||
|
37, sys_alarm, unsigned int seconds, , , , ,
|
||||||
|
38, sys_setitimer, int which, struct itimerval *value, struct itimerval *ovalue, , ,
|
||||||
|
39, sys_getpid, , , , , ,
|
||||||
|
40, sys_sendfile, int out_fd, int in_fd, off_t *offset, size_t count, ,
|
||||||
|
41, sys_socket, int family, int type, int protocol, , ,
|
||||||
|
42, sys_connect, int fd, struct sockaddr *uservaddr, int addrlen, , ,
|
||||||
|
43, sys_accept, int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen, , ,
|
||||||
|
44, sys_sendto, int fd, void *buff, size_t len, unsigned flags, struct sockaddr *addr, int addr_len
|
||||||
|
45, sys_recvfrom, int fd, void *ubuf, size_t size, unsigned flags, struct sockaddr *addr, int *addr_len
|
||||||
|
46, sys_sendmsg, int fd, struct msghdr *msg, unsigned flags, , ,
|
||||||
|
47, sys_recvmsg, int fd, struct msghdr *msg, unsigned int flags, , ,
|
||||||
|
48, sys_shutdown, int fd, int how, , , ,
|
||||||
|
49, sys_bind, int fd, struct sokaddr *umyaddr, int addrlen, , ,
|
||||||
|
50, sys_listen, int fd, int backlog, , , ,
|
||||||
|
51, sys_getsockname, int fd, struct sockaddr *usockaddr, int *usockaddr_len, , ,
|
||||||
|
52, sys_getpeername, int fd, struct sockaddr *usockaddr, int *usockaddr_len, , ,
|
||||||
|
53, sys_socketpair, int family, int type, int protocol, int *usockvec, ,
|
||||||
|
54, sys_setsockopt, int fd, int level, int optname, char *optval, int optlen,
|
||||||
|
55, sys_getsockopt, int fd, int level, int optname, char *optval, int *optlen,
|
||||||
|
56, sys_clone, unsigned long clone_flags, unsigned long newsp, void *parent_tid, void *child_tid, unsigned int tid,
|
||||||
|
57, sys_fork, , , , , ,
|
||||||
|
58, sys_vfork, , , , , ,
|
||||||
|
59, sys_execve, const char *filename, const char *const argv[], const char *const envp[], , ,
|
||||||
|
60, sys_exit, int error_code, , , , ,
|
||||||
|
61, sys_wait4, pid_t upid, int *stat_addr, int options, struct rusage *ru, ,
|
||||||
|
62, sys_kill, pid_t pid, int sig, , , ,
|
||||||
|
63, sys_uname, struct old_utsname *name, , , , ,
|
||||||
|
64, sys_semget, key_t key, int nsems, int semflg, , ,
|
||||||
|
65, sys_semop, int semid, struct sembuf *tsops, unsigned nsops, , ,
|
||||||
|
66, sys_semctl, int semid, int semnum, int cmd, union semun arg, ,
|
||||||
|
67, sys_shmdt, char *shmaddr, , , , ,
|
||||||
|
68, sys_msgget, key_t key, int msgflg, , , ,
|
||||||
|
69, sys_msgsnd, int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg, ,
|
||||||
|
70, sys_msgrcv, int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg,
|
||||||
|
71, sys_msgctl, int msqid, int cmd, struct msqid_ds *buf, , ,
|
||||||
|
72, sys_fcntl, unsigned int fd, unsigned int cmd, unsigned long arg, , ,
|
||||||
|
73, sys_flock, unsigned int fd, unsigned int cmd, , , ,
|
||||||
|
74, sys_fsync, unsigned int fd, , , , ,
|
||||||
|
75, sys_fdatasync, unsigned int fd, , , , ,
|
||||||
|
76, sys_truncate, const char *path, long length, , , ,
|
||||||
|
77, sys_ftruncate, unsigned int fd, unsigned long length, , , ,
|
||||||
|
78, sys_getdents, unsigned int fd, struct linux_dirent *dirent, unsigned int count, , ,
|
||||||
|
79, sys_getcwd, char *buf, unsigned long size, , , ,
|
||||||
|
80, sys_chdir, const char *filename, , , , ,
|
||||||
|
81, sys_fchdir, unsigned int fd, , , , ,
|
||||||
|
82, sys_rename, const char *oldname, const char *newname, , , ,
|
||||||
|
83, sys_mkdir, const char *pathname, int mode, , , ,
|
||||||
|
84, sys_rmdir, const char *pathname, , , , ,
|
||||||
|
85, sys_creat, const char *pathname, int mode, , , ,
|
||||||
|
86, sys_link, const char *oldname, const char *newname, , , ,
|
||||||
|
87, sys_unlink, const char *pathname, , , , ,
|
||||||
|
88, sys_symlink, const char *oldname, const char *newname, , , ,
|
||||||
|
89, sys_readlink, const char *path, char *buf, int bufsiz, , ,
|
||||||
|
90, sys_chmod, const char *filename, mode_t mode, , , ,
|
||||||
|
91, sys_fchmod, unsigned int fd, mode_t mode, , , ,
|
||||||
|
92, sys_chown, const char *filename, uid_t user, gid_t group, , ,
|
||||||
|
93, sys_fchown, unsigned int fd, uid_t user, gid_t group, , ,
|
||||||
|
94, sys_lchown, const char *filename, uid_t user, gid_t group, , ,
|
||||||
|
95, sys_umask, int mask, , , , ,
|
||||||
|
96, sys_gettimeofday, struct timeval *tv, struct timezone *tz, , , ,
|
||||||
|
97, sys_getrlimit, unsigned int resource, struct rlimit *rlim, , , ,
|
||||||
|
98, sys_getrusage, int who, struct rusage *ru, , , ,
|
||||||
|
99, sys_sysinfo, struct sysinfo *info, , , , ,
|
||||||
|
100, sys_times, struct tms *tbuf, , , , ,
|
||||||
|
101, sys_ptrace, long request, long pid, unsigned long addr, unsigned long data, ,
|
||||||
|
102, sys_getuid, , , , , ,
|
||||||
|
103, sys_syslog, int type, char *buf, int len, , ,
|
||||||
|
104, sys_getgid, , , , , ,
|
||||||
|
105, sys_setuid, uid_t uid, , , , ,
|
||||||
|
106, sys_setgid, gid_t gid, , , , ,
|
||||||
|
107, sys_geteuid, , , , , ,
|
||||||
|
108, sys_getegid, , , , , ,
|
||||||
|
109, sys_setpgid, pid_t pid, pid_t pgid, , , ,
|
||||||
|
110, sys_getppid, , , , , ,
|
||||||
|
111, sys_getpgrp, , , , , ,
|
||||||
|
112, sys_setsid, , , , , ,
|
||||||
|
113, sys_setreuid, uid_t ruid, uid_t euid, , , ,
|
||||||
|
114, sys_setregid, gid_t rgid, gid_t egid, , , ,
|
||||||
|
115, sys_getgroups, int gidsetsize, gid_t *grouplist, , , ,
|
||||||
|
116, sys_setgroups, int gidsetsize, gid_t *grouplist, , , ,
|
||||||
|
117, sys_setresuid, uid_t *ruid, uid_t *euid, uid_t *suid, , ,
|
||||||
|
118, sys_getresuid, uid_t *ruid, uid_t *euid, uid_t *suid, , ,
|
||||||
|
119, sys_setresgid, gid_t rgid, gid_t egid, gid_t sgid, , ,
|
||||||
|
120, sys_getresgid, gid_t *rgid, gid_t *egid, gid_t *sgid, , ,
|
||||||
|
121, sys_getpgid, pid_t pid, , , , ,
|
||||||
|
122, sys_setfsuid, uid_t uid, , , , ,
|
||||||
|
123, sys_setfsgid, gid_t gid, , , , ,
|
||||||
|
124, sys_getsid, pid_t pid, , , , ,
|
||||||
|
125, sys_capget, cap_user_header_t header, cap_user_data_t dataptr, , , ,
|
||||||
|
126, sys_capset, cap_user_header_t header, const cap_user_data_t data, , , ,
|
||||||
|
127, sys_rt_sigpending, sigset_t *set, size_t sigsetsize, , , ,
|
||||||
|
128, sys_rt_sigtimedwait, const sigset_t *uthese, siginfo_t *uinfo, const struct timespec *uts, size_t sigsetsize, ,
|
||||||
|
129, sys_rt_sigqueueinfo, pid_t pid, int sig, siginfo_t *uinfo, , ,
|
||||||
|
130, sys_rt_sigsuspend, sigset_t *unewset, size_t sigsetsize, , , ,
|
||||||
|
131, sys_sigaltstack, const stack_t *uss, stack_t *uoss, , , ,
|
||||||
|
132, sys_utime, char *filename, struct utimbuf *times, , , ,
|
||||||
|
133, sys_mknod, const char *filename, umode_t mode, unsigned dev, , ,
|
||||||
|
134, sys_uselib, NOT IMPLEMENTED, , , , ,
|
||||||
|
135, sys_personality, unsigned int personality, , , , ,
|
||||||
|
136, sys_ustat, unsigned dev, struct ustat *ubuf, , , ,
|
||||||
|
137, sys_statfs, const char *pathname, struct statfs *buf, , , ,
|
||||||
|
138, sys_fstatfs, unsigned int fd, struct statfs *buf, , , ,
|
||||||
|
139, sys_sysfs, int option, unsigned long arg1, unsigned long arg2, , ,
|
||||||
|
140, sys_getpriority, int which, int who, , , ,
|
||||||
|
141, sys_setpriority, int which, int who, int niceval, , ,
|
||||||
|
142, sys_sched_setparam, pid_t pid, struct sched_param *param, , , ,
|
||||||
|
143, sys_sched_getparam, pid_t pid, struct sched_param *param, , , ,
|
||||||
|
144, sys_sched_setscheduler, pid_t pid, int policy, struct sched_param *param, , ,
|
||||||
|
145, sys_sched_getscheduler, pid_t pid, , , , ,
|
||||||
|
146, sys_sched_get_priority_max, int policy, , , , ,
|
||||||
|
147, sys_sched_get_priority_min, int policy, , , , ,
|
||||||
|
148, sys_sched_rr_get_interval, pid_t pid, struct timespec *interval, , , ,
|
||||||
|
149, sys_mlock, unsigned long start, size_t len, , , ,
|
||||||
|
150, sys_munlock, unsigned long start, size_t len, , , ,
|
||||||
|
151, sys_mlockall, int flags, , , , ,
|
||||||
|
152, sys_munlockall, , , , , ,
|
||||||
|
153, sys_vhangup, , , , , ,
|
||||||
|
154, sys_modify_ldt, int func, void *ptr, unsigned long bytecount, , ,
|
||||||
|
155, sys_pivot_root, const char *new_root, const char *put_old, , , ,
|
||||||
|
156, sys__sysctl, struct __sysctl_args *args, , , , ,
|
||||||
|
157, sys_prctl, int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, , unsigned long arg5
|
||||||
|
158, sys_arch_prctl, struct task_struct *task, int code, unsigned long *addr, , ,
|
||||||
|
159, sys_adjtimex, struct timex *txc_p, , , , ,
|
||||||
|
160, sys_setrlimit, unsigned int resource, struct rlimit *rlim, , , ,
|
||||||
|
161, sys_chroot, const char *filename, , , , ,
|
||||||
|
162, sys_sync, , , , , ,
|
||||||
|
163, sys_acct, const char *name, , , , ,
|
||||||
|
164, sys_settimeofday, struct timeval *tv, struct timezone *tz, , , ,
|
||||||
|
165, sys_mount, char *dev_name, char *dir_name, char *type, unsigned long flags, void *data,
|
||||||
|
166, sys_umount2, const char *target, int flags, , , ,
|
||||||
|
167, sys_swapon, const char *specialfile, int swap_flags, , , ,
|
||||||
|
168, sys_swapoff, const char *specialfile, , , , ,
|
||||||
|
169, sys_reboot, int magic1, int magic2, unsigned int cmd, void *arg, ,
|
||||||
|
170, sys_sethostname, char *name, int len, , , ,
|
||||||
|
171, sys_setdomainname, char *name, int len, , , ,
|
||||||
|
172, sys_iopl, unsigned int level, struct pt_regs *regs, , , ,
|
||||||
|
173, sys_ioperm, unsigned long from, unsigned long num, int turn_on, , ,
|
||||||
|
174, sys_create_module, REMOVED IN Linux 2.6, , , , ,
|
||||||
|
175, sys_init_module, void *umod, unsigned long len, const char *uargs, , ,
|
||||||
|
176, sys_delete_module, const chat *name_user, unsigned int flags, , , ,
|
||||||
|
177, sys_get_kernel_syms, REMOVED IN Linux 2.6, , , , ,
|
||||||
|
178, sys_query_module, REMOVED IN Linux 2.6, , , , ,
|
||||||
|
179, sys_quotactl, unsigned int cmd, const char *special, qid_t id, void *addr, ,
|
||||||
|
180, sys_nfsservctl, NOT IMPLEMENTED, , , , ,
|
||||||
|
181, sys_getpmsg, NOT IMPLEMENTED, , , , ,
|
||||||
|
182, sys_putpmsg, NOT IMPLEMENTED, , , , ,
|
||||||
|
183, sys_afs_syscall, NOT IMPLEMENTED, , , , ,
|
||||||
|
184, sys_tuxcall, NOT IMPLEMENTED, , , , ,
|
||||||
|
185, sys_security, NOT IMPLEMENTED, , , , ,
|
||||||
|
186, sys_gettid, , , , , ,
|
||||||
|
187, sys_readahead, int fd, loff_t offset, size_t count, , ,
|
||||||
|
188, sys_setxattr, const char *pathname, const char *name, const void *value, size_t size, int flags,
|
||||||
|
189, sys_lsetxattr, const char *pathname, const char *name, const void *value, size_t size, int flags,
|
||||||
|
190, sys_fsetxattr, int fd, const char *name, const void *value, size_t size, int flags,
|
||||||
|
191, sys_getxattr, const char *pathname, const char *name, void *value, size_t size, ,
|
||||||
|
192, sys_lgetxattr, const char *pathname, const char *name, void *value, size_t size, ,
|
||||||
|
193, sys_fgetxattr, int fd, const har *name, void *value, size_t size, ,
|
||||||
|
194, sys_listxattr, const char *pathname, char *list, size_t size, , ,
|
||||||
|
195, sys_llistxattr, const char *pathname, char *list, size_t size, , ,
|
||||||
|
196, sys_flistxattr, int fd, char *list, size_t size, , ,
|
||||||
|
197, sys_removexattr, const char *pathname, const char *name, , , ,
|
||||||
|
198, sys_lremovexattr, const char *pathname, const char *name, , , ,
|
||||||
|
199, sys_fremovexattr, int fd, const char *name, , , ,
|
||||||
|
200, sys_tkill, pid_t pid, ing sig, , , ,
|
||||||
|
201, sys_time, time_t *tloc, , , , ,
|
||||||
|
202, sys_futex, u32 *uaddr, int op, u32 val, struct timespec *utime, u32 *uaddr2, u32 val3
|
||||||
|
203, sys_sched_setaffinity, pid_t pid, unsigned int len, unsigned long *user_mask_ptr, , ,
|
||||||
|
204, sys_sched_getaffinity, pid_t pid, unsigned int len, unsigned long *user_mask_ptr, , ,
|
||||||
|
205, sys_set_thread_area, NOT IMPLEMENTED. Use arch_prctl, , , , ,
|
||||||
|
206, sys_io_setup, unsigned nr_events, aio_context_t *ctxp, , , ,
|
||||||
|
207, sys_io_destroy, aio_context_t ctx, , , , ,
|
||||||
|
208, sys_io_getevents, aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, ,
|
||||||
|
209, sys_io_submit, aio_context_t ctx_id, long nr, struct iocb **iocbpp, , ,
|
||||||
|
210, sys_io_cancel, aio_context_t ctx_id, struct iocb *iocb, struct io_event *result, , ,
|
||||||
|
211, sys_get_thread_area, NOT IMPLEMENTED. Use arch_prctl, , , , ,
|
||||||
|
212, sys_lookup_dcookie, u64 cookie64, long buf, long len, , ,
|
||||||
|
213, sys_epoll_create, int size, , , , ,
|
||||||
|
214, sys_epoll_ctl_old, NOT IMPLEMENTED, , , , ,
|
||||||
|
215, sys_epoll_wait_old, NOT IMPLEMENTED, , , , ,
|
||||||
|
216, sys_remap_file_pages, unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long flags,
|
||||||
|
217, sys_getdents64, unsigned int fd, struct linux_dirent64 *dirent, unsigned int count, , ,
|
||||||
|
218, sys_set_tid_address, int *tidptr, , , , ,
|
||||||
|
219, sys_restart_syscall, , , , , ,
|
||||||
|
220, sys_semtimedop, int semid, struct sembuf *tsops, unsigned nsops, const struct timespec *timeout, ,
|
||||||
|
221, sys_fadvise64, int fd, loff_t offset, size_t len, int advice, ,
|
||||||
|
222, sys_timer_create, const clockid_t which_clock, struct sigevent *timer_event_spec, timer_t *created_timer_id, , ,
|
||||||
|
223, sys_timer_settime, timer_t timer_id, int flags, const struct itimerspec *new_setting, struct itimerspec *old_setting, ,
|
||||||
|
224, sys_timer_gettime, timer_t timer_id, struct itimerspec *setting, , , ,
|
||||||
|
225, sys_timer_getoverrun, timer_t timer_id, , , , ,
|
||||||
|
226, sys_timer_delete, timer_t timer_id, , , , ,
|
||||||
|
227, sys_clock_settime, const clockid_t which_clock, const struct timespec *tp, , , ,
|
||||||
|
228, sys_clock_gettime, const clockid_t which_clock, struct timespec *tp, , , ,
|
||||||
|
229, sys_clock_getres, const clockid_t which_clock, struct timespec *tp, , , ,
|
||||||
|
230, sys_clock_nanosleep, const clockid_t which_clock, int flags, const struct timespec *rqtp, struct timespec *rmtp, ,
|
||||||
|
231, sys_exit_group, int error_code, , , , ,
|
||||||
|
232, sys_epoll_wait, int epfd, struct epoll_event *events, int maxevents, int timeout, ,
|
||||||
|
233, sys_epoll_ctl, int epfd, int op, int fd, struct epoll_event *event, ,
|
||||||
|
234, sys_tgkill, pid_t tgid, pid_t pid, int sig, , ,
|
||||||
|
235, sys_utimes, char *filename, struct timeval *utimes, , , ,
|
||||||
|
236, sys_vserver, NOT IMPLEMENTED, , , , ,
|
||||||
|
237, sys_mbind, unsigned long start, unsigned long len, unsigned long mode, unsigned long *nmask, unsigned long maxnode, unsigned flags
|
||||||
|
238, sys_set_mempolicy, int mode, unsigned long *nmask, unsigned long maxnode, , ,
|
||||||
|
239, sys_get_mempolicy, int *policy, unsigned long *nmask, unsigned long maxnode, unsigned long addr, unsigned long flags,
|
||||||
|
240, sys_mq_open, const char *u_name, int oflag, mode_t mode, struct mq_attr *u_attr, ,
|
||||||
|
241, sys_mq_unlink, const char *u_name, , , , ,
|
||||||
|
242, sys_mq_timedsend, mqd_t mqdes, const char *u_msg_ptr, size_t msg_len, unsigned int msg_prio, const stuct timespec *u_abs_timeout,
|
||||||
|
243, sys_mq_timedreceive, mqd_t mqdes, char *u_msg_ptr, size_t msg_len, unsigned int *u_msg_prio, const struct timespec *u_abs_timeout,
|
||||||
|
244, sys_mq_notify, mqd_t mqdes, const struct sigevent *u_notification, , , ,
|
||||||
|
245, sys_mq_getsetattr, mqd_t mqdes, const struct mq_attr *u_mqstat, struct mq_attr *u_omqstat, , ,
|
||||||
|
246, sys_kexec_load, unsigned long entry, unsigned long nr_segments, struct kexec_segment *segments, unsigned long flags, ,
|
||||||
|
247, sys_waitid, int which, pid_t upid, struct siginfo *infop, int options, struct rusage *ru,
|
||||||
|
248, sys_add_key, const char *_type, const char *_description, const void *_payload, size_t plen, ,
|
||||||
|
249, sys_request_key, const char *_type, const char *_description, const char *_callout_info, key_serial_t destringid, ,
|
||||||
|
250, sys_keyctl, int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5,
|
||||||
|
251, sys_ioprio_set, int which, int who, int ioprio, , ,
|
||||||
|
252, sys_ioprio_get, int which, int who, , , ,
|
||||||
|
253, sys_inotify_init, , , , , ,
|
||||||
|
254, sys_inotify_add_watch, int fd, const char *pathname, u32 mask, , ,
|
||||||
|
255, sys_inotify_rm_watch, int fd, __s32 wd, , , ,
|
||||||
|
256, sys_migrate_pages, pid_t pid, unsigned long maxnode, const unsigned long *old_nodes, const unsigned long *new_nodes, ,
|
||||||
|
257, sys_openat, int dfd, const char *filename, int flags, int mode, ,
|
||||||
|
258, sys_mkdirat, int dfd, const char *pathname, int mode, , ,
|
||||||
|
259, sys_mknodat, int dfd, const char *filename, int mode, unsigned dev, ,
|
||||||
|
260, sys_fchownat, int dfd, const char *filename, uid_t user, gid_t group, int flag,
|
||||||
|
261, sys_futimesat, int dfd, const char *filename, struct timeval *utimes, , ,
|
||||||
|
262, sys_newfstatat, int dfd, const char *filename, struct stat *statbuf, int flag, ,
|
||||||
|
263, sys_unlinkat, int dfd, const char *pathname, int flag, , ,
|
||||||
|
264, sys_renameat, int oldfd, const char *oldname, int newfd, const char *newname, ,
|
||||||
|
265, sys_linkat, int oldfd, const char *oldname, int newfd, const char *newname, int flags,
|
||||||
|
266, sys_symlinkat, const char *oldname, int newfd, const char *newname, , ,
|
||||||
|
267, sys_readlinkat, int dfd, const char *pathname, char *buf, int bufsiz, ,
|
||||||
|
268, sys_fchmodat, int dfd, const char *filename, mode_t mode, , ,
|
||||||
|
269, sys_faccessat, int dfd, const char *filename, int mode, , ,
|
||||||
|
270, sys_pselect6, int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timespec *tsp, void *sig
|
||||||
|
271, sys_ppoll, struct pollfd *ufds, unsigned int nfds, struct timespec *tsp, const sigset_t *sigmask, size_t sigsetsize,
|
||||||
|
272, sys_unshare, unsigned long unshare_flags, , , , ,
|
||||||
|
273, sys_set_robust_list, struct robust_list_head *head, size_t len, , , ,
|
||||||
|
274, sys_get_robust_list, int pid, struct robust_list_head **head_ptr, size_t *len_ptr, , ,
|
||||||
|
275, sys_splice, int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags
|
||||||
|
276, sys_tee, int fdin, int fdout, size_t len, unsigned int flags, ,
|
||||||
|
277, sys_sync_file_range, long fd, loff_t offset, loff_t bytes, long flags, ,
|
||||||
|
278, sys_vmsplice, int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags, ,
|
||||||
|
279, sys_move_pages, pid_t pid, unsigned long nr_pages, const void **pages, const int *nodes, int *status, int flags
|
||||||
|
280, sys_utimensat, int dfd, const char *filename, struct timespec *utimes, int flags, ,
|
||||||
|
281, sys_epoll_pwait, int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask, size_t sigsetsize
|
||||||
|
282, sys_signalfd, int ufd, sigset_t *user_mask, size_t sizemask, , ,
|
||||||
|
283, sys_timerfd_create, int clockid, int flags, , , ,
|
||||||
|
284, sys_eventfd, unsigned int count, , , , ,
|
||||||
|
285, sys_fallocate, long fd, long mode, loff_t offset, loff_t len, ,
|
||||||
|
286, sys_timerfd_settime, int ufd, int flags, const struct itimerspec *utmr, struct itimerspec *otmr, ,
|
||||||
|
287, sys_timerfd_gettime, int ufd, struct itimerspec *otmr, , , ,
|
||||||
|
288, sys_accept4, int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen, int flags, ,
|
||||||
|
289, sys_signalfd4, int ufd, sigset_t *user_mask, size_t sizemask, int flags, ,
|
||||||
|
290, sys_eventfd2, unsigned int count, int flags, , , ,
|
||||||
|
291, sys_epoll_create1, int flags, , , , ,
|
||||||
|
292, sys_dup3, unsigned int oldfd, unsigned int newfd, int flags, , ,
|
||||||
|
293, sys_pipe2, int *filedes, int flags, , , ,
|
||||||
|
294, sys_inotify_init1, int flags, , , , ,
|
||||||
|
295, sys_preadv, unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h,
|
||||||
|
296, sys_pwritev, unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h,
|
||||||
|
297, sys_rt_tgsigqueueinfo, pid_t tgid, pid_t pid, int sig, siginfo_t *uinfo, ,
|
||||||
|
298, sys_perf_event_open, struct perf_event_attr *attr_uptr, pid_t pid, int cpu, int group_fd, unsigned long flags,
|
||||||
|
299, sys_recvmmsg, int fd, struct msghdr *mmsg, unsigned int vlen, unsigned int flags, struct timespec *timeout,
|
||||||
|
300, sys_fanotify_init, unsigned int flags, unsigned int event_f_flags, , , ,
|
||||||
|
301, sys_fanotify_mark, long fanotify_fd, long flags, __u64 mask, long dfd, long pathname,
|
||||||
|
302, sys_prlimit64, pid_t pid, unsigned int resource, const struct rlimit64 *new_rlim, struct rlimit64 *old_rlim, ,
|
||||||
|
303, sys_name_to_handle_at, int dfd, const char *name, struct file_handle *handle, int *mnt_id, int flag,
|
||||||
|
304, sys_open_by_handle_at, int dfd, const char *name, struct file_handle *handle, int *mnt_id, int flags,
|
||||||
|
305, sys_clock_adjtime, clockid_t which_clock, struct timex *tx, , , ,
|
||||||
|
306, sys_syncfs, int fd, , , , ,
|
||||||
|
307, sys_sendmmsg, int fd, struct mmsghdr *mmsg, unsigned int vlen, unsigned int flags, ,
|
||||||
|
308, sys_setns, int fd, int nstype, , , ,
|
||||||
|
309, sys_getcpu, unsigned *cpup, unsigned *nodep, struct getcpu_cache *unused, , ,
|
||||||
|
310, sys_process_vm_readv, pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovec *rvec, unsigned long riovcnt, unsigned long flags
|
||||||
|
311, sys_process_vm_writev, pid_t pid, const struct iovec *lvec, unsigned long liovcnt, const struct iovcc *rvec, unsigned long riovcnt, unsigned long flags
|
||||||
|
312, sys_kcmp, pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2,
|
||||||
|
313, sys_finit_module, int fd, const char __user *uargs, int flags, , ,
|
||||||
|
314, sys_sched_setattr, pid_t pid, struct sched_attr __user *attr, unsigned int flags, , ,
|
||||||
|
315, sys_sched_getattr, pid_t pid, struct sched_attr __user *attr, unsigned int size, unsigned int flags, ,
|
||||||
|
316, sys_renameat2, int olddfd, const char __user *oldname, int newdfd, const char __user *newname, unsigned int flags,
|
||||||
|
317, sys_seccomp, unsigned int op, unsigned int flags, const char __user *uargs, , ,
|
||||||
|
318, sys_getrandom, char __user *buf, size_t count, unsigned int flags, , ,
|
||||||
|
319, sys_memfd_create, const char __user *uname_ptr, unsigned int flags, , , ,
|
||||||
|
320, sys_kexec_file_load, int kernel_fd, int initrd_fd, unsigned long cmdline_len, const char __user *cmdline_ptr, unsigned long flags,
|
||||||
|
321, sys_bpf, int cmd, union bpf_attr *attr, unsigned int size, , ,
|
||||||
|
322, stub_execveat, int dfd, const char __user *filename, const char __user *const __user *argv, const char __user *const __user *envp, int flags,
|
||||||
|
323, userfaultfd, int flags, , , , ,
|
||||||
|
324, membarrier, int cmd, int flags, , , ,
|
||||||
|
325, mlock2, unsigned long start, size_t len, int flags, , ,
|
||||||
|
326, copy_file_range, int fd_in, loff_t __user *off_in, int fd_out, loff_t __user * off_out, size_t len, unsigned int flags
|
||||||
|
327, preadv2, unsigned long fd, const struct iovec __user *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, int flags
|
||||||
|
328, pwritev2, unsigned long fd, const struct iovec __user *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, int flags
|
||||||
|
329, pkey_mprotect, , , , , ,
|
||||||
|
330, pkey_alloc, , , , , ,
|
||||||
|
331, pkey_free, , , , , ,
|
||||||
|
332, statx, , , , , ,
|
||||||
|
333, io_pgetevents, , , , , ,
|
||||||
|
334, rseq, , , , , ,
|
||||||
|
335, pkey_mprotect, , , , , ,
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = convert_csv_to_functions(sample_csv)
|
||||||
|
print(result)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
340
example/core/syscall.nub
Normal file
340
example/core/syscall.nub
Normal file
@@ -0,0 +1,340 @@
|
|||||||
|
namespace sys
|
||||||
|
|
||||||
|
let read: i64 = 0
|
||||||
|
let write: i64 = 1
|
||||||
|
let open: i64 = 2
|
||||||
|
let close: i64 = 3
|
||||||
|
let stat: i64 = 4
|
||||||
|
let fstat: i64 = 5
|
||||||
|
let lstat: i64 = 6
|
||||||
|
let poll: i64 = 7
|
||||||
|
let lseek: i64 = 8
|
||||||
|
let mmap: i64 = 9
|
||||||
|
let mprotect: i64 = 10
|
||||||
|
let munmap: i64 = 11
|
||||||
|
let brk: i64 = 12
|
||||||
|
let rt_sigaction: i64 = 13
|
||||||
|
let rt_sigprocmask: i64 = 14
|
||||||
|
let rt_sigreturn: i64 = 15
|
||||||
|
let ioctl: i64 = 16
|
||||||
|
let pread64: i64 = 17
|
||||||
|
let pwrite64: i64 = 18
|
||||||
|
let readv: i64 = 19
|
||||||
|
let writev: i64 = 20
|
||||||
|
let access: i64 = 21
|
||||||
|
let pipe: i64 = 22
|
||||||
|
let select: i64 = 23
|
||||||
|
let sched_yield: i64 = 24
|
||||||
|
let mremap: i64 = 25
|
||||||
|
let msync: i64 = 26
|
||||||
|
let mincore: i64 = 27
|
||||||
|
let madvise: i64 = 28
|
||||||
|
let shmget: i64 = 29
|
||||||
|
let shmat: i64 = 30
|
||||||
|
let shmctl: i64 = 31
|
||||||
|
let dup: i64 = 32
|
||||||
|
let dup2: i64 = 33
|
||||||
|
let pause: i64 = 34
|
||||||
|
let nanosleep: i64 = 35
|
||||||
|
let getitimer: i64 = 36
|
||||||
|
let alarm: i64 = 37
|
||||||
|
let setitimer: i64 = 38
|
||||||
|
let getpid: i64 = 39
|
||||||
|
let sendfile: i64 = 40
|
||||||
|
let socket: i64 = 41
|
||||||
|
let connect: i64 = 42
|
||||||
|
let accept: i64 = 43
|
||||||
|
let sendto: i64 = 44
|
||||||
|
let recvfrom: i64 = 45
|
||||||
|
let sendmsg: i64 = 46
|
||||||
|
let recvmsg: i64 = 47
|
||||||
|
let shutdown: i64 = 48
|
||||||
|
let bind: i64 = 49
|
||||||
|
let listen: i64 = 50
|
||||||
|
let getsockname: i64 = 51
|
||||||
|
let getpeername: i64 = 52
|
||||||
|
let socketpair: i64 = 53
|
||||||
|
let setsockopt: i64 = 54
|
||||||
|
let getsockopt: i64 = 55
|
||||||
|
let clone: i64 = 56
|
||||||
|
let fork: i64 = 57
|
||||||
|
let vfork: i64 = 58
|
||||||
|
let execve: i64 = 59
|
||||||
|
let exit: i64 = 60
|
||||||
|
let wait4: i64 = 61
|
||||||
|
let kill: i64 = 62
|
||||||
|
let uname: i64 = 63
|
||||||
|
let semget: i64 = 64
|
||||||
|
let semop: i64 = 65
|
||||||
|
let semctl: i64 = 66
|
||||||
|
let shmdt: i64 = 67
|
||||||
|
let msgget: i64 = 68
|
||||||
|
let msgsnd: i64 = 69
|
||||||
|
let msgrcv: i64 = 70
|
||||||
|
let msgctl: i64 = 71
|
||||||
|
let fcntl: i64 = 72
|
||||||
|
let flock: i64 = 73
|
||||||
|
let fsync: i64 = 74
|
||||||
|
let fdatasync: i64 = 75
|
||||||
|
let truncate: i64 = 76
|
||||||
|
let ftruncate: i64 = 77
|
||||||
|
let getdents: i64 = 78
|
||||||
|
let getcwd: i64 = 79
|
||||||
|
let chdir: i64 = 80
|
||||||
|
let fchdir: i64 = 81
|
||||||
|
let rename: i64 = 82
|
||||||
|
let mkdir: i64 = 83
|
||||||
|
let rmdir: i64 = 84
|
||||||
|
let creat: i64 = 85
|
||||||
|
let link: i64 = 86
|
||||||
|
let unlink: i64 = 87
|
||||||
|
let symlink: i64 = 88
|
||||||
|
let readlink: i64 = 89
|
||||||
|
let chmod: i64 = 90
|
||||||
|
let fchmod: i64 = 91
|
||||||
|
let chown: i64 = 92
|
||||||
|
let fchown: i64 = 93
|
||||||
|
let lchown: i64 = 94
|
||||||
|
let umask: i64 = 95
|
||||||
|
let gettimeofday: i64 = 96
|
||||||
|
let getrlimit: i64 = 97
|
||||||
|
let getrusage: i64 = 98
|
||||||
|
let sysinfo: i64 = 99
|
||||||
|
let times: i64 = 100
|
||||||
|
let ptrace: i64 = 101
|
||||||
|
let getuid: i64 = 102
|
||||||
|
let syslog: i64 = 103
|
||||||
|
let getgid: i64 = 104
|
||||||
|
let setuid: i64 = 105
|
||||||
|
let setgid: i64 = 106
|
||||||
|
let geteuid: i64 = 107
|
||||||
|
let getegid: i64 = 108
|
||||||
|
let setpgid: i64 = 109
|
||||||
|
let getppid: i64 = 110
|
||||||
|
let getpgrp: i64 = 111
|
||||||
|
let setsid: i64 = 112
|
||||||
|
let setreuid: i64 = 113
|
||||||
|
let setregid: i64 = 114
|
||||||
|
let getgroups: i64 = 115
|
||||||
|
let setgroups: i64 = 116
|
||||||
|
let setresuid: i64 = 117
|
||||||
|
let getresuid: i64 = 118
|
||||||
|
let setresgid: i64 = 119
|
||||||
|
let getresgid: i64 = 120
|
||||||
|
let getpgid: i64 = 121
|
||||||
|
let setfsuid: i64 = 122
|
||||||
|
let setfsgid: i64 = 123
|
||||||
|
let getsid: i64 = 124
|
||||||
|
let capget: i64 = 125
|
||||||
|
let capset: i64 = 126
|
||||||
|
let rt_sigpending: i64 = 127
|
||||||
|
let rt_sigtimedwait: i64 = 128
|
||||||
|
let rt_sigqueueinfo: i64 = 129
|
||||||
|
let rt_sigsuspend: i64 = 130
|
||||||
|
let sigaltstack: i64 = 131
|
||||||
|
let utime: i64 = 132
|
||||||
|
let mknod: i64 = 133
|
||||||
|
let uselib: i64 = 134
|
||||||
|
let personality: i64 = 135
|
||||||
|
let ustat: i64 = 136
|
||||||
|
let statfs: i64 = 137
|
||||||
|
let fstatfs: i64 = 138
|
||||||
|
let sysfs: i64 = 139
|
||||||
|
let getpriority: i64 = 140
|
||||||
|
let setpriority: i64 = 141
|
||||||
|
let sched_setparam: i64 = 142
|
||||||
|
let sched_getparam: i64 = 143
|
||||||
|
let sched_setscheduler: i64 = 144
|
||||||
|
let sched_getscheduler: i64 = 145
|
||||||
|
let sched_get_priority_max: i64 = 146
|
||||||
|
let sched_get_priority_min: i64 = 147
|
||||||
|
let sched_rr_get_interval: i64 = 148
|
||||||
|
let mlock: i64 = 149
|
||||||
|
let munlock: i64 = 150
|
||||||
|
let mlockall: i64 = 151
|
||||||
|
let munlockall: i64 = 152
|
||||||
|
let vhangup: i64 = 153
|
||||||
|
let modify_ldt: i64 = 154
|
||||||
|
let pivot_root: i64 = 155
|
||||||
|
let _sysctl: i64 = 156
|
||||||
|
let prctl: i64 = 157
|
||||||
|
let arch_prctl: i64 = 158
|
||||||
|
let adjtimex: i64 = 159
|
||||||
|
let setrlimit: i64 = 160
|
||||||
|
let chroot: i64 = 161
|
||||||
|
let sync: i64 = 162
|
||||||
|
let acct: i64 = 163
|
||||||
|
let settimeofday: i64 = 164
|
||||||
|
let mount: i64 = 165
|
||||||
|
let umount2: i64 = 166
|
||||||
|
let swapon: i64 = 167
|
||||||
|
let swapoff: i64 = 168
|
||||||
|
let reboot: i64 = 169
|
||||||
|
let sethostname: i64 = 170
|
||||||
|
let setdomainname: i64 = 171
|
||||||
|
let iopl: i64 = 172
|
||||||
|
let ioperm: i64 = 173
|
||||||
|
let create_module: i64 = 174
|
||||||
|
let init_module: i64 = 175
|
||||||
|
let delete_module: i64 = 176
|
||||||
|
let get_kernel_syms: i64 = 177
|
||||||
|
let query_module: i64 = 178
|
||||||
|
let quotactl: i64 = 179
|
||||||
|
let nfsservctl: i64 = 180
|
||||||
|
let getpmsg: i64 = 181
|
||||||
|
let putpmsg: i64 = 182
|
||||||
|
let afs_syscall: i64 = 183
|
||||||
|
let tuxcall: i64 = 184
|
||||||
|
let security: i64 = 185
|
||||||
|
let gettid: i64 = 186
|
||||||
|
let readahead: i64 = 187
|
||||||
|
let setxattr: i64 = 188
|
||||||
|
let lsetxattr: i64 = 189
|
||||||
|
let fsetxattr: i64 = 190
|
||||||
|
let getxattr: i64 = 191
|
||||||
|
let lgetxattr: i64 = 192
|
||||||
|
let fgetxattr: i64 = 193
|
||||||
|
let listxattr: i64 = 194
|
||||||
|
let llistxattr: i64 = 195
|
||||||
|
let flistxattr: i64 = 196
|
||||||
|
let removexattr: i64 = 197
|
||||||
|
let lremovexattr: i64 = 198
|
||||||
|
let fremovexattr: i64 = 199
|
||||||
|
let tkill: i64 = 200
|
||||||
|
let time: i64 = 201
|
||||||
|
let futex: i64 = 202
|
||||||
|
let sched_setaffinity: i64 = 203
|
||||||
|
let sched_getaffinity: i64 = 204
|
||||||
|
let set_thread_area: i64 = 205
|
||||||
|
let io_setup: i64 = 206
|
||||||
|
let io_destroy: i64 = 207
|
||||||
|
let io_getevents: i64 = 208
|
||||||
|
let io_submit: i64 = 209
|
||||||
|
let io_cancel: i64 = 210
|
||||||
|
let get_thread_area: i64 = 211
|
||||||
|
let lookup_dcookie: i64 = 212
|
||||||
|
let epoll_create: i64 = 213
|
||||||
|
let epoll_ctl_old: i64 = 214
|
||||||
|
let epoll_wait_old: i64 = 215
|
||||||
|
let remap_file_pages: i64 = 216
|
||||||
|
let getdents64: i64 = 217
|
||||||
|
let set_tid_address: i64 = 218
|
||||||
|
let restart_syscall: i64 = 219
|
||||||
|
let semtimedop: i64 = 220
|
||||||
|
let fadvise64: i64 = 221
|
||||||
|
let timer_create: i64 = 222
|
||||||
|
let timer_settime: i64 = 223
|
||||||
|
let timer_gettime: i64 = 224
|
||||||
|
let timer_getoverrun: i64 = 225
|
||||||
|
let timer_delete: i64 = 226
|
||||||
|
let clock_settime: i64 = 227
|
||||||
|
let clock_gettime: i64 = 228
|
||||||
|
let clock_getres: i64 = 229
|
||||||
|
let clock_nanosleep: i64 = 230
|
||||||
|
let exit_group: i64 = 231
|
||||||
|
let epoll_wait: i64 = 232
|
||||||
|
let epoll_ctl: i64 = 233
|
||||||
|
let tgkill: i64 = 234
|
||||||
|
let utimes: i64 = 235
|
||||||
|
let vserver: i64 = 236
|
||||||
|
let mbind: i64 = 237
|
||||||
|
let set_mempolicy: i64 = 238
|
||||||
|
let get_mempolicy: i64 = 239
|
||||||
|
let mq_open: i64 = 240
|
||||||
|
let mq_unlink: i64 = 241
|
||||||
|
let mq_timedsend: i64 = 242
|
||||||
|
let mq_timedreceive: i64 = 243
|
||||||
|
let mq_notify: i64 = 244
|
||||||
|
let mq_getsetattr: i64 = 245
|
||||||
|
let kexec_load: i64 = 246
|
||||||
|
let waitid: i64 = 247
|
||||||
|
let add_key: i64 = 248
|
||||||
|
let request_key: i64 = 249
|
||||||
|
let keyctl: i64 = 250
|
||||||
|
let ioprio_set: i64 = 251
|
||||||
|
let ioprio_get: i64 = 252
|
||||||
|
let inotify_init: i64 = 253
|
||||||
|
let inotify_add_watch: i64 = 254
|
||||||
|
let inotify_rm_watch: i64 = 255
|
||||||
|
let migrate_pages: i64 = 256
|
||||||
|
let openat: i64 = 257
|
||||||
|
let mkdirat: i64 = 258
|
||||||
|
let mknodat: i64 = 259
|
||||||
|
let fchownat: i64 = 260
|
||||||
|
let futimesat: i64 = 261
|
||||||
|
let newfstatat: i64 = 262
|
||||||
|
let unlinkat: i64 = 263
|
||||||
|
let renameat: i64 = 264
|
||||||
|
let linkat: i64 = 265
|
||||||
|
let symlinkat: i64 = 266
|
||||||
|
let readlinkat: i64 = 267
|
||||||
|
let fchmodat: i64 = 268
|
||||||
|
let faccessat: i64 = 269
|
||||||
|
let pselect6: i64 = 270
|
||||||
|
let ppoll: i64 = 271
|
||||||
|
let unshare: i64 = 272
|
||||||
|
let set_robust_list: i64 = 273
|
||||||
|
let get_robust_list: i64 = 274
|
||||||
|
let splice: i64 = 275
|
||||||
|
let tee: i64 = 276
|
||||||
|
let sync_file_range: i64 = 277
|
||||||
|
let vmsplice: i64 = 278
|
||||||
|
let move_pages: i64 = 279
|
||||||
|
let utimensat: i64 = 280
|
||||||
|
let epoll_pwait: i64 = 281
|
||||||
|
let signalfd: i64 = 282
|
||||||
|
let timerfd_create: i64 = 283
|
||||||
|
let eventfd: i64 = 284
|
||||||
|
let fallocate: i64 = 285
|
||||||
|
let timerfd_settime: i64 = 286
|
||||||
|
let timerfd_gettime: i64 = 287
|
||||||
|
let accept4: i64 = 288
|
||||||
|
let signalfd4: i64 = 289
|
||||||
|
let eventfd2: i64 = 290
|
||||||
|
let epoll_create1: i64 = 291
|
||||||
|
let dup3: i64 = 292
|
||||||
|
let pipe2: i64 = 293
|
||||||
|
let inotify_init1: i64 = 294
|
||||||
|
let preadv: i64 = 295
|
||||||
|
let pwritev: i64 = 296
|
||||||
|
let rt_tgsigqueueinfo: i64 = 297
|
||||||
|
let perf_event_open: i64 = 298
|
||||||
|
let recvmmsg: i64 = 299
|
||||||
|
let fanotify_init: i64 = 300
|
||||||
|
let fanotify_mark: i64 = 301
|
||||||
|
let prlimit64: i64 = 302
|
||||||
|
let name_to_handle_at: i64 = 303
|
||||||
|
let open_by_handle_at: i64 = 304
|
||||||
|
let clock_adjtime: i64 = 305
|
||||||
|
let syncfs: i64 = 306
|
||||||
|
let sendmmsg: i64 = 307
|
||||||
|
let setns: i64 = 308
|
||||||
|
let getcpu: i64 = 309
|
||||||
|
let process_vm_readv: i64 = 310
|
||||||
|
let process_vm_writev: i64 = 311
|
||||||
|
let kcmp: i64 = 312
|
||||||
|
let finit_module: i64 = 313
|
||||||
|
let sched_setattr: i64 = 314
|
||||||
|
let sched_getattr: i64 = 315
|
||||||
|
let renameat2: i64 = 316
|
||||||
|
let seccomp: i64 = 317
|
||||||
|
let getrandom: i64 = 318
|
||||||
|
let memfd_create: i64 = 319
|
||||||
|
let kexec_file_load: i64 = 320
|
||||||
|
let bpf: i64 = 321
|
||||||
|
let execveat: i64 = 322
|
||||||
|
let userfaultfd: i64 = 323
|
||||||
|
let membarrier: i64 = 324
|
||||||
|
let mlock2: i64 = 325
|
||||||
|
let copy_file_range: i64 = 326
|
||||||
|
let preadv2: i64 = 327
|
||||||
|
let pwritev2: i64 = 328
|
||||||
|
let pkey_mprotect: i64 = 329
|
||||||
|
let pkey_alloc: i64 = 330
|
||||||
|
let pkey_free: i64 = 331
|
||||||
|
let statx: i64 = 332
|
||||||
|
let io_pgetevents: i64 = 333
|
||||||
|
let rseq: i64 = 334
|
||||||
|
let pkey_mprotect: i64 = 335
|
||||||
|
|
||||||
|
extern func call(num: i64, ...args: any) calls core_syscall
|
||||||
@@ -1,15 +1,5 @@
|
|||||||
namespace main
|
namespace main
|
||||||
|
|
||||||
struct Human {
|
|
||||||
name: string
|
|
||||||
age: i64
|
|
||||||
}
|
|
||||||
|
|
||||||
export func main(args: []^string) {
|
export func main(args: []^string) {
|
||||||
let me = alloc Human {
|
sys::call(60, 0)
|
||||||
name = "oliver"
|
|
||||||
age = 32
|
|
||||||
}
|
|
||||||
|
|
||||||
c::printf("%s is %d years old\n", me.name, me.age)
|
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,6 @@ public class Generator
|
|||||||
private Stack<string> _continueLabels = [];
|
private Stack<string> _continueLabels = [];
|
||||||
private int _variableIndex;
|
private int _variableIndex;
|
||||||
private int _labelIndex;
|
private int _labelIndex;
|
||||||
private int _funcIndex;
|
|
||||||
private bool _codeIsReachable = true;
|
private bool _codeIsReachable = true;
|
||||||
private Dictionary<IFuncSignature, string> _funcNames = [];
|
private Dictionary<IFuncSignature, string> _funcNames = [];
|
||||||
|
|
||||||
@@ -35,7 +34,6 @@ public class Generator
|
|||||||
_breakLabels = [];
|
_breakLabels = [];
|
||||||
_continueLabels = [];
|
_continueLabels = [];
|
||||||
_variableIndex = 0;
|
_variableIndex = 0;
|
||||||
_funcIndex = 0;
|
|
||||||
_labelIndex = 0;
|
_labelIndex = 0;
|
||||||
_codeIsReachable = true;
|
_codeIsReachable = true;
|
||||||
|
|
||||||
@@ -45,12 +43,14 @@ public class Generator
|
|||||||
_builder.AppendLine();
|
_builder.AppendLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var localFuncIndex = 0;
|
||||||
|
|
||||||
foreach (var funcSignature in _sourceFiles.SelectMany(f => f.Definitions).OfType<IFuncSignature>())
|
foreach (var funcSignature in _sourceFiles.SelectMany(f => f.Definitions).OfType<IFuncSignature>())
|
||||||
{
|
{
|
||||||
switch (funcSignature)
|
switch (funcSignature)
|
||||||
{
|
{
|
||||||
case ExternFuncDefinitionNode externFuncDefinitionNode:
|
case ExternFuncDefinitionNode externFuncDefinitionNode:
|
||||||
_funcNames[funcSignature] = "$" + externFuncDefinitionNode.Name;
|
_funcNames[funcSignature] = "$" + externFuncDefinitionNode.CallName;
|
||||||
break;
|
break;
|
||||||
case LocalFuncDefinitionNode localFuncDefinitionNode:
|
case LocalFuncDefinitionNode localFuncDefinitionNode:
|
||||||
if (localFuncDefinitionNode.Exported)
|
if (localFuncDefinitionNode.Exported)
|
||||||
@@ -59,8 +59,7 @@ public class Generator
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var funcName = GenFuncName();
|
_funcNames[funcSignature] = $"$func{++localFuncIndex}";
|
||||||
_funcNames[funcSignature] = funcName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -88,7 +87,6 @@ public class Generator
|
|||||||
|
|
||||||
private enum TypeContext
|
private enum TypeContext
|
||||||
{
|
{
|
||||||
Struct,
|
|
||||||
FuncDef,
|
FuncDef,
|
||||||
FuncCall,
|
FuncCall,
|
||||||
}
|
}
|
||||||
@@ -97,30 +95,6 @@ public class Generator
|
|||||||
{
|
{
|
||||||
return context switch
|
return context switch
|
||||||
{
|
{
|
||||||
TypeContext.Struct => type switch
|
|
||||||
{
|
|
||||||
NubArrayType => "l", // TODO: Arrays in structs are pointers for now
|
|
||||||
NubPointerType => "l",
|
|
||||||
NubPrimitiveType primitiveType => primitiveType.Kind switch
|
|
||||||
{
|
|
||||||
PrimitiveTypeKind.I64 => "l",
|
|
||||||
PrimitiveTypeKind.I32 => "w",
|
|
||||||
PrimitiveTypeKind.I16 => "h",
|
|
||||||
PrimitiveTypeKind.I8 => "b",
|
|
||||||
PrimitiveTypeKind.U64 => "l",
|
|
||||||
PrimitiveTypeKind.U32 => "w",
|
|
||||||
PrimitiveTypeKind.U16 => "h",
|
|
||||||
PrimitiveTypeKind.U8 => "b",
|
|
||||||
PrimitiveTypeKind.F64 => "d",
|
|
||||||
PrimitiveTypeKind.F32 => "s",
|
|
||||||
PrimitiveTypeKind.Bool => "w",
|
|
||||||
PrimitiveTypeKind.String => "l", // TODO: Strings in structs are pointers for now
|
|
||||||
PrimitiveTypeKind.Any => throw new NotSupportedException("any type cannot be used in structs"),
|
|
||||||
_ => throw new ArgumentOutOfRangeException()
|
|
||||||
},
|
|
||||||
NubStructType => throw new NotImplementedException(),
|
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(type))
|
|
||||||
},
|
|
||||||
TypeContext.FuncDef => type switch
|
TypeContext.FuncDef => type switch
|
||||||
{
|
{
|
||||||
NubArrayType => "l",
|
NubArrayType => "l",
|
||||||
@@ -143,6 +117,7 @@ public class Generator
|
|||||||
_ => throw new ArgumentOutOfRangeException()
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
},
|
},
|
||||||
NubStructType structType => $":{structType.Namespace}_{structType.Name}",
|
NubStructType structType => $":{structType.Namespace}_{structType.Name}",
|
||||||
|
NubFixedArrayType => "l",
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(type))
|
_ => throw new ArgumentOutOfRangeException(nameof(type))
|
||||||
},
|
},
|
||||||
TypeContext.FuncCall => type switch
|
TypeContext.FuncCall => type switch
|
||||||
@@ -167,6 +142,7 @@ public class Generator
|
|||||||
_ => throw new ArgumentOutOfRangeException()
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
},
|
},
|
||||||
NubStructType structType => $":{structType.Namespace}_{structType.Name}",
|
NubStructType structType => $":{structType.Namespace}_{structType.Name}",
|
||||||
|
NubFixedArrayType => "l",
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(type))
|
_ => throw new ArgumentOutOfRangeException(nameof(type))
|
||||||
},
|
},
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(context), context, null)
|
_ => throw new ArgumentOutOfRangeException(nameof(context), context, null)
|
||||||
@@ -197,6 +173,7 @@ public class Generator
|
|||||||
_ => throw new ArgumentOutOfRangeException()
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
},
|
},
|
||||||
NubStructType => "l",
|
NubStructType => "l",
|
||||||
|
NubFixedArrayType => "l",
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(type))
|
_ => throw new ArgumentOutOfRangeException(nameof(type))
|
||||||
}}";
|
}}";
|
||||||
}
|
}
|
||||||
@@ -225,6 +202,7 @@ public class Generator
|
|||||||
_ => throw new ArgumentOutOfRangeException()
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
},
|
},
|
||||||
NubStructType => "l",
|
NubStructType => "l",
|
||||||
|
NubFixedArrayType => "l",
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(type))
|
_ => throw new ArgumentOutOfRangeException(nameof(type))
|
||||||
}}";
|
}}";
|
||||||
}
|
}
|
||||||
@@ -253,11 +231,12 @@ public class Generator
|
|||||||
_ => throw new ArgumentOutOfRangeException()
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
},
|
},
|
||||||
NubStructType => "l",
|
NubStructType => "l",
|
||||||
|
NubFixedArrayType => "l",
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(type))
|
_ => throw new ArgumentOutOfRangeException(nameof(type))
|
||||||
}}";
|
}}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private int QbeTypeSize(NubType type)
|
private int SizeOf(NubType type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
@@ -291,16 +270,20 @@ public class Generator
|
|||||||
case NubStructType nubStructType:
|
case NubStructType nubStructType:
|
||||||
{
|
{
|
||||||
var definition = LookupStructDefinition(nubStructType.Namespace, nubStructType.Name);
|
var definition = LookupStructDefinition(nubStructType.Namespace, nubStructType.Name);
|
||||||
return definition.Fields.Sum(f => QbeTypeSize(f.Type));
|
return definition.Fields.Sum(f => SizeOf(f.Type));
|
||||||
}
|
}
|
||||||
case NubPointerType:
|
case NubPointerType:
|
||||||
case NubArrayType:
|
case NubArrayType:
|
||||||
{
|
{
|
||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
|
case NubFixedArrayType nubFixedArrayType:
|
||||||
|
{
|
||||||
|
return SizeOf(nubFixedArrayType.ElementType) * nubFixedArrayType.Capacity;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new UnreachableException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -313,6 +296,7 @@ public class Generator
|
|||||||
NubPointerType => false,
|
NubPointerType => false,
|
||||||
NubPrimitiveType => false,
|
NubPrimitiveType => false,
|
||||||
NubStructType => true,
|
NubStructType => true,
|
||||||
|
NubFixedArrayType => true,
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(type))
|
_ => throw new ArgumentOutOfRangeException(nameof(type))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -368,7 +352,7 @@ public class Generator
|
|||||||
}
|
}
|
||||||
|
|
||||||
var pointerName = GenVarName();
|
var pointerName = GenVarName();
|
||||||
_builder.AppendLine($" {pointerName} {QBEAssign(parameter.Type)} alloc8 {QbeTypeSize(parameter.Type)}");
|
_builder.AppendLine($" {pointerName} {QBEAssign(parameter.Type)} alloc8 {SizeOf(parameter.Type)}");
|
||||||
_builder.AppendLine($" storel %{parameterName}, {pointerName}");
|
_builder.AppendLine($" storel %{parameterName}, {pointerName}");
|
||||||
|
|
||||||
_variables[parameter.Name] = new Variable
|
_variables[parameter.Name] = new Variable
|
||||||
@@ -403,8 +387,42 @@ public class Generator
|
|||||||
|
|
||||||
private void GenerateStructDefinition(StructDefinitionNode structDefinition)
|
private void GenerateStructDefinition(StructDefinitionNode structDefinition)
|
||||||
{
|
{
|
||||||
var fields = structDefinition.Fields.Select(f => QBEType(f.Type, TypeContext.Struct));
|
_builder.Append($"type :{structDefinition.Namespace}_{structDefinition.Name} = {{ ");
|
||||||
_builder.AppendLine($"type :{structDefinition.Name} = {{ {string.Join(", ", fields)} }}");
|
foreach (var structDefinitionField in structDefinition.Fields)
|
||||||
|
{
|
||||||
|
var fieldDefinition = GenerateFieldType(structDefinitionField.Type);
|
||||||
|
_builder.Append(fieldDefinition + ", ");
|
||||||
|
}
|
||||||
|
_builder.AppendLine("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateFieldType(NubType type)
|
||||||
|
{
|
||||||
|
return type switch
|
||||||
|
{
|
||||||
|
NubArrayType => "l",
|
||||||
|
NubPointerType => "l",
|
||||||
|
NubPrimitiveType primitiveType => primitiveType.Kind switch
|
||||||
|
{
|
||||||
|
PrimitiveTypeKind.I64 => "l",
|
||||||
|
PrimitiveTypeKind.I32 => "w",
|
||||||
|
PrimitiveTypeKind.I16 => "h",
|
||||||
|
PrimitiveTypeKind.I8 => "b",
|
||||||
|
PrimitiveTypeKind.U64 => "l",
|
||||||
|
PrimitiveTypeKind.U32 => "w",
|
||||||
|
PrimitiveTypeKind.U16 => "h",
|
||||||
|
PrimitiveTypeKind.U8 => "b",
|
||||||
|
PrimitiveTypeKind.F64 => "d",
|
||||||
|
PrimitiveTypeKind.F32 => "s",
|
||||||
|
PrimitiveTypeKind.Bool => "w",
|
||||||
|
PrimitiveTypeKind.String => "l",
|
||||||
|
PrimitiveTypeKind.Any => throw new NotSupportedException("any type cannot be used in structs"),
|
||||||
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
|
},
|
||||||
|
NubStructType structType => $":{structType.Namespace}_{structType.Name}",
|
||||||
|
NubFixedArrayType fixedArrayType => $"b {SizeOf(fixedArrayType)}",
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(type))
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateStatement(StatementNode statement)
|
private void GenerateStatement(StatementNode statement)
|
||||||
@@ -451,31 +469,59 @@ public class Generator
|
|||||||
|
|
||||||
private void GenerateArrayIndexAssignment(ArrayIndexAssignmentNode arrayIndexAssignment)
|
private void GenerateArrayIndexAssignment(ArrayIndexAssignmentNode arrayIndexAssignment)
|
||||||
{
|
{
|
||||||
var arrayType = (NubArrayType)arrayIndexAssignment.ArrayIndexAccess.Array.Type;
|
|
||||||
|
|
||||||
var array = GenerateExpression(arrayIndexAssignment.ArrayIndexAccess.Array);
|
var array = GenerateExpression(arrayIndexAssignment.ArrayIndexAccess.Array);
|
||||||
var index = GenerateExpression(arrayIndexAssignment.ArrayIndexAccess.Index);
|
var index = GenerateExpression(arrayIndexAssignment.ArrayIndexAccess.Index);
|
||||||
|
|
||||||
GenerateArrayBoundsCheck(array, index);
|
GenerateArrayBoundsCheck(array, index);
|
||||||
|
|
||||||
var value = GenerateExpression(arrayIndexAssignment.Value);
|
var value = GenerateExpression(arrayIndexAssignment.Value);
|
||||||
|
|
||||||
|
switch (arrayIndexAssignment.ArrayIndexAccess.Array.Type)
|
||||||
|
{
|
||||||
|
case NubArrayType arrayType:
|
||||||
|
{
|
||||||
var startName = GenVarName();
|
var startName = GenVarName();
|
||||||
_builder.AppendLine($" {startName} =l add {array}, 8");
|
_builder.AppendLine($" {startName} =l add {array}, 8");
|
||||||
|
|
||||||
var adjustedIndex = GenVarName();
|
var adjustedIndex = GenVarName();
|
||||||
_builder.AppendLine($" {adjustedIndex} =l mul {index}, {QbeTypeSize(arrayType.BaseType)}");
|
_builder.AppendLine($" {adjustedIndex} =l mul {index}, {SizeOf(arrayType.ElementType)}");
|
||||||
|
|
||||||
var offsetName = GenVarName();
|
var offsetName = GenVarName();
|
||||||
_builder.AppendLine($" {offsetName} =l add {startName}, {adjustedIndex}");
|
_builder.AppendLine($" {offsetName} =l add {startName}, {adjustedIndex}");
|
||||||
|
|
||||||
if (IsLargeType(arrayType.BaseType))
|
if (IsLargeType(arrayType.ElementType))
|
||||||
{
|
{
|
||||||
_builder.AppendLine($" blit {value}, {offsetName}, {QbeTypeSize(arrayType.BaseType)}");
|
_builder.AppendLine($" blit {value}, {offsetName}, {SizeOf(arrayType.ElementType)}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_builder.AppendLine($" {QBEStore(arrayType.BaseType)} {value}, {offsetName}");
|
_builder.AppendLine($" {QBEStore(arrayType.ElementType)} {value}, {offsetName}");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NubFixedArrayType fixedArrayType:
|
||||||
|
{
|
||||||
|
var startName = GenVarName();
|
||||||
|
_builder.AppendLine($" {startName} =l add {array}, 8");
|
||||||
|
|
||||||
|
var adjustedIndex = GenVarName();
|
||||||
|
_builder.AppendLine($" {adjustedIndex} =l mul {index}, {SizeOf(fixedArrayType.ElementType)}");
|
||||||
|
|
||||||
|
var offsetName = GenVarName();
|
||||||
|
_builder.AppendLine($" {offsetName} =l add {startName}, {adjustedIndex}");
|
||||||
|
|
||||||
|
if (IsLargeType(fixedArrayType.ElementType))
|
||||||
|
{
|
||||||
|
_builder.AppendLine($" blit {value}, {offsetName}, {SizeOf(fixedArrayType.ElementType)}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_builder.AppendLine($" {QBEStore(fixedArrayType.ElementType)} {value}, {offsetName}");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
throw new UnreachableException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,7 +554,7 @@ public class Generator
|
|||||||
|
|
||||||
if (IsLargeType(dereferenceAssignment.Value.Type))
|
if (IsLargeType(dereferenceAssignment.Value.Type))
|
||||||
{
|
{
|
||||||
_builder.AppendLine($" blit {value}, {location}, {QbeTypeSize(dereferenceAssignment.Value.Type)}");
|
_builder.AppendLine($" blit {value}, {location}, {SizeOf(dereferenceAssignment.Value.Type)}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -555,7 +601,14 @@ public class Generator
|
|||||||
|
|
||||||
var value = GenerateExpression(memberAssignment.Value);
|
var value = GenerateExpression(memberAssignment.Value);
|
||||||
|
|
||||||
throw new NotImplementedException();
|
if (IsLargeType(memberAssignment.Value.Type))
|
||||||
|
{
|
||||||
|
_builder.AppendLine($" blit {value}, {offsetName}, {SizeOf(memberAssignment.Value.Type)}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_builder.AppendLine($" {QBEStore(memberAssignment.Value.Type)} {value}, {offsetName}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateReturn(ReturnNode @return)
|
private void GenerateReturn(ReturnNode @return)
|
||||||
@@ -579,30 +632,31 @@ public class Generator
|
|||||||
|
|
||||||
private void GenerateVariableDeclaration(VariableDeclarationNode variableDeclaration)
|
private void GenerateVariableDeclaration(VariableDeclarationNode variableDeclaration)
|
||||||
{
|
{
|
||||||
var pointerName = GenVarName();
|
|
||||||
|
|
||||||
var type = variableDeclaration.ExplicitType.Value ?? variableDeclaration.Value.Value?.Type!;
|
var type = variableDeclaration.ExplicitType.Value ?? variableDeclaration.Value.Value?.Type!;
|
||||||
|
|
||||||
_builder.AppendLine($" {pointerName} {QBEAssign(type)} alloc8 {QbeTypeSize(type)}");
|
string pointerName;
|
||||||
|
|
||||||
if (variableDeclaration.Value.HasValue)
|
if (variableDeclaration.Value.HasValue)
|
||||||
{
|
{
|
||||||
var result = GenerateExpression(variableDeclaration.Value.Value);
|
var result = GenerateExpression(variableDeclaration.Value.Value);
|
||||||
|
|
||||||
if (IsLargeType(type))
|
if (IsLargeType(type))
|
||||||
{
|
{
|
||||||
_builder.AppendLine($" blit {result}, {pointerName}, {QbeTypeSize(type)}");
|
pointerName = result;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
pointerName = GenVarName();
|
||||||
|
_builder.AppendLine($" {pointerName} {QBEAssign(type)} alloc8 {SizeOf(type)}");
|
||||||
_builder.AppendLine($" {QBEStore(type)} {result}, {pointerName}");
|
_builder.AppendLine($" {QBEStore(type)} {result}, {pointerName}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
pointerName = GenVarName();
|
||||||
|
_builder.AppendLine($" {pointerName} {QBEAssign(type)} alloc8 {SizeOf(type)}");
|
||||||
if (IsLargeType(type))
|
if (IsLargeType(type))
|
||||||
{
|
{
|
||||||
_builder.AppendLine($" blit 0, {pointerName}, {QbeTypeSize(type)}");
|
_builder.AppendLine($" call $nub_memset(l {pointerName}, ub 0, l {SizeOf(type)})");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -648,6 +702,7 @@ public class Generator
|
|||||||
BinaryExpressionNode binaryExpression => GenerateBinaryExpression(binaryExpression),
|
BinaryExpressionNode binaryExpression => GenerateBinaryExpression(binaryExpression),
|
||||||
CastNode cast => GenerateCast(cast),
|
CastNode cast => GenerateCast(cast),
|
||||||
DereferenceNode dereference => GenerateDereference(dereference),
|
DereferenceNode dereference => GenerateDereference(dereference),
|
||||||
|
FixedArrayInitializerNode fixedArrayInitializer => GenerateFixedArrayInitializer(fixedArrayInitializer),
|
||||||
FuncCallNode funcCallExpression => GenerateFuncCall(funcCallExpression),
|
FuncCallNode funcCallExpression => GenerateFuncCall(funcCallExpression),
|
||||||
IdentifierNode identifier => GenerateIdentifier(identifier),
|
IdentifierNode identifier => GenerateIdentifier(identifier),
|
||||||
LiteralNode literal => GenerateLiteral(literal),
|
LiteralNode literal => GenerateLiteral(literal),
|
||||||
@@ -660,31 +715,58 @@ public class Generator
|
|||||||
|
|
||||||
private string GenerateArrayIndex(ArrayIndexAccessNode arrayIndexAccess)
|
private string GenerateArrayIndex(ArrayIndexAccessNode arrayIndexAccess)
|
||||||
{
|
{
|
||||||
var arrayType = ((NubArrayType)arrayIndexAccess.Array.Type).BaseType;
|
|
||||||
|
|
||||||
var array = GenerateExpression(arrayIndexAccess.Array);
|
var array = GenerateExpression(arrayIndexAccess.Array);
|
||||||
var index = GenerateExpression(arrayIndexAccess.Index);
|
var index = GenerateExpression(arrayIndexAccess.Index);
|
||||||
|
|
||||||
GenerateArrayBoundsCheck(array, index);
|
GenerateArrayBoundsCheck(array, index);
|
||||||
|
|
||||||
|
switch (arrayIndexAccess.Array.Type)
|
||||||
|
{
|
||||||
|
case NubArrayType arrayType:
|
||||||
|
{
|
||||||
var firstItemPointerName = GenVarName();
|
var firstItemPointerName = GenVarName();
|
||||||
_builder.AppendLine($" {firstItemPointerName} =l add {array}, 8");
|
_builder.AppendLine($" {firstItemPointerName} =l add {array}, 8");
|
||||||
var offsetPointerName = GenVarName();
|
var offsetPointerName = GenVarName();
|
||||||
_builder.AppendLine($" {offsetPointerName} =l mul {index}, {QbeTypeSize(arrayType)}");
|
_builder.AppendLine($" {offsetPointerName} =l mul {index}, {SizeOf(arrayType.ElementType)}");
|
||||||
var resultPointerName = GenVarName();
|
var resultPointerName = GenVarName();
|
||||||
_builder.AppendLine($" {resultPointerName} =l add {firstItemPointerName}, {offsetPointerName}");
|
_builder.AppendLine($" {resultPointerName} =l add {firstItemPointerName}, {offsetPointerName}");
|
||||||
|
|
||||||
if (IsLargeType(arrayType))
|
if (IsLargeType(arrayType.ElementType))
|
||||||
{
|
{
|
||||||
return resultPointerName;
|
return resultPointerName;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var outputName = GenVarName();
|
var outputName = GenVarName();
|
||||||
_builder.AppendLine($" {outputName} {QBEAssign(arrayType)} {QBELoad(arrayType)} {resultPointerName}");
|
_builder.AppendLine($" {outputName} {QBEAssign(arrayType.ElementType)} {QBELoad(arrayType.ElementType)} {resultPointerName}");
|
||||||
return outputName;
|
return outputName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case NubFixedArrayType fixedArrayType:
|
||||||
|
{
|
||||||
|
var firstItemPointerName = GenVarName();
|
||||||
|
_builder.AppendLine($" {firstItemPointerName} =l add {array}, 8");
|
||||||
|
var offsetPointerName = GenVarName();
|
||||||
|
_builder.AppendLine($" {offsetPointerName} =l mul {index}, {SizeOf(fixedArrayType.ElementType)}");
|
||||||
|
var resultPointerName = GenVarName();
|
||||||
|
_builder.AppendLine($" {resultPointerName} =l add {firstItemPointerName}, {offsetPointerName}");
|
||||||
|
|
||||||
|
if (IsLargeType(fixedArrayType.ElementType))
|
||||||
|
{
|
||||||
|
return resultPointerName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var outputName = GenVarName();
|
||||||
|
_builder.AppendLine($" {outputName} {QBEAssign(fixedArrayType.ElementType)} {QBELoad(fixedArrayType.ElementType)} {resultPointerName}");
|
||||||
|
return outputName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
throw new UnreachableException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void GenerateArrayBoundsCheck(string array, string index)
|
private void GenerateArrayBoundsCheck(string array, string index)
|
||||||
{
|
{
|
||||||
@@ -714,7 +796,7 @@ public class Generator
|
|||||||
{
|
{
|
||||||
var capacity = GenerateExpression(arrayInitializer.Capacity);
|
var capacity = GenerateExpression(arrayInitializer.Capacity);
|
||||||
var capacityInBytes = GenVarName();
|
var capacityInBytes = GenVarName();
|
||||||
_builder.AppendLine($" {capacityInBytes} =l mul {capacity}, {QbeTypeSize(arrayInitializer.ElementType)}");
|
_builder.AppendLine($" {capacityInBytes} =l mul {capacity}, {SizeOf(arrayInitializer.ElementType)}");
|
||||||
var totalArraySize = GenVarName();
|
var totalArraySize = GenVarName();
|
||||||
_builder.AppendLine($" {totalArraySize} =l add {capacityInBytes}, 8");
|
_builder.AppendLine($" {totalArraySize} =l add {capacityInBytes}, 8");
|
||||||
var outputName = GenVarName();
|
var outputName = GenVarName();
|
||||||
@@ -1483,7 +1565,7 @@ public class Generator
|
|||||||
var structDefinition = LookupStructDefinition(structInitializer.StructType.Namespace, structInitializer.StructType.Name);
|
var structDefinition = LookupStructDefinition(structInitializer.StructType.Namespace, structInitializer.StructType.Name);
|
||||||
|
|
||||||
var structVar = GenVarName();
|
var structVar = GenVarName();
|
||||||
var size = structDefinition.Fields.Sum(x => QbeTypeSize(x.Type));
|
var size = structDefinition.Fields.Sum(x => SizeOf(x.Type));
|
||||||
_builder.AppendLine($" {structVar} =l alloc8 {size}");
|
_builder.AppendLine($" {structVar} =l alloc8 {size}");
|
||||||
|
|
||||||
foreach (var field in structDefinition.Fields)
|
foreach (var field in structDefinition.Fields)
|
||||||
@@ -1498,7 +1580,7 @@ public class Generator
|
|||||||
|
|
||||||
if (IsLargeType(field.Type))
|
if (IsLargeType(field.Type))
|
||||||
{
|
{
|
||||||
_builder.AppendLine($" blit {var}, {offsetName}, {QbeTypeSize(field.Type)}");
|
_builder.AppendLine($" blit {var}, {offsetName}, {SizeOf(field.Type)}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1513,7 +1595,7 @@ public class Generator
|
|||||||
|
|
||||||
if (IsLargeType(field.Type))
|
if (IsLargeType(field.Type))
|
||||||
{
|
{
|
||||||
_builder.AppendLine($" blit {var}, {offsetName}, {QbeTypeSize(field.Type)}");
|
_builder.AppendLine($" blit {var}, {offsetName}, {SizeOf(field.Type)}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1620,6 +1702,20 @@ public class Generator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GenerateFixedArrayInitializer(FixedArrayInitializerNode fixedArrayInitializer)
|
||||||
|
{
|
||||||
|
var capacityInBytes = SizeOf(fixedArrayInitializer.Type);
|
||||||
|
var outputName = GenVarName();
|
||||||
|
_builder.AppendLine($" {outputName} =l alloc8 {capacityInBytes + 8}");
|
||||||
|
_builder.AppendLine($" storel {fixedArrayInitializer.Capacity}, {outputName}");
|
||||||
|
|
||||||
|
var dataPtr = GenVarName();
|
||||||
|
_builder.AppendLine($" {dataPtr} =l add {outputName}, 8");
|
||||||
|
_builder.AppendLine($" call $nub_memset(l {dataPtr}, w 0, l {capacityInBytes})");
|
||||||
|
|
||||||
|
return outputName;
|
||||||
|
}
|
||||||
|
|
||||||
private string GenerateFuncCall(FuncCallNode funcCall)
|
private string GenerateFuncCall(FuncCallNode funcCall)
|
||||||
{
|
{
|
||||||
var funcDefinition = LookupFuncSignature(funcCall.Namespace, funcCall.Name, funcCall.Parameters.Select(p => p.Type).ToList());
|
var funcDefinition = LookupFuncSignature(funcCall.Namespace, funcCall.Name, funcCall.Parameters.Select(p => p.Type).ToList());
|
||||||
@@ -1664,11 +1760,6 @@ public class Generator
|
|||||||
return $"%v{++_variableIndex}";
|
return $"%v{++_variableIndex}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GenFuncName()
|
|
||||||
{
|
|
||||||
return $"$f{++_funcIndex}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GenLabelName()
|
private string GenLabelName()
|
||||||
{
|
{
|
||||||
return $"@l{++_labelIndex}";
|
return $"@l{++_labelIndex}";
|
||||||
@@ -1694,7 +1785,7 @@ public class Generator
|
|||||||
|
|
||||||
private int LookupMemberOffset(StructDefinitionNode structDefinition, string member)
|
private int LookupMemberOffset(StructDefinitionNode structDefinition, string member)
|
||||||
{
|
{
|
||||||
return structDefinition.Fields.TakeWhile(f => f.Name != member).Sum(f => QbeTypeSize(f.Type));
|
return structDefinition.Fields.TakeWhile(f => f.Name != member).Sum(f => SizeOf(f.Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Variable
|
private class Variable
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ public class Lexer
|
|||||||
["alloc"] = Symbol.Alloc,
|
["alloc"] = Symbol.Alloc,
|
||||||
["struct"] = Symbol.Struct,
|
["struct"] = Symbol.Struct,
|
||||||
["let"] = Symbol.Let,
|
["let"] = Symbol.Let,
|
||||||
|
["calls"] = Symbol.Calls,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly Dictionary<string, Modifier> Modifiers = new()
|
private static readonly Dictionary<string, Modifier> Modifiers = new()
|
||||||
|
|||||||
@@ -42,5 +42,6 @@ public enum Symbol
|
|||||||
DoubleColon,
|
DoubleColon,
|
||||||
Namespace,
|
Namespace,
|
||||||
Let,
|
Let,
|
||||||
Alloc
|
Alloc,
|
||||||
|
Calls
|
||||||
}
|
}
|
||||||
@@ -16,6 +16,7 @@ public class FuncParameter(string name, NubType type, bool variadic)
|
|||||||
public interface IFuncSignature
|
public interface IFuncSignature
|
||||||
{
|
{
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
public string Namespace { get; }
|
||||||
public List<FuncParameter> Parameters { get; }
|
public List<FuncParameter> Parameters { get; }
|
||||||
public Optional<NubType> ReturnType { get; }
|
public Optional<NubType> ReturnType { get; }
|
||||||
|
|
||||||
@@ -53,9 +54,10 @@ public interface IFuncSignature
|
|||||||
public string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){(ReturnType.HasValue ? ": " + ReturnType.Value : "")}";
|
public string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){(ReturnType.HasValue ? ": " + ReturnType.Value : "")}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LocalFuncDefinitionNode(IReadOnlyList<Token> tokens, Optional<string> documentation, string name, List<FuncParameter> parameters, BlockNode body, Optional<NubType> returnType, bool exported) : DefinitionNode(tokens, documentation), IFuncSignature
|
public class LocalFuncDefinitionNode(IReadOnlyList<Token> tokens, Optional<string> documentation, string name, string @namespace, List<FuncParameter> parameters, BlockNode body, Optional<NubType> returnType, bool exported) : DefinitionNode(tokens, documentation), IFuncSignature
|
||||||
{
|
{
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
|
public string Namespace { get; } = @namespace;
|
||||||
public List<FuncParameter> Parameters { get; } = parameters;
|
public List<FuncParameter> Parameters { get; } = parameters;
|
||||||
public BlockNode Body { get; } = body;
|
public BlockNode Body { get; } = body;
|
||||||
public Optional<NubType> ReturnType { get; } = returnType;
|
public Optional<NubType> ReturnType { get; } = returnType;
|
||||||
@@ -64,9 +66,11 @@ public class LocalFuncDefinitionNode(IReadOnlyList<Token> tokens, Optional<strin
|
|||||||
public override string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){(ReturnType.HasValue ? ": " + ReturnType.Value : "")}";
|
public override string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){(ReturnType.HasValue ? ": " + ReturnType.Value : "")}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ExternFuncDefinitionNode(IReadOnlyList<Token> tokens, Optional<string> documentation, string name, List<FuncParameter> parameters, Optional<NubType> returnType) : DefinitionNode(tokens, documentation), IFuncSignature
|
public class ExternFuncDefinitionNode(IReadOnlyList<Token> tokens, Optional<string> documentation, string name, string @namespace, string callName, List<FuncParameter> parameters, Optional<NubType> returnType) : DefinitionNode(tokens, documentation), IFuncSignature
|
||||||
{
|
{
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
|
public string Namespace { get; } = @namespace;
|
||||||
|
public string CallName { get; } = callName;
|
||||||
public List<FuncParameter> Parameters { get; } = parameters;
|
public List<FuncParameter> Parameters { get; } = parameters;
|
||||||
public Optional<NubType> ReturnType { get; } = returnType;
|
public Optional<NubType> ReturnType { get; } = returnType;
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ public class StructField(string name, NubType type, Optional<ExpressionNode> val
|
|||||||
public Optional<ExpressionNode> Value { get; } = value;
|
public Optional<ExpressionNode> Value { get; } = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class StructDefinitionNode(IReadOnlyList<Token> tokens, Optional<string> documentation, string name, List<StructField> fields) : DefinitionNode(tokens, documentation)
|
public class StructDefinitionNode(IReadOnlyList<Token> tokens, Optional<string> documentation, string name, string @namespace, List<StructField> fields) : DefinitionNode(tokens, documentation)
|
||||||
{
|
{
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
|
public string Namespace { get; } = @namespace;
|
||||||
public List<StructField> Fields { get; } = fields;
|
public List<StructField> Fields { get; } = fields;
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Nub.Lang.Diagnostics;
|
using Nub.Lang.Diagnostics;
|
||||||
using Nub.Lang.Frontend.Lexing;
|
using Nub.Lang.Frontend.Lexing;
|
||||||
using Nub.Lang.Frontend.Parsing.Definitions;
|
using Nub.Lang.Frontend.Parsing.Definitions;
|
||||||
@@ -116,7 +117,14 @@ public class Parser
|
|||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ExternFuncDefinitionNode(GetTokensForNode(startIndex), documentation, name.Value, parameters, returnType);
|
var callName = name.Value;
|
||||||
|
|
||||||
|
if (TryExpectSymbol(Symbol.Calls))
|
||||||
|
{
|
||||||
|
callName = ExpectIdentifier().Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ExternFuncDefinitionNode(GetTokensForNode(startIndex), documentation, name.Value, _namespace, callName, parameters, returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
var body = ParseBlock();
|
var body = ParseBlock();
|
||||||
@@ -131,7 +139,7 @@ public class Parser
|
|||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LocalFuncDefinitionNode(GetTokensForNode(startIndex), documentation, name.Value, parameters, body, returnType, exported);
|
return new LocalFuncDefinitionNode(GetTokensForNode(startIndex), documentation, name.Value, _namespace, parameters, body, returnType, exported);
|
||||||
}
|
}
|
||||||
|
|
||||||
private StructDefinitionNode ParseStruct(int startIndex, List<ModifierToken> _, Optional<string> documentation)
|
private StructDefinitionNode ParseStruct(int startIndex, List<ModifierToken> _, Optional<string> documentation)
|
||||||
@@ -158,7 +166,7 @@ public class Parser
|
|||||||
variables.Add(new StructField(variableName, variableType, variableValue));
|
variables.Add(new StructField(variableName, variableType, variableValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new StructDefinitionNode(GetTokensForNode(startIndex), documentation, name, variables);
|
return new StructDefinitionNode(GetTokensForNode(startIndex), documentation, name, _namespace, variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FuncParameter ParseFuncParameter()
|
private FuncParameter ParseFuncParameter()
|
||||||
@@ -520,12 +528,36 @@ public class Parser
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Symbol.OpenBracket:
|
case Symbol.OpenBracket:
|
||||||
|
{
|
||||||
|
if (Peek().TryGetValue(out var capacityToken) && capacityToken is LiteralToken { Type: NubPrimitiveType { Kind: PrimitiveTypeKind.I64 } } literalToken)
|
||||||
|
{
|
||||||
|
var capacity = int.Parse(literalToken.Value);
|
||||||
|
Next();
|
||||||
|
ExpectSymbol(Symbol.CloseBracket);
|
||||||
|
var elementType = ParseType();
|
||||||
|
|
||||||
|
if (capacity > 0)
|
||||||
|
{
|
||||||
|
expr = new FixedArrayInitializerNode(GetTokensForNode(startIndex), elementType, capacity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ParseException(Diagnostic
|
||||||
|
.Error("Fixed array size must be a positive integer")
|
||||||
|
.WithHelp("Use a positive integer literal for the array size")
|
||||||
|
.At(literalToken)
|
||||||
|
.Build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
var capacity = ParseExpression();
|
var capacity = ParseExpression();
|
||||||
ExpectSymbol(Symbol.CloseBracket);
|
ExpectSymbol(Symbol.CloseBracket);
|
||||||
var type = ParseType();
|
var type = ParseType();
|
||||||
|
|
||||||
expr = new ArrayInitializerNode(GetTokensForNode(startIndex), capacity, type);
|
expr = new ArrayInitializerNode(GetTokensForNode(startIndex), capacity, type);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Symbol.Alloc:
|
case Symbol.Alloc:
|
||||||
@@ -656,13 +688,33 @@ public class Parser
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.OpenBracket))
|
if (TryExpectSymbol(Symbol.OpenBracket))
|
||||||
|
{
|
||||||
|
if (Peek().TryGetValue(out var token) && token is LiteralToken { Type: NubPrimitiveType { Kind: PrimitiveTypeKind.I64 }, Value: var sizeValue })
|
||||||
|
{
|
||||||
|
Next();
|
||||||
|
ExpectSymbol(Symbol.CloseBracket);
|
||||||
|
var baseType = ParseType();
|
||||||
|
|
||||||
|
var size = int.Parse(sizeValue);
|
||||||
|
|
||||||
|
if (size > 0)
|
||||||
|
{
|
||||||
|
return new NubFixedArrayType(baseType, size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new UnreachableException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ExpectSymbol(Symbol.CloseBracket);
|
ExpectSymbol(Symbol.CloseBracket);
|
||||||
var baseType = ParseType();
|
var baseType = ParseType();
|
||||||
return new NubArrayType(baseType);
|
return new NubArrayType(baseType);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!Peek().TryGetValue(out var token))
|
if (!Peek().TryGetValue(out var peekToken))
|
||||||
{
|
{
|
||||||
throw new ParseException(Diagnostic
|
throw new ParseException(Diagnostic
|
||||||
.Error("Unexpected end of file while parsing type")
|
.Error("Unexpected end of file while parsing type")
|
||||||
@@ -674,9 +726,9 @@ public class Parser
|
|||||||
throw new ParseException(Diagnostic
|
throw new ParseException(Diagnostic
|
||||||
.Error("Invalid type syntax")
|
.Error("Invalid type syntax")
|
||||||
.WithHelp("Expected type name, '^' for pointer, or '[]' for array")
|
.WithHelp("Expected type name, '^' for pointer, or '[]' for array")
|
||||||
.At(token)
|
.At(peekToken)
|
||||||
.Build());
|
.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Token ExpectToken()
|
private Token ExpectToken()
|
||||||
{
|
{
|
||||||
@@ -803,9 +855,9 @@ public class Parser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<Token> Peek()
|
private Optional<Token> Peek(int offset = 0)
|
||||||
{
|
{
|
||||||
var peekIndex = _index;
|
var peekIndex = _index + offset;
|
||||||
while (peekIndex < _tokens.Count && _tokens[peekIndex] is DocumentationToken)
|
while (peekIndex < _tokens.Count && _tokens[peekIndex] is DocumentationToken)
|
||||||
{
|
{
|
||||||
peekIndex++;
|
peekIndex++;
|
||||||
|
|||||||
@@ -6,7 +6,22 @@ public abstract class NubType
|
|||||||
{
|
{
|
||||||
public static bool IsCompatibleWith(NubType sourceType, NubType targetType)
|
public static bool IsCompatibleWith(NubType sourceType, NubType targetType)
|
||||||
{
|
{
|
||||||
return targetType.Equals(NubPrimitiveType.Any) || sourceType.Equals(targetType);
|
if (targetType.Equals(NubPrimitiveType.Any) || sourceType.Equals(targetType))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceType is NubFixedArrayType fixedArray && targetType is NubArrayType array && IsCompatibleWith(fixedArray.ElementType, array.ElementType))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceType.Equals(NubPrimitiveType.String) && targetType is NubArrayType arrayType && IsCompatibleWith(NubPrimitiveType.U8, arrayType.ElementType))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract override bool Equals(object? obj);
|
public abstract override bool Equals(object? obj);
|
||||||
@@ -55,27 +70,45 @@ public class NubPointerType(NubType baseType) : NubType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NubArrayType(NubType baseType) : NubType
|
public class NubArrayType(NubType elementType) : NubType
|
||||||
{
|
{
|
||||||
public NubType BaseType { get; } = baseType;
|
public NubType ElementType { get; } = elementType;
|
||||||
|
|
||||||
public override bool Equals(object? obj)
|
public override bool Equals(object? obj)
|
||||||
{
|
{
|
||||||
if (obj is NubArrayType other)
|
if (obj is NubArrayType other)
|
||||||
{
|
{
|
||||||
return BaseType.Equals(other.BaseType);
|
return ElementType.Equals(other.ElementType);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return HashCode.Combine(BaseType);
|
return HashCode.Combine(ElementType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return "[]" + BaseType;
|
return "[]" + ElementType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NubFixedArrayType(NubType elementType, int capacity) : NubType
|
||||||
|
{
|
||||||
|
public NubType ElementType { get; } = elementType;
|
||||||
|
public int Capacity { get; } = capacity;
|
||||||
|
|
||||||
|
public override string ToString() => $"[{Capacity}]{ElementType}";
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
return obj is NubFixedArrayType other && ElementType.Equals(other.ElementType) && Capacity == other.Capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(ElementType, Capacity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
using Nub.Lang.Diagnostics;
|
using Nub.Lang.Diagnostics;
|
||||||
using Nub.Lang.Frontend.Parsing;
|
using Nub.Lang.Frontend.Parsing;
|
||||||
using Nub.Lang.Frontend.Parsing.Definitions;
|
using Nub.Lang.Frontend.Parsing.Definitions;
|
||||||
@@ -245,6 +246,11 @@ public class TypeChecker
|
|||||||
return nubPointerType.BaseType;
|
return nubPointerType.BaseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private NubType TypeCheckFixedInitializerArray(FixedArrayInitializerNode fixedArrayInitializer)
|
||||||
|
{
|
||||||
|
return new NubFixedArrayType(fixedArrayInitializer.ElementType, fixedArrayInitializer.Capacity);
|
||||||
|
}
|
||||||
|
|
||||||
private NubType? TypeCheckFuncCall(FuncCallNode funcCall, Node node)
|
private NubType? TypeCheckFuncCall(FuncCallNode funcCall, Node node)
|
||||||
{
|
{
|
||||||
List<NubType> parameterTypes = [];
|
List<NubType> parameterTypes = [];
|
||||||
@@ -375,11 +381,12 @@ public class TypeChecker
|
|||||||
BinaryExpressionNode binaryExpr => TypeCheckBinaryExpression(binaryExpr),
|
BinaryExpressionNode binaryExpr => TypeCheckBinaryExpression(binaryExpr),
|
||||||
CastNode cast => TypeCheckCast(cast),
|
CastNode cast => TypeCheckCast(cast),
|
||||||
DereferenceNode dereference => TypeCheckDereference(dereference),
|
DereferenceNode dereference => TypeCheckDereference(dereference),
|
||||||
|
FixedArrayInitializerNode fixedArray => TypeCheckFixedInitializerArray(fixedArray),
|
||||||
FuncCallNode funcCallExpr => TypeCheckFuncCall(funcCallExpr, funcCallExpr),
|
FuncCallNode funcCallExpr => TypeCheckFuncCall(funcCallExpr, funcCallExpr),
|
||||||
StructInitializerNode structInit => TypeCheckStructInitializer(structInit),
|
StructInitializerNode structInit => TypeCheckStructInitializer(structInit),
|
||||||
UnaryExpressionNode unaryExpression => TypeCheckUnaryExpression(unaryExpression),
|
UnaryExpressionNode unaryExpression => TypeCheckUnaryExpression(unaryExpression),
|
||||||
MemberAccessNode memberAccess => TypeCheckMemberAccess(memberAccess),
|
MemberAccessNode memberAccess => TypeCheckMemberAccess(memberAccess),
|
||||||
_ => ReportUnsupportedExpression(expression)
|
_ => throw new UnreachableException()
|
||||||
};
|
};
|
||||||
|
|
||||||
if (resultType != null)
|
if (resultType != null)
|
||||||
@@ -390,30 +397,28 @@ public class TypeChecker
|
|||||||
return resultType;
|
return resultType;
|
||||||
}
|
}
|
||||||
|
|
||||||
private NubType? ReportUnsupportedExpression(ExpressionNode expression)
|
|
||||||
{
|
|
||||||
ReportError($"Unsupported expression type: {expression.GetType().Name}", expression);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private NubType? TypeCheckArrayIndex(ArrayIndexAccessNode arrayIndexAccess)
|
private NubType? TypeCheckArrayIndex(ArrayIndexAccessNode arrayIndexAccess)
|
||||||
{
|
{
|
||||||
var expressionType = TypeCheckExpression(arrayIndexAccess.Array);
|
var expressionType = TypeCheckExpression(arrayIndexAccess.Array);
|
||||||
if (expressionType == null) return null;
|
if (expressionType == null) return null;
|
||||||
|
|
||||||
if (expressionType is not NubArrayType arrayType)
|
|
||||||
{
|
|
||||||
ReportError($"Cannot access index of non-array type {expressionType}", arrayIndexAccess.Array);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var indexType = TypeCheckExpression(arrayIndexAccess.Index);
|
var indexType = TypeCheckExpression(arrayIndexAccess.Index);
|
||||||
if (indexType != null && !IsInteger(indexType))
|
if (indexType != null && !IsInteger(indexType))
|
||||||
{
|
{
|
||||||
ReportError("Array index type must be an integer", arrayIndexAccess.Index);
|
ReportError("Array index type must be an integer", arrayIndexAccess.Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
return arrayType.BaseType;
|
if (expressionType is NubArrayType arrayType)
|
||||||
|
{
|
||||||
|
return arrayType.ElementType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expressionType is NubFixedArrayType fixedArrayType)
|
||||||
|
{
|
||||||
|
return fixedArrayType.ElementType;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReportError($"Cannot access index of non-array type {expressionType}", arrayIndexAccess.Array);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private NubType TypeCheckArrayInitializer(ArrayInitializerNode arrayInitializer)
|
private NubType TypeCheckArrayInitializer(ArrayInitializerNode arrayInitializer)
|
||||||
|
|||||||
9
src/runtime/core/syscall.asm
Normal file
9
src/runtime/core/syscall.asm
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
section .text
|
||||||
|
global core_syscall
|
||||||
|
core_syscall:
|
||||||
|
mov rax, rdi
|
||||||
|
mov rdi, rsi
|
||||||
|
mov rsi, rdx
|
||||||
|
mov r10, rcx
|
||||||
|
syscall
|
||||||
|
ret
|
||||||
@@ -9,6 +9,9 @@ _start:
|
|||||||
mov rax, 60
|
mov rax, 60
|
||||||
syscall
|
syscall
|
||||||
|
|
||||||
|
; String comparison function null-terminated strings
|
||||||
|
; Arguments: rdi = lhs (*char), rsi = rhs (*char)
|
||||||
|
; Returns: 1 if equal, else 0
|
||||||
global nub_strcmp
|
global nub_strcmp
|
||||||
nub_strcmp:
|
nub_strcmp:
|
||||||
xor rdx, rdx
|
xor rdx, rdx
|
||||||
@@ -28,6 +31,9 @@ nub_strcmp:
|
|||||||
mov rax, 1
|
mov rax, 1
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
; Panic function with message
|
||||||
|
; Arguments: rdi = message (*char), rsi = message length (long)
|
||||||
|
; Remarks: exits the program
|
||||||
global nub_panic
|
global nub_panic
|
||||||
nub_panic:
|
nub_panic:
|
||||||
mov rdx, rsi
|
mov rdx, rsi
|
||||||
@@ -39,73 +45,50 @@ nub_panic:
|
|||||||
mov rdi, 101
|
mov rdi, 101
|
||||||
syscall
|
syscall
|
||||||
|
|
||||||
; TODO: This is ai-generated. Should be re-implemented in the future
|
; Memory set function
|
||||||
|
; Arguments: rdi = destination pointer, rsi = value (byte), rdx = count
|
||||||
|
; Returns: rdi (original destination pointer)
|
||||||
global nub_memset
|
global nub_memset
|
||||||
nub_memset:
|
nub_memset:
|
||||||
; Save original destination for return value
|
push rdi ; Save original destination for return value
|
||||||
mov rax, rdi
|
mov rcx, rdx ; Load count into counter register
|
||||||
|
mov al, sil ; Move byte value to al (lower 8 bits of rsi)
|
||||||
|
|
||||||
; Handle zero length
|
; Handle zero count case
|
||||||
test rdx, rdx
|
test rcx, rcx
|
||||||
jz .done
|
jz .done
|
||||||
|
|
||||||
; For small sizes, use simple byte-by-byte loop
|
.loop:
|
||||||
cmp rdx, 16
|
mov [rdi], al ; Store byte at current position
|
||||||
jb .byte_loop
|
inc rdi ; Move to next byte
|
||||||
|
dec rcx ; Decrement counter
|
||||||
; Prepare value for bulk setting
|
jnz .loop ; Continue if counter not zero
|
||||||
; Replicate the byte across all 8 bytes of rsi
|
|
||||||
and rsi, 0xFF ; Ensure only low byte is used
|
|
||||||
mov rcx, rsi ; rcx = byte value
|
|
||||||
shl rsi, 8
|
|
||||||
or rsi, rcx ; rsi = byte | (byte << 8)
|
|
||||||
mov rcx, rsi
|
|
||||||
shl rsi, 16
|
|
||||||
or rsi, rcx ; rsi = 4 copies of byte
|
|
||||||
mov rcx, rsi
|
|
||||||
shl rsi, 32
|
|
||||||
or rsi, rcx ; rsi = 8 copies of byte
|
|
||||||
|
|
||||||
; Align to 8-byte boundary if needed
|
|
||||||
mov rcx, rdi
|
|
||||||
and rcx, 7 ; rcx = bytes until 8-byte aligned
|
|
||||||
jz .aligned
|
|
||||||
|
|
||||||
; Fill bytes until aligned
|
|
||||||
neg rcx
|
|
||||||
add rcx, 8 ; rcx = bytes to fill for alignment
|
|
||||||
cmp rcx, rdx
|
|
||||||
jbe .align_loop
|
|
||||||
mov rcx, rdx ; Don't go past end
|
|
||||||
.align_loop:
|
|
||||||
mov [rdi], sil
|
|
||||||
inc rdi
|
|
||||||
dec rdx
|
|
||||||
dec rcx
|
|
||||||
jnz .align_loop
|
|
||||||
|
|
||||||
.aligned:
|
|
||||||
; Fill 8 bytes at a time
|
|
||||||
mov rcx, rdx
|
|
||||||
shr rcx, 3 ; rcx = number of 8-byte chunks
|
|
||||||
jz .remainder
|
|
||||||
.quad_loop:
|
|
||||||
mov [rdi], rsi
|
|
||||||
add rdi, 8
|
|
||||||
dec rcx
|
|
||||||
jnz .quad_loop
|
|
||||||
|
|
||||||
; Handle remainder bytes
|
|
||||||
and rdx, 7 ; rdx = remaining bytes
|
|
||||||
.remainder:
|
|
||||||
test rdx, rdx
|
|
||||||
jz .done
|
|
||||||
|
|
||||||
.byte_loop:
|
|
||||||
mov [rdi], sil
|
|
||||||
inc rdi
|
|
||||||
dec rdx
|
|
||||||
jnz .byte_loop
|
|
||||||
|
|
||||||
.done:
|
.done:
|
||||||
|
pop rax ; Return original destination pointer
|
||||||
|
ret
|
||||||
|
|
||||||
|
; Memory copy function
|
||||||
|
; Arguments: rdi = destination, rsi = source, rdx = count
|
||||||
|
; Returns: rdi (original destination pointer)
|
||||||
|
global nub_memcpy
|
||||||
|
nub_memcpy:
|
||||||
|
push rdi ; Save original destination for return value
|
||||||
|
mov rcx, rdx ; Load count into counter register
|
||||||
|
|
||||||
|
; Handle zero count case
|
||||||
|
test rcx, rcx
|
||||||
|
jz .done
|
||||||
|
|
||||||
|
; Simple byte-by-byte copy (no overlap handling)
|
||||||
|
.loop:
|
||||||
|
mov al, [rsi] ; Load byte from source
|
||||||
|
mov [rdi], al ; Store byte to destination
|
||||||
|
inc rsi ; Move to next source byte
|
||||||
|
inc rdi ; Move to next destination byte
|
||||||
|
dec rcx ; Decrement counter
|
||||||
|
jnz .loop ; Continue if counter not zero
|
||||||
|
|
||||||
|
.done:
|
||||||
|
pop rax ; Return original destination pointer
|
||||||
ret
|
ret
|
||||||
Reference in New Issue
Block a user