From 9a541c12140e8768fabbbd8834cd0e1570df344b Mon Sep 17 00:00:00 2001 From: Greg V Date: Wed, 17 Oct 2018 16:48:17 +0300 Subject: Add FreeBSD support to os.cpp --- src/os.cpp | 26 ++++++++++++++++++++------ src/os.hpp | 2 ++ 2 files changed, 22 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/os.cpp b/src/os.cpp index 6df463d8a5..86bef6d5e8 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -50,10 +50,13 @@ typedef SSIZE_T ssize_t; #endif -#if defined(ZIG_OS_LINUX) +#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) #include #endif +#if defined(ZIG_OS_FREEBSD) +#include +#endif #if defined(__MACH__) #include @@ -75,7 +78,9 @@ static clock_serv_t cclock; #if defined(__APPLE__) && !defined(environ) #include #define environ (*_NSGetEnviron()) -#endif +#elif defined(ZIG_OS_FREEBSD) +extern char **environ; +#endif #if defined(ZIG_OS_POSIX) static void populate_termination(Termination *term, int status) { @@ -1442,6 +1447,15 @@ Error os_self_exe_path(Buf *out_path) { } buf_resize(out_path, amt); return ErrorNone; +#elif defined(ZIG_OS_FREEBSD) + buf_resize(out_path, PATH_MAX); + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; + size_t cb = PATH_MAX; + if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) { + return ErrorUnexpected; + } + buf_resize(out_path, cb); + return ErrorNone; #endif return ErrorFileNotFound; } @@ -1747,7 +1761,7 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) { buf_resize(out_path, 0); buf_appendf(out_path, "%s/Library/Application Support/%s", home_dir, appname); return ErrorNone; -#elif defined(ZIG_OS_LINUX) +#elif defined(ZIG_OS_POSIX) const char *home_dir = getenv("HOME"); if (home_dir == nullptr) { // TODO use /etc/passwd @@ -1760,7 +1774,7 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) { } -#if defined(ZIG_OS_LINUX) +#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, void *data) { ZigList *libs = reinterpret_cast< ZigList *>(data); if (info->dlpi_name[0] == '/') { @@ -1771,7 +1785,7 @@ static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, #endif Error os_self_exe_shared_libs(ZigList &paths) { -#if defined(ZIG_OS_LINUX) +#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) paths.resize(0); dl_iterate_phdr(self_exe_shared_libs_callback, &paths); return ErrorNone; @@ -1940,7 +1954,7 @@ Error os_file_mtime(OsFile file, OsTimeStamp *mtime) { mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime; mtime->nsec = 0; return ErrorNone; -#elif defined(ZIG_OS_LINUX) +#elif defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) struct stat statbuf; if (fstat(file, &statbuf) == -1) return ErrorFileSystem; diff --git a/src/os.hpp b/src/os.hpp index 30083971eb..a552c4461c 100644 --- a/src/os.hpp +++ b/src/os.hpp @@ -24,6 +24,8 @@ #define ZIG_OS_WINDOWS #elif defined(__linux__) #define ZIG_OS_LINUX +#elif defined(__FreeBSD__) +#define ZIG_OS_FREEBSD #else #define ZIG_OS_UNKNOWN #endif -- cgit v1.2.3 From e2b9c153bdfa2c5e4005d5957062e0eaf3b339a2 Mon Sep 17 00:00:00 2001 From: Marc Tiehuis Date: Fri, 20 Oct 2017 06:16:56 +0000 Subject: Add initial freebsd stdlib functionality Trivial program now compiles with now warnings. --- src/target.cpp | 2 +- std/os/freebsd.zig | 733 ++++++++++++++++++++++++++++++++++++++++++++++ std/os/freebsd_errno.zig | 121 ++++++++ std/os/freebsd_i386.zig | 614 ++++++++++++++++++++++++++++++++++++++ std/os/freebsd_x86_64.zig | 637 ++++++++++++++++++++++++++++++++++++++++ std/os/get_user_id.zig | 2 +- std/os/index.zig | 6 +- std/os/path.zig | 4 +- 8 files changed, 2113 insertions(+), 6 deletions(-) create mode 100644 std/os/freebsd.zig create mode 100644 std/os/freebsd_errno.zig create mode 100644 std/os/freebsd_i386.zig create mode 100644 std/os/freebsd_x86_64.zig (limited to 'src') diff --git a/src/target.cpp b/src/target.cpp index 25dfa9d3cb..e93465ba40 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -738,6 +738,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { case OsLinux: case OsMacOSX: case OsZen: + case OsFreeBSD: case OsOpenBSD: switch (id) { case CIntTypeShort: @@ -774,7 +775,6 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { case OsAnanas: case OsCloudABI: case OsDragonFly: - case OsFreeBSD: case OsIOS: case OsKFreeBSD: case OsLv2: diff --git a/std/os/freebsd.zig b/std/os/freebsd.zig new file mode 100644 index 0000000000..7fd233aef7 --- /dev/null +++ b/std/os/freebsd.zig @@ -0,0 +1,733 @@ +const assert = @import("../debug.zig").assert; +const builtin = @import("builtin"); +const arch = switch (builtin.arch) { + builtin.Arch.x86_64 => @import("freebsd_x86_64.zig"), + builtin.Arch.i386 => @import("freebsd_i386.zig"), + else => @compileError("unsupported arch"), +}; +pub use @import("freebsd_errno.zig"); + +pub const PATH_MAX = 1024; + +pub const STDIN_FILENO = 0; +pub const STDOUT_FILENO = 1; +pub const STDERR_FILENO = 2; + +pub const PROT_NONE = 0; +pub const PROT_READ = 1; +pub const PROT_WRITE = 2; +pub const PROT_EXEC = 4; + +pub const MAP_FAILED = @maxValue(usize); +pub const MAP_SHARED = 0x0001; +pub const MAP_PRIVATE = 0x0002; +pub const MAP_FIXED = 0x0010; +pub const MAP_STACK = 0x0400; +pub const MAP_NOSYNC = 0x0800; +pub const MAP_ANON = 0x1000; +pub const MAP_ANONYMOUS = MAP_ANON; +pub const MAP_FILE = 0; + +pub const MAP_GUARD = 0x00002000; +pub const MAP_EXCL = 0x00004000; +pub const MAP_NOCORE = 0x00020000; +pub const MAP_PREFAULT_READ = 0x00040000; +pub const MAP_32BIT = 0x00080000; + +pub const WNOHANG = 1; +pub const WUNTRACED = 2; +pub const WSTOPPED = WUNTRACED; +pub const WCONTINUED = 4; +pub const WNOWAIT = 8; +pub const WEXITED = 16; +pub const WTRAPPED = 32; + +pub const SA_ONSTACK = 0x0001; +pub const SA_RESTART = 0x0002; +pub const SA_RESETHAND = 0x0004; +pub const SA_NOCLDSTOP = 0x0008; +pub const SA_NODEFER = 0x0010; +pub const SA_NOCLDWAIT = 0x0020; +pub const SA_SIGINFO = 0x0040; + +pub const SIGHUP = 1; +pub const SIGINT = 2; +pub const SIGQUIT = 3; +pub const SIGILL = 4; +pub const SIGTRAP = 5; +pub const SIGABRT = 6; +pub const SIGIOT = SIGABRT; +pub const SIGEMT = 7; +pub const SIGFPE = 8; +pub const SIGKILL = 9; +pub const SIGBUS = 10; +pub const SIGSEGV = 11; +pub const SIGSYS = 12; +pub const SIGPIPE = 13; +pub const SIGALRM = 14; +pub const SIGTERM = 15; +pub const SIGURG = 16; +pub const SIGSTOP = 17; +pub const SIGTSTP = 18; +pub const SIGCONT = 19; +pub const SIGCHLD = 20; +pub const SIGTTIN = 21; +pub const SIGTTOU = 22; +pub const SIGIO = 23; +pub const SIGXCPU = 24; +pub const SIGXFSZ = 25; +pub const SIGVTALRM = 26; +pub const SIGPROF = 27; +pub const SIGWINCH = 28; +pub const SIGINFO = 29; +pub const SIGUSR1 = 30; +pub const SIGUSR2 = 31; +pub const SIGTHR = 32; +pub const SIGLWP = SIGTHR; +pub const SIGLIBRT = 33; + +pub const SIGRTMIN = 65; +pub const SIGRTMAX = 126; + +pub const O_RDONLY = 0o0; +pub const O_WRONLY = 0o1; +pub const O_RDWR = 0o2; +pub const O_ACCMODE = 0o3; + +pub const O_CREAT = arch.O_CREAT; +pub const O_EXCL = arch.O_EXCL; +pub const O_NOCTTY = arch.O_NOCTTY; +pub const O_TRUNC = arch.O_TRUNC; +pub const O_APPEND = arch.O_APPEND; +pub const O_NONBLOCK = arch.O_NONBLOCK; +pub const O_DSYNC = arch.O_DSYNC; +pub const O_SYNC = arch.O_SYNC; +pub const O_RSYNC = arch.O_RSYNC; +pub const O_DIRECTORY = arch.O_DIRECTORY; +pub const O_NOFOLLOW = arch.O_NOFOLLOW; +pub const O_CLOEXEC = arch.O_CLOEXEC; + +pub const O_ASYNC = arch.O_ASYNC; +pub const O_DIRECT = arch.O_DIRECT; +pub const O_LARGEFILE = arch.O_LARGEFILE; +pub const O_NOATIME = arch.O_NOATIME; +pub const O_PATH = arch.O_PATH; +pub const O_TMPFILE = arch.O_TMPFILE; +pub const O_NDELAY = arch.O_NDELAY; + +pub const SEEK_SET = 0; +pub const SEEK_CUR = 1; +pub const SEEK_END = 2; + +pub const SIG_BLOCK = 1; +pub const SIG_UNBLOCK = 2; +pub const SIG_SETMASK = 3; + +pub const SOCK_STREAM = 1; +pub const SOCK_DGRAM = 2; +pub const SOCK_RAW = 3; +pub const SOCK_RDM = 4; +pub const SOCK_SEQPACKET = 5; + +pub const SOCK_CLOEXEC = 0x10000000; +pub const SOCK_NONBLOCK = 0x20000000; + +// TODO: From here +pub const PROTO_ip = 0o000; +pub const PROTO_icmp = 0o001; +pub const PROTO_igmp = 0o002; +pub const PROTO_ggp = 0o003; +pub const PROTO_ipencap = 0o004; +pub const PROTO_st = 0o005; +pub const PROTO_tcp = 0o006; +pub const PROTO_egp = 0o010; +pub const PROTO_pup = 0o014; +pub const PROTO_udp = 0o021; +pub const PROTO_hmp = 0o024; +pub const PROTO_xns_idp = 0o026; +pub const PROTO_rdp = 0o033; +pub const PROTO_iso_tp4 = 0o035; +pub const PROTO_xtp = 0o044; +pub const PROTO_ddp = 0o045; +pub const PROTO_idpr_cmtp = 0o046; +pub const PROTO_ipv6 = 0o051; +pub const PROTO_ipv6_route = 0o053; +pub const PROTO_ipv6_frag = 0o054; +pub const PROTO_idrp = 0o055; +pub const PROTO_rsvp = 0o056; +pub const PROTO_gre = 0o057; +pub const PROTO_esp = 0o062; +pub const PROTO_ah = 0o063; +pub const PROTO_skip = 0o071; +pub const PROTO_ipv6_icmp = 0o072; +pub const PROTO_ipv6_nonxt = 0o073; +pub const PROTO_ipv6_opts = 0o074; +pub const PROTO_rspf = 0o111; +pub const PROTO_vmtp = 0o121; +pub const PROTO_ospf = 0o131; +pub const PROTO_ipip = 0o136; +pub const PROTO_encap = 0o142; +pub const PROTO_pim = 0o147; +pub const PROTO_raw = 0o377; + +pub const PF_UNSPEC = 0; +pub const PF_LOCAL = 1; +pub const PF_UNIX = PF_LOCAL; +pub const PF_FILE = PF_LOCAL; +pub const PF_INET = 2; +pub const PF_AX25 = 3; +pub const PF_IPX = 4; +pub const PF_APPLETALK = 5; +pub const PF_NETROM = 6; +pub const PF_BRIDGE = 7; +pub const PF_ATMPVC = 8; +pub const PF_X25 = 9; +pub const PF_INET6 = 10; +pub const PF_ROSE = 11; +pub const PF_DECnet = 12; +pub const PF_NETBEUI = 13; +pub const PF_SECURITY = 14; +pub const PF_KEY = 15; +pub const PF_NETLINK = 16; +pub const PF_ROUTE = PF_NETLINK; +pub const PF_PACKET = 17; +pub const PF_ASH = 18; +pub const PF_ECONET = 19; +pub const PF_ATMSVC = 20; +pub const PF_RDS = 21; +pub const PF_SNA = 22; +pub const PF_IRDA = 23; +pub const PF_PPPOX = 24; +pub const PF_WANPIPE = 25; +pub const PF_LLC = 26; +pub const PF_IB = 27; +pub const PF_MPLS = 28; +pub const PF_CAN = 29; +pub const PF_TIPC = 30; +pub const PF_BLUETOOTH = 31; +pub const PF_IUCV = 32; +pub const PF_RXRPC = 33; +pub const PF_ISDN = 34; +pub const PF_PHONET = 35; +pub const PF_IEEE802154 = 36; +pub const PF_CAIF = 37; +pub const PF_ALG = 38; +pub const PF_NFC = 39; +pub const PF_VSOCK = 40; +pub const PF_MAX = 41; + +pub const AF_UNSPEC = PF_UNSPEC; +pub const AF_LOCAL = PF_LOCAL; +pub const AF_UNIX = AF_LOCAL; +pub const AF_FILE = AF_LOCAL; +pub const AF_INET = PF_INET; +pub const AF_AX25 = PF_AX25; +pub const AF_IPX = PF_IPX; +pub const AF_APPLETALK = PF_APPLETALK; +pub const AF_NETROM = PF_NETROM; +pub const AF_BRIDGE = PF_BRIDGE; +pub const AF_ATMPVC = PF_ATMPVC; +pub const AF_X25 = PF_X25; +pub const AF_INET6 = PF_INET6; +pub const AF_ROSE = PF_ROSE; +pub const AF_DECnet = PF_DECnet; +pub const AF_NETBEUI = PF_NETBEUI; +pub const AF_SECURITY = PF_SECURITY; +pub const AF_KEY = PF_KEY; +pub const AF_NETLINK = PF_NETLINK; +pub const AF_ROUTE = PF_ROUTE; +pub const AF_PACKET = PF_PACKET; +pub const AF_ASH = PF_ASH; +pub const AF_ECONET = PF_ECONET; +pub const AF_ATMSVC = PF_ATMSVC; +pub const AF_RDS = PF_RDS; +pub const AF_SNA = PF_SNA; +pub const AF_IRDA = PF_IRDA; +pub const AF_PPPOX = PF_PPPOX; +pub const AF_WANPIPE = PF_WANPIPE; +pub const AF_LLC = PF_LLC; +pub const AF_IB = PF_IB; +pub const AF_MPLS = PF_MPLS; +pub const AF_CAN = PF_CAN; +pub const AF_TIPC = PF_TIPC; +pub const AF_BLUETOOTH = PF_BLUETOOTH; +pub const AF_IUCV = PF_IUCV; +pub const AF_RXRPC = PF_RXRPC; +pub const AF_ISDN = PF_ISDN; +pub const AF_PHONET = PF_PHONET; +pub const AF_IEEE802154 = PF_IEEE802154; +pub const AF_CAIF = PF_CAIF; +pub const AF_ALG = PF_ALG; +pub const AF_NFC = PF_NFC; +pub const AF_VSOCK = PF_VSOCK; +pub const AF_MAX = PF_MAX; + +pub const DT_UNKNOWN = 0; +pub const DT_FIFO = 1; +pub const DT_CHR = 2; +pub const DT_DIR = 4; +pub const DT_BLK = 6; +pub const DT_REG = 8; +pub const DT_LNK = 10; +pub const DT_SOCK = 12; +pub const DT_WHT = 14; + + +pub const TCGETS = 0x5401; +pub const TCSETS = 0x5402; +pub const TCSETSW = 0x5403; +pub const TCSETSF = 0x5404; +pub const TCGETA = 0x5405; +pub const TCSETA = 0x5406; +pub const TCSETAW = 0x5407; +pub const TCSETAF = 0x5408; +pub const TCSBRK = 0x5409; +pub const TCXONC = 0x540A; +pub const TCFLSH = 0x540B; +pub const TIOCEXCL = 0x540C; +pub const TIOCNXCL = 0x540D; +pub const TIOCSCTTY = 0x540E; +pub const TIOCGPGRP = 0x540F; +pub const TIOCSPGRP = 0x5410; +pub const TIOCOUTQ = 0x5411; +pub const TIOCSTI = 0x5412; +pub const TIOCGWINSZ = 0x5413; +pub const TIOCSWINSZ = 0x5414; +pub const TIOCMGET = 0x5415; +pub const TIOCMBIS = 0x5416; +pub const TIOCMBIC = 0x5417; +pub const TIOCMSET = 0x5418; +pub const TIOCGSOFTCAR = 0x5419; +pub const TIOCSSOFTCAR = 0x541A; +pub const FIONREAD = 0x541B; +pub const TIOCINQ = FIONREAD; +pub const TIOCLINUX = 0x541C; +pub const TIOCCONS = 0x541D; +pub const TIOCGSERIAL = 0x541E; +pub const TIOCSSERIAL = 0x541F; +pub const TIOCPKT = 0x5420; +pub const FIONBIO = 0x5421; +pub const TIOCNOTTY = 0x5422; +pub const TIOCSETD = 0x5423; +pub const TIOCGETD = 0x5424; +pub const TCSBRKP = 0x5425; +pub const TIOCSBRK = 0x5427; +pub const TIOCCBRK = 0x5428; +pub const TIOCGSID = 0x5429; +pub const TIOCGRS485 = 0x542E; +pub const TIOCSRS485 = 0x542F; +pub const TIOCGPTN = 0x80045430; +pub const TIOCSPTLCK = 0x40045431; +pub const TIOCGDEV = 0x80045432; +pub const TCGETX = 0x5432; +pub const TCSETX = 0x5433; +pub const TCSETXF = 0x5434; +pub const TCSETXW = 0x5435; +pub const TIOCSIG = 0x40045436; +pub const TIOCVHANGUP = 0x5437; +pub const TIOCGPKT = 0x80045438; +pub const TIOCGPTLCK = 0x80045439; +pub const TIOCGEXCL = 0x80045440; + +fn unsigned(s: i32) -> u32 { @bitCast(u32, s) } +fn signed(s: u32) -> i32 { @bitCast(i32, s) } +pub fn WEXITSTATUS(s: i32) -> i32 { signed((unsigned(s) & 0xff00) >> 8) } +pub fn WTERMSIG(s: i32) -> i32 { signed(unsigned(s) & 0x7f) } +pub fn WSTOPSIG(s: i32) -> i32 { WEXITSTATUS(s) } +pub fn WIFEXITED(s: i32) -> bool { WTERMSIG(s) == 0 } +pub fn WIFSTOPPED(s: i32) -> bool { (u16)(((unsigned(s)&0xffff)*%0x10001)>>8) > 0x7f00 } +pub fn WIFSIGNALED(s: i32) -> bool { (unsigned(s)&0xffff)-%1 < 0xff } + + +pub const winsize = extern struct { + ws_row: u16, + ws_col: u16, + ws_xpixel: u16, + ws_ypixel: u16, +}; + +/// Get the errno from a syscall return value, or 0 for no error. +pub fn getErrno(r: usize) -> usize { + const signed_r = @bitCast(isize, r); + if (signed_r > -4096 and signed_r < 0) usize(-signed_r) else 0 +} + +pub fn dup2(old: i32, new: i32) -> usize { + arch.syscall2(arch.SYS_dup2, usize(old), usize(new)) +} + +pub fn chdir(path: &const u8) -> usize { + arch.syscall1(arch.SYS_chdir, @ptrToInt(path)) +} + +pub fn execve(path: &const u8, argv: &const ?&const u8, envp: &const ?&const u8) -> usize { + arch.syscall3(arch.SYS_execve, @ptrToInt(path), @ptrToInt(argv), @ptrToInt(envp)) +} + +pub fn fork() -> usize { + arch.syscall0(arch.SYS_fork) +} + +pub fn getcwd(buf: &u8, size: usize) -> usize { + arch.syscall2(arch.SYS_getcwd, @ptrToInt(buf), size) +} + +pub fn getdents(fd: i32, dirp: &u8, count: usize) -> usize { + arch.syscall3(arch.SYS_getdents, usize(fd), @ptrToInt(dirp), count) +} + +pub fn isatty(fd: i32) -> bool { + var wsz: winsize = undefined; + return arch.syscall3(arch.SYS_ioctl, usize(fd), TIOCGWINSZ, @ptrToInt(&wsz)) == 0; +} + +pub fn readlink(noalias path: &const u8, noalias buf_ptr: &u8, buf_len: usize) -> usize { + arch.syscall3(arch.SYS_readlink, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len) +} + +pub fn mkdir(path: &const u8, mode: u32) -> usize { + arch.syscall2(arch.SYS_mkdir, @ptrToInt(path), mode) +} + +pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: usize, fd: i32, offset: isize) + -> usize +{ + arch.syscall6(arch.SYS_mmap, @ptrToInt(address), length, prot, flags, usize(fd), + @bitCast(usize, offset)) +} + +pub fn munmap(address: &u8, length: usize) -> usize { + arch.syscall2(arch.SYS_munmap, @ptrToInt(address), length) +} + +pub fn read(fd: i32, buf: &u8, count: usize) -> usize { + arch.syscall3(arch.SYS_read, usize(fd), @ptrToInt(buf), count) +} + +pub fn rmdir(path: &const u8) -> usize { + arch.syscall1(arch.SYS_rmdir, @ptrToInt(path)) +} + +pub fn symlink(existing: &const u8, new: &const u8) -> usize { + arch.syscall2(arch.SYS_symlink, @ptrToInt(existing), @ptrToInt(new)) +} + +pub fn pread(fd: i32, buf: &u8, count: usize, offset: usize) -> usize { + arch.syscall4(arch.SYS_pread, usize(fd), @ptrToInt(buf), count, offset) +} + +pub fn pipe(fd: &[2]i32) -> usize { + pipe2(fd, 0) +} + +pub fn pipe2(fd: &[2]i32, flags: usize) -> usize { + arch.syscall2(arch.SYS_pipe2, @ptrToInt(fd), flags) +} + +pub fn write(fd: i32, buf: &const u8, count: usize) -> usize { + arch.syscall3(arch.SYS_write, usize(fd), @ptrToInt(buf), count) +} + +pub fn pwrite(fd: i32, buf: &const u8, count: usize, offset: usize) -> usize { + arch.syscall4(arch.SYS_pwrite, usize(fd), @ptrToInt(buf), count, offset) +} + +pub fn rename(old: &const u8, new: &const u8) -> usize { + arch.syscall2(arch.SYS_rename, @ptrToInt(old), @ptrToInt(new)) +} + +pub fn open(path: &const u8, flags: u32, perm: usize) -> usize { + arch.syscall3(arch.SYS_open, @ptrToInt(path), flags, perm) +} + +pub fn create(path: &const u8, perm: usize) -> usize { + arch.syscall2(arch.SYS_creat, @ptrToInt(path), perm) +} + +pub fn openat(dirfd: i32, path: &const u8, flags: usize, mode: usize) -> usize { + arch.syscall4(arch.SYS_openat, usize(dirfd), @ptrToInt(path), flags, mode) +} + +pub fn close(fd: i32) -> usize { + arch.syscall1(arch.SYS_close, usize(fd)) +} + +pub fn lseek(fd: i32, offset: isize, ref_pos: usize) -> usize { + arch.syscall3(arch.SYS_lseek, usize(fd), @bitCast(usize, offset), ref_pos) +} + +pub fn exit(status: i32) -> noreturn { + _ = arch.syscall1(arch.SYS_exit, @bitCast(usize, isize(status))); + unreachable +} + +pub fn getrandom(buf: &u8, count: usize, flags: u32) -> usize { + arch.syscall3(arch.SYS_getrandom, @ptrToInt(buf), count, usize(flags)) +} + +pub fn kill(pid: i32, sig: i32) -> usize { + arch.syscall2(arch.SYS_kill, @bitCast(usize, isize(pid)), usize(sig)) +} + +pub fn unlink(path: &const u8) -> usize { + arch.syscall1(arch.SYS_unlink, @ptrToInt(path)) +} + +pub fn waitpid(pid: i32, status: &i32, options: i32) -> usize { + arch.syscall4(arch.SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0) +} + +pub fn nanosleep(req: &const timespec, rem: ?×pec) -> usize { + arch.syscall2(arch.SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem)) +} + +pub fn setuid(uid: u32) -> usize { + arch.syscall1(arch.SYS_setuid, uid) +} + +pub fn setgid(gid: u32) -> usize { + arch.syscall1(arch.SYS_setgid, gid) +} + +pub fn setreuid(ruid: u32, euid: u32) -> usize { + arch.syscall2(arch.SYS_setreuid, ruid, euid) +} + +pub fn setregid(rgid: u32, egid: u32) -> usize { + arch.syscall2(arch.SYS_setregid, rgid, egid) +} + +pub fn sigprocmask(flags: u32, noalias set: &const sigset_t, noalias oldset: ?&sigset_t) -> usize { + arch.syscall4(arch.SYS_rt_sigprocmask, flags, @ptrToInt(set), @ptrToInt(oldset), NSIG/8) +} + +pub fn sigaction(sig: u6, noalias act: &const Sigaction, noalias oact: ?&Sigaction) -> usize { + assert(sig >= 1); + assert(sig != SIGKILL); + assert(sig != SIGSTOP); + var ksa = k_sigaction { + .handler = act.handler, + .flags = act.flags | SA_RESTORER, + .mask = undefined, + .restorer = @ptrCast(extern fn(), arch.restore_rt), + }; + var ksa_old: k_sigaction = undefined; + @memcpy(@ptrCast(&u8, &ksa.mask), @ptrCast(&const u8, &act.mask), 8); + const result = arch.syscall4(arch.SYS_rt_sigaction, sig, @ptrToInt(&ksa), @ptrToInt(&ksa_old), @sizeOf(@typeOf(ksa.mask))); + const err = getErrno(result); + if (err != 0) { + return result; + } + if (oact) |old| { + old.handler = ksa_old.handler; + old.flags = @truncate(u32, ksa_old.flags); + @memcpy(@ptrCast(&u8, &old.mask), @ptrCast(&const u8, &ksa_old.mask), @sizeOf(@typeOf(ksa_old.mask))); + } + return 0; +} + +const NSIG = 65; +const sigset_t = [128 / @sizeOf(usize)]usize; +const all_mask = []usize{@maxValue(usize)}; +const app_mask = []usize{0xfffffffc7fffffff}; + +const k_sigaction = extern struct { + handler: extern fn(i32), + flags: usize, + restorer: extern fn(), + mask: [2]u32, +}; + +/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. +pub const Sigaction = struct { + handler: extern fn(i32), + mask: sigset_t, + flags: u32, +}; + +pub const SIG_ERR = @intToPtr(extern fn(i32), @maxValue(usize)); +pub const SIG_DFL = @intToPtr(extern fn(i32), 0); +pub const SIG_IGN = @intToPtr(extern fn(i32), 1); +pub const empty_sigset = []usize{0} ** sigset_t.len; + +pub fn raise(sig: i32) -> usize { + // TODO implement, see linux equivalent for what we want to try and do + return 0; +} + +fn blockAllSignals(set: &sigset_t) { + // TODO implement +} + +fn blockAppSignals(set: &sigset_t) { + // TODO implement +} + +fn restoreSignals(set: &sigset_t) { + // TODO implement +} + +pub fn sigaddset(set: &sigset_t, sig: u6) { + const s = sig - 1; + (*set)[usize(s) / usize.bit_count] |= usize(1) << (s & (usize.bit_count - 1)); +} + +pub fn sigismember(set: &const sigset_t, sig: u6) -> bool { + const s = sig - 1; + return ((*set)[usize(s) / usize.bit_count] & (usize(1) << (s & (usize.bit_count - 1)))) != 0; +} + + +pub const sa_family_t = u16; +pub const socklen_t = u32; +pub const in_addr = u32; +pub const in6_addr = [16]u8; + +pub const sockaddr = extern struct { + family: sa_family_t, + port: u16, + data: [12]u8, +}; + +pub const sockaddr_in = extern struct { + family: sa_family_t, + port: u16, + addr: in_addr, + zero: [8]u8, +}; + +pub const sockaddr_in6 = extern struct { + family: sa_family_t, + port: u16, + flowinfo: u32, + addr: in6_addr, + scope_id: u32, +}; + +pub const iovec = extern struct { + iov_base: &u8, + iov_len: usize, +}; + +// +//const IF_NAMESIZE = 16; +// +//export struct ifreq { +// ifrn_name: [IF_NAMESIZE]u8, +// union { +// ifru_addr: sockaddr, +// ifru_dstaddr: sockaddr, +// ifru_broadaddr: sockaddr, +// ifru_netmask: sockaddr, +// ifru_hwaddr: sockaddr, +// ifru_flags: i16, +// ifru_ivalue: i32, +// ifru_mtu: i32, +// ifru_map: ifmap, +// ifru_slave: [IF_NAMESIZE]u8, +// ifru_newname: [IF_NAMESIZE]u8, +// ifru_data: &u8, +// } ifr_ifru; +//} +// + +pub fn getsockname(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) -> usize { + arch.syscall3(arch.SYS_getsockname, usize(fd), @ptrToInt(addr), @ptrToInt(len)) +} + +pub fn getpeername(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) -> usize { + arch.syscall3(arch.SYS_getpeername, usize(fd), @ptrToInt(addr), @ptrToInt(len)) +} + +pub fn socket(domain: i32, socket_type: i32, protocol: i32) -> usize { + arch.syscall3(arch.SYS_socket, usize(domain), usize(socket_type), usize(protocol)) +} + +pub fn setsockopt(fd: i32, level: i32, optname: i32, optval: &const u8, optlen: socklen_t) -> usize { + arch.syscall5(arch.SYS_setsockopt, usize(fd), usize(level), usize(optname), usize(optval), @ptrToInt(optlen)) +} + +pub fn getsockopt(fd: i32, level: i32, optname: i32, noalias optval: &u8, noalias optlen: &socklen_t) -> usize { + arch.syscall5(arch.SYS_getsockopt, usize(fd), usize(level), usize(optname), @ptrToInt(optval), @ptrToInt(optlen)) +} + +pub fn sendmsg(fd: i32, msg: &const arch.msghdr, flags: u32) -> usize { + arch.syscall3(arch.SYS_sendmsg, usize(fd), @ptrToInt(msg), flags) +} + +pub fn connect(fd: i32, addr: &const sockaddr, len: socklen_t) -> usize { + arch.syscall3(arch.SYS_connect, usize(fd), @ptrToInt(addr), usize(len)) +} + +pub fn recvmsg(fd: i32, msg: &arch.msghdr, flags: u32) -> usize { + arch.syscall3(arch.SYS_recvmsg, usize(fd), @ptrToInt(msg), flags) +} + +pub fn recvfrom(fd: i32, noalias buf: &u8, len: usize, flags: u32, + noalias addr: ?&sockaddr, noalias alen: ?&socklen_t) -> usize +{ + arch.syscall6(arch.SYS_recvfrom, usize(fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen)) +} + +pub fn shutdown(fd: i32, how: i32) -> usize { + arch.syscall2(arch.SYS_shutdown, usize(fd), usize(how)) +} + +pub fn bind(fd: i32, addr: &const sockaddr, len: socklen_t) -> usize { + arch.syscall3(arch.SYS_bind, usize(fd), @ptrToInt(addr), usize(len)) +} + +pub fn listen(fd: i32, backlog: i32) -> usize { + arch.syscall2(arch.SYS_listen, usize(fd), usize(backlog)) +} + +pub fn sendto(fd: i32, buf: &const u8, len: usize, flags: u32, addr: ?&const sockaddr, alen: socklen_t) -> usize { + arch.syscall6(arch.SYS_sendto, usize(fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), usize(alen)) +} + +pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) -> usize { + arch.syscall4(arch.SYS_socketpair, usize(domain), usize(socket_type), usize(protocol), @ptrToInt(&fd[0])) +} + +pub fn accept(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) -> usize { + accept4(fd, addr, len, 0) +} + +pub fn accept4(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t, flags: u32) -> usize { + arch.syscall4(arch.SYS_accept4, usize(fd), @ptrToInt(addr), @ptrToInt(len), flags) +} + +// error NameTooLong; +// error SystemResources; +// error Io; +// +// pub fn if_nametoindex(name: []u8) -> %u32 { +// var ifr: ifreq = undefined; +// +// if (name.len >= ifr.ifr_name.len) { +// return error.NameTooLong; +// } +// +// const socket_ret = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); +// const socket_err = getErrno(socket_ret); +// if (socket_err > 0) { +// return error.SystemResources; +// } +// const socket_fd = i32(socket_ret); +// @memcpy(&ifr.ifr_name[0], &name[0], name.len); +// ifr.ifr_name[name.len] = 0; +// const ioctl_ret = ioctl(socket_fd, SIOCGIFINDEX, &ifr); +// close(socket_fd); +// const ioctl_err = getErrno(ioctl_ret); +// if (ioctl_err > 0) { +// return error.Io; +// } +// return ifr.ifr_ifindex; +// } + +pub const Stat = arch.Stat; +pub const timespec = arch.timespec; + +pub fn fstat(fd: i32, stat_buf: &Stat) -> usize { + arch.syscall2(arch.SYS_fstat, usize(fd), @ptrToInt(stat_buf)) +} diff --git a/std/os/freebsd_errno.zig b/std/os/freebsd_errno.zig new file mode 100644 index 0000000000..132683de1d --- /dev/null +++ b/std/os/freebsd_errno.zig @@ -0,0 +1,121 @@ +pub const EPERM = 1; // Operation not permitted +pub const ENOENT = 2; // No such file or directory +pub const ESRCH = 3; // No such process +pub const EINTR = 4; // Interrupted system call +pub const EIO = 5; // Input/output error +pub const ENXIO = 6; // Device not configured +pub const E2BIG = 7; // Argument list too long +pub const ENOEXEC = 8; // Exec format error +pub const EBADF = 9; // Bad file descriptor +pub const ECHILD = 10; // No child processes +pub const EDEADLK = 11; // Resource deadlock avoided + // 11 was EAGAIN +pub const ENOMEM = 12; // Cannot allocate memory +pub const EACCES = 13; // Permission denied +pub const EFAULT = 14; // Bad address +pub const ENOTBLK = 15; // Block device required +pub const EBUSY = 16; // Device busy +pub const EEXIST = 17; // File exists +pub const EXDEV = 18; // Cross-device link +pub const ENODEV = 19; // Operation not supported by device +pub const ENOTDIR = 20; // Not a directory +pub const EISDIR = 21; // Is a directory +pub const EINVAL = 22; // Invalid argument +pub const ENFILE = 23; // Too many open files in system +pub const EMFILE = 24; // Too many open files +pub const ENOTTY = 25; // Inappropriate ioctl for device +pub const ETXTBSY = 26; // Text file busy +pub const EFBIG = 27; // File too large +pub const ENOSPC = 28; // No space left on device +pub const ESPIPE = 29; // Illegal seek +pub const EROFS = 30; // Read-only filesystem +pub const EMLINK = 31; // Too many links +pub const EPIPE = 32; // Broken pipe + +// math software +pub const EDOM = 33; // Numerical argument out of domain +pub const ERANGE = 34; // Result too large + +// non-blocking and interrupt i/o +pub const EAGAIN = 35; // Resource temporarily unavailable +pub const EWOULDBLOCK = EAGAIN; // Operation would block +pub const EINPROGRESS = 36; // Operation now in progress +pub const EALREADY = 37; // Operation already in progress + +// ipc/network software -- argument errors +pub const ENOTSOCK = 38; // Socket operation on non-socket +pub const EDESTADDRREQ = 39; // Destination address required +pub const EMSGSIZE = 40; // Message too long +pub const EPROTOTYPE = 41; // Protocol wrong type for socket +pub const ENOPROTOOPT = 42; // Protocol not available +pub const EPROTONOSUPPORT = 43; // Protocol not supported +pub const ESOCKTNOSUPPORT = 44; // Socket type not supported +pub const EOPNOTSUPP = 45; // Operation not supported +pub const ENOTSUP = EOPNOTSUPP; // Operation not supported +pub const EPFNOSUPPORT = 46; // Protocol family not supported +pub const EAFNOSUPPORT = 47; // Address family not supported by protocol family +pub const EADDRINUSE = 48; // Address already in use +pub const EADDRNOTAVAIL = 49; // Can't assign requested address + +// ipc/network software -- operational errors +pub const ENETDOWN = 50; // Network is down +pub const ENETUNREACH = 51; // Network is unreachable +pub const ENETRESET = 52; // Network dropped connection on reset +pub const ECONNABORTED = 53; // Software caused connection abort +pub const ECONNRESET = 54; // Connection reset by peer +pub const ENOBUFS = 55; // No buffer space available +pub const EISCONN = 56; // Socket is already connected +pub const ENOTCONN = 57; // Socket is not connected +pub const ESHUTDOWN = 58; // Can't send after socket shutdown +pub const ETOOMANYREFS = 59; // Too many references: can't splice +pub const ETIMEDOUT = 60; // Operation timed out +pub const ECONNREFUSED = 61; // Connection refused + +pub const ELOOP = 62; // Too many levels of symbolic links +pub const ENAMETOOLONG = 63; // File name too long + +// should be rearranged +pub const EHOSTDOWN = 64; // Host is down +pub const EHOSTUNREACH = 65; // No route to host +pub const ENOTEMPTY = 66; // Directory not empty + +// quotas & mush +pub const EPROCLIM = 67; // Too many processes +pub const EUSERS = 68; // Too many users +pub const EDQUOT = 69; // Disc quota exceeded + +// Network File System +pub const ESTALE = 70; // Stale NFS file handle +pub const EREMOTE = 71; // Too many levels of remote in path +pub const EBADRPC = 72; // RPC struct is bad +pub const ERPCMISMATCH = 73; // RPC version wrong +pub const EPROGUNAVAIL = 74; // RPC prog. not avail +pub const EPROGMISMATCH = 75; // Program version wrong +pub const EPROCUNAVAIL = 76; // Bad procedure for program + +pub const ENOLCK = 77; // No locks available +pub const ENOSYS = 78; // Function not implemented + +pub const EFTYPE = 79; // Inappropriate file type or format +pub const EAUTH = 80; // Authentication error +pub const ENEEDAUTH = 81; // Need authenticator +pub const EIDRM = 82; // Identifier removed +pub const ENOMSG = 83; // No message of desired type +pub const EOVERFLOW = 84; // Value too large to be stored in data type +pub const ECANCELED = 85; // Operation canceled +pub const EILSEQ = 86; // Illegal byte sequence +pub const ENOATTR = 87; // Attribute not found + +pub const EDOOFUS = 88; // Programming error + +pub const EBADMSG = 89; // Bad message +pub const EMULTIHOP = 90; // Multihop attempted +pub const ENOLINK = 91; // Link has been severed +pub const EPROTO = 92; // Protocol error + +pub const ENOTCAPABLE = 93; // Capabilities insufficient +pub const ECAPMODE = 94; // Not permitted in capability mode +pub const ENOTRECOVERABLE = 95; // State not recoverable +pub const EOWNERDEAD = 96; // Previous owner died + +pub const ELAST = 96; // Must be equal largest errno diff --git a/std/os/freebsd_i386.zig b/std/os/freebsd_i386.zig new file mode 100644 index 0000000000..fd1f58639b --- /dev/null +++ b/std/os/freebsd_i386.zig @@ -0,0 +1,614 @@ +const freebsd = @import("freebsd.zig"); +const socklen_t = freebsd.socklen_t; +const iovec = freebsd.iovec; + +pub const SYS_syscall = 0; +pub const SYS_exit = 1; +pub const SYS_fork = 2; +pub const SYS_read = 3; +pub const SYS_write = 4; +pub const SYS_open = 5; +pub const SYS_close = 6; +pub const SYS_wait4 = 7; +// 8 is old creat +pub const SYS_link = 9; +pub const SYS_unlink = 10; +// 11 is obsolete execv +pub const SYS_chdir = 12; +pub const SYS_fchdir = 13; +pub const SYS_freebsd11_mknod = 14; +pub const SYS_chmod = 15; +pub const SYS_chown = 16; +pub const SYS_break = 17; +// 18 is freebsd4 getfsstat +// 19 is old lseek +pub const SYS_getpid = 20; +pub const SYS_mount = 21; +pub const SYS_unmount = 22; +pub const SYS_setuid = 23; +pub const SYS_getuid = 24; +pub const SYS_geteuid = 25; +pub const SYS_ptrace = 26; +pub const SYS_recvmsg = 27; +pub const SYS_sendmsg = 28; +pub const SYS_recvfrom = 29; +pub const SYS_accept = 30; +pub const SYS_getpeername = 31; +pub const SYS_getsockname = 32; +pub const SYS_access = 33; +pub const SYS_chflags = 34; +pub const SYS_fchflags = 35; +pub const SYS_sync = 36; +pub const SYS_kill = 37; +// 38 is old stat +pub const SYS_getppid = 39; +// 40 is old lstat +pub const SYS_dup = 41; +pub const SYS_freebsd10_pipe = 42; +pub const SYS_getegid = 43; +pub const SYS_profil = 44; +pub const SYS_ktrace = 45; +// 46 is old sigaction +pub const SYS_getgid = 47; +// 48 is old sigprocmask +pub const SYS_getlogin = 49; +pub const SYS_setlogin = 50; +pub const SYS_acct = 51; +// 52 is old sigpending +pub const SYS_sigaltstack = 53; +pub const SYS_ioctl = 54; +pub const SYS_reboot = 55; +pub const SYS_revoke = 56; +pub const SYS_symlink = 57; +pub const SYS_readlink = 58; +pub const SYS_execve = 59; +pub const SYS_umask = 60; +pub const SYS_chroot = 61; +// 62 is old fstat +// 63 is old getkerninfo +// 64 is old getpagesize +pub const SYS_msync = 65; +pub const SYS_vfork = 66; +// 67 is obsolete vread +// 68 is obsolete vwrite +pub const SYS_sbrk = 69; +pub const SYS_sstk = 70; +// 71 is old mmap +pub const SYS_vadvise = 72; +pub const SYS_munmap = 73; +pub const SYS_mprotect = 74; +pub const SYS_madvise = 75; +// 76 is obsolete vhangup +// 77 is obsolete vlimit +pub const SYS_mincore = 78; +pub const SYS_getgroups = 79; +pub const SYS_setgroups = 80; +pub const SYS_getpgrp = 81; +pub const SYS_setpgid = 82; +pub const SYS_setitimer = 83; +// 84 is old wait +pub const SYS_swapon = 85; +pub const SYS_getitimer = 86; +// 87 is old gethostname +// 88 is old sethostname +pub const SYS_getdtablesize = 89; +pub const SYS_dup2 = 90; +pub const SYS_fcntl = 92; +pub const SYS_select = 93; +pub const SYS_fsync = 95; +pub const SYS_setpriority = 96; +pub const SYS_socket = 97; +pub const SYS_connect = 98; +// 99 is old accept +pub const SYS_getpriority = 100; +// 101 is old send +// 102 is old recv +// 103 is old sigreturn +pub const SYS_bind = 104; +pub const SYS_setsockopt = 105; +pub const SYS_listen = 106; +// 107 is obsolete vtimes +// 108 is old sigvec +// 109 is old sigblock +// 110 is old sigsetmask +// 111 is old sigsuspend +// 112 is old sigstack +// 113 is old recvmsg +// 114 is old sendmsg +// 115 is obsolete vtrace +pub const SYS_gettimeofday = 116; +pub const SYS_getrusage = 117; +pub const SYS_getsockopt = 118; +pub const SYS_readv = 120; +pub const SYS_writev = 121; +pub const SYS_settimeofday = 122; +pub const SYS_fchown = 123; +pub const SYS_fchmod = 124; +// 125 is old recvfrom +pub const SYS_setreuid = 126; +pub const SYS_setregid = 127; +pub const SYS_rename = 128; +// 129 is old truncate +// 130 is old ftruncate +pub const SYS_flock = 131; +pub const SYS_mkfifo = 132; +pub const SYS_sendto = 133; +pub const SYS_shutdown = 134; +pub const SYS_socketpair = 135; +pub const SYS_mkdir = 136; +pub const SYS_rmdir = 137; +pub const SYS_utimes = 138; +// 139 is obsolete 4.2 sigreturn +pub const SYS_adjtime = 140; +// 141 is old getpeername +// 142 is old gethostid +// 143 is old sethostid +// 144 is old getrlimit +// 145 is old setrlimit +// 146 is old killpg +pub const SYS_setsid = 147; +pub const SYS_quotactl = 148; +// 149 is old quota +// 150 is old getsockname +pub const SYS_nlm_syscall = 154; +pub const SYS_nfssvc = 155; +// 156 is old getdirentries +// 157 is freebsd4 statfs +// 158 is freebsd4 fstatfs +pub const SYS_lgetfh = 160; +pub const SYS_getfh = 161; +// 162 is freebsd4 getdomainname +// 163 is freebsd4 setdomainname +// 164 is freebsd4 uname +pub const SYS_sysarch = 165; +pub const SYS_rtprio = 166; +pub const SYS_semsys = 169; +pub const SYS_msgsys = 170; +pub const SYS_shmsys = 171; +// 173 is freebsd6 pread +// 174 is freebsd6 pwrite +pub const SYS_setfib = 175; +pub const SYS_ntp_adjtime = 176; +pub const SYS_setgid = 181; +pub const SYS_setegid = 182; +pub const SYS_seteuid = 183; +pub const SYS_freebsd11_stat = 188; +pub const SYS_freebsd11_fstat = 189; +pub const SYS_freebsd11_lstat = 190; +pub const SYS_pathconf = 191; +pub const SYS_fpathconf = 192; +pub const SYS_getrlimit = 194; +pub const SYS_setrlimit = 195; +pub const SYS_freebsd11_getdirentries = 196; +// 197 is freebsd6 mmap +pub const SYS___syscall = 198; +// 199 is freebsd6 lseek +// 200 is freebsd6 truncate +// 201 is freebsd6 ftruncate +pub const SYS___sysctl = 202; +pub const SYS_mlock = 203; +pub const SYS_munlock = 204; +pub const SYS_undelete = 205; +pub const SYS_futimes = 206; +pub const SYS_getpgid = 207; +pub const SYS_poll = 209; +pub const SYS_freebsd7___semctl = 220; +pub const SYS_semget = 221; +pub const SYS_semop = 222; +pub const SYS_freebsd7_msgctl = 224; +pub const SYS_msgget = 225; +pub const SYS_msgsnd = 226; +pub const SYS_msgrcv = 227; +pub const SYS_shmat = 228; +pub const SYS_freebsd7_shmctl = 229; +pub const SYS_shmdt = 230; +pub const SYS_shmget = 231; +pub const SYS_clock_gettime = 232; +pub const SYS_clock_settime = 233; +pub const SYS_clock_getres = 234; +pub const SYS_ktimer_create = 235; +pub const SYS_ktimer_delete = 236; +pub const SYS_ktimer_settime = 237; +pub const SYS_ktimer_gettime = 238; +pub const SYS_ktimer_getoverrun = 239; +pub const SYS_nanosleep = 240; +pub const SYS_ffclock_getcounter = 241; +pub const SYS_ffclock_setestimate = 242; +pub const SYS_ffclock_getestimate = 243; +pub const SYS_clock_nanosleep = 244; +pub const SYS_clock_getcpuclockid2 = 247; +pub const SYS_ntp_gettime = 248; +pub const SYS_minherit = 250; +pub const SYS_rfork = 251; +// 252 is obsolete openbsd_poll +pub const SYS_issetugid = 253; +pub const SYS_lchown = 254; +pub const SYS_aio_read = 255; +pub const SYS_aio_write = 256; +pub const SYS_lio_listio = 257; +pub const SYS_freebsd11_getdents = 272; +pub const SYS_lchmod = 274; +pub const SYS_netbsd_lchown = 275; +pub const SYS_lutimes = 276; +pub const SYS_netbsd_msync = 277; +pub const SYS_freebsd11_nstat = 278; +pub const SYS_freebsd11_nfstat = 279; +pub const SYS_freebsd11_nlstat = 280; +pub const SYS_preadv = 289; +pub const SYS_pwritev = 290; +// 297 is freebsd4 fhstatfs +pub const SYS_fhopen = 298; +pub const SYS_freebsd11_fhstat = 299; +pub const SYS_modnext = 300; +pub const SYS_modstat = 301; +pub const SYS_modfnext = 302; +pub const SYS_modfind = 303; +pub const SYS_kldload = 304; +pub const SYS_kldunload = 305; +pub const SYS_kldfind = 306; +pub const SYS_kldnext = 307; +pub const SYS_kldstat = 308; +pub const SYS_kldfirstmod = 309; +pub const SYS_getsid = 310; +pub const SYS_setresuid = 311; +pub const SYS_setresgid = 312; +// 313 is obsolete signanosleep +pub const SYS_aio_return = 314; +pub const SYS_aio_suspend = 315; +pub const SYS_aio_cancel = 316; +pub const SYS_aio_error = 317; +// 318 is freebsd6 aio_read +// 319 is freebsd6 aio_write +// 320 is freebsd6 lio_listio +pub const SYS_yield = 321; +// 322 is obsolete thr_sleep +// 323 is obsolete thr_wakeup +pub const SYS_mlockall = 324; +pub const SYS_munlockall = 325; +pub const SYS___getcwd = 326; +pub const SYS_sched_setparam = 327; +pub const SYS_sched_getparam = 328; +pub const SYS_sched_setscheduler = 329; +pub const SYS_sched_getscheduler = 330; +pub const SYS_sched_yield = 331; +pub const SYS_sched_get_priority_max = 332; +pub const SYS_sched_get_priority_min = 333; +pub const SYS_sched_rr_get_interval = 334; +pub const SYS_utrace = 335; +// 336 is freebsd4 sendfile +pub const SYS_kldsym = 337; +pub const SYS_jail = 338; +pub const SYS_nnpfs_syscall = 339; +pub const SYS_sigprocmask = 340; +pub const SYS_sigsuspend = 341; +// 342 is freebsd4 sigaction +pub const SYS_sigpending = 343; +// 344 is freebsd4 sigreturn +pub const SYS_sigtimedwait = 345; +pub const SYS_sigwaitinfo = 346; +pub const SYS___acl_get_file = 347; +pub const SYS___acl_set_file = 348; +pub const SYS___acl_get_fd = 349; +pub const SYS___acl_set_fd = 350; +pub const SYS___acl_delete_file = 351; +pub const SYS___acl_delete_fd = 352; +pub const SYS___acl_aclcheck_file = 353; +pub const SYS___acl_aclcheck_fd = 354; +pub const SYS_extattrctl = 355; +pub const SYS_extattr_set_file = 356; +pub const SYS_extattr_get_file = 357; +pub const SYS_extattr_delete_file = 358; +pub const SYS_aio_waitcomplete = 359; +pub const SYS_getresuid = 360; +pub const SYS_getresgid = 361; +pub const SYS_kqueue = 362; +pub const SYS_freebsd11_kevent = 363; +pub const SYS_extattr_set_fd = 371; +pub const SYS_extattr_get_fd = 372; +pub const SYS_extattr_delete_fd = 373; +pub const SYS___setugid = 374; +pub const SYS_eaccess = 376; +pub const SYS_afs3_syscall = 377; +pub const SYS_nmount = 378; +pub const SYS___mac_get_proc = 384; +pub const SYS___mac_set_proc = 385; +pub const SYS___mac_get_fd = 386; +pub const SYS___mac_get_file = 387; +pub const SYS___mac_set_fd = 388; +pub const SYS___mac_set_file = 389; +pub const SYS_kenv = 390; +pub const SYS_lchflags = 391; +pub const SYS_uuidgen = 392; +pub const SYS_sendfile = 393; +pub const SYS_mac_syscall = 394; +pub const SYS_freebsd11_getfsstat = 395; +pub const SYS_freebsd11_statfs = 396; +pub const SYS_freebsd11_fstatfs = 397; +pub const SYS_freebsd11_fhstatfs = 398; +pub const SYS_ksem_close = 400; +pub const SYS_ksem_post = 401; +pub const SYS_ksem_wait = 402; +pub const SYS_ksem_trywait = 403; +pub const SYS_ksem_init = 404; +pub const SYS_ksem_open = 405; +pub const SYS_ksem_unlink = 406; +pub const SYS_ksem_getvalue = 407; +pub const SYS_ksem_destroy = 408; +pub const SYS___mac_get_pid = 409; +pub const SYS___mac_get_link = 410; +pub const SYS___mac_set_link = 411; +pub const SYS_extattr_set_link = 412; +pub const SYS_extattr_get_link = 413; +pub const SYS_extattr_delete_link = 414; +pub const SYS___mac_execve = 415; +pub const SYS_sigaction = 416; +pub const SYS_sigreturn = 417; +pub const SYS_getcontext = 421; +pub const SYS_setcontext = 422; +pub const SYS_swapcontext = 423; +pub const SYS_swapoff = 424; +pub const SYS___acl_get_link = 425; +pub const SYS___acl_set_link = 426; +pub const SYS___acl_delete_link = 427; +pub const SYS___acl_aclcheck_link = 428; +pub const SYS_sigwait = 429; +pub const SYS_thr_create = 430; +pub const SYS_thr_exit = 431; +pub const SYS_thr_self = 432; +pub const SYS_thr_kill = 433; +pub const SYS_jail_attach = 436; +pub const SYS_extattr_list_fd = 437; +pub const SYS_extattr_list_file = 438; +pub const SYS_extattr_list_link = 439; +pub const SYS_ksem_timedwait = 441; +pub const SYS_thr_suspend = 442; +pub const SYS_thr_wake = 443; +pub const SYS_kldunloadf = 444; +pub const SYS_audit = 445; +pub const SYS_auditon = 446; +pub const SYS_getauid = 447; +pub const SYS_setauid = 448; +pub const SYS_getaudit = 449; +pub const SYS_setaudit = 450; +pub const SYS_getaudit_addr = 451; +pub const SYS_setaudit_addr = 452; +pub const SYS_auditctl = 453; +pub const SYS__umtx_op = 454; +pub const SYS_thr_new = 455; +pub const SYS_sigqueue = 456; +pub const SYS_kmq_open = 457; +pub const SYS_kmq_setattr = 458; +pub const SYS_kmq_timedreceive = 459; +pub const SYS_kmq_timedsend = 460; +pub const SYS_kmq_notify = 461; +pub const SYS_kmq_unlink = 462; +pub const SYS_abort2 = 463; +pub const SYS_thr_set_name = 464; +pub const SYS_aio_fsync = 465; +pub const SYS_rtprio_thread = 466; +pub const SYS_sctp_peeloff = 471; +pub const SYS_sctp_generic_sendmsg = 472; +pub const SYS_sctp_generic_sendmsg_iov = 473; +pub const SYS_sctp_generic_recvmsg = 474; +pub const SYS_pread = 475; +pub const SYS_pwrite = 476; +pub const SYS_mmap = 477; +pub const SYS_lseek = 478; +pub const SYS_truncate = 479; +pub const SYS_ftruncate = 480; +pub const SYS_thr_kill2 = 481; +pub const SYS_shm_open = 482; +pub const SYS_shm_unlink = 483; +pub const SYS_cpuset = 484; +pub const SYS_cpuset_setid = 485; +pub const SYS_cpuset_getid = 486; +pub const SYS_cpuset_getaffinity = 487; +pub const SYS_cpuset_setaffinity = 488; +pub const SYS_faccessat = 489; +pub const SYS_fchmodat = 490; +pub const SYS_fchownat = 491; +pub const SYS_fexecve = 492; +pub const SYS_freebsd11_fstatat = 493; +pub const SYS_futimesat = 494; +pub const SYS_linkat = 495; +pub const SYS_mkdirat = 496; +pub const SYS_mkfifoat = 497; +pub const SYS_freebsd11_mknodat = 498; +pub const SYS_openat = 499; +pub const SYS_readlinkat = 500; +pub const SYS_renameat = 501; +pub const SYS_symlinkat = 502; +pub const SYS_unlinkat = 503; +pub const SYS_posix_openpt = 504; +pub const SYS_gssd_syscall = 505; +pub const SYS_jail_get = 506; +pub const SYS_jail_set = 507; +pub const SYS_jail_remove = 508; +pub const SYS_closefrom = 509; +pub const SYS___semctl = 510; +pub const SYS_msgctl = 511; +pub const SYS_shmctl = 512; +pub const SYS_lpathconf = 513; +// 514 is obsolete cap_new +pub const SYS___cap_rights_get = 515; +pub const SYS_cap_enter = 516; +pub const SYS_cap_getmode = 517; +pub const SYS_pdfork = 518; +pub const SYS_pdkill = 519; +pub const SYS_pdgetpid = 520; +pub const SYS_pselect = 522; +pub const SYS_getloginclass = 523; +pub const SYS_setloginclass = 524; +pub const SYS_rctl_get_racct = 525; +pub const SYS_rctl_get_rules = 526; +pub const SYS_rctl_get_limits = 527; +pub const SYS_rctl_add_rule = 528; +pub const SYS_rctl_remove_rule = 529; +pub const SYS_posix_fallocate = 530; +pub const SYS_posix_fadvise = 531; +pub const SYS_wait6 = 532; +pub const SYS_cap_rights_limit = 533; +pub const SYS_cap_ioctls_limit = 534; +pub const SYS_cap_ioctls_get = 535; +pub const SYS_cap_fcntls_limit = 536; +pub const SYS_cap_fcntls_get = 537; +pub const SYS_bindat = 538; +pub const SYS_connectat = 539; +pub const SYS_chflagsat = 540; +pub const SYS_accept4 = 541; +pub const SYS_pipe2 = 542; +pub const SYS_aio_mlock = 543; +pub const SYS_procctl = 544; +pub const SYS_ppoll = 545; +pub const SYS_futimens = 546; +pub const SYS_utimensat = 547; +pub const SYS_numa_getaffinity = 548; +pub const SYS_numa_setaffinity = 549; +pub const SYS_fdatasync = 550; +pub const SYS_fstat = 551; +pub const SYS_fstatat = 552; +pub const SYS_fhstat = 553; +pub const SYS_getdirentries = 554; +pub const SYS_statfs = 555; +pub const SYS_fstatfs = 556; +pub const SYS_getfsstat = 557; +pub const SYS_fhstatfs = 558; +pub const SYS_mknodat = 559; +pub const SYS_kevent = 560; +pub const SYS_MAXSYSCALL = 561; + +// From here +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_GETLK = 12; +pub const F_SETLK = 13; +pub const F_SETLKW = 14; + +pub const F_SETOWN_EX = 15; +pub const F_GETOWN_EX = 16; + +pub const F_GETOWNER_UIDS = 17; + +pub inline fn syscall0(number: usize) -> usize { + asm volatile ("int $0x80" + : [ret] "={eax}" (-> usize) + : [number] "{eax}" (number)) +} + +pub inline fn syscall1(number: usize, arg1: usize) -> usize { + asm volatile ("int $0x80" + : [ret] "={eax}" (-> usize) + : [number] "{eax}" (number), + [arg1] "{ebx}" (arg1)) +} + +pub inline fn syscall2(number: usize, arg1: usize, arg2: usize) -> usize { + asm volatile ("int $0x80" + : [ret] "={eax}" (-> usize) + : [number] "{eax}" (number), + [arg1] "{ebx}" (arg1), + [arg2] "{ecx}" (arg2)) +} + +pub inline fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { + asm volatile ("int $0x80" + : [ret] "={eax}" (-> usize) + : [number] "{eax}" (number), + [arg1] "{ebx}" (arg1), + [arg2] "{ecx}" (arg2), + [arg3] "{edx}" (arg3)) +} + +pub inline fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) -> usize { + asm volatile ("int $0x80" + : [ret] "={eax}" (-> usize) + : [number] "{eax}" (number), + [arg1] "{ebx}" (arg1), + [arg2] "{ecx}" (arg2), + [arg3] "{edx}" (arg3), + [arg4] "{esi}" (arg4)) +} + +pub inline fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, + arg4: usize, arg5: usize) -> usize +{ + asm volatile ("int $0x80" + : [ret] "={eax}" (-> usize) + : [number] "{eax}" (number), + [arg1] "{ebx}" (arg1), + [arg2] "{ecx}" (arg2), + [arg3] "{edx}" (arg3), + [arg4] "{esi}" (arg4), + [arg5] "{edi}" (arg5)) +} + +pub inline fn syscall6(number: usize, arg1: usize, arg2: usize, arg3: usize, + arg4: usize, arg5: usize, arg6: usize) -> usize +{ + asm volatile ("int $0x80" + : [ret] "={eax}" (-> usize) + : [number] "{eax}" (number), + [arg1] "{ebx}" (arg1), + [arg2] "{ecx}" (arg2), + [arg3] "{edx}" (arg3), + [arg4] "{esi}" (arg4), + [arg5] "{edi}" (arg5), + [arg6] "{ebp}" (arg6)) +} + +pub nakedcc fn restore() { + asm volatile ( + \\popl %%eax + \\movl $119, %%eax + \\int $0x80 + : + : + : "rcx", "r11") +} + +pub nakedcc fn restore_rt() { + asm volatile ("int $0x80" + : + : [number] "{eax}" (usize(SYS_rt_sigreturn)) + : "rcx", "r11") +} + +export struct msghdr { + msg_name: &u8, + msg_namelen: socklen_t, + msg_iov: &iovec, + msg_iovlen: i32, + msg_control: &u8, + msg_controllen: socklen_t, + msg_flags: i32, +} diff --git a/std/os/freebsd_x86_64.zig b/std/os/freebsd_x86_64.zig new file mode 100644 index 0000000000..ec3b93be14 --- /dev/null +++ b/std/os/freebsd_x86_64.zig @@ -0,0 +1,637 @@ +const freebsd = @import("freebsd.zig"); +const socklen_t = freebsd.socklen_t; +const iovec = freebsd.iovec; + +pub const SYS_syscall = 0; +pub const SYS_exit = 1; +pub const SYS_fork = 2; +pub const SYS_read = 3; +pub const SYS_write = 4; +pub const SYS_open = 5; +pub const SYS_close = 6; +pub const SYS_wait4 = 7; +// 8 is old creat +pub const SYS_link = 9; +pub const SYS_unlink = 10; +// 11 is obsolete execv +pub const SYS_chdir = 12; +pub const SYS_fchdir = 13; +pub const SYS_freebsd11_mknod = 14; +pub const SYS_chmod = 15; +pub const SYS_chown = 16; +pub const SYS_break = 17; +// 18 is freebsd4 getfsstat +// 19 is old lseek +pub const SYS_getpid = 20; +pub const SYS_mount = 21; +pub const SYS_unmount = 22; +pub const SYS_setuid = 23; +pub const SYS_getuid = 24; +pub const SYS_geteuid = 25; +pub const SYS_ptrace = 26; +pub const SYS_recvmsg = 27; +pub const SYS_sendmsg = 28; +pub const SYS_recvfrom = 29; +pub const SYS_accept = 30; +pub const SYS_getpeername = 31; +pub const SYS_getsockname = 32; +pub const SYS_access = 33; +pub const SYS_chflags = 34; +pub const SYS_fchflags = 35; +pub const SYS_sync = 36; +pub const SYS_kill = 37; +// 38 is old stat +pub const SYS_getppid = 39; +// 40 is old lstat +pub const SYS_dup = 41; +pub const SYS_freebsd10_pipe = 42; +pub const SYS_getegid = 43; +pub const SYS_profil = 44; +pub const SYS_ktrace = 45; +// 46 is old sigaction +pub const SYS_getgid = 47; +// 48 is old sigprocmask +pub const SYS_getlogin = 49; +pub const SYS_setlogin = 50; +pub const SYS_acct = 51; +// 52 is old sigpending +pub const SYS_sigaltstack = 53; +pub const SYS_ioctl = 54; +pub const SYS_reboot = 55; +pub const SYS_revoke = 56; +pub const SYS_symlink = 57; +pub const SYS_readlink = 58; +pub const SYS_execve = 59; +pub const SYS_umask = 60; +pub const SYS_chroot = 61; +// 62 is old fstat +// 63 is old getkerninfo +// 64 is old getpagesize +pub const SYS_msync = 65; +pub const SYS_vfork = 66; +// 67 is obsolete vread +// 68 is obsolete vwrite +pub const SYS_sbrk = 69; +pub const SYS_sstk = 70; +// 71 is old mmap +pub const SYS_vadvise = 72; +pub const SYS_munmap = 73; +pub const SYS_mprotect = 74; +pub const SYS_madvise = 75; +// 76 is obsolete vhangup +// 77 is obsolete vlimit +pub const SYS_mincore = 78; +pub const SYS_getgroups = 79; +pub const SYS_setgroups = 80; +pub const SYS_getpgrp = 81; +pub const SYS_setpgid = 82; +pub const SYS_setitimer = 83; +// 84 is old wait +pub const SYS_swapon = 85; +pub const SYS_getitimer = 86; +// 87 is old gethostname +// 88 is old sethostname +pub const SYS_getdtablesize = 89; +pub const SYS_dup2 = 90; +pub const SYS_fcntl = 92; +pub const SYS_select = 93; +pub const SYS_fsync = 95; +pub const SYS_setpriority = 96; +pub const SYS_socket = 97; +pub const SYS_connect = 98; +// 99 is old accept +pub const SYS_getpriority = 100; +// 101 is old send +// 102 is old recv +// 103 is old sigreturn +pub const SYS_bind = 104; +pub const SYS_setsockopt = 105; +pub const SYS_listen = 106; +// 107 is obsolete vtimes +// 108 is old sigvec +// 109 is old sigblock +// 110 is old sigsetmask +// 111 is old sigsuspend +// 112 is old sigstack +// 113 is old recvmsg +// 114 is old sendmsg +// 115 is obsolete vtrace +pub const SYS_gettimeofday = 116; +pub const SYS_getrusage = 117; +pub const SYS_getsockopt = 118; +pub const SYS_readv = 120; +pub const SYS_writev = 121; +pub const SYS_settimeofday = 122; +pub const SYS_fchown = 123; +pub const SYS_fchmod = 124; +// 125 is old recvfrom +pub const SYS_setreuid = 126; +pub const SYS_setregid = 127; +pub const SYS_rename = 128; +// 129 is old truncate +// 130 is old ftruncate +pub const SYS_flock = 131; +pub const SYS_mkfifo = 132; +pub const SYS_sendto = 133; +pub const SYS_shutdown = 134; +pub const SYS_socketpair = 135; +pub const SYS_mkdir = 136; +pub const SYS_rmdir = 137; +pub const SYS_utimes = 138; +// 139 is obsolete 4.2 sigreturn +pub const SYS_adjtime = 140; +// 141 is old getpeername +// 142 is old gethostid +// 143 is old sethostid +// 144 is old getrlimit +// 145 is old setrlimit +// 146 is old killpg +pub const SYS_setsid = 147; +pub const SYS_quotactl = 148; +// 149 is old quota +// 150 is old getsockname +pub const SYS_nlm_syscall = 154; +pub const SYS_nfssvc = 155; +// 156 is old getdirentries +// 157 is freebsd4 statfs +// 158 is freebsd4 fstatfs +pub const SYS_lgetfh = 160; +pub const SYS_getfh = 161; +// 162 is freebsd4 getdomainname +// 163 is freebsd4 setdomainname +// 164 is freebsd4 uname +pub const SYS_sysarch = 165; +pub const SYS_rtprio = 166; +pub const SYS_semsys = 169; +pub const SYS_msgsys = 170; +pub const SYS_shmsys = 171; +// 173 is freebsd6 pread +// 174 is freebsd6 pwrite +pub const SYS_setfib = 175; +pub const SYS_ntp_adjtime = 176; +pub const SYS_setgid = 181; +pub const SYS_setegid = 182; +pub const SYS_seteuid = 183; +pub const SYS_freebsd11_stat = 188; +pub const SYS_freebsd11_fstat = 189; +pub const SYS_freebsd11_lstat = 190; +pub const SYS_pathconf = 191; +pub const SYS_fpathconf = 192; +pub const SYS_getrlimit = 194; +pub const SYS_setrlimit = 195; +pub const SYS_freebsd11_getdirentries = 196; +// 197 is freebsd6 mmap +pub const SYS___syscall = 198; +// 199 is freebsd6 lseek +// 200 is freebsd6 truncate +// 201 is freebsd6 ftruncate +pub const SYS___sysctl = 202; +pub const SYS_mlock = 203; +pub const SYS_munlock = 204; +pub const SYS_undelete = 205; +pub const SYS_futimes = 206; +pub const SYS_getpgid = 207; +pub const SYS_poll = 209; +pub const SYS_freebsd7___semctl = 220; +pub const SYS_semget = 221; +pub const SYS_semop = 222; +pub const SYS_freebsd7_msgctl = 224; +pub const SYS_msgget = 225; +pub const SYS_msgsnd = 226; +pub const SYS_msgrcv = 227; +pub const SYS_shmat = 228; +pub const SYS_freebsd7_shmctl = 229; +pub const SYS_shmdt = 230; +pub const SYS_shmget = 231; +pub const SYS_clock_gettime = 232; +pub const SYS_clock_settime = 233; +pub const SYS_clock_getres = 234; +pub const SYS_ktimer_create = 235; +pub const SYS_ktimer_delete = 236; +pub const SYS_ktimer_settime = 237; +pub const SYS_ktimer_gettime = 238; +pub const SYS_ktimer_getoverrun = 239; +pub const SYS_nanosleep = 240; +pub const SYS_ffclock_getcounter = 241; +pub const SYS_ffclock_setestimate = 242; +pub const SYS_ffclock_getestimate = 243; +pub const SYS_clock_nanosleep = 244; +pub const SYS_clock_getcpuclockid2 = 247; +pub const SYS_ntp_gettime = 248; +pub const SYS_minherit = 250; +pub const SYS_rfork = 251; +// 252 is obsolete openbsd_poll +pub const SYS_issetugid = 253; +pub const SYS_lchown = 254; +pub const SYS_aio_read = 255; +pub const SYS_aio_write = 256; +pub const SYS_lio_listio = 257; +pub const SYS_freebsd11_getdents = 272; +pub const SYS_lchmod = 274; +pub const SYS_netbsd_lchown = 275; +pub const SYS_lutimes = 276; +pub const SYS_netbsd_msync = 277; +pub const SYS_freebsd11_nstat = 278; +pub const SYS_freebsd11_nfstat = 279; +pub const SYS_freebsd11_nlstat = 280; +pub const SYS_preadv = 289; +pub const SYS_pwritev = 290; +// 297 is freebsd4 fhstatfs +pub const SYS_fhopen = 298; +pub const SYS_freebsd11_fhstat = 299; +pub const SYS_modnext = 300; +pub const SYS_modstat = 301; +pub const SYS_modfnext = 302; +pub const SYS_modfind = 303; +pub const SYS_kldload = 304; +pub const SYS_kldunload = 305; +pub const SYS_kldfind = 306; +pub const SYS_kldnext = 307; +pub const SYS_kldstat = 308; +pub const SYS_kldfirstmod = 309; +pub const SYS_getsid = 310; +pub const SYS_setresuid = 311; +pub const SYS_setresgid = 312; +// 313 is obsolete signanosleep +pub const SYS_aio_return = 314; +pub const SYS_aio_suspend = 315; +pub const SYS_aio_cancel = 316; +pub const SYS_aio_error = 317; +// 318 is freebsd6 aio_read +// 319 is freebsd6 aio_write +// 320 is freebsd6 lio_listio +pub const SYS_yield = 321; +// 322 is obsolete thr_sleep +// 323 is obsolete thr_wakeup +pub const SYS_mlockall = 324; +pub const SYS_munlockall = 325; +pub const SYS___getcwd = 326; +pub const SYS_sched_setparam = 327; +pub const SYS_sched_getparam = 328; +pub const SYS_sched_setscheduler = 329; +pub const SYS_sched_getscheduler = 330; +pub const SYS_sched_yield = 331; +pub const SYS_sched_get_priority_max = 332; +pub const SYS_sched_get_priority_min = 333; +pub const SYS_sched_rr_get_interval = 334; +pub const SYS_utrace = 335; +// 336 is freebsd4 sendfile +pub const SYS_kldsym = 337; +pub const SYS_jail = 338; +pub const SYS_nnpfs_syscall = 339; +pub const SYS_sigprocmask = 340; +pub const SYS_sigsuspend = 341; +// 342 is freebsd4 sigaction +pub const SYS_sigpending = 343; +// 344 is freebsd4 sigreturn +pub const SYS_sigtimedwait = 345; +pub const SYS_sigwaitinfo = 346; +pub const SYS___acl_get_file = 347; +pub const SYS___acl_set_file = 348; +pub const SYS___acl_get_fd = 349; +pub const SYS___acl_set_fd = 350; +pub const SYS___acl_delete_file = 351; +pub const SYS___acl_delete_fd = 352; +pub const SYS___acl_aclcheck_file = 353; +pub const SYS___acl_aclcheck_fd = 354; +pub const SYS_extattrctl = 355; +pub const SYS_extattr_set_file = 356; +pub const SYS_extattr_get_file = 357; +pub const SYS_extattr_delete_file = 358; +pub const SYS_aio_waitcomplete = 359; +pub const SYS_getresuid = 360; +pub const SYS_getresgid = 361; +pub const SYS_kqueue = 362; +pub const SYS_freebsd11_kevent = 363; +pub const SYS_extattr_set_fd = 371; +pub const SYS_extattr_get_fd = 372; +pub const SYS_extattr_delete_fd = 373; +pub const SYS___setugid = 374; +pub const SYS_eaccess = 376; +pub const SYS_afs3_syscall = 377; +pub const SYS_nmount = 378; +pub const SYS___mac_get_proc = 384; +pub const SYS___mac_set_proc = 385; +pub const SYS___mac_get_fd = 386; +pub const SYS___mac_get_file = 387; +pub const SYS___mac_set_fd = 388; +pub const SYS___mac_set_file = 389; +pub const SYS_kenv = 390; +pub const SYS_lchflags = 391; +pub const SYS_uuidgen = 392; +pub const SYS_sendfile = 393; +pub const SYS_mac_syscall = 394; +pub const SYS_freebsd11_getfsstat = 395; +pub const SYS_freebsd11_statfs = 396; +pub const SYS_freebsd11_fstatfs = 397; +pub const SYS_freebsd11_fhstatfs = 398; +pub const SYS_ksem_close = 400; +pub const SYS_ksem_post = 401; +pub const SYS_ksem_wait = 402; +pub const SYS_ksem_trywait = 403; +pub const SYS_ksem_init = 404; +pub const SYS_ksem_open = 405; +pub const SYS_ksem_unlink = 406; +pub const SYS_ksem_getvalue = 407; +pub const SYS_ksem_destroy = 408; +pub const SYS___mac_get_pid = 409; +pub const SYS___mac_get_link = 410; +pub const SYS___mac_set_link = 411; +pub const SYS_extattr_set_link = 412; +pub const SYS_extattr_get_link = 413; +pub const SYS_extattr_delete_link = 414; +pub const SYS___mac_execve = 415; +pub const SYS_sigaction = 416; +pub const SYS_sigreturn = 417; +pub const SYS_getcontext = 421; +pub const SYS_setcontext = 422; +pub const SYS_swapcontext = 423; +pub const SYS_swapoff = 424; +pub const SYS___acl_get_link = 425; +pub const SYS___acl_set_link = 426; +pub const SYS___acl_delete_link = 427; +pub const SYS___acl_aclcheck_link = 428; +pub const SYS_sigwait = 429; +pub const SYS_thr_create = 430; +pub const SYS_thr_exit = 431; +pub const SYS_thr_self = 432; +pub const SYS_thr_kill = 433; +pub const SYS_jail_attach = 436; +pub const SYS_extattr_list_fd = 437; +pub const SYS_extattr_list_file = 438; +pub const SYS_extattr_list_link = 439; +pub const SYS_ksem_timedwait = 441; +pub const SYS_thr_suspend = 442; +pub const SYS_thr_wake = 443; +pub const SYS_kldunloadf = 444; +pub const SYS_audit = 445; +pub const SYS_auditon = 446; +pub const SYS_getauid = 447; +pub const SYS_setauid = 448; +pub const SYS_getaudit = 449; +pub const SYS_setaudit = 450; +pub const SYS_getaudit_addr = 451; +pub const SYS_setaudit_addr = 452; +pub const SYS_auditctl = 453; +pub const SYS__umtx_op = 454; +pub const SYS_thr_new = 455; +pub const SYS_sigqueue = 456; +pub const SYS_kmq_open = 457; +pub const SYS_kmq_setattr = 458; +pub const SYS_kmq_timedreceive = 459; +pub const SYS_kmq_timedsend = 460; +pub const SYS_kmq_notify = 461; +pub const SYS_kmq_unlink = 462; +pub const SYS_abort2 = 463; +pub const SYS_thr_set_name = 464; +pub const SYS_aio_fsync = 465; +pub const SYS_rtprio_thread = 466; +pub const SYS_sctp_peeloff = 471; +pub const SYS_sctp_generic_sendmsg = 472; +pub const SYS_sctp_generic_sendmsg_iov = 473; +pub const SYS_sctp_generic_recvmsg = 474; +pub const SYS_pread = 475; +pub const SYS_pwrite = 476; +pub const SYS_mmap = 477; +pub const SYS_lseek = 478; +pub const SYS_truncate = 479; +pub const SYS_ftruncate = 480; +pub const SYS_thr_kill2 = 481; +pub const SYS_shm_open = 482; +pub const SYS_shm_unlink = 483; +pub const SYS_cpuset = 484; +pub const SYS_cpuset_setid = 485; +pub const SYS_cpuset_getid = 486; +pub const SYS_cpuset_getaffinity = 487; +pub const SYS_cpuset_setaffinity = 488; +pub const SYS_faccessat = 489; +pub const SYS_fchmodat = 490; +pub const SYS_fchownat = 491; +pub const SYS_fexecve = 492; +pub const SYS_freebsd11_fstatat = 493; +pub const SYS_futimesat = 494; +pub const SYS_linkat = 495; +pub const SYS_mkdirat = 496; +pub const SYS_mkfifoat = 497; +pub const SYS_freebsd11_mknodat = 498; +pub const SYS_openat = 499; +pub const SYS_readlinkat = 500; +pub const SYS_renameat = 501; +pub const SYS_symlinkat = 502; +pub const SYS_unlinkat = 503; +pub const SYS_posix_openpt = 504; +pub const SYS_gssd_syscall = 505; +pub const SYS_jail_get = 506; +pub const SYS_jail_set = 507; +pub const SYS_jail_remove = 508; +pub const SYS_closefrom = 509; +pub const SYS___semctl = 510; +pub const SYS_msgctl = 511; +pub const SYS_shmctl = 512; +pub const SYS_lpathconf = 513; +// 514 is obsolete cap_new +pub const SYS___cap_rights_get = 515; +pub const SYS_cap_enter = 516; +pub const SYS_cap_getmode = 517; +pub const SYS_pdfork = 518; +pub const SYS_pdkill = 519; +pub const SYS_pdgetpid = 520; +pub const SYS_pselect = 522; +pub const SYS_getloginclass = 523; +pub const SYS_setloginclass = 524; +pub const SYS_rctl_get_racct = 525; +pub const SYS_rctl_get_rules = 526; +pub const SYS_rctl_get_limits = 527; +pub const SYS_rctl_add_rule = 528; +pub const SYS_rctl_remove_rule = 529; +pub const SYS_posix_fallocate = 530; +pub const SYS_posix_fadvise = 531; +pub const SYS_wait6 = 532; +pub const SYS_cap_rights_limit = 533; +pub const SYS_cap_ioctls_limit = 534; +pub const SYS_cap_ioctls_get = 535; +pub const SYS_cap_fcntls_limit = 536; +pub const SYS_cap_fcntls_get = 537; +pub const SYS_bindat = 538; +pub const SYS_connectat = 539; +pub const SYS_chflagsat = 540; +pub const SYS_accept4 = 541; +pub const SYS_pipe2 = 542; +pub const SYS_aio_mlock = 543; +pub const SYS_procctl = 544; +pub const SYS_ppoll = 545; +pub const SYS_futimens = 546; +pub const SYS_utimensat = 547; +pub const SYS_numa_getaffinity = 548; +pub const SYS_numa_setaffinity = 549; +pub const SYS_fdatasync = 550; +pub const SYS_fstat = 551; +pub const SYS_fstatat = 552; +pub const SYS_fhstat = 553; +pub const SYS_getdirentries = 554; +pub const SYS_statfs = 555; +pub const SYS_fstatfs = 556; +pub const SYS_getfsstat = 557; +pub const SYS_fhstatfs = 558; +pub const SYS_mknodat = 559; +pub const SYS_kevent = 560; +pub const SYS_MAXSYSCALL = 561; + +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 = 0; +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_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 fn syscall0(number: usize) -> usize { + asm volatile ("syscall" + : [ret] "={rax}" (-> usize) + : [number] "{rax}" (number) + : "rcx", "r11") +} + +pub fn syscall1(number: usize, arg1: usize) -> usize { + asm volatile ("syscall" + : [ret] "={rax}" (-> usize) + : [number] "{rax}" (number), + [arg1] "{rdi}" (arg1) + : "rcx", "r11") +} + +pub fn syscall2(number: usize, arg1: usize, arg2: usize) -> usize { + asm volatile ("syscall" + : [ret] "={rax}" (-> usize) + : [number] "{rax}" (number), + [arg1] "{rdi}" (arg1), + [arg2] "{rsi}" (arg2) + : "rcx", "r11") +} + +pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { + asm volatile ("syscall" + : [ret] "={rax}" (-> usize) + : [number] "{rax}" (number), + [arg1] "{rdi}" (arg1), + [arg2] "{rsi}" (arg2), + [arg3] "{rdx}" (arg3) + : "rcx", "r11") +} + +pub fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) -> usize { + asm volatile ("syscall" + : [ret] "={rax}" (-> usize) + : [number] "{rax}" (number), + [arg1] "{rdi}" (arg1), + [arg2] "{rsi}" (arg2), + [arg3] "{rdx}" (arg3), + [arg4] "{r10}" (arg4) + : "rcx", "r11") +} + +pub fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) -> usize { + asm volatile ("syscall" + : [ret] "={rax}" (-> usize) + : [number] "{rax}" (number), + [arg1] "{rdi}" (arg1), + [arg2] "{rsi}" (arg2), + [arg3] "{rdx}" (arg3), + [arg4] "{r10}" (arg4), + [arg5] "{r8}" (arg5) + : "rcx", "r11") +} + +pub fn syscall6(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, + arg5: usize, arg6: usize) -> usize +{ + asm volatile ("syscall" + : [ret] "={rax}" (-> usize) + : [number] "{rax}" (number), + [arg1] "{rdi}" (arg1), + [arg2] "{rsi}" (arg2), + [arg3] "{rdx}" (arg3), + [arg4] "{r10}" (arg4), + [arg5] "{r8}" (arg5), + [arg6] "{r9}" (arg6) + : "rcx", "r11") +} + +pub nakedcc fn restore_rt() { + asm volatile ("syscall" + : + : [number] "{rax}" (usize(SYS_rt_sigreturn)) + : "rcx", "r11") +} + + +pub const msghdr = extern struct { + msg_name: &u8, + msg_namelen: socklen_t, + msg_iov: &iovec, + msg_iovlen: i32, + __pad1: i32, + msg_control: &u8, + msg_controllen: socklen_t, + __pad2: socklen_t, + msg_flags: i32, +}; + +/// Renamed to Stat to not conflict with the stat function. +pub const Stat = extern struct { + dev: u64, + ino: u64, + nlink: usize, + + mode: u32, + uid: u32, + gid: u32, + __pad0: u32, + rdev: u64, + size: i64, + blksize: isize, + blocks: i64, + + atim: timespec, + mtim: timespec, + ctim: timespec, + __unused: [3]isize, +}; + +pub const timespec = extern struct { + tv_sec: isize, + tv_nsec: isize, +}; diff --git a/std/os/get_user_id.zig b/std/os/get_user_id.zig index 1bcf69478f..b56b0fd1fc 100644 --- a/std/os/get_user_id.zig +++ b/std/os/get_user_id.zig @@ -11,7 +11,7 @@ pub const UserInfo = struct.{ /// POSIX function which gets a uid from username. pub fn getUserInfo(name: []const u8) !UserInfo { return switch (builtin.os) { - Os.linux, Os.macosx, Os.ios => posixGetUserInfo(name), + Os.linux, Os.macosx, Os.ios, Os.freebsd => posixGetUserInfo(name), else => @compileError("Unsupported OS"), }; } diff --git a/std/os/index.zig b/std/os/index.zig index d9e6c3c81d..f332e8212a 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -24,10 +24,12 @@ test "std.os" { pub const windows = @import("windows/index.zig"); pub const darwin = @import("darwin.zig"); pub const linux = @import("linux/index.zig"); +pub const freebsd = @import("freebsd.zig"); pub const zen = @import("zen.zig"); pub const posix = switch (builtin.os) { Os.linux => linux, Os.macosx, Os.ios => darwin, + Os.freebsd => freebsd, Os.zen => zen, else => @compileError("Unsupported OS"), }; @@ -174,7 +176,7 @@ pub fn abort() noreturn { c.abort(); } switch (builtin.os) { - Os.linux, Os.macosx, Os.ios => { + Os.linux, Os.macosx, Os.ios, Os.freebsd => { _ = posix.raise(posix.SIGABRT); _ = posix.raise(posix.SIGKILL); while (true) {} @@ -196,7 +198,7 @@ pub fn exit(status: u8) noreturn { c.exit(status); } switch (builtin.os) { - Os.linux, Os.macosx, Os.ios => { + Os.linux, Os.macosx, Os.ios, Os.freebsd => { posix.exit(status); }, Os.windows => { diff --git a/std/os/path.zig b/std/os/path.zig index 01409abb88..8096cdd0d2 100644 --- a/std/os/path.zig +++ b/std/os/path.zig @@ -1161,7 +1161,7 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro const pathname_w = try windows_util.cStrToPrefixedFileW(pathname); return realW(out_buffer, pathname_w); }, - Os.macosx, Os.ios => { + Os.macosx, Os.ios, Os.freebsd => { // TODO instead of calling the libc function here, port the implementation to Zig const err = posix.getErrno(posix.realpath(pathname, out_buffer)); switch (err) { @@ -1202,7 +1202,7 @@ pub fn real(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: []const u8) RealError! const pathname_w = try windows_util.sliceToPrefixedFileW(pathname); return realW(out_buffer, &pathname_w); }, - Os.macosx, Os.ios, Os.linux => { + Os.macosx, Os.ios, Os.linux, Os.freebsd => { const pathname_c = try os.toPosixPath(pathname); return realC(out_buffer, &pathname_c); }, -- cgit v1.2.3 From 264dd2eb579e78471c639baf698f7665ea016349 Mon Sep 17 00:00:00 2001 From: Marc Tiehuis Date: Sat, 21 Oct 2017 22:24:15 +0000 Subject: Set FreeBSD ELF OS/ABI when targeting Closes #553. --- src/link.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/link.cpp b/src/link.cpp index 424b06169e..613768cec8 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -150,6 +150,10 @@ static const char *getLDMOption(const ZigTarget *t) { if (t->env_type == ZigLLVM_GNUX32) { return "elf32_x86_64"; } + // Any target elf will use the freebsd osabi if suffixed with "_fbsd". + if (t->os == OsFreeBSD) { + return "elf_x86_64_fbsd"; + } return "elf_x86_64"; default: zig_unreachable(); -- cgit v1.2.3 From 831bb668955fa9d332f7beb1ea11f1c8028e5235 Mon Sep 17 00:00:00 2001 From: Greg V Date: Wed, 17 Oct 2018 22:21:16 +0300 Subject: Set up libc/rtld paths for FreeBSD --- src-self-hosted/libc_installation.zig | 2 +- src-self-hosted/target.zig | 9 ++++++++- src/analyze.cpp | 6 +++++- src/link.cpp | 3 +++ 4 files changed, 17 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index daab058223..86672a2b95 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -172,7 +172,7 @@ pub const LibCInstallation = struct.{ try group.call(findNativeStaticLibDir, self, loop); try group.call(findNativeDynamicLinker, self, loop); }, - builtin.Os.macosx => { + builtin.Os.macosx, builtin.Os.freebsd => { self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include"); }, else => @compileError("unimplemented: find libc for this OS"), diff --git a/src-self-hosted/target.zig b/src-self-hosted/target.zig index 44c98e79bf..0b6842490d 100644 --- a/src-self-hosted/target.zig +++ b/src-self-hosted/target.zig @@ -299,6 +299,13 @@ pub const Target = union(enum).{ pub fn getDynamicLinkerPath(self: Target) ?[]const u8 { const env = self.getEnviron(); const arch = self.getArch(); + const os = self.getOs(); + switch (os) { + builtin.Os.freebsd => { + return "/libexec/ld-elf.so.1"; + }, + else => {}, + } switch (env) { builtin.Environ.android => { if (self.is64bit()) { @@ -493,6 +500,7 @@ pub const Target = union(enum).{ builtin.Os.linux, builtin.Os.macosx, + builtin.Os.freebsd, builtin.Os.openbsd, builtin.Os.zen, => switch (id) { @@ -527,7 +535,6 @@ pub const Target = union(enum).{ builtin.Os.ananas, builtin.Os.cloudabi, builtin.Os.dragonfly, - builtin.Os.freebsd, builtin.Os.fuchsia, builtin.Os.ios, builtin.Os.kfreebsd, diff --git a/src/analyze.cpp b/src/analyze.cpp index e71369eac9..4d7fe1a656 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -4606,7 +4606,7 @@ void find_libc_include_path(CodeGen *g) { } } else if (g->zig_target.os == OsLinux) { g->libc_include_dir = get_linux_libc_include_path(); - } else if (g->zig_target.os == OsMacOSX) { + } else if (g->zig_target.os == OsMacOSX || g->zig_target.os == OsFreeBSD) { g->libc_include_dir = buf_create_from_str("/usr/include"); } else { // TODO find libc at runtime for other operating systems @@ -4652,6 +4652,8 @@ void find_libc_lib_path(CodeGen *g) { } else if (g->zig_target.os == OsLinux) { g->libc_lib_dir = get_linux_libc_lib_path("crt1.o"); + } else if (g->zig_target.os == OsFreeBSD) { + g->libc_lib_dir = buf_create_from_str("/usr/lib"); } else { zig_panic("Unable to determine libc lib path."); } @@ -4664,6 +4666,8 @@ void find_libc_lib_path(CodeGen *g) { return; } else if (g->zig_target.os == OsLinux) { g->libc_static_lib_dir = get_linux_libc_lib_path("crtbegin.o"); + } else if (g->zig_target.os == OsFreeBSD) { + g->libc_static_lib_dir = buf_create_from_str("/usr/lib"); } else { zig_panic("Unable to determine libc static lib path."); } diff --git a/src/link.cpp b/src/link.cpp index 613768cec8..0913b96a01 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -195,6 +195,9 @@ static Buf *try_dynamic_linker_path(const char *ld_name) { } static Buf *get_dynamic_linker_path(CodeGen *g) { + if (g->zig_target.os == OsFreeBSD) { + return buf_create_from_str("/libexec/ld-elf.so.1"); + } if (g->is_native_target && g->zig_target.arch.arch == ZigLLVM_x86_64) { static const char *ld_names[] = { "ld-linux-x86-64.so.2", -- cgit v1.2.3 From 6a8fb060067685a2ff27d05092f3fcf2ee17e83c Mon Sep 17 00:00:00 2001 From: Greg V Date: Wed, 17 Oct 2018 18:00:36 +0300 Subject: Split at zero byte in SplitIterator To avoid extra zeros in buffers --- src/util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/util.cpp b/src/util.cpp index 192d74e766..f7bda86c42 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -47,7 +47,7 @@ bool ptr_eq(const void *a, const void *b) { // Ported from std/mem.zig. bool SplitIterator_isSplitByte(SplitIterator *self, uint8_t byte) { for (size_t i = 0; i < self->split_bytes.len; i += 1) { - if (byte == self->split_bytes.ptr[i]) { + if (byte == self->split_bytes.ptr[i] || byte == 0) { return true; } } -- cgit v1.2.3 From 2a580278c4db3a60766bb904f42486f0f1872c72 Mon Sep 17 00:00:00 2001 From: Jimmi HC Date: Sat, 17 Nov 2018 14:42:47 +0100 Subject: Updated comments in parser.cpp --- src/parser.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/parser.cpp b/src/parser.cpp index b5c67875de..077365995e 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -91,7 +91,7 @@ static Token *ast_parse_break_label(ParseContext *pc); static Token *ast_parse_block_label(ParseContext *pc); static AstNode *ast_parse_field_init(ParseContext *pc); static AstNode *ast_parse_while_continue_expr(ParseContext *pc); -static AstNode *ast_parse_section(ParseContext *pc); +static AstNode *ast_parse_link_section(ParseContext *pc); static Optional ast_parse_fn_cc(ParseContext *pc); static AstNode *ast_parse_param_decl(ParseContext *pc); static AstNode *ast_parse_param_type(ParseContext *pc); @@ -775,7 +775,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { return nullptr; } -// FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? Section? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) +// FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) static AstNode *ast_parse_fn_proto(ParseContext *pc) { Token *first = peek_token(pc); AstNodeFnProto fn_cc; @@ -806,7 +806,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { expect_token(pc, TokenIdRParen); AstNode *align_expr = ast_parse_byte_align(pc); - AstNode *section_expr = ast_parse_section(pc); + AstNode *section_expr = ast_parse_link_section(pc); Token *var = eat_token_if(pc, TokenIdKeywordVar); Token *exmark = nullptr; AstNode *return_type = nullptr; @@ -842,7 +842,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { return res; } -// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? Section? (EQUAL Expr)? SEMICOLON +// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON static AstNode *ast_parse_var_decl(ParseContext *pc) { Token *first = eat_token_if(pc, TokenIdKeywordConst); if (first == nullptr) @@ -856,7 +856,7 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) { type_expr = ast_expect(pc, ast_parse_type_expr); AstNode *align_expr = ast_parse_byte_align(pc); - AstNode *section_expr = ast_parse_section(pc); + AstNode *section_expr = ast_parse_link_section(pc); AstNode *expr = nullptr; if (eat_token_if(pc, TokenIdEq) != nullptr) expr = ast_expect(pc, ast_parse_expr); @@ -1490,8 +1490,8 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) { } // SuffixExpr -// <- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArgumnets -// / PrimaryTypeExpr (SuffixOp / FnCallArgumnets)* +// <- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArguments +// / PrimaryTypeExpr (SuffixOp / FnCallArguments)* static AstNode *ast_parse_suffix_expr(ParseContext *pc) { AstNode *async_call = ast_parse_async_prefix(pc); if (async_call != nullptr) { @@ -1599,7 +1599,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) { } // PrimaryTypeExpr -// <- BUILTININDENTIFIER FnCallArgumnets +// <- BUILTINIDENTIFIER FnCallArguments // / CHAR_LITERAL // / ContainerDecl // / ErrorSetDecl @@ -1978,7 +1978,7 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) { return res; } -// AsmInput <- COLON AsmInputList AsmCloppers? +// AsmInput <- COLON AsmInputList AsmClobbers? static AstNode *ast_parse_asm_input(ParseContext *pc) { if (eat_token_if(pc, TokenIdColon) == nullptr) return nullptr; @@ -2011,7 +2011,7 @@ static AsmInput *ast_parse_asm_input_item(ParseContext *pc) { return res; } -// AsmCloppers <- COLON StringList +// AsmClobbers <- COLON StringList static AstNode *ast_parse_asm_cloppers(ParseContext *pc) { if (eat_token_if(pc, TokenIdColon) == nullptr) return nullptr; @@ -2080,8 +2080,8 @@ static AstNode *ast_parse_while_continue_expr(ParseContext *pc) { return expr; } -// Section <- KEYWORD_section LPAREN Expr RPAREN -static AstNode *ast_parse_section(ParseContext *pc) { +// LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN +static AstNode *ast_parse_link_section(ParseContext *pc) { Token *first = eat_token_if(pc, TokenIdKeywordLinkSection); if (first == nullptr) return nullptr; @@ -2742,7 +2742,7 @@ static AstNode *ast_parse_async_prefix(ParseContext *pc) { return res; } -// FnCallArgumnets <- LPAREN ExprList RPAREN +// FnCallArguments <- LPAREN ExprList RPAREN static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) { Token *paren = eat_token_if(pc, TokenIdLParen); if (paren == nullptr) -- cgit v1.2.3 From 085d049a088af20c1eeeab2b8ebeb7dc6af7b07d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 17 Nov 2018 11:19:46 -0500 Subject: aarch64 improvements * support C ABI for all return types * don't include __aeabi_uldivmod & co on aarch64 since it's 64 bit --- src/analyze.cpp | 2 +- src/target.cpp | 61 ++++++++++++++++ src/target.hpp | 2 + std/special/compiler_rt/index.zig | 143 +++++++++++++++++++++----------------- 4 files changed, 144 insertions(+), 64 deletions(-) (limited to 'src') diff --git a/src/analyze.cpp b/src/analyze.cpp index bc9789fca8..349169f9d1 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1059,7 +1059,7 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) { } zig_panic("TODO implement C ABI for x86_64 return types. type '%s'\nSee https://github.com/ziglang/zig/issues/1481", buf_ptr(&fn_type_id->return_type->name)); - } else if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb) { + } else if (target_is_arm(&g->zig_target)) { return type_size(g, fn_type_id->return_type) > 16; } zig_panic("TODO implement C ABI for this architecture. See https://github.com/ziglang/zig/issues/1481"); diff --git a/src/target.cpp b/src/target.cpp index 8372e9ce95..7075c8a5c7 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -1011,3 +1011,64 @@ const char *arch_stack_pointer_register_name(const ArchType *arch) { } zig_unreachable(); } + +bool target_is_arm(const ZigTarget *target) { + switch (target->arch.arch) { + case ZigLLVM_UnknownArch: + zig_unreachable(); + case ZigLLVM_aarch64: + case ZigLLVM_arm: + case ZigLLVM_thumb: + case ZigLLVM_aarch64_be: + case ZigLLVM_armeb: + case ZigLLVM_thumbeb: + return true; + + case ZigLLVM_x86: + case ZigLLVM_x86_64: + case ZigLLVM_amdgcn: + case ZigLLVM_amdil: + case ZigLLVM_amdil64: + case ZigLLVM_arc: + case ZigLLVM_avr: + case ZigLLVM_bpfeb: + case ZigLLVM_bpfel: + case ZigLLVM_hexagon: + case ZigLLVM_lanai: + case ZigLLVM_hsail: + case ZigLLVM_hsail64: + case ZigLLVM_kalimba: + case ZigLLVM_le32: + case ZigLLVM_le64: + case ZigLLVM_mips: + case ZigLLVM_mips64: + case ZigLLVM_mips64el: + case ZigLLVM_mipsel: + case ZigLLVM_msp430: + case ZigLLVM_nios2: + case ZigLLVM_nvptx: + case ZigLLVM_nvptx64: + case ZigLLVM_ppc64le: + case ZigLLVM_r600: + case ZigLLVM_renderscript32: + case ZigLLVM_renderscript64: + case ZigLLVM_riscv32: + case ZigLLVM_riscv64: + case ZigLLVM_shave: + case ZigLLVM_sparc: + case ZigLLVM_sparcel: + case ZigLLVM_sparcv9: + case ZigLLVM_spir: + case ZigLLVM_spir64: + case ZigLLVM_systemz: + case ZigLLVM_tce: + case ZigLLVM_tcele: + case ZigLLVM_wasm32: + case ZigLLVM_wasm64: + case ZigLLVM_xcore: + case ZigLLVM_ppc: + case ZigLLVM_ppc64: + return false; + } + zig_unreachable(); +} diff --git a/src/target.hpp b/src/target.hpp index a4685fc09e..04652179d2 100644 --- a/src/target.hpp +++ b/src/target.hpp @@ -121,4 +121,6 @@ Buf *target_dynamic_linker(ZigTarget *target); bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target); ZigLLVM_OSType get_llvm_os_type(Os os_type); +bool target_is_arm(const ZigTarget *target); + #endif diff --git a/std/special/compiler_rt/index.zig b/std/special/compiler_rt/index.zig index c826af83bc..b2add4e3fa 100644 --- a/std/special/compiler_rt/index.zig +++ b/std/special/compiler_rt/index.zig @@ -59,7 +59,7 @@ comptime { @export("__umoddi3", __umoddi3, linkage); @export("__udivmodsi4", __udivmodsi4, linkage); - if (isArmArch()) { + if (is_arm_arch and !is_arm_64) { @export("__aeabi_uldivmod", __aeabi_uldivmod, linkage); @export("__aeabi_uidivmod", __aeabi_uidivmod, linkage); @export("__aeabi_uidiv", __udivsi3, linkage); @@ -149,68 +149,85 @@ extern fn __aeabi_uldivmod(numerator: u64, denominator: u64) AeabiUlDivModResult return result; } -fn isArmArch() bool { - return switch (builtin.arch) { - builtin.Arch.armv8_3a, - builtin.Arch.armv8_2a, - builtin.Arch.armv8_1a, - builtin.Arch.armv8, - builtin.Arch.armv8r, - builtin.Arch.armv8m_baseline, - builtin.Arch.armv8m_mainline, - builtin.Arch.armv7, - builtin.Arch.armv7em, - builtin.Arch.armv7m, - builtin.Arch.armv7s, - builtin.Arch.armv7k, - builtin.Arch.armv7ve, - builtin.Arch.armv6, - builtin.Arch.armv6m, - builtin.Arch.armv6k, - builtin.Arch.armv6t2, - builtin.Arch.armv5, - builtin.Arch.armv5te, - builtin.Arch.armv4t, - builtin.Arch.armebv8_3a, - builtin.Arch.armebv8_2a, - builtin.Arch.armebv8_1a, - builtin.Arch.armebv8, - builtin.Arch.armebv8r, - builtin.Arch.armebv8m_baseline, - builtin.Arch.armebv8m_mainline, - builtin.Arch.armebv7, - builtin.Arch.armebv7em, - builtin.Arch.armebv7m, - builtin.Arch.armebv7s, - builtin.Arch.armebv7k, - builtin.Arch.armebv7ve, - builtin.Arch.armebv6, - builtin.Arch.armebv6m, - builtin.Arch.armebv6k, - builtin.Arch.armebv6t2, - builtin.Arch.armebv5, - builtin.Arch.armebv5te, - builtin.Arch.armebv4t, - builtin.Arch.aarch64v8_3a, - builtin.Arch.aarch64v8_2a, - builtin.Arch.aarch64v8_1a, - builtin.Arch.aarch64v8, - builtin.Arch.aarch64v8r, - builtin.Arch.aarch64v8m_baseline, - builtin.Arch.aarch64v8m_mainline, - builtin.Arch.aarch64_bev8_3a, - builtin.Arch.aarch64_bev8_2a, - builtin.Arch.aarch64_bev8_1a, - builtin.Arch.aarch64_bev8, - builtin.Arch.aarch64_bev8r, - builtin.Arch.aarch64_bev8m_baseline, - builtin.Arch.aarch64_bev8m_mainline, - builtin.Arch.thumb, - builtin.Arch.thumbeb, - => true, - else => false, - }; -} +const is_arm_64 = switch (builtin.arch) { + builtin.Arch.aarch64v8_3a, + builtin.Arch.aarch64v8_2a, + builtin.Arch.aarch64v8_1a, + builtin.Arch.aarch64v8, + builtin.Arch.aarch64v8r, + builtin.Arch.aarch64v8m_baseline, + builtin.Arch.aarch64v8m_mainline, + builtin.Arch.aarch64_bev8_3a, + builtin.Arch.aarch64_bev8_2a, + builtin.Arch.aarch64_bev8_1a, + builtin.Arch.aarch64_bev8, + builtin.Arch.aarch64_bev8r, + builtin.Arch.aarch64_bev8m_baseline, + builtin.Arch.aarch64_bev8m_mainline, + => true, + else => false, +}; + +const is_arm_arch = switch (builtin.arch) { + builtin.Arch.armv8_3a, + builtin.Arch.armv8_2a, + builtin.Arch.armv8_1a, + builtin.Arch.armv8, + builtin.Arch.armv8r, + builtin.Arch.armv8m_baseline, + builtin.Arch.armv8m_mainline, + builtin.Arch.armv7, + builtin.Arch.armv7em, + builtin.Arch.armv7m, + builtin.Arch.armv7s, + builtin.Arch.armv7k, + builtin.Arch.armv7ve, + builtin.Arch.armv6, + builtin.Arch.armv6m, + builtin.Arch.armv6k, + builtin.Arch.armv6t2, + builtin.Arch.armv5, + builtin.Arch.armv5te, + builtin.Arch.armv4t, + builtin.Arch.armebv8_3a, + builtin.Arch.armebv8_2a, + builtin.Arch.armebv8_1a, + builtin.Arch.armebv8, + builtin.Arch.armebv8r, + builtin.Arch.armebv8m_baseline, + builtin.Arch.armebv8m_mainline, + builtin.Arch.armebv7, + builtin.Arch.armebv7em, + builtin.Arch.armebv7m, + builtin.Arch.armebv7s, + builtin.Arch.armebv7k, + builtin.Arch.armebv7ve, + builtin.Arch.armebv6, + builtin.Arch.armebv6m, + builtin.Arch.armebv6k, + builtin.Arch.armebv6t2, + builtin.Arch.armebv5, + builtin.Arch.armebv5te, + builtin.Arch.armebv4t, + builtin.Arch.aarch64v8_3a, + builtin.Arch.aarch64v8_2a, + builtin.Arch.aarch64v8_1a, + builtin.Arch.aarch64v8, + builtin.Arch.aarch64v8r, + builtin.Arch.aarch64v8m_baseline, + builtin.Arch.aarch64v8m_mainline, + builtin.Arch.aarch64_bev8_3a, + builtin.Arch.aarch64_bev8_2a, + builtin.Arch.aarch64_bev8_1a, + builtin.Arch.aarch64_bev8, + builtin.Arch.aarch64_bev8r, + builtin.Arch.aarch64_bev8m_baseline, + builtin.Arch.aarch64_bev8m_mainline, + builtin.Arch.thumb, + builtin.Arch.thumbeb, + => true, + else => false, +}; nakedcc fn __aeabi_uidivmod() void { @setRuntimeSafety(false); -- cgit v1.2.3 From 947cdafd917f30cfd3d28b85e16a6ca980162dc9 Mon Sep 17 00:00:00 2001 From: kristopher tate Date: Sun, 18 Nov 2018 15:15:17 +0900 Subject: src/os.cpp: os_file_read: return ErrorIsDir on case EISDIR; --- src/os.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/os.cpp b/src/os.cpp index 5d43e73d8a..9d16d763ec 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -1976,7 +1976,7 @@ Error os_file_read(OsFile file, void *ptr, size_t *len) { case EFAULT: zig_unreachable(); case EISDIR: - zig_unreachable(); + return ErrorIsDir; default: return ErrorFileSystem; } -- cgit v1.2.3 From f8a782fb2ec63b89fadb409f7378066a26945d3b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 18 Nov 2018 19:36:27 -0500 Subject: all numbers with comptime known values implicitly cast to all number types. If the value does not fit, a compile error is emitted. closes #422 closes #1712 --- doc/langref.html.in | 4 +- src/ir.cpp | 406 +++++++++++++++++++++++++++++++++--------------- test/cases/cast.zig | 10 ++ test/compile_errors.zig | 87 +++++++---- 4 files changed, 346 insertions(+), 161 deletions(-) (limited to 'src') diff --git a/doc/langref.html.in b/doc/langref.html.in index c3d8af4420..022b03ef40 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -6659,7 +6659,7 @@ fn foo(x: []const u8) u8 { {#header_close#} {#header_open|Cast Negative Number to Unsigned Integer#}

At compile-time:

- {#code_begin|test_err|attempt to cast negative value to unsigned integer#} + {#code_begin|test_err|cannot cast negative value -1 to unsigned integer type 'u32'#} comptime { const value: i32 = -1; const unsigned = @intCast(u32, value); @@ -6681,7 +6681,7 @@ pub fn main() void { {#header_close#} {#header_open|Cast Truncates Data#}

At compile-time:

- {#code_begin|test_err|cast from 'u16' to 'u8' truncates bits#} + {#code_begin|test_err|integer value 300 cannot be implicitly casted to type 'u8'#} comptime { const spartan_count: u16 = 300; const byte = @intCast(u8, spartan_count); diff --git a/src/ir.cpp b/src/ir.cpp index 2c499e885d..3a22d0aa17 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -138,6 +138,11 @@ struct ConstCastErrSetMismatch { ZigList missing_errors; }; +enum UndefAllowed { + UndefOk, + UndefBad, +}; + static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope); static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval); static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction); @@ -157,6 +162,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, ConstExprValue *out_val, ConstExprValue *ptr_val); static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, ZigType *dest_type, IrInstruction *dest_type_src); +static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed); static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { assert(get_src_ptr_type(const_val->type) != nullptr); @@ -8063,15 +8069,153 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc return false; } - ConstExprValue *const_val = &instruction->value; - assert(const_val->special != ConstValSpecialRuntime); + ConstExprValue *const_val = ir_resolve_const(ira, instruction, UndefBad); + assert(const_val != nullptr); + + bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt); + bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || const_val->type->id == ZigTypeIdComptimeFloat); - bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || - const_val->type->id == ZigTypeIdComptimeInt); - bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || - const_val->type->id == ZigTypeIdComptimeFloat); if (other_type->id == ZigTypeIdFloat) { - return true; + if (const_val->type->id == ZigTypeIdComptimeInt || const_val->type->id == ZigTypeIdComptimeFloat) { + return true; + } + if (const_val->type->id == ZigTypeIdInt) { + BigFloat tmp_bf; + bigfloat_init_bigint(&tmp_bf, &const_val->data.x_bigint); + BigFloat orig_bf; + switch (other_type->data.floating.bit_count) { + case 16: { + float16_t tmp = bigfloat_to_f16(&tmp_bf); + bigfloat_init_16(&orig_bf, tmp); + break; + } + case 32: { + float tmp = bigfloat_to_f32(&tmp_bf); + bigfloat_init_32(&orig_bf, tmp); + break; + } + case 64: { + double tmp = bigfloat_to_f64(&tmp_bf); + bigfloat_init_64(&orig_bf, tmp); + break; + } + case 80: + zig_panic("TODO"); + case 128: { + float128_t tmp = bigfloat_to_f128(&tmp_bf); + bigfloat_init_128(&orig_bf, tmp); + break; + } + default: + zig_unreachable(); + } + BigInt orig_bi; + bigint_init_bigfloat(&orig_bi, &orig_bf); + if (bigint_cmp(&orig_bi, &const_val->data.x_bigint) == CmpEQ) { + return true; + } + Buf *val_buf = buf_alloc(); + bigint_append_buf(val_buf, &const_val->data.x_bigint, 10); + ir_add_error(ira, instruction, + buf_sprintf("integer value %s has no representation in type '%s'", + buf_ptr(val_buf), + buf_ptr(&other_type->name))); + return false; + } + if (other_type->data.floating.bit_count >= const_val->type->data.floating.bit_count) { + return true; + } + switch (other_type->data.floating.bit_count) { + case 16: + switch (const_val->type->data.floating.bit_count) { + case 32: { + float16_t tmp = zig_double_to_f16(const_val->data.x_f32); + float orig = zig_f16_to_double(tmp); + if (const_val->data.x_f32 == orig) { + return true; + } + break; + } + case 64: { + float16_t tmp = zig_double_to_f16(const_val->data.x_f64); + double orig = zig_f16_to_double(tmp); + if (const_val->data.x_f64 == orig) { + return true; + } + break; + } + case 80: + zig_panic("TODO"); + case 128: { + float16_t tmp = f128M_to_f16(&const_val->data.x_f128); + float128_t orig; + f16_to_f128M(tmp, &orig); + if (f128M_eq(&orig, &const_val->data.x_f128)) { + return true; + } + break; + } + default: + zig_unreachable(); + } + break; + case 32: + switch (const_val->type->data.floating.bit_count) { + case 64: { + float tmp = const_val->data.x_f64; + double orig = tmp; + if (const_val->data.x_f64 == orig) { + return true; + } + break; + } + case 80: + zig_panic("TODO"); + case 128: { + float32_t tmp = f128M_to_f32(&const_val->data.x_f128); + float128_t orig; + f32_to_f128M(tmp, &orig); + if (f128M_eq(&orig, &const_val->data.x_f128)) { + return true; + } + break; + } + default: + zig_unreachable(); + } + break; + case 64: + switch (const_val->type->data.floating.bit_count) { + case 80: + zig_panic("TODO"); + case 128: { + float64_t tmp = f128M_to_f64(&const_val->data.x_f128); + float128_t orig; + f64_to_f128M(tmp, &orig); + if (f128M_eq(&orig, &const_val->data.x_f128)) { + return true; + } + break; + } + default: + zig_unreachable(); + } + break; + case 80: + assert(const_val->type->data.floating.bit_count == 128); + zig_panic("TODO"); + case 128: + return true; + default: + zig_unreachable(); + } + Buf *val_buf = buf_alloc(); + float_append_buf(val_buf, const_val); + ir_add_error(ira, instruction, + buf_sprintf("cast of value %s to type '%s' loses information", + buf_ptr(val_buf), + buf_ptr(&other_type->name))); + return false; } else if (other_type->id == ZigTypeIdInt && const_val_is_int) { if (!other_type->data.integral.is_signed && const_val->data.x_bigint.is_negative) { Buf *val_buf = buf_alloc(); @@ -9453,11 +9597,6 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio return const_instr; } -enum UndefAllowed { - UndefOk, - UndefBad, -}; - static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) { switch (value->value.special) { case ConstValSpecialStatic: @@ -10370,6 +10509,121 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false); } + // cast from T to ?T + // note that the *T to ?*T case is handled via the "ConstCastOnly" mechanism + if (wanted_type->id == ZigTypeIdOptional) { + ZigType *wanted_child_type = wanted_type->data.maybe.child_type; + if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node, + false).id == ConstCastResultIdOk) + { + return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); + } else if (actual_type->id == ZigTypeIdComptimeInt || + actual_type->id == ZigTypeIdComptimeFloat) + { + if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) { + return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); + } else { + return ira->codegen->invalid_instruction; + } + } else if ( + wanted_child_type->id == ZigTypeIdPointer && + wanted_child_type->data.pointer.ptr_len == PtrLenUnknown && + actual_type->id == ZigTypeIdPointer && + actual_type->data.pointer.ptr_len == PtrLenSingle && + actual_type->data.pointer.child_type->id == ZigTypeIdArray) + { + if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) + return ira->codegen->invalid_instruction; + if ((err = type_resolve(ira->codegen, wanted_child_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) + return ira->codegen->invalid_instruction; + if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_child_type) && + types_match_const_cast_only(ira, wanted_child_type->data.pointer.child_type, + actual_type->data.pointer.child_type->data.array.child_type, source_node, + !wanted_child_type->data.pointer.is_const).id == ConstCastResultIdOk) + { + IrInstruction *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, + wanted_child_type); + if (type_is_invalid(cast1->value.type)) + return ira->codegen->invalid_instruction; + return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type); + } + } + } + + // T to E!T + if (wanted_type->id == ZigTypeIdErrorUnion) { + if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type, + source_node, false).id == ConstCastResultIdOk) + { + return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type); + } else if (actual_type->id == ZigTypeIdComptimeInt || + actual_type->id == ZigTypeIdComptimeFloat) + { + if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) { + return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type); + } else { + return ira->codegen->invalid_instruction; + } + } + } + + // cast from T to E!?T + if (wanted_type->id == ZigTypeIdErrorUnion && + wanted_type->data.error_union.payload_type->id == ZigTypeIdOptional && + actual_type->id != ZigTypeIdOptional) + { + ZigType *wanted_child_type = wanted_type->data.error_union.payload_type->data.maybe.child_type; + if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node, false).id == ConstCastResultIdOk || + actual_type->id == ZigTypeIdNull || + actual_type->id == ZigTypeIdComptimeInt || + actual_type->id == ZigTypeIdComptimeFloat) + { + IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value); + if (type_is_invalid(cast1->value.type)) + return ira->codegen->invalid_instruction; + + IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1); + if (type_is_invalid(cast2->value.type)) + return ira->codegen->invalid_instruction; + + return cast2; + } + } + + + // cast from comptime-known number to another number type + if (instr_is_comptime(value) && + (actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt || + actual_type->id == ZigTypeIdFloat || actual_type->id == ZigTypeIdComptimeFloat) && + (wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt || + wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat)) + { + if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) { + if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) { + IrInstruction *result = ir_const(ira, source_instr, wanted_type); + if (actual_type->id == ZigTypeIdComptimeInt || actual_type->id == ZigTypeIdInt) { + bigint_init_bigint(&result->value.data.x_bigint, &value->value.data.x_bigint); + } else { + float_init_bigint(&result->value.data.x_bigint, &value->value); + } + return result; + } else if (wanted_type->id == ZigTypeIdComptimeFloat || wanted_type->id == ZigTypeIdFloat) { + IrInstruction *result = ir_const(ira, source_instr, wanted_type); + if (actual_type->id == ZigTypeIdComptimeInt || actual_type->id == ZigTypeIdInt) { + BigFloat bf; + bigfloat_init_bigint(&bf, &value->value.data.x_bigint); + float_init_bigfloat(&result->value, &bf); + } else { + float_init_float(&result->value, &value->value); + } + return result; + } + zig_unreachable(); + } else { + return ira->codegen->invalid_instruction; + } + } + // widening conversion if (wanted_type->id == ZigTypeIdInt && actual_type->id == ZigTypeIdInt && @@ -10472,47 +10726,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst } - // cast from T to ?T - // note that the *T to ?*T case is handled via the "ConstCastOnly" mechanism - if (wanted_type->id == ZigTypeIdOptional) { - ZigType *wanted_child_type = wanted_type->data.maybe.child_type; - if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node, - false).id == ConstCastResultIdOk) - { - return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); - } else if (actual_type->id == ZigTypeIdComptimeInt || - actual_type->id == ZigTypeIdComptimeFloat) - { - if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) { - return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); - } else { - return ira->codegen->invalid_instruction; - } - } else if ( - wanted_child_type->id == ZigTypeIdPointer && - wanted_child_type->data.pointer.ptr_len == PtrLenUnknown && - actual_type->id == ZigTypeIdPointer && - actual_type->data.pointer.ptr_len == PtrLenSingle && - actual_type->data.pointer.child_type->id == ZigTypeIdArray) - { - if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) - return ira->codegen->invalid_instruction; - if ((err = type_resolve(ira->codegen, wanted_child_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) - return ira->codegen->invalid_instruction; - if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_child_type) && - types_match_const_cast_only(ira, wanted_child_type->data.pointer.child_type, - actual_type->data.pointer.child_type->data.array.child_type, source_node, - !wanted_child_type->data.pointer.is_const).id == ConstCastResultIdOk) - { - IrInstruction *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, - wanted_child_type); - if (type_is_invalid(cast1->value.type)) - return ira->codegen->invalid_instruction; - return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type); - } - } - } - // cast from null literal to maybe type if (wanted_type->id == ZigTypeIdOptional && actual_type->id == ZigTypeIdNull) @@ -10520,23 +10733,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type); } - // cast from child type of error type to error type - if (wanted_type->id == ZigTypeIdErrorUnion) { - if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type, - source_node, false).id == ConstCastResultIdOk) - { - return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type); - } else if (actual_type->id == ZigTypeIdComptimeInt || - actual_type->id == ZigTypeIdComptimeFloat) - { - if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) { - return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type); - } else { - return ira->codegen->invalid_instruction; - } - } - } - // cast from [N]T to E![]const T if (wanted_type->id == ZigTypeIdErrorUnion && is_slice(wanted_type->data.error_union.payload_type) && @@ -10568,54 +10764,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type); } - // cast from T to E!?T - if (wanted_type->id == ZigTypeIdErrorUnion && - wanted_type->data.error_union.payload_type->id == ZigTypeIdOptional && - actual_type->id != ZigTypeIdOptional) - { - ZigType *wanted_child_type = wanted_type->data.error_union.payload_type->data.maybe.child_type; - if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node, false).id == ConstCastResultIdOk || - actual_type->id == ZigTypeIdNull || - actual_type->id == ZigTypeIdComptimeInt || - actual_type->id == ZigTypeIdComptimeFloat) - { - IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value); - if (type_is_invalid(cast1->value.type)) - return ira->codegen->invalid_instruction; - - IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1); - if (type_is_invalid(cast2->value.type)) - return ira->codegen->invalid_instruction; - - return cast2; - } - } - - // cast from number literal to another type - if (actual_type->id == ZigTypeIdComptimeFloat || - actual_type->id == ZigTypeIdComptimeInt) - { - if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) { - CastOp op; - if ((actual_type->id == ZigTypeIdComptimeFloat && - wanted_type->id == ZigTypeIdFloat) || - (actual_type->id == ZigTypeIdComptimeInt && - wanted_type->id == ZigTypeIdInt)) - { - op = CastOpNumLitToConcrete; - } else if (wanted_type->id == ZigTypeIdInt) { - op = CastOpFloatToInt; - } else if (wanted_type->id == ZigTypeIdFloat) { - op = CastOpIntToFloat; - } else { - zig_unreachable(); - } - return ir_resolve_cast(ira, source_instr, value, wanted_type, op, false); - } else { - return ira->codegen->invalid_instruction; - } - } - // cast from typed number to integer or float literal. // works when the number is known at compile time if (instr_is_comptime(value) && @@ -17878,7 +18026,7 @@ static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstruct if (type_is_invalid(dest_type)) return ira->codegen->invalid_instruction; - if (dest_type->id != ZigTypeIdInt) { + if (dest_type->id != ZigTypeIdInt && dest_type->id != ZigTypeIdComptimeInt) { ir_add_error(ira, instruction->dest_type, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name))); return ira->codegen->invalid_instruction; } @@ -17887,20 +18035,22 @@ static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstruct if (type_is_invalid(target->value.type)) return ira->codegen->invalid_instruction; - if (target->value.type->id == ZigTypeIdComptimeInt) { - if (ir_num_lit_fits_in_other_type(ira, target, dest_type, true)) { - return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpNumLitToConcrete, false); - } else { - return ira->codegen->invalid_instruction; - } - } - - if (target->value.type->id != ZigTypeIdInt) { + if (target->value.type->id != ZigTypeIdInt && target->value.type->id != ZigTypeIdComptimeInt) { ir_add_error(ira, instruction->target, buf_sprintf("expected integer type, found '%s'", buf_ptr(&target->value.type->name))); return ira->codegen->invalid_instruction; } + if (instr_is_comptime(target)) { + return ir_implicit_cast(ira, target, dest_type); + } + + if (dest_type->id == ZigTypeIdComptimeInt) { + ir_add_error(ira, instruction->target, buf_sprintf("attempt to cast runtime value to '%s'", + buf_ptr(&dest_type->name))); + return ira->codegen->invalid_instruction; + } + return ir_analyze_widen_or_shorten(ira, &instruction->base, target, dest_type); } diff --git a/test/cases/cast.zig b/test/cases/cast.zig index e893ec13cd..06c029a405 100644 --- a/test/cases/cast.zig +++ b/test/cases/cast.zig @@ -452,3 +452,13 @@ test "implicit ptr to *c_void" { var c: *u32 = @ptrCast(*u32, ptr2.?); assert(c.* == 1); } + +test "@intCast to comptime_int" { + assert(@intCast(comptime_int, 0) == 0); +} + +test "implicit cast comptime numbers to any type when the value fits" { + const a: u64 = 255; + var b: u8 = a; + assert(b == 255); +} diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 7339be7fad..45bd6cb40b 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1,6 +1,61 @@ const tests = @import("tests.zig"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.add( + "cast negative value to unsigned integer", + \\comptime { + \\ const value: i32 = -1; + \\ const unsigned = @intCast(u32, value); + \\} + \\export fn entry1() void { + \\ const value: i32 = -1; + \\ const unsigned: u32 = value; + \\} + , + ".tmp_source.zig:3:36: error: cannot cast negative value -1 to unsigned integer type 'u32'", + ".tmp_source.zig:7:27: error: cannot cast negative value -1 to unsigned integer type 'u32'", + ); + + cases.add( + "integer cast truncates bits", + \\export fn entry1() void { + \\ const spartan_count: u16 = 300; + \\ const byte = @intCast(u8, spartan_count); + \\} + \\export fn entry2() void { + \\ const spartan_count: u16 = 300; + \\ const byte: u8 = spartan_count; + \\} + \\export fn entry3() void { + \\ var spartan_count: u16 = 300; + \\ var byte: u8 = spartan_count; + \\} + , + ".tmp_source.zig:3:31: error: integer value 300 cannot be implicitly casted to type 'u8'", + ".tmp_source.zig:7:22: error: integer value 300 cannot be implicitly casted to type 'u8'", + ".tmp_source.zig:11:20: error: expected type 'u8', found 'u16'", + ); + + cases.add( + "comptime implicit cast f64 to f32", + \\export fn entry() void { + \\ const x: f64 = 16777217; + \\ const y: f32 = x; + \\} + , + ".tmp_source.zig:3:20: error: cast of value 16777217.000000 to type 'f32' loses information", + ); + + cases.add( + "implicit cast from f64 to f32", + \\var x: f64 = 1.0; + \\var y: f32 = x; + \\ + \\export fn entry() usize { return @sizeOf(@typeOf(y)); } + , + ".tmp_source.zig:2:14: error: expected type 'f32', found 'f64'", + ); + cases.add( "exceeded maximum bit width of integer", \\export fn entry1() void { @@ -1819,7 +1874,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ if (0) {} \\} , - ".tmp_source.zig:2:9: error: integer value 0 cannot be implicitly casted to type 'bool'", + ".tmp_source.zig:2:9: error: expected type 'bool', found 'comptime_int'", ); cases.add( @@ -2422,16 +2477,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { ".tmp_source.zig:1:36: error: expected type 'fn(i32) i32', found 'extern fn(i32) i32'", ); - cases.add( - "implicit cast from f64 to f32", - \\const x : f64 = 1.0; - \\const y : f32 = x; - \\ - \\export fn entry() usize { return @sizeOf(@typeOf(y)); } - , - ".tmp_source.zig:2:17: error: expected type 'f32', found 'f64'", - ); - cases.add( "colliding invalid top level functions", \\fn func() bogus {} @@ -4049,16 +4094,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { ".tmp_source.zig:2:14: error: remainder division with 'i32' and 'i32': signed integers and floats must use @rem or @mod", ); - cases.add( - "cast negative value to unsigned integer", - \\comptime { - \\ const value: i32 = -1; - \\ const unsigned = @intCast(u32, value); - \\} - , - ".tmp_source.zig:3:22: error: attempt to cast negative value to unsigned integer", - ); - cases.add( "compile-time division by zero", \\comptime { @@ -4081,16 +4116,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { ".tmp_source.zig:4:17: error: division by zero", ); - cases.add( - "compile-time integer cast truncates bits", - \\comptime { - \\ const spartan_count: u16 = 300; - \\ const byte = @intCast(u8, spartan_count); - \\} - , - ".tmp_source.zig:3:18: error: cast from 'u16' to 'u8' truncates bits", - ); - cases.add( "@setRuntimeSafety twice for same scope", \\export fn foo() void { -- cgit v1.2.3 From 3829e200ecc251d6b55686c24bdbd579c5a2246a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 18 Nov 2018 20:03:35 -0500 Subject: fix assertion failure related to @intToEnum --- src/ir.cpp | 2 +- test/cases/cast.zig | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ir.cpp b/src/ir.cpp index 3a22d0aa17..55f17b811d 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -10153,7 +10153,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour return ira->codegen->invalid_instruction; } - assert(actual_type->id == ZigTypeIdInt); + assert(actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt); if (instr_is_comptime(target)) { ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); diff --git a/test/cases/cast.zig b/test/cases/cast.zig index 06c029a405..bd45bbc00f 100644 --- a/test/cases/cast.zig +++ b/test/cases/cast.zig @@ -462,3 +462,11 @@ test "implicit cast comptime numbers to any type when the value fits" { var b: u8 = a; assert(b == 255); } + +test "@intToEnum passed a comptime_int to an enum with one item" { + const E = enum { + A, + }; + const x = @intToEnum(E, 0); + assert(x == E.A); +} -- cgit v1.2.3 From 2f5d1ec5006ccae81f6de80233fa7800237779e2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 19 Nov 2018 11:22:57 -0500 Subject: improve error message when wrong type returned closes #1650 --- src/ir.cpp | 8 +++++++- test/compile_errors.zig | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ir.cpp b/src/ir.cpp index 55f17b811d..03389a2320 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -34,6 +34,7 @@ struct IrAnalyze { size_t old_bb_index; size_t instruction_index; ZigType *explicit_return_type; + AstNode *explicit_return_type_source_node; ZigList src_implicit_return_type_list; IrBasicBlock *const_predecessor_bb; }; @@ -11162,8 +11163,12 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio return ir_unreach_error(ira); IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->explicit_return_type); - if (type_is_invalid(casted_value->value.type)) + if (type_is_invalid(casted_value->value.type) && ira->explicit_return_type_source_node != nullptr) { + ErrorMsg *msg = ira->codegen->errors.last(); + add_error_note(ira->codegen, msg, ira->explicit_return_type_source_node, + buf_sprintf("return type declared here")); return ir_unreach_error(ira); + } if (casted_value->value.special == ConstValSpecialRuntime && casted_value->value.type->id == ZigTypeIdPointer && @@ -21213,6 +21218,7 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_ ZigFn *fn_entry = exec_fn_entry(old_exec); bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; ira->explicit_return_type = is_async ? get_promise_type(codegen, expected_type) : expected_type; + ira->explicit_return_type_source_node = expected_type_source_node; ira->old_irb.codegen = codegen; ira->old_irb.exec = old_exec; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 45bd6cb40b..16690daf29 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -3219,6 +3219,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\fn something() anyerror!void { } , ".tmp_source.zig:2:5: error: expected type 'void', found 'anyerror'", + ".tmp_source.zig:1:15: note: return type declared here", ); cases.add( -- cgit v1.2.3 From 89e82281be73701f5a634770366e9dca5a0e89a9 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 19 Nov 2018 13:26:35 -0500 Subject: fix incorrect --help text --- src/main.cpp | 9 +-------- std/special/build_runner.zig | 1 - 2 files changed, 1 insertion(+), 9 deletions(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 84ff2fb4b2..078dfb25f9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -466,16 +466,9 @@ int main(int argc, char **argv) { "\n" "General Options:\n" " --help Print this help and exit\n" - " --build-file [file] Override path to build.zig\n" - " --cache-dir [path] Override path to cache directory\n" " --verbose Print commands before executing them\n" - " --verbose-tokenize Enable compiler debug output for tokenization\n" - " --verbose-ast Enable compiler debug output for parsing into an AST\n" - " --verbose-link Enable compiler debug output for linking\n" - " --verbose-ir Enable compiler debug output for Zig IR\n" - " --verbose-llvm-ir Enable compiler debug output for LLVM IR\n" - " --verbose-cimport Enable compiler debug output for C imports\n" " --prefix [path] Override default install prefix\n" + " --search-prefix [path] Add a path to look for binaries, libraries, headers\n" "\n" "Project-specific options become available when the build file is found.\n" "\n" diff --git a/std/special/build_runner.zig b/std/special/build_runner.zig index 15e3534380..ff3b53619d 100644 --- a/std/special/build_runner.zig +++ b/std/special/build_runner.zig @@ -164,7 +164,6 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void { \\ \\General Options: \\ --help Print this help and exit - \\ --init Generate a build.zig template \\ --verbose Print commands before executing them \\ --prefix [path] Override default install prefix \\ --search-prefix [path] Add a path to look for binaries, libraries, headers -- cgit v1.2.3 From 703c6684d103f14193411b589eaa0e0b1e1189f0 Mon Sep 17 00:00:00 2001 From: Sahnvour Date: Mon, 19 Nov 2018 22:22:21 +0100 Subject: Crash fixes and small improvements to inline asm. (#1756) * codegen: LLVMConstInlineAsm is deprecated. * codegen: replace commas in asm constraint strings by pipes as required by LLVM. * ir: enforce usage of '=' constraint modifier for inline assembly outputs. Others are not currently supported and this was just asserted alter in `ir_render_asm`. * asm: forbid comptime_int/floats as inputs in favor of explicitely sized constants. Fixes a crash due to comptime_int/floats having no type_ref. * asm: handle inputs with integers of <8 or non power of 2 bitsize. We widen them to the next highest power of two. --- src/buffer.hpp | 10 ++++++++++ src/codegen.cpp | 31 +++++++++++++++++++++++++++---- src/ir.cpp | 23 +++++++++++++++++++++-- src/util.hpp | 11 +++++++++++ test/cases/asm.zig | 24 ++++++++++++++++++++++++ test/compile_errors.zig | 28 ++++++++++++++++++++++++++++ 6 files changed, 121 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/buffer.hpp b/src/buffer.hpp index 8155df87a1..afe9fd8a91 100644 --- a/src/buffer.hpp +++ b/src/buffer.hpp @@ -181,5 +181,15 @@ static inline Slice buf_to_slice(Buf *buf) { return Slice{reinterpret_cast(buf_ptr(buf)), buf_len(buf)}; } +static inline void buf_replace(Buf* buf, char from, char to) { + const size_t count = buf_len(buf); + char* ptr = buf_ptr(buf); + for (size_t i = 0; i < count; ++i) { + char& l = ptr[i]; + if (l == from) + l = to; + } +} + #endif diff --git a/src/codegen.cpp b/src/codegen.cpp index bd9063d020..40f71e38fe 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3660,6 +3660,13 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru AsmOutput *asm_output = asm_expr->output_list.at(i); bool is_return = (asm_output->return_type != nullptr); assert(*buf_ptr(asm_output->constraint) == '='); + // LLVM uses commas internally to separate different constraints, + // alternative constraints are achieved with pipes. + // We still allow the user to use commas in a way that is similar + // to GCC's inline assembly. + // http://llvm.org/docs/LangRef.html#constraint-codes + buf_replace(asm_output->constraint, ',', '|'); + if (is_return) { buf_appendf(&constraint_buf, "=%s", buf_ptr(asm_output->constraint) + 1); } else { @@ -3679,14 +3686,30 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru } for (size_t i = 0; i < asm_expr->input_list.length; i += 1, total_index += 1, param_index += 1) { AsmInput *asm_input = asm_expr->input_list.at(i); + buf_replace(asm_input->constraint, ',', '|'); IrInstruction *ir_input = instruction->input_list[i]; buf_append_buf(&constraint_buf, asm_input->constraint); if (total_index + 1 < total_constraint_count) { buf_append_char(&constraint_buf, ','); } - param_types[param_index] = ir_input->value.type->type_ref; - param_values[param_index] = ir_llvm_value(g, ir_input); + ZigType *const type = ir_input->value.type; + LLVMTypeRef type_ref = type->type_ref; + LLVMValueRef value_ref = ir_llvm_value(g, ir_input); + // Handle integers of non pot bitsize by widening them. + if (type->id == ZigTypeIdInt) { + const size_t bitsize = type->data.integral.bit_count; + if (bitsize < 8 || !is_power_of_2(bitsize)) { + const bool is_signed = type->data.integral.is_signed; + const size_t wider_bitsize = bitsize < 8 ? 8 : round_to_next_power_of_2(bitsize); + ZigType *const wider_type = get_int_type(g, is_signed, wider_bitsize); + type_ref = wider_type->type_ref; + value_ref = gen_widen_or_shorten(g, false, type, wider_type, value_ref); + } + } + + param_types[param_index] = type_ref; + param_values[param_index] = value_ref; } for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1, total_index += 1) { Buf *clobber_buf = asm_expr->clobber_list.at(i); @@ -3705,8 +3728,8 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, (unsigned)input_and_output_count, false); bool is_volatile = asm_expr->is_volatile || (asm_expr->output_list.length == 0); - LLVMValueRef asm_fn = LLVMConstInlineAsm(function_type, buf_ptr(&llvm_template), - buf_ptr(&constraint_buf), is_volatile, false); + LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(&llvm_template), buf_len(&llvm_template), + buf_ptr(&constraint_buf), buf_len(&constraint_buf), is_volatile, false, LLVMInlineAsmDialectATT); return LLVMBuildCall(g->builder, asm_fn, param_values, (unsigned)input_and_output_count, ""); } diff --git a/src/ir.cpp b/src/ir.cpp index 03389a2320..a62da827bc 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -5537,6 +5537,15 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod return irb->codegen->invalid_instruction; } } + + const char modifier = *buf_ptr(asm_output->constraint); + if (modifier != '=') { + add_node_error(irb->codegen, node, + buf_sprintf("invalid modifier starting output constraint for '%s': '%c', only '=' is supported." + " Compiler TODO: see https://github.com/ziglang/zig/issues/215", + buf_ptr(asm_output->asm_symbolic_name), modifier)); + return irb->codegen->invalid_instruction; + } } for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1) { AsmInput *asm_input = node->data.asm_expr.input_list.at(i); @@ -15386,9 +15395,19 @@ static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAs } for (size_t i = 0; i < asm_expr->input_list.length; i += 1) { - input_list[i] = asm_instruction->input_list[i]->child; - if (type_is_invalid(input_list[i]->value.type)) + IrInstruction *const input_value = asm_instruction->input_list[i]->child; + if (type_is_invalid(input_value->value.type)) return ira->codegen->invalid_instruction; + + if (instr_is_comptime(input_value) && + (input_value->value.type->id == ZigTypeIdComptimeInt || + input_value->value.type->id == ZigTypeIdComptimeFloat)) { + ir_add_error_node(ira, input_value->source_node, + buf_sprintf("expected sized integer or sized float, found %s", buf_ptr(&input_value->value.type->name))); + return ira->codegen->invalid_instruction; + } + + input_list[i] = input_value; } IrInstruction *result = ir_build_asm(&ira->new_irb, diff --git a/src/util.hpp b/src/util.hpp index a78231324f..cc83022328 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -158,6 +158,17 @@ static inline bool is_power_of_2(uint64_t x) { return x != 0 && ((x & (~x + 1)) == x); } +static inline uint64_t round_to_next_power_of_2(uint64_t x) { + --x; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x |= x >> 32; + return x + 1; +} + uint32_t int_hash(int i); bool int_eq(int a, int b); uint32_t uint64_hash(uint64_t i); diff --git a/test/cases/asm.zig b/test/cases/asm.zig index 1c4208f403..63e37c857c 100644 --- a/test/cases/asm.zig +++ b/test/cases/asm.zig @@ -17,6 +17,30 @@ test "module level assembly" { } } +test "output constraint modifiers" { + // This is only testing compilation. + var a: u32 = 3; + asm volatile ("" : [_]"=m,r"(a) : : ""); + asm volatile ("" : [_]"=r,m"(a) : : ""); +} + +test "alternative constraints" { + // Make sure we allow commas as a separator for alternative constraints. + var a: u32 = 3; + asm volatile ("" : [_]"=r,m"(a) : [_]"r,m"(a) : ""); +} + +test "sized integer/float in asm input" { + asm volatile ("" : : [_]"m"(usize(3)) : ""); + asm volatile ("" : : [_]"m"(i15(-3)) : ""); + asm volatile ("" : : [_]"m"(u3(3)) : ""); + asm volatile ("" : : [_]"m"(i3(3)) : ""); + asm volatile ("" : : [_]"m"(u121(3)) : ""); + asm volatile ("" : : [_]"m"(i121(3)) : ""); + asm volatile ("" : : [_]"m"(f32(3.17)) : ""); + asm volatile ("" : : [_]"m"(f64(3.17)) : ""); +} + extern fn aoeu() i32; export fn derp() i32 { diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 16690daf29..c5575a0c0b 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -5232,4 +5232,32 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { , ".tmp_source.zig:3:36: error: @ArgType could not resolve the type of arg 0 because 'fn(var)var' is generic", ); + + cases.add( + "unsupported modifier at start of asm output constraint", + \\export fn foo() void { + \\ var bar: u32 = 3; + \\ asm volatile ("" : [baz]"+r"(bar) : : ""); + \\} + , + ".tmp_source.zig:3:5: error: invalid modifier starting output constraint for 'baz': '+', only '=' is supported. Compiler TODO: see https://github.com/ziglang/zig/issues/215", + ); + + cases.add( + "comptime_int in asm input", + \\export fn foo() void { + \\ asm volatile ("" : : [bar]"r"(3) : ""); + \\} + , + ".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_int", + ); + + cases.add( + "comptime_float in asm input", + \\export fn foo() void { + \\ asm volatile ("" : : [bar]"r"(3.17) : ""); + \\} + , + ".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_float", + ); } -- cgit v1.2.3 From 56a8f2b018a6ee1f1116a64d34803511a6fbad80 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 24 Nov 2018 14:36:16 -0500 Subject: fix @intCast not catching negative numbers to unsigned --- src/codegen.cpp | 2 +- std/os/linux/index.zig | 103 ++++++++++++++++++++++++++---------------------- test/runtime_safety.zig | 10 +++++ 3 files changed, 67 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/codegen.cpp b/src/codegen.cpp index 40f71e38fe..096552037d 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1645,7 +1645,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z zig_unreachable(); } - if (actual_bits >= wanted_bits && actual_type->id == ZigTypeIdInt && + if (actual_type->id == ZigTypeIdInt && !wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed && want_runtime_safety) { diff --git a/std/os/linux/index.zig b/std/os/linux/index.zig index bfa046ba0f..ec90755164 100644 --- a/std/os/linux/index.zig +++ b/std/os/linux/index.zig @@ -703,7 +703,7 @@ pub fn dup2(old: i32, new: i32) usize { } pub fn dup3(old: i32, new: i32, flags: u32) usize { - return syscall3(SYS_dup3, @intCast(usize, old), @intCast(usize, new), flags); + return syscall3(SYS_dup3, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)), flags); } // TODO https://github.com/ziglang/zig/issues/265 @@ -747,7 +747,7 @@ pub fn getcwd(buf: [*]u8, size: usize) usize { } pub fn getdents64(fd: i32, dirp: [*]u8, count: usize) usize { - return syscall3(SYS_getdents64, @intCast(usize, fd), @ptrToInt(dirp), count); + return syscall3(SYS_getdents64, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count); } pub fn inotify_init1(flags: u32) usize { @@ -755,16 +755,16 @@ pub fn inotify_init1(flags: u32) usize { } pub fn inotify_add_watch(fd: i32, pathname: [*]const u8, mask: u32) usize { - return syscall3(SYS_inotify_add_watch, @intCast(usize, fd), @ptrToInt(pathname), mask); + return syscall3(SYS_inotify_add_watch, @bitCast(usize, isize(fd)), @ptrToInt(pathname), mask); } pub fn inotify_rm_watch(fd: i32, wd: i32) usize { - return syscall2(SYS_inotify_rm_watch, @intCast(usize, fd), @intCast(usize, wd)); + return syscall2(SYS_inotify_rm_watch, @bitCast(usize, isize(fd)), @bitCast(usize, isize(wd))); } pub fn isatty(fd: i32) bool { var wsz: winsize = undefined; - return syscall3(SYS_ioctl, @intCast(usize, fd), TIOCGWINSZ, @ptrToInt(&wsz)) == 0; + return syscall3(SYS_ioctl, @bitCast(usize, isize(fd)), TIOCGWINSZ, @ptrToInt(&wsz)) == 0; } // TODO https://github.com/ziglang/zig/issues/265 @@ -774,7 +774,7 @@ pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usiz // TODO https://github.com/ziglang/zig/issues/265 pub fn readlinkat(dirfd: i32, noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize { - return syscall4(SYS_readlinkat, @intCast(usize, dirfd), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len); + return syscall4(SYS_readlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len); } // TODO https://github.com/ziglang/zig/issues/265 @@ -784,7 +784,7 @@ pub fn mkdir(path: [*]const u8, mode: u32) usize { // TODO https://github.com/ziglang/zig/issues/265 pub fn mkdirat(dirfd: i32, path: [*]const u8, mode: u32) usize { - return syscall3(SYS_mkdirat, @intCast(usize, dirfd), @ptrToInt(path), mode); + return syscall3(SYS_mkdirat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode); } // TODO https://github.com/ziglang/zig/issues/265 @@ -803,7 +803,7 @@ pub fn umount2(special: [*]const u8, flags: u32) usize { } pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize { - return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @intCast(usize, fd), @bitCast(usize, offset)); + return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @bitCast(usize, isize(fd)), @bitCast(usize, offset)); } pub fn munmap(address: usize, length: usize) usize { @@ -811,23 +811,23 @@ pub fn munmap(address: usize, length: usize) usize { } pub fn read(fd: i32, buf: [*]u8, count: usize) usize { - return syscall3(SYS_read, @intCast(usize, fd), @ptrToInt(buf), count); + return syscall3(SYS_read, @bitCast(usize, isize(fd)), @ptrToInt(buf), count); } pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize { - return syscall4(SYS_preadv, @intCast(usize, fd), @ptrToInt(iov), count, offset); + return syscall4(SYS_preadv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset); } pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize { - return syscall3(SYS_readv, @intCast(usize, fd), @ptrToInt(iov), count); + return syscall3(SYS_readv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count); } pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize { - return syscall3(SYS_writev, @intCast(usize, fd), @ptrToInt(iov), count); + return syscall3(SYS_writev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count); } pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) usize { - return syscall4(SYS_pwritev, @intCast(usize, fd), @ptrToInt(iov), count, offset); + return syscall4(SYS_pwritev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset); } // TODO https://github.com/ziglang/zig/issues/265 @@ -842,12 +842,12 @@ pub fn symlink(existing: [*]const u8, new: [*]const u8) usize { // TODO https://github.com/ziglang/zig/issues/265 pub fn symlinkat(existing: [*]const u8, newfd: i32, newpath: [*]const u8) usize { - return syscall3(SYS_symlinkat, @ptrToInt(existing), @intCast(usize, newfd), @ptrToInt(newpath)); + return syscall3(SYS_symlinkat, @ptrToInt(existing), @bitCast(usize, isize(newfd)), @ptrToInt(newpath)); } // TODO https://github.com/ziglang/zig/issues/265 pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize { - return syscall4(SYS_pread, @intCast(usize, fd), @ptrToInt(buf), count, offset); + return syscall4(SYS_pread, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset); } // TODO https://github.com/ziglang/zig/issues/265 @@ -856,7 +856,7 @@ pub fn access(path: [*]const u8, mode: u32) usize { } pub fn faccessat(dirfd: i32, path: [*]const u8, mode: u32) usize { - return syscall3(SYS_faccessat, @intCast(usize, dirfd), @ptrToInt(path), mode); + return syscall3(SYS_faccessat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode); } pub fn pipe(fd: *[2]i32) usize { @@ -868,11 +868,11 @@ pub fn pipe2(fd: *[2]i32, flags: u32) usize { } pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { - return syscall3(SYS_write, @intCast(usize, fd), @ptrToInt(buf), count); + return syscall3(SYS_write, @bitCast(usize, isize(fd)), @ptrToInt(buf), count); } pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize { - return syscall4(SYS_pwrite, @intCast(usize, fd), @ptrToInt(buf), count, offset); + return syscall4(SYS_pwrite, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset); } // TODO https://github.com/ziglang/zig/issues/265 @@ -882,7 +882,7 @@ pub fn rename(old: [*]const u8, new: [*]const u8) usize { // TODO https://github.com/ziglang/zig/issues/265 pub fn renameat2(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const u8, flags: u32) usize { - return syscall5(SYS_renameat2, @intCast(usize, oldfd), @ptrToInt(oldpath), @intCast(usize, newfd), @ptrToInt(newpath), flags); + return syscall5(SYS_renameat2, @bitCast(usize, isize(oldfd)), @ptrToInt(oldpath), @bitCast(usize, isize(newfd)), @ptrToInt(newpath), flags); } // TODO https://github.com/ziglang/zig/issues/265 @@ -897,7 +897,8 @@ pub fn create(path: [*]const u8, perm: usize) usize { // TODO https://github.com/ziglang/zig/issues/265 pub fn openat(dirfd: i32, path: [*]const u8, flags: u32, mode: usize) usize { - return syscall4(SYS_openat, @intCast(usize, dirfd), @ptrToInt(path), flags, mode); + // dirfd could be negative, for example AT_FDCWD is -100 + return syscall4(SYS_openat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags, mode); } /// See also `clone` (from the arch-specific include) @@ -911,11 +912,11 @@ pub fn clone2(flags: u32, child_stack_ptr: usize) usize { } pub fn close(fd: i32) usize { - return syscall1(SYS_close, @intCast(usize, fd)); + return syscall1(SYS_close, @bitCast(usize, isize(fd))); } pub fn lseek(fd: i32, offset: isize, ref_pos: usize) usize { - return syscall3(SYS_lseek, @intCast(usize, fd), @bitCast(usize, offset), ref_pos); + return syscall3(SYS_lseek, @bitCast(usize, isize(fd)), @bitCast(usize, offset), ref_pos); } pub fn exit(status: i32) noreturn { @@ -933,7 +934,7 @@ pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize { } pub fn kill(pid: i32, sig: i32) usize { - return syscall2(SYS_kill, @bitCast(usize, isize(pid)), @intCast(usize, sig)); + return syscall2(SYS_kill, @bitCast(usize, isize(pid)), @bitCast(usize, isize(sig))); } // TODO https://github.com/ziglang/zig/issues/265 @@ -943,7 +944,7 @@ pub fn unlink(path: [*]const u8) usize { // TODO https://github.com/ziglang/zig/issues/265 pub fn unlinkat(dirfd: i32, path: [*]const u8, flags: u32) usize { - return syscall3(SYS_unlinkat, @intCast(usize, dirfd), @ptrToInt(path), flags); + return syscall3(SYS_unlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags); } pub fn waitpid(pid: i32, status: *i32, options: i32) usize { @@ -1120,8 +1121,8 @@ pub const empty_sigset = []usize{0} ** sigset_t.len; pub fn raise(sig: i32) usize { var set: sigset_t = undefined; blockAppSignals(&set); - const tid = @intCast(i32, syscall0(SYS_gettid)); - const ret = syscall2(SYS_tkill, @intCast(usize, tid), @intCast(usize, sig)); + const tid = syscall0(SYS_gettid); + const ret = syscall2(SYS_tkill, tid, @bitCast(usize, isize(sig))); restoreSignals(&set); return ret; } @@ -1189,11 +1190,11 @@ pub const iovec_const = extern struct { }; pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { - return syscall3(SYS_getsockname, @intCast(usize, fd), @ptrToInt(addr), @ptrToInt(len)); + return syscall3(SYS_getsockname, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len)); } pub fn getpeername(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { - return syscall3(SYS_getpeername, @intCast(usize, fd), @ptrToInt(addr), @ptrToInt(len)); + return syscall3(SYS_getpeername, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len)); } pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize { @@ -1201,47 +1202,47 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize { } pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: [*]const u8, optlen: socklen_t) usize { - return syscall5(SYS_setsockopt, @intCast(usize, fd), level, optname, @ptrToInt(optval), @intCast(usize, optlen)); + return syscall5(SYS_setsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @intCast(usize, optlen)); } pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noalias optlen: *socklen_t) usize { - return syscall5(SYS_getsockopt, @intCast(usize, fd), level, optname, @ptrToInt(optval), @ptrToInt(optlen)); + return syscall5(SYS_getsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen)); } pub fn sendmsg(fd: i32, msg: *const msghdr, flags: u32) usize { - return syscall3(SYS_sendmsg, @intCast(usize, fd), @ptrToInt(msg), flags); + return syscall3(SYS_sendmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags); } pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize { - return syscall3(SYS_connect, @intCast(usize, fd), @ptrToInt(addr), len); + return syscall3(SYS_connect, @bitCast(usize, isize(fd)), @ptrToInt(addr), len); } pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize { - return syscall3(SYS_recvmsg, @intCast(usize, fd), @ptrToInt(msg), flags); + return syscall3(SYS_recvmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags); } pub fn recvfrom(fd: i32, noalias buf: [*]u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t) usize { - return syscall6(SYS_recvfrom, @intCast(usize, fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen)); + return syscall6(SYS_recvfrom, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen)); } pub fn shutdown(fd: i32, how: i32) usize { - return syscall2(SYS_shutdown, @intCast(usize, fd), @intCast(usize, how)); + return syscall2(SYS_shutdown, @bitCast(usize, isize(fd)), @bitCast(usize, isize(how))); } pub fn bind(fd: i32, addr: *const sockaddr, len: socklen_t) usize { - return syscall3(SYS_bind, @intCast(usize, fd), @ptrToInt(addr), @intCast(usize, len)); + return syscall3(SYS_bind, @bitCast(usize, isize(fd)), @ptrToInt(addr), @intCast(usize, len)); } pub fn listen(fd: i32, backlog: u32) usize { - return syscall2(SYS_listen, @intCast(usize, fd), backlog); + return syscall2(SYS_listen, @bitCast(usize, isize(fd)), backlog); } pub fn sendto(fd: i32, buf: [*]const u8, len: usize, flags: u32, addr: ?*const sockaddr, alen: socklen_t) usize { - return syscall6(SYS_sendto, @intCast(usize, fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen)); + return syscall6(SYS_sendto, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen)); } pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) usize { - return syscall4(SYS_socketpair, @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(*fd[0])); + return syscall4(SYS_socketpair, @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(&fd[0])); } pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { @@ -1249,11 +1250,11 @@ pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { } pub fn accept4(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t, flags: u32) usize { - return syscall4(SYS_accept4, @intCast(usize, fd), @ptrToInt(addr), @ptrToInt(len), flags); + return syscall4(SYS_accept4, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len), flags); } pub fn fstat(fd: i32, stat_buf: *Stat) usize { - return syscall2(SYS_fstat, @intCast(usize, fd), @ptrToInt(stat_buf)); + return syscall2(SYS_fstat, @bitCast(usize, isize(fd)), @ptrToInt(stat_buf)); } // TODO https://github.com/ziglang/zig/issues/265 @@ -1268,7 +1269,7 @@ pub fn lstat(pathname: [*]const u8, statbuf: *Stat) usize { // TODO https://github.com/ziglang/zig/issues/265 pub fn fstatat(dirfd: i32, path: [*]const u8, stat_buf: *Stat, flags: u32) usize { - return syscall4(SYS_fstatat, @intCast(usize, dirfd), @ptrToInt(path), @ptrToInt(stat_buf), flags); + return syscall4(SYS_fstatat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags); } // TODO https://github.com/ziglang/zig/issues/265 @@ -1355,7 +1356,7 @@ pub fn epoll_create1(flags: usize) usize { } pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: *epoll_event) usize { - return syscall4(SYS_epoll_ctl, @intCast(usize, epoll_fd), @intCast(usize, op), @intCast(usize, fd), @ptrToInt(ev)); + return syscall4(SYS_epoll_ctl, @bitCast(usize, isize(epoll_fd)), @intCast(usize, op), @bitCast(usize, isize(fd)), @ptrToInt(ev)); } pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize { @@ -1363,7 +1364,15 @@ pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout } pub fn epoll_pwait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32, sigmask: ?*sigset_t) usize { - return syscall6(SYS_epoll_pwait, @intCast(usize, epoll_fd), @ptrToInt(events), @intCast(usize, maxevents), @intCast(usize, timeout), @ptrToInt(sigmask), @sizeOf(sigset_t)); + return syscall6( + SYS_epoll_pwait, + @bitCast(usize, isize(epoll_fd)), + @ptrToInt(events), + @intCast(usize, maxevents), + @bitCast(usize, isize(timeout)), + @ptrToInt(sigmask), + @sizeOf(sigset_t), + ); } pub fn eventfd(count: u32, flags: u32) usize { @@ -1371,7 +1380,7 @@ pub fn eventfd(count: u32, flags: u32) usize { } pub fn timerfd_create(clockid: i32, flags: u32) usize { - return syscall2(SYS_timerfd_create, @intCast(usize, clockid), flags); + return syscall2(SYS_timerfd_create, @bitCast(usize, isize(clockid)), flags); } pub const itimerspec = extern struct { @@ -1380,11 +1389,11 @@ pub const itimerspec = extern struct { }; pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize { - return syscall2(SYS_timerfd_gettime, @intCast(usize, fd), @ptrToInt(curr_value)); + return syscall2(SYS_timerfd_gettime, @bitCast(usize, isize(fd)), @ptrToInt(curr_value)); } pub fn timerfd_settime(fd: i32, flags: u32, new_value: *const itimerspec, old_value: ?*itimerspec) usize { - return syscall4(SYS_timerfd_settime, @intCast(usize, fd), flags, @ptrToInt(new_value), @ptrToInt(old_value)); + return syscall4(SYS_timerfd_settime, @bitCast(usize, isize(fd)), flags, @ptrToInt(new_value), @ptrToInt(old_value)); } pub const _LINUX_CAPABILITY_VERSION_1 = 0x19980330; diff --git a/test/runtime_safety.zig b/test/runtime_safety.zig index 343b3ff592..7c13f5b6fa 100644 --- a/test/runtime_safety.zig +++ b/test/runtime_safety.zig @@ -275,6 +275,16 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { \\} ); + cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer - widening", + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { + \\ @import("std").os.exit(126); + \\} + \\pub fn main() void { + \\ var value: c_short = -1; + \\ var casted = @intCast(u32, value); + \\} + ); + cases.addRuntimeSafety("unwrap error", \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) { -- cgit v1.2.3 From 3d2752cc3677535ddfbeeefba4036633bcab01dc Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 24 Nov 2018 16:15:58 -0500 Subject: refactor type_requires_comptime to have possible error fixes a compiler crash when building https://github.com/AndreaOrru/zen --- src/analyze.cpp | 85 ++++++++++++++++++++++++------------------- src/analyze.hpp | 8 ++++- src/codegen.cpp | 10 ++++-- src/ir.cpp | 110 +++++++++++++++++++++++++++++++++----------------------- 4 files changed, 129 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/analyze.cpp b/src/analyze.cpp index 349169f9d1..e5679a21d5 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1619,13 +1619,16 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc case ZigTypeIdUnion: case ZigTypeIdFn: case ZigTypeIdPromise: - if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) - return g->builtin_types.entry_invalid; - if (type_requires_comptime(type_entry)) { - add_node_error(g, param_node->data.param_decl.type, - buf_sprintf("parameter of type '%s' must be declared comptime", - buf_ptr(&type_entry->name))); - return g->builtin_types.entry_invalid; + switch (type_requires_comptime(g, type_entry)) { + case ReqCompTimeNo: + break; + case ReqCompTimeYes: + add_node_error(g, param_node->data.param_decl.type, + buf_sprintf("parameter of type '%s' must be declared comptime", + buf_ptr(&type_entry->name))); + return g->builtin_types.entry_invalid; + case ReqCompTimeInvalid: + return g->builtin_types.entry_invalid; } break; } @@ -1711,10 +1714,13 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc case ZigTypeIdUnion: case ZigTypeIdFn: case ZigTypeIdPromise: - if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusZeroBitsKnown))) - return g->builtin_types.entry_invalid; - if (type_requires_comptime(fn_type_id.return_type)) { - return get_generic_fn_type(g, &fn_type_id); + switch (type_requires_comptime(g, fn_type_id.return_type)) { + case ReqCompTimeInvalid: + return g->builtin_types.entry_invalid; + case ReqCompTimeYes: + return get_generic_fn_type(g, &fn_type_id); + case ReqCompTimeNo: + break; } break; } @@ -2560,8 +2566,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { assert(struct_type->id == ZigTypeIdStruct); - Error err; - if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) return ErrorSemanticAnalyzeFail; if (struct_type->data.structure.resolve_status >= ResolveStatusZeroBitsKnown) @@ -2619,13 +2623,15 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { buf_sprintf("enums, not structs, support field assignment")); } - if ((err = type_resolve(g, field_type, ResolveStatusZeroBitsKnown))) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - continue; - } - - if (type_requires_comptime(field_type)) { - struct_type->data.structure.requires_comptime = true; + switch (type_requires_comptime(g, field_type)) { + case ReqCompTimeYes: + struct_type->data.structure.requires_comptime = true; + break; + case ReqCompTimeInvalid: + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + continue; + case ReqCompTimeNo: + break; } if (!type_has_bits(field_type)) @@ -2890,11 +2896,17 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { } union_field->type_entry = field_type; - if (type_requires_comptime(field_type)) { - union_type->data.unionation.requires_comptime = true; + switch (type_requires_comptime(g, field_type)) { + case ReqCompTimeInvalid: + union_type->data.unionation.is_invalid = true; + continue; + case ReqCompTimeYes: + union_type->data.unionation.requires_comptime = true; + break; + case ReqCompTimeNo: + break; } - if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) { ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value, buf_sprintf("non-enum union field assignment")); @@ -5089,7 +5101,10 @@ bool type_has_bits(ZigType *type_entry) { return !type_entry->zero_bits; } -bool type_requires_comptime(ZigType *type_entry) { +ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) { + Error err; + if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) + return ReqCompTimeInvalid; switch (type_entry->id) { case ZigTypeIdInvalid: case ZigTypeIdOpaque: @@ -5102,27 +5117,25 @@ bool type_requires_comptime(ZigType *type_entry) { case ZigTypeIdNamespace: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: - return true; + return ReqCompTimeYes; case ZigTypeIdArray: - return type_requires_comptime(type_entry->data.array.child_type); + return type_requires_comptime(g, type_entry->data.array.child_type); case ZigTypeIdStruct: - assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown)); - return type_entry->data.structure.requires_comptime; + return type_entry->data.structure.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo; case ZigTypeIdUnion: - assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown)); - return type_entry->data.unionation.requires_comptime; + return type_entry->data.unionation.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo; case ZigTypeIdOptional: - return type_requires_comptime(type_entry->data.maybe.child_type); + return type_requires_comptime(g, type_entry->data.maybe.child_type); case ZigTypeIdErrorUnion: - return type_requires_comptime(type_entry->data.error_union.payload_type); + return type_requires_comptime(g, type_entry->data.error_union.payload_type); case ZigTypeIdPointer: if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) { - return false; + return ReqCompTimeNo; } else { - return type_requires_comptime(type_entry->data.pointer.child_type); + return type_requires_comptime(g, type_entry->data.pointer.child_type); } case ZigTypeIdFn: - return type_entry->data.fn.is_generic; + return type_entry->data.fn.is_generic ? ReqCompTimeYes : ReqCompTimeNo; case ZigTypeIdEnum: case ZigTypeIdErrorSet: case ZigTypeIdBool: @@ -5131,7 +5144,7 @@ bool type_requires_comptime(ZigType *type_entry) { case ZigTypeIdVoid: case ZigTypeIdUnreachable: case ZigTypeIdPromise: - return false; + return ReqCompTimeNo; } zig_unreachable(); } diff --git a/src/analyze.hpp b/src/analyze.hpp index e727b050ea..b506b533ca 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -87,7 +87,6 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node); ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value); void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc); AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index); -bool type_requires_comptime(ZigType *type_entry); Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry); Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status); void complete_enum(CodeGen *g, ZigType *enum_type); @@ -216,4 +215,11 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id); uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field); +enum ReqCompTime { + ReqCompTimeInvalid, + ReqCompTimeNo, + ReqCompTimeYes, +}; +ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry); + #endif diff --git a/src/codegen.cpp b/src/codegen.cpp index 096552037d..37e0424961 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6281,8 +6281,14 @@ static void do_code_gen(CodeGen *g) { } if (ir_get_var_is_comptime(var)) continue; - if (type_requires_comptime(var->value->type)) - continue; + switch (type_requires_comptime(g, var->value->type)) { + case ReqCompTimeInvalid: + zig_unreachable(); + case ReqCompTimeYes: + continue; + case ReqCompTimeNo: + break; + } if (var->src_arg_index == SIZE_MAX) { var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes); diff --git a/src/ir.cpp b/src/ir.cpp index a62da827bc..1edb122670 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -11276,7 +11276,6 @@ static bool optional_value_is_null(ConstExprValue *val) { } static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { - Error err; IrInstruction *op1 = bin_op_instruction->op1->child; if (type_is_invalid(op1->value.type)) return ira->codegen->invalid_instruction; @@ -11470,10 +11469,19 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * if (casted_op2 == ira->codegen->invalid_instruction) return ira->codegen->invalid_instruction; - if ((err = type_resolve(ira->codegen, resolved_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; + bool requires_comptime; + switch (type_requires_comptime(ira->codegen, resolved_type)) { + case ReqCompTimeYes: + requires_comptime = true; + break; + case ReqCompTimeNo: + requires_comptime = false; + break; + case ReqCompTimeInvalid: + return ira->codegen->invalid_instruction; + } - bool one_possible_value = !type_requires_comptime(resolved_type) && !type_has_bits(resolved_type); + bool one_possible_value = !requires_comptime && !type_has_bits(resolved_type); if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) { ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad); if (op1_val == nullptr) @@ -12406,42 +12414,41 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct ZigType *result_type = casted_init_value->value.type; if (type_is_invalid(result_type)) { result_type = ira->codegen->builtin_types.entry_invalid; - } else { - if ((err = type_resolve(ira->codegen, result_type, ResolveStatusZeroBitsKnown))) { - result_type = ira->codegen->builtin_types.entry_invalid; - } + } else if (result_type->id == ZigTypeIdUnreachable || result_type->id == ZigTypeIdOpaque) { + ir_add_error_node(ira, source_node, + buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name))); + result_type = ira->codegen->builtin_types.entry_invalid; } - if (!type_is_invalid(result_type)) { - if (result_type->id == ZigTypeIdUnreachable || - result_type->id == ZigTypeIdOpaque) - { + switch (type_requires_comptime(ira->codegen, result_type)) { + case ReqCompTimeInvalid: + result_type = ira->codegen->builtin_types.entry_invalid; + break; + case ReqCompTimeYes: { + var_class_requires_const = true; + if (!var->gen_is_const && !is_comptime_var) { ir_add_error_node(ira, source_node, - buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name))); + buf_sprintf("variable of type '%s' must be const or comptime", + buf_ptr(&result_type->name))); result_type = ira->codegen->builtin_types.entry_invalid; - } else if (type_requires_comptime(result_type)) { + } + break; + } + case ReqCompTimeNo: + if (casted_init_value->value.special == ConstValSpecialStatic && + casted_init_value->value.type->id == ZigTypeIdFn && + casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways) + { var_class_requires_const = true; - if (!var->gen_is_const && !is_comptime_var) { - ir_add_error_node(ira, source_node, - buf_sprintf("variable of type '%s' must be const or comptime", - buf_ptr(&result_type->name))); + if (!var->src_is_const && !is_comptime_var) { + ErrorMsg *msg = ir_add_error_node(ira, source_node, + buf_sprintf("functions marked inline must be stored in const or comptime var")); + AstNode *proto_node = casted_init_value->value.data.x_ptr.data.fn.fn_entry->proto_node; + add_error_note(ira->codegen, msg, proto_node, buf_sprintf("declared here")); result_type = ira->codegen->builtin_types.entry_invalid; } - } else { - if (casted_init_value->value.special == ConstValSpecialStatic && - casted_init_value->value.type->id == ZigTypeIdFn && - casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways) - { - var_class_requires_const = true; - if (!var->src_is_const && !is_comptime_var) { - ErrorMsg *msg = ir_add_error_node(ira, source_node, - buf_sprintf("functions marked inline must be stored in const or comptime var")); - AstNode *proto_node = casted_init_value->value.data.x_ptr.data.fn.fn_entry->proto_node; - add_error_note(ira->codegen, msg, proto_node, buf_sprintf("declared here")); - result_type = ira->codegen->builtin_types.entry_invalid; - } - } } + break; } if (var->value->type != nullptr && !is_comptime_var) { @@ -12912,10 +12919,15 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod } if (!comptime_arg) { - if (type_requires_comptime(casted_arg->value.type)) { + switch (type_requires_comptime(ira->codegen, casted_arg->value.type)) { + case ReqCompTimeYes: ir_add_error(ira, casted_arg, buf_sprintf("parameter of type '%s' requires comptime", buf_ptr(&casted_arg->value.type->name))); return false; + case ReqCompTimeInvalid: + return false; + case ReqCompTimeNo: + break; } casted_args[fn_type_id->param_count] = casted_arg; @@ -13388,12 +13400,15 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call inst_fn_type_id.return_type = specified_return_type; } - if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; - - if (type_requires_comptime(specified_return_type)) { + switch (type_requires_comptime(ira->codegen, specified_return_type)) { + case ReqCompTimeYes: // Throw out our work and call the function as if it were comptime. - return ir_analyze_fn_call(ira, call_instruction, fn_entry, fn_type, fn_ref, first_arg_ptr, true, FnInlineAuto); + return ir_analyze_fn_call(ira, call_instruction, fn_entry, fn_type, fn_ref, first_arg_ptr, + true, FnInlineAuto); + case ReqCompTimeInvalid: + return ira->codegen->invalid_instruction; + case ReqCompTimeNo: + break; } } IrInstruction *async_allocator_inst = nullptr; @@ -14334,11 +14349,16 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct } else { // runtime known element index - if (type_requires_comptime(return_type)) { + switch (type_requires_comptime(ira->codegen, return_type)) { + case ReqCompTimeYes: ir_add_error(ira, elem_index, buf_sprintf("values of type '%s' must be comptime known, but index value is runtime known", buf_ptr(&return_type->data.pointer.child_type->name))); return ira->codegen->invalid_instruction; + case ReqCompTimeInvalid: + return ira->codegen->invalid_instruction; + case ReqCompTimeNo: + break; } if (ptr_align < abi_align) { if (elem_size >= ptr_align && elem_size % ptr_align == 0) { @@ -19390,7 +19410,6 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, } static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) { - Error err; AstNode *proto_node = instruction->base.source_node; assert(proto_node->type == NodeTypeFnProto); @@ -19429,11 +19448,8 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct if (type_is_invalid(param_type_value->value.type)) return ira->codegen->invalid_instruction; ZigType *param_type = ir_resolve_type(ira, param_type_value); - if (type_is_invalid(param_type)) - return ira->codegen->invalid_instruction; - if ((err = type_resolve(ira->codegen, param_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; - if (type_requires_comptime(param_type)) { + switch (type_requires_comptime(ira->codegen, param_type)) { + case ReqCompTimeYes: if (!calling_convention_allows_zig_types(fn_type_id.cc)) { ir_add_error(ira, param_type_value, buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'", @@ -19443,6 +19459,10 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct param_info->type = param_type; fn_type_id.next_param_index += 1; return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id)); + case ReqCompTimeInvalid: + return ira->codegen->invalid_instruction; + case ReqCompTimeNo: + break; } if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) { ir_add_error(ira, param_type_value, -- cgit v1.2.3 From 67a39a4c99106714588676db0168fef52e0ecd9c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 26 Nov 2018 20:04:35 -0500 Subject: stage1: better file path handling * better message printed when cache hash fails * better handling of '/' as root source file * os_path_split parses '/' and '/a' correctly closes #1693 closes #1746 --- src/cache_hash.cpp | 6 ++++-- src/codegen.cpp | 11 ++++++++++- src/error.cpp | 1 + src/error.hpp | 1 + src/os.cpp | 10 ++++++++-- 5 files changed, 24 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/cache_hash.cpp b/src/cache_hash.cpp index 7a3c08bc27..5e6c3b9a9d 100644 --- a/src/cache_hash.cpp +++ b/src/cache_hash.cpp @@ -352,8 +352,9 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { // if the mtime matches we can trust the digest OsFile this_file; if ((err = os_file_open_r(chf->path, &this_file))) { + fprintf(stderr, "Unable to open %s\n: %s", buf_ptr(chf->path), err_str(err)); os_file_close(ch->manifest_file); - return err; + return ErrorCacheUnavailable; } OsTimeStamp actual_mtime; if ((err = os_file_mtime(this_file, &actual_mtime))) { @@ -392,8 +393,9 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { for (; file_i < input_file_count; file_i += 1) { CacheHashFile *chf = &ch->files.at(file_i); if ((err = populate_file_hash(ch, chf, nullptr))) { + fprintf(stderr, "Unable to hash %s: %s\n", buf_ptr(chf->path), err_str(err)); os_file_close(ch->manifest_file); - return err; + return ErrorCacheUnavailable; } } return ErrorNone; diff --git a/src/codegen.cpp b/src/codegen.cpp index 37e0424961..1033ed8120 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -129,6 +129,11 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out Buf *src_dir = buf_alloc(); os_path_split(root_src_path, src_dir, src_basename); + if (buf_len(src_basename) == 0) { + fprintf(stderr, "Invalid root source path: %s\n", buf_ptr(root_src_path)); + exit(1); + } + g->root_package = new_package(buf_ptr(src_dir), buf_ptr(src_basename)); g->std_package = new_package(buf_ptr(g->zig_std_dir), "index.zig"); g->root_package->package_table.put(buf_create_from_str("std"), g->std_package); @@ -8178,7 +8183,11 @@ void codegen_build_and_link(CodeGen *g) { os_path_join(stage1_dir, buf_create_from_str("build"), manifest_dir); if ((err = check_cache(g, manifest_dir, &digest))) { - fprintf(stderr, "Unable to check cache: %s\n", err_str(err)); + if (err == ErrorCacheUnavailable) { + // message already printed + } else { + fprintf(stderr, "Unable to check cache: %s\n", err_str(err)); + } exit(1); } diff --git a/src/error.cpp b/src/error.cpp index d0575a8494..10186fbde5 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -33,6 +33,7 @@ const char *err_str(Error err) { case ErrorSharingViolation: return "sharing violation"; case ErrorPipeBusy: return "pipe busy"; case ErrorPrimitiveTypeNotFound: return "primitive type not found"; + case ErrorCacheUnavailable: return "cache unavailable"; } return "(invalid error)"; } diff --git a/src/error.hpp b/src/error.hpp index 8b8fa5ce17..b60cb8517e 100644 --- a/src/error.hpp +++ b/src/error.hpp @@ -35,6 +35,7 @@ enum Error { ErrorSharingViolation, ErrorPipeBusy, ErrorPrimitiveTypeNotFound, + ErrorCacheUnavailable, }; const char *err_str(Error err); diff --git a/src/os.cpp b/src/os.cpp index 9d16d763ec..f739ee44e7 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -188,14 +188,20 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename) { size_t len = buf_len(full_path); if (len != 0) { size_t last_index = len - 1; - if (os_is_sep(buf_ptr(full_path)[last_index])) { + char last_char = buf_ptr(full_path)[last_index]; + if (os_is_sep(last_char)) { + if (last_index == 0) { + if (out_dirname) buf_init_from_mem(out_dirname, &last_char, 1); + if (out_basename) buf_init_from_str(out_basename, ""); + return; + } last_index -= 1; } for (size_t i = last_index;;) { uint8_t c = buf_ptr(full_path)[i]; if (os_is_sep(c)) { if (out_dirname) { - buf_init_from_mem(out_dirname, buf_ptr(full_path), i); + buf_init_from_mem(out_dirname, buf_ptr(full_path), (i == 0) ? 1 : i); } if (out_basename) { buf_init_from_mem(out_basename, buf_ptr(full_path) + i + 1, buf_len(full_path) - (i + 1)); -- cgit v1.2.3 From dd2450b1b21809c3fe62920498c318fbe519f579 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 27 Nov 2018 20:56:43 -0500 Subject: tier 2 support for freebsd --- README.md | 2 +- cmake/Findlld.cmake | 10 +- src-self-hosted/target.zig | 292 +++++++++++++++++++++++---------------------- src/util.cpp | 2 +- std/os/index.zig | 4 +- 5 files changed, 156 insertions(+), 154 deletions(-) (limited to 'src') diff --git a/README.md b/README.md index e50d31856d..a19e9eb67a 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ clarity. | | freestanding | linux | macosx | windows | freebsd | other | |--------|--------------|--------|--------|---------|---------|--------| -|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 3 | Tier 3 | +|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 3 | |i386 | Tier 2 | Tier 2 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | |arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | |arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | diff --git a/cmake/Findlld.cmake b/cmake/Findlld.cmake index 4e5b0c9a19..93ed1a9de1 100644 --- a/cmake/Findlld.cmake +++ b/cmake/Findlld.cmake @@ -8,13 +8,13 @@ find_path(LLD_INCLUDE_DIRS NAMES lld/Common/Driver.h PATHS - /usr/lib/llvm-6.0/include - /usr/local/llvm60/include + /usr/lib/llvm-7.0/include + /usr/local/llvm70/include /mingw64/include) -find_library(LLD_LIBRARY NAMES lld-6.0 lld60 lld +find_library(LLD_LIBRARY NAMES lld-7.0 lld70 lld PATHS - /usr/lib/llvm-6.0/lib + /usr/lib/llvm-7.0/lib /usr/local/llvm70/lib) if(EXISTS ${LLD_LIBRARY}) set(LLD_LIBRARIES ${LLD_LIBRARY}) @@ -23,7 +23,7 @@ else() string(TOUPPER ${_libname_} _prettylibname_) find_library(LLD_${_prettylibname_}_LIB NAMES ${_libname_} PATHS - /usr/lib/llvm-6.0/lib + /usr/lib/llvm-7.0/lib /usr/local/llvm70/lib /mingw64/lib /c/msys64/mingw64/lib diff --git a/src-self-hosted/target.zig b/src-self-hosted/target.zig index eae0a12325..218353c9d7 100644 --- a/src-self-hosted/target.zig +++ b/src-self-hosted/target.zig @@ -304,154 +304,156 @@ pub const Target = union(enum) { builtin.Os.freebsd => { return "/libexec/ld-elf.so.1"; }, - else => {}, - } - switch (env) { - builtin.Environ.android => { - if (self.is64bit()) { - return "/system/bin/linker64"; - } else { - return "/system/bin/linker"; + builtin.Os.linux => { + switch (env) { + builtin.Environ.android => { + if (self.is64bit()) { + return "/system/bin/linker64"; + } else { + return "/system/bin/linker"; + } + }, + builtin.Environ.gnux32 => { + if (arch == builtin.Arch.x86_64) { + return "/libx32/ld-linux-x32.so.2"; + } + }, + builtin.Environ.musl, + builtin.Environ.musleabi, + builtin.Environ.musleabihf, + => { + if (arch == builtin.Arch.x86_64) { + return "/lib/ld-musl-x86_64.so.1"; + } + }, + else => {}, } - }, - builtin.Environ.gnux32 => { - if (arch == builtin.Arch.x86_64) { - return "/libx32/ld-linux-x32.so.2"; + switch (arch) { + builtin.Arch.i386, + builtin.Arch.sparc, + builtin.Arch.sparcel, + => return "/lib/ld-linux.so.2", + + builtin.Arch.aarch64v8_3a, + builtin.Arch.aarch64v8_2a, + builtin.Arch.aarch64v8_1a, + builtin.Arch.aarch64v8, + builtin.Arch.aarch64v8r, + builtin.Arch.aarch64v8m_baseline, + builtin.Arch.aarch64v8m_mainline, + => return "/lib/ld-linux-aarch64.so.1", + + builtin.Arch.aarch64_bev8_3a, + builtin.Arch.aarch64_bev8_2a, + builtin.Arch.aarch64_bev8_1a, + builtin.Arch.aarch64_bev8, + builtin.Arch.aarch64_bev8r, + builtin.Arch.aarch64_bev8m_baseline, + builtin.Arch.aarch64_bev8m_mainline, + => return "/lib/ld-linux-aarch64_be.so.1", + + builtin.Arch.armv8_3a, + builtin.Arch.armv8_2a, + builtin.Arch.armv8_1a, + builtin.Arch.armv8, + builtin.Arch.armv8r, + builtin.Arch.armv8m_baseline, + builtin.Arch.armv8m_mainline, + builtin.Arch.armv7, + builtin.Arch.armv7em, + builtin.Arch.armv7m, + builtin.Arch.armv7s, + builtin.Arch.armv7k, + builtin.Arch.armv7ve, + builtin.Arch.armv6, + builtin.Arch.armv6m, + builtin.Arch.armv6k, + builtin.Arch.armv6t2, + builtin.Arch.armv5, + builtin.Arch.armv5te, + builtin.Arch.armv4t, + builtin.Arch.thumb, + => return switch (self.getFloatAbi()) { + FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3", + else => return "/lib/ld-linux.so.3", + }, + + builtin.Arch.armebv8_3a, + builtin.Arch.armebv8_2a, + builtin.Arch.armebv8_1a, + builtin.Arch.armebv8, + builtin.Arch.armebv8r, + builtin.Arch.armebv8m_baseline, + builtin.Arch.armebv8m_mainline, + builtin.Arch.armebv7, + builtin.Arch.armebv7em, + builtin.Arch.armebv7m, + builtin.Arch.armebv7s, + builtin.Arch.armebv7k, + builtin.Arch.armebv7ve, + builtin.Arch.armebv6, + builtin.Arch.armebv6m, + builtin.Arch.armebv6k, + builtin.Arch.armebv6t2, + builtin.Arch.armebv5, + builtin.Arch.armebv5te, + builtin.Arch.armebv4t, + builtin.Arch.thumbeb, + => return switch (self.getFloatAbi()) { + FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3", + else => return "/lib/ld-linux.so.3", + }, + + builtin.Arch.mips, + builtin.Arch.mipsel, + builtin.Arch.mips64, + builtin.Arch.mips64el, + => return null, + + builtin.Arch.powerpc => return "/lib/ld.so.1", + builtin.Arch.powerpc64 => return "/lib64/ld64.so.2", + builtin.Arch.powerpc64le => return "/lib64/ld64.so.2", + builtin.Arch.s390x => return "/lib64/ld64.so.1", + builtin.Arch.sparcv9 => return "/lib64/ld-linux.so.2", + builtin.Arch.x86_64 => return "/lib64/ld-linux-x86-64.so.2", + + builtin.Arch.arc, + builtin.Arch.avr, + builtin.Arch.bpfel, + builtin.Arch.bpfeb, + builtin.Arch.hexagon, + builtin.Arch.msp430, + builtin.Arch.nios2, + builtin.Arch.r600, + builtin.Arch.amdgcn, + builtin.Arch.riscv32, + builtin.Arch.riscv64, + builtin.Arch.tce, + builtin.Arch.tcele, + builtin.Arch.xcore, + builtin.Arch.nvptx, + builtin.Arch.nvptx64, + builtin.Arch.le32, + builtin.Arch.le64, + builtin.Arch.amdil, + builtin.Arch.amdil64, + builtin.Arch.hsail, + builtin.Arch.hsail64, + builtin.Arch.spir, + builtin.Arch.spir64, + builtin.Arch.kalimbav3, + builtin.Arch.kalimbav4, + builtin.Arch.kalimbav5, + builtin.Arch.shave, + builtin.Arch.lanai, + builtin.Arch.wasm32, + builtin.Arch.wasm64, + builtin.Arch.renderscript32, + builtin.Arch.renderscript64, + => return null, } }, - builtin.Environ.musl, - builtin.Environ.musleabi, - builtin.Environ.musleabihf, - => { - if (arch == builtin.Arch.x86_64) { - return "/lib/ld-musl-x86_64.so.1"; - } - }, - else => {}, - } - switch (arch) { - builtin.Arch.i386, - builtin.Arch.sparc, - builtin.Arch.sparcel, - => return "/lib/ld-linux.so.2", - - builtin.Arch.aarch64v8_3a, - builtin.Arch.aarch64v8_2a, - builtin.Arch.aarch64v8_1a, - builtin.Arch.aarch64v8, - builtin.Arch.aarch64v8r, - builtin.Arch.aarch64v8m_baseline, - builtin.Arch.aarch64v8m_mainline, - => return "/lib/ld-linux-aarch64.so.1", - - builtin.Arch.aarch64_bev8_3a, - builtin.Arch.aarch64_bev8_2a, - builtin.Arch.aarch64_bev8_1a, - builtin.Arch.aarch64_bev8, - builtin.Arch.aarch64_bev8r, - builtin.Arch.aarch64_bev8m_baseline, - builtin.Arch.aarch64_bev8m_mainline, - => return "/lib/ld-linux-aarch64_be.so.1", - - builtin.Arch.armv8_3a, - builtin.Arch.armv8_2a, - builtin.Arch.armv8_1a, - builtin.Arch.armv8, - builtin.Arch.armv8r, - builtin.Arch.armv8m_baseline, - builtin.Arch.armv8m_mainline, - builtin.Arch.armv7, - builtin.Arch.armv7em, - builtin.Arch.armv7m, - builtin.Arch.armv7s, - builtin.Arch.armv7k, - builtin.Arch.armv7ve, - builtin.Arch.armv6, - builtin.Arch.armv6m, - builtin.Arch.armv6k, - builtin.Arch.armv6t2, - builtin.Arch.armv5, - builtin.Arch.armv5te, - builtin.Arch.armv4t, - builtin.Arch.thumb, - => return switch (self.getFloatAbi()) { - FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3", - else => return "/lib/ld-linux.so.3", - }, - - builtin.Arch.armebv8_3a, - builtin.Arch.armebv8_2a, - builtin.Arch.armebv8_1a, - builtin.Arch.armebv8, - builtin.Arch.armebv8r, - builtin.Arch.armebv8m_baseline, - builtin.Arch.armebv8m_mainline, - builtin.Arch.armebv7, - builtin.Arch.armebv7em, - builtin.Arch.armebv7m, - builtin.Arch.armebv7s, - builtin.Arch.armebv7k, - builtin.Arch.armebv7ve, - builtin.Arch.armebv6, - builtin.Arch.armebv6m, - builtin.Arch.armebv6k, - builtin.Arch.armebv6t2, - builtin.Arch.armebv5, - builtin.Arch.armebv5te, - builtin.Arch.armebv4t, - builtin.Arch.thumbeb, - => return switch (self.getFloatAbi()) { - FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3", - else => return "/lib/ld-linux.so.3", - }, - - builtin.Arch.mips, - builtin.Arch.mipsel, - builtin.Arch.mips64, - builtin.Arch.mips64el, - => return null, - - builtin.Arch.powerpc => return "/lib/ld.so.1", - builtin.Arch.powerpc64 => return "/lib64/ld64.so.2", - builtin.Arch.powerpc64le => return "/lib64/ld64.so.2", - builtin.Arch.s390x => return "/lib64/ld64.so.1", - builtin.Arch.sparcv9 => return "/lib64/ld-linux.so.2", - builtin.Arch.x86_64 => return "/lib64/ld-linux-x86-64.so.2", - - builtin.Arch.arc, - builtin.Arch.avr, - builtin.Arch.bpfel, - builtin.Arch.bpfeb, - builtin.Arch.hexagon, - builtin.Arch.msp430, - builtin.Arch.nios2, - builtin.Arch.r600, - builtin.Arch.amdgcn, - builtin.Arch.riscv32, - builtin.Arch.riscv64, - builtin.Arch.tce, - builtin.Arch.tcele, - builtin.Arch.xcore, - builtin.Arch.nvptx, - builtin.Arch.nvptx64, - builtin.Arch.le32, - builtin.Arch.le64, - builtin.Arch.amdil, - builtin.Arch.amdil64, - builtin.Arch.hsail, - builtin.Arch.hsail64, - builtin.Arch.spir, - builtin.Arch.spir64, - builtin.Arch.kalimbav3, - builtin.Arch.kalimbav4, - builtin.Arch.kalimbav5, - builtin.Arch.shave, - builtin.Arch.lanai, - builtin.Arch.wasm32, - builtin.Arch.wasm64, - builtin.Arch.renderscript32, - builtin.Arch.renderscript64, - => return null, + else => return null, } } diff --git a/src/util.cpp b/src/util.cpp index f7bda86c42..192d74e766 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -47,7 +47,7 @@ bool ptr_eq(const void *a, const void *b) { // Ported from std/mem.zig. bool SplitIterator_isSplitByte(SplitIterator *self, uint8_t byte) { for (size_t i = 0; i < self->split_bytes.len; i += 1) { - if (byte == self->split_bytes.ptr[i] || byte == 0) { + if (byte == self->split_bytes.ptr[i]) { return true; } } diff --git a/std/os/index.zig b/std/os/index.zig index ba1fdb2be6..15be08c689 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -1731,8 +1731,8 @@ pub const Dir = struct { } fn nextFreebsd(self: *Dir) !?Entry { - self.handle.buf = try self.allocator.alloc(u8, page_size); - return null; // TODO + //self.handle.buf = try self.allocator.alloc(u8, page_size); + @compileError("TODO implement dirs for FreeBSD"); } }; -- cgit v1.2.3 From c54fe0d3ae867744bf1c0b27202f779fffc5ac7f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 28 Nov 2018 22:58:52 -0500 Subject: work around to support debian's fork of llvm 7.0.1 it has a patch that adds an OS type, breaking the public API this commit avoids depending on the last os type enum item, but retains the safety assertion checks. closes #1788 --- src/zig_llvm.cpp | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 163 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index 00023f6232..bda8fa0adc 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -681,18 +681,6 @@ void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) { } -static_assert((Triple::ArchType)ZigLLVM_LastArchType == Triple::LastArchType, ""); -static_assert((Triple::VendorType)ZigLLVM_LastVendorType == Triple::LastVendorType, ""); -static_assert((Triple::OSType)ZigLLVM_LastOSType == Triple::LastOSType, ""); -static_assert((Triple::EnvironmentType)ZigLLVM_LastEnvironmentType == Triple::LastEnvironmentType, ""); -static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v5 == Triple::KalimbaSubArch_v5, ""); - -static_assert((Triple::ObjectFormatType)ZigLLVM_UnknownObjectFormat == Triple::UnknownObjectFormat, ""); -static_assert((Triple::ObjectFormatType)ZigLLVM_COFF == Triple::COFF, ""); -static_assert((Triple::ObjectFormatType)ZigLLVM_ELF == Triple::ELF, ""); -static_assert((Triple::ObjectFormatType)ZigLLVM_MachO == Triple::MachO, ""); -static_assert((Triple::ObjectFormatType)ZigLLVM_Wasm == Triple::Wasm, ""); - const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch) { return (const char*)Triple::getArchTypeName((Triple::ArchType)arch).bytes_begin(); } @@ -919,3 +907,166 @@ bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_ assert(false); // unreachable abort(); } + +static_assert((Triple::ArchType)ZigLLVM_UnknownArch == Triple::UnknownArch, ""); +static_assert((Triple::ArchType)ZigLLVM_arm == Triple::arm, ""); +static_assert((Triple::ArchType)ZigLLVM_armeb == Triple::armeb, ""); +static_assert((Triple::ArchType)ZigLLVM_aarch64 == Triple::aarch64, ""); +static_assert((Triple::ArchType)ZigLLVM_aarch64_be == Triple::aarch64_be, ""); +static_assert((Triple::ArchType)ZigLLVM_arc == Triple::arc, ""); +static_assert((Triple::ArchType)ZigLLVM_avr == Triple::avr, ""); +static_assert((Triple::ArchType)ZigLLVM_bpfel == Triple::bpfel, ""); +static_assert((Triple::ArchType)ZigLLVM_bpfeb == Triple::bpfeb, ""); +static_assert((Triple::ArchType)ZigLLVM_hexagon == Triple::hexagon, ""); +static_assert((Triple::ArchType)ZigLLVM_mips == Triple::mips, ""); +static_assert((Triple::ArchType)ZigLLVM_mipsel == Triple::mipsel, ""); +static_assert((Triple::ArchType)ZigLLVM_mips64 == Triple::mips64, ""); +static_assert((Triple::ArchType)ZigLLVM_mips64el == Triple::mips64el, ""); +static_assert((Triple::ArchType)ZigLLVM_msp430 == Triple::msp430, ""); +static_assert((Triple::ArchType)ZigLLVM_nios2 == Triple::nios2, ""); +static_assert((Triple::ArchType)ZigLLVM_ppc == Triple::ppc, ""); +static_assert((Triple::ArchType)ZigLLVM_ppc64 == Triple::ppc64, ""); +static_assert((Triple::ArchType)ZigLLVM_ppc64le == Triple::ppc64le, ""); +static_assert((Triple::ArchType)ZigLLVM_r600 == Triple::r600, ""); +static_assert((Triple::ArchType)ZigLLVM_amdgcn == Triple::amdgcn, ""); +static_assert((Triple::ArchType)ZigLLVM_riscv32 == Triple::riscv32, ""); +static_assert((Triple::ArchType)ZigLLVM_riscv64 == Triple::riscv64, ""); +static_assert((Triple::ArchType)ZigLLVM_sparc == Triple::sparc, ""); +static_assert((Triple::ArchType)ZigLLVM_sparcv9 == Triple::sparcv9, ""); +static_assert((Triple::ArchType)ZigLLVM_sparcel == Triple::sparcel, ""); +static_assert((Triple::ArchType)ZigLLVM_systemz == Triple::systemz, ""); +static_assert((Triple::ArchType)ZigLLVM_tce == Triple::tce, ""); +static_assert((Triple::ArchType)ZigLLVM_tcele == Triple::tcele, ""); +static_assert((Triple::ArchType)ZigLLVM_thumb == Triple::thumb, ""); +static_assert((Triple::ArchType)ZigLLVM_thumbeb == Triple::thumbeb, ""); +static_assert((Triple::ArchType)ZigLLVM_x86 == Triple::x86, ""); +static_assert((Triple::ArchType)ZigLLVM_x86_64 == Triple::x86_64, ""); +static_assert((Triple::ArchType)ZigLLVM_xcore == Triple::xcore, ""); +static_assert((Triple::ArchType)ZigLLVM_nvptx == Triple::nvptx, ""); +static_assert((Triple::ArchType)ZigLLVM_nvptx64 == Triple::nvptx64, ""); +static_assert((Triple::ArchType)ZigLLVM_le32 == Triple::le32, ""); +static_assert((Triple::ArchType)ZigLLVM_le64 == Triple::le64, ""); +static_assert((Triple::ArchType)ZigLLVM_amdil == Triple::amdil, ""); +static_assert((Triple::ArchType)ZigLLVM_amdil64 == Triple::amdil64, ""); +static_assert((Triple::ArchType)ZigLLVM_hsail == Triple::hsail, ""); +static_assert((Triple::ArchType)ZigLLVM_hsail64 == Triple::hsail64, ""); +static_assert((Triple::ArchType)ZigLLVM_spir == Triple::spir, ""); +static_assert((Triple::ArchType)ZigLLVM_spir64 == Triple::spir64, ""); +static_assert((Triple::ArchType)ZigLLVM_kalimba == Triple::kalimba, ""); +static_assert((Triple::ArchType)ZigLLVM_shave == Triple::shave, ""); +static_assert((Triple::ArchType)ZigLLVM_lanai == Triple::lanai, ""); +static_assert((Triple::ArchType)ZigLLVM_wasm32 == Triple::wasm32, ""); +static_assert((Triple::ArchType)ZigLLVM_wasm64 == Triple::wasm64, ""); +static_assert((Triple::ArchType)ZigLLVM_renderscript32 == Triple::renderscript32, ""); +static_assert((Triple::ArchType)ZigLLVM_renderscript64 == Triple::renderscript64, ""); +// Uncomment this when testing LLVM 8.0.0 +//static_assert((Triple::ArchType)ZigLLVM_LastArchType == Triple::LastArchType, ""); + +static_assert((Triple::SubArchType)ZigLLVM_NoSubArch == Triple::NoSubArch, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_4a == Triple::ARMSubArch_v8_4a, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_3a == Triple::ARMSubArch_v8_3a, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_2a == Triple::ARMSubArch_v8_2a, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_1a == Triple::ARMSubArch_v8_1a, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8 == Triple::ARMSubArch_v8, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8r == Triple::ARMSubArch_v8r, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8m_baseline == Triple::ARMSubArch_v8m_baseline, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8m_mainline == Triple::ARMSubArch_v8m_mainline, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7 == Triple::ARMSubArch_v7, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7em == Triple::ARMSubArch_v7em, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7m == Triple::ARMSubArch_v7m, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7s == Triple::ARMSubArch_v7s, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7k == Triple::ARMSubArch_v7k, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7ve == Triple::ARMSubArch_v7ve, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6 == Triple::ARMSubArch_v6, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6m == Triple::ARMSubArch_v6m, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6k == Triple::ARMSubArch_v6k, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6t2 == Triple::ARMSubArch_v6t2, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v5 == Triple::ARMSubArch_v5, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v5te == Triple::ARMSubArch_v5te, ""); +static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v4t == Triple::ARMSubArch_v4t, ""); +static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v3 == Triple::KalimbaSubArch_v3, ""); +static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v4 == Triple::KalimbaSubArch_v4, ""); +static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v5 == Triple::KalimbaSubArch_v5, ""); + +static_assert((Triple::VendorType)ZigLLVM_UnknownVendor == Triple::UnknownVendor, ""); +static_assert((Triple::VendorType)ZigLLVM_Apple == Triple::Apple, ""); +static_assert((Triple::VendorType)ZigLLVM_PC == Triple::PC, ""); +static_assert((Triple::VendorType)ZigLLVM_SCEI == Triple::SCEI, ""); +static_assert((Triple::VendorType)ZigLLVM_BGP == Triple::BGP, ""); +static_assert((Triple::VendorType)ZigLLVM_BGQ == Triple::BGQ, ""); +static_assert((Triple::VendorType)ZigLLVM_Freescale == Triple::Freescale, ""); +static_assert((Triple::VendorType)ZigLLVM_IBM == Triple::IBM, ""); +static_assert((Triple::VendorType)ZigLLVM_ImaginationTechnologies == Triple::ImaginationTechnologies, ""); +static_assert((Triple::VendorType)ZigLLVM_MipsTechnologies == Triple::MipsTechnologies, ""); +static_assert((Triple::VendorType)ZigLLVM_NVIDIA == Triple::NVIDIA, ""); +static_assert((Triple::VendorType)ZigLLVM_CSR == Triple::CSR, ""); +static_assert((Triple::VendorType)ZigLLVM_Myriad == Triple::Myriad, ""); +static_assert((Triple::VendorType)ZigLLVM_AMD == Triple::AMD, ""); +static_assert((Triple::VendorType)ZigLLVM_Mesa == Triple::Mesa, ""); +static_assert((Triple::VendorType)ZigLLVM_SUSE == Triple::SUSE, ""); +static_assert((Triple::VendorType)ZigLLVM_OpenEmbedded == Triple::OpenEmbedded, ""); +// Uncomment this when testing LLVM 8.0.0 +//static_assert((Triple::VendorType)ZigLLVM_LastVendorType == Triple::LastVendorType, ""); + +static_assert((Triple::OSType)ZigLLVM_UnknownOS == Triple::UnknownOS, ""); +static_assert((Triple::OSType)ZigLLVM_Ananas == Triple::Ananas, ""); +static_assert((Triple::OSType)ZigLLVM_CloudABI == Triple::CloudABI, ""); +static_assert((Triple::OSType)ZigLLVM_Darwin == Triple::Darwin, ""); +static_assert((Triple::OSType)ZigLLVM_DragonFly == Triple::DragonFly, ""); +static_assert((Triple::OSType)ZigLLVM_FreeBSD == Triple::FreeBSD, ""); +static_assert((Triple::OSType)ZigLLVM_Fuchsia == Triple::Fuchsia, ""); +static_assert((Triple::OSType)ZigLLVM_IOS == Triple::IOS, ""); +static_assert((Triple::OSType)ZigLLVM_KFreeBSD == Triple::KFreeBSD, ""); +static_assert((Triple::OSType)ZigLLVM_Linux == Triple::Linux, ""); +static_assert((Triple::OSType)ZigLLVM_Lv2 == Triple::Lv2, ""); +static_assert((Triple::OSType)ZigLLVM_MacOSX == Triple::MacOSX, ""); +static_assert((Triple::OSType)ZigLLVM_NetBSD == Triple::NetBSD, ""); +static_assert((Triple::OSType)ZigLLVM_OpenBSD == Triple::OpenBSD, ""); +static_assert((Triple::OSType)ZigLLVM_Solaris == Triple::Solaris, ""); +static_assert((Triple::OSType)ZigLLVM_Win32 == Triple::Win32, ""); +static_assert((Triple::OSType)ZigLLVM_Haiku == Triple::Haiku, ""); +static_assert((Triple::OSType)ZigLLVM_Minix == Triple::Minix, ""); +static_assert((Triple::OSType)ZigLLVM_RTEMS == Triple::RTEMS, ""); +static_assert((Triple::OSType)ZigLLVM_NaCl == Triple::NaCl, ""); +static_assert((Triple::OSType)ZigLLVM_CNK == Triple::CNK, ""); +static_assert((Triple::OSType)ZigLLVM_AIX == Triple::AIX, ""); +static_assert((Triple::OSType)ZigLLVM_CUDA == Triple::CUDA, ""); +static_assert((Triple::OSType)ZigLLVM_NVCL == Triple::NVCL, ""); +static_assert((Triple::OSType)ZigLLVM_AMDHSA == Triple::AMDHSA, ""); +static_assert((Triple::OSType)ZigLLVM_PS4 == Triple::PS4, ""); +static_assert((Triple::OSType)ZigLLVM_ELFIAMCU == Triple::ELFIAMCU, ""); +static_assert((Triple::OSType)ZigLLVM_TvOS == Triple::TvOS, ""); +static_assert((Triple::OSType)ZigLLVM_WatchOS == Triple::WatchOS, ""); +static_assert((Triple::OSType)ZigLLVM_Mesa3D == Triple::Mesa3D, ""); +static_assert((Triple::OSType)ZigLLVM_Contiki == Triple::Contiki, ""); +static_assert((Triple::OSType)ZigLLVM_AMDPAL == Triple::AMDPAL, ""); +// Uncomment this when testing LLVM 8.0.0 +//static_assert((Triple::OSType)ZigLLVM_LastOSType == Triple::LastOSType, ""); + +static_assert((Triple::EnvironmentType)ZigLLVM_UnknownEnvironment == Triple::UnknownEnvironment, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_GNU == Triple::GNU, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_GNUABIN32 == Triple::GNUABIN32, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_GNUABI64 == Triple::GNUABI64, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_GNUEABI == Triple::GNUEABI, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_GNUEABIHF == Triple::GNUEABIHF, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_GNUX32 == Triple::GNUX32, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_CODE16 == Triple::CODE16, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_EABI == Triple::EABI, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_EABIHF == Triple::EABIHF, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_Android == Triple::Android, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_Musl == Triple::Musl, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_MuslEABI == Triple::MuslEABI, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_MuslEABIHF == Triple::MuslEABIHF, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_MSVC == Triple::MSVC, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_Itanium == Triple::Itanium, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_Cygnus == Triple::Cygnus, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_CoreCLR == Triple::CoreCLR, ""); +static_assert((Triple::EnvironmentType)ZigLLVM_Simulator == Triple::Simulator, ""); +// Uncomment this when testing LLVM 8.0.0 +//static_assert((Triple::EnvironmentType)ZigLLVM_LastEnvironmentType == Triple::LastEnvironmentType, ""); + +static_assert((Triple::ObjectFormatType)ZigLLVM_UnknownObjectFormat == Triple::UnknownObjectFormat, ""); +static_assert((Triple::ObjectFormatType)ZigLLVM_COFF == Triple::COFF, ""); +static_assert((Triple::ObjectFormatType)ZigLLVM_ELF == Triple::ELF, ""); +static_assert((Triple::ObjectFormatType)ZigLLVM_MachO == Triple::MachO, ""); +static_assert((Triple::ObjectFormatType)ZigLLVM_Wasm == Triple::Wasm, ""); -- cgit v1.2.3 From 1b0f4d59763e273901717199e47764745aed2631 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 5 Dec 2018 15:32:25 -0500 Subject: implement compile error note for function parameter type mismatch --- src/ir.cpp | 14 +++++++++++++- test/compile_errors.zig | 20 ++++++++++++++++---- 2 files changed, 29 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/ir.cpp b/src/ir.cpp index 1edb122670..68a0b7f6f6 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -67,6 +67,8 @@ enum ConstCastResultId { struct ConstCastOnly; struct ConstCastArg { size_t arg_index; + ZigType *actual_param_type; + ZigType *expected_param_type; ConstCastOnly *child; }; @@ -8638,6 +8640,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted if (arg_child.id != ConstCastResultIdOk) { result.id = ConstCastResultIdFnArg; result.data.fn_arg.arg_index = i; + result.data.fn_arg.actual_param_type = actual_param_info->type; + result.data.fn_arg.expected_param_type = expected_param_info->type; result.data.fn_arg.child = allocate_nonzero(1); *result.data.fn_arg.child = arg_child; return result; @@ -10483,6 +10487,15 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa } break; } + case ConstCastResultIdFnArg: { + ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node, + buf_sprintf("parameter %" ZIG_PRI_usize ": '%s' cannot cast into '%s'", + cast_result->data.fn_arg.arg_index, + buf_ptr(&cast_result->data.fn_arg.actual_param_type->name), + buf_ptr(&cast_result->data.fn_arg.expected_param_type->name))); + report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg); + break; + } case ConstCastResultIdFnAlign: // TODO case ConstCastResultIdFnCC: // TODO case ConstCastResultIdFnVarArgs: // TODO @@ -10490,7 +10503,6 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa case ConstCastResultIdFnReturnType: // TODO case ConstCastResultIdFnArgCount: // TODO case ConstCastResultIdFnGenericArgCount: // TODO - case ConstCastResultIdFnArg: // TODO case ConstCastResultIdFnArgNoAlias: // TODO case ConstCastResultIdUnresolvedInferredErrSet: // TODO case ConstCastResultIdAsyncAllocatorType: // TODO diff --git a/test/compile_errors.zig b/test/compile_errors.zig index c5575a0c0b..be839f0550 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1,6 +1,18 @@ const tests = @import("tests.zig"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.add( + "error note for function parameter incompatibility", + \\fn do_the_thing(func: fn (arg: i32) void) void {} + \\fn bar(arg: bool) void {} + \\export fn entry() void { + \\ do_the_thing(bar); + \\} + , + ".tmp_source.zig:4:18: error: expected type 'fn(i32) void', found 'fn(bool) void", + ".tmp_source.zig:4:18: note: parameter 0: 'bool' cannot cast into 'i32'", + ); + cases.add( "cast negative value to unsigned integer", \\comptime { @@ -5248,8 +5260,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn foo() void { \\ asm volatile ("" : : [bar]"r"(3) : ""); \\} - , - ".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_int", + , + ".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_int", ); cases.add( @@ -5257,7 +5269,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn foo() void { \\ asm volatile ("" : : [bar]"r"(3.17) : ""); \\} - , - ".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_float", + , + ".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_float", ); } -- cgit v1.2.3 From b883bc873df7f1a8fa3a13800402e1ec8da74328 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 12 Dec 2018 20:19:46 -0500 Subject: breaking API changes to all readInt/writeInt functions & more * add `@bswap` builtin function. See #767 * comptime evaluation facilities are improved to be able to handle a `@ptrCast` with a backing array. * `@truncate` allows "truncating" a u0 value to any integer type, and the result is always comptime known to be `0`. * when specifying pointer alignment in a type expression, the alignment value of pointers which do not have addresses at runtime is ignored, and always has the default/ABI alignment * threw in a fix to freebsd/x86_64.zig to update syntax from language changes * some improvements are pending #863 closes #638 closes #1733 std lib API changes * io.InStream().readIntNe renamed to readIntNative * io.InStream().readIntLe renamed to readIntLittle * io.InStream().readIntBe renamed to readIntBig * introduced io.InStream().readIntForeign * io.InStream().readInt has parameter order changed * io.InStream().readVarInt has parameter order changed * io.InStream().writeIntNe renamed to writeIntNative * introduced io.InStream().writeIntForeign * io.InStream().writeIntLe renamed to writeIntLittle * io.InStream().writeIntBe renamed to writeIntBig * io.InStream().writeInt has parameter order changed * mem.readInt has different parameters and semantics * introduced mem.readIntNative * introduced mem.readIntForeign * mem.readIntBE renamed to mem.readIntBig and different API * mem.readIntLE renamed to mem.readIntLittle and different API * introduced mem.readIntSliceNative * introduced mem.readIntSliceForeign * introduced mem.readIntSliceLittle * introduced mem.readIntSliceBig * introduced mem.readIntSlice * mem.writeInt has different parameters and semantics * introduced mem.writeIntNative * introduced mem.writeIntForeign * mem.writeIntBE renamed to mem.readIntBig and different semantics * mem.writeIntLE renamed to mem.readIntLittle and different semantics * introduced mem.writeIntSliceForeign * introduced mem.writeIntSliceNative * introduced mem.writeIntSliceBig * introduced mem.writeIntSliceLittle * introduced mem.writeIntSlice * removed mem.endianSwapIfLe * removed mem.endianSwapIfBe * removed mem.endianSwapIf * added mem.littleToNative * added mem.bigToNative * added mem.toNative * added mem.nativeTo * added mem.nativeToLittle * added mem.nativeToBig --- doc/langref.html.in | 9 + example/guess_number/main.zig | 2 +- src-self-hosted/compilation.zig | 2 +- src/all_types.hpp | 13 ++ src/analyze.cpp | 7 +- src/codegen.cpp | 31 +++ src/ir.cpp | 156 ++++++++++++++- src/ir_print.cpp | 15 ++ std/coff.zig | 44 ++--- std/crypto/blake2.zig | 11 +- std/crypto/chacha20.zig | 53 ++--- std/crypto/md5.zig | 3 +- std/crypto/poly1305.zig | 27 +-- std/crypto/sha1.zig | 3 +- std/crypto/sha2.zig | 6 +- std/crypto/sha3.zig | 5 +- std/crypto/x25519.zig | 41 ++-- std/debug/index.zig | 60 +++--- std/elf.zig | 70 +++---- std/event/io.zig | 14 +- std/hash/siphash.zig | 14 +- std/heap.zig | 2 +- std/io.zig | 60 +++--- std/mem.zig | 427 +++++++++++++++++++++++++--------------- std/net.zig | 12 +- std/os/child_process.zig | 4 +- std/os/freebsd/x86_64.zig | 6 +- std/pdb.zig | 6 +- std/rand/index.zig | 8 +- std/unicode.zig | 30 +-- test/behavior.zig | 2 + test/cases/bswap.zig | 32 +++ test/cases/truncate.zig | 8 + test/compile_errors.zig | 12 ++ 34 files changed, 797 insertions(+), 398 deletions(-) create mode 100644 test/cases/bswap.zig create mode 100644 test/cases/truncate.zig (limited to 'src') diff --git a/doc/langref.html.in b/doc/langref.html.in index a1903331a4..f820a05b69 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -5312,6 +5312,15 @@ comptime {

{#header_close#} + {#header_open|@bswap#} +
{#syntax#}@swap(comptime T: type, value: T) T{#endsyntax#}
+

{#syntax#}T{#endsyntax#} must be an integer type with bit count evenly divisible by 8.

+

+ Swaps the byte order of the integer. This converts a big endian integer to a little endian integer, + and converts a little endian integer to a big endian integer. +

+ {#header_close#} + {#header_open|@bytesToSlice#}
{#syntax#}@bytesToSlice(comptime Element: type, bytes: []u8) []Element{#endsyntax#}

diff --git a/example/guess_number/main.zig b/example/guess_number/main.zig index 66264666bc..b4eb1c292a 100644 --- a/example/guess_number/main.zig +++ b/example/guess_number/main.zig @@ -15,7 +15,7 @@ pub fn main() !void { std.debug.warn("unable to seed random number generator: {}", err); return err; }; - const seed = std.mem.readInt(seed_bytes, u64, builtin.Endian.Big); + const seed = std.mem.readIntNative(u64, &seed_bytes); var prng = std.rand.DefaultPrng.init(seed); const answer = prng.random.range(u8, 0, 100) + 1; diff --git a/src-self-hosted/compilation.zig b/src-self-hosted/compilation.zig index a8c3e13e33..0594cbd749 100644 --- a/src-self-hosted/compilation.zig +++ b/src-self-hosted/compilation.zig @@ -55,7 +55,7 @@ pub const ZigCompiler = struct { var seed_bytes: [@sizeOf(u64)]u8 = undefined; try std.os.getRandomBytes(seed_bytes[0..]); - const seed = std.mem.readInt(seed_bytes, u64, builtin.Endian.Big); + const seed = mem.readIntNative(u64, &seed_bytes); return ZigCompiler{ .loop = loop, diff --git a/src/all_types.hpp b/src/all_types.hpp index f7ada09a57..83b7e8495f 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1415,6 +1415,7 @@ enum BuiltinFnId { BuiltinFnIdErrorReturnTrace, BuiltinFnIdAtomicRmw, BuiltinFnIdAtomicLoad, + BuiltinFnIdBswap, }; struct BuiltinFnEntry { @@ -1487,6 +1488,7 @@ enum ZigLLVMFnId { ZigLLVMFnIdFloor, ZigLLVMFnIdCeil, ZigLLVMFnIdSqrt, + ZigLLVMFnIdBswap, }; enum AddSubMul { @@ -1516,6 +1518,9 @@ struct ZigLLVMFnKey { uint32_t bit_count; bool is_signed; } overflow_arithmetic; + struct { + uint32_t bit_count; + } bswap; } data; }; @@ -2158,6 +2163,7 @@ enum IrInstructionId { IrInstructionIdMergeErrRetTraces, IrInstructionIdMarkErrRetTracePtr, IrInstructionIdSqrt, + IrInstructionIdBswap, IrInstructionIdErrSetCast, IrInstructionIdToBytes, IrInstructionIdFromBytes, @@ -3251,6 +3257,13 @@ struct IrInstructionCheckRuntimeScope { IrInstruction *is_comptime; }; +struct IrInstructionBswap { + IrInstruction base; + + IrInstruction *type; + IrInstruction *op; +}; + static const size_t slice_ptr_index = 0; static const size_t slice_len_index = 1; diff --git a/src/analyze.cpp b/src/analyze.cpp index 2f4b173c5f..46686ce772 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -401,7 +401,8 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) { } ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, - bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset_in_host, uint32_t host_int_bytes) + bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, + uint32_t bit_offset_in_host, uint32_t host_int_bytes) { assert(!type_is_invalid(child_type)); assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque); @@ -6110,6 +6111,8 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) { return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089; case ZigLLVMFnIdSqrt: return (uint32_t)(x.data.floating.bit_count) * (uint32_t)2225366385; + case ZigLLVMFnIdBswap: + return (uint32_t)(x.data.bswap.bit_count) * (uint32_t)3661994335; case ZigLLVMFnIdOverflowArithmetic: return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) + ((uint32_t)(x.data.overflow_arithmetic.add_sub_mul) * 31640542) + @@ -6128,6 +6131,8 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) { return a.data.clz.bit_count == b.data.clz.bit_count; case ZigLLVMFnIdPopCount: return a.data.pop_count.bit_count == b.data.pop_count.bit_count; + case ZigLLVMFnIdBswap: + return a.data.bswap.bit_count == b.data.bswap.bit_count; case ZigLLVMFnIdFloor: case ZigLLVMFnIdCeil: case ZigLLVMFnIdSqrt: diff --git a/src/codegen.cpp b/src/codegen.cpp index 1033ed8120..08dd11800a 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3814,6 +3814,11 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI n_args = 1; key.id = ZigLLVMFnIdPopCount; key.data.pop_count.bit_count = (uint32_t)int_type->data.integral.bit_count; + } else if (fn_id == BuiltinFnIdBswap) { + fn_name = "bswap"; + n_args = 1; + key.id = ZigLLVMFnIdBswap; + key.data.bswap.bit_count = (uint32_t)int_type->data.integral.bit_count; } else { zig_unreachable(); } @@ -5098,6 +5103,29 @@ static LLVMValueRef ir_render_sqrt(CodeGen *g, IrExecutable *executable, IrInstr return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); } +static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInstructionBswap *instruction) { + LLVMValueRef op = ir_llvm_value(g, instruction->op); + ZigType *int_type = instruction->base.value.type; + assert(int_type->id == ZigTypeIdInt); + if (int_type->data.integral.bit_count % 16 == 0) { + LLVMValueRef fn_val = get_int_builtin_fn(g, instruction->base.value.type, BuiltinFnIdBswap); + return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); + } + // Not an even number of bytes, so we zext 1 byte, then bswap, shift right 1 byte, truncate + ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed, + int_type->data.integral.bit_count + 8); + // aabbcc + LLVMValueRef extended = LLVMBuildZExt(g->builder, op, extended_type->type_ref, ""); + // 00aabbcc + LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap); + LLVMValueRef swapped = LLVMBuildCall(g->builder, fn_val, &extended, 1, ""); + // ccbbaa00 + LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped, + LLVMConstInt(extended_type->type_ref, 8, false), ""); + // 00ccbbaa + return LLVMBuildTrunc(g->builder, shifted, int_type->type_ref, ""); +} + static void set_debug_location(CodeGen *g, IrInstruction *instruction) { AstNode *source_node = instruction->source_node; Scope *scope = instruction->scope; @@ -5335,6 +5363,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction); case IrInstructionIdSqrt: return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction); + case IrInstructionIdBswap: + return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction); } zig_unreachable(); } @@ -6757,6 +6787,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1); create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2); create_builtin_fn(g, BuiltinFnIdThis, "This", 0); + create_builtin_fn(g, BuiltinFnIdBswap, "bswap", 2); } static const char *bool_to_str(bool b) { diff --git a/src/ir.cpp b/src/ir.cpp index 68a0b7f6f6..dc87f040bc 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -856,6 +856,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) { return IrInstructionIdSqrt; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionBswap *) { + return IrInstructionIdBswap; +} + static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) { return IrInstructionIdCheckRuntimeScope; } @@ -2705,6 +2709,17 @@ static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *sourc return &instruction->base; } +static IrInstruction *ir_build_bswap(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) { + IrInstructionBswap *instruction = ir_build_instruction(irb, scope, source_node); + instruction->type = type; + instruction->op = op; + + if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block); + ir_ref_instruction(op, irb->current_basic_block); + + return &instruction->base; +} + static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) { IrInstructionCheckRuntimeScope *instruction = ir_build_instruction(irb, scope, source_node); instruction->scope_is_comptime = scope_is_comptime; @@ -4689,6 +4704,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, result, lval); } + case BuiltinFnIdBswap: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_instruction) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_instruction) + return arg1_value; + + IrInstruction *result = ir_build_bswap(irb, scope, node, arg0_value, arg1_value); + return ir_lval_wrap(irb, scope, result, lval); + } } zig_unreachable(); } @@ -13674,18 +13704,55 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, return ErrorNone; } - if (dst_size > src_size) { - ir_add_error_node(ira, source_node, - buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes", - dst_size, buf_ptr(&pointee->type->name), src_size)); - return ErrorSemanticAnalyzeFail; + if (dst_size <= src_size) { + Buf buf = BUF_INIT; + buf_resize(&buf, src_size); + buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee); + buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val); + return ErrorNone; } - Buf buf = BUF_INIT; - buf_resize(&buf, src_size); - buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee); - buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val); - return ErrorNone; + switch (ptr_val->data.x_ptr.special) { + case ConstPtrSpecialInvalid: + zig_unreachable(); + case ConstPtrSpecialRef: { + ir_add_error_node(ira, source_node, + buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes", + dst_size, buf_ptr(&pointee->type->name), src_size)); + return ErrorSemanticAnalyzeFail; + } + case ConstPtrSpecialBaseArray: { + ConstExprValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val; + assert(array_val->type->id == ZigTypeIdArray); + if (array_val->data.x_array.special != ConstArraySpecialNone) + zig_panic("TODO"); + size_t elem_size = src_size; + src_size = elem_size * + (array_val->type->data.array.len - ptr_val->data.x_ptr.data.base_array.elem_index); + if (dst_size > src_size) { + ir_add_error_node(ira, source_node, + buf_sprintf("attempt to read %zu bytes from %s at index %" ZIG_PRI_usize " which is %zu bytes", + dst_size, buf_ptr(&array_val->type->name), ptr_val->data.x_ptr.data.base_array.elem_index, + src_size)); + return ErrorSemanticAnalyzeFail; + } + size_t elem_count = (dst_size % elem_size == 0) ? (dst_size / elem_size) : (dst_size / elem_size + 1); + Buf buf = BUF_INIT; + buf_resize(&buf, elem_count * elem_size); + for (size_t i = 0; i < elem_count; i += 1) { + ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[i]; + buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val); + } + buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val); + return ErrorNone; + } + case ConstPtrSpecialBaseStruct: + case ConstPtrSpecialDiscard: + case ConstPtrSpecialHardCodedAddr: + case ConstPtrSpecialFunction: + zig_panic("TODO"); + } + zig_unreachable(); } static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { @@ -18054,6 +18121,12 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct return ira->codegen->invalid_instruction; } + if (src_type->data.integral.bit_count == 0) { + IrInstruction *result = ir_const(ira, &instruction->base, dest_type); + bigint_init_unsigned(&result->value.data.x_bigint, 0); + return result; + } + if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) { const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned"; ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name))); @@ -20299,6 +20372,9 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct return ira->codegen->invalid_instruction; if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown))) return ira->codegen->invalid_instruction; + if (!type_has_bits(child_type)) { + align_bytes = 0; + } } else { if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown))) return ira->codegen->invalid_instruction; @@ -20898,6 +20974,63 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS return result; } +static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) { + ZigType *int_type = ir_resolve_type(ira, instruction->type->child); + if (type_is_invalid(int_type)) + return ira->codegen->invalid_instruction; + + IrInstruction *op = instruction->op->child; + if (type_is_invalid(op->value.type)) + return ira->codegen->invalid_instruction; + + if (int_type->id != ZigTypeIdInt) { + ir_add_error(ira, instruction->type, + buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name))); + return ira->codegen->invalid_instruction; + } + + if (int_type->data.integral.bit_count % 8 != 0) { + ir_add_error(ira, instruction->type, + buf_sprintf("@bswap integer type '%s' has %" PRIu32 " bits which is not evenly divisible by 8", + buf_ptr(&int_type->name), int_type->data.integral.bit_count)); + return ira->codegen->invalid_instruction; + } + + IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type); + if (type_is_invalid(casted_op->value.type)) + return ira->codegen->invalid_instruction; + + if (int_type->data.integral.bit_count == 0) { + IrInstruction *result = ir_const(ira, &instruction->base, int_type); + bigint_init_unsigned(&result->value.data.x_bigint, 0); + return result; + } + + if (int_type->data.integral.bit_count == 8) { + return casted_op; + } + + if (instr_is_comptime(casted_op)) { + ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad); + if (!val) + return ira->codegen->invalid_instruction; + + IrInstruction *result = ir_const(ira, &instruction->base, int_type); + size_t buf_size = int_type->data.integral.bit_count / 8; + uint8_t *buf = allocate_nonzero(buf_size); + bigint_write_twos_complement(&val->data.x_bigint, buf, int_type->data.integral.bit_count, true); + bigint_read_twos_complement(&result->value.data.x_bigint, buf, int_type->data.integral.bit_count, false, + int_type->data.integral.is_signed); + return result; + } + + IrInstruction *result = ir_build_bswap(&ira->new_irb, instruction->base.scope, + instruction->base.source_node, nullptr, casted_op); + result->value.type = int_type; + return result; +} + + static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) { Error err; IrInstruction *target = instruction->target->child; @@ -21233,6 +21366,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction); case IrInstructionIdSqrt: return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction); + case IrInstructionIdBswap: + return ir_analyze_instruction_bswap(ira, (IrInstructionBswap *)instruction); case IrInstructionIdIntToErr: return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction); case IrInstructionIdErrToInt: @@ -21454,6 +21589,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdCoroPromise: case IrInstructionIdPromiseResultType: case IrInstructionIdSqrt: + case IrInstructionIdBswap: case IrInstructionIdAtomicLoad: case IrInstructionIdIntCast: case IrInstructionIdFloatCast: diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 13c06e4e2d..e09b0073eb 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -1323,6 +1323,18 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) { fprintf(irp->f, ")"); } +static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) { + fprintf(irp->f, "@bswap("); + if (instruction->type != nullptr) { + ir_print_other_instruction(irp, instruction->type); + } else { + fprintf(irp->f, "null"); + } + fprintf(irp->f, ","); + ir_print_other_instruction(irp, instruction->op); + fprintf(irp->f, ")"); +} + static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { ir_print_prefix(irp, instruction); switch (instruction->id) { @@ -1736,6 +1748,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { case IrInstructionIdSqrt: ir_print_sqrt(irp, (IrInstructionSqrt *)instruction); break; + case IrInstructionIdBswap: + ir_print_bswap(irp, (IrInstructionBswap *)instruction); + break; case IrInstructionIdAtomicLoad: ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction); break; diff --git a/std/coff.zig b/std/coff.zig index 6a1aa34b46..53bd2a4b7a 100644 --- a/std/coff.zig +++ b/std/coff.zig @@ -51,7 +51,7 @@ pub const Coff = struct { // Seek to PE File Header (coff header) try self.in_file.seekTo(pe_pointer_offset); - const pe_magic_offset = try in.readIntLe(u32); + const pe_magic_offset = try in.readIntLittle(u32); try self.in_file.seekTo(pe_magic_offset); var pe_header_magic: [4]u8 = undefined; @@ -60,13 +60,13 @@ pub const Coff = struct { return error.InvalidPEHeader; self.coff_header = CoffHeader{ - .machine = try in.readIntLe(u16), - .number_of_sections = try in.readIntLe(u16), - .timedate_stamp = try in.readIntLe(u32), - .pointer_to_symbol_table = try in.readIntLe(u32), - .number_of_symbols = try in.readIntLe(u32), - .size_of_optional_header = try in.readIntLe(u16), - .characteristics = try in.readIntLe(u16), + .machine = try in.readIntLittle(u16), + .number_of_sections = try in.readIntLittle(u16), + .timedate_stamp = try in.readIntLittle(u32), + .pointer_to_symbol_table = try in.readIntLittle(u32), + .number_of_symbols = try in.readIntLittle(u32), + .size_of_optional_header = try in.readIntLittle(u16), + .characteristics = try in.readIntLittle(u16), }; switch (self.coff_header.machine) { @@ -79,7 +79,7 @@ pub const Coff = struct { fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void { const in = &file_stream.stream; - self.pe_header.magic = try in.readIntLe(u16); + self.pe_header.magic = try in.readIntLittle(u16); // For now we're only interested in finding the reference to the .pdb, // so we'll skip most of this header, which size is different in 32 // 64 bits by the way. @@ -93,14 +93,14 @@ pub const Coff = struct { try self.in_file.seekForward(skip_size); - const number_of_rva_and_sizes = try in.readIntLe(u32); + const number_of_rva_and_sizes = try in.readIntLittle(u32); if (number_of_rva_and_sizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES) return error.InvalidPEHeader; for (self.pe_header.data_directory) |*data_dir| { data_dir.* = OptionalHeader.DataDirectory{ - .virtual_address = try in.readIntLe(u32), - .size = try in.readIntLe(u32), + .virtual_address = try in.readIntLittle(u32), + .size = try in.readIntLittle(u32), }; } } @@ -124,7 +124,7 @@ pub const Coff = struct { if (!mem.eql(u8, cv_signature, "RSDS")) return error.InvalidPEMagic; try in.readNoEof(self.guid[0..]); - self.age = try in.readIntLe(u32); + self.age = try in.readIntLittle(u32); // Finally read the null-terminated string. var byte = try in.readByte(); @@ -157,15 +157,15 @@ pub const Coff = struct { try self.sections.append(Section{ .header = SectionHeader{ .name = name, - .misc = SectionHeader.Misc{ .physical_address = try in.readIntLe(u32) }, - .virtual_address = try in.readIntLe(u32), - .size_of_raw_data = try in.readIntLe(u32), - .pointer_to_raw_data = try in.readIntLe(u32), - .pointer_to_relocations = try in.readIntLe(u32), - .pointer_to_line_numbers = try in.readIntLe(u32), - .number_of_relocations = try in.readIntLe(u16), - .number_of_line_numbers = try in.readIntLe(u16), - .characteristics = try in.readIntLe(u32), + .misc = SectionHeader.Misc{ .physical_address = try in.readIntLittle(u32) }, + .virtual_address = try in.readIntLittle(u32), + .size_of_raw_data = try in.readIntLittle(u32), + .pointer_to_raw_data = try in.readIntLittle(u32), + .pointer_to_relocations = try in.readIntLittle(u32), + .pointer_to_line_numbers = try in.readIntLittle(u32), + .number_of_relocations = try in.readIntLittle(u16), + .number_of_line_numbers = try in.readIntLittle(u16), + .characteristics = try in.readIntLittle(u32), }, }); } diff --git a/std/crypto/blake2.zig b/std/crypto/blake2.zig index dc68d806d2..e3de65916a 100644 --- a/std/crypto/blake2.zig +++ b/std/crypto/blake2.zig @@ -123,7 +123,8 @@ fn Blake2s(comptime out_len: usize) type { const rr = d.h[0 .. out_len / 32]; for (rr) |s, j| { - mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Little); + // TODO https://github.com/ziglang/zig/issues/863 + mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s); } } @@ -134,7 +135,8 @@ fn Blake2s(comptime out_len: usize) type { var v: [16]u32 = undefined; for (m) |*r, i| { - r.* = mem.readIntLE(u32, b[4 * i .. 4 * i + 4]); + // TODO https://github.com/ziglang/zig/issues/863 + r.* = mem.readIntSliceLittle(u32, b[4 * i .. 4 * i + 4]); } var k: usize = 0; @@ -356,7 +358,8 @@ fn Blake2b(comptime out_len: usize) type { const rr = d.h[0 .. out_len / 64]; for (rr) |s, j| { - mem.writeInt(out[8 * j .. 8 * j + 8], s, builtin.Endian.Little); + // TODO https://github.com/ziglang/zig/issues/863 + mem.writeIntSliceLittle(u64, out[8 * j .. 8 * j + 8], s); } } @@ -367,7 +370,7 @@ fn Blake2b(comptime out_len: usize) type { var v: [16]u64 = undefined; for (m) |*r, i| { - r.* = mem.readIntLE(u64, b[8 * i .. 8 * i + 8]); + r.* = mem.readIntSliceLittle(u64, b[8 * i .. 8 * i + 8]); } var k: usize = 0; diff --git a/std/crypto/chacha20.zig b/std/crypto/chacha20.zig index 059bc82088..5ec1e79756 100644 --- a/std/crypto/chacha20.zig +++ b/std/crypto/chacha20.zig @@ -59,7 +59,8 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void { } for (x) |_, i| { - mem.writeInt(out[4 * i .. 4 * i + 4], x[i] +% input[i], builtin.Endian.Little); + // TODO https://github.com/ziglang/zig/issues/863 + mem.writeIntSliceLittle(u32, out[4 * i .. 4 * i + 4], x[i] +% input[i]); } } @@ -70,10 +71,10 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo const c = "expand 32-byte k"; const constant_le = []u32{ - mem.readIntLE(u32, c[0..4]), - mem.readIntLE(u32, c[4..8]), - mem.readIntLE(u32, c[8..12]), - mem.readIntLE(u32, c[12..16]), + mem.readIntSliceLittle(u32, c[0..4]), + mem.readIntSliceLittle(u32, c[4..8]), + mem.readIntSliceLittle(u32, c[8..12]), + mem.readIntSliceLittle(u32, c[12..16]), }; mem.copy(u32, ctx[0..], constant_le[0..4]); @@ -117,19 +118,19 @@ pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: var k: [8]u32 = undefined; var c: [4]u32 = undefined; - k[0] = mem.readIntLE(u32, key[0..4]); - k[1] = mem.readIntLE(u32, key[4..8]); - k[2] = mem.readIntLE(u32, key[8..12]); - k[3] = mem.readIntLE(u32, key[12..16]); - k[4] = mem.readIntLE(u32, key[16..20]); - k[5] = mem.readIntLE(u32, key[20..24]); - k[6] = mem.readIntLE(u32, key[24..28]); - k[7] = mem.readIntLE(u32, key[28..32]); + k[0] = mem.readIntSliceLittle(u32, key[0..4]); + k[1] = mem.readIntSliceLittle(u32, key[4..8]); + k[2] = mem.readIntSliceLittle(u32, key[8..12]); + k[3] = mem.readIntSliceLittle(u32, key[12..16]); + k[4] = mem.readIntSliceLittle(u32, key[16..20]); + k[5] = mem.readIntSliceLittle(u32, key[20..24]); + k[6] = mem.readIntSliceLittle(u32, key[24..28]); + k[7] = mem.readIntSliceLittle(u32, key[28..32]); c[0] = counter; - c[1] = mem.readIntLE(u32, nonce[0..4]); - c[2] = mem.readIntLE(u32, nonce[4..8]); - c[3] = mem.readIntLE(u32, nonce[8..12]); + c[1] = mem.readIntSliceLittle(u32, nonce[0..4]); + c[2] = mem.readIntSliceLittle(u32, nonce[4..8]); + c[3] = mem.readIntSliceLittle(u32, nonce[8..12]); chaCha20_internal(out, in, k, c); } @@ -144,19 +145,19 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32] var k: [8]u32 = undefined; var c: [4]u32 = undefined; - k[0] = mem.readIntLE(u32, key[0..4]); - k[1] = mem.readIntLE(u32, key[4..8]); - k[2] = mem.readIntLE(u32, key[8..12]); - k[3] = mem.readIntLE(u32, key[12..16]); - k[4] = mem.readIntLE(u32, key[16..20]); - k[5] = mem.readIntLE(u32, key[20..24]); - k[6] = mem.readIntLE(u32, key[24..28]); - k[7] = mem.readIntLE(u32, key[28..32]); + k[0] = mem.readIntSliceLittle(u32, key[0..4]); + k[1] = mem.readIntSliceLittle(u32, key[4..8]); + k[2] = mem.readIntSliceLittle(u32, key[8..12]); + k[3] = mem.readIntSliceLittle(u32, key[12..16]); + k[4] = mem.readIntSliceLittle(u32, key[16..20]); + k[5] = mem.readIntSliceLittle(u32, key[20..24]); + k[6] = mem.readIntSliceLittle(u32, key[24..28]); + k[7] = mem.readIntSliceLittle(u32, key[28..32]); c[0] = @truncate(u32, counter); c[1] = @truncate(u32, counter >> 32); - c[2] = mem.readIntLE(u32, nonce[0..4]); - c[3] = mem.readIntLE(u32, nonce[4..8]); + c[2] = mem.readIntSliceLittle(u32, nonce[0..4]); + c[3] = mem.readIntSliceLittle(u32, nonce[4..8]); const block_size = (1 << 6); const big_block = (block_size << 32); diff --git a/std/crypto/md5.zig b/std/crypto/md5.zig index 8663fa751f..994a7fa25c 100644 --- a/std/crypto/md5.zig +++ b/std/crypto/md5.zig @@ -112,7 +112,8 @@ pub const Md5 = struct { d.round(d.buf[0..]); for (d.s) |s, j| { - mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Little); + // TODO https://github.com/ziglang/zig/issues/863 + mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s); } } diff --git a/std/crypto/poly1305.zig b/std/crypto/poly1305.zig index a5d9fcdf57..0d7a4d672d 100644 --- a/std/crypto/poly1305.zig +++ b/std/crypto/poly1305.zig @@ -6,8 +6,8 @@ const std = @import("../index.zig"); const builtin = @import("builtin"); const Endian = builtin.Endian; -const readInt = std.mem.readInt; -const writeInt = std.mem.writeInt; +const readIntSliceLittle = std.mem.readIntSliceLittle; +const writeIntSliceLittle = std.mem.writeIntSliceLittle; pub const Poly1305 = struct { const Self = @This(); @@ -59,19 +59,19 @@ pub const Poly1305 = struct { { var i: usize = 0; while (i < 1) : (i += 1) { - ctx.r[0] = readInt(key[0..4], u32, Endian.Little) & 0x0fffffff; + ctx.r[0] = readIntSliceLittle(u32, key[0..4]) & 0x0fffffff; } } { var i: usize = 1; while (i < 4) : (i += 1) { - ctx.r[i] = readInt(key[i * 4 .. i * 4 + 4], u32, Endian.Little) & 0x0ffffffc; + ctx.r[i] = readIntSliceLittle(u32, key[i * 4 .. i * 4 + 4]) & 0x0ffffffc; } } { var i: usize = 0; while (i < 4) : (i += 1) { - ctx.pad[i] = readInt(key[i * 4 + 16 .. i * 4 + 16 + 4], u32, Endian.Little); + ctx.pad[i] = readIntSliceLittle(u32, key[i * 4 + 16 .. i * 4 + 16 + 4]); } } @@ -168,10 +168,10 @@ pub const Poly1305 = struct { const nb_blocks = nmsg.len >> 4; var i: usize = 0; while (i < nb_blocks) : (i += 1) { - ctx.c[0] = readInt(nmsg[0..4], u32, Endian.Little); - ctx.c[1] = readInt(nmsg[4..8], u32, Endian.Little); - ctx.c[2] = readInt(nmsg[8..12], u32, Endian.Little); - ctx.c[3] = readInt(nmsg[12..16], u32, Endian.Little); + ctx.c[0] = readIntSliceLittle(u32, nmsg[0..4]); + ctx.c[1] = readIntSliceLittle(u32, nmsg[4..8]); + ctx.c[2] = readIntSliceLittle(u32, nmsg[8..12]); + ctx.c[3] = readIntSliceLittle(u32, nmsg[12..16]); polyBlock(ctx); nmsg = nmsg[16..]; } @@ -210,10 +210,11 @@ pub const Poly1305 = struct { const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000 const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000 - writeInt(out[0..], @truncate(u32, uu0), Endian.Little); - writeInt(out[4..], @truncate(u32, uu1), Endian.Little); - writeInt(out[8..], @truncate(u32, uu2), Endian.Little); - writeInt(out[12..], @truncate(u32, uu3), Endian.Little); + // TODO https://github.com/ziglang/zig/issues/863 + writeIntSliceLittle(u32, out[0..], @truncate(u32, uu0)); + writeIntSliceLittle(u32, out[4..], @truncate(u32, uu1)); + writeIntSliceLittle(u32, out[8..], @truncate(u32, uu2)); + writeIntSliceLittle(u32, out[12..], @truncate(u32, uu3)); ctx.secureZero(); } diff --git a/std/crypto/sha1.zig b/std/crypto/sha1.zig index 1cb0b17434..d5aab8f33f 100644 --- a/std/crypto/sha1.zig +++ b/std/crypto/sha1.zig @@ -109,7 +109,8 @@ pub const Sha1 = struct { d.round(d.buf[0..]); for (d.s) |s, j| { - mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Big); + // TODO https://github.com/ziglang/zig/issues/863 + mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s); } } diff --git a/std/crypto/sha2.zig b/std/crypto/sha2.zig index 7e9749364b..0476a3a25e 100644 --- a/std/crypto/sha2.zig +++ b/std/crypto/sha2.zig @@ -167,7 +167,8 @@ fn Sha2_32(comptime params: Sha2Params32) type { const rr = d.s[0 .. params.out_len / 32]; for (rr) |s, j| { - mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Big); + // TODO https://github.com/ziglang/zig/issues/863 + mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s); } } @@ -508,7 +509,8 @@ fn Sha2_64(comptime params: Sha2Params64) type { const rr = d.s[0 .. params.out_len / 64]; for (rr) |s, j| { - mem.writeInt(out[8 * j .. 8 * j + 8], s, builtin.Endian.Big); + // TODO https://github.com/ziglang/zig/issues/863 + mem.writeIntSliceBig(u64, out[8 * j .. 8 * j + 8], s); } } diff --git a/std/crypto/sha3.zig b/std/crypto/sha3.zig index 881370e686..e686e1337c 100644 --- a/std/crypto/sha3.zig +++ b/std/crypto/sha3.zig @@ -120,7 +120,7 @@ fn keccak_f(comptime F: usize, d: []u8) void { var c = []const u64{0} ** 5; for (s) |*r, i| { - r.* = mem.readIntLE(u64, d[8 * i .. 8 * i + 8]); + r.* = mem.readIntSliceLittle(u64, d[8 * i .. 8 * i + 8]); } comptime var x: usize = 0; @@ -167,7 +167,8 @@ fn keccak_f(comptime F: usize, d: []u8) void { } for (s) |r, i| { - mem.writeInt(d[8 * i .. 8 * i + 8], r, builtin.Endian.Little); + // TODO https://github.com/ziglang/zig/issues/863 + mem.writeIntSliceLittle(u64, d[8 * i .. 8 * i + 8], r); } } diff --git a/std/crypto/x25519.zig b/std/crypto/x25519.zig index 281813b457..daccb56808 100644 --- a/std/crypto/x25519.zig +++ b/std/crypto/x25519.zig @@ -7,8 +7,8 @@ const builtin = @import("builtin"); const fmt = std.fmt; const Endian = builtin.Endian; -const readInt = std.mem.readInt; -const writeInt = std.mem.writeInt; +const readIntSliceLittle = std.mem.readIntSliceLittle; +const writeIntSliceLittle = std.mem.writeIntSliceLittle; // Based on Supercop's ref10 implementation. pub const X25519 = struct { @@ -255,16 +255,16 @@ const Fe = struct { var t: [10]i64 = undefined; - t[0] = readInt(s[0..4], u32, Endian.Little); - t[1] = readInt(s[4..7], u32, Endian.Little) << 6; - t[2] = readInt(s[7..10], u32, Endian.Little) << 5; - t[3] = readInt(s[10..13], u32, Endian.Little) << 3; - t[4] = readInt(s[13..16], u32, Endian.Little) << 2; - t[5] = readInt(s[16..20], u32, Endian.Little); - t[6] = readInt(s[20..23], u32, Endian.Little) << 7; - t[7] = readInt(s[23..26], u32, Endian.Little) << 5; - t[8] = readInt(s[26..29], u32, Endian.Little) << 4; - t[9] = (readInt(s[29..32], u32, Endian.Little) & 0x7fffff) << 2; + t[0] = readIntSliceLittle(u32, s[0..4]); + t[1] = u32(readIntSliceLittle(u24, s[4..7])) << 6; + t[2] = u32(readIntSliceLittle(u24, s[7..10])) << 5; + t[3] = u32(readIntSliceLittle(u24, s[10..13])) << 3; + t[4] = u32(readIntSliceLittle(u24, s[13..16])) << 2; + t[5] = readIntSliceLittle(u32, s[16..20]); + t[6] = u32(readIntSliceLittle(u24, s[20..23])) << 7; + t[7] = u32(readIntSliceLittle(u24, s[23..26])) << 5; + t[8] = u32(readIntSliceLittle(u24, s[26..29])) << 4; + t[9] = (u32(readIntSliceLittle(u24, s[29..32])) & 0x7fffff) << 2; carry1(h, t[0..]); } @@ -544,14 +544,15 @@ const Fe = struct { ut[i] = @bitCast(u32, @intCast(i32, t[i])); } - writeInt(s[0..], (ut[0] >> 0) | (ut[1] << 26), Endian.Little); - writeInt(s[4..], (ut[1] >> 6) | (ut[2] << 19), Endian.Little); - writeInt(s[8..], (ut[2] >> 13) | (ut[3] << 13), Endian.Little); - writeInt(s[12..], (ut[3] >> 19) | (ut[4] << 6), Endian.Little); - writeInt(s[16..], (ut[5] >> 0) | (ut[6] << 25), Endian.Little); - writeInt(s[20..], (ut[6] >> 7) | (ut[7] << 19), Endian.Little); - writeInt(s[24..], (ut[7] >> 13) | (ut[8] << 12), Endian.Little); - writeInt(s[28..], (ut[8] >> 20) | (ut[9] << 6), Endian.Little); + // TODO https://github.com/ziglang/zig/issues/863 + writeIntSliceLittle(u32, s[0..4], (ut[0] >> 0) | (ut[1] << 26)); + writeIntSliceLittle(u32, s[4..8], (ut[1] >> 6) | (ut[2] << 19)); + writeIntSliceLittle(u32, s[8..12], (ut[2] >> 13) | (ut[3] << 13)); + writeIntSliceLittle(u32, s[12..16], (ut[3] >> 19) | (ut[4] << 6)); + writeIntSliceLittle(u32, s[16..20], (ut[5] >> 0) | (ut[6] << 25)); + writeIntSliceLittle(u32, s[20..24], (ut[6] >> 7) | (ut[7] << 19)); + writeIntSliceLittle(u32, s[24..28], (ut[7] >> 13) | (ut[8] << 12)); + writeIntSliceLittle(u32, s[28..], (ut[8] >> 20) | (ut[9] << 6)); std.mem.secureZero(i64, t[0..]); } diff --git a/std/debug/index.zig b/std/debug/index.zig index 4a96e9d259..3967e5a8be 100644 --- a/std/debug/index.zig +++ b/std/debug/index.zig @@ -523,7 +523,7 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void { const modi = di.pdb.getStreamById(mod.mod_info.ModuleSymStream) orelse return error.MissingDebugInfo; - const signature = try modi.stream.readIntLe(u32); + const signature = try modi.stream.readIntLittle(u32); if (signature != 4) return error.InvalidDebugInfo; @@ -757,9 +757,9 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { try di.pdb.openFile(di.coff, path); var pdb_stream = di.pdb.getStream(pdb.StreamType.Pdb) orelse return error.InvalidDebugInfo; - const version = try pdb_stream.stream.readIntLe(u32); - const signature = try pdb_stream.stream.readIntLe(u32); - const age = try pdb_stream.stream.readIntLe(u32); + const version = try pdb_stream.stream.readIntLittle(u32); + const signature = try pdb_stream.stream.readIntLittle(u32); + const age = try pdb_stream.stream.readIntLittle(u32); var guid: [16]u8 = undefined; try pdb_stream.stream.readNoEof(guid[0..]); if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age) @@ -767,7 +767,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { // We validated the executable and pdb match. const string_table_index = str_tab_index: { - const name_bytes_len = try pdb_stream.stream.readIntLe(u32); + const name_bytes_len = try pdb_stream.stream.readIntLittle(u32); const name_bytes = try allocator.alloc(u8, name_bytes_len); try pdb_stream.stream.readNoEof(name_bytes); @@ -797,8 +797,8 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { }; const bucket_list = try allocator.alloc(Bucket, present.len); for (present) |_| { - const name_offset = try pdb_stream.stream.readIntLe(u32); - const name_index = try pdb_stream.stream.readIntLe(u32); + const name_offset = try pdb_stream.stream.readIntLittle(u32); + const name_index = try pdb_stream.stream.readIntLittle(u32); const name = mem.toSlice(u8, name_bytes.ptr + name_offset); if (mem.eql(u8, name, "/names")) { break :str_tab_index name_index; @@ -859,7 +859,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator); var sect_cont_offset: usize = 0; if (section_contrib_size != 0) { - const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLe(u32)); + const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLittle(u32)); if (ver != pdb.SectionContrSubstreamVersion.Ver60) return error.InvalidDebugInfo; sect_cont_offset += @sizeOf(u32); @@ -879,11 +879,11 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { } fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize { - const num_words = try stream.readIntLe(u32); + const num_words = try stream.readIntLittle(u32); var word_i: usize = 0; var list = ArrayList(usize).init(allocator); while (word_i != num_words) : (word_i += 1) { - const word = try stream.readIntLe(u32); + const word = try stream.readIntLittle(u32); var bit_i: u5 = 0; while (true) : (bit_i += 1) { if (word & (u32(1) << bit_i) != 0) { @@ -1200,7 +1200,7 @@ const Constant = struct { fn asUnsignedLe(self: *const Constant) !u64 { if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo; if (self.signed) return error.InvalidDebugInfo; - return mem.readInt(self.payload, u64, builtin.Endian.Little); + return mem.readIntSliceLittle(u64, self.payload); } }; @@ -1381,7 +1381,7 @@ fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize } fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue { - const block_len = try in_stream.readVarInt(builtin.Endian.Little, usize, size); + const block_len = try in_stream.readVarInt(usize, builtin.Endian.Little, size); return parseFormValueBlockLen(allocator, in_stream, block_len); } @@ -1395,11 +1395,11 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo } fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 { - return if (is_64) try in_stream.readIntLe(u64) else u64(try in_stream.readIntLe(u32)); + return if (is_64) try in_stream.readIntLittle(u64) else u64(try in_stream.readIntLittle(u32)); } fn parseFormValueTargetAddrSize(in_stream: var) !u64 { - return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64) else unreachable; + return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLittle(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLittle(u64) else unreachable; } fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue { @@ -1408,7 +1408,7 @@ fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) } fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue { - const block_len = try in_stream.readIntLe(T); + const block_len = try in_stream.readIntLittle(T); return parseFormValueRefLen(allocator, in_stream, block_len); } @@ -1450,7 +1450,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 }, DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, - DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLe(u64) }, + DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLittle(u64) }, DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) }, DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, @@ -1747,11 +1747,11 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr continue; } - const version = try di.dwarf_in_stream.readInt(di.endian, u16); + const version = try di.dwarf_in_stream.readInt(u16, di.endian); // TODO support 3 and 5 if (version != 2 and version != 4) return error.InvalidDebugInfo; - const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(di.endian, u64) else try di.dwarf_in_stream.readInt(di.endian, u32); + const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian); const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length; const minimum_instruction_length = try di.dwarf_in_stream.readByte(); @@ -1820,7 +1820,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr return error.MissingDebugInfo; }, DW.LNE_set_address => { - const addr = try di.dwarf_in_stream.readInt(di.endian, usize); + const addr = try di.dwarf_in_stream.readInt(usize, di.endian); prog.address = addr; }, DW.LNE_define_file => { @@ -1882,7 +1882,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr prog.address += inc_addr; }, DW.LNS_fixed_advance_pc => { - const arg = try di.dwarf_in_stream.readInt(di.endian, u16); + const arg = try di.dwarf_in_stream.readInt(u16, di.endian); prog.address += arg; }, DW.LNS_set_prologue_end => {}, @@ -1914,10 +1914,10 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void { if (unit_length == 0) return; const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); - const version = try di.dwarf_in_stream.readInt(di.endian, u16); + const version = try di.dwarf_in_stream.readInt(u16, di.endian); if (version < 2 or version > 5) return error.InvalidDebugInfo; - const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(di.endian, u64) else try di.dwarf_in_stream.readInt(di.endian, u32); + const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian); const address_size = try di.dwarf_in_stream.readByte(); if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; @@ -1978,8 +1978,8 @@ fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit { if (di.debug_ranges) |debug_ranges| { try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset); while (true) { - const begin_addr = try di.dwarf_in_stream.readIntLe(usize); - const end_addr = try di.dwarf_in_stream.readIntLe(usize); + const begin_addr = try di.dwarf_in_stream.readIntLittle(usize); + const end_addr = try di.dwarf_in_stream.readIntLittle(usize); if (begin_addr == 0 and end_addr == 0) { break; } @@ -2001,7 +2001,8 @@ fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit { } fn readIntMem(ptr: *[*]const u8, comptime T: type, endian: builtin.Endian) T { - const result = mem.readInt(ptr.*[0..@sizeOf(T)], T, endian); + // TODO https://github.com/ziglang/zig/issues/863 + const result = mem.readIntSlice(T, ptr.*[0..@sizeOf(T)], endian); ptr.* += @sizeOf(T); return result; } @@ -2017,11 +2018,12 @@ fn readByteSignedMem(ptr: *[*]const u8) i8 { } fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 { - const first_32_bits = mem.readIntLE(u32, ptr.*[0..4]); + // TODO this code can be improved with https://github.com/ziglang/zig/issues/863 + const first_32_bits = mem.readIntSliceLittle(u32, ptr.*[0..4]); is_64.* = (first_32_bits == 0xffffffff); if (is_64.*) { ptr.* += 4; - const result = mem.readIntLE(u64, ptr.*[0..8]); + const result = mem.readIntSliceLittle(u64, ptr.*[0..8]); ptr.* += 8; return result; } else { @@ -2084,10 +2086,10 @@ fn readILeb128Mem(ptr: *[*]const u8) !i64 { } fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 { - const first_32_bits = try in_stream.readIntLe(u32); + const first_32_bits = try in_stream.readIntLittle(u32); is_64.* = (first_32_bits == 0xffffffff); if (is_64.*) { - return in_stream.readIntLe(u64); + return in_stream.readIntLittle(u64); } else { if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo; return u64(first_32_bits); diff --git a/std/elf.zig b/std/elf.zig index cf7c29b1e5..6a564c3283 100644 --- a/std/elf.zig +++ b/std/elf.zig @@ -412,7 +412,7 @@ pub const Elf = struct { // skip over padding try seekable_stream.seekForward(9); - elf.file_type = switch (try in.readInt(elf.endian, u16)) { + elf.file_type = switch (try in.readInt(u16, elf.endian)) { 1 => FileType.Relocatable, 2 => FileType.Executable, 3 => FileType.Shared, @@ -420,7 +420,7 @@ pub const Elf = struct { else => return error.InvalidFormat, }; - elf.arch = switch (try in.readInt(elf.endian, u16)) { + elf.arch = switch (try in.readInt(u16, elf.endian)) { 0x02 => Arch.Sparc, 0x03 => Arch.x86, 0x08 => Arch.Mips, @@ -433,32 +433,32 @@ pub const Elf = struct { else => return error.InvalidFormat, }; - const elf_version = try in.readInt(elf.endian, u32); + const elf_version = try in.readInt(u32, elf.endian); if (elf_version != 1) return error.InvalidFormat; if (elf.is_64) { - elf.entry_addr = try in.readInt(elf.endian, u64); - elf.program_header_offset = try in.readInt(elf.endian, u64); - elf.section_header_offset = try in.readInt(elf.endian, u64); + elf.entry_addr = try in.readInt(u64, elf.endian); + elf.program_header_offset = try in.readInt(u64, elf.endian); + elf.section_header_offset = try in.readInt(u64, elf.endian); } else { - elf.entry_addr = u64(try in.readInt(elf.endian, u32)); - elf.program_header_offset = u64(try in.readInt(elf.endian, u32)); - elf.section_header_offset = u64(try in.readInt(elf.endian, u32)); + elf.entry_addr = u64(try in.readInt(u32, elf.endian)); + elf.program_header_offset = u64(try in.readInt(u32, elf.endian)); + elf.section_header_offset = u64(try in.readInt(u32, elf.endian)); } // skip over flags try seekable_stream.seekForward(4); - const header_size = try in.readInt(elf.endian, u16); + const header_size = try in.readInt(u16, elf.endian); if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) { return error.InvalidFormat; } - const ph_entry_size = try in.readInt(elf.endian, u16); - const ph_entry_count = try in.readInt(elf.endian, u16); - const sh_entry_size = try in.readInt(elf.endian, u16); - const sh_entry_count = try in.readInt(elf.endian, u16); - elf.string_section_index = u64(try in.readInt(elf.endian, u16)); + const ph_entry_size = try in.readInt(u16, elf.endian); + const ph_entry_count = try in.readInt(u16, elf.endian); + const sh_entry_size = try in.readInt(u16, elf.endian); + const sh_entry_count = try in.readInt(u16, elf.endian); + elf.string_section_index = u64(try in.readInt(u16, elf.endian)); if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat; @@ -481,32 +481,32 @@ pub const Elf = struct { if (sh_entry_size != 64) return error.InvalidFormat; for (elf.section_headers) |*elf_section| { - elf_section.name = try in.readInt(elf.endian, u32); - elf_section.sh_type = try in.readInt(elf.endian, u32); - elf_section.flags = try in.readInt(elf.endian, u64); - elf_section.addr = try in.readInt(elf.endian, u64); - elf_section.offset = try in.readInt(elf.endian, u64); - elf_section.size = try in.readInt(elf.endian, u64); - elf_section.link = try in.readInt(elf.endian, u32); - elf_section.info = try in.readInt(elf.endian, u32); - elf_section.addr_align = try in.readInt(elf.endian, u64); - elf_section.ent_size = try in.readInt(elf.endian, u64); + elf_section.name = try in.readInt(u32, elf.endian); + elf_section.sh_type = try in.readInt(u32, elf.endian); + elf_section.flags = try in.readInt(u64, elf.endian); + elf_section.addr = try in.readInt(u64, elf.endian); + elf_section.offset = try in.readInt(u64, elf.endian); + elf_section.size = try in.readInt(u64, elf.endian); + elf_section.link = try in.readInt(u32, elf.endian); + elf_section.info = try in.readInt(u32, elf.endian); + elf_section.addr_align = try in.readInt(u64, elf.endian); + elf_section.ent_size = try in.readInt(u64, elf.endian); } } else { if (sh_entry_size != 40) return error.InvalidFormat; for (elf.section_headers) |*elf_section| { // TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ? - elf_section.name = try in.readInt(elf.endian, u32); - elf_section.sh_type = try in.readInt(elf.endian, u32); - elf_section.flags = u64(try in.readInt(elf.endian, u32)); - elf_section.addr = u64(try in.readInt(elf.endian, u32)); - elf_section.offset = u64(try in.readInt(elf.endian, u32)); - elf_section.size = u64(try in.readInt(elf.endian, u32)); - elf_section.link = try in.readInt(elf.endian, u32); - elf_section.info = try in.readInt(elf.endian, u32); - elf_section.addr_align = u64(try in.readInt(elf.endian, u32)); - elf_section.ent_size = u64(try in.readInt(elf.endian, u32)); + elf_section.name = try in.readInt(u32, elf.endian); + elf_section.sh_type = try in.readInt(u32, elf.endian); + elf_section.flags = u64(try in.readInt(u32, elf.endian)); + elf_section.addr = u64(try in.readInt(u32, elf.endian)); + elf_section.offset = u64(try in.readInt(u32, elf.endian)); + elf_section.size = u64(try in.readInt(u32, elf.endian)); + elf_section.link = try in.readInt(u32, elf.endian); + elf_section.info = try in.readInt(u32, elf.endian); + elf_section.addr_align = u64(try in.readInt(u32, elf.endian)); + elf_section.ent_size = u64(try in.readInt(u32, elf.endian)); } } diff --git a/std/event/io.zig b/std/event/io.zig index bb377a3b68..b11550f7aa 100644 --- a/std/event/io.zig +++ b/std/event/io.zig @@ -39,18 +39,22 @@ pub fn InStream(comptime ReadError: type) type { if (amt_read < buf.len) return error.EndOfStream; } - pub async fn readIntLe(self: *Self, comptime T: type) !T { - return await (async self.readInt(builtin.Endian.Little, T) catch unreachable); + pub async fn readIntLittle(self: *Self, comptime T: type) !T { + var bytes: [@sizeOf(T)]u8 = undefined; + try await (async self.readNoEof(bytes[0..]) catch unreachable); + return mem.readIntLittle(T, &bytes); } pub async fn readIntBe(self: *Self, comptime T: type) !T { - return await (async self.readInt(builtin.Endian.Big, T) catch unreachable); + var bytes: [@sizeOf(T)]u8 = undefined; + try await (async self.readNoEof(bytes[0..]) catch unreachable); + return mem.readIntBig(T, &bytes); } - pub async fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T { + pub async fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T { var bytes: [@sizeOf(T)]u8 = undefined; try await (async self.readNoEof(bytes[0..]) catch unreachable); - return mem.readInt(bytes, T, endian); + return mem.readInt(T, &bytes, endian); } pub async fn readStruct(self: *Self, comptime T: type) !T { diff --git a/std/hash/siphash.zig b/std/hash/siphash.zig index 0fe958c38b..ee26950272 100644 --- a/std/hash/siphash.zig +++ b/std/hash/siphash.zig @@ -42,8 +42,8 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) pub fn init(key: []const u8) Self { debug.assert(key.len >= 16); - const k0 = mem.readInt(key[0..8], u64, Endian.Little); - const k1 = mem.readInt(key[8..16], u64, Endian.Little); + const k0 = mem.readIntSliceLittle(u64, key[0..8]); + const k1 = mem.readIntSliceLittle(u64, key[8..16]); var d = Self{ .v0 = k0 ^ 0x736f6d6570736575, @@ -121,7 +121,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) fn round(d: *Self, b: []const u8) void { debug.assert(b.len == 8); - const m = mem.readInt(b[0..], u64, Endian.Little); + const m = mem.readIntSliceLittle(u64, b[0..]); d.v3 ^= m; comptime var i: usize = 0; @@ -162,7 +162,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"; test "siphash64-2-4 sanity" { - const vectors = [][]const u8{ + const vectors = [][8]u8{ "\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // "" "\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00" "\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc @@ -235,13 +235,13 @@ test "siphash64-2-4 sanity" { for (vectors) |vector, i| { buffer[i] = @intCast(u8, i); - const expected = mem.readInt(vector, u64, Endian.Little); + const expected = mem.readIntLittle(u64, &vector); debug.assert(siphash.hash(test_key, buffer[0..i]) == expected); } } test "siphash128-2-4 sanity" { - const vectors = [][]const u8{ + const vectors = [][16]u8{ "\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93", "\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45", "\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4", @@ -314,7 +314,7 @@ test "siphash128-2-4 sanity" { for (vectors) |vector, i| { buffer[i] = @intCast(u8, i); - const expected = mem.readInt(vector, u128, Endian.Little); + const expected = mem.readIntLittle(u128, &vector); debug.assert(siphash.hash(test_key, buffer[0..i]) == expected); } } diff --git a/std/heap.zig b/std/heap.zig index 5c31d412cf..46b247fa7e 100644 --- a/std/heap.zig +++ b/std/heap.zig @@ -66,7 +66,7 @@ pub const DirectAllocator = struct { } } - fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 { + fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 { const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); switch (builtin.os) { diff --git a/std/io.zig b/std/io.zig index bdca2b03e8..4442191717 100644 --- a/std/io.zig +++ b/std/io.zig @@ -152,35 +152,42 @@ pub fn InStream(comptime ReadError: type) type { } /// Reads a native-endian integer - pub fn readIntNe(self: *Self, comptime T: type) !T { - return self.readInt(builtin.endian, T); + pub fn readIntNative(self: *Self, comptime T: type) !T { + var bytes: [@sizeOf(T)]u8 = undefined; + try self.readNoEof(bytes[0..]); + return mem.readIntSliceNative(T, bytes); } - pub fn readIntLe(self: *Self, comptime T: type) !T { + /// Reads a foreign-endian integer + pub fn readIntForeign(self: *Self, comptime T: type) !T { var bytes: [@sizeOf(T)]u8 = undefined; try self.readNoEof(bytes[0..]); - return mem.readIntLE(T, bytes); + return mem.readIntSliceForeign(T, bytes); } - pub fn readIntBe(self: *Self, comptime T: type) !T { + pub fn readIntLittle(self: *Self, comptime T: type) !T { var bytes: [@sizeOf(T)]u8 = undefined; try self.readNoEof(bytes[0..]); - return mem.readIntBE(T, bytes); + return mem.readIntSliceLittle(T, bytes); } - pub fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T { + pub fn readIntBig(self: *Self, comptime T: type) !T { var bytes: [@sizeOf(T)]u8 = undefined; try self.readNoEof(bytes[0..]); - return mem.readInt(bytes, T, endian); + return mem.readIntSliceBig(T, bytes); } - pub fn readVarInt(self: *Self, endian: builtin.Endian, comptime T: type, size: usize) !T { + pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T { + var bytes: [@sizeOf(T)]u8 = undefined; + try self.readNoEof(bytes[0..]); + return mem.readIntSlice(T, bytes, endian); + } + + pub fn readVarInt(self: *Self, comptime T: type, endian: builtin.Endian, size: usize) !T { assert(size <= @sizeOf(T)); - assert(size <= 8); - var input_buf: [8]u8 = undefined; - const input_slice = input_buf[0..size]; - try self.readNoEof(input_slice); - return mem.readInt(input_slice, T, endian); + var bytes: [@sizeOf(T)]u8 = undefined; + try self.readNoEof(bytes[0..]); + return mem.readIntSlice(T, bytes, endian); } pub fn skipBytes(self: *Self, num_bytes: usize) !void { @@ -229,25 +236,34 @@ pub fn OutStream(comptime WriteError: type) type { } /// Write a native-endian integer. - pub fn writeIntNe(self: *Self, comptime T: type, value: T) Error!void { - return self.writeInt(builtin.endian, T, value); + pub fn writeIntNative(self: *Self, comptime T: type, value: T) Error!void { + var bytes: [@sizeOf(T)]u8 = undefined; + mem.writeIntNative(T, &bytes, value); + return self.writeFn(self, bytes); + } + + /// Write a foreign-endian integer. + pub fn writeIntForeign(self: *Self, comptime T: type, value: T) Error!void { + var bytes: [@sizeOf(T)]u8 = undefined; + mem.writeIntForeign(T, &bytes, value); + return self.writeFn(self, bytes); } - pub fn writeIntLe(self: *Self, comptime T: type, value: T) Error!void { + pub fn writeIntLittle(self: *Self, comptime T: type, value: T) Error!void { var bytes: [@sizeOf(T)]u8 = undefined; - mem.writeIntLE(T, &bytes, value); + mem.writeIntLittle(T, &bytes, value); return self.writeFn(self, bytes); } - pub fn writeIntBe(self: *Self, comptime T: type, value: T) Error!void { + pub fn writeIntBig(self: *Self, comptime T: type, value: T) Error!void { var bytes: [@sizeOf(T)]u8 = undefined; - mem.writeIntBE(T, &bytes, value); + mem.writeIntBig(T, &bytes, value); return self.writeFn(self, bytes); } - pub fn writeInt(self: *Self, endian: builtin.Endian, comptime T: type, value: T) Error!void { + pub fn writeInt(self: *Self, comptime T: type, value: T, endian: builtin.Endian) Error!void { var bytes: [@sizeOf(T)]u8 = undefined; - mem.writeInt(bytes[0..], value, endian); + mem.writeInt(T, &bytes, value, endian); return self.writeFn(self, bytes); } }; diff --git a/std/mem.zig b/std/mem.zig index 9914a08e65..97dc46a80f 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -407,186 +407,250 @@ test "mem.indexOf" { assert(lastIndexOfScalar(u8, "boo", 'o').? == 2); } -/// Reads an integer from memory with size equal to bytes.len. -/// T specifies the return type, which must be large enough to store -/// the result. -/// See also ::readIntBE or ::readIntLE. -pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T { - if (T.bit_count == 8) { - return bytes[0]; - } - var result: T = 0; - switch (endian) { - builtin.Endian.Big => { - for (bytes) |b| { - result = (result << 8) | b; - } - }, - builtin.Endian.Little => { - const ShiftType = math.Log2Int(T); - for (bytes) |b, index| { - result = result | (T(b) << @intCast(ShiftType, index * 8)); - } - }, - } - return result; -} +/// Reads an integer from memory with bit count specified by T. +/// The bit count of T must be evenly divisible by 8. +/// This function cannot fail and cannot cause undefined behavior. +/// Assumes the endianness of memory is native. This means the function can +/// simply pointer cast memory. +pub fn readIntNative(comptime T: type, bytes: *const [@sizeOf(T)]u8) T { + comptime assert(T.bit_count % 8 == 0); + return @ptrCast(*align(1) const T, bytes).*; +} + +/// Reads an integer from memory with bit count specified by T. +/// The bit count of T must be evenly divisible by 8. +/// This function cannot fail and cannot cause undefined behavior. +/// Assumes the endianness of memory is foreign, so it must byte-swap. +pub fn readIntForeign(comptime T: type, bytes: *const [@sizeOf(T)]u8) T { + comptime assert(T.bit_count % 8 == 0); + return @bswap(T, @ptrCast(*align(1) const T, bytes).*); +} + +pub const readIntLittle = switch (builtin.endian) { + builtin.Endian.Little => readIntNative, + builtin.Endian.Big => readIntForeign, +}; -/// Reads a big-endian int of type T from bytes. -/// bytes.len must be exactly @sizeOf(T). -pub fn readIntBE(comptime T: type, bytes: []const u8) T { - if (T.is_signed) { - return @bitCast(T, readIntBE(@IntType(false, T.bit_count), bytes)); - } - assert(bytes.len == @sizeOf(T)); - if (T == u8) return bytes[0]; - var result: T = 0; - { - comptime var i = 0; - inline while (i < @sizeOf(T)) : (i += 1) { - result = (result << 8) | T(bytes[i]); - } +pub const readIntBig = switch (builtin.endian) { + builtin.Endian.Little => readIntForeign, + builtin.Endian.Big => readIntNative, +}; + +/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0 +/// and ignores extra bytes. +/// Note that @sizeOf(u24) is 3. +/// The bit count of T must be evenly divisible by 8. +/// Assumes the endianness of memory is native. This means the function can +/// simply pointer cast memory. +pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T { + assert(@sizeOf(u24) == 3); + assert(bytes.len >= @sizeOf(T)); + // TODO https://github.com/ziglang/zig/issues/863 + return readIntNative(T, @ptrCast(*const [@sizeOf(T)]u8, bytes.ptr)); +} + +/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0 +/// and ignores extra bytes. +/// Note that @sizeOf(u24) is 3. +/// The bit count of T must be evenly divisible by 8. +/// Assumes the endianness of memory is foreign, so it must byte-swap. +pub fn readIntSliceForeign(comptime T: type, bytes: []const u8) T { + assert(@sizeOf(u24) == 3); + assert(bytes.len >= @sizeOf(T)); + // TODO https://github.com/ziglang/zig/issues/863 + return readIntForeign(T, @ptrCast(*const [@sizeOf(T)]u8, bytes.ptr)); +} + +pub const readIntSliceLittle = switch (builtin.endian) { + builtin.Endian.Little => readIntSliceNative, + builtin.Endian.Big => readIntSliceForeign, +}; + +pub const readIntSliceBig = switch (builtin.endian) { + builtin.Endian.Little => readIntSliceForeign, + builtin.Endian.Big => readIntSliceNative, +}; + +/// Reads an integer from memory with bit count specified by T. +/// The bit count of T must be evenly divisible by 8. +/// This function cannot fail and cannot cause undefined behavior. +pub fn readInt(comptime T: type, bytes: *const [@sizeOf(T)]u8, endian: builtin.Endian) T { + if (endian == builtin.endian) { + return readIntNative(T, bytes); + } else { + return readIntForeign(T, bytes); } - return result; } -/// Reads a little-endian int of type T from bytes. -/// bytes.len must be exactly @sizeOf(T). -pub fn readIntLE(comptime T: type, bytes: []const u8) T { - if (T.is_signed) { - return @bitCast(T, readIntLE(@IntType(false, T.bit_count), bytes)); - } - assert(bytes.len == @sizeOf(T)); - if (T == u8) return bytes[0]; - var result: T = 0; - { - comptime var i = 0; - inline while (i < @sizeOf(T)) : (i += 1) { - result |= T(bytes[i]) << i * 8; - } - } - return result; +/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0 +/// and ignores extra bytes. +/// Note that @sizeOf(u24) is 3. +/// The bit count of T must be evenly divisible by 8. +pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T { + assert(@sizeOf(u24) == 3); + assert(bytes.len >= @sizeOf(T)); + // TODO https://github.com/ziglang/zig/issues/863 + return readInt(T, @ptrCast(*const [@sizeOf(T)]u8, bytes.ptr), endian); } -test "readIntBE/LE" { - assert(readIntBE(u0, []u8{}) == 0x0); - assert(readIntLE(u0, []u8{}) == 0x0); +test "readIntBig and readIntLittle" { + assert(readIntSliceBig(u0, []u8{}) == 0x0); + assert(readIntSliceLittle(u0, []u8{}) == 0x0); - assert(readIntBE(u8, []u8{0x32}) == 0x32); - assert(readIntLE(u8, []u8{0x12}) == 0x12); + assert(readIntSliceBig(u8, []u8{0x32}) == 0x32); + assert(readIntSliceLittle(u8, []u8{0x12}) == 0x12); - assert(readIntBE(u16, []u8{ 0x12, 0x34 }) == 0x1234); - assert(readIntLE(u16, []u8{ 0x12, 0x34 }) == 0x3412); + assert(readIntSliceBig(u16, []u8{ 0x12, 0x34 }) == 0x1234); + assert(readIntSliceLittle(u16, []u8{ 0x12, 0x34 }) == 0x3412); - assert(readIntBE(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024); - assert(readIntLE(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec); + assert(readIntSliceBig(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024); + assert(readIntSliceLittle(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec); - assert(readIntBE(i8, []u8{0xff}) == -1); - assert(readIntLE(i8, []u8{0xfe}) == -2); + assert(readIntSliceBig(i8, []u8{0xff}) == -1); + assert(readIntSliceLittle(i8, []u8{0xfe}) == -2); - assert(readIntBE(i16, []u8{ 0xff, 0xfd }) == -3); - assert(readIntLE(i16, []u8{ 0xfc, 0xff }) == -4); + assert(readIntSliceBig(i16, []u8{ 0xff, 0xfd }) == -3); + assert(readIntSliceLittle(i16, []u8{ 0xfc, 0xff }) == -4); } -/// Writes an integer to memory with size equal to bytes.len. Pads with zeroes -/// to fill the entire buffer provided. -/// value must be an integer. -pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void { - const uint = @IntType(false, @typeOf(value).bit_count); - var bits = @truncate(uint, value); - switch (endian) { - builtin.Endian.Big => { - var index: usize = buf.len; - while (index != 0) { - index -= 1; +/// Writes an integer to memory, storing it in twos-complement. +/// This function always succeeds, has defined behavior for all inputs, and +/// accepts any integer bit width. +/// This function stores in native endian, which means it is implemented as a simple +/// memory store. +pub fn writeIntNative(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void { + @ptrCast(*align(1) T, buf).* = value; +} - buf[index] = @truncate(u8, bits); - bits >>= 8; - } - }, - builtin.Endian.Little => { - for (buf) |*b| { - b.* = @truncate(u8, bits); - bits >>= 8; - } - }, +/// Writes an integer to memory, storing it in twos-complement. +/// This function always succeeds, has defined behavior for all inputs, but +/// the integer bit width must be divisible by 8. +/// This function stores in foreign endian, which means it does a @bswap first. +pub fn writeIntForeign(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void { + @ptrCast(*align(1) T, buf).* = @bswap(T, value); +} + +pub const writeIntLittle = switch (builtin.endian) { + builtin.Endian.Little => writeIntNative, + builtin.Endian.Big => writeIntForeign, +}; + +pub const writeIntBig = switch (builtin.endian) { + builtin.Endian.Little => writeIntForeign, + builtin.Endian.Big => writeIntNative, +}; + +/// Writes an integer to memory, storing it in twos-complement. +/// This function always succeeds, has defined behavior for all inputs, but +/// the integer bit width must be divisible by 8. +pub fn writeInt(comptime T: type, buffer: *[@sizeOf(T)]u8, value: T, endian: builtin.Endian) void { + comptime assert(T.bit_count % 8 == 0); + if (endian == builtin.endian) { + return writeIntNative(T, buffer, value); + } else { + return writeIntForeign(T, buffer, value); } - assert(bits == 0); } -pub fn writeIntBE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void { - assert(T.bit_count % 8 == 0); +/// Writes a twos-complement little-endian integer to memory. +/// Asserts that buf.len >= @sizeOf(T). Note that @sizeOf(u24) is 3. +/// The bit count of T must be divisible by 8. +/// Any extra bytes in buffer after writing the integer are set to zero. To +/// avoid the branch to check for extra buffer bytes, use writeIntLittle +/// instead. +pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void { + comptime assert(@sizeOf(u24) == 3); + comptime assert(T.bit_count % 8 == 0); + assert(buffer.len >= @sizeOf(T)); + + // TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough const uint = @IntType(false, T.bit_count); - if (uint == u0) { - return; - } - var bits = @bitCast(uint, value); - if (uint == u8) { - buf[0] = bits; - return; + var bits = @truncate(uint, value); + for (buffer) |*b| { + b.* = @truncate(u8, bits); + bits >>= 8; } - var index: usize = buf.len; +} + +/// Writes a twos-complement big-endian integer to memory. +/// Asserts that buffer.len >= @sizeOf(T). Note that @sizeOf(u24) is 3. +/// The bit count of T must be divisible by 8. +/// Any extra bytes in buffer before writing the integer are set to zero. To +/// avoid the branch to check for extra buffer bytes, use writeIntBig instead. +pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void { + comptime assert(@sizeOf(u24) == 3); + comptime assert(T.bit_count % 8 == 0); + assert(buffer.len >= @sizeOf(T)); + + // TODO I want to call writeIntBig here but comptime eval facilities aren't good enough + const uint = @IntType(false, T.bit_count); + var bits = @truncate(uint, value); + var index: usize = buffer.len; while (index != 0) { index -= 1; - - buf[index] = @truncate(u8, bits); + buffer[index] = @truncate(u8, bits); bits >>= 8; } - assert(bits == 0); } -pub fn writeIntLE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void { - assert(T.bit_count % 8 == 0); - const uint = @IntType(false, T.bit_count); - if (uint == u0) { - return; - } - var bits = @bitCast(uint, value); - if (uint == u8) { - buf[0] = bits; - return; - } - for (buf) |*b| { - b.* = @truncate(u8, bits); - bits >>= 8; +pub const writeIntSliceNative = switch (builtin.endian) { + builtin.Endian.Little => writeIntSliceLittle, + builtin.Endian.Big => writeIntSliceBig, +}; + +pub const writeIntSliceForeign = switch (builtin.endian) { + builtin.Endian.Little => writeIntSliceBig, + builtin.Endian.Big => writeIntSliceLittle, +}; + +/// Writes a twos-complement integer to memory, with the specified endianness. +/// Asserts that buf.len >= @sizeOf(T). Note that @sizeOf(u24) is 3. +/// The bit count of T must be evenly divisible by 8. +/// Any extra bytes in buffer not part of the integer are set to zero, with +/// respect to endianness. To avoid the branch to check for extra buffer bytes, +/// use writeInt instead. +pub fn writeIntSlice(comptime T: type, buffer: []u8, value: T, endian: builtin.Endian) void { + comptime assert(T.bit_count % 8 == 0); + switch (endian) { + builtin.Endian.Little => return writeIntSliceLittle(T, buffer, value), + builtin.Endian.Big => return writeIntSliceBig(T, buffer, value), } - assert(bits == 0); } -test "writeIntBE/LE" { +test "writeIntBig and writeIntLittle" { var buf0: [0]u8 = undefined; var buf1: [1]u8 = undefined; var buf2: [2]u8 = undefined; var buf9: [9]u8 = undefined; - writeIntBE(u0, &buf0, 0x0); + writeIntBig(u0, &buf0, 0x0); assert(eql_slice_u8(buf0[0..], []u8{})); - writeIntLE(u0, &buf0, 0x0); + writeIntLittle(u0, &buf0, 0x0); assert(eql_slice_u8(buf0[0..], []u8{})); - writeIntBE(u8, &buf1, 0x12); + writeIntBig(u8, &buf1, 0x12); assert(eql_slice_u8(buf1[0..], []u8{0x12})); - writeIntLE(u8, &buf1, 0x34); + writeIntLittle(u8, &buf1, 0x34); assert(eql_slice_u8(buf1[0..], []u8{0x34})); - writeIntBE(u16, &buf2, 0x1234); + writeIntBig(u16, &buf2, 0x1234); assert(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 })); - writeIntLE(u16, &buf2, 0x5678); + writeIntLittle(u16, &buf2, 0x5678); assert(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 })); - writeIntBE(u72, &buf9, 0x123456789abcdef024); + writeIntBig(u72, &buf9, 0x123456789abcdef024); assert(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 })); - writeIntLE(u72, &buf9, 0xfedcba9876543210ec); + writeIntLittle(u72, &buf9, 0xfedcba9876543210ec); assert(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe })); - writeIntBE(i8, &buf1, -1); + writeIntBig(i8, &buf1, -1); assert(eql_slice_u8(buf1[0..], []u8{0xff})); - writeIntLE(i8, &buf1, -2); + writeIntLittle(i8, &buf1, -2); assert(eql_slice_u8(buf1[0..], []u8{0xfe})); - writeIntBE(i16, &buf2, -3); + writeIntBig(i16, &buf2, -3); assert(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd })); - writeIntLE(i16, &buf2, -4); + writeIntLittle(i16, &buf2, -4); assert(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff })); } @@ -735,12 +799,12 @@ fn testReadIntImpl() void { 0x56, 0x78, }; - assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678); - assert(readIntBE(u32, bytes) == 0x12345678); - assert(readIntBE(i32, bytes) == 0x12345678); - assert(readInt(bytes, u32, builtin.Endian.Little) == 0x78563412); - assert(readIntLE(u32, bytes) == 0x78563412); - assert(readIntLE(i32, bytes) == 0x78563412); + assert(readInt(u32, &bytes, builtin.Endian.Big) == 0x12345678); + assert(readIntBig(u32, &bytes) == 0x12345678); + assert(readIntBig(i32, &bytes) == 0x12345678); + assert(readInt(u32, &bytes, builtin.Endian.Little) == 0x78563412); + assert(readIntLittle(u32, &bytes) == 0x78563412); + assert(readIntLittle(i32, &bytes) == 0x78563412); } { const buf = []u8{ @@ -749,7 +813,7 @@ fn testReadIntImpl() void { 0x12, 0x34, }; - const answer = readInt(buf, u64, builtin.Endian.Big); + const answer = readInt(u32, &buf, builtin.Endian.Big); assert(answer == 0x00001234); } { @@ -759,7 +823,7 @@ fn testReadIntImpl() void { 0x00, 0x00, }; - const answer = readInt(buf, u64, builtin.Endian.Little); + const answer = readInt(u32, &buf, builtin.Endian.Little); assert(answer == 0x00003412); } { @@ -767,21 +831,33 @@ fn testReadIntImpl() void { 0xff, 0xfe, }; - assert(readIntBE(u16, bytes) == 0xfffe); - assert(readIntBE(i16, bytes) == -0x0002); - assert(readIntLE(u16, bytes) == 0xfeff); - assert(readIntLE(i16, bytes) == -0x0101); + assert(readIntBig(u16, &bytes) == 0xfffe); + assert(readIntBig(i16, &bytes) == -0x0002); + assert(readIntLittle(u16, &bytes) == 0xfeff); + assert(readIntLittle(i16, &bytes) == -0x0101); } } -test "testWriteInt" { +test "std.mem.writeIntSlice" { testWriteIntImpl(); comptime testWriteIntImpl(); } fn testWriteIntImpl() void { var bytes: [8]u8 = undefined; - writeInt(bytes[0..], u64(0x12345678CAFEBABE), builtin.Endian.Big); + writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Big); + assert(eql(u8, bytes, []u8{ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + })); + + writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Little); + assert(eql(u8, bytes, []u8{ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + })); + + writeIntSlice(u64, bytes[0..], 0x12345678CAFEBABE, builtin.Endian.Big); assert(eql(u8, bytes, []u8{ 0x12, 0x34, @@ -793,7 +869,7 @@ fn testWriteIntImpl() void { 0xBE, })); - writeInt(bytes[0..], u64(0xBEBAFECA78563412), builtin.Endian.Little); + writeIntSlice(u64, bytes[0..], 0xBEBAFECA78563412, builtin.Endian.Little); assert(eql(u8, bytes, []u8{ 0x12, 0x34, @@ -805,7 +881,7 @@ fn testWriteIntImpl() void { 0xBE, })); - writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big); + writeIntSlice(u32, bytes[0..], 0x12345678, builtin.Endian.Big); assert(eql(u8, bytes, []u8{ 0x00, 0x00, @@ -817,7 +893,7 @@ fn testWriteIntImpl() void { 0x78, })); - writeInt(bytes[0..], u32(0x78563412), builtin.Endian.Little); + writeIntSlice(u32, bytes[0..], 0x78563412, builtin.Endian.Little); assert(eql(u8, bytes, []u8{ 0x12, 0x34, @@ -829,7 +905,7 @@ fn testWriteIntImpl() void { 0x00, })); - writeInt(bytes[0..], u16(0x1234), builtin.Endian.Big); + writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Big); assert(eql(u8, bytes, []u8{ 0x00, 0x00, @@ -841,7 +917,7 @@ fn testWriteIntImpl() void { 0x34, })); - writeInt(bytes[0..], u16(0x1234), builtin.Endian.Little); + writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Little); assert(eql(u8, bytes, []u8{ 0x34, 0x12, @@ -939,29 +1015,52 @@ test "std.mem.rotate" { })); } -// TODO: When https://github.com/ziglang/zig/issues/649 is solved these can be done by -// endian-casting the pointer and then dereferencing +/// Converts a little-endian integer to host endianness. +pub fn littleToNative(comptime T: type, x: T) T { + return switch (builtin.endian) { + builtin.Endian.Little => x, + builtin.Endian.Big => @bswap(T, x), + }; +} -pub fn endianSwapIfLe(comptime T: type, x: T) T { - return endianSwapIf(builtin.Endian.Little, T, x); +/// Converts a big-endian integer to host endianness. +pub fn bigToNative(comptime T: type, x: T) T { + return switch (builtin.endian) { + builtin.Endian.Little => @bswap(T, x), + builtin.Endian.Big => x, + }; } -pub fn endianSwapIfBe(comptime T: type, x: T) T { - return endianSwapIf(builtin.Endian.Big, T, x); +/// Converts an integer from specified endianness to host endianness. +pub fn toNative(comptime T: type, x: T, endianness_of_x: builtin.Endian) T { + return switch (endianness_of_x) { + builtin.Endian.Little => littleToNative(T, x), + builtin.Endian.Big => bigToNative(T, x), + }; } -pub fn endianSwapIf(endian: builtin.Endian, comptime T: type, x: T) T { - return if (builtin.endian == endian) endianSwap(T, x) else x; +/// Converts an integer which has host endianness to the desired endianness. +pub fn nativeTo(comptime T: type, x: T, desired_endianness: builtin.Endian) T { + return switch (desired_endianness) { + builtin.Endian.Little => nativeToLittle(T, x), + builtin.Endian.Big => nativeToBig(T, x), + }; } -pub fn endianSwap(comptime T: type, x: T) T { - var buf: [@sizeOf(T)]u8 = undefined; - mem.writeInt(buf[0..], x, builtin.Endian.Little); - return mem.readInt(buf, T, builtin.Endian.Big); +/// Converts an integer which has host endianness to little endian. +pub fn nativeToLittle(comptime T: type, x: T) T { + return switch (builtin.endian) { + builtin.Endian.Little => x, + builtin.Endian.Big => @bswap(T, x), + }; } -test "std.mem.endianSwap" { - assert(endianSwap(u32, 0xDEADBEEF) == 0xEFBEADDE); +/// Converts an integer which has host endianness to big endian. +pub fn nativeToBig(comptime T: type, x: T) T { + return switch (builtin.endian) { + builtin.Endian.Little => @bswap(T, x), + builtin.Endian.Big => x, + }; } fn AsBytesReturnType(comptime P: type) type { diff --git a/std/net.zig b/std/net.zig index 006a9d4ac5..968c1f019f 100644 --- a/std/net.zig +++ b/std/net.zig @@ -23,7 +23,7 @@ pub const Address = struct { .os_addr = posix.sockaddr{ .in = posix.sockaddr_in{ .family = posix.AF_INET, - .port = std.mem.endianSwapIfLe(u16, _port), + .port = mem.nativeToBig(u16, _port), .addr = ip4, .zero = []u8{0} ** 8, }, @@ -37,7 +37,7 @@ pub const Address = struct { .os_addr = posix.sockaddr{ .in6 = posix.sockaddr_in6{ .family = posix.AF_INET6, - .port = std.mem.endianSwapIfLe(u16, _port), + .port = mem.nativeToBig(u16, _port), .flowinfo = 0, .addr = ip6.addr, .scope_id = ip6.scope_id, @@ -47,7 +47,7 @@ pub const Address = struct { } pub fn port(self: Address) u16 { - return std.mem.endianSwapIfLe(u16, self.os_addr.in.port); + return mem.bigToNative(u16, self.os_addr.in.port); } pub fn initPosix(addr: posix.sockaddr) Address { @@ -57,12 +57,12 @@ pub const Address = struct { pub fn format(self: *const Address, out_stream: var) !void { switch (self.os_addr.in.family) { posix.AF_INET => { - const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in.port); + const native_endian_port = mem.bigToNative(u16, self.os_addr.in.port); const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]); try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port); }, posix.AF_INET6 => { - const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in6.port); + const native_endian_port = mem.bigToNative(u16, self.os_addr.in6.port); try out_stream.print("[TODO render ip6 address]:{}", native_endian_port); }, else => try out_stream.write("(unrecognized address family)"), @@ -193,7 +193,7 @@ pub fn parseIp6(buf: []const u8) !Ip6Addr { } test "std.net.parseIp4" { - assert((try parseIp4("127.0.0.1")) == std.mem.endianSwapIfLe(u32, 0x7f000001)); + assert((try parseIp4("127.0.0.1")) == mem.bigToNative(u32, 0x7f000001)); testParseIp4Fail("256.0.0.1", error.Overflow); testParseIp4Fail("x.0.0.1", error.InvalidCharacter); diff --git a/std/os/child_process.zig b/std/os/child_process.zig index c8865bfacd..0aa896ff1b 100644 --- a/std/os/child_process.zig +++ b/std/os/child_process.zig @@ -807,10 +807,10 @@ const ErrInt = @IntType(false, @sizeOf(anyerror) * 8); fn writeIntFd(fd: i32, value: ErrInt) !void { const stream = &os.File.openHandle(fd).outStream().stream; - stream.writeIntNe(ErrInt, value) catch return error.SystemResources; + stream.writeIntNative(ErrInt, value) catch return error.SystemResources; } fn readIntFd(fd: i32) !ErrInt { const stream = &os.File.openHandle(fd).inStream().stream; - return stream.readIntNe(ErrInt) catch return error.SystemResources; + return stream.readIntNative(ErrInt) catch return error.SystemResources; } diff --git a/std/os/freebsd/x86_64.zig b/std/os/freebsd/x86_64.zig index 20a6710596..509075386f 100644 --- a/std/os/freebsd/x86_64.zig +++ b/std/os/freebsd/x86_64.zig @@ -98,12 +98,12 @@ pub nakedcc fn restore_rt() void { } pub const msghdr = extern struct { - msg_name: &u8, + msg_name: *u8, msg_namelen: socklen_t, - msg_iov: &iovec, + msg_iov: *iovec, msg_iovlen: i32, __pad1: i32, - msg_control: &u8, + msg_control: *u8, msg_controllen: socklen_t, __pad2: socklen_t, msg_flags: i32, diff --git a/std/pdb.zig b/std/pdb.zig index 2c5df3e597..0cfc6a6cda 100644 --- a/std/pdb.zig +++ b/std/pdb.zig @@ -508,11 +508,11 @@ const Msf = struct { allocator, ); - const stream_count = try self.directory.stream.readIntLe(u32); + const stream_count = try self.directory.stream.readIntLittle(u32); const stream_sizes = try allocator.alloc(u32, stream_count); for (stream_sizes) |*s| { - const size = try self.directory.stream.readIntLe(u32); + const size = try self.directory.stream.readIntLittle(u32); s.* = blockCountFromSize(size, superblock.BlockSize); } @@ -603,7 +603,7 @@ const MsfStream = struct { var i: u32 = 0; while (i < block_count) : (i += 1) { - stream.blocks[i] = try in.readIntLe(u32); + stream.blocks[i] = try in.readIntLittle(u32); } return stream; diff --git a/std/rand/index.zig b/std/rand/index.zig index 97101bc3b7..c335063e64 100644 --- a/std/rand/index.zig +++ b/std/rand/index.zig @@ -5,7 +5,7 @@ // ``` // var buf: [8]u8 = undefined; // try std.os.getRandomBytes(buf[0..]); -// const seed = mem.readIntLE(u64, buf[0..8]); +// const seed = mem.readIntSliceLittle(u64, buf[0..8]); // // var r = DefaultPrng.init(seed); // @@ -52,7 +52,7 @@ pub const Random = struct { // use LE instead of native endian for better portability maybe? // TODO: endian portability is pointless if the underlying prng isn't endian portable. // TODO: document the endian portability of this library. - const byte_aligned_result = mem.readIntLE(ByteAlignedT, rand_bytes); + const byte_aligned_result = mem.readIntSliceLittle(ByteAlignedT, rand_bytes); const unsigned_result = @truncate(UnsignedT, byte_aligned_result); return @bitCast(T, unsigned_result); } @@ -69,6 +69,7 @@ pub const Random = struct { return @intCast(T, limitRangeBiased(u64, r.int(u64), less_than)); } } + /// Returns an evenly distributed random unsigned integer `0 <= i < less_than`. /// This function assumes that the underlying ::fillFn produces evenly distributed values. /// Within this assumption, the runtime of this function is exponentially distributed. @@ -123,6 +124,7 @@ pub const Random = struct { } return r.uintLessThanBiased(T, at_most + 1); } + /// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`. /// See ::uintLessThan, which this function uses in most cases, /// for commentary on the runtime of this function. @@ -151,6 +153,7 @@ pub const Random = struct { return at_least + r.uintLessThanBiased(T, less_than - at_least); } } + /// Returns an evenly distributed random integer `at_least <= i < less_than`. /// See ::uintLessThan, which this function uses in most cases, /// for commentary on the runtime of this function. @@ -185,6 +188,7 @@ pub const Random = struct { return at_least + r.uintAtMostBiased(T, at_most - at_least); } } + /// Returns an evenly distributed random integer `at_least <= i <= at_most`. /// See ::uintLessThan, which this function uses in most cases, /// for commentary on the runtime of this function. diff --git a/std/unicode.zig b/std/unicode.zig index fcb748401f..2e542bcb19 100644 --- a/std/unicode.zig +++ b/std/unicode.zig @@ -249,12 +249,12 @@ pub const Utf16LeIterator = struct { pub fn nextCodepoint(it: *Utf16LeIterator) !?u32 { assert(it.i <= it.bytes.len); if (it.i == it.bytes.len) return null; - const c0: u32 = mem.readIntLE(u16, it.bytes[it.i .. it.i + 2]); + const c0: u32 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]); if (c0 & ~u32(0x03ff) == 0xd800) { // surrogate pair it.i += 2; if (it.i >= it.bytes.len) return error.DanglingSurrogateHalf; - const c1: u32 = mem.readIntLE(u16, it.bytes[it.i .. it.i + 2]); + const c1: u32 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]); if (c1 & ~u32(0x03ff) != 0xdc00) return error.ExpectedSecondSurrogateHalf; it.i += 2; return 0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff)); @@ -510,46 +510,46 @@ test "utf16leToUtf8" { const utf16le_as_bytes = @sliceToBytes(utf16le[0..]); { - mem.writeInt(utf16le_as_bytes[0..], u16('A'), builtin.Endian.Little); - mem.writeInt(utf16le_as_bytes[2..], u16('a'), builtin.Endian.Little); + mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 'A'); + mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 'a'); const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); assert(mem.eql(u8, utf8, "Aa")); } { - mem.writeInt(utf16le_as_bytes[0..], u16(0x80), builtin.Endian.Little); - mem.writeInt(utf16le_as_bytes[2..], u16(0xffff), builtin.Endian.Little); + mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0x80); + mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xffff); const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); assert(mem.eql(u8, utf8, "\xc2\x80" ++ "\xef\xbf\xbf")); } { // the values just outside the surrogate half range - mem.writeInt(utf16le_as_bytes[0..], u16(0xd7ff), builtin.Endian.Little); - mem.writeInt(utf16le_as_bytes[2..], u16(0xe000), builtin.Endian.Little); + mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd7ff); + mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xe000); const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); assert(mem.eql(u8, utf8, "\xed\x9f\xbf" ++ "\xee\x80\x80")); } { // smallest surrogate pair - mem.writeInt(utf16le_as_bytes[0..], u16(0xd800), builtin.Endian.Little); - mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little); + mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd800); + mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00); const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); assert(mem.eql(u8, utf8, "\xf0\x90\x80\x80")); } { // largest surrogate pair - mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little); - mem.writeInt(utf16le_as_bytes[2..], u16(0xdfff), builtin.Endian.Little); + mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff); + mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdfff); const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); assert(mem.eql(u8, utf8, "\xf4\x8f\xbf\xbf")); } { - mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little); - mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little); + mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff); + mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00); const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le); assert(mem.eql(u8, utf8, "\xf4\x8f\xb0\x80")); } @@ -583,7 +583,7 @@ pub fn utf8ToUtf16Le(utf16le: []u16, utf8: []const u8) !usize { while (it.nextCodepoint()) |codepoint| { if (end_index == utf16le_as_bytes.len) return (end_index / 2) + 1; // TODO surrogate pairs - mem.writeInt(utf16le_as_bytes[end_index..], @intCast(u16, codepoint), builtin.Endian.Little); + mem.writeIntSliceLittle(u16, utf16le_as_bytes[end_index..], @intCast(u16, codepoint)); end_index += 2; } return end_index / 2; diff --git a/test/behavior.zig b/test/behavior.zig index 1d031343d6..499c20ee20 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -8,6 +8,7 @@ comptime { _ = @import("cases/atomics.zig"); _ = @import("cases/bitcast.zig"); _ = @import("cases/bool.zig"); + _ = @import("cases/bswap.zig"); _ = @import("cases/bugs/1076.zig"); _ = @import("cases/bugs/1111.zig"); _ = @import("cases/bugs/1277.zig"); @@ -64,6 +65,7 @@ comptime { _ = @import("cases/switch_prong_implicit_cast.zig"); _ = @import("cases/syntax.zig"); _ = @import("cases/this.zig"); + _ = @import("cases/truncate.zig"); _ = @import("cases/try.zig"); _ = @import("cases/type_info.zig"); _ = @import("cases/undefined.zig"); diff --git a/test/cases/bswap.zig b/test/cases/bswap.zig new file mode 100644 index 0000000000..57993077e1 --- /dev/null +++ b/test/cases/bswap.zig @@ -0,0 +1,32 @@ +const std = @import("std"); +const assert = std.debug.assert; + +test "@bswap" { + comptime testByteSwap(); + testByteSwap(); +} + +fn testByteSwap() void { + assert(@bswap(u0, 0) == 0); + assert(@bswap(u8, 0x12) == 0x12); + assert(@bswap(u16, 0x1234) == 0x3412); + assert(@bswap(u24, 0x123456) == 0x563412); + assert(@bswap(u32, 0x12345678) == 0x78563412); + assert(@bswap(u40, 0x123456789a) == 0x9a78563412); + assert(@bswap(u48, 0x123456789abc) == 0xbc9a78563412); + assert(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412); + assert(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412); + assert(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412); + + assert(@bswap(i0, 0) == 0); + assert(@bswap(i8, -50) == -50); + assert(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412))); + assert(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412))); + assert(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412))); + assert(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412))); + assert(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412))); + assert(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412))); + assert(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412))); + assert(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == + @bitCast(i128, u128(0x8171615141312111f1debc9a78563412))); +} diff --git a/test/cases/truncate.zig b/test/cases/truncate.zig new file mode 100644 index 0000000000..02b5085ccd --- /dev/null +++ b/test/cases/truncate.zig @@ -0,0 +1,8 @@ +const std = @import("std"); +const assert = std.debug.assert; + +test "truncate u0 to larger integer allowed and has comptime known result" { + var x: u0 = 0; + const y = @truncate(u8, x); + comptime assert(y == 0); +} diff --git a/test/compile_errors.zig b/test/compile_errors.zig index be839f0550..ee3741ee6b 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1,6 +1,18 @@ const tests = @import("tests.zig"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.add( + "reading past end of pointer casted array", + \\comptime { + \\ const array = "aoeu"; + \\ const slice = array[2..]; + \\ const int_ptr = @ptrCast(*const u24, slice.ptr); + \\ const deref = int_ptr.*; + \\} + , + ".tmp_source.zig:5:26: error: attempt to read 3 bytes from [4]u8 at index 2 which is 2 bytes", + ); + cases.add( "error note for function parameter incompatibility", \\fn do_the_thing(func: fn (arg: i32) void) void {} -- cgit v1.2.3 From d770333827549e5dcbb727c7f434eaac9dd433d2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 12 Dec 2018 22:28:15 -0500 Subject: freebsd: fix os_self_exe_path function and update std lib --- src/os.cpp | 2 +- std/os/freebsd/index.zig | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/os.cpp b/src/os.cpp index eba95b9f2f..2f0379c09b 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -1456,7 +1456,7 @@ Error os_self_exe_path(Buf *out_path) { if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) { return ErrorUnexpected; } - buf_resize(out_path, cb); + buf_resize(out_path, cb - 1); return ErrorNone; #endif return ErrorFileNotFound; diff --git a/std/os/freebsd/index.zig b/std/os/freebsd/index.zig index 75389fc403..9fbeaf1dc1 100644 --- a/std/os/freebsd/index.zig +++ b/std/os/freebsd/index.zig @@ -9,6 +9,7 @@ pub use @import("errno.zig"); const std = @import("../../index.zig"); const c = std.c; +const maxInt = std.math.maxInt; pub const Kevent = c.Kevent; pub const PATH_MAX = 1024; @@ -22,7 +23,7 @@ pub const PROT_READ = 1; pub const PROT_WRITE = 2; pub const PROT_EXEC = 4; -pub const MAP_FAILED = @maxValue(usize); +pub const MAP_FAILED = maxInt(usize); pub const MAP_SHARED = 0x0001; pub const MAP_PRIVATE = 0x0002; pub const MAP_FIXED = 0x0010; @@ -700,7 +701,7 @@ pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigacti const NSIG = 65; const sigset_t = [128 / @sizeOf(usize)]usize; -const all_mask = []usize{@maxValue(usize)}; +const all_mask = []usize{maxInt(usize)}; const app_mask = []usize{0xfffffffc7fffffff}; /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. @@ -711,7 +712,7 @@ pub const Sigaction = struct { flags: u32, }; -pub const SIG_ERR = @intToPtr(extern fn (i32) void, @maxValue(usize)); +pub const SIG_ERR = @intToPtr(extern fn (i32) void, maxInt(usize)); pub const SIG_DFL = @intToPtr(extern fn (i32) void, 0); pub const SIG_IGN = @intToPtr(extern fn (i32) void, 1); pub const empty_sigset = []usize{0} ** sigset_t.len; -- cgit v1.2.3 From 757d0665ae951bdd5cb754adbe433488f0bea8c4 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 16 Dec 2018 12:03:37 -0500 Subject: implement comptime pointer cast closes #955 closes #1835 --- src/ir.cpp | 25 ++++++++++++++++++++++--- std/mem.zig | 9 +++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ir.cpp b/src/ir.cpp index dc87f040bc..ef7ad221cf 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -166,6 +166,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, ZigType *dest_type, IrInstruction *dest_type_src); static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed); +static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs); static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { assert(get_src_ptr_type(const_val->type) != nullptr); @@ -7364,15 +7365,31 @@ static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction, return ir_add_error_node(ira, source_instruction->source_node, msg); } +// This function takes a comptime ptr and makes the child const value conform to the type +// described by the pointer. +static Error eval_comptime_ptr_reinterpret(IrAnalyze *ira, AstNode *source_node, ConstExprValue *ptr_val) { + Error err; + assert(ptr_val->type->id == ZigTypeIdPointer); + ConstExprValue tmp = {}; + tmp.special = ConstValSpecialStatic; + tmp.type = ptr_val->type->data.pointer.child_type; + if ((err = ir_read_const_ptr(ira, source_node, &tmp, ptr_val))) + return err; + ConstExprValue *child_val = const_ptr_pointee_unchecked(ira->codegen, ptr_val); + copy_const_val(child_val, &tmp, false); + return ErrorNone; +} + static ConstExprValue *ir_const_ptr_pointee(IrAnalyze *ira, ConstExprValue *const_val, AstNode *source_node) { + Error err; ConstExprValue *val = const_ptr_pointee_unchecked(ira->codegen, const_val); assert(val != nullptr); assert(const_val->type->id == ZigTypeIdPointer); ZigType *expected_type = const_val->type->data.pointer.child_type; if (!types_have_same_zig_comptime_repr(val->type, expected_type)) { - ir_add_error_node(ira, source_node, - buf_sprintf("TODO handle comptime reinterpreted pointer. See https://github.com/ziglang/zig/issues/955")); - return nullptr; + if ((err = eval_comptime_ptr_reinterpret(ira, source_node, const_val))) + return nullptr; + return const_ptr_pointee_unchecked(ira->codegen, const_val); } return val; } @@ -19990,6 +20007,8 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct } static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) { + if (val->special == ConstValSpecialUndef) + val->special = ConstValSpecialStatic; assert(val->special == ConstValSpecialStatic); switch (val->type->id) { case ZigTypeIdInvalid: diff --git a/std/mem.zig b/std/mem.zig index b9772acd6d..0e51601eb2 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -510,6 +510,15 @@ pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) return readInt(T, @ptrCast(*const [@sizeOf(T)]u8, bytes.ptr), endian); } +test "comptime read/write int" { + comptime { + var bytes: [2]u8 = undefined; + std.mem.writeIntLittle(u16, &bytes, 0x1234); + const result = std.mem.readIntBig(u16, &bytes); + std.debug.assert(result == 0x3412); + } +} + test "readIntBig and readIntLittle" { assert(readIntSliceBig(u0, []u8{}) == 0x0); assert(readIntSliceLittle(u0, []u8{}) == 0x0); -- cgit v1.2.3 From f75262b79f0656ebfac7fb5bd2d6d8e8cce01258 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 17 Dec 2018 11:05:50 -0500 Subject: fix comptime pointer reinterpretation array index offset closes #1835 --- src/ir.cpp | 9 ++++----- std/mem.zig | 6 ++++++ test/behavior.zig | 1 + test/cases/ptrcast.zig | 17 +++++++++++++++++ 4 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 test/cases/ptrcast.zig (limited to 'src') diff --git a/src/ir.cpp b/src/ir.cpp index ef7ad221cf..09a9fceabe 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -13744,20 +13744,19 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, if (array_val->data.x_array.special != ConstArraySpecialNone) zig_panic("TODO"); size_t elem_size = src_size; - src_size = elem_size * - (array_val->type->data.array.len - ptr_val->data.x_ptr.data.base_array.elem_index); + size_t elem_index = ptr_val->data.x_ptr.data.base_array.elem_index; + src_size = elem_size * (array_val->type->data.array.len - elem_index); if (dst_size > src_size) { ir_add_error_node(ira, source_node, buf_sprintf("attempt to read %zu bytes from %s at index %" ZIG_PRI_usize " which is %zu bytes", - dst_size, buf_ptr(&array_val->type->name), ptr_val->data.x_ptr.data.base_array.elem_index, - src_size)); + dst_size, buf_ptr(&array_val->type->name), elem_index, src_size)); return ErrorSemanticAnalyzeFail; } size_t elem_count = (dst_size % elem_size == 0) ? (dst_size / elem_size) : (dst_size / elem_size + 1); Buf buf = BUF_INIT; buf_resize(&buf, elem_count * elem_size); for (size_t i = 0; i < elem_count; i += 1) { - ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[i]; + ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[elem_index + i]; buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val); } buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val); diff --git a/std/mem.zig b/std/mem.zig index 0e51601eb2..fb5f6fd5da 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -517,6 +517,12 @@ test "comptime read/write int" { const result = std.mem.readIntBig(u16, &bytes); std.debug.assert(result == 0x3412); } + comptime { + var bytes: [2]u8 = undefined; + std.mem.writeIntBig(u16, &bytes, 0x1234); + const result = std.mem.readIntLittle(u16, &bytes); + std.debug.assert(result == 0x3412); + } } test "readIntBig and readIntLittle" { diff --git a/test/behavior.zig b/test/behavior.zig index 499c20ee20..e32063dec8 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -52,6 +52,7 @@ comptime { _ = @import("cases/optional.zig"); _ = @import("cases/pointers.zig"); _ = @import("cases/popcount.zig"); + _ = @import("cases/ptrcast.zig"); _ = @import("cases/pub_enum/index.zig"); _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig"); _ = @import("cases/reflection.zig"); diff --git a/test/cases/ptrcast.zig b/test/cases/ptrcast.zig new file mode 100644 index 0000000000..071087c5c4 --- /dev/null +++ b/test/cases/ptrcast.zig @@ -0,0 +1,17 @@ +const builtin = @import("builtin"); +const std = @import("std"); +const assertOrPanic = std.debug.assertOrPanic; + +test "reinterpret bytes as integer with nonzero offset" { + testReinterpretBytesAsInteger(); + comptime testReinterpretBytesAsInteger(); +} + +fn testReinterpretBytesAsInteger() void { + const bytes = "\x12\x34\x56\x78\xab"; + const expected = switch (builtin.endian) { + builtin.Endian.Little => 0xab785634, + builtin.Endian.Big => 0x345678ab, + }; + assertOrPanic(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected); +} -- cgit v1.2.3 From e077a446566b0aa77a121f9554f3cb355899653a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 18 Dec 2018 15:48:26 -0500 Subject: ir: delete dead code --- src/all_types.hpp | 1 - src/codegen.cpp | 26 -------------------------- src/ir.cpp | 3 +-- 3 files changed, 1 insertion(+), 29 deletions(-) (limited to 'src') diff --git a/src/all_types.hpp b/src/all_types.hpp index 83b7e8495f..11304e536d 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -605,7 +605,6 @@ enum CastOp { CastOpFloatToInt, CastOpBoolToInt, CastOpResizeSlice, - CastOpBytesToSlice, CastOpNumLitToConcrete, CastOpErrSet, CastOpBitCast, diff --git a/src/codegen.cpp b/src/codegen.cpp index 08dd11800a..e37703d5f0 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2882,32 +2882,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, gen_store_untyped(g, new_len, dest_len_ptr, 0, false); - return cast_instruction->tmp_ptr; - } - case CastOpBytesToSlice: - { - assert(cast_instruction->tmp_ptr); - assert(wanted_type->id == ZigTypeIdStruct); - assert(wanted_type->data.structure.is_slice); - assert(actual_type->id == ZigTypeIdArray); - - ZigType *wanted_pointer_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry; - ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type; - - - size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index; - LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, - (unsigned)wanted_ptr_index, ""); - LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, expr_val, wanted_pointer_type->type_ref, ""); - gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false); - - size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index; - LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, - (unsigned)wanted_len_index, ""); - LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, - actual_type->data.array.len / type_size(g, wanted_child_type), false); - gen_store_untyped(g, len_val, len_ptr, 0, false); - return cast_instruction->tmp_ptr; } case CastOpIntToFloat: diff --git a/src/ir.cpp b/src/ir.cpp index 09a9fceabe..76dd6c6391 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -9339,7 +9339,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ const_val->type = new_type; break; case CastOpResizeSlice: - case CastOpBytesToSlice: // can't do it zig_unreachable(); case CastOpIntToFloat: @@ -9396,7 +9395,7 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst ZigType *wanted_type, CastOp cast_op, bool need_alloca) { if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) && - cast_op != CastOpResizeSlice && cast_op != CastOpBytesToSlice) + cast_op != CastOpResizeSlice) { IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, source_instr->source_node, wanted_type); -- cgit v1.2.3 From 45e72c0b3944b2fa6d06c7018e9648b4ae60006a Mon Sep 17 00:00:00 2001 From: Jimmi Holst Christensen Date: Wed, 19 Dec 2018 15:39:18 +0100 Subject: Fixed intToPtr to fn type when the address is hardcoded (#1842) * Fixed intToPtr to fn type * Added test * Import inttoptr.zig in behavior.zig --- src/ir.cpp | 1 + test/behavior.zig | 1 + test/cases/inttoptr.zig | 13 +++++++++++++ 3 files changed, 15 insertions(+) create mode 100644 test/cases/inttoptr.zig (limited to 'src') diff --git a/src/ir.cpp b/src/ir.cpp index 76dd6c6391..028582f87f 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -12495,6 +12495,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct case ReqCompTimeNo: if (casted_init_value->value.special == ConstValSpecialStatic && casted_init_value->value.type->id == ZigTypeIdFn && + casted_init_value->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr && casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways) { var_class_requires_const = true; diff --git a/test/behavior.zig b/test/behavior.zig index e32063dec8..8090359772 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -42,6 +42,7 @@ comptime { _ = @import("cases/if.zig"); _ = @import("cases/import.zig"); _ = @import("cases/incomplete_struct_param_tld.zig"); + _ = @import("cases/inttoptr.zig"); _ = @import("cases/ir_block_deps.zig"); _ = @import("cases/math.zig"); _ = @import("cases/merge_error_sets.zig"); diff --git a/test/cases/inttoptr.zig b/test/cases/inttoptr.zig new file mode 100644 index 0000000000..6695352383 --- /dev/null +++ b/test/cases/inttoptr.zig @@ -0,0 +1,13 @@ +const builtin = @import("builtin"); +const std = @import("std"); +const assertOrPanic = std.debug.assertOrPanic; + +test "casting random address to function pointer" { + randomAddressToFunction(); + comptime randomAddressToFunction(); +} + +fn randomAddressToFunction() void { + var addr: usize = 0xdeadbeef; + var ptr = @intToPtr(fn () void, addr); +} -- cgit v1.2.3 From 39567e8b50e9026288bb1323d84f481740bd0de7 Mon Sep 17 00:00:00 2001 From: kristopher tate Date: Thu, 20 Dec 2018 22:47:44 +0900 Subject: src/analyze.cpp: support alignOf(struct T) aligned member inside struct T; ref: ziglang/zig#1832 --- src/analyze.cpp | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/analyze.cpp b/src/analyze.cpp index 46686ce772..e209822132 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2686,13 +2686,22 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { } size_t field_count = struct_type->data.structure.src_field_count; + bool self_resolving = false; for (size_t i = 0; i < field_count; i += 1) { TypeStructField *field = &struct_type->data.structure.fields[i]; - // If this assertion trips, look up the call stack. Probably something is - // calling type_resolve with ResolveStatusAlignmentKnown when it should only - // be resolving ResolveStatusZeroBitsKnown - assert(field->type_entry != nullptr); + // If we have no type_entry for the field, assume that we are in the + // midst of resolving this struct. We further assume that since the + // resolved alignment of the other fields of this struct is ultimately + // equal to the resolved alignment of this struct, we can safely ignore. + // + // If this struct is used down-stream in aligning a sub-struct, ignoring + // this struct in the context of a sub struct has the same effect since + // the other fields will be calculated and bubble-up. + if (nullptr == field->type_entry) { + self_resolving = true; + continue; + } if (type_is_invalid(field->type_entry)) { struct_type->data.structure.resolve_status = ResolveStatusInvalid; @@ -2723,6 +2732,14 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { return ErrorSemanticAnalyzeFail; } + if ( self_resolving + && field_count > 0 + ) { + // If we get here it's due to self-referencing this struct before it has been fully resolved. + // In this case, set alignment to target pointer default. + struct_type->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, + LLVMPointerType(LLVMInt8Type(), 0)); + } struct_type->data.structure.resolve_status = ResolveStatusAlignmentKnown; return ErrorNone; } -- cgit v1.2.3 From 0f54194e6ab2b0cbdc798b84cc4213a07ed1d0c1 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 20 Dec 2018 12:36:15 -0500 Subject: fixups --- src/analyze.cpp | 72 ++++++++++++++++++++++++++------------------------------- 1 file changed, 33 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/analyze.cpp b/src/analyze.cpp index e209822132..9c24f3cc8d 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2681,48 +2681,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { assert(decl_node->type == NodeTypeContainerDecl); assert(struct_type->di_type); + size_t field_count = struct_type->data.structure.src_field_count; if (struct_type->data.structure.layout == ContainerLayoutPacked) { struct_type->data.structure.abi_alignment = 1; - } - - size_t field_count = struct_type->data.structure.src_field_count; - bool self_resolving = false; - for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; - - // If we have no type_entry for the field, assume that we are in the - // midst of resolving this struct. We further assume that since the - // resolved alignment of the other fields of this struct is ultimately - // equal to the resolved alignment of this struct, we can safely ignore. - // - // If this struct is used down-stream in aligning a sub-struct, ignoring - // this struct in the context of a sub struct has the same effect since - // the other fields will be calculated and bubble-up. - if (nullptr == field->type_entry) { - self_resolving = true; - continue; - } - - if (type_is_invalid(field->type_entry)) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - break; + for (size_t i = 0; i < field_count; i += 1) { + TypeStructField *field = &struct_type->data.structure.fields[i]; + if (field->type_entry != nullptr && type_is_invalid(field->type_entry)) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + break; + } } + } else for (size_t i = 0; i < field_count; i += 1) { + TypeStructField *field = &struct_type->data.structure.fields[i]; + uint32_t this_field_align; + + // TODO If we have no type_entry for the field, we've already failed to + // compile the program correctly. This stage1 compiler needs a deeper + // reworking to make this correct, or we can ignore the problem + // and make sure it is fixed in stage2. This workaround is for when + // there is a false positive of a dependency loop, of alignment depending + // on itself. When this false positive happens we assume a pointer-aligned + // field, which is usually fine but could be incorrectly over-aligned or + // even under-aligned. See https://github.com/ziglang/zig/issues/1512 + if (field->type_entry == nullptr) { + this_field_align = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0)); + } else { + if (type_is_invalid(field->type_entry)) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + break; + } - if (!type_has_bits(field->type_entry)) - continue; + if (!type_has_bits(field->type_entry)) + continue; - // alignment of structs is the alignment of the most-aligned field - if (struct_type->data.structure.layout != ContainerLayoutPacked) { if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) { struct_type->data.structure.resolve_status = ResolveStatusInvalid; break; } - uint32_t this_field_align = get_abi_alignment(g, field->type_entry); + this_field_align = get_abi_alignment(g, field->type_entry); assert(this_field_align != 0); - if (this_field_align > struct_type->data.structure.abi_alignment) { - struct_type->data.structure.abi_alignment = this_field_align; - } + } + // alignment of structs is the alignment of the most-aligned field + if (this_field_align > struct_type->data.structure.abi_alignment) { + struct_type->data.structure.abi_alignment = this_field_align; } } @@ -2732,14 +2734,6 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { return ErrorSemanticAnalyzeFail; } - if ( self_resolving - && field_count > 0 - ) { - // If we get here it's due to self-referencing this struct before it has been fully resolved. - // In this case, set alignment to target pointer default. - struct_type->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, - LLVMPointerType(LLVMInt8Type(), 0)); - } struct_type->data.structure.resolve_status = ResolveStatusAlignmentKnown; return ErrorNone; } -- cgit v1.2.3 From 56fedbb52423eba6d2088a1e2c8b94e0c4eb85ac Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 20 Dec 2018 19:56:24 -0500 Subject: translate-c: --verbose-cimport prints clang command --- src/translate_c.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/translate_c.cpp b/src/translate_c.cpp index 10f2124eb6..f6bc9cd683 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -4776,6 +4776,14 @@ Error parse_h_file(ImportTableEntry *import, ZigList *errors, const clang_argv.append(target_file); + if (codegen->verbose_cimport) { + fprintf(stderr, "clang"); + for (size_t i = 0; i < clang_argv.length; i += 1) { + fprintf(stderr, " %s", clang_argv.at(i)); + } + fprintf(stderr, "\n"); + } + // to make the [start...end] argument work clang_argv.append(nullptr); -- cgit v1.2.3 From 218a4d4b30f320797121ad9900d48743da77a1b3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 22 Dec 2018 23:06:30 -0500 Subject: comptime: ability to @ptrCast to an extern struct and read fields --- src/ir.cpp | 64 ++++++++++++++++++++++++++++++++++++++------------ test/cases/ptrcast.zig | 19 +++++++++++++++ 2 files changed, 68 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/ir.cpp b/src/ir.cpp index 028582f87f..83960f2eee 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -159,7 +159,7 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval); static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align); static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align); -static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); +static Error buf_read_value_bytes(IrAnalyze *ira, AstNode *source_node, uint8_t *buf, ConstExprValue *val); static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, ConstExprValue *out_val, ConstExprValue *ptr_val); @@ -13725,7 +13725,8 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, Buf buf = BUF_INIT; buf_resize(&buf, src_size); buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee); - buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val); + if ((err = buf_read_value_bytes(ira, source_node, (uint8_t*)buf_ptr(&buf), out_val))) + return err; return ErrorNone; } @@ -13759,7 +13760,8 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[elem_index + i]; buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val); } - buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val); + if ((err = buf_read_value_bytes(ira, source_node, (uint8_t*)buf_ptr(&buf), out_val))) + return err; return ErrorNone; } case ConstPtrSpecialBaseStruct: @@ -20077,7 +20079,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue zig_unreachable(); } -static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) { +static Error buf_read_value_bytes(IrAnalyze *ira, AstNode *source_node, uint8_t *buf, ConstExprValue *val) { + Error err; assert(val->special == ConstValSpecialStatic); switch (val->type->id) { case ZigTypeIdInvalid: @@ -20094,30 +20097,60 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue case ZigTypeIdPromise: zig_unreachable(); case ZigTypeIdVoid: - return; + return ErrorNone; case ZigTypeIdBool: val->data.x_bool = (buf[0] != 0); - return; + return ErrorNone; case ZigTypeIdInt: bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count, - codegen->is_big_endian, val->type->data.integral.is_signed); - return; + ira->codegen->is_big_endian, val->type->data.integral.is_signed); + return ErrorNone; case ZigTypeIdFloat: - float_read_ieee597(val, buf, codegen->is_big_endian); - return; + float_read_ieee597(val, buf, ira->codegen->is_big_endian); + return ErrorNone; case ZigTypeIdPointer: { val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr; BigInt bn; - bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count, - codegen->is_big_endian, false); + bigint_read_twos_complement(&bn, buf, ira->codegen->builtin_types.entry_usize->data.integral.bit_count, + ira->codegen->is_big_endian, false); val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn); - return; + return ErrorNone; } case ZigTypeIdArray: zig_panic("TODO buf_read_value_bytes array type"); case ZigTypeIdStruct: - zig_panic("TODO buf_read_value_bytes struct type"); + switch (val->type->data.structure.layout) { + case ContainerLayoutAuto: { + ErrorMsg *msg = ir_add_error_node(ira, source_node, + buf_sprintf("non-extern, non-packed struct '%s' cannot have its bytes reinterpreted", + buf_ptr(&val->type->name))); + add_error_note(ira->codegen, msg, val->type->data.structure.decl_node, + buf_sprintf("declared here")); + return ErrorSemanticAnalyzeFail; + } + case ContainerLayoutExtern: { + size_t src_field_count = val->type->data.structure.src_field_count; + val->data.x_struct.fields = create_const_vals(src_field_count); + for (size_t field_i = 0; field_i < src_field_count; field_i += 1) { + ConstExprValue *field_val = &val->data.x_struct.fields[field_i]; + field_val->special = ConstValSpecialStatic; + TypeStructField *type_field = &val->type->data.structure.fields[field_i]; + field_val->type = type_field->type_entry; + if (type_field->gen_index == SIZE_MAX) + continue; + size_t offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, val->type->type_ref, + type_field->gen_index); + uint8_t *new_buf = buf + offset; + if ((err = buf_read_value_bytes(ira, source_node, new_buf, field_val))) + return err; + } + return ErrorNone; + } + case ContainerLayoutPacked: + zig_panic("TODO buf_read_value_bytes packed struct"); + } + zig_unreachable(); case ZigTypeIdOptional: zig_panic("TODO buf_read_value_bytes maybe type"); case ZigTypeIdErrorUnion: @@ -20220,7 +20253,8 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct IrInstruction *result = ir_const(ira, &instruction->base, dest_type); uint8_t *buf = allocate_nonzero(src_size_bytes); buf_write_value_bytes(ira->codegen, buf, val); - buf_read_value_bytes(ira->codegen, buf, &result->value); + if ((err = buf_read_value_bytes(ira, instruction->base.source_node, buf, &result->value))) + return ira->codegen->invalid_instruction; return result; } diff --git a/test/cases/ptrcast.zig b/test/cases/ptrcast.zig index 071087c5c4..6f0e6e5946 100644 --- a/test/cases/ptrcast.zig +++ b/test/cases/ptrcast.zig @@ -15,3 +15,22 @@ fn testReinterpretBytesAsInteger() void { }; assertOrPanic(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected); } + +test "reinterpret bytes of an array into an extern struct" { + testReinterpretBytesAsExternStruct(); + comptime testReinterpretBytesAsExternStruct(); +} + +fn testReinterpretBytesAsExternStruct() void { + var bytes align(2) = []u8{ 1, 2, 3, 4, 5, 6 }; + + const S = extern struct { + a: u8, + b: u16, + c: u8, + }; + + var ptr = @ptrCast(*const S, &bytes); + var val = ptr.c; + assertOrPanic(val == 5); +} -- cgit v1.2.3