harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 08368a2643f3d8604d7c299089dda3aa5c22dc64
parent fa6d196321fe4e34ed4dc1d084d2c6e6f3ad590b
Author: Brian Callahan <bcallah@posteo.net>
Date:   Fri, 29 Apr 2022 03:56:07 +0000

Add OpenBSD port

Signed-off-by: Brian Callahan <bcallah@posteo.net>

Diffstat:
Mconfig.sh | 5+++++
Minclude/gen.h | 2+-
Art/+openbsd/errno.ha | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Art/+openbsd/segmalloc.ha | 10++++++++++
Art/+openbsd/start+aarch64.s | 8++++++++
Art/+openbsd/start+riscv64.s | 6++++++
Art/+openbsd/start+x86_64.s | 15+++++++++++++++
Art/+openbsd/syscall+aarch64.s | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Art/+openbsd/syscall+riscv64.s | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Art/+openbsd/syscall+x86_64.s | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Art/+openbsd/syscallno.ha | 222+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Art/+openbsd/syscalls.ha | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mrt/configure | 27+++++++++++++++++++++++++++
Art/hare+openbsd.sc | 47+++++++++++++++++++++++++++++++++++++++++++++++
Msrc/emit.c | 3++-
Msrc/gen.c | 70+++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/genutil.c | 2+-
Msrc/qtype.c | 9+++++----
Msrc/typedef.c | 8++++----
Mtests/configure | 9++++++++-
20 files changed, 781 insertions(+), 47 deletions(-)

