From e5a11020cc838019de12955437b371511b4745e5 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Mon, 17 Aug 2020 15:07:57 +0700 Subject: [PATCH 01/28] Add sparc64 syscall interface --- lib/std/os/linux.zig | 1 + lib/std/os/linux/sparc64.zig | 136 +++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 lib/std/os/linux/sparc64.zig diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index e38d9bc10d..0a675cf10f 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -24,6 +24,7 @@ pub usingnamespace switch (builtin.arch) { .aarch64 => @import("linux/arm64.zig"), .arm => @import("linux/arm-eabi.zig"), .riscv64 => @import("linux/riscv64.zig"), + .sparcv9 => @import("linux/sparc64.zig"), .mips, .mipsel => @import("linux/mips.zig"), .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"), else => struct {}, diff --git a/lib/std/os/linux/sparc64.zig b/lib/std/os/linux/sparc64.zig new file mode 100644 index 0000000000..0cc5882b26 --- /dev/null +++ b/lib/std/os/linux/sparc64.zig @@ -0,0 +1,136 @@ +usingnamespace @import("../bits.zig"); + +// TODO: Handle the case of pipe(2) returning multiple values. +// From syscall(2)'s manual page: +// Some architectures (namely, Alpha, IA-64, MIPS, SuperH, sparc/32, and sparc/64) +// use an additional register ("Retval2" in the above table) to pass back a second +// return value from the pipe(2) system call; Alpha uses this technique in the +// architecture-specific getxpid(2), getxuid(2), and getxgid(2) system calls +// as well. Other architectures do not use the second return value register in +// the system call interface, even if it is defined in the System V ABI. + +pub fn syscall0(number: SYS) usize { + return asm volatile ( + \\ t 0x6d + \\ bcc %%xcc, 1f + \\ neg %%o0 + \\ 1: + : [ret] "={%o0}" (-> usize) + : [number] "{%g1}" (@enumToInt(number)) + : "memory", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7" + ); +} + +pub fn syscall1(number: SYS, arg1: usize) usize { + return asm volatile ( + \\ t 0x6d + \\ bcc %%xcc, 1f + \\ neg %%o0 + \\ 1: + : [ret] "={%o0}" (-> usize) + : [number] "{%g1}" (@enumToInt(number)), + [arg1] "{%o0}" (arg1) + : "memory", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7" + ); +} + +pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize { + return asm volatile ( + \\ t 0x6d + \\ bcc %%xcc, 1f + \\ neg %%o0 + \\ 1: + : [ret] "={%o0}" (-> usize) + : [number] "{%g1}" (@enumToInt(number)), + [arg1] "{%o0}" (arg1), + [arg2] "{%o1}" (arg2) + : "memory", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7" + ); +} + +pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize { + return asm volatile ( + \\ t 0x6d + \\ bcc %%xcc, 1f + \\ neg %%o0 + \\ 1: + : [ret] "={%o0}" (-> usize) + : [number] "{%g1}" (@enumToInt(number)), + [arg1] "{%o0}" (arg1), + [arg2] "{%o1}" (arg2), + [arg3] "{%o2}" (arg3) + : "memory", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7" + ); +} + +pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize { + return asm volatile ( + \\ t 0x6d + \\ bcc %%xcc, 1f + \\ neg %%o0 + \\ 1: + : [ret] "={%o0}" (-> usize) + : [number] "{%g1}" (@enumToInt(number)), + [arg1] "{%o0}" (arg1), + [arg2] "{%o1}" (arg2), + [arg3] "{%o2}" (arg3), + [arg4] "{%o3}" (arg4) + : "memory", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7" + ); +} + +pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize { + return asm volatile ( + \\ t 0x6d + \\ bcc %%xcc, 1f + \\ neg %%o0 + \\ 1: + : [ret] "={%o0}" (-> usize) + : [number] "{%g1}" (@enumToInt(number)), + [arg1] "{%o0}" (arg1), + [arg2] "{%o1}" (arg2), + [arg3] "{%o2}" (arg3), + [arg4] "{%o3}" (arg4), + [arg5] "{%o4}" (arg5), + : "memory", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7" + ); +} + +pub fn syscall6( + number: SYS, + arg1: usize, + arg2: usize, + arg3: usize, + arg4: usize, + arg5: usize, + arg6: usize, +) usize { + return asm volatile ( + \\ t 0x6d + \\ bcc %%xcc, 1f + \\ neg %%o0 + \\ 1: + : [ret] "={%o0}" (-> usize) + : [number] "{%g1}" (@enumToInt(number)), + [arg1] "{%o0}" (arg1), + [arg2] "{%o1}" (arg2), + [arg3] "{%o2}" (arg3), + [arg4] "{%o3}" (arg4), + [arg5] "{%o4}" (arg5), + [arg6] "{%o5}" (arg6), + : "memory", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7" + ); +} + +/// This matches the libc clone function. +pub extern fn clone(func: fn (arg: usize) callconv(.C) u8, stack: usize, flags: usize, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; + +pub const restore = restore_rt; + +pub fn restore_rt() callconv(.Naked) void { + return asm volatile ("t 0x6d" + : + : [number] "{%g1}" (@enumToInt(SYS.rt_sigreturn)) + : "memory", "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7" + ); +} From de06b0a635bb865715e60ce1ac3ba336cfe7c385 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sat, 22 Aug 2020 14:34:49 +0700 Subject: [PATCH 02/28] Add sparc64 linux bits --- lib/std/os/bits/linux.zig | 1 + lib/std/os/bits/linux/sparc64.zig | 621 ++++++++++++++++++++++++++++++ 2 files changed, 622 insertions(+) create mode 100644 lib/std/os/bits/linux/sparc64.zig diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig index 19cc3be775..ab9fe9ffb4 100644 --- a/lib/std/os/bits/linux.zig +++ b/lib/std/os/bits/linux.zig @@ -19,6 +19,7 @@ pub usingnamespace switch (builtin.arch) { .aarch64 => @import("linux/arm64.zig"), .arm => @import("linux/arm-eabi.zig"), .riscv64 => @import("linux/riscv64.zig"), + .sparcv9 => @import("linux/sparc64.zig"), .mips, .mipsel => @import("linux/mips.zig"), .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"), else => struct {}, diff --git a/lib/std/os/bits/linux/sparc64.zig b/lib/std/os/bits/linux/sparc64.zig new file mode 100644 index 0000000000..d90cb20ab2 --- /dev/null +++ b/lib/std/os/bits/linux/sparc64.zig @@ -0,0 +1,621 @@ +// sparc64-specific declarations that are intended to be imported into the POSIX namespace. +const std = @import("../../../std.zig"); +const pid_t = linux.pid_t; +const uid_t = linux.uid_t; +const clock_t = linux.clock_t; +const stack_t = linux.stack_t; +const sigset_t = linux.sigset_t; + +const linux = std.os.linux; +const sockaddr = linux.sockaddr; +const socklen_t = linux.socklen_t; +const iovec = linux.iovec; +const iovec_const = linux.iovec_const; + +pub const mode_t = usize; + +pub const SYS = extern enum(usize) { + restart_syscall = 0, + exit = 1, + fork = 2, + read = 3, + write = 4, + open = 5, + close = 6, + wait4 = 7, + creat = 8, + link = 9, + unlink = 10, + execv = 11, + chdir = 12, + chown = 13, + mknod = 14, + chmod = 15, + lchown = 16, + brk = 17, + perfctr = 18, + lseek = 19, + getpid = 20, + capget = 21, + capset = 22, + setuid = 23, + getuid = 24, + vmsplice = 25, + ptrace = 26, + alarm = 27, + sigaltstack = 28, + pause = 29, + utime = 30, + access = 33, + nice = 34, + sync = 36, + kill = 37, + stat = 38, + sendfile = 39, + lstat = 40, + dup = 41, + pipe = 42, + times = 43, + umount2 = 45, + setgid = 46, + getgid = 47, + signal = 48, + geteuid = 49, + getegid = 50, + acct = 51, + memory_ordering = 52, + ioctl = 54, + reboot = 55, + symlink = 57, + readlink = 58, + execve = 59, + umask = 60, + chroot = 61, + fstat = 62, + fstat64 = 63, + getpagesize = 64, + msync = 65, + vfork = 66, + pread64 = 67, + pwrite64 = 68, + mmap = 71, + munmap = 73, + mprotect = 74, + madvise = 75, + vhangup = 76, + mincore = 78, + getgroups = 79, + setgroups = 80, + getpgrp = 81, + setitimer = 83, + swapon = 85, + getitimer = 86, + sethostname = 88, + dup2 = 90, + fcntl = 92, + select = 93, + fsync = 95, + setpriority = 96, + socket = 97, + connect = 98, + accept = 99, + getpriority = 100, + rt_sigreturn = 101, + rt_sigaction = 102, + rt_sigprocmask = 103, + rt_sigpending = 104, + rt_sigtimedwait = 105, + rt_sigqueueinfo = 106, + rt_sigsuspend = 107, + setresuid = 108, + getresuid = 109, + setresgid = 110, + getresgid = 111, + recvmsg = 113, + sendmsg = 114, + gettimeofday = 116, + getrusage = 117, + getsockopt = 118, + getcwd = 119, + readv = 120, + writev = 121, + settimeofday = 122, + fchown = 123, + fchmod = 124, + recvfrom = 125, + setreuid = 126, + setregid = 127, + rename = 128, + truncate = 129, + ftruncate = 130, + flock = 131, + lstat64 = 132, + sendto = 133, + shutdown = 134, + socketpair = 135, + mkdir = 136, + rmdir = 137, + utimes = 138, + stat64 = 139, + sendfile64 = 140, + getpeername = 141, + futex = 142, + gettid = 143, + getrlimit = 144, + setrlimit = 145, + pivot_root = 146, + prctl = 147, + pciconfig_read = 148, + pciconfig_write = 149, + getsockname = 150, + inotify_init = 151, + inotify_add_watch = 152, + poll = 153, + getdents64 = 154, + inotify_rm_watch = 156, + statfs = 157, + fstatfs = 158, + umount = 159, + sched_set_affinity = 160, + sched_get_affinity = 161, + getdomainname = 162, + setdomainname = 163, + utrap_install = 164, + quotactl = 165, + set_tid_address = 166, + mount = 167, + ustat = 168, + setxattr = 169, + lsetxattr = 170, + fsetxattr = 171, + getxattr = 172, + lgetxattr = 173, + getdents = 174, + setsid = 175, + fchdir = 176, + fgetxattr = 177, + listxattr = 178, + llistxattr = 179, + flistxattr = 180, + removexattr = 181, + lremovexattr = 182, + sigpending = 183, + query_module = 184, + setpgid = 185, + fremovexattr = 186, + tkill = 187, + exit_group = 188, + uname = 189, + init_module = 190, + personality = 191, + remap_file_pages = 192, + epoll_create = 193, + epoll_ctl = 194, + epoll_wait = 195, + ioprio_set = 196, + getppid = 197, + sigaction = 198, + sgetmask = 199, + ssetmask = 200, + sigsuspend = 201, + oldlstat = 202, + uselib = 203, + readdir = 204, + readahead = 205, + socketcall = 206, + syslog = 207, + lookup_dcookie = 208, + fadvise64 = 209, + fadvise64_64 = 210, + tgkill = 211, + waitpid = 212, + swapoff = 213, + sysinfo = 214, + ipc = 215, + sigreturn = 216, + clone = 217, + ioprio_get = 218, + adjtimex = 219, + sigprocmask = 220, + create_module = 221, + delete_module = 222, + get_kernel_syms = 223, + getpgid = 224, + bdflush = 225, + sysfs = 226, + afs_syscall = 227, + setfsuid = 228, + setfsgid = 229, + _newselect = 230, + splice = 232, + stime = 233, + statfs64 = 234, + fstatfs64 = 235, + _llseek = 236, + mlock = 237, + munlock = 238, + mlockall = 239, + munlockall = 240, + sched_setparam = 241, + sched_getparam = 242, + sched_setscheduler = 243, + sched_getscheduler = 244, + sched_yield = 245, + sched_get_priority_max = 246, + sched_get_priority_min = 247, + sched_rr_get_interval = 248, + nanosleep = 249, + mremap = 250, + _sysctl = 251, + getsid = 252, + fdatasync = 253, + nfsservctl = 254, + sync_file_range = 255, + clock_settime = 256, + clock_gettime = 257, + clock_getres = 258, + clock_nanosleep = 259, + sched_getaffinity = 260, + sched_setaffinity = 261, + timer_settime = 262, + timer_gettime = 263, + timer_getoverrun = 264, + timer_delete = 265, + timer_create = 266, + vserver = 267, + io_setup = 268, + io_destroy = 269, + io_submit = 270, + io_cancel = 271, + io_getevents = 272, + mq_open = 273, + mq_unlink = 274, + mq_timedsend = 275, + mq_timedreceive = 276, + mq_notify = 277, + mq_getsetattr = 278, + waitid = 279, + tee = 280, + add_key = 281, + request_key = 282, + keyctl = 283, + openat = 284, + mkdirat = 285, + mknodat = 286, + fchownat = 287, + futimesat = 288, + fstatat64 = 289, + unlinkat = 290, + renameat = 291, + linkat = 292, + symlinkat = 293, + readlinkat = 294, + fchmodat = 295, + faccessat = 296, + pselect6 = 297, + ppoll = 298, + unshare = 299, + set_robust_list = 300, + get_robust_list = 301, + migrate_pages = 302, + mbind = 303, + get_mempolicy = 304, + set_mempolicy = 305, + kexec_load = 306, + move_pages = 307, + getcpu = 308, + epoll_pwait = 309, + utimensat = 310, + signalfd = 311, + timerfd_create = 312, + eventfd = 313, + fallocate = 314, + timerfd_settime = 315, + timerfd_gettime = 316, + signalfd4 = 317, + eventfd2 = 318, + epoll_create1 = 319, + dup3 = 320, + pipe2 = 321, + inotify_init1 = 322, + accept4 = 323, + preadv = 324, + pwritev = 325, + rt_tgsigqueueinfo = 326, + perf_event_open = 327, + recvmmsg = 328, + fanotify_init = 329, + fanotify_mark = 330, + prlimit64 = 331, + name_to_handle_at = 332, + open_by_handle_at = 333, + clock_adjtime = 334, + syncfs = 335, + sendmmsg = 336, + setns = 337, + process_vm_readv = 338, + process_vm_writev = 339, + kern_features = 340, + kcmp = 341, + finit_module = 342, + sched_setattr = 343, + sched_getattr = 344, + renameat2 = 345, + seccomp = 346, + getrandom = 347, + memfd_create = 348, + bpf = 349, + execveat = 350, + membarrier = 351, + userfaultfd = 352, + bind = 353, + listen = 354, + setsockopt = 355, + mlock2 = 356, + copy_file_range = 357, + preadv2 = 358, + pwritev2 = 359, + statx = 360, + io_pgetevents = 361, + pkey_mprotect = 362, + pkey_alloc = 363, + pkey_free = 364, + rseq = 365, + semtimedop = 392, + semget = 393, + semctl = 394, + shmget = 395, + shmctl = 396, + shmat = 397, + shmdt = 398, + msgget = 399, + msgsnd = 400, + msgrcv = 401, + msgctl = 402, + pidfd_send_signal = 424, + io_uring_setup = 425, + io_uring_enter = 426, + io_uring_register = 427, + open_tree = 428, + move_mount = 429, + fsopen = 430, + fsconfig = 431, + fsmount = 432, + fspick = 433, + pidfd_open = 434, + openat2 = 437, + pidfd_getfd = 438, + + _, +}; + +pub const O_CREAT = 0o100; +pub const O_EXCL = 0o200; +pub const O_NOCTTY = 0o400; +pub const O_TRUNC = 0o1000; +pub const O_APPEND = 0o2000; +pub const O_NONBLOCK = 0o4000; +pub const O_DSYNC = 0o10000; +pub const O_SYNC = 0o4010000; +pub const O_RSYNC = 0o4010000; +pub const O_DIRECTORY = 0o200000; +pub const O_NOFOLLOW = 0o400000; +pub const O_CLOEXEC = 0o2000000; + +pub const O_ASYNC = 0o20000; +pub const O_DIRECT = 0o40000; +pub const O_LARGEFILE = 0o100000; +pub const O_NOATIME = 0o1000000; +pub const O_PATH = 0o10000000; +pub const O_TMPFILE = 0o20200000; +pub const O_NDELAY = O_NONBLOCK; + +pub const F_DUPFD = 0; +pub const F_GETFD = 1; +pub const F_SETFD = 2; +pub const F_GETFL = 3; +pub const F_SETFL = 4; + +pub const F_SETOWN = 8; +pub const F_GETOWN = 9; +pub const F_SETSIG = 10; +pub const F_GETSIG = 11; + +pub const F_RDLCK = 0; +pub const F_WRLCK = 1; +pub const F_UNLCK = 2; + +pub const F_GETLK = 5; +pub const F_SETLK = 6; +pub const F_SETLKW = 7; + +pub const F_SETOWN_EX = 15; +pub const F_GETOWN_EX = 16; + +pub const F_GETOWNER_UIDS = 17; + +pub const LOCK_SH = 1; +pub const LOCK_EX = 2; +pub const LOCK_UN = 8; +pub const LOCK_NB = 4; + +/// stack-like segment +pub const MAP_GROWSDOWN = 0x0200; + +/// ETXTBSY +pub const MAP_DENYWRITE = 0x0800; + +/// mark it as an executable +pub const MAP_EXECUTABLE = 0x1000; + +/// pages are locked +pub const MAP_LOCKED = 0x0100; + +/// don't check for reservations +pub const MAP_NORESERVE = 0x0040; + +pub const VDSO_CGT_SYM = "__vdso_clock_gettime"; +pub const VDSO_CGT_VER = "LINUX_2.6"; + +// TODO do this + +pub const Flock = extern struct { + l_type: i16, + l_whence: i16, + l_start: off_t, + l_len: off_t, + l_pid: pid_t, +}; + +pub const msghdr = extern struct { + msg_name: ?*sockaddr, + msg_namelen: socklen_t, + msg_iov: [*]iovec, + msg_iovlen: u64, + msg_control: ?*c_void, + msg_controllen: u64, + msg_flags: i32, +}; + +pub const msghdr_const = extern struct { + msg_name: ?*const sockaddr, + msg_namelen: socklen_t, + msg_iov: [*]iovec_const, + msg_iovlen: u64, + msg_control: ?*c_void, + msg_controllen: u64, + msg_flags: i32, +}; + +pub const off_t = i64; +pub const ino_t = u64; + +/// Renamed to Stat to not conflict with the stat function. +/// atime, mtime, and ctime have functions to return `timespec`, +/// because although this is a POSIX API, the layout and names of +/// the structs are inconsistent across operating systems, and +/// in C, macros are used to hide the differences. Here we use +/// methods to accomplish this. +pub const Stat = extern struct { + dev: u64, + ino: ino_t, + mode: u32, + nlink: usize, + + uid: u32, + gid: u32, + rdev: u64, + __pad0: u32, + + size: off_t, + blksize: isize, + blocks: i64, + + atim: timespec, + mtim: timespec, + ctim: timespec, + __unused: [2]isize, + + pub fn atime(self: Stat) timespec { + return self.atim; + } + + pub fn mtime(self: Stat) timespec { + return self.mtim; + } + + pub fn ctime(self: Stat) timespec { + return self.ctim; + } +}; + +pub const timespec = extern struct { + tv_sec: isize, + tv_nsec: isize, +}; + +pub const timeval = extern struct { + tv_sec: isize, + tv_usec: isize, +}; + +pub const timezone = extern struct { + tz_minuteswest: i32, + tz_dsttime: i32, +}; + +pub const Elf_Symndx = u32; + +// TODO figure out how to do these on sparc64. + +pub const fpstate = extern struct { + regs: [32]u64, + fsr: u64, + gsr: u64, + fprs: u64, +}; +pub const fpregset_t = *fpstate; + +pub const siginfo_fpu_t = extern struct { + float_regs: [64]u32, + fsr: u64, + gsr: u64, + fprs: u64, +}; + +pub const sigcontext = extern struct { + info: [128]i8, + regs: extern struct { + u_regs: [16]u64, + tstate: u64, + tpc: u64, + tnpc: u64, + y: u64, + fprs: u64, + }, + fpu_save: *siginfo_fpu_t, + stack: extern struct { + sp: usize, + flags: i32, + size: u64, + }, + mask: u64, +}; + +pub const greg_t = u64; +pub const gregset_t = [19]greg_t; + +pub const fq = extern struct { + addr: *u64, + insn: u32, +}; + +pub const fpu_t = extern struct { + fregs: extern union { + sregs: [32]u32, + dregs: [32]u64, + qregs: [16]c_longdouble, + }, + fsr: u64, + fprs: u64, + fq: *fq, + qcnt: u8, + qentsz: u8, + enab: u8, +}; + +pub const mcontext_t = extern struct { + gregs: gregset_t, + fp: greg_t, + i7: greg_t, + fpregs: fpu_t, +}; + +pub const ucontext_t = extern struct { + link: *ucontext_t, + flags: u64, + __sigmask: u64, + mcontext: mcontext_t, + stack: stack_t, + sigmask: sigset_t, +}; From 206f96d474cb24cd8c00721b7ade96633b6b239f Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sat, 22 Aug 2020 14:35:03 +0700 Subject: [PATCH 03/28] Add sparc64 linux C ABI --- src/stage1/analyze.cpp | 5 +++-- src/stage1/target.cpp | 4 ++++ src/stage1/target.hpp | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp index 04c064efe3..d5f57aee81 100644 --- a/src/stage1/analyze.cpp +++ b/src/stage1/analyze.cpp @@ -1016,6 +1016,7 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) { target_is_arm(g->zig_target) || target_is_riscv(g->zig_target) || target_is_wasm(g->zig_target) || + target_is_sparc(g->zig_target) || target_is_ppc(g->zig_target)) { X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type); @@ -1988,7 +1989,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc // behaviour when checking expected alignment with `@ptrToInt(fn_ptr)` // or similar. This commit proposes to make `align` expressions a // compile error when compiled to Wasm architecture. - // + // // Some references: // [1] [Mozilla: WebAssembly Tables](https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format#WebAssembly_tables) // [2] [Sunfishcode's Wasm Ref Manual](https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#indirect-call) @@ -9044,7 +9045,7 @@ static void resolve_llvm_types_optional(CodeGen *g, ZigType *type, ResolveStatus 8 * child_type->abi_align, val_offset_in_bits, ZigLLVM_DIFlags_Zero, child_llvm_di_type); - di_element_types[maybe_null_index] = + di_element_types[maybe_null_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(type->llvm_di_type), "maybe", di_file, line, 8*g->builtin_types.entry_bool->abi_size, diff --git a/src/stage1/target.cpp b/src/stage1/target.cpp index 433c988a01..f10e95d04c 100644 --- a/src/stage1/target.cpp +++ b/src/stage1/target.cpp @@ -1196,6 +1196,10 @@ bool target_is_riscv(const ZigTarget *target) { return target->arch == ZigLLVM_riscv32 || target->arch == ZigLLVM_riscv64; } +bool target_is_sparc(const ZigTarget *target) { + return target->arch == ZigLLVM_sparc || target->arch == ZigLLVM_sparcv9; +} + bool target_is_mips(const ZigTarget *target) { return target->arch == ZigLLVM_mips || target->arch == ZigLLVM_mipsel || target->arch == ZigLLVM_mips64 || target->arch == ZigLLVM_mips64el; diff --git a/src/stage1/target.hpp b/src/stage1/target.hpp index d34c2aeae5..099c3c1e78 100644 --- a/src/stage1/target.hpp +++ b/src/stage1/target.hpp @@ -86,6 +86,7 @@ bool target_is_glibc(const ZigTarget *target); bool target_is_musl(const ZigTarget *target); bool target_is_wasm(const ZigTarget *target); bool target_is_riscv(const ZigTarget *target); +bool target_is_sparc(const ZigTarget *target); bool target_is_android(const ZigTarget *target); bool target_has_debug_info(const ZigTarget *target); const char *target_arch_musl_name(ZigLLVM_ArchType arch); From 23433fb3172597b10d57d9dda49fcd0d13950fb4 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sat, 22 Aug 2020 16:27:08 +0700 Subject: [PATCH 04/28] Fix register naming --- lib/std/os/bits/linux/sparc64.zig | 2 - lib/std/os/linux/sparc64.zig | 88 +++++++++++++++---------------- 2 files changed, 44 insertions(+), 46 deletions(-) diff --git a/lib/std/os/bits/linux/sparc64.zig b/lib/std/os/bits/linux/sparc64.zig index d90cb20ab2..ba2183acb1 100644 --- a/lib/std/os/bits/linux/sparc64.zig +++ b/lib/std/os/bits/linux/sparc64.zig @@ -546,8 +546,6 @@ pub const timezone = extern struct { pub const Elf_Symndx = u32; -// TODO figure out how to do these on sparc64. - pub const fpstate = extern struct { regs: [32]u64, fsr: u64, diff --git a/lib/std/os/linux/sparc64.zig b/lib/std/os/linux/sparc64.zig index 0cc5882b26..cb91ed21f3 100644 --- a/lib/std/os/linux/sparc64.zig +++ b/lib/std/os/linux/sparc64.zig @@ -15,9 +15,9 @@ pub fn syscall0(number: SYS) usize { \\ bcc %%xcc, 1f \\ neg %%o0 \\ 1: - : [ret] "={%o0}" (-> usize) - : [number] "{%g1}" (@enumToInt(number)) - : "memory", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7" + : [ret] "={o0}" (-> usize) + : [number] "{g1}" (@enumToInt(number)) + : "memory", "o1", "o2", "o3", "o4", "o5", "o7" ); } @@ -27,10 +27,10 @@ pub fn syscall1(number: SYS, arg1: usize) usize { \\ bcc %%xcc, 1f \\ neg %%o0 \\ 1: - : [ret] "={%o0}" (-> usize) - : [number] "{%g1}" (@enumToInt(number)), - [arg1] "{%o0}" (arg1) - : "memory", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7" + : [ret] "={o0}" (-> usize) + : [number] "{g1}" (@enumToInt(number)), + [arg1] "{o0}" (arg1) + : "memory", "o1", "o2", "o3", "o4", "o5", "o7" ); } @@ -40,11 +40,11 @@ pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize { \\ bcc %%xcc, 1f \\ neg %%o0 \\ 1: - : [ret] "={%o0}" (-> usize) - : [number] "{%g1}" (@enumToInt(number)), - [arg1] "{%o0}" (arg1), - [arg2] "{%o1}" (arg2) - : "memory", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7" + : [ret] "={o0}" (-> usize) + : [number] "{g1}" (@enumToInt(number)), + [arg1] "{o0}" (arg1), + [arg2] "{o1}" (arg2) + : "memory", "o1", "o2", "o3", "o4", "o5", "o7" ); } @@ -54,12 +54,12 @@ pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize { \\ bcc %%xcc, 1f \\ neg %%o0 \\ 1: - : [ret] "={%o0}" (-> usize) - : [number] "{%g1}" (@enumToInt(number)), - [arg1] "{%o0}" (arg1), - [arg2] "{%o1}" (arg2), - [arg3] "{%o2}" (arg3) - : "memory", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7" + : [ret] "={o0}" (-> usize) + : [number] "{g1}" (@enumToInt(number)), + [arg1] "{o0}" (arg1), + [arg2] "{o1}" (arg2), + [arg3] "{o2}" (arg3) + : "memory", "o1", "o2", "o3", "o4", "o5", "o7" ); } @@ -69,13 +69,13 @@ pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) \\ bcc %%xcc, 1f \\ neg %%o0 \\ 1: - : [ret] "={%o0}" (-> usize) - : [number] "{%g1}" (@enumToInt(number)), - [arg1] "{%o0}" (arg1), - [arg2] "{%o1}" (arg2), - [arg3] "{%o2}" (arg3), - [arg4] "{%o3}" (arg4) - : "memory", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7" + : [ret] "={o0}" (-> usize) + : [number] "{g1}" (@enumToInt(number)), + [arg1] "{o0}" (arg1), + [arg2] "{o1}" (arg2), + [arg3] "{o2}" (arg3), + [arg4] "{o3}" (arg4) + : "memory", "o1", "o2", "o3", "o4", "o5", "o7" ); } @@ -85,14 +85,14 @@ pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, \\ bcc %%xcc, 1f \\ neg %%o0 \\ 1: - : [ret] "={%o0}" (-> usize) - : [number] "{%g1}" (@enumToInt(number)), - [arg1] "{%o0}" (arg1), - [arg2] "{%o1}" (arg2), - [arg3] "{%o2}" (arg3), - [arg4] "{%o3}" (arg4), - [arg5] "{%o4}" (arg5), - : "memory", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7" + : [ret] "={o0}" (-> usize) + : [number] "{g1}" (@enumToInt(number)), + [arg1] "{o0}" (arg1), + [arg2] "{o1}" (arg2), + [arg3] "{o2}" (arg3), + [arg4] "{o3}" (arg4), + [arg5] "{o4}" (arg5), + : "memory", "o1", "o2", "o3", "o4", "o5", "o7" ); } @@ -110,15 +110,15 @@ pub fn syscall6( \\ bcc %%xcc, 1f \\ neg %%o0 \\ 1: - : [ret] "={%o0}" (-> usize) - : [number] "{%g1}" (@enumToInt(number)), - [arg1] "{%o0}" (arg1), - [arg2] "{%o1}" (arg2), - [arg3] "{%o2}" (arg3), - [arg4] "{%o3}" (arg4), - [arg5] "{%o4}" (arg5), - [arg6] "{%o5}" (arg6), - : "memory", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7" + : [ret] "={o0}" (-> usize) + : [number] "{g1}" (@enumToInt(number)), + [arg1] "{o0}" (arg1), + [arg2] "{o1}" (arg2), + [arg3] "{o2}" (arg3), + [arg4] "{o3}" (arg4), + [arg5] "{o4}" (arg5), + [arg6] "{o5}" (arg6), + : "memory", "o1", "o2", "o3", "o4", "o5", "o7" ); } @@ -130,7 +130,7 @@ pub const restore = restore_rt; pub fn restore_rt() callconv(.Naked) void { return asm volatile ("t 0x6d" : - : [number] "{%g1}" (@enumToInt(SYS.rt_sigreturn)) - : "memory", "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7" + : [number] "{g1}" (@enumToInt(SYS.rt_sigreturn)) + : "memory", "o0", "o1", "o2", "o3", "o4", "o5", "o7" ); } From c29da84c0e0793683904a32deb8a7eff1ba98b54 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sat, 22 Aug 2020 16:30:17 +0700 Subject: [PATCH 05/28] Add sp loading --- lib/std/os/bits/linux/sparc64.zig | 3 +++ lib/std/start.zig | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/lib/std/os/bits/linux/sparc64.zig b/lib/std/os/bits/linux/sparc64.zig index ba2183acb1..e216f8abaa 100644 --- a/lib/std/os/bits/linux/sparc64.zig +++ b/lib/std/os/bits/linux/sparc64.zig @@ -544,6 +544,9 @@ pub const timezone = extern struct { tz_dsttime: i32, }; +// TODO I'm not sure if the code below is correct, need someone with more +// knowledge about sparc64 linux internals to look into. + pub const Elf_Symndx = u32; pub const fpstate = extern struct { diff --git a/lib/std/start.zig b/lib/std/start.zig index 47164a0820..dae8251d9a 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -147,6 +147,11 @@ fn _start() callconv(.Naked) noreturn { : "r0" ); }, + .sparcv9 => { + starting_stack_ptr = asm ("" + : [argc] "={o6}" (-> [*]usize) + ); + }, else => @compileError("unsupported arch"), } // If LLVM inlines stack variables into _start, they will overwrite From dba009fd21f76759e41158909b558a7f9955daa0 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Fri, 28 Aug 2020 21:01:39 +0700 Subject: [PATCH 06/28] Account for the delay slot --- lib/std/os/linux/sparc64.zig | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/std/os/linux/sparc64.zig b/lib/std/os/linux/sparc64.zig index cb91ed21f3..d3dd551a25 100644 --- a/lib/std/os/linux/sparc64.zig +++ b/lib/std/os/linux/sparc64.zig @@ -1,18 +1,11 @@ usingnamespace @import("../bits.zig"); -// TODO: Handle the case of pipe(2) returning multiple values. -// From syscall(2)'s manual page: -// Some architectures (namely, Alpha, IA-64, MIPS, SuperH, sparc/32, and sparc/64) -// use an additional register ("Retval2" in the above table) to pass back a second -// return value from the pipe(2) system call; Alpha uses this technique in the -// architecture-specific getxpid(2), getxuid(2), and getxgid(2) system calls -// as well. Other architectures do not use the second return value register in -// the system call interface, even if it is defined in the System V ABI. pub fn syscall0(number: SYS) usize { return asm volatile ( \\ t 0x6d \\ bcc %%xcc, 1f + \\ nop \\ neg %%o0 \\ 1: : [ret] "={o0}" (-> usize) @@ -25,6 +18,7 @@ pub fn syscall1(number: SYS, arg1: usize) usize { return asm volatile ( \\ t 0x6d \\ bcc %%xcc, 1f + \\ nop \\ neg %%o0 \\ 1: : [ret] "={o0}" (-> usize) @@ -38,6 +32,7 @@ pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize { return asm volatile ( \\ t 0x6d \\ bcc %%xcc, 1f + \\ nop \\ neg %%o0 \\ 1: : [ret] "={o0}" (-> usize) @@ -52,6 +47,7 @@ pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize { return asm volatile ( \\ t 0x6d \\ bcc %%xcc, 1f + \\ nop \\ neg %%o0 \\ 1: : [ret] "={o0}" (-> usize) @@ -67,6 +63,7 @@ pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) return asm volatile ( \\ t 0x6d \\ bcc %%xcc, 1f + \\ nop \\ neg %%o0 \\ 1: : [ret] "={o0}" (-> usize) @@ -83,6 +80,7 @@ pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, return asm volatile ( \\ t 0x6d \\ bcc %%xcc, 1f + \\ nop \\ neg %%o0 \\ 1: : [ret] "={o0}" (-> usize) @@ -108,6 +106,7 @@ pub fn syscall6( return asm volatile ( \\ t 0x6d \\ bcc %%xcc, 1f + \\ nop \\ neg %%o0 \\ 1: : [ret] "={o0}" (-> usize) From 6146f81c6e5bb96f834a02dfd9cbadbe6e48e982 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Fri, 28 Aug 2020 21:42:26 +0700 Subject: [PATCH 07/28] Add pipe(2) support --- lib/std/os/linux.zig | 2 +- lib/std/os/linux/sparc64.zig | 34 ++++++++++++++++++++++++++-------- lib/std/target.zig | 7 +++++++ 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 0a675cf10f..af4f127228 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -381,7 +381,7 @@ pub fn faccessat(dirfd: i32, path: [*:0]const u8, mode: u32, flags: u32) usize { } pub fn pipe(fd: *[2]i32) usize { - if (comptime builtin.arch.isMIPS()) { + if (comptime builtin.arch.isMIPS() || comptime builtin.arch.isSPARC()) { return syscall_pipe(fd); } else if (@hasField(SYS, "pipe")) { return syscall1(.pipe, @ptrToInt(fd)); diff --git a/lib/std/os/linux/sparc64.zig b/lib/std/os/linux/sparc64.zig index d3dd551a25..dc0b5845b1 100644 --- a/lib/std/os/linux/sparc64.zig +++ b/lib/std/os/linux/sparc64.zig @@ -1,5 +1,23 @@ usingnamespace @import("../bits.zig"); +pub fn syscall_pipe(fd: *[2]i32) usize { + return asm volatile ( + \\ mov %%o0, %%o2 + \\ t 0x6d + \\ bcc %%xcc, 1f + \\ nop + \\ ba 2f + \\ neg %%o0 + \\ 1: + \\ st %%o0, [%%o2] + \\ st %%o1, [%%o2 + 4] + \\ clr %%o0 + \\ 2: + : [ret] "={o0}" (-> usize) + : [number] "{$2}" (@enumToInt(SYS.pipe)) + : "memory", "xcc", "o1", "o2", "o3", "o4", "o5", "o7" + ); +} pub fn syscall0(number: SYS) usize { return asm volatile ( @@ -10,7 +28,7 @@ pub fn syscall0(number: SYS) usize { \\ 1: : [ret] "={o0}" (-> usize) : [number] "{g1}" (@enumToInt(number)) - : "memory", "o1", "o2", "o3", "o4", "o5", "o7" + : "memory", "xcc", "o1", "o2", "o3", "o4", "o5", "o7" ); } @@ -24,7 +42,7 @@ pub fn syscall1(number: SYS, arg1: usize) usize { : [ret] "={o0}" (-> usize) : [number] "{g1}" (@enumToInt(number)), [arg1] "{o0}" (arg1) - : "memory", "o1", "o2", "o3", "o4", "o5", "o7" + : "memory", "xcc", "o1", "o2", "o3", "o4", "o5", "o7" ); } @@ -39,7 +57,7 @@ pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize { : [number] "{g1}" (@enumToInt(number)), [arg1] "{o0}" (arg1), [arg2] "{o1}" (arg2) - : "memory", "o1", "o2", "o3", "o4", "o5", "o7" + : "memory", "xcc", "o1", "o2", "o3", "o4", "o5", "o7" ); } @@ -55,7 +73,7 @@ pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize { [arg1] "{o0}" (arg1), [arg2] "{o1}" (arg2), [arg3] "{o2}" (arg3) - : "memory", "o1", "o2", "o3", "o4", "o5", "o7" + : "memory", "xcc", "o1", "o2", "o3", "o4", "o5", "o7" ); } @@ -72,7 +90,7 @@ pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) [arg2] "{o1}" (arg2), [arg3] "{o2}" (arg3), [arg4] "{o3}" (arg4) - : "memory", "o1", "o2", "o3", "o4", "o5", "o7" + : "memory", "xcc", "o1", "o2", "o3", "o4", "o5", "o7" ); } @@ -90,7 +108,7 @@ pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, [arg3] "{o2}" (arg3), [arg4] "{o3}" (arg4), [arg5] "{o4}" (arg5), - : "memory", "o1", "o2", "o3", "o4", "o5", "o7" + : "memory", "xcc", "o1", "o2", "o3", "o4", "o5", "o7" ); } @@ -117,7 +135,7 @@ pub fn syscall6( [arg4] "{o3}" (arg4), [arg5] "{o4}" (arg5), [arg6] "{o5}" (arg6), - : "memory", "o1", "o2", "o3", "o4", "o5", "o7" + : "memory", "xcc", "o1", "o2", "o3", "o4", "o5", "o7" ); } @@ -130,6 +148,6 @@ pub fn restore_rt() callconv(.Naked) void { return asm volatile ("t 0x6d" : : [number] "{g1}" (@enumToInt(SYS.rt_sigreturn)) - : "memory", "o0", "o1", "o2", "o3", "o4", "o5", "o7" + : "memory", "xcc", "o0", "o1", "o2", "o3", "o4", "o5", "o7" ); } diff --git a/lib/std/target.zig b/lib/std/target.zig index 7fbac8a4be..798a90bbdf 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -761,6 +761,13 @@ pub const Target = struct { }; } + pub fn isSPARC(arch: Arch) bool { + return switch (arch) { + .sparcv8, .sparcv9 => true, + else => false, + }; + } + pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model { for (arch.allCpuModels()) |cpu| { if (mem.eql(u8, cpu_name, cpu.name)) { From 300cfbf252b5798c696a9ccd0abf4ed474260de6 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Fri, 28 Aug 2020 21:48:10 +0700 Subject: [PATCH 08/28] Add TLS implementation for sparc64 --- lib/std/os/linux/tls.zig | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index 69e7816f13..4f2ada90b9 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -54,7 +54,7 @@ const TLSVariant = enum { const tls_variant = switch (builtin.arch) { .arm, .armeb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => TLSVariant.VariantI, - .x86_64, .i386 => TLSVariant.VariantII, + .x86_64, .i386, .sparcv9 => TLSVariant.VariantII, else => @compileError("undefined tls_variant for this architecture"), }; @@ -168,6 +168,11 @@ pub fn setThreadPointer(addr: usize) void { .powerpc, .powerpc64, .powerpc64le => { asm volatile ( \\ mr 13, %[addr] + ); + }, + .sparcv9 => { + asm volatile ( + \\ mov %[addr], %%g7 : : [addr] "r" (addr) ); From 341eec71fd430def554cb48fd7b8db4f081cd946 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sat, 29 Aug 2020 11:50:07 +0700 Subject: [PATCH 09/28] Add clone(2) implementation This implementation kindly provided by @LemonBoy at GitHub https://github.com/ziglang/zig/pull/6187#issuecomment-682635168 --- lib/std/special/c.zig | 45 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/lib/std/special/c.zig b/lib/std/special/c.zig index e0583f4302..c50aa940d3 100644 --- a/lib/std/special/c.zig +++ b/lib/std/special/c.zig @@ -479,7 +479,6 @@ fn clone() callconv(.Naked) void { \\ syscall ); }, - .powerpc64, .powerpc64le => { asm volatile ( \\ # store non-volatile regs r30, r31 on stack in order to put our @@ -528,7 +527,51 @@ fn clone() callconv(.Naked) void { \\ blr ); }, + .sparcv9 => { + // Implementation by @LemonBoy (https://github.com/LemonBoy) + // __clone(func, stack, flags, arg, ptid, tls, ctid) + // i0, i1, i2, i3, i4, i5, sp + // syscall(SYS_clone, flags, stack, ptid, tls, ctid) + // g1 o0, o1, o2, o3, o4 + asm volatile ( + \\ save %%sp, -192, %%sp + \\ # Save the func pointer and the arg pointer + \\ mov %%i0, %%g2 + \\ mov %%i3, %%g3 + \\ # Shuffle the arguments + \\ mov 217, %%g1 + \\ mov %%i2, %%o0 + \\ sub %%i1, 2047, %%o1 + \\ mov %%i4, %%o2 + \\ mov %%i5, %%o3 + \\ ldx [%%fp + 192 - 2*8 + 2047], %%o4 + \\ t 0x6d + \\ bcs,pn %%xcc, 2f + \\ nop + \\ # sparc64 returns the child pid in o0 and a flag telling + \\ # whether the process is the child in o1 + \\ brnz %%o1, 1f + \\ nop + \\ # This is the parent process, return the child pid + \\ mov %%o0, %%i0 + \\ ret + \\ restore + \\1: + \\ # This is the child process + \\ mov %%g0, %%fp + \\ call %%g2 + \\ mov %%g3, %%o0 + \\ # Exit + \\ mov 1, %%g1 + \\ t 0x6d + \\2: + \\ # The syscall failed + \\ sub %%g0, %%o0, %%i0 + \\ ret + \\ restore + ); + }, else => @compileError("Implement clone() for this arch."), } } From cefbe4e7bec28d9a048581d15431b20c9619bfc6 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sat, 29 Aug 2020 13:12:50 +0700 Subject: [PATCH 10/28] Use correct names for generic SPARC targets LLVM calls generic sparc32 CPUs "v8" and generic sparc64 CPUs "v9". --- lib/std/target.zig | 3 ++- lib/std/target/sparc.zig | 5 ----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/std/target.zig b/lib/std/target.zig index 798a90bbdf..66008ef6c2 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -1127,7 +1127,8 @@ pub const Target = struct { .amdgcn => &amdgpu.cpu.generic, .riscv32 => &riscv.cpu.generic_rv32, .riscv64 => &riscv.cpu.generic_rv64, - .sparc, .sparcv9, .sparcel => &sparc.cpu.generic, + .sparc, .sparcel => &sparc.cpu.v8, + .sparcv9 => &sparc.cpu.v9, .s390x => &systemz.cpu.generic, .i386 => &x86.cpu._i386, .x86_64 => &x86.cpu.x86_64, diff --git a/lib/std/target/sparc.zig b/lib/std/target/sparc.zig index 8baac12635..4b6698e8de 100644 --- a/lib/std/target/sparc.zig +++ b/lib/std/target/sparc.zig @@ -160,11 +160,6 @@ pub const cpu = struct { .llvm_name = "f934", .features = featureSet(&[_]Feature{}), }; - pub const generic = CpuModel{ - .name = "generic", - .llvm_name = "generic", - .features = featureSet(&[_]Feature{}), - }; pub const gr712rc = CpuModel{ .name = "gr712rc", .llvm_name = "gr712rc", From 238f253de95aef0afe6c245dbbf4ef75dc616cc2 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sat, 29 Aug 2020 22:11:48 +0700 Subject: [PATCH 11/28] Move comptime out --- lib/std/os/linux.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index af4f127228..a17c99a6a9 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -381,7 +381,7 @@ pub fn faccessat(dirfd: i32, path: [*:0]const u8, mode: u32, flags: u32) usize { } pub fn pipe(fd: *[2]i32) usize { - if (comptime builtin.arch.isMIPS() || comptime builtin.arch.isSPARC()) { + if (comptime (builtin.arch.isMIPS() || builtin.arch.isSPARC())) { return syscall_pipe(fd); } else if (@hasField(SYS, "pipe")) { return syscall1(.pipe, @ptrToInt(fd)); From 268516d5d90cfb183a4986e7e04b05b41c3dd1e0 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sat, 24 Oct 2020 15:52:10 +0700 Subject: [PATCH 12/28] Fix constants --- lib/std/os/bits/linux/sparc64.zig | 61 ++++++++++++++----------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/lib/std/os/bits/linux/sparc64.zig b/lib/std/os/bits/linux/sparc64.zig index e216f8abaa..dc18fe7a0b 100644 --- a/lib/std/os/bits/linux/sparc64.zig +++ b/lib/std/os/bits/linux/sparc64.zig @@ -389,26 +389,26 @@ pub const SYS = extern enum(usize) { _, }; -pub const O_CREAT = 0o100; -pub const O_EXCL = 0o200; -pub const O_NOCTTY = 0o400; -pub const O_TRUNC = 0o1000; -pub const O_APPEND = 0o2000; -pub const O_NONBLOCK = 0o4000; -pub const O_DSYNC = 0o10000; -pub const O_SYNC = 0o4010000; -pub const O_RSYNC = 0o4010000; -pub const O_DIRECTORY = 0o200000; -pub const O_NOFOLLOW = 0o400000; -pub const O_CLOEXEC = 0o2000000; +pub const O_CREAT = 0x200; +pub const O_EXCL = 0x800; +pub const O_NOCTTY = 0x8000; +pub const O_TRUNC = 0x400; +pub const O_APPEND = 0x8; +pub const O_NONBLOCK = 0x4000; +pub const O_SYNC = 0x802000; +pub const O_DSYNC = 0x2000; +pub const O_RSYNC = O_SYNC; +pub const O_DIRECTORY = 0x10000; +pub const O_NOFOLLOW = 0x20000; +pub const O_CLOEXEC = 0x400000; -pub const O_ASYNC = 0o20000; -pub const O_DIRECT = 0o40000; -pub const O_LARGEFILE = 0o100000; -pub const O_NOATIME = 0o1000000; -pub const O_PATH = 0o10000000; -pub const O_TMPFILE = 0o20200000; -pub const O_NDELAY = O_NONBLOCK; +pub const O_ASYNC = 0x40; +pub const O_DIRECT = 0x100000; +pub const O_LARGEFILE = 0; +pub const O_NOATIME = 0x200000; +pub const O_PATH = 0x1000000; +pub const O_TMPFILE = 0x2010000; +pub const O_NDELAY = O_NONBLOCK | 0x4; pub const F_DUPFD = 0; pub const F_GETFD = 1; @@ -416,18 +416,15 @@ pub const F_SETFD = 2; pub const F_GETFL = 3; pub const F_SETFL = 4; -pub const F_SETOWN = 8; -pub const F_GETOWN = 9; -pub const F_SETSIG = 10; -pub const F_GETSIG = 11; +pub const F_SETOWN = 5; +pub const F_GETOWN = 6; +pub const F_GETLK = 7; +pub const F_SETLK = 8; +pub const F_SETLKW = 9; -pub const F_RDLCK = 0; -pub const F_WRLCK = 1; -pub const F_UNLCK = 2; - -pub const F_GETLK = 5; -pub const F_SETLK = 6; -pub const F_SETLKW = 7; +pub const F_RDLCK = 1; +pub const F_WRLCK = 2; +pub const F_UNLCK = 3; pub const F_SETOWN_EX = 15; pub const F_GETOWN_EX = 16; @@ -436,8 +433,8 @@ pub const F_GETOWNER_UIDS = 17; pub const LOCK_SH = 1; pub const LOCK_EX = 2; -pub const LOCK_UN = 8; pub const LOCK_NB = 4; +pub const LOCK_UN = 8; /// stack-like segment pub const MAP_GROWSDOWN = 0x0200; @@ -457,8 +454,6 @@ pub const MAP_NORESERVE = 0x0040; pub const VDSO_CGT_SYM = "__vdso_clock_gettime"; pub const VDSO_CGT_VER = "LINUX_2.6"; -// TODO do this - pub const Flock = extern struct { l_type: i16, l_whence: i16, From cdbf66e36ec110993347e5158005ec1cc0adaf13 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sat, 24 Oct 2020 19:52:52 +0700 Subject: [PATCH 13/28] Add sparc64-specific values for the various SA_ and SIG_ constants --- lib/std/os/bits/linux.zig | 19 +++++++++++++++++-- lib/std/target.zig | 2 +- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig index ab9fe9ffb4..087f06672b 100644 --- a/lib/std/os/bits/linux.zig +++ b/lib/std/os/bits/linux.zig @@ -31,6 +31,7 @@ pub usingnamespace @import("linux/securebits.zig"); const is_mips = builtin.arch.isMIPS(); const is_ppc64 = builtin.arch.isPPC64(); +const is_sparc = builtin.arch.isSPARC(); pub const pid_t = i32; pub const fd_t = i32; @@ -183,16 +184,32 @@ pub usingnamespace if (is_mips) pub const SA_NOCLDSTOP = 1; pub const SA_NOCLDWAIT = 0x10000; pub const SA_SIGINFO = 8; + pub const SA_RESTART = 0x10000000; + pub const SA_RESETHAND = 0x80000000; pub const SIG_BLOCK = 1; pub const SIG_UNBLOCK = 2; pub const SIG_SETMASK = 3; } +else if (is_sparc) + struct { + pub const SA_NOCLDSTOP = 1; + pub const SA_NOCLDWAIT = 2; + pub const SA_SIGINFO = 0x200; + pub const SA_RESTART = 0x2; + pub const SA_RESETHAND = 0x4; + + pub const SIG_BLOCK = 0; + pub const SIG_UNBLOCK = 1; + pub const SIG_SETMASK = 2; + } else struct { pub const SA_NOCLDSTOP = 1; pub const SA_NOCLDWAIT = 2; pub const SA_SIGINFO = 4; + pub const SA_RESTART = 0x10000000; + pub const SA_RESETHAND = 0x80000000; pub const SIG_BLOCK = 0; pub const SIG_UNBLOCK = 1; @@ -200,9 +217,7 @@ else }; pub const SA_ONSTACK = 0x08000000; -pub const SA_RESTART = 0x10000000; pub const SA_NODEFER = 0x40000000; -pub const SA_RESETHAND = 0x80000000; pub const SA_RESTORER = 0x04000000; pub const SIGHUP = 1; diff --git a/lib/std/target.zig b/lib/std/target.zig index 66008ef6c2..45b182982a 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -763,7 +763,7 @@ pub const Target = struct { pub fn isSPARC(arch: Arch) bool { return switch (arch) { - .sparcv8, .sparcv9 => true, + .sparc, .sparcel, .sparcv9 => true, else => false, }; } From 792526c0bd45754bced18298573ad2a145a7141e Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sat, 24 Oct 2020 19:54:58 +0700 Subject: [PATCH 14/28] Fix sparc64 argument loading --- lib/std/start.zig | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/std/start.zig b/lib/std/start.zig index dae8251d9a..8bb9780e27 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -148,8 +148,14 @@ fn _start() callconv(.Naked) noreturn { ); }, .sparcv9 => { - starting_stack_ptr = asm ("" - : [argc] "={o6}" (-> [*]usize) + // On sparc64, the stack pointer register points to a place + // 2047 bytes below the actual stack. Also, argc and friends are + // placed starting at [stack-start + 128], so we need to account for that too. + // Ref: System V Application Binary Interface: SPARC Version 9 Processor Supplement + // Version 1.35, figure 3-16. + // TODO: find a better way to do this. + starting_stack_ptr = asm ("add %%o6, 2175, %[argc]" + : [argc] "=r" (-> [*]usize) ); }, else => @compileError("unsupported arch"), From 73e62f22ecf25e58db343a45dfce35fccd8a4fa3 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sat, 24 Oct 2020 19:58:01 +0700 Subject: [PATCH 15/28] Fix sigaction(2) call on sparc64 --- lib/std/os/linux.zig | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index a17c99a6a9..bb8ce00efe 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -818,7 +818,12 @@ pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigacti var ksa_old: k_sigaction = undefined; const ksa_mask_size = @sizeOf(@TypeOf(ksa_old.mask)); @memcpy(@ptrCast([*]u8, &ksa.mask), @ptrCast([*]const u8, &act.mask), ksa_mask_size); - const result = syscall4(.rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), ksa_mask_size); + const result = switch (builtin.arch) { + // The sparc version of rt_sigaction needs the restorer function to be passed as an argument too. + .sparc, .sparcv9 => syscall5(.rt_sigaction, sig, + @ptrToInt(&ksa), @ptrToInt(&ksa_old), @ptrToInt(ksa.restorer), ksa_mask_size), + else => syscall4(.rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), ksa_mask_size), + }; const err = getErrno(result); if (err != 0) { return result; From e7369ada936e6bf744ab8d119f6b3b435b0be8cd Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sat, 24 Oct 2020 21:33:40 +0700 Subject: [PATCH 16/28] Fix boolean operator in if clause --- lib/std/os/linux.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index bb8ce00efe..05543a9e3f 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -381,7 +381,7 @@ pub fn faccessat(dirfd: i32, path: [*:0]const u8, mode: u32, flags: u32) usize { } pub fn pipe(fd: *[2]i32) usize { - if (comptime (builtin.arch.isMIPS() || builtin.arch.isSPARC())) { + if (comptime (builtin.arch.isMIPS() or builtin.arch.isSPARC())) { return syscall_pipe(fd); } else if (@hasField(SYS, "pipe")) { return syscall1(.pipe, @ptrToInt(fd)); From 1d3abb761d49a88a3245220cb470e2621867442e Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sun, 25 Oct 2020 13:37:03 +0700 Subject: [PATCH 17/28] "zig fmt" on lib/std/os/linux.zig --- lib/std/os/linux.zig | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 05543a9e3f..765ed06cf3 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -820,8 +820,7 @@ pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigacti @memcpy(@ptrCast([*]u8, &ksa.mask), @ptrCast([*]const u8, &act.mask), ksa_mask_size); const result = switch (builtin.arch) { // The sparc version of rt_sigaction needs the restorer function to be passed as an argument too. - .sparc, .sparcv9 => syscall5(.rt_sigaction, sig, - @ptrToInt(&ksa), @ptrToInt(&ksa_old), @ptrToInt(ksa.restorer), ksa_mask_size), + .sparc, .sparcv9 => syscall5(.rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), @ptrToInt(ksa.restorer), ksa_mask_size), else => syscall4(.rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), ksa_mask_size), }; const err = getErrno(result); @@ -1280,13 +1279,7 @@ pub fn setrlimit(resource: rlimit_resource, rlim: *const rlimit) usize { } pub fn prlimit(pid: pid_t, resource: rlimit_resource, new_limit: ?*const rlimit, old_limit: ?*rlimit) usize { - return syscall4( - .prlimit64, - @bitCast(usize, @as(isize, pid)), - @bitCast(usize, @as(isize, @enumToInt(resource))), - @ptrToInt(new_limit), - @ptrToInt(old_limit) - ); + return syscall4(.prlimit64, @bitCast(usize, @as(isize, pid)), @bitCast(usize, @as(isize, @enumToInt(resource))), @ptrToInt(new_limit), @ptrToInt(old_limit)); } test "" { From 2e7a4758b30323939fad5b3a5a5421ab93f60fad Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sun, 25 Oct 2020 13:39:22 +0700 Subject: [PATCH 18/28] Add back ppc input/output/clobber definitions Accidentally removed when rebasing, this adds it back. --- lib/std/os/linux/tls.zig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index 4f2ada90b9..f6c339bc2c 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -168,6 +168,8 @@ pub fn setThreadPointer(addr: usize) void { .powerpc, .powerpc64, .powerpc64le => { asm volatile ( \\ mr 13, %[addr] + : + : [addr] "r" (addr) ); }, .sparcv9 => { From f0182010099a437146c0c5ae7c7c7d80bd2fbab4 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sun, 25 Oct 2020 20:07:18 +0700 Subject: [PATCH 19/28] Predict error-less path on syscalls --- lib/std/os/linux/sparc64.zig | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/std/os/linux/sparc64.zig b/lib/std/os/linux/sparc64.zig index dc0b5845b1..c3c95424a0 100644 --- a/lib/std/os/linux/sparc64.zig +++ b/lib/std/os/linux/sparc64.zig @@ -4,7 +4,7 @@ pub fn syscall_pipe(fd: *[2]i32) usize { return asm volatile ( \\ mov %%o0, %%o2 \\ t 0x6d - \\ bcc %%xcc, 1f + \\ bcc,pt %%xcc, 1f \\ nop \\ ba 2f \\ neg %%o0 @@ -21,8 +21,8 @@ pub fn syscall_pipe(fd: *[2]i32) usize { pub fn syscall0(number: SYS) usize { return asm volatile ( - \\ t 0x6d - \\ bcc %%xcc, 1f + \\ t 0x6d + \\ bcc,pt %%xcc, 1f \\ nop \\ neg %%o0 \\ 1: @@ -34,8 +34,8 @@ pub fn syscall0(number: SYS) usize { pub fn syscall1(number: SYS, arg1: usize) usize { return asm volatile ( - \\ t 0x6d - \\ bcc %%xcc, 1f + \\ t 0x6d + \\ bcc,pt %%xcc, 1f \\ nop \\ neg %%o0 \\ 1: @@ -48,8 +48,8 @@ pub fn syscall1(number: SYS, arg1: usize) usize { pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize { return asm volatile ( - \\ t 0x6d - \\ bcc %%xcc, 1f + \\ t 0x6d + \\ bcc,pt %%xcc, 1f \\ nop \\ neg %%o0 \\ 1: @@ -63,8 +63,8 @@ pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize { pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize { return asm volatile ( - \\ t 0x6d - \\ bcc %%xcc, 1f + \\ t 0x6d + \\ bcc,pt %%xcc, 1f \\ nop \\ neg %%o0 \\ 1: @@ -79,8 +79,8 @@ pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize { pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize { return asm volatile ( - \\ t 0x6d - \\ bcc %%xcc, 1f + \\ t 0x6d + \\ bcc,pt %%xcc, 1f \\ nop \\ neg %%o0 \\ 1: @@ -96,8 +96,8 @@ pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize { return asm volatile ( - \\ t 0x6d - \\ bcc %%xcc, 1f + \\ t 0x6d + \\ bcc,pt %%xcc, 1f \\ nop \\ neg %%o0 \\ 1: @@ -122,8 +122,8 @@ pub fn syscall6( arg6: usize, ) usize { return asm volatile ( - \\ t 0x6d - \\ bcc %%xcc, 1f + \\ t 0x6d + \\ bcc,pt %%xcc, 1f \\ nop \\ neg %%o0 \\ 1: From 785153d756e2148a30a1e2d7987bedda1ae2d570 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sun, 25 Oct 2020 20:39:32 +0700 Subject: [PATCH 20/28] Fix SA_* constants for sparc64 --- lib/std/os/bits/linux.zig | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig index 087f06672b..8029c2e4f3 100644 --- a/lib/std/os/bits/linux.zig +++ b/lib/std/os/bits/linux.zig @@ -186,6 +186,9 @@ pub usingnamespace if (is_mips) pub const SA_SIGINFO = 8; pub const SA_RESTART = 0x10000000; pub const SA_RESETHAND = 0x80000000; + pub const SA_ONSTACK = 0x08000000; + pub const SA_NODEFER = 0x40000000; + pub const SA_RESTORER = 0x04000000; pub const SIG_BLOCK = 1; pub const SIG_UNBLOCK = 2; @@ -193,15 +196,18 @@ pub usingnamespace if (is_mips) } else if (is_sparc) struct { - pub const SA_NOCLDSTOP = 1; - pub const SA_NOCLDWAIT = 2; + pub const SA_NOCLDSTOP = 0x8; + pub const SA_NOCLDWAIT = 0x100; pub const SA_SIGINFO = 0x200; pub const SA_RESTART = 0x2; pub const SA_RESETHAND = 0x4; + pub const SA_ONSTACK = 0x1; + pub const SA_NODEFER = 0x20; + pub const SA_RESTORER = 0x04000000; - pub const SIG_BLOCK = 0; - pub const SIG_UNBLOCK = 1; - pub const SIG_SETMASK = 2; + pub const SIG_BLOCK = 1; + pub const SIG_UNBLOCK = 2; + pub const SIG_SETMASK = 4; } else struct { @@ -210,16 +216,15 @@ else pub const SA_SIGINFO = 4; pub const SA_RESTART = 0x10000000; pub const SA_RESETHAND = 0x80000000; + pub const SA_ONSTACK = 0x08000000; + pub const SA_NODEFER = 0x40000000; + pub const SA_RESTORER = 0x04000000; pub const SIG_BLOCK = 0; pub const SIG_UNBLOCK = 1; pub const SIG_SETMASK = 2; }; -pub const SA_ONSTACK = 0x08000000; -pub const SA_NODEFER = 0x40000000; -pub const SA_RESTORER = 0x04000000; - pub const SIGHUP = 1; pub const SIGINT = 2; pub const SIGQUIT = 3; From 1a362ea5b032d7e7f0300e0d9ace1b36b164576c Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sun, 25 Oct 2020 21:38:39 +0700 Subject: [PATCH 21/28] Fix sparc64 bits definitions --- lib/std/os/bits/linux/sparc64.zig | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/lib/std/os/bits/linux/sparc64.zig b/lib/std/os/bits/linux/sparc64.zig index dc18fe7a0b..3dd8d2abfe 100644 --- a/lib/std/os/bits/linux/sparc64.zig +++ b/lib/std/os/bits/linux/sparc64.zig @@ -550,7 +550,31 @@ pub const fpstate = extern struct { gsr: u64, fprs: u64, }; -pub const fpregset_t = *fpstate; + +pub const __fpq = extern struct { + fpq_addr: *u32, + fpq_instr: u32, +}; + +pub const __fq = extern struct { + FQu: extern union { + whole: f64, + fpq: __fpq, + }, +}; + +pub const fpregset_t = extern struct { + fpu_fr: extern union { + fpu_regs: [32]u32, + fpu_dregs: [32]f64, + fpu_qregs: [16]c_longdouble, + }, + fpu_q: *__fq, + fpu_fsr: u64, + fpu_qcnt: u8, + fpu_q_entrysize: u8, + fpu_en: u8, +}; pub const siginfo_fpu_t = extern struct { float_regs: [64]u32, @@ -594,6 +618,7 @@ pub const fpu_t = extern struct { }, fsr: u64, fprs: u64, + gsr: u64, fq: *fq, qcnt: u8, qentsz: u8, @@ -603,14 +628,14 @@ pub const fpu_t = extern struct { pub const mcontext_t = extern struct { gregs: gregset_t, fp: greg_t, - i7: greg_t, + @"i7": greg_t, fpregs: fpu_t, }; pub const ucontext_t = extern struct { link: *ucontext_t, flags: u64, - __sigmask: u64, + sigmask: u64, mcontext: mcontext_t, stack: stack_t, sigmask: sigset_t, From 5474d4338905e8535b13391f952830a15bc5eaeb Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sun, 25 Oct 2020 21:51:01 +0700 Subject: [PATCH 22/28] Zero %i6 to terminate backchain --- lib/std/start.zig | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/std/start.zig b/lib/std/start.zig index 8bb9780e27..b1cbefcc67 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -148,13 +148,10 @@ fn _start() callconv(.Naked) noreturn { ); }, .sparcv9 => { - // On sparc64, the stack pointer register points to a place - // 2047 bytes below the actual stack. Also, argc and friends are - // placed starting at [stack-start + 128], so we need to account for that too. - // Ref: System V Application Binary Interface: SPARC Version 9 Processor Supplement - // Version 1.35, figure 3-16. - // TODO: find a better way to do this. - starting_stack_ptr = asm ("add %%o6, 2175, %[argc]" + // argc is stored after a register window (16 registers) plus stack bias + starting_stack_ptr = asm ( + \\ mov %%g0, %%i6 + \\ add %%o6, 2175, %[argc] : [argc] "=r" (-> [*]usize) ); }, From 3ce9428e3d617625227bf6b61cae0b4ded946bfe Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sun, 25 Oct 2020 21:53:16 +0700 Subject: [PATCH 23/28] Various formatting fixes --- lib/std/os/linux.zig | 8 +++++++- lib/std/special/c.zig | 2 -- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 765ed06cf3..da17799566 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -1279,7 +1279,13 @@ pub fn setrlimit(resource: rlimit_resource, rlim: *const rlimit) usize { } pub fn prlimit(pid: pid_t, resource: rlimit_resource, new_limit: ?*const rlimit, old_limit: ?*rlimit) usize { - return syscall4(.prlimit64, @bitCast(usize, @as(isize, pid)), @bitCast(usize, @as(isize, @enumToInt(resource))), @ptrToInt(new_limit), @ptrToInt(old_limit)); + return syscall4( + .prlimit64, + @bitCast(usize, @as(isize, pid)), + @bitCast(usize, @as(isize, @enumToInt(resource))), + @ptrToInt(new_limit), + @ptrToInt(old_limit), + ); } test "" { diff --git a/lib/std/special/c.zig b/lib/std/special/c.zig index c50aa940d3..462dcb537f 100644 --- a/lib/std/special/c.zig +++ b/lib/std/special/c.zig @@ -528,10 +528,8 @@ fn clone() callconv(.Naked) void { ); }, .sparcv9 => { - // Implementation by @LemonBoy (https://github.com/LemonBoy) // __clone(func, stack, flags, arg, ptid, tls, ctid) // i0, i1, i2, i3, i4, i5, sp - // syscall(SYS_clone, flags, stack, ptid, tls, ctid) // g1 o0, o1, o2, o3, o4 asm volatile ( From cbc8750502630cc38c0c776a76393e766c609124 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Sun, 25 Oct 2020 23:52:08 +0700 Subject: [PATCH 24/28] Separate libc stat and kernel stat definitions --- lib/std/os/bits/linux/sparc64.zig | 45 ++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/lib/std/os/bits/linux/sparc64.zig b/lib/std/os/bits/linux/sparc64.zig index 3dd8d2abfe..8b073c5c08 100644 --- a/lib/std/os/bits/linux/sparc64.zig +++ b/lib/std/os/bits/linux/sparc64.zig @@ -12,8 +12,6 @@ const socklen_t = linux.socklen_t; const iovec = linux.iovec; const iovec_const = linux.iovec_const; -pub const mode_t = usize; - pub const SYS = extern enum(usize) { restart_syscall = 0, exit = 1, @@ -484,14 +482,14 @@ pub const msghdr_const = extern struct { pub const off_t = i64; pub const ino_t = u64; +pub const mode_t = u32; -/// Renamed to Stat to not conflict with the stat function. /// atime, mtime, and ctime have functions to return `timespec`, /// because although this is a POSIX API, the layout and names of /// the structs are inconsistent across operating systems, and /// in C, macros are used to hide the differences. Here we use /// methods to accomplish this. -pub const Stat = extern struct { +pub const libc_stat = extern struct { dev: u64, ino: ino_t, mode: u32, @@ -524,6 +522,45 @@ pub const Stat = extern struct { } }; +pub const kernel_stat = extern struct { + dev: u32, + ino: ino_t, + mode: mode_t, + nlink: i16, + + uid: u32, + gid: u32, + rdev: u32, + + size: off_t, + atim: isize, + mtim: isize, + ctim: isize, + + blksize: off_t, + blocks: off_t, + + __unused4: [2]isize, + + // Hack to make the stdlib not complain about atime + // and friends not being a method. + // TODO what should tv_nsec be filled with? + pub fn atime(self: Stat) timespec { + return timespec{.tv_sec=self.atim, .tv_nsec=0}; + } + + pub fn mtime(self: Stat) timespec { + return timespec{.tv_sec=self.mtim, .tv_nsec=0}; + } + + pub fn ctime(self: Stat) timespec { + return timespec{.tv_sec=self.ctim, .tv_nsec=0}; + } +}; + +/// Renamed to Stat to not conflict with the stat function. +pub const Stat = kernel_stat; + pub const timespec = extern struct { tv_sec: isize, tv_nsec: isize, From 2b87cc7ed31062ca8d814f4971a77952a473703c Mon Sep 17 00:00:00 2001 From: Koakuma Date: Tue, 27 Oct 2020 22:46:18 +0700 Subject: [PATCH 25/28] starting_stack_ptr -> argc_argv_ptr to reflect actual use --- lib/std/start.zig | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/std/start.zig b/lib/std/start.zig index b1cbefcc67..4e1a9d71d4 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -11,7 +11,7 @@ const builtin = std.builtin; const assert = std.debug.assert; const uefi = std.os.uefi; -var starting_stack_ptr: [*]usize = undefined; +var argc_argv_ptr: [*]usize = undefined; const start_sym_name = if (builtin.arch.isMIPS()) "__start" else "_start"; @@ -102,26 +102,26 @@ fn _start() callconv(.Naked) noreturn { switch (builtin.arch) { .x86_64 => { - starting_stack_ptr = asm volatile ( + argc_argv_ptr = asm volatile ( \\ xor %%rbp, %%rbp : [argc] "={rsp}" (-> [*]usize) ); }, .i386 => { - starting_stack_ptr = asm volatile ( + argc_argv_ptr = asm volatile ( \\ xor %%ebp, %%ebp : [argc] "={esp}" (-> [*]usize) ); }, .aarch64, .aarch64_be, .arm, .armeb => { - starting_stack_ptr = asm volatile ( + argc_argv_ptr = asm volatile ( \\ mov fp, #0 \\ mov lr, #0 : [argc] "={sp}" (-> [*]usize) ); }, .riscv64 => { - starting_stack_ptr = asm volatile ( + argc_argv_ptr = asm volatile ( \\ li s0, 0 \\ li ra, 0 : [argc] "={sp}" (-> [*]usize) @@ -129,7 +129,7 @@ fn _start() callconv(.Naked) noreturn { }, .mips, .mipsel => { // The lr is already zeroed on entry, as specified by the ABI. - starting_stack_ptr = asm volatile ( + argc_argv_ptr = asm volatile ( \\ move $fp, $0 : [argc] "={sp}" (-> [*]usize) ); @@ -137,7 +137,7 @@ fn _start() callconv(.Naked) noreturn { .powerpc64le => { // Setup the initial stack frame and clear the back chain pointer. // TODO: Support powerpc64 (big endian) on ELFv2. - starting_stack_ptr = asm volatile ( + argc_argv_ptr = asm volatile ( \\ mr 4, 1 \\ li 0, 0 \\ stdu 0, -32(1) @@ -149,7 +149,7 @@ fn _start() callconv(.Naked) noreturn { }, .sparcv9 => { // argc is stored after a register window (16 registers) plus stack bias - starting_stack_ptr = asm ( + argc_argv_ptr = asm ( \\ mov %%g0, %%i6 \\ add %%o6, 2175, %[argc] : [argc] "=r" (-> [*]usize) @@ -190,8 +190,8 @@ fn posixCallMainAndExit() noreturn { if (builtin.os.tag == .freebsd) { @setAlignStack(16); } - const argc = starting_stack_ptr[0]; - const argv = @ptrCast([*][*:0]u8, starting_stack_ptr + 1); + const argc = argc_argv_ptr[0]; + const argv = @ptrCast([*][*:0]u8, argc_argv_ptr + 1); const envp_optional = @ptrCast([*:null]?[*:0]u8, @alignCast(@alignOf(usize), argv + argc + 1)); var envp_count: usize = 0; From 3a58b2330c7164852b2b201b1c20ead5328269a1 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Wed, 28 Oct 2020 17:46:26 +0700 Subject: [PATCH 26/28] Update stack traces testcases --- test/stack_traces.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/stack_traces.zig b/test/stack_traces.zig index 522d3ad9aa..151e0baf70 100644 --- a/test/stack_traces.zig +++ b/test/stack_traces.zig @@ -282,10 +282,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\source.zig:10:8: [address] in main (test) \\ foo(); \\ ^ - \\start.zig:323:29: [address] in std.start.posixCallMainAndExit (test) + \\start.zig:331:29: [address] in std.start.posixCallMainAndExit (test) \\ return root.main(); \\ ^ - \\start.zig:154:5: [address] in std.start._start (test) + \\start.zig:162:5: [address] in std.start._start (test) \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{}); \\ ^ \\ @@ -294,7 +294,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { switch (std.Target.current.cpu.arch) { .aarch64 => "", // TODO disabled; results in segfault else => - \\start.zig:154:5: [address] in std.start._start (test) + \\start.zig:162:5: [address] in std.start._start (test) \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{}); \\ ^ \\ From 5125eb77bdf7b87ebf65957f540d82879eb94238 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Thu, 29 Oct 2020 21:37:45 +0700 Subject: [PATCH 27/28] Use the *_stat type as self --- lib/std/os/bits/linux/sparc64.zig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/std/os/bits/linux/sparc64.zig b/lib/std/os/bits/linux/sparc64.zig index 8b073c5c08..53024c0b73 100644 --- a/lib/std/os/bits/linux/sparc64.zig +++ b/lib/std/os/bits/linux/sparc64.zig @@ -509,15 +509,15 @@ pub const libc_stat = extern struct { ctim: timespec, __unused: [2]isize, - pub fn atime(self: Stat) timespec { + pub fn atime(self: libc_stat) timespec { return self.atim; } - pub fn mtime(self: Stat) timespec { + pub fn mtime(self: libc_stat) timespec { return self.mtim; } - pub fn ctime(self: Stat) timespec { + pub fn ctime(self: libc_stat) timespec { return self.ctim; } }; @@ -545,15 +545,15 @@ pub const kernel_stat = extern struct { // Hack to make the stdlib not complain about atime // and friends not being a method. // TODO what should tv_nsec be filled with? - pub fn atime(self: Stat) timespec { + pub fn atime(self: kernel_stat) timespec { return timespec{.tv_sec=self.atim, .tv_nsec=0}; } - pub fn mtime(self: Stat) timespec { + pub fn mtime(self: kernel_stat) timespec { return timespec{.tv_sec=self.mtim, .tv_nsec=0}; } - pub fn ctime(self: Stat) timespec { + pub fn ctime(self: kernel_stat) timespec { return timespec{.tv_sec=self.ctim, .tv_nsec=0}; } }; From 891c6ddd5f4aa7a2de79bf5c155ffea71417bb15 Mon Sep 17 00:00:00 2001 From: Koakuma Date: Fri, 30 Oct 2020 11:46:33 +0700 Subject: [PATCH 28/28] Select stat struct type based on whether we are linking with libc --- lib/std/os/bits/linux/sparc64.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/os/bits/linux/sparc64.zig b/lib/std/os/bits/linux/sparc64.zig index 53024c0b73..0f2e5b5035 100644 --- a/lib/std/os/bits/linux/sparc64.zig +++ b/lib/std/os/bits/linux/sparc64.zig @@ -559,7 +559,7 @@ pub const kernel_stat = extern struct { }; /// Renamed to Stat to not conflict with the stat function. -pub const Stat = kernel_stat; +pub const Stat = if (std.builtin.link_libc) libc_stat else kernel_stat; pub const timespec = extern struct { tv_sec: isize,