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