diff --git a/config.sh b/config.sh @@ -8,6 +8,11 @@ LDFLAGS=${LDFLAGS:-} LD=${LD:-ld} QBE=${QBE:-qbe} +if [ `uname -s` = "OpenBSD" ] +then + LD="${LD:-ld} -nopie" +fi + for arg do case "$arg" in diff --git a/include/gen.h b/include/gen.h @@ -83,7 +83,7 @@ void gen(const struct unit *unit, // genutil.c char *gen_name(struct gen_context *ctx, const char *fmt); -struct gen_value mktemp(struct gen_context *ctx, +struct gen_value mkgtemp(struct gen_context *ctx, const struct type *type, const char *fmt); struct qbe_value mkqval(struct gen_context *ctx, struct gen_value *value); struct qbe_value mklval(struct gen_context *ctx, struct gen_value *value); diff --git a/rt/+openbsd/errno.ha b/rt/+openbsd/errno.ha @@ -0,0 +1,97 @@ +export def EPERM: int = 1; +export def ENOENT: int = 2; +export def ESRCH: int = 3; +export def EINTR: int = 4; +export def EIO: int = 5; +export def ENXIO: int = 6; +export def E2BIG: int = 7; +export def ENOEXEC: int = 8; +export def EBADF: int = 9; +export def ECHILD: int = 10; +export def EDEADLK: int = 11; +export def ENOMEM: int = 12; +export def EACCES: int = 13; +export def EFAULT: int = 14; +export def ENOTBLK: int = 15; +export def EBUSY: int = 16; +export def EEXIST: int = 17; +export def EXDEV: int = 18; +export def ENODEV: int = 19; +export def ENOTDIR: int = 20; +export def EISDIR: int = 21; +export def EINVAL: int = 22; +export def ENFILE: int = 23; +export def EMFILE: int = 24; +export def ENOTTY: int = 25; +export def ETXTBSY: int = 26; +export def EFBIG: int = 27; +export def ENOSPC: int = 28; +export def ESPIPE: int = 29; +export def EROFS: int = 30; +export def EMLINK: int = 31; +export def EPIPE: int = 32; +export def EDOM: int = 33; +export def ERANGE: int = 34; +export def EAGAIN: int = 35; +export def EWOULDBLOCK: int = EAGAIN; +export def EINPROGRESS: int = 36; +export def EALREADY: int = 37; +export def ENOTSOCK: int = 38; +export def EDESTADDRREQ: int = 39; +export def EMSGSIZE: int = 40; +export def EPROTOTYPE: int = 41; +export def ENOPROTOOPT: int = 42; +export def EPROTONOSUPPORT: int = 43; +export def ESOCKTNOSUPPORT: int = 44; +export def EOPNOTSUPP: int = 45; +export def EPFNOSUPPORT: int = 46; +export def EAFNOSUPPORT: int = 47; +export def EADDRINUSE: int = 48; +export def EADDRNOTAVAIL: int = 49; +export def ENETDOWN: int = 50; +export def ENETUNREACH: int = 51; +export def ENETRESET: int = 52; +export def ECONNABORTED: int = 53; +export def ECONNRESET: int = 54; +export def ENOBUFS: int = 55; +export def EISCONN: int = 56; +export def ENOTCONN: int = 57; +export def ESHUTDOWN: int = 58; +export def ETOOMANYREFS: int = 59; +export def ETIMEDOUT: int = 60; +export def ECONNREFUSED: int = 61; +export def ELOOP: int = 62; +export def ENAMETOOLONG: int = 63; +export def EHOSTDOWN: int = 64; +export def EHOSTUNREACH: int = 65; +export def ENOTEMPTY: int = 66; +export def EPROCLIM: int = 67; +export def EUSERS: int = 68; +export def EDQUOT: int = 69; +export def ESTALE: int = 70; +export def EREMOTE: int = 71; +export def EBADRPC: int = 72; +export def ERPCMISMATCH: int = 73; +export def EPROGUNAVAIL: int = 74; +export def EPROGMISMATCH: int = 75; +export def EPROCUNAVAIL: int = 76; +export def ENOLCK: int = 77; +export def ENOSYS: int = 78; +export def EFTYPE: int = 79; +export def EAUTH: int = 80; +export def ENEEDAUTH: int = 81; +export def EIPSEC: int = 82; +export def ENOATTR: int = 83; +export def EILSEQ: int = 84; +export def ENOMEDIUM: int = 85; +export def EMEDIUMTYPE: int = 86; +export def EOVERFLOW: int = 87; +export def ECANCELED: int = 88; +export def EIDRM: int = 89; +export def ENOMSG: int = 90; +export def ENOTSUP: int = 91; +export def EBADMSG: int = 92; +export def ENOTRECOVERABLE: int = 93; +export def EOWNERDEAD: int = 94; +export def EPROTO: int = 95; +export def ELAST: int = 95; diff --git a/rt/+openbsd/segmalloc.ha b/rt/+openbsd/segmalloc.ha @@ -0,0 +1,10 @@ +// Allocates a segment. +fn segmalloc(n: size) nullable *void = { + let p: *void = mmap(null, n, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + return if (p: uintptr: int == -ENOMEM) null else p; +}; + +// Frees a segment allocated with segmalloc. +fn segfree(p: *void, s: size) int = munmap(p, s); diff --git a/rt/+openbsd/start+aarch64.s b/rt/+openbsd/start+aarch64.s @@ -0,0 +1,8 @@ +.text +.global _start +_start: + mov x29, #0 + mov x30, #0 + mov x0, sp + add sp, x0, #-16 + b rt.start_ha diff --git a/rt/+openbsd/start+riscv64.s b/rt/+openbsd/start+riscv64.s @@ -0,0 +1,6 @@ +.text +.global _start +_start: + mv a0, sp + andi sp, sp, -16 + tail rt.start_ha diff --git a/rt/+openbsd/start+x86_64.s b/rt/+openbsd/start+x86_64.s @@ -0,0 +1,15 @@ + .section ".note.openbsd.ident", "a" + .p2align 2 + .long 0x8 + .long 0x4 + .long 0x1 + .asciz "OpenBSD" + .long 0x0 + .previous + +.text +.global _start +_start: + xor %rbp, %rbp + movq %rsp, %rdi + call rt.start_ha diff --git a/rt/+openbsd/syscall+aarch64.s b/rt/+openbsd/syscall+aarch64.s @@ -0,0 +1,69 @@ +.section .text.rt.syscall0 +.global rt.syscall0 +rt.syscall0: + mov x8, x0 + svc 0 + ret + +.section .text.rt.syscall1 +.global rt.syscall1 +rt.syscall1: + mov x8, x0 + mov x0, x1 + svc 0 + ret + +.section .text.rt.syscall2 +.global rt.syscall2 +rt.syscall2: + mov x8, x0 + mov x0, x1 + mov x1, x2 + svc 0 + ret + +.section .text.rt.syscall3 +.global rt.syscall3 +rt.syscall3: + mov x8, x0 + mov x0, x1 + mov x1, x2 + mov x2, x3 + svc 0 + ret + +.section .text.rt.syscall4 +.global rt.syscall4 +rt.syscall4: + mov x8, x0 + mov x0, x1 + mov x1, x2 + mov x2, x3 + mov x3, x4 + svc 0 + ret + +.section .text.rt.syscall5 +.global rt.syscall5 +rt.syscall5: + mov x8, x0 + mov x0, x1 + mov x1, x2 + mov x2, x3 + mov x3, x4 + mov x4, x5 + svc 0 + ret + +.section .text.rt.syscall6 +.global rt.syscall6 +rt.syscall6: + mov x8, x0 + mov x0, x1 + mov x1, x2 + mov x2, x3 + mov x3, x4 + mov x4, x5 + mov x5, x6 + svc 0 + ret diff --git a/rt/+openbsd/syscall+riscv64.s b/rt/+openbsd/syscall+riscv64.s @@ -0,0 +1,69 @@ +.section .text.rt.syscall0 +.global rt.syscall0 +rt.syscall0: + mv a7, a0 + ecall + ret + +.section .text.rt.syscall1 +.global rt.syscall1 +rt.syscall1: + mv a7, a0 + mv a0, a1 + ecall + ret + +.section .text.rt.syscall2 +.global rt.syscall2 +rt.syscall2: + mv a7, a0 + mv a0, a1 + mv a1, a2 + ecall + ret + +.section .text.rt.syscall3 +.global rt.syscall3 +rt.syscall3: + mv a7, a0 + mv a0, a1 + mv a1, a2 + mv a2, a3 + ecall + ret + +.section .text.rt.syscall4 +.global rt.syscall4 +rt.syscall4: + mv a7, a0 + mv a0, a1 + mv a1, a2 + mv a2, a3 + mv a3, a4 + ecall + ret + +.section .text.rt.syscall5 +.global rt.syscall5 +rt.syscall5: + mv a7, a0 + mv a0, a1 + mv a1, a2 + mv a2, a3 + mv a3, a4 + mv a4, a5 + ecall + ret + +.section .text.rt.syscall6 +.global rt.syscall6 +rt.syscall6: + mv a7, a0 + mv a0, a1 + mv a1, a2 + mv a2, a3 + mv a3, a4 + mv a4, a5 + mv a5, a6 + ecall + ret diff --git a/rt/+openbsd/syscall+x86_64.s b/rt/+openbsd/syscall+x86_64.s @@ -0,0 +1,69 @@ +.section .text.rt.syscall0 +.global rt.syscall0 +rt.syscall0: + movq %rdi, %rax + syscall + ret + +.section .text.rt.syscall1 +.global rt.syscall1 +rt.syscall1: + movq %rdi, %rax + movq %rsi, %rdi + syscall + ret + +.section .text.rt.syscall2 +.global rt.syscall2 +rt.syscall2: + movq %rdi, %rax + movq %rsi, %rdi + movq %rdx, %rsi + syscall + ret + +.section .text.rt.syscall3 +.global rt.syscall3 +rt.syscall3: + movq %rdi, %rax + movq %rsi, %rdi + movq %rdx, %rsi + movq %rcx, %rdx + syscall + ret + +.section .text.rt.syscall4 +.global rt.syscall4 +rt.syscall4: + movq %rdi, %rax + movq %r8, %r10 + movq %rsi, %rdi + movq %rdx, %rsi + movq %rcx, %rdx + syscall + ret + +.section .text.rt.syscall5 +.global rt.syscall5 +rt.syscall5: + movq %rdi, %rax + movq %r8, %r10 + movq %rsi, %rdi + movq %r9, %r8 + movq %rdx, %rsi + movq %rcx, %rdx + syscall + ret + +.section .text.rt.syscall6 +.global rt.syscall6 +rt.syscall6: + movq %rdi, %rax + movq %r8, %r10 + movq %rsi, %rdi + movq %r9, %r8 + movq %rdx, %rsi + movq 8(%rsp), %r9 + movq %rcx, %rdx + syscall + ret diff --git a/rt/+openbsd/syscallno.ha b/rt/+openbsd/syscallno.ha @@ -0,0 +1,222 @@ +export def SYS_syscall: u64 = 0; +export def SYS_exit: u64 = 1; +export def SYS_fork: u64 = 2; +export def SYS_read: u64 = 3; +export def SYS_write: u64 = 4; +export def SYS_open: u64 = 5; +export def SYS_close: u64 = 6; +export def SYS_getentropy: u64 = 7; +export def SYS___tfork: u64 = 8; +export def SYS_link: u64 = 9; +export def SYS_unlink: u64 = 10; +export def SYS_wait4: u64 = 11; +export def SYS_chdir: u64 = 12; +export def SYS_fchdir: u64 = 13; +export def SYS_mknod: u64 = 14; +export def SYS_chmod: u64 = 15; +export def SYS_chown: u64 = 16; +export def SYS_break: u64 = 17; +export def SYS_getdtablecount: u64 = 18; +export def SYS_getrusage: u64 = 19; +export def SYS_getpid: u64 = 20; +export def SYS_mount: u64 = 21; +export def SYS_unmount: u64 = 22; +export def SYS_setuid: u64 = 23; +export def SYS_getuid: u64 = 24; +export def SYS_geteuid: u64 = 25; +export def SYS_ptrace: u64 = 26; +export def SYS_recvmsg: u64 = 27; +export def SYS_sendmsg: u64 = 28; +export def SYS_recvfrom: u64 = 29; +export def SYS_accept: u64 = 30; +export def SYS_getpeername: u64 = 31; +export def SYS_getsockname: u64 = 32; +export def SYS_access: u64 = 33; +export def SYS_chflags: u64 = 34; +export def SYS_fchflags: u64 = 35; +export def SYS_sync: u64 = 36; +export def SYS_msyscall: u64 = 37; +export def SYS_stat: u64 = 38; +export def SYS_getppid: u64 = 39; +export def SYS_lstat: u64 = 40; +export def SYS_dup: u64 = 41; +export def SYS_fstatat: u64 = 42; +export def SYS_getegid: u64 = 43; +export def SYS_profil: u64 = 44; +export def SYS_ktrace: u64 = 45; +export def SYS_sigaction: u64 = 46; +export def SYS_getgid: u64 = 47; +export def SYS_sigprocmask: u64 = 48; +export def SYS_mmap: u64 = 49; +export def SYS_setlogin: u64 = 50; +export def SYS_acct: u64 = 51; +export def SYS_sigpending: u64 = 52; +export def SYS_fstat: u64 = 53; +export def SYS_ioctl: u64 = 54; +export def SYS_reboot: u64 = 55; +export def SYS_revoke: u64 = 56; +export def SYS_symlink: u64 = 57; +export def SYS_readlink: u64 = 58; +export def SYS_execve: u64 = 59; +export def SYS_umask: u64 = 60; +export def SYS_chroot: u64 = 61; +export def SYS_getfsstat: u64 = 62; +export def SYS_statfs: u64 = 63; +export def SYS_fstatfs: u64 = 64; +export def SYS_fhstatfs: u64 = 65; +export def SYS_vfork: u64 = 66; +export def SYS_gettimeofday: u64 = 67; +export def SYS_settimeofday: u64 = 68; +export def SYS_setitimer: u64 = 69; +export def SYS_getitimer: u64 = 70; +export def SYS_select: u64 = 71; +export def SYS_kevent: u64 = 72; +export def SYS_munmap: u64 = 73; +export def SYS_mprotect: u64 = 74; +export def SYS_madvise: u64 = 75; +export def SYS_utimes: u64 = 76; +export def SYS_futimes: u64 = 77; +export def SYS_mquery: u64 = 78; +export def SYS_getgroups: u64 = 79; +export def SYS_setgroups: u64 = 80; +export def SYS_getpgrp: u64 = 81; +export def SYS_setpgid: u64 = 82; +export def SYS_futex: u64 = 83; +export def SYS_utimensat: u64 = 84; +export def SYS_futimens: u64 = 85; +export def SYS_kbind: u64 = 86; +export def SYS_clock_gettime: u64 = 87; +export def SYS_clock_settime: u64 = 88; +export def SYS_clock_getres: u64 = 89; +export def SYS_dup2: u64 = 90; +export def SYS_nanosleep: u64 = 91; +export def SYS_fcntl: u64 = 92; +export def SYS_accept4: u64 = 93; +export def SYS___thrsleep: u64 = 94; +export def SYS_fsync: u64 = 95; +export def SYS_setpriority: u64 = 96; +export def SYS_socket: u64 = 97; +export def SYS_connect: u64 = 98; +export def SYS_getdents: u64 = 99; +export def SYS_getpriority: u64 = 100; +export def SYS_pipe2: u64 = 101; +export def SYS_dup3: u64 = 102; +export def SYS_sigreturn: u64 = 103; +export def SYS_bind: u64 = 104; +export def SYS_setsockopt: u64 = 105; +export def SYS_listen: u64 = 106; +export def SYS_chflagsat: u64 = 107; +export def SYS_pledge: u64 = 108; +export def SYS_ppoll: u64 = 109; +export def SYS_pselect: u64 = 110; +export def SYS_sigsuspend: u64 = 111; +export def SYS_sendsyslog: u64 = 112; +export def SYS_unveil: u64 = 114; +export def SYS___realpath: u64 = 115; +export def SYS_getsockopt: u64 = 118; +export def SYS_thrkill: u64 = 119; +export def SYS_readv: u64 = 120; +export def SYS_writev: u64 = 121; +export def SYS_kill: u64 = 122; +export def SYS_fchown: u64 = 123; +export def SYS_fchmod: u64 = 124; +export def SYS_setreuid: u64 = 126; +export def SYS_setregid: u64 = 127; +export def SYS_rename: u64 = 128; +export def SYS_flock: u64 = 131; +export def SYS_mkfifo: u64 = 132; +export def SYS_sendto: u64 = 133; +export def SYS_shutdown: u64 = 134; +export def SYS_socketpair: u64 = 135; +export def SYS_mkdir: u64 = 136; +export def SYS_rmdir: u64 = 137; +export def SYS_adjtime: u64 = 140; +export def SYS_getlogin_r: u64 = 141; +export def SYS_setsid: u64 = 147; +export def SYS_quotactl: u64 = 148; +export def SYS_nfssvc: u64 = 155; +export def SYS_getfh: u64 = 161; +export def SYS___tmpfd: u64 = 164; +export def SYS_sysarch: u64 = 165; +export def SYS_lseek: u64 = 166; +export def SYS_truncate: u64 = 167; +export def SYS_ftruncate: u64 = 168; +export def SYS_pread: u64 = 169; +export def SYS_pwrite: u64 = 170; +export def SYS_preadv: u64 = 171; +export def SYS_pwritev: u64 = 172; +export def SYS_pad_pread: u64 = 173; +export def SYS_pad_pwrite: u64 = 174; +export def SYS_setgid: u64 = 181; +export def SYS_setegid: u64 = 182; +export def SYS_seteuid: u64 = 183; +export def SYS_pathconf: u64 = 191; +export def SYS_fpathconf: u64 = 192; +export def SYS_swapctl: u64 = 193; +export def SYS_getrlimit: u64 = 194; +export def SYS_setrlimit: u64 = 195; +export def SYS_pad_mmap: u64 = 197; +export def SYS___syscall: u64 = 198; +export def SYS_pad_lseek: u64 = 199; +export def SYS_pad_truncate: u64 = 200; +export def SYS_pad_ftruncate: u64 = 201; +export def SYS_sysctl: u64 = 202; +export def SYS_mlock: u64 = 203; +export def SYS_munlock: u64 = 204; +export def SYS_getpgid: u64 = 207; +export def SYS_utrace: u64 = 209; +export def SYS_semget: u64 = 221; +export def SYS_msgget: u64 = 225; +export def SYS_msgsnd: u64 = 226; +export def SYS_msgrcv: u64 = 227; +export def SYS_shmat: u64 = 228; +export def SYS_shmdt: u64 = 230; +export def SYS_minherit: u64 = 250; +export def SYS_poll: u64 = 252; +export def SYS_issetugid: u64 = 253; +export def SYS_lchown: u64 = 254; +export def SYS_getsid: u64 = 255; +export def SYS_msync: u64 = 256; +export def SYS_pipe: u64 = 263; +export def SYS_fhopen: u64 = 264; +export def SYS_pad_preadv: u64 = 267; +export def SYS_pad_pwritev: u64 = 268; +export def SYS_pad_kqueue: u64 = 269; +export def SYS_mlockall: u64 = 271; +export def SYS_munlockall: u64 = 272; +export def SYS_getresuid: u64 = 281; +export def SYS_setresuid: u64 = 282; +export def SYS_getresgid: u64 = 283; +export def SYS_setresgid: u64 = 284; +export def SYS_pad_mquery: u64 = 286; +export def SYS_closefrom: u64 = 287; +export def SYS_sigaltstack: u64 = 288; +export def SYS_shmget: u64 = 289; +export def SYS_semop: u64 = 290; +export def SYS_fhstat: u64 = 294; +export def SYS___semctl: u64 = 295; +export def SYS_shmctl: u64 = 296; +export def SYS_msgctl: u64 = 297; +export def SYS_sched_yield: u64 = 298; +export def SYS_getthrid: u64 = 299; +export def SYS___thrwakeup: u64 = 301; +export def SYS___threxit: u64 = 302; +export def SYS___thrsigdivert: u64 = 303; +export def SYS___getcwd: u64 = 304; +export def SYS_adjfreq: u64 = 305; +export def SYS_setrtable: u64 = 310; +export def SYS_getrtable: u64 = 311; +export def SYS_faccessat: u64 = 313; +export def SYS_fchmodat: u64 = 314; +export def SYS_fchownat: u64 = 315; +export def SYS_linkat: u64 = 317; +export def SYS_mkdirat: u64 = 318; +export def SYS_mkfifoat: u64 = 319; +export def SYS_mknodat: u64 = 320; +export def SYS_openat: u64 = 321; +export def SYS_readlinkat: u64 = 322; +export def SYS_renameat: u64 = 323; +export def SYS_symlinkat: u64 = 324; +export def SYS_unlinkat: u64 = 325; +export def SYS___set_tcb: u64 = 329; +export def SYS___get_tcb: u64 = 330; diff --git a/rt/+openbsd/syscalls.ha b/rt/+openbsd/syscalls.ha @@ -0,0 +1,81 @@ +fn syscall0(_: u64) u64; +fn syscall1(_: u64, _: u64) u64; +fn syscall2(_: u64, _: u64, _: u64) u64; +fn syscall3(_: u64, _: u64, _: u64, _: u64) u64; +fn syscall4(_: u64, _: u64, _: u64, _: u64, _: u64) u64; +fn syscall5(_: u64, _: u64, _: u64, _: u64, _: u64, _: u64) u64; +fn syscall6(_: u64, _: u64, _: u64, _: u64, _: u64, _: u64, _: u64) u64; + +export fn write(fd: int, buf: *const void, count: size) size = + syscall3(SYS_write, fd: u64, buf: uintptr: u64, count: u64): size; + +export fn close(fd: int) int = syscall1(SYS_close, fd: u64): int; + +export fn dup2(old: int, new: int) int = + syscall2(SYS_dup2, old: u64, new: u64): int; + +export fn getpid() int = syscall0(SYS_getpid): int; + +export @noreturn fn exit(status: int) void = { syscall1(SYS_exit, status: u64); }; + +export fn fork() int = syscall0(SYS_fork): int; + +export fn execve( + path: *const char, + argv: *[*]nullable *const char, + envp: *[*]nullable *const char, +) int = syscall3(SYS_execve, + path: uintptr: u64, + argv: uintptr: u64, + envp: uintptr: u64): int; + +export fn wait4(pid: int, status: *int, options: int, rusage: nullable *void) void = { + syscall4(SYS_wait4, pid: u64, status: uintptr: u64, + options: u64, rusage: uintptr: u64); +}; + +export fn wifexited(status: int) bool = wtermsig(status) == 0; +export fn wexitstatus(status: int) int = (status & 0xff00) >> 8; + +export fn wtermsig(status: int) int = status & 0x7f; +export fn wifsignaled(status: int) bool = + wtermsig(status) != 0o177 && wtermsig(status) != 0 && status != 0x13; + +export fn kill(pid: int, signal: int) int = + syscall2(SYS_kill, pid: u64, signal: u64): int; + +export fn pipe2(pipefd: *[2]int, flags: int) int = + syscall2(SYS_pipe2, pipefd: uintptr: u64, flags: u64): int; + +export def MAP_SHARED: uint = 0x0001; +export def MAP_PRIVATE: uint = 0x0002; +export def MAP_FIXED: uint = 0x0010; +export def __MAP_NOREPLACE: uint = 0x0800; +export def MAP_ANON: uint = 0x1000; +export def MAP_ANONYMOUS: uint = MAP_ANON; +export def __MAP_NOFAULT: uint = 0x2000; +export def MAP_STACK: uint = 0x4000; +export def MAP_CONCEAL: uint = 0x8000; + +def PROT_NONE: uint = 0x00; +def PROT_READ: uint = 0x01; +def PROT_WRITE: uint = 0x02; +def PROT_EXEC: uint = 0x04; + +export fn mmap( + addr: nullable *void, + length: size, + prot: uint, + flags: uint, + fd: int, + offs: size +) *void = { + return syscall6(SYS_mmap, addr: uintptr: u64, length: u64, prot: u64, + flags: u64, fd: u64, offs: u64): uintptr: *void; +}; + +export fn munmap(addr: *void, length: size) int = + syscall2(SYS_munmap, addr: uintptr: u64, length: u64): int; + +export def SIGABRT: int = 6; +export def SIGCHLD: int = 20; diff --git a/rt/configure b/rt/configure @@ -48,6 +48,33 @@ rt() { rt: libhart.a rt/+freebsd/start+$arch.o EOF ;; + OpenBSD) + case $arch in + amd64) + arch=x86_64 + ;; + aarch64|riscv64) + ;; + *) + printf "unsupported OpenBSD arch %s\n" "$(uname)" >&2 + ;; + esac + rtstart=rt/+openbsd/start+$arch.o + cat <<-EOF + rtstart=rt/+openbsd/start+$arch.o + + libhart_srcs=\ + rt/+openbsd/errno.ha \ + rt/+openbsd/segmalloc.ha \ + rt/+openbsd/syscallno.ha \ + rt/+openbsd/syscalls.ha \ + + libhart_objs=\ + rt/+openbsd/syscall+$arch.o + + rt: libhart.a rt/+openbsd/start+$arch.o + EOF + ;; *) printf "rt not supported for %s\n" "$(uname)" >&2 exit 1 diff --git a/rt/hare+openbsd.sc b/rt/hare+openbsd.sc @@ -0,0 +1,47 @@ +PHDRS { + headers PT_PHDR PHDRS; + text PT_LOAD FILEHDR PHDRS; + data PT_LOAD; + note PT_NOTE; +} +ENTRY(_start); +SECTIONS { + . = 0x8000000; + .text : { + KEEP (*(.text)) + *(.text.*) + } :text + . = 0x80000000; + .data : { + KEEP (*(.data)) + *(.data.*) + } :data + + .init_array : { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } :data + + .fini_array : { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + } :data + + .test_array : { + PROVIDE_HIDDEN (__test_array_start = .); + KEEP (*(.test_array)) + PROVIDE_HIDDEN (__test_array_end = .); + } :data + + .note.openbsd.ident : { + KEEP (*(.note.openbsd.ident)) + *(.note.openbsd.*) + } :data :note + + .bss : { + KEEP (*(.bss)) + *(.bss.*) + } :data +} diff --git a/src/emit.c b/src/emit.c @@ -1,6 +1,7 @@ #include <assert.h> #include <ctype.h> #include <float.h> +#include <inttypes.h> #include <stdlib.h> #include <stdio.h> #include "emit.h" @@ -96,7 +97,7 @@ emit_const(struct qbe_value *val, FILE *out) fprintf(out, "%u", val->wval); break; case Q_LONG: - fprintf(out, "%lu", val->lval); + fprintf(out, "%" PRIu64, val->lval); break; case Q_SINGLE: fprintf(out, "s_%.*g", DECIMAL_DIG, val->sval); diff --git a/src/gen.c b/src/gen.c @@ -501,7 +501,7 @@ gen_expr_alloc_init_with(struct gen_context *ctx, objtype = objtype->pointer.referent; struct qbe_value sz = constl(objtype->size); - struct gen_value result = mktemp(ctx, expr->result, ".%d"); + struct gen_value result = mkgtemp(ctx, expr->result, ".%d"); struct qbe_value qresult = mkqval(ctx, &result); struct qbe_value rtfunc = mkrtfunc(ctx, "rt.malloc"); pushi(ctx->current, &qresult, Q_CALL, &rtfunc, &sz, NULL); @@ -539,7 +539,7 @@ gen_expr_alloc_slice_with(struct gen_context *ctx, gen_alloc_slice_at(ctx, expr, *out, expand); return gv_void; } - struct gen_value temp = mktemp(ctx, expr->result, "object.%d"); + struct gen_value temp = mkgtemp(ctx, expr->result, "object.%d"); struct qbe_value base = mkqval(ctx, &temp); struct qbe_value sz = constl(expr->result->size); enum qbe_instr alloc = alloc_for_align(expr->result->align); @@ -555,7 +555,7 @@ gen_expr_alloc_copy_with(struct gen_context *ctx, // alloc(init...) case struct gen_value ret = gv_void; if (out == NULL) { - ret = mktemp(ctx, expr->result, "object.%d"); + ret = mkgtemp(ctx, expr->result, "object.%d"); out = &ret; struct qbe_value base = mkqval(ctx, out); @@ -906,7 +906,7 @@ gen_expr_binarithm(struct gen_context *ctx, const struct expression *expr) { const struct type *ltype = type_dealias(expr->binarithm.lvalue->result); const struct type *rtype = type_dealias(expr->binarithm.rvalue->result); - struct gen_value result = mktemp(ctx, expr->result, ".%d"); + struct gen_value result = mkgtemp(ctx, expr->result, ".%d"); struct qbe_value qresult = mkqval(ctx, &result); if (expr->binarithm.op == BIN_LAND || expr->binarithm.op == BIN_LOR) { @@ -1070,7 +1070,7 @@ gen_expr_call(struct gen_context *ctx, const struct expression *expr) }; struct gen_value rval = gv_void; if (type_dealias(rtype->func.result)->storage != STORAGE_VOID) { - rval = mktemp(ctx, rtype->func.result, "returns.%d"); + rval = mkgtemp(ctx, rtype->func.result, "returns.%d"); call.out = xcalloc(1, sizeof(struct qbe_value)); *call.out = mkqval(ctx, &rval); call.out->type = qtype_lookup(ctx, rtype->func.result, false); @@ -1238,8 +1238,8 @@ gen_expr_cast_tagged_at(struct gen_context *ctx, subtype = tagged_subset_compat(to, from) ? from : to; const struct type *innertype = type_store_tagged_to_union( ctx->store, type_dealias(subtype)); - struct gen_value iout = mktemp(ctx, innertype, ".%d"); - struct gen_value ival = mktemp(ctx, innertype, ".%d"); + struct gen_value iout = mkgtemp(ctx, innertype, ".%d"); + struct gen_value ival = mkgtemp(ctx, innertype, ".%d"); struct qbe_value qiout = mkqval(ctx, &iout); struct qbe_value qival = mkqval(ctx, &ival); struct qbe_value offs = constl(to->align); @@ -1259,7 +1259,7 @@ gen_expr_cast_tagged_at(struct gen_context *ctx, return; } - struct gen_value storage = mktemp(ctx, subtype, ".%d"); + struct gen_value storage = mkgtemp(ctx, subtype, ".%d"); struct qbe_value qstor = mklval(ctx, &storage); struct qbe_value offs = constl(to->align); pushi(ctx->current, &qstor, Q_ADD, &qout, &offs, NULL); @@ -1323,9 +1323,9 @@ gen_expr_cast_array_at(struct gen_context *ctx, struct qbe_value base = mkqval(ctx, &out); struct qbe_value offs = constl((typein->array.length - 1) * membtype->size); - struct gen_value next = mktemp(ctx, membtype, ".%d"); + struct gen_value next = mkgtemp(ctx, membtype, ".%d"); struct qbe_value ptr = mklval(ctx, &next); - struct gen_value item = mktemp(ctx, membtype, "item.%d"); + struct gen_value item = mkgtemp(ctx, membtype, "item.%d"); struct qbe_value qitem = mklval(ctx, &item); pushi(ctx->current, &qitem, Q_ADD, &base, &offs, NULL); @@ -1404,7 +1404,7 @@ gen_expr_cast(struct gen_context *ctx, const struct expression *expr) } if (cast_prefers_at(expr)) { - struct gen_value out = mktemp(ctx, expr->result, "object.%d"); + struct gen_value out = mkgtemp(ctx, expr->result, "object.%d"); struct qbe_value base = mkqval(ctx, &out); struct qbe_value sz = constl(expr->result->size); enum qbe_instr alloc = alloc_for_align(expr->result->align); @@ -1437,7 +1437,7 @@ gen_expr_cast(struct gen_context *ctx, const struct expression *expr) struct qbe_value qval = mkqval(ctx, &val); if (expr->cast.kind == C_TEST) { struct gen_value out = - mktemp(ctx, &builtin_type_bool, ".%d"); + mkgtemp(ctx, &builtin_type_bool, ".%d"); struct qbe_value qout = mkqval(ctx, &out); struct qbe_value zero = constl(0); @@ -1507,7 +1507,7 @@ gen_expr_cast(struct gen_context *ctx, const struct expression *expr) struct gen_value value = gen_expr(ctx, expr->cast.value); struct qbe_value qvalue = mkqval(ctx, &value); - struct gen_value result = mktemp(ctx, expr->result, "cast.%d"); + struct gen_value result = mkgtemp(ctx, expr->result, "cast.%d"); struct qbe_value qresult = mkqval(ctx, &result); struct gen_value intermediate; struct qbe_value qintermediate; @@ -1580,7 +1580,7 @@ gen_expr_cast(struct gen_context *ctx, const struct expression *expr) switch (from->size) { case 1: case 2: - intermediate = mktemp(ctx, + intermediate = mkgtemp(ctx, &builtin_type_i32, "cast.%d"); qintermediate = mkqval(ctx, &intermediate); pushi(ctx->current, &qintermediate, @@ -1600,7 +1600,7 @@ gen_expr_cast(struct gen_context *ctx, const struct expression *expr) switch (from->size) { case 1: case 2: - intermediate = mktemp(ctx, + intermediate = mkgtemp(ctx, &builtin_type_i32, "cast.%d"); qintermediate = mkqval(ctx, &intermediate); pushi(ctx->current, &qintermediate, @@ -1665,7 +1665,7 @@ gen_expr_compound_with(struct gen_context *ctx, struct gen_value gvout = gv_void; if (!out) { - gvout = mktemp(ctx, expr->result, ".%d"); + gvout = mkgtemp(ctx, expr->result, ".%d"); } scope->out = out; scope->result = gvout; @@ -1692,7 +1692,7 @@ gen_const_array_at(struct gen_context *ctx, size_t n = 0; const struct type *atype = type_dealias(expr->result); - struct gen_value item = mktemp(ctx, atype->array.members, "item.%d"); + struct gen_value item = mkgtemp(ctx, atype->array.members, "item.%d"); for (const struct array_constant *ac = aexpr; ac; ac = ac->next) { struct qbe_value offs = constl(n * atype->array.members->size); struct qbe_value ptr = mklval(ctx, &item); @@ -1768,7 +1768,7 @@ static struct gen_value gen_expr_const(struct gen_context *ctx, const struct expression *expr) { if (type_is_aggregate(type_dealias(expr->result))) { - struct gen_value out = mktemp(ctx, expr->result, "object.%d"); + struct gen_value out = mkgtemp(ctx, expr->result, "object.%d"); struct qbe_value base = mkqval(ctx, &out); struct qbe_value sz = constl(expr->result->size); enum qbe_instr alloc = alloc_for_align(expr->result->align); @@ -1987,7 +1987,7 @@ gen_expr_if_with(struct gen_context *ctx, { struct gen_value gvout = gv_void; if (!out) { - gvout = mktemp(ctx, expr->result, ".%d"); + gvout = mkgtemp(ctx, expr->result, ".%d"); } struct qbe_statement ltrue, lfalse, lend; @@ -2194,7 +2194,7 @@ gen_nested_match_tests(struct gen_context *ctx, struct gen_value object, // tag of the foo object for int. struct qbe_value *subtag = &tag; struct qbe_value subval = mkcopy(ctx, &object, "subval.%d"); - struct gen_value match = mktemp(ctx, &builtin_type_bool, ".%d"); + struct gen_value match = mkgtemp(ctx, &builtin_type_bool, ".%d"); struct qbe_value qmatch = mkqval(ctx, &match); struct qbe_value temp = mkqtmp(ctx, &qbe_word, ".%d"); const struct type *subtype = object.type; @@ -2244,7 +2244,7 @@ gen_subset_match_tests(struct gen_context *ctx, // // In this situation, we test the match object's tag against each type // ID of the case type. - struct gen_value match = mktemp(ctx, &builtin_type_bool, ".%d"); + struct gen_value match = mkgtemp(ctx, &builtin_type_bool, ".%d"); for (const struct type_tagged_union *tu = &type->tagged; tu; tu = tu->next) { struct qbe_statement lnexttag; struct qbe_value bnexttag = mklabel(ctx, &lnexttag, ".%d"); @@ -2265,7 +2265,7 @@ gen_match_with_tagged(struct gen_context *ctx, { struct gen_value gvout = gv_void; if (!out) { - gvout = mktemp(ctx, expr->result, ".%d"); + gvout = mkgtemp(ctx, expr->result, ".%d"); } const struct type *objtype = expr->match.value->result; @@ -2397,7 +2397,7 @@ gen_match_with_nullable(struct gen_context *ctx, { struct gen_value gvout = gv_void; if (!out) { - gvout = mktemp(ctx, expr->result, ".%d"); + gvout = mkgtemp(ctx, expr->result, ".%d"); } struct qbe_statement lout; @@ -2433,7 +2433,7 @@ gen_match_with_nullable(struct gen_context *ctx, } struct gen_binding *gb = xcalloc(1, sizeof(struct gen_binding)); - gb->value = mktemp(ctx, _case->type, "binding.%d"); + gb->value = mkgtemp(ctx, _case->type, "binding.%d"); gb->object = _case->object; gb->next = ctx->bindings; ctx->bindings = gb; @@ -2509,7 +2509,7 @@ gen_expr_measure(struct gen_context *ctx, const struct expression *expr) case STORAGE_STRING: gv = gen_expr(ctx, value); gv = gen_autoderef(ctx, gv); - temp = mktemp(ctx, &builtin_type_size, ".%d"); + temp = mkgtemp(ctx, &builtin_type_size, ".%d"); struct qbe_value qv = mkqval(ctx, &gv), qtemp = mkqval(ctx, &temp), offs = constl(builtin_type_size.size); @@ -2580,7 +2580,7 @@ gen_expr_struct_at(struct gen_context *ctx, &base, &zero, &size, NULL); } - struct gen_value ftemp = mktemp(ctx, &builtin_type_void, "field.%d"); + struct gen_value ftemp = mkgtemp(ctx, &builtin_type_void, "field.%d"); for (const struct expr_struct_field *field = expr->_struct.fields; field; field = field->next) { if (!field->value) { @@ -2603,7 +2603,7 @@ gen_expr_switch_with(struct gen_context *ctx, { struct gen_value gvout = gv_void; if (!out) { - gvout = mktemp(ctx, expr->result, ".%d"); + gvout = mkgtemp(ctx, expr->result, ".%d"); } struct qbe_statement lout; @@ -2714,7 +2714,7 @@ gen_expr_slice_at(struct gen_context *ctx, qbase = mkqtmp(ctx, ctx->arch.sz, "base.%d"); enum qbe_instr load = load_for_type(ctx, &builtin_type_size); pushi(ctx->current, &qbase, load, &qobject, NULL); - length = mktemp(ctx, &builtin_type_size, "len.%d"); + length = mkgtemp(ctx, &builtin_type_size, "len.%d"); qlength = mkqval(ctx, &length); pushi(ctx->current, &qptr, Q_ADD, &qobject, &offset, NULL); pushi(ctx->current, &qlength, load, &qptr, NULL); @@ -2795,7 +2795,7 @@ gen_expr_tuple_at(struct gen_context *ctx, struct qbe_value base = mkqval(ctx, &out); const struct type *type = type_dealias(expr->result); - struct gen_value vtemp = mktemp(ctx, &builtin_type_void, "value.%d"); + struct gen_value vtemp = mkgtemp(ctx, &builtin_type_void, "value.%d"); const struct expression_tuple *value = &expr->tuple; for (const struct type_tuple *tuple = &type->tuple; tuple; tuple = tuple->next) { @@ -2822,7 +2822,7 @@ gen_expr_unarithm(struct gen_context *ctx, val.type = expr->result; return val; } - struct gen_value val = mktemp(ctx, operand->result, ".%d"); + struct gen_value val = mkgtemp(ctx, operand->result, ".%d"); struct qbe_value qv = mklval(ctx, &val); struct qbe_value sz = constl(val.type->size); enum qbe_instr alloc = alloc_for_align(val.type->align); @@ -2837,21 +2837,21 @@ gen_expr_unarithm(struct gen_context *ctx, return gen_load(ctx, val); case UN_BNOT: val = gen_expr(ctx, operand); - temp = mktemp(ctx, operand->result, ".%d"); + temp = mkgtemp(ctx, operand->result, ".%d"); qval = mkqval(ctx, &val), qtmp = mkqval(ctx, &temp); struct qbe_value ones = constl((uint64_t)-1); pushi(ctx->current, &qtmp, Q_XOR, &qval, &ones, NULL); return temp; case UN_LNOT: val = gen_expr(ctx, operand); - temp = mktemp(ctx, operand->result, ".%d"); + temp = mkgtemp(ctx, operand->result, ".%d"); qval = mkqval(ctx, &val), qtmp = mkqval(ctx, &temp); struct qbe_value zerow = constw(0); pushi(ctx->current, &qtmp, Q_CEQW, &qval, &zerow, NULL); return temp; case UN_MINUS: val = gen_expr(ctx, operand); - temp = mktemp(ctx, operand->result, ".%d"); + temp = mkgtemp(ctx, operand->result, ".%d"); qval = mkqval(ctx, &val), qtmp = mkqval(ctx, &temp); pushi(ctx->current, &qtmp, Q_NEG, &qval, NULL); return temp; @@ -2866,7 +2866,7 @@ gen_expr_vaarg(struct gen_context *ctx, const struct expression *expr) { // XXX: qbe only supports variadic base types, should check for this - struct gen_value result = mktemp(ctx, expr->result, ".%d"); + struct gen_value result = mkgtemp(ctx, expr->result, ".%d"); struct qbe_value qresult = mkqval(ctx, &result); struct gen_value ap = gen_expr(ctx, expr->vaarg.ap); struct qbe_value qap = mkqval(ctx, &ap); @@ -2951,7 +2951,7 @@ gen_expr(struct gen_context *ctx, const struct expression *expr) return *(struct gen_value *)expr->user; } - struct gen_value out = mktemp(ctx, expr->result, "object.%d"); + struct gen_value out = mkgtemp(ctx, expr->result, "object.%d"); struct qbe_value base = mkqval(ctx, &out); struct qbe_value sz = constl(expr->result->size); enum qbe_instr alloc = alloc_for_align(expr->result->align); diff --git a/src/genutil.c b/src/genutil.c @@ -66,7 +66,7 @@ mkqtmp(struct gen_context *ctx, const struct qbe_type *qtype, const char *fmt) } struct gen_value -mktemp(struct gen_context *ctx, const struct type *type, const char *fmt) +mkgtemp(struct gen_context *ctx, const struct type *type, const char *fmt) { return (struct gen_value){ .kind = GV_TEMP, diff --git a/src/qtype.c b/src/qtype.c @@ -1,4 +1,5 @@ #include <assert.h> +#include <inttypes.h> #include <stdlib.h> #include <stdio.h> #include "gen.h" @@ -18,9 +19,9 @@ sf_compar(const void *_a, const void *_b) static const struct qbe_type * tagged_qtype(struct gen_context *ctx, const struct type *type) { - int n = snprintf(NULL, 0, "tags.%zd", ctx->id); + int n = snprintf(NULL, 0, "tags.%" PRIu64, ctx->id); char *name = xcalloc(1, n + 1); - snprintf(name, n + 1, "tags.%zd", ctx->id); + snprintf(name, n + 1, "tags.%" PRIu64, ctx->id); ++ctx->id; struct qbe_def *def = xcalloc(1, sizeof(struct qbe_def)); @@ -65,9 +66,9 @@ aggregate_lookup(struct gen_context *ctx, const struct type *type) } } - int n = snprintf(NULL, 0, "type.%zd", ctx->id); + int n = snprintf(NULL, 0, "type.%" PRIu64, ctx->id); char *name = xcalloc(1, n + 1); - snprintf(name, n + 1, "type.%zd", ctx->id); + snprintf(name, n + 1, "type.%" PRIu64, ctx->id); ++ctx->id; struct qbe_def *def = xcalloc(1, sizeof(struct qbe_def)); diff --git a/src/typedef.c b/src/typedef.c @@ -86,7 +86,7 @@ emit_const(const struct expression *expr, FILE *out) case STORAGE_I8: case STORAGE_ICONST: case STORAGE_INT: - fprintf(out, "%ld%s", val->ival, + fprintf(out, "%" PRIiMAX "%s", val->ival, storage_to_suffix(type_dealias(expr->result)->storage)); break; case STORAGE_NULL: @@ -99,7 +99,7 @@ emit_const(const struct expression *expr, FILE *out) case STORAGE_U8: case STORAGE_UINT: case STORAGE_UINTPTR: - fprintf(out, "%lu%s", val->uval, + fprintf(out, "%" PRIuMAX "%s", val->uval, storage_to_suffix(type_dealias(expr->result)->storage)); break; case STORAGE_VOID: @@ -301,10 +301,10 @@ emit_type(const struct type *type, FILE *out) ev; ev = ev->next) { fprintf(out, "%s = ", ev->name); if (type_is_signed(type)) { - fprintf(out, "%zd%s", ev->ival, + fprintf(out, "%" PRIi64 "%s", ev->ival, storage_to_suffix(type->_enum.storage)); } else { - fprintf(out, "%zu%s", ev->uval, + fprintf(out, "%" PRIu64 "%s", ev->uval, storage_to_suffix(type->_enum.storage)); } if (ev->next) { diff --git a/tests/configure b/tests/configure @@ -1,6 +1,13 @@ #!/bin/sh all="$all tests" +rtscript="rt/hare.sc" + +if [ `uname -s` = "OpenBSD" ] +then + rtscript="rt/hare+openbsd.sc" +fi + tests() { # harec tests for t in \ @@ -46,7 +53,7 @@ tests/$t: libhart.a tests/$t.ha @HARECACHE=\$(HARECACHE) ./harec -o tests/$t.ssa tests/$t.ha @\$(QBE) -o tests/$t.s tests/$t.ssa @\$(AS) -g -o tests/$t.o tests/$t.s - @\$(LD) --gc-sections -T rt/hare.sc -o tests/$t $rtstart tests/$t.o libhart.a + @\$(LD) --gc-sections -T $rtscript -o tests/$t $rtstart tests/$t.o libhart.a @rm tests/$t.s tests/$t.ssa tests/$t.o check: tests/$t