From b3a3e2094e8b88e40eecf65d29f39af10442bde4 Mon Sep 17 00:00:00 2001
From: Jay Weisskopf
Date: Fri, 15 Jun 2018 14:06:56 -0400
Subject: [PATCH 01/28] Make `zig version` compliant with SemVer (#1113)
The git revision is build metadata and should be appended with a plus sign.
https://semver.org/#spec-item-10
---
CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cfa0146bb15a6fc0d4f12a81fcadd6ab32b01121..dd4770ad7205fee41800c3b1cac37eee02b9be00 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -30,7 +30,7 @@ if(GIT_EXE)
message("WARNING: Tag does not match configured Zig version")
endif()
else()
- set(ZIG_VERSION "${ZIG_VERSION_MAJOR}.${ZIG_VERSION_MINOR}.${ZIG_VERSION_PATCH}.${ZIG_GIT_REV}")
+ set(ZIG_VERSION "${ZIG_VERSION}+${ZIG_GIT_REV}")
endif()
endif()
message("Configuring zig version ${ZIG_VERSION}")
--
2.54.0
From 48de57d8248d9203b44d28d7749b5d7c1a00deba Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 16 Jun 2018 17:01:23 -0400
Subject: [PATCH 02/28] add basic std lib code for loading dynamic libraries
this is going to only work for very basic libraries;
I plan to slowly add more features over time to support more
complicated libraries
---
CMakeLists.txt | 1 +
src/codegen.cpp | 12 +-
src/link.cpp | 4 +-
std/dynamic_library.zig | 161 ++++++++++++++++++
std/elf.zig | 15 ++
std/index.zig | 1 +
std/io.zig | 7 +-
std/math/index.zig | 11 ++
std/os/file.zig | 11 +-
std/os/index.zig | 14 ++
test/build_examples.zig | 5 +
test/standalone/load_dynamic_library/add.zig | 3 +
.../standalone/load_dynamic_library/build.zig | 22 +++
test/standalone/load_dynamic_library/main.zig | 17 ++
14 files changed, 265 insertions(+), 19 deletions(-)
create mode 100644 std/dynamic_library.zig
create mode 100644 test/standalone/load_dynamic_library/add.zig
create mode 100644 test/standalone/load_dynamic_library/build.zig
create mode 100644 test/standalone/load_dynamic_library/main.zig
diff --git a/CMakeLists.txt b/CMakeLists.txt
index dd4770ad7205fee41800c3b1cac37eee02b9be00..e502901bd280ee77bfaca3ec0718e6d34b5c09c2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -438,6 +438,7 @@ set(ZIG_STD_FILES
"debug/failing_allocator.zig"
"debug/index.zig"
"dwarf.zig"
+ "dynamic_library.zig"
"elf.zig"
"empty.zig"
"event.zig"
diff --git a/src/codegen.cpp b/src/codegen.cpp
index d05bcba2ce89e2b63ca37dc14f25cc8862aa0883..fedfcfa7440f0cd683884d9872bd60072e6a1555 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -6768,7 +6768,7 @@ static void define_builtin_compile_vars(CodeGen *g) {
int err;
Buf *abs_full_path = buf_alloc();
if ((err = os_path_real(builtin_zig_path, abs_full_path))) {
- fprintf(stderr, "unable to open '%s': %s", buf_ptr(builtin_zig_path), err_str(err));
+ fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(builtin_zig_path), err_str(err));
exit(1);
}
@@ -6936,11 +6936,11 @@ static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package
Buf *abs_full_path = buf_alloc();
int err;
if ((err = os_path_real(&path_to_code_src, abs_full_path))) {
- zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err));
+ zig_panic("unable to open '%s': %s\n", buf_ptr(&path_to_code_src), err_str(err));
}
Buf *import_code = buf_alloc();
if ((err = os_fetch_file_path(abs_full_path, import_code, false))) {
- zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err));
+ zig_panic("unable to open '%s': %s\n", buf_ptr(&path_to_code_src), err_str(err));
}
return add_source_file(g, package, abs_full_path, import_code);
@@ -7024,13 +7024,13 @@ static void gen_root_source(CodeGen *g) {
Buf *abs_full_path = buf_alloc();
int err;
if ((err = os_path_real(rel_full_path, abs_full_path))) {
- fprintf(stderr, "unable to open '%s': %s", buf_ptr(rel_full_path), err_str(err));
+ fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(rel_full_path), err_str(err));
exit(1);
}
Buf *source_code = buf_alloc();
if ((err = os_fetch_file_path(rel_full_path, source_code, true))) {
- fprintf(stderr, "unable to open '%s': %s", buf_ptr(rel_full_path), err_str(err));
+ fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(rel_full_path), err_str(err));
exit(1);
}
@@ -7374,7 +7374,7 @@ static void gen_h_file(CodeGen *g) {
FILE *out_h = fopen(buf_ptr(g->out_h_path), "wb");
if (!out_h)
- zig_panic("unable to open %s: %s", buf_ptr(g->out_h_path), strerror(errno));
+ zig_panic("unable to open %s: %s\n", buf_ptr(g->out_h_path), strerror(errno));
Buf *export_macro = preprocessor_mangle(buf_sprintf("%s_EXPORT", buf_ptr(g->root_out_name)));
buf_upcase(export_macro);
diff --git a/src/link.cpp b/src/link.cpp
index d2925cb5a8dfe00332dd4c6928be50f1e13ad06d..a4631b1dafbdc85f0d1780835a4c9f479a083d00 100644
--- a/src/link.cpp
+++ b/src/link.cpp
@@ -208,7 +208,7 @@ static Buf *get_dynamic_linker_path(CodeGen *g) {
static void construct_linker_job_elf(LinkJob *lj) {
CodeGen *g = lj->codegen;
- if (lj->link_in_crt) {
+ if (g->libc_link_lib != nullptr) {
find_libc_lib_path(g);
}
@@ -432,7 +432,7 @@ static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, si
static void construct_linker_job_coff(LinkJob *lj) {
CodeGen *g = lj->codegen;
- if (lj->link_in_crt) {
+ if (g->libc_link_lib != nullptr) {
find_libc_lib_path(g);
}
diff --git a/std/dynamic_library.zig b/std/dynamic_library.zig
new file mode 100644
index 0000000000000000000000000000000000000000..87b58ec20753f01f89d44dde619fc59a80fd61ff
--- /dev/null
+++ b/std/dynamic_library.zig
@@ -0,0 +1,161 @@
+const std = @import("index.zig");
+const mem = std.mem;
+const elf = std.elf;
+const cstr = std.cstr;
+const linux = std.os.linux;
+
+pub const DynLib = struct {
+ allocator: *mem.Allocator,
+ elf_lib: ElfLib,
+ fd: i32,
+ map_addr: usize,
+ map_size: usize,
+
+ /// Trusts the file
+ pub fn findAndOpen(allocator: *mem.Allocator, name: []const u8) !DynLib {
+ return open(allocator, name);
+ }
+
+ /// Trusts the file
+ pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib {
+ const fd = try std.os.posixOpen(allocator, path, 0, linux.O_RDONLY);
+ errdefer std.os.close(fd);
+
+ const size = usize((try std.os.posixFStat(fd)).size);
+
+ const addr = linux.mmap(
+ null,
+ size,
+ linux.PROT_READ | linux.PROT_EXEC,
+ linux.MAP_PRIVATE | linux.MAP_LOCKED,
+ fd,
+ 0,
+ );
+ errdefer _ = linux.munmap(addr, size);
+
+ const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size];
+
+ return DynLib{
+ .allocator = allocator,
+ .elf_lib = try ElfLib.init(bytes),
+ .fd = fd,
+ .map_addr = addr,
+ .map_size = size,
+ };
+ }
+
+ pub fn close(self: *DynLib) void {
+ _ = linux.munmap(self.map_addr, self.map_size);
+ std.os.close(self.fd);
+ self.* = undefined;
+ }
+
+ pub fn lookup(self: *DynLib, name: []const u8) ?usize {
+ return self.elf_lib.lookup("", name);
+ }
+};
+
+pub const ElfLib = struct {
+ strings: [*]u8,
+ syms: [*]elf.Sym,
+ hashtab: [*]linux.Elf_Symndx,
+ versym: ?[*]u16,
+ verdef: ?*elf.Verdef,
+ base: usize,
+
+ // Trusts the memory
+ pub fn init(bytes: []align(@alignOf(elf.Ehdr)) u8) !ElfLib {
+ const eh = @ptrCast(*elf.Ehdr, bytes.ptr);
+ if (!mem.eql(u8, eh.e_ident[0..4], "\x7fELF")) return error.NotElfFile;
+ if (eh.e_type != elf.ET_DYN) return error.NotDynamicLibrary;
+
+ const elf_addr = @ptrToInt(bytes.ptr);
+ var ph_addr: usize = elf_addr + eh.e_phoff;
+
+ var base: usize = @maxValue(usize);
+ var maybe_dynv: ?[*]usize = null;
+ {
+ var i: usize = 0;
+ while (i < eh.e_phnum) : ({
+ i += 1;
+ ph_addr += eh.e_phentsize;
+ }) {
+ const ph = @intToPtr(*elf.Phdr, ph_addr);
+ switch (ph.p_type) {
+ elf.PT_LOAD => base = elf_addr + ph.p_offset - ph.p_vaddr,
+ elf.PT_DYNAMIC => maybe_dynv = @intToPtr([*]usize, elf_addr + ph.p_offset),
+ else => {},
+ }
+ }
+ }
+ const dynv = maybe_dynv orelse return error.MissingDynamicLinkingInformation;
+ if (base == @maxValue(usize)) return error.BaseNotFound;
+
+ var maybe_strings: ?[*]u8 = null;
+ var maybe_syms: ?[*]elf.Sym = null;
+ var maybe_hashtab: ?[*]linux.Elf_Symndx = null;
+ var maybe_versym: ?[*]u16 = null;
+ var maybe_verdef: ?*elf.Verdef = null;
+
+ {
+ var i: usize = 0;
+ while (dynv[i] != 0) : (i += 2) {
+ const p = base + dynv[i + 1];
+ switch (dynv[i]) {
+ elf.DT_STRTAB => maybe_strings = @intToPtr([*]u8, p),
+ elf.DT_SYMTAB => maybe_syms = @intToPtr([*]elf.Sym, p),
+ elf.DT_HASH => maybe_hashtab = @intToPtr([*]linux.Elf_Symndx, p),
+ elf.DT_VERSYM => maybe_versym = @intToPtr([*]u16, p),
+ elf.DT_VERDEF => maybe_verdef = @intToPtr(*elf.Verdef, p),
+ else => {},
+ }
+ }
+ }
+
+ return ElfLib{
+ .base = base,
+ .strings = maybe_strings orelse return error.ElfStringSectionNotFound,
+ .syms = maybe_syms orelse return error.ElfSymSectionNotFound,
+ .hashtab = maybe_hashtab orelse return error.ElfHashTableNotFound,
+ .versym = maybe_versym,
+ .verdef = maybe_verdef,
+ };
+ }
+
+ /// Returns the address of the symbol
+ pub fn lookup(self: *const ElfLib, vername: []const u8, name: []const u8) ?usize {
+ const maybe_versym = if (self.verdef == null) null else self.versym;
+
+ const OK_TYPES = (1 << elf.STT_NOTYPE | 1 << elf.STT_OBJECT | 1 << elf.STT_FUNC | 1 << elf.STT_COMMON);
+ const OK_BINDS = (1 << elf.STB_GLOBAL | 1 << elf.STB_WEAK | 1 << elf.STB_GNU_UNIQUE);
+
+ var i: usize = 0;
+ while (i < self.hashtab[1]) : (i += 1) {
+ if (0 == (u32(1) << u5(self.syms[i].st_info & 0xf) & OK_TYPES)) continue;
+ if (0 == (u32(1) << u5(self.syms[i].st_info >> 4) & OK_BINDS)) continue;
+ if (0 == self.syms[i].st_shndx) continue;
+ if (!mem.eql(u8, name, cstr.toSliceConst(self.strings + self.syms[i].st_name))) continue;
+ if (maybe_versym) |versym| {
+ if (!checkver(self.verdef.?, versym[i], vername, self.strings))
+ continue;
+ }
+ return self.base + self.syms[i].st_value;
+ }
+
+ return null;
+ }
+};
+
+fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [*]u8) bool {
+ var def = def_arg;
+ const vsym = @bitCast(u32, vsym_arg) & 0x7fff;
+ while (true) {
+ if (0 == (def.vd_flags & elf.VER_FLG_BASE) and (def.vd_ndx & 0x7fff) == vsym)
+ break;
+ if (def.vd_next == 0)
+ return false;
+ def = @intToPtr(*elf.Verdef, @ptrToInt(def) + def.vd_next);
+ }
+ const aux = @intToPtr(*elf.Verdaux, @ptrToInt(def) + def.vd_aux);
+ return mem.eql(u8, vername, cstr.toSliceConst(strings + aux.vda_name));
+}
diff --git a/std/elf.zig b/std/elf.zig
index 50e97ab2713762f53f8ab55d39d6f181b7af207c..8e6445c6314154d88bd460ef2128bb30beb804eb 100644
--- a/std/elf.zig
+++ b/std/elf.zig
@@ -305,6 +305,21 @@ pub const STT_ARM_16BIT = STT_HIPROC;
pub const VER_FLG_BASE = 0x1;
pub const VER_FLG_WEAK = 0x2;
+/// An unknown type.
+pub const ET_NONE = 0;
+
+/// A relocatable file.
+pub const ET_REL = 1;
+
+/// An executable file.
+pub const ET_EXEC = 2;
+
+/// A shared object.
+pub const ET_DYN = 3;
+
+/// A core file.
+pub const ET_CORE = 4;
+
pub const FileType = enum {
Relocatable,
Executable,
diff --git a/std/index.zig b/std/index.zig
index 8abfa3db888dc44107ad4a49b76a6a6cfb199f3a..3b523f519f09762e2c2762841c9e4342e66bd708 100644
--- a/std/index.zig
+++ b/std/index.zig
@@ -8,6 +8,7 @@ pub const HashMap = @import("hash_map.zig").HashMap;
pub const LinkedList = @import("linked_list.zig").LinkedList;
pub const IntrusiveLinkedList = @import("linked_list.zig").IntrusiveLinkedList;
pub const SegmentedList = @import("segmented_list.zig").SegmentedList;
+pub const DynLib = @import("dynamic_library.zig").DynLib;
pub const atomic = @import("atomic/index.zig");
pub const base64 = @import("base64.zig");
diff --git a/std/io.zig b/std/io.zig
index a603d0cf5e8ddadfe2dac9d0ed008d4288729a63..cfe1a7f58563427877701f5be9c5558556200358 100644
--- a/std/io.zig
+++ b/std/io.zig
@@ -242,11 +242,16 @@ pub fn writeFile(allocator: *mem.Allocator, path: []const u8, data: []const u8)
/// On success, caller owns returned buffer.
pub fn readFileAlloc(allocator: *mem.Allocator, path: []const u8) ![]u8 {
+ return readFileAllocAligned(allocator, path, @alignOf(u8));
+}
+
+/// On success, caller owns returned buffer.
+pub fn readFileAllocAligned(allocator: *mem.Allocator, path: []const u8, comptime A: u29) ![]align(A) u8 {
var file = try File.openRead(allocator, path);
defer file.close();
const size = try file.getEndPos();
- const buf = try allocator.alloc(u8, size);
+ const buf = try allocator.alignedAlloc(u8, A, size);
errdefer allocator.free(buf);
var adapter = FileInStream.init(&file);
diff --git a/std/math/index.zig b/std/math/index.zig
index cc1b833a372f0e7e1407b98d358f76c63dc287e6..8c1dcc32c4bcabe987a22dea7cef1c53f248def0 100644
--- a/std/math/index.zig
+++ b/std/math/index.zig
@@ -536,6 +536,17 @@ test "math.cast" {
assert(@typeOf(try cast(u8, u32(255))) == u8);
}
+pub const AlignCastError = error{UnalignedMemory};
+
+/// Align cast a pointer but return an error if it's the wrong field
+pub fn alignCast(comptime alignment: u29, ptr: var) AlignCastError!@typeOf(@alignCast(alignment, ptr)) {
+ const addr = @ptrToInt(ptr);
+ if (addr % alignment != 0) {
+ return error.UnalignedMemory;
+ }
+ return @alignCast(alignment, ptr);
+}
+
pub fn floorPowerOfTwo(comptime T: type, value: T) T {
var x = value;
diff --git a/std/os/file.zig b/std/os/file.zig
index 56da4f73a6ebfa92444ccfcf3bfa728bdf46eb3f..41d3dfbf956cd9956e0a54314bc91189a14321f5 100644
--- a/std/os/file.zig
+++ b/std/os/file.zig
@@ -265,16 +265,7 @@ pub const File = struct {
pub fn getEndPos(self: *File) !usize {
if (is_posix) {
- var stat: posix.Stat = undefined;
- const err = posix.getErrno(posix.fstat(self.handle, &stat));
- if (err > 0) {
- return switch (err) {
- posix.EBADF => error.BadFd,
- posix.ENOMEM => error.SystemResources,
- else => os.unexpectedErrorPosix(err),
- };
- }
-
+ const stat = try os.posixFStat(self.handle);
return usize(stat.size);
} else if (is_windows) {
var file_size: windows.LARGE_INTEGER = undefined;
diff --git a/std/os/index.zig b/std/os/index.zig
index 62eeb7e43e0475956d80b5df3f61391f56fe0fc1..fb4605fce02d7e42a88d8ee6567e7587ddc8fcb0 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -2697,3 +2697,17 @@ pub fn posixWait(pid: i32) i32 {
}
}
}
+
+pub fn posixFStat(fd: i32) !posix.Stat {
+ var stat: posix.Stat = undefined;
+ const err = posix.getErrno(posix.fstat(fd, &stat));
+ if (err > 0) {
+ return switch (err) {
+ posix.EBADF => error.BadFd,
+ posix.ENOMEM => error.SystemResources,
+ else => os.unexpectedErrorPosix(err),
+ };
+ }
+
+ return stat;
+}
diff --git a/test/build_examples.zig b/test/build_examples.zig
index 1ba0ca46cf8ff504a8b12064dac32aa4862d6e18..7cae7346779b0e40f66738f725afd5c1c4bf4906 100644
--- a/test/build_examples.zig
+++ b/test/build_examples.zig
@@ -18,4 +18,9 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void {
cases.addBuildFile("test/standalone/pkg_import/build.zig");
cases.addBuildFile("test/standalone/use_alias/build.zig");
cases.addBuildFile("test/standalone/brace_expansion/build.zig");
+ if (builtin.os == builtin.Os.linux) {
+ // TODO hook up the DynLib API for windows using LoadLibraryA
+ // TODO figure out how to make this work on darwin - probably libSystem has dlopen/dlsym in it
+ cases.addBuildFile("test/standalone/load_dynamic_library/build.zig");
+ }
}
diff --git a/test/standalone/load_dynamic_library/add.zig b/test/standalone/load_dynamic_library/add.zig
new file mode 100644
index 0000000000000000000000000000000000000000..a04ec1544dc82e27afb137de2672a48d726a72fc
--- /dev/null
+++ b/test/standalone/load_dynamic_library/add.zig
@@ -0,0 +1,3 @@
+export fn add(a: i32, b: i32) i32 {
+ return a + b;
+}
diff --git a/test/standalone/load_dynamic_library/build.zig b/test/standalone/load_dynamic_library/build.zig
new file mode 100644
index 0000000000000000000000000000000000000000..1f981a5c7d5e46830022b1677cbfec644155a508
--- /dev/null
+++ b/test/standalone/load_dynamic_library/build.zig
@@ -0,0 +1,22 @@
+const Builder = @import("std").build.Builder;
+
+pub fn build(b: *Builder) void {
+ const opts = b.standardReleaseOptions();
+
+ const lib = b.addSharedLibrary("add", "add.zig", b.version(1, 0, 0));
+ lib.setBuildMode(opts);
+ lib.linkSystemLibrary("c");
+
+ const main = b.addExecutable("main", "main.zig");
+ main.setBuildMode(opts);
+
+ const run = b.addCommand(".", b.env_map, [][]const u8{
+ main.getOutputPath(),
+ lib.getOutputPath(),
+ });
+ run.step.dependOn(&lib.step);
+ run.step.dependOn(&main.step);
+
+ const test_step = b.step("test", "Test the program");
+ test_step.dependOn(&run.step);
+}
diff --git a/test/standalone/load_dynamic_library/main.zig b/test/standalone/load_dynamic_library/main.zig
new file mode 100644
index 0000000000000000000000000000000000000000..4c45ad6fdef122ca7b80d43f22f00e4bccdeecde
--- /dev/null
+++ b/test/standalone/load_dynamic_library/main.zig
@@ -0,0 +1,17 @@
+const std = @import("std");
+
+pub fn main() !void {
+ const args = try std.os.argsAlloc(std.debug.global_allocator);
+ defer std.os.argsFree(std.debug.global_allocator, args);
+
+ const dynlib_name = args[1];
+
+ var lib = try std.DynLib.open(std.debug.global_allocator, dynlib_name);
+ defer lib.close();
+
+ const addr = lib.lookup("add") orelse return error.SymbolNotFound;
+ const addFn = @intToPtr(extern fn (i32, i32) i32, addr);
+
+ const result = addFn(12, 34);
+ std.debug.assert(result == 46);
+}
--
2.54.0
From 65d04cbeb42318c66313346bb88999aee17f856f Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 16 Jun 2018 17:27:45 -0400
Subject: [PATCH 03/28] std.DynLib: open the fd with CLOEXEC
---
std/dynamic_library.zig | 7 +------
std/math/index.zig | 2 +-
2 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/std/dynamic_library.zig b/std/dynamic_library.zig
index 87b58ec20753f01f89d44dde619fc59a80fd61ff..8fe5f7f818e6e007c281115cb4b2303503049b1f 100644
--- a/std/dynamic_library.zig
+++ b/std/dynamic_library.zig
@@ -11,14 +11,9 @@ pub const DynLib = struct {
map_addr: usize,
map_size: usize,
- /// Trusts the file
- pub fn findAndOpen(allocator: *mem.Allocator, name: []const u8) !DynLib {
- return open(allocator, name);
- }
-
/// Trusts the file
pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib {
- const fd = try std.os.posixOpen(allocator, path, 0, linux.O_RDONLY);
+ const fd = try std.os.posixOpen(allocator, path, 0, linux.O_RDONLY | linux.O_CLOEXEC);
errdefer std.os.close(fd);
const size = usize((try std.os.posixFStat(fd)).size);
diff --git a/std/math/index.zig b/std/math/index.zig
index 8c1dcc32c4bcabe987a22dea7cef1c53f248def0..99e5b4ecf1597b633cf46d0dd3a9b32bea32fb3d 100644
--- a/std/math/index.zig
+++ b/std/math/index.zig
@@ -538,7 +538,7 @@ test "math.cast" {
pub const AlignCastError = error{UnalignedMemory};
-/// Align cast a pointer but return an error if it's the wrong field
+/// Align cast a pointer but return an error if it's the wrong alignment
pub fn alignCast(comptime alignment: u29, ptr: var) AlignCastError!@typeOf(@alignCast(alignment, ptr)) {
const addr = @ptrToInt(ptr);
if (addr % alignment != 0) {
--
2.54.0
From c529b814ee292250ad34b0f2b00f5bd5e6796597 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 16 Jun 2018 18:54:41 -0400
Subject: [PATCH 04/28] load_dynamic_library test: no need to link libc
---
test/standalone/load_dynamic_library/build.zig | 1 -
1 file changed, 1 deletion(-)
diff --git a/test/standalone/load_dynamic_library/build.zig b/test/standalone/load_dynamic_library/build.zig
index 1f981a5c7d5e46830022b1677cbfec644155a508..2d47a893f25cab1149b90c2332ffe23878109634 100644
--- a/test/standalone/load_dynamic_library/build.zig
+++ b/test/standalone/load_dynamic_library/build.zig
@@ -5,7 +5,6 @@ pub fn build(b: *Builder) void {
const lib = b.addSharedLibrary("add", "add.zig", b.version(1, 0, 0));
lib.setBuildMode(opts);
- lib.linkSystemLibrary("c");
const main = b.addExecutable("main", "main.zig");
main.setBuildMode(opts);
--
2.54.0
From a7d59086b49b0ae11a4830d2ea72b63be05fab94 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 16 Jun 2018 19:36:06 -0400
Subject: [PATCH 05/28] disable load dynamic library test
it's failing on CI. I will troubleshoot it and then re-enable
---
test/build_examples.zig | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/test/build_examples.zig b/test/build_examples.zig
index 7cae7346779b0e40f66738f725afd5c1c4bf4906..b48fcbb698e0e8d3b54d382b3c1adf2244b5bca1 100644
--- a/test/build_examples.zig
+++ b/test/build_examples.zig
@@ -18,7 +18,9 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void {
cases.addBuildFile("test/standalone/pkg_import/build.zig");
cases.addBuildFile("test/standalone/use_alias/build.zig");
cases.addBuildFile("test/standalone/brace_expansion/build.zig");
- if (builtin.os == builtin.Os.linux) {
+ if (false) {
+ // TODO this test is disabled because it is failing on the CI server's linux. when this is fixed
+ // enable it for at least linux
// TODO hook up the DynLib API for windows using LoadLibraryA
// TODO figure out how to make this work on darwin - probably libSystem has dlopen/dlsym in it
cases.addBuildFile("test/standalone/load_dynamic_library/build.zig");
--
2.54.0
From 59b3dc8907f76b93caa689732e878a5bfa2f65c2 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 13 Jun 2018 22:40:38 -0400
Subject: [PATCH 06/28] allow passing by non-copying value
closes #733
---
doc/langref.html.in | 39 +++++++++++++++------------------------
src/analyze.cpp | 11 ++++-------
test/cases/fn.zig | 13 +++++++++++++
test/compile_errors.zig | 23 -----------------------
4 files changed, 32 insertions(+), 54 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 814de721a694f5c17406d91b78a798ebd066170d..b32c8165e22843872ec03e9cb2820e43ca4bb651 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -2797,39 +2797,30 @@ fn foo() void { }
{#code_end#}
{#header_open|Pass-by-value Parameters#}
- In Zig, structs, unions, and enums with payloads cannot be passed by value
- to a function.
-
- {#code_begin|test_err|not copyable; cannot pass by value#}
-const Foo = struct {
- x: i32,
-};
-
-fn bar(foo: Foo) void {}
-
-test "pass aggregate type by value to function" {
- bar(Foo {.x = 12,});
-}
- {#code_end#}
-
- Instead, one must use *const. Zig allows implicitly casting something
- to a const pointer to it:
+ In Zig, structs, unions, and enums with payloads can be passed directly to a function:
{#code_begin|test#}
-const Foo = struct {
+const Point = struct {
x: i32,
+ y: i32,
};
-fn bar(foo: *const Foo) void {}
+fn foo(point: Point) i32 {
+ return point.x + point.y;
+}
-test "implicitly cast to const pointer" {
- bar(Foo {.x = 12,});
+const assert = @import("std").debug.assert;
+
+test "pass aggregate type by non-copy value to function" {
+ assert(foo(Point{ .x = 1, .y = 2 }) == 3);
}
{#code_end#}
- However,
- the C ABI does allow passing structs and unions by value. So functions which
- use the C calling convention may pass structs and unions by value.
+ In this case, the value may be passed by reference, or by value, whichever way
+ Zig decides will be faster.
+
+
+ For extern functions, Zig follows the C ABI for passing structs and unions by value.
{#header_close#}
{#header_open|Function Reflection#}
diff --git a/src/analyze.cpp b/src/analyze.cpp
index cbeac7bc212e5188561cd89f5c9bbc0f16407814..758bc1a045b5fe0c0d3331dcb041e95533a85f23 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -1135,7 +1135,10 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
gen_param_info->src_index = i;
gen_param_info->gen_index = SIZE_MAX;
- type_ensure_zero_bits_known(g, type_entry);
+ ensure_complete_type(g, type_entry);
+ if (type_is_invalid(type_entry))
+ return g->builtin_types.entry_invalid;
+
if (type_has_bits(type_entry)) {
TypeTableEntry *gen_type;
if (handle_is_ptr(type_entry)) {
@@ -1546,12 +1549,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
case TypeTableEntryIdUnion:
case TypeTableEntryIdFn:
case TypeTableEntryIdPromise:
- ensure_complete_type(g, type_entry);
- if (calling_convention_allows_zig_types(fn_type_id.cc) && !type_is_copyable(g, type_entry)) {
- add_node_error(g, param_node->data.param_decl.type,
- buf_sprintf("type '%s' is not copyable; cannot pass by value", buf_ptr(&type_entry->name)));
- return g->builtin_types.entry_invalid;
- }
break;
}
FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index];
diff --git a/test/cases/fn.zig b/test/cases/fn.zig
index dfb254c6aaa132f051df6a23ecdfd14b2248cbdb..2426a411dfd01e4ccb998ea031db7166641f0a75 100644
--- a/test/cases/fn.zig
+++ b/test/cases/fn.zig
@@ -119,3 +119,16 @@ test "assign inline fn to const variable" {
}
inline fn inlineFn() void {}
+
+test "pass by non-copying value" {
+ assert(bar(Point{ .x = 1, .y = 2 }) == 3);
+}
+
+const Point = struct {
+ x: i32,
+ y: i32,
+};
+
+fn bar(pt: Point) i32 {
+ return pt.x + pt.y;
+}
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 06f17a37eedfb9fac1c9a2d67120ace2a8439d14..60ba2551726e5dabb0e321a2cf28750ced0e9c61 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -2573,15 +2573,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
break :x tc;
});
- cases.add(
- "pass non-copyable type by value to function",
- \\const Point = struct { x: i32, y: i32, };
- \\fn foo(p: Point) void { }
- \\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
- ,
- ".tmp_source.zig:2:11: error: type 'Point' is not copyable; cannot pass by value",
- );
-
cases.add(
"implicit cast from array to mutable slice",
\\var global_array: [10]i32 = undefined;
@@ -4066,20 +4057,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
".tmp_source.zig:3:5: note: field 'A' has type 'i32'",
);
- cases.add(
- "self-referencing function pointer field",
- \\const S = struct {
- \\ f: fn(_: S) void,
- \\};
- \\fn f(_: S) void {
- \\}
- \\export fn entry() void {
- \\ var _ = S { .f = f };
- \\}
- ,
- ".tmp_source.zig:4:9: error: type 'S' is not copyable; cannot pass by value",
- );
-
cases.add(
"taking offset of void field in struct",
\\const Empty = struct {
--
2.54.0
From e311cd562b47529bdcd2423658915539ddb6bc36 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Fri, 15 Jun 2018 13:49:39 -0400
Subject: [PATCH 07/28] don't automatically take pointer when passing by
non-copying value
this commit does not have all tests passing
---
src/ir.cpp | 57 ++++---
std/array_list.zig | 26 +--
std/build.zig | 2 +-
std/fmt/index.zig | 8 +-
std/json.zig | 2 +-
std/math/big/int.zig | 346 +++++++++++++++++-----------------------
std/mem.zig | 10 +-
test/cases/cast.zig | 8 -
test/cases/fn.zig | 48 +++++-
test/cases/var_args.zig | 12 --
test/compile_errors.zig | 2 +-
11 files changed, 249 insertions(+), 272 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index e5e8dcbb9dd0b68a7dbd427fb88308c52c47cadf..d008ead1132e6b7acdcd4a8156ce5601fd490e0a 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -10463,13 +10463,6 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Typ
zig_unreachable();
}
-static IrInstruction *ir_implicit_byval_const_ref_cast(IrAnalyze *ira, IrInstruction *inst) {
- if (type_is_copyable(ira->codegen, inst->value.type))
- return inst;
- TypeTableEntry *const_ref_type = get_pointer_to_type(ira->codegen, inst->value.type, true);
- return ir_implicit_cast(ira, inst, const_ref_type);
-}
-
static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr) {
TypeTableEntry *type_entry = ptr->value.type;
if (type_is_invalid(type_entry)) {
@@ -12283,7 +12276,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
IrInstruction *casted_arg;
if (is_var_args) {
arg_part_of_generic_id = true;
- casted_arg = ir_implicit_byval_const_ref_cast(ira, arg);
+ casted_arg = arg;
} else {
if (param_decl_node->data.param_decl.var_token == nullptr) {
AstNode *param_type_node = param_decl_node->data.param_decl.type;
@@ -12296,7 +12289,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
return false;
} else {
arg_part_of_generic_id = true;
- casted_arg = ir_implicit_byval_const_ref_cast(ira, arg);
+ casted_arg = arg;
}
}
@@ -12515,9 +12508,18 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
size_t next_proto_i = 0;
if (first_arg_ptr) {
- IrInstruction *first_arg;
assert(first_arg_ptr->value.type->id == TypeTableEntryIdPointer);
- if (handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) {
+
+ bool first_arg_known_bare = false;
+ if (fn_type_id->next_param_index >= 1) {
+ TypeTableEntry *param_type = fn_type_id->param_info[next_proto_i].type;
+ if (type_is_invalid(param_type))
+ return ira->codegen->builtin_types.entry_invalid;
+ first_arg_known_bare = param_type->id != TypeTableEntryIdPointer;
+ }
+
+ IrInstruction *first_arg;
+ if (!first_arg_known_bare && handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) {
first_arg = first_arg_ptr;
} else {
first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr);
@@ -12667,9 +12669,18 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
size_t next_proto_i = 0;
if (first_arg_ptr) {
- IrInstruction *first_arg;
assert(first_arg_ptr->value.type->id == TypeTableEntryIdPointer);
- if (handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) {
+
+ bool first_arg_known_bare = false;
+ if (fn_type_id->next_param_index >= 1) {
+ TypeTableEntry *param_type = fn_type_id->param_info[next_proto_i].type;
+ if (type_is_invalid(param_type))
+ return ira->codegen->builtin_types.entry_invalid;
+ first_arg_known_bare = param_type->id != TypeTableEntryIdPointer;
+ }
+
+ IrInstruction *first_arg;
+ if (!first_arg_known_bare && handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) {
first_arg = first_arg_ptr;
} else {
first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr);
@@ -12802,10 +12813,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
return ira->codegen->builtin_types.entry_invalid;
}
if (inst_fn_type_id.async_allocator_type == nullptr) {
- IrInstruction *casted_inst = ir_implicit_byval_const_ref_cast(ira, uncasted_async_allocator_inst);
- if (type_is_invalid(casted_inst->value.type))
- return ira->codegen->builtin_types.entry_invalid;
- inst_fn_type_id.async_allocator_type = casted_inst->value.type;
+ inst_fn_type_id.async_allocator_type = uncasted_async_allocator_inst->value.type;
}
async_allocator_inst = ir_implicit_cast(ira, uncasted_async_allocator_inst, inst_fn_type_id.async_allocator_type);
if (type_is_invalid(async_allocator_inst->value.type))
@@ -12866,9 +12874,16 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
IrInstruction **casted_args = allocate(call_param_count);
size_t next_arg_index = 0;
if (first_arg_ptr) {
- IrInstruction *first_arg;
assert(first_arg_ptr->value.type->id == TypeTableEntryIdPointer);
- if (handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) {
+
+ TypeTableEntry *param_type = fn_type_id->param_info[next_arg_index].type;
+ if (type_is_invalid(param_type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ IrInstruction *first_arg;
+ if (param_type->id == TypeTableEntryIdPointer &&
+ handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type))
+ {
first_arg = first_arg_ptr;
} else {
first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr);
@@ -12876,10 +12891,6 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
return ira->codegen->builtin_types.entry_invalid;
}
- TypeTableEntry *param_type = fn_type_id->param_info[next_arg_index].type;
- if (type_is_invalid(param_type))
- return ira->codegen->builtin_types.entry_invalid;
-
IrInstruction *casted_arg = ir_implicit_cast(ira, first_arg, param_type);
if (type_is_invalid(casted_arg->value.type))
return ira->codegen->builtin_types.entry_invalid;
diff --git a/std/array_list.zig b/std/array_list.zig
index 1a235d28a354416bb57da0a4d09b6baa379dd560..fd1d5cbe26d99a84ddaced248ab60f4ac31f8368 100644
--- a/std/array_list.zig
+++ b/std/array_list.zig
@@ -29,36 +29,36 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
};
}
- pub fn deinit(self: *const Self) void {
+ pub fn deinit(self: Self) void {
self.allocator.free(self.items);
}
- pub fn toSlice(self: *const Self) []align(A) T {
+ pub fn toSlice(self: Self) []align(A) T {
return self.items[0..self.len];
}
- pub fn toSliceConst(self: *const Self) []align(A) const T {
+ pub fn toSliceConst(self: Self) []align(A) const T {
return self.items[0..self.len];
}
- pub fn at(self: *const Self, n: usize) T {
+ pub fn at(self: Self, n: usize) T {
return self.toSliceConst()[n];
}
/// Sets the value at index `i`, or returns `error.OutOfBounds` if
/// the index is not in range.
- pub fn setOrError(self: *const Self, i: usize, item: *const T) !void {
+ pub fn setOrError(self: Self, i: usize, item: T) !void {
if (i >= self.len) return error.OutOfBounds;
- self.items[i] = item.*;
+ self.items[i] = item;
}
/// Sets the value at index `i`, asserting that the value is in range.
- pub fn set(self: *const Self, i: usize, item: *const T) void {
+ pub fn set(self: *Self, i: usize, item: T) void {
assert(i < self.len);
- self.items[i] = item.*;
+ self.items[i] = item;
}
- pub fn count(self: *const Self) usize {
+ pub fn count(self: Self) usize {
return self.len;
}
@@ -81,12 +81,12 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
return result;
}
- pub fn insert(self: *Self, n: usize, item: *const T) !void {
+ pub fn insert(self: *Self, n: usize, item: T) !void {
try self.ensureCapacity(self.len + 1);
self.len += 1;
mem.copy(T, self.items[n + 1 .. self.len], self.items[n .. self.len - 1]);
- self.items[n] = item.*;
+ self.items[n] = item;
}
pub fn insertSlice(self: *Self, n: usize, items: []align(A) const T) !void {
@@ -97,9 +97,9 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
mem.copy(T, self.items[n .. n + items.len], items);
}
- pub fn append(self: *Self, item: *const T) !void {
+ pub fn append(self: *Self, item: T) !void {
const new_item_ptr = try self.addOne();
- new_item_ptr.* = item.*;
+ new_item_ptr.* = item;
}
pub fn appendSlice(self: *Self, items: []align(A) const T) !void {
diff --git a/std/build.zig b/std/build.zig
index 16ce426bcb96ac940e281f53ab750be4396f71de..92454a183ae46c47e026f2d90ca75bda3d091ae0 100644
--- a/std/build.zig
+++ b/std/build.zig
@@ -234,7 +234,7 @@ pub const Builder = struct {
defer wanted_steps.deinit();
if (step_names.len == 0) {
- try wanted_steps.append(&self.default_step);
+ try wanted_steps.append(self.default_step);
} else {
for (step_names) |step_name| {
const s = try self.getTopLevelStepByName(step_name);
diff --git a/std/fmt/index.zig b/std/fmt/index.zig
index cfc0948d2cfbc6837f691998b5c6b73719dfedb8..90d3a559c4458c6c32b1f62af4268c51e8465e75 100644
--- a/std/fmt/index.zig
+++ b/std/fmt/index.zig
@@ -162,8 +162,6 @@ pub fn formatType(
},
builtin.TypeInfo.Pointer.Size.Many => {
if (ptr_info.child == u8) {
- //This is a bit of a hack, but it made more sense to
- // do this check here than have formatText do it
if (fmt[0] == 's') {
const len = std.cstr.len(value);
return formatText(value[0..len], fmt, context, Errors, output);
@@ -176,6 +174,12 @@ pub fn formatType(
return output(context, casted_value);
},
},
+ builtin.TypeId.Array => |info| {
+ if (info.child == u8) {
+ return formatText(value, fmt, context, Errors, output);
+ }
+ return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));
+ },
else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
}
}
diff --git a/std/json.zig b/std/json.zig
index 75ea2eee1c75d62e0a01c18d02f057f6871a007f..8bbee981e38725173ab0b676ba86339893e89f14 100644
--- a/std/json.zig
+++ b/std/json.zig
@@ -1326,7 +1326,7 @@ pub const Parser = struct {
},
// Array Parent -> [ ..., , value ]
Value.Array => |*array| {
- try array.append(value);
+ try array.append(value.*);
p.state = State.ArrayValue;
},
else => {
diff --git a/std/math/big/int.zig b/std/math/big/int.zig
index 19af10e69569337ce5cc65b0aeb3a58dbd56d70b..5e15cfb895e3d97e9556f555177cc5f33ffcac67 100644
--- a/std/math/big/int.zig
+++ b/std/math/big/int.zig
@@ -18,39 +18,6 @@ comptime {
debug.assert(Limb.is_signed == false);
}
-const wrapped_buffer_size = 512;
-
-// Converts primitive integer values onto a stack-based big integer, or passes through existing
-// Int types with no modifications. This can fail at runtime if using a very large dynamic
-// integer but it is very unlikely and is considered a user error.
-fn wrapInt(allocator: *Allocator, bn: var) *const Int {
- const T = @typeOf(bn);
- switch (@typeInfo(T)) {
- TypeId.Pointer => |info| {
- if (info.child == Int) {
- return bn;
- } else {
- @compileError("cannot set Int using type " ++ @typeName(T));
- }
- },
- else => {
- var s = allocator.create(Int) catch unreachable;
- s.* = Int{
- .allocator = allocator,
- .positive = false,
- .limbs = block: {
- var limbs = allocator.alloc(Limb, Int.default_capacity) catch unreachable;
- limbs[0] = 0;
- break :block limbs;
- },
- .len = 1,
- };
- s.set(bn) catch unreachable;
- return s;
- },
- }
-}
-
pub const Int = struct {
allocator: *Allocator,
positive: bool,
@@ -93,11 +60,11 @@ pub const Int = struct {
self.limbs = try self.allocator.realloc(Limb, self.limbs, capacity);
}
- pub fn deinit(self: *const Int) void {
+ pub fn deinit(self: Int) void {
self.allocator.free(self.limbs);
}
- pub fn clone(other: *const Int) !Int {
+ pub fn clone(other: Int) !Int {
return Int{
.allocator = other.allocator,
.positive = other.positive,
@@ -110,8 +77,8 @@ pub const Int = struct {
};
}
- pub fn copy(self: *Int, other: *const Int) !void {
- if (self == other) {
+ pub fn copy(self: *Int, other: Int) !void {
+ if (self == &other) {
return;
}
@@ -125,7 +92,7 @@ pub const Int = struct {
mem.swap(Int, self, other);
}
- pub fn dump(self: *const Int) void {
+ pub fn dump(self: Int) void {
for (self.limbs) |limb| {
debug.warn("{x} ", limb);
}
@@ -140,20 +107,20 @@ pub const Int = struct {
r.positive = true;
}
- pub fn isOdd(r: *const Int) bool {
+ pub fn isOdd(r: Int) bool {
return r.limbs[0] & 1 != 0;
}
- pub fn isEven(r: *const Int) bool {
+ pub fn isEven(r: Int) bool {
return !r.isOdd();
}
- fn bitcount(self: *const Int) usize {
+ fn bitcount(self: Int) usize {
const u_bit_count = (self.len - 1) * Limb.bit_count + (Limb.bit_count - @clz(self.limbs[self.len - 1]));
return usize(!self.positive) + u_bit_count;
}
- pub fn sizeInBase(self: *const Int, base: usize) usize {
+ pub fn sizeInBase(self: Int, base: usize) usize {
return (self.bitcount() / math.log2(base)) + 1;
}
@@ -219,7 +186,7 @@ pub const Int = struct {
TargetTooSmall,
};
- pub fn to(self: *const Int, comptime T: type) ConvertError!T {
+ pub fn to(self: Int, comptime T: type) ConvertError!T {
switch (@typeId(T)) {
TypeId.Int => {
const UT = if (T.is_signed) @IntType(false, T.bit_count - 1) else T;
@@ -286,16 +253,28 @@ pub const Int = struct {
i += 1;
}
+ // TODO values less than limb size should guarantee non allocating
+ var base_buffer: [512]u8 = undefined;
+ const base_al = &std.heap.FixedBufferAllocator.init(base_buffer[0..]).allocator;
+ const base_ap = try Int.initSet(base_al, base);
+
+ var d_buffer: [512]u8 = undefined;
+ var d_fba = std.heap.FixedBufferAllocator.init(d_buffer[0..]);
+ const d_al = &d_fba.allocator;
+
try self.set(0);
for (value[i..]) |ch| {
const d = try charToDigit(ch, base);
- try self.mul(self, base);
- try self.add(self, d);
+ d_fba.end_index = 0;
+ const d_ap = try Int.initSet(d_al, d);
+
+ try self.mul(self.*, base_ap);
+ try self.add(self.*, d_ap);
}
self.positive = positive;
}
- pub fn toString(self: *const Int, allocator: *Allocator, base: u8) ![]const u8 {
+ pub fn toString(self: Int, allocator: *Allocator, base: u8) ![]const u8 {
if (base < 2 or base > 16) {
return error.InvalidBase;
}
@@ -345,7 +324,7 @@ pub const Int = struct {
var b = try Int.initSet(allocator, limb_base);
while (q.len >= 2) {
- try Int.divTrunc(&q, &r, &q, &b);
+ try Int.divTrunc(&q, &r, q, b);
var r_word = r.limbs[0];
var i: usize = 0;
@@ -378,12 +357,7 @@ pub const Int = struct {
}
// returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.
- pub fn cmpAbs(a: *const Int, bv: var) i8 {
- // TODO: Thread-local buffer.
- var buffer: [wrapped_buffer_size]u8 = undefined;
- var stack = std.heap.FixedBufferAllocator.init(buffer[0..]);
- var b = wrapInt(&stack.allocator, bv);
-
+ pub fn cmpAbs(a: Int, b: Int) i8 {
if (a.len < b.len) {
return -1;
}
@@ -408,11 +382,7 @@ pub const Int = struct {
}
// returns -1, 0, 1 if a < b, a == b or a > b respectively.
- pub fn cmp(a: *const Int, bv: var) i8 {
- var buffer: [wrapped_buffer_size]u8 = undefined;
- var stack = std.heap.FixedBufferAllocator.init(buffer[0..]);
- var b = wrapInt(&stack.allocator, bv);
-
+ pub fn cmp(a: Int, b: Int) i8 {
if (a.positive != b.positive) {
return if (a.positive) i8(1) else -1;
} else {
@@ -422,17 +392,17 @@ pub const Int = struct {
}
// if a == 0
- pub fn eqZero(a: *const Int) bool {
+ pub fn eqZero(a: Int) bool {
return a.len == 1 and a.limbs[0] == 0;
}
// if |a| == |b|
- pub fn eqAbs(a: *const Int, b: var) bool {
+ pub fn eqAbs(a: Int, b: Int) bool {
return cmpAbs(a, b) == 0;
}
// if a == b
- pub fn eq(a: *const Int, b: var) bool {
+ pub fn eq(a: Int, b: Int) bool {
return cmp(a, b) == 0;
}
@@ -473,12 +443,7 @@ pub const Int = struct {
}
// r = a + b
- pub fn add(r: *Int, av: var, bv: var) Allocator.Error!void {
- var buffer: [2 * wrapped_buffer_size]u8 = undefined;
- var stack = std.heap.FixedBufferAllocator.init(buffer[0..]);
- var a = wrapInt(&stack.allocator, av);
- var b = wrapInt(&stack.allocator, bv);
-
+ pub fn add(r: *Int, a: Int, b: Int) Allocator.Error!void {
if (a.eqZero()) {
try r.copy(b);
return;
@@ -547,12 +512,7 @@ pub const Int = struct {
}
// r = a - b
- pub fn sub(r: *Int, av: var, bv: var) !void {
- var buffer: [wrapped_buffer_size]u8 = undefined;
- var stack = std.heap.FixedBufferAllocator.init(buffer[0..]);
- var a = wrapInt(&stack.allocator, av);
- var b = wrapInt(&stack.allocator, bv);
-
+ pub fn sub(r: *Int, a: Int, b: Int) !void {
if (a.positive != b.positive) {
if (a.positive) {
// (a) - (-b) => a + b
@@ -632,14 +592,9 @@ pub const Int = struct {
// rma = a * b
//
// For greatest efficiency, ensure rma does not alias a or b.
- pub fn mul(rma: *Int, av: var, bv: var) !void {
- var buffer: [2 * wrapped_buffer_size]u8 = undefined;
- var stack = std.heap.FixedBufferAllocator.init(buffer[0..]);
- var a = wrapInt(&stack.allocator, av);
- var b = wrapInt(&stack.allocator, bv);
-
+ pub fn mul(rma: *Int, a: Int, b: Int) !void {
var r = rma;
- var aliased = rma == a or rma == b;
+ var aliased = rma.limbs.ptr == a.limbs.ptr or rma.limbs.ptr == b.limbs.ptr;
var sr: Int = undefined;
if (aliased) {
@@ -714,29 +669,29 @@ pub const Int = struct {
}
}
- pub fn divFloor(q: *Int, r: *Int, a: var, b: var) !void {
+ pub fn divFloor(q: *Int, r: *Int, a: Int, b: Int) !void {
try div(q, r, a, b);
// Trunc -> Floor.
if (!q.positive) {
- try q.sub(q, 1);
- try r.add(q, 1);
+ // TODO values less than limb size should guarantee non allocating
+ var one_buffer: [512]u8 = undefined;
+ const one_al = &std.heap.FixedBufferAllocator.init(one_buffer[0..]).allocator;
+ const one_ap = try Int.initSet(one_al, 1);
+
+ try q.sub(q.*, one_ap);
+ try r.add(q.*, one_ap);
}
r.positive = b.positive;
}
- pub fn divTrunc(q: *Int, r: *Int, a: var, b: var) !void {
+ pub fn divTrunc(q: *Int, r: *Int, a: Int, b: Int) !void {
try div(q, r, a, b);
r.positive = a.positive;
}
// Truncates by default.
- fn div(quo: *Int, rem: *Int, av: var, bv: var) !void {
- var buffer: [2 * wrapped_buffer_size]u8 = undefined;
- var stack = std.heap.FixedBufferAllocator.init(buffer[0..]);
- var a = wrapInt(&stack.allocator, av);
- var b = wrapInt(&stack.allocator, bv);
-
+ fn div(quo: *Int, rem: *Int, a: Int, b: Int) !void {
if (b.eqZero()) {
@panic("division by zero");
}
@@ -821,8 +776,8 @@ pub const Int = struct {
// Normalize so y > Limb.bit_count / 2 (i.e. leading bit is set)
const norm_shift = @clz(y.limbs[y.len - 1]);
- try x.shiftLeft(x, norm_shift);
- try y.shiftLeft(y, norm_shift);
+ try x.shiftLeft(x.*, norm_shift);
+ try y.shiftLeft(y.*, norm_shift);
const n = x.len - 1;
const t = y.len - 1;
@@ -832,10 +787,10 @@ pub const Int = struct {
mem.set(Limb, q.limbs[0..q.len], 0);
// 2.
- try tmp.shiftLeft(y, Limb.bit_count * (n - t));
- while (x.cmp(&tmp) >= 0) {
+ try tmp.shiftLeft(y.*, Limb.bit_count * (n - t));
+ while (x.cmp(tmp) >= 0) {
q.limbs[n - t] += 1;
- try x.sub(x, tmp);
+ try x.sub(x.*, tmp);
}
// 3.
@@ -864,7 +819,7 @@ pub const Int = struct {
r.limbs[2] = carry;
r.normN(3);
- if (r.cmpAbs(&tmp) <= 0) {
+ if (r.cmpAbs(tmp) <= 0) {
break;
}
@@ -873,13 +828,13 @@ pub const Int = struct {
// 3.3
try tmp.set(q.limbs[i - t - 1]);
- try tmp.mul(&tmp, y);
- try tmp.shiftLeft(&tmp, Limb.bit_count * (i - t - 1));
- try x.sub(x, &tmp);
+ try tmp.mul(tmp, y.*);
+ try tmp.shiftLeft(tmp, Limb.bit_count * (i - t - 1));
+ try x.sub(x.*, tmp);
if (!x.positive) {
- try tmp.shiftLeft(y, Limb.bit_count * (i - t - 1));
- try x.add(x, &tmp);
+ try tmp.shiftLeft(y.*, Limb.bit_count * (i - t - 1));
+ try x.add(x.*, tmp);
q.limbs[i - t - 1] -= 1;
}
}
@@ -887,16 +842,12 @@ pub const Int = struct {
// Denormalize
q.normN(q.len);
- try r.shiftRight(x, norm_shift);
+ try r.shiftRight(x.*, norm_shift);
r.normN(r.len);
}
// r = a << shift, in other words, r = a * 2^shift
- pub fn shiftLeft(r: *Int, av: var, shift: usize) !void {
- var buffer: [wrapped_buffer_size]u8 = undefined;
- var stack = std.heap.FixedBufferAllocator.init(buffer[0..]);
- var a = wrapInt(&stack.allocator, av);
-
+ pub fn shiftLeft(r: *Int, a: Int, shift: usize) !void {
try r.ensureCapacity(a.len + (shift / Limb.bit_count) + 1);
llshl(r.limbs[0..], a.limbs[0..a.len], shift);
r.norm1(a.len + (shift / Limb.bit_count) + 1);
@@ -927,11 +878,7 @@ pub const Int = struct {
}
// r = a >> shift
- pub fn shiftRight(r: *Int, av: var, shift: usize) !void {
- var buffer: [wrapped_buffer_size]u8 = undefined;
- var stack = std.heap.FixedBufferAllocator.init(buffer[0..]);
- var a = wrapInt(&stack.allocator, av);
-
+ pub fn shiftRight(r: *Int, a: Int, shift: usize) !void {
if (a.len <= shift / Limb.bit_count) {
r.len = 1;
r.limbs[0] = 0;
@@ -966,12 +913,7 @@ pub const Int = struct {
}
// r = a | b
- pub fn bitOr(r: *Int, av: var, bv: var) !void {
- var buffer: [2 * wrapped_buffer_size]u8 = undefined;
- var stack = std.heap.FixedBufferAllocator.init(buffer[0..]);
- var a = wrapInt(&stack.allocator, av);
- var b = wrapInt(&stack.allocator, bv);
-
+ pub fn bitOr(r: *Int, a: Int, b: Int) !void {
if (a.len > b.len) {
try r.ensureCapacity(a.len);
llor(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);
@@ -998,12 +940,7 @@ pub const Int = struct {
}
// r = a & b
- pub fn bitAnd(r: *Int, av: var, bv: var) !void {
- var buffer: [2 * wrapped_buffer_size]u8 = undefined;
- var stack = std.heap.FixedBufferAllocator.init(buffer[0..]);
- var a = wrapInt(&stack.allocator, av);
- var b = wrapInt(&stack.allocator, bv);
-
+ pub fn bitAnd(r: *Int, a: Int, b: Int) !void {
if (a.len > b.len) {
try r.ensureCapacity(b.len);
lland(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);
@@ -1027,12 +964,7 @@ pub const Int = struct {
}
// r = a ^ b
- pub fn bitXor(r: *Int, av: var, bv: var) !void {
- var buffer: [2 * wrapped_buffer_size]u8 = undefined;
- var stack = std.heap.FixedBufferAllocator.init(buffer[0..]);
- var a = wrapInt(&stack.allocator, av);
- var b = wrapInt(&stack.allocator, bv);
-
+ pub fn bitXor(r: *Int, a: Int, b: Int) !void {
if (a.len > b.len) {
try r.ensureCapacity(a.len);
llxor(r.limbs[0..], a.limbs[0..a.len], b.limbs[0..b.len]);
@@ -1065,7 +997,7 @@ pub const Int = struct {
// may be untested in some cases.
const u256 = @IntType(false, 256);
-var al = debug.global_allocator;
+const al = debug.global_allocator;
test "big.int comptime_int set" {
comptime var s = 0xefffffff00000001eeeeeeefaaaaaaab;
@@ -1198,7 +1130,7 @@ test "big.int bitcount + sizeInBase" {
debug.assert(a.sizeInBase(2) >= 32);
debug.assert(a.sizeInBase(10) >= 10);
- try a.shiftLeft(&a, 5000);
+ try a.shiftLeft(a, 5000);
debug.assert(a.bitcount() == 5032);
debug.assert(a.sizeInBase(2) >= 5032);
a.positive = false;
@@ -1320,40 +1252,40 @@ test "big.int compare" {
var a = try Int.initSet(al, -11);
var b = try Int.initSet(al, 10);
- debug.assert(a.cmpAbs(&b) == 1);
- debug.assert(a.cmp(&b) == -1);
+ debug.assert(a.cmpAbs(b) == 1);
+ debug.assert(a.cmp(b) == -1);
}
test "big.int compare similar" {
var a = try Int.initSet(al, 0xffffffffeeeeeeeeffffffffeeeeeeee);
var b = try Int.initSet(al, 0xffffffffeeeeeeeeffffffffeeeeeeef);
- debug.assert(a.cmpAbs(&b) == -1);
- debug.assert(b.cmpAbs(&a) == 1);
+ debug.assert(a.cmpAbs(b) == -1);
+ debug.assert(b.cmpAbs(a) == 1);
}
test "big.int compare different limb size" {
var a = try Int.initSet(al, @maxValue(Limb) + 1);
var b = try Int.initSet(al, 1);
- debug.assert(a.cmpAbs(&b) == 1);
- debug.assert(b.cmpAbs(&a) == -1);
+ debug.assert(a.cmpAbs(b) == 1);
+ debug.assert(b.cmpAbs(a) == -1);
}
test "big.int compare multi-limb" {
var a = try Int.initSet(al, -0x7777777799999999ffffeeeeffffeeeeffffeeeef);
var b = try Int.initSet(al, 0x7777777799999999ffffeeeeffffeeeeffffeeeee);
- debug.assert(a.cmpAbs(&b) == 1);
- debug.assert(a.cmp(&b) == -1);
+ debug.assert(a.cmpAbs(b) == 1);
+ debug.assert(a.cmp(b) == -1);
}
test "big.int equality" {
var a = try Int.initSet(al, 0xffffffff1);
var b = try Int.initSet(al, -0xffffffff1);
- debug.assert(a.eqAbs(&b));
- debug.assert(!a.eq(&b));
+ debug.assert(a.eqAbs(b));
+ debug.assert(!a.eq(b));
}
test "big.int abs" {
@@ -1381,7 +1313,7 @@ test "big.int add single-single" {
var b = try Int.initSet(al, 5);
var c = try Int.init(al);
- try c.add(&a, &b);
+ try c.add(a, b);
debug.assert((try c.to(u32)) == 55);
}
@@ -1392,10 +1324,10 @@ test "big.int add multi-single" {
var c = try Int.init(al);
- try c.add(&a, &b);
+ try c.add(a, b);
debug.assert((try c.to(DoubleLimb)) == @maxValue(Limb) + 2);
- try c.add(&b, &a);
+ try c.add(b, a);
debug.assert((try c.to(DoubleLimb)) == @maxValue(Limb) + 2);
}
@@ -1406,7 +1338,7 @@ test "big.int add multi-multi" {
var b = try Int.initSet(al, op2);
var c = try Int.init(al);
- try c.add(&a, &b);
+ try c.add(a, b);
debug.assert((try c.to(u128)) == op1 + op2);
}
@@ -1416,7 +1348,7 @@ test "big.int add zero-zero" {
var b = try Int.initSet(al, 0);
var c = try Int.init(al);
- try c.add(&a, &b);
+ try c.add(a, b);
debug.assert((try c.to(u32)) == 0);
}
@@ -1426,7 +1358,7 @@ test "big.int add alias multi-limb nonzero-zero" {
var a = try Int.initSet(al, op1);
var b = try Int.initSet(al, 0);
- try a.add(&a, &b);
+ try a.add(a, b);
debug.assert((try a.to(u128)) == op1);
}
@@ -1434,16 +1366,21 @@ test "big.int add alias multi-limb nonzero-zero" {
test "big.int add sign" {
var a = try Int.init(al);
- try a.add(1, 2);
+ const one = try Int.initSet(al, 1);
+ const two = try Int.initSet(al, 2);
+ const neg_one = try Int.initSet(al, -1);
+ const neg_two = try Int.initSet(al, -2);
+
+ try a.add(one, two);
debug.assert((try a.to(i32)) == 3);
- try a.add(-1, 2);
+ try a.add(neg_one, two);
debug.assert((try a.to(i32)) == 1);
- try a.add(1, -2);
+ try a.add(one, neg_two);
debug.assert((try a.to(i32)) == -1);
- try a.add(-1, -2);
+ try a.add(neg_one, neg_two);
debug.assert((try a.to(i32)) == -3);
}
@@ -1452,7 +1389,7 @@ test "big.int sub single-single" {
var b = try Int.initSet(al, 5);
var c = try Int.init(al);
- try c.sub(&a, &b);
+ try c.sub(a, b);
debug.assert((try c.to(u32)) == 45);
}
@@ -1462,7 +1399,7 @@ test "big.int sub multi-single" {
var b = try Int.initSet(al, 1);
var c = try Int.init(al);
- try c.sub(&a, &b);
+ try c.sub(a, b);
debug.assert((try c.to(Limb)) == @maxValue(Limb));
}
@@ -1475,7 +1412,7 @@ test "big.int sub multi-multi" {
var b = try Int.initSet(al, op2);
var c = try Int.init(al);
- try c.sub(&a, &b);
+ try c.sub(a, b);
debug.assert((try c.to(u128)) == op1 - op2);
}
@@ -1485,7 +1422,7 @@ test "big.int sub equal" {
var b = try Int.initSet(al, 0x11efefefefefefefefefefefef);
var c = try Int.init(al);
- try c.sub(&a, &b);
+ try c.sub(a, b);
debug.assert((try c.to(u32)) == 0);
}
@@ -1493,19 +1430,24 @@ test "big.int sub equal" {
test "big.int sub sign" {
var a = try Int.init(al);
- try a.sub(1, 2);
+ const one = try Int.initSet(al, 1);
+ const two = try Int.initSet(al, 2);
+ const neg_one = try Int.initSet(al, -1);
+ const neg_two = try Int.initSet(al, -2);
+
+ try a.sub(one, two);
debug.assert((try a.to(i32)) == -1);
- try a.sub(-1, 2);
+ try a.sub(neg_one, two);
debug.assert((try a.to(i32)) == -3);
- try a.sub(1, -2);
+ try a.sub(one, neg_two);
debug.assert((try a.to(i32)) == 3);
- try a.sub(-1, -2);
+ try a.sub(neg_one, neg_two);
debug.assert((try a.to(i32)) == 1);
- try a.sub(-2, -1);
+ try a.sub(neg_two, neg_one);
debug.assert((try a.to(i32)) == -1);
}
@@ -1514,7 +1456,7 @@ test "big.int mul single-single" {
var b = try Int.initSet(al, 5);
var c = try Int.init(al);
- try c.mul(&a, &b);
+ try c.mul(a, b);
debug.assert((try c.to(u64)) == 250);
}
@@ -1524,7 +1466,7 @@ test "big.int mul multi-single" {
var b = try Int.initSet(al, 2);
var c = try Int.init(al);
- try c.mul(&a, &b);
+ try c.mul(a, b);
debug.assert((try c.to(DoubleLimb)) == 2 * @maxValue(Limb));
}
@@ -1536,7 +1478,7 @@ test "big.int mul multi-multi" {
var b = try Int.initSet(al, op2);
var c = try Int.init(al);
- try c.mul(&a, &b);
+ try c.mul(a, b);
debug.assert((try c.to(u256)) == op1 * op2);
}
@@ -1545,7 +1487,7 @@ test "big.int mul alias r with a" {
var a = try Int.initSet(al, @maxValue(Limb));
var b = try Int.initSet(al, 2);
- try a.mul(&a, &b);
+ try a.mul(a, b);
debug.assert((try a.to(DoubleLimb)) == 2 * @maxValue(Limb));
}
@@ -1554,7 +1496,7 @@ test "big.int mul alias r with b" {
var a = try Int.initSet(al, @maxValue(Limb));
var b = try Int.initSet(al, 2);
- try a.mul(&b, &a);
+ try a.mul(b, a);
debug.assert((try a.to(DoubleLimb)) == 2 * @maxValue(Limb));
}
@@ -1562,7 +1504,7 @@ test "big.int mul alias r with b" {
test "big.int mul alias r with a and b" {
var a = try Int.initSet(al, @maxValue(Limb));
- try a.mul(&a, &a);
+ try a.mul(a, a);
debug.assert((try a.to(DoubleLimb)) == @maxValue(Limb) * @maxValue(Limb));
}
@@ -1572,7 +1514,7 @@ test "big.int mul a*0" {
var b = try Int.initSet(al, 0);
var c = try Int.init(al);
- try c.mul(&a, &b);
+ try c.mul(a, b);
debug.assert((try c.to(u32)) == 0);
}
@@ -1582,7 +1524,7 @@ test "big.int mul 0*0" {
var b = try Int.initSet(al, 0);
var c = try Int.init(al);
- try c.mul(&a, &b);
+ try c.mul(a, b);
debug.assert((try c.to(u32)) == 0);
}
@@ -1593,7 +1535,7 @@ test "big.int div single-single no rem" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divTrunc(&q, &r, &a, &b);
+ try Int.divTrunc(&q, &r, a, b);
debug.assert((try q.to(u32)) == 10);
debug.assert((try r.to(u32)) == 0);
@@ -1605,7 +1547,7 @@ test "big.int div single-single with rem" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divTrunc(&q, &r, &a, &b);
+ try Int.divTrunc(&q, &r, a, b);
debug.assert((try q.to(u32)) == 9);
debug.assert((try r.to(u32)) == 4);
@@ -1620,7 +1562,7 @@ test "big.int div multi-single no rem" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divTrunc(&q, &r, &a, &b);
+ try Int.divTrunc(&q, &r, a, b);
debug.assert((try q.to(u64)) == op1 / op2);
debug.assert((try r.to(u64)) == 0);
@@ -1635,7 +1577,7 @@ test "big.int div multi-single with rem" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divTrunc(&q, &r, &a, &b);
+ try Int.divTrunc(&q, &r, a, b);
debug.assert((try q.to(u64)) == op1 / op2);
debug.assert((try r.to(u64)) == 3);
@@ -1650,7 +1592,7 @@ test "big.int div multi>2-single" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divTrunc(&q, &r, &a, &b);
+ try Int.divTrunc(&q, &r, a, b);
debug.assert((try q.to(u128)) == op1 / op2);
debug.assert((try r.to(u32)) == 0x3e4e);
@@ -1662,7 +1604,7 @@ test "big.int div single-single q < r" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divTrunc(&q, &r, &a, &b);
+ try Int.divTrunc(&q, &r, a, b);
debug.assert((try q.to(u64)) == 0);
debug.assert((try r.to(u64)) == 0x0078f432);
@@ -1674,7 +1616,7 @@ test "big.int div single-single q == r" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divTrunc(&q, &r, &a, &b);
+ try Int.divTrunc(&q, &r, a, b);
debug.assert((try q.to(u64)) == 1);
debug.assert((try r.to(u64)) == 0);
@@ -1684,7 +1626,7 @@ test "big.int div q=0 alias" {
var a = try Int.initSet(al, 3);
var b = try Int.initSet(al, 10);
- try Int.divTrunc(&a, &b, &a, &b);
+ try Int.divTrunc(&a, &b, a, b);
debug.assert((try a.to(u64)) == 0);
debug.assert((try b.to(u64)) == 3);
@@ -1698,7 +1640,7 @@ test "big.int div multi-multi q < r" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divTrunc(&q, &r, &a, &b);
+ try Int.divTrunc(&q, &r, a, b);
debug.assert((try q.to(u128)) == 0);
debug.assert((try r.to(u128)) == op1);
@@ -1713,7 +1655,7 @@ test "big.int div trunc single-single +/+" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divTrunc(&q, &r, &a, &b);
+ try Int.divTrunc(&q, &r, a, b);
// n = q * d + r
// 5 = 1 * 3 + 2
@@ -1733,7 +1675,7 @@ test "big.int div trunc single-single -/+" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divTrunc(&q, &r, &a, &b);
+ try Int.divTrunc(&q, &r, a, b);
// n = q * d + r
// -5 = 1 * -3 - 2
@@ -1753,7 +1695,7 @@ test "big.int div trunc single-single +/-" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divTrunc(&q, &r, &a, &b);
+ try Int.divTrunc(&q, &r, a, b);
// n = q * d + r
// 5 = -1 * -3 + 2
@@ -1773,7 +1715,7 @@ test "big.int div trunc single-single -/-" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divTrunc(&q, &r, &a, &b);
+ try Int.divTrunc(&q, &r, a, b);
// n = q * d + r
// -5 = 1 * -3 - 2
@@ -1793,7 +1735,7 @@ test "big.int div floor single-single +/+" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divFloor(&q, &r, &a, &b);
+ try Int.divFloor(&q, &r, a, b);
// n = q * d + r
// 5 = 1 * 3 + 2
@@ -1813,7 +1755,7 @@ test "big.int div floor single-single -/+" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divFloor(&q, &r, &a, &b);
+ try Int.divFloor(&q, &r, a, b);
// n = q * d + r
// -5 = -2 * 3 + 1
@@ -1833,7 +1775,7 @@ test "big.int div floor single-single +/-" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divFloor(&q, &r, &a, &b);
+ try Int.divFloor(&q, &r, a, b);
// n = q * d + r
// 5 = -2 * -3 - 1
@@ -1853,7 +1795,7 @@ test "big.int div floor single-single -/-" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divFloor(&q, &r, &a, &b);
+ try Int.divFloor(&q, &r, a, b);
// n = q * d + r
// -5 = 2 * -3 + 1
@@ -1870,7 +1812,7 @@ test "big.int div multi-multi with rem" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divTrunc(&q, &r, &a, &b);
+ try Int.divTrunc(&q, &r, a, b);
debug.assert((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b);
debug.assert((try r.to(u128)) == 0x28de0acacd806823638);
@@ -1882,7 +1824,7 @@ test "big.int div multi-multi no rem" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divTrunc(&q, &r, &a, &b);
+ try Int.divTrunc(&q, &r, a, b);
debug.assert((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b);
debug.assert((try r.to(u128)) == 0);
@@ -1894,7 +1836,7 @@ test "big.int div multi-multi (2 branch)" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divTrunc(&q, &r, &a, &b);
+ try Int.divTrunc(&q, &r, a, b);
debug.assert((try q.to(u128)) == 0x10000000000000000);
debug.assert((try r.to(u128)) == 0x44444443444444431111111111111111);
@@ -1906,7 +1848,7 @@ test "big.int div multi-multi (3.1/3.3 branch)" {
var q = try Int.init(al);
var r = try Int.init(al);
- try Int.divTrunc(&q, &r, &a, &b);
+ try Int.divTrunc(&q, &r, a, b);
debug.assert((try q.to(u128)) == 0xfffffffffffffffffff);
debug.assert((try r.to(u256)) == 0x1111111111111111111110b12222222222222222282);
@@ -1943,17 +1885,17 @@ test "big.int shift-left multi" {
test "big.int shift-right negative" {
var a = try Int.init(al);
- try a.shiftRight(-20, 2);
+ try a.shiftRight(try Int.initSet(al, -20), 2);
debug.assert((try a.to(i32)) == -20 >> 2);
- try a.shiftRight(-5, 10);
+ try a.shiftRight(try Int.initSet(al, -5), 10);
debug.assert((try a.to(i32)) == -5 >> 10);
}
test "big.int shift-left negative" {
var a = try Int.init(al);
- try a.shiftRight(-10, 1232);
+ try a.shiftRight(try Int.initSet(al, -10), 1232);
debug.assert((try a.to(i32)) == -10 >> 1232);
}
@@ -1961,7 +1903,7 @@ test "big.int bitwise and simple" {
var a = try Int.initSet(al, 0xffffffff11111111);
var b = try Int.initSet(al, 0xeeeeeeee22222222);
- try a.bitAnd(&a, &b);
+ try a.bitAnd(a, b);
debug.assert((try a.to(u64)) == 0xeeeeeeee00000000);
}
@@ -1970,7 +1912,7 @@ test "big.int bitwise and multi-limb" {
var a = try Int.initSet(al, @maxValue(Limb) + 1);
var b = try Int.initSet(al, @maxValue(Limb));
- try a.bitAnd(&a, &b);
+ try a.bitAnd(a, b);
debug.assert((try a.to(u128)) == 0);
}
@@ -1979,7 +1921,7 @@ test "big.int bitwise xor simple" {
var a = try Int.initSet(al, 0xffffffff11111111);
var b = try Int.initSet(al, 0xeeeeeeee22222222);
- try a.bitXor(&a, &b);
+ try a.bitXor(a, b);
debug.assert((try a.to(u64)) == 0x1111111133333333);
}
@@ -1988,7 +1930,7 @@ test "big.int bitwise xor multi-limb" {
var a = try Int.initSet(al, @maxValue(Limb) + 1);
var b = try Int.initSet(al, @maxValue(Limb));
- try a.bitXor(&a, &b);
+ try a.bitXor(a, b);
debug.assert((try a.to(DoubleLimb)) == (@maxValue(Limb) + 1) ^ @maxValue(Limb));
}
@@ -1997,7 +1939,7 @@ test "big.int bitwise or simple" {
var a = try Int.initSet(al, 0xffffffff11111111);
var b = try Int.initSet(al, 0xeeeeeeee22222222);
- try a.bitOr(&a, &b);
+ try a.bitOr(a, b);
debug.assert((try a.to(u64)) == 0xffffffff33333333);
}
@@ -2006,7 +1948,7 @@ test "big.int bitwise or multi-limb" {
var a = try Int.initSet(al, @maxValue(Limb) + 1);
var b = try Int.initSet(al, @maxValue(Limb));
- try a.bitOr(&a, &b);
+ try a.bitOr(a, b);
// TODO: big.int.cpp or is wrong on multi-limb.
debug.assert((try a.to(DoubleLimb)) == (@maxValue(Limb) + 1) + @maxValue(Limb));
@@ -2015,9 +1957,9 @@ test "big.int bitwise or multi-limb" {
test "big.int var args" {
var a = try Int.initSet(al, 5);
- try a.add(&a, 6);
+ try a.add(a, try Int.initSet(al, 6));
debug.assert((try a.to(u64)) == 11);
- debug.assert(a.cmp(11) == 0);
- debug.assert(a.cmp(14) <= 0);
+ debug.assert(a.cmp(try Int.initSet(al, 11)) == 0);
+ debug.assert(a.cmp(try Int.initSet(al, 14)) <= 0);
}
diff --git a/std/mem.zig b/std/mem.zig
index f961c7862bd5de160f549af0c47db313ff8e729e..10b3eb8fef1a5a101bbb3bf9138866c55d17b281 100644
--- a/std/mem.zig
+++ b/std/mem.zig
@@ -40,16 +40,12 @@ pub const Allocator = struct {
/// Call destroy with the result
/// TODO once #733 is solved, this will replace create
- pub fn construct(self: *Allocator, init: var) t: {
- // TODO this is a workaround for type getting parsed as Error!&const T
- const T = @typeOf(init).Child;
- break :t Error!*T;
- } {
- const T = @typeOf(init).Child;
+ pub fn construct(self: *Allocator, init: var) Error!*@typeOf(init) {
+ const T = @typeOf(init);
if (@sizeOf(T) == 0) return &{};
const slice = try self.alloc(T, 1);
const ptr = &slice[0];
- ptr.* = init.*;
+ ptr.* = init;
return ptr;
}
diff --git a/test/cases/cast.zig b/test/cases/cast.zig
index ade1cf78aac76c09d2aba9749d3270853bcf9946..4c216010eb00cb53e1806954187cacebb3101ab5 100644
--- a/test/cases/cast.zig
+++ b/test/cases/cast.zig
@@ -318,14 +318,6 @@ fn testCastConstArrayRefToConstSlice() void {
assert(mem.eql(u8, slice, "aoeu"));
}
-test "var args implicitly casts by value arg to const ref" {
- foo("hello");
-}
-
-fn foo(args: ...) void {
- assert(@typeOf(args[0]) == *const [5]u8);
-}
-
test "peer type resolution: error and [N]T" {
// TODO: implicit error!T to error!U where T can implicitly cast to U
//assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
diff --git a/test/cases/fn.zig b/test/cases/fn.zig
index 2426a411dfd01e4ccb998ea031db7166641f0a75..12f22bfc356c4eaf4bb52107e83b8717c37615f7 100644
--- a/test/cases/fn.zig
+++ b/test/cases/fn.zig
@@ -121,7 +121,7 @@ test "assign inline fn to const variable" {
inline fn inlineFn() void {}
test "pass by non-copying value" {
- assert(bar(Point{ .x = 1, .y = 2 }) == 3);
+ assert(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
}
const Point = struct {
@@ -129,6 +129,50 @@ const Point = struct {
y: i32,
};
-fn bar(pt: Point) i32 {
+fn addPointCoords(pt: Point) i32 {
return pt.x + pt.y;
}
+
+test "pass by non-copying value through var arg" {
+ assert(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3);
+}
+
+fn addPointCoordsVar(pt: var) i32 {
+ comptime assert(@typeOf(pt) == Point);
+ return pt.x + pt.y;
+}
+
+test "pass by non-copying value as method" {
+ var pt = Point2{ .x = 1, .y = 2 };
+ assert(pt.addPointCoords() == 3);
+}
+
+const Point2 = struct {
+ x: i32,
+ y: i32,
+
+ fn addPointCoords(self: Point2) i32 {
+ return self.x + self.y;
+ }
+};
+
+test "pass by non-copying value as method, which is generic" {
+ var pt = Point3{ .x = 1, .y = 2 };
+ assert(pt.addPointCoords(i32) == 3);
+}
+
+const Point3 = struct {
+ x: i32,
+ y: i32,
+
+ fn addPointCoords(self: Point3, comptime T: type) i32 {
+ return self.x + self.y;
+ }
+};
+
+test "pass by non-copying value as method, at comptime" {
+ comptime {
+ var pt = Point2{ .x = 1, .y = 2 };
+ assert(pt.addPointCoords() == 3);
+ }
+}
diff --git a/test/cases/var_args.zig b/test/cases/var_args.zig
index 5ef41f52ba6cd053255a4da7d006cf575fcdc349..3eb6e304486b22492c7a3470f8cc4aa61dcd8fb1 100644
--- a/test/cases/var_args.zig
+++ b/test/cases/var_args.zig
@@ -75,18 +75,6 @@ test "array of var args functions" {
assert(!foos[1]());
}
-test "pass array and slice of same array to var args should have same pointers" {
- const array = "hi";
- const slice: []const u8 = array;
- return assertSlicePtrsEql(array, slice);
-}
-
-fn assertSlicePtrsEql(args: ...) void {
- const s1 = ([]const u8)(args[0]);
- const s2 = args[1];
- assert(s1.ptr == s2.ptr);
-}
-
test "pass zero length array to var args param" {
doNothingWithFirstArg("");
}
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 60ba2551726e5dabb0e321a2cf28750ced0e9c61..ed46e43066b8904de1194089e47f621e0f1bfa0b 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -2215,7 +2215,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ derp.init();
\\}
,
- ".tmp_source.zig:14:5: error: expected type 'i32', found '*const Foo'",
+ ".tmp_source.zig:14:5: error: expected type 'i32', found 'Foo'",
);
cases.add(
--
2.54.0
From 472b7ef7e6db4bdd4717ff5b44b63e233853bb06 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 16 Jun 2018 19:14:14 -0400
Subject: [PATCH 08/28] disable byval
---
src/codegen.cpp | 21 ---------------------
test/behavior.zig | 1 +
test/cases/byval_arg_var.zig | 27 +++++++++++++++++++++++++++
3 files changed, 28 insertions(+), 21 deletions(-)
create mode 100644 test/cases/byval_arg_var.zig
diff --git a/src/codegen.cpp b/src/codegen.cpp
index fedfcfa7440f0cd683884d9872bd60072e6a1555..425cdac0249f519665fc1e053c1b60ff48c7a1d4 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -326,13 +326,6 @@ static void addLLVMArgAttr(LLVMValueRef arg_val, unsigned param_index, const cha
return addLLVMAttr(arg_val, param_index + 1, attr_name);
}
-static void addLLVMCallsiteAttr(LLVMValueRef call_instr, unsigned param_index, const char *attr_name) {
- unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));
- assert(kind_id != 0);
- LLVMAttributeRef llvm_attr = LLVMCreateEnumAttribute(LLVMGetGlobalContext(), kind_id, 0);
- LLVMAddCallSiteAttribute(call_instr, param_index + 1, llvm_attr);
-}
-
static bool is_symbol_available(CodeGen *g, Buf *name) {
return g->exported_symbol_names.maybe_get(name) == nullptr && g->external_prototypes.maybe_get(name) == nullptr;
}
@@ -581,11 +574,6 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
if (param_type->id == TypeTableEntryIdPointer) {
addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "nonnull");
}
- // Note: byval is disabled on windows due to an LLVM bug:
- // https://github.com/ziglang/zig/issues/536
- if (is_byval && g->zig_target.os != OsWindows) {
- addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "byval");
- }
}
uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
@@ -3114,15 +3102,6 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
}
- for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) {
- FnGenParamInfo *gen_info = &fn_type->data.fn.gen_param_info[param_i];
- // Note: byval is disabled on windows due to an LLVM bug:
- // https://github.com/ziglang/zig/issues/536
- if (gen_info->is_byval && g->zig_target.os != OsWindows) {
- addLLVMCallsiteAttr(result, (unsigned)gen_info->gen_index, "byval");
- }
- }
-
if (instruction->is_async) {
LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_payload_index, "");
LLVMBuildStore(g->builder, result, payload_ptr);
diff --git a/test/behavior.zig b/test/behavior.zig
index eb8b643bb7376f06a528006bf1e116fa6b5934cf..096c07b2e0261096a8376cd4b6626ee48dc2944d 100644
--- a/test/behavior.zig
+++ b/test/behavior.zig
@@ -13,6 +13,7 @@ comptime {
_ = @import("cases/bugs/656.zig");
_ = @import("cases/bugs/828.zig");
_ = @import("cases/bugs/920.zig");
+ _ = @import("cases/byval_arg_var.zig");
_ = @import("cases/cast.zig");
_ = @import("cases/const_slice_child.zig");
_ = @import("cases/coroutines.zig");
diff --git a/test/cases/byval_arg_var.zig b/test/cases/byval_arg_var.zig
new file mode 100644
index 0000000000000000000000000000000000000000..826b9cc9e59334d4c67300ac5740929539c6217d
--- /dev/null
+++ b/test/cases/byval_arg_var.zig
@@ -0,0 +1,27 @@
+const std = @import("std");
+
+var result: []const u8 = "wrong";
+
+test "aoeu" {
+ start();
+ blowUpStack(10);
+
+ std.debug.assert(std.mem.eql(u8, result, "string literal"));
+}
+
+fn start() void {
+ foo("string literal");
+}
+
+fn foo(x: var) void {
+ bar(x);
+}
+
+fn bar(x: var) void {
+ result = x;
+}
+
+fn blowUpStack(x: u32) void {
+ if (x == 0) return;
+ blowUpStack(x - 1);
+}
--
2.54.0
From eae9634ac959bdb32c95f2acdcadde59beec23d5 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 16 Jun 2018 19:53:52 -0400
Subject: [PATCH 09/28] langref: be clear that float types are always IEEE 754
---
doc/langref.html.in | 27 ++++++++++++++++++++++++---
1 file changed, 24 insertions(+), 3 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 814de721a694f5c17406d91b78a798ebd066170d..039109f938024f9d5038c55ef741273d3256c4c4 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -370,17 +370,17 @@ pub fn main() void {
f32 |
float |
- 32-bit floating point (23-bit mantissa) |
+ 32-bit floating point (23-bit mantissa) IEEE-754-2008 binary32 |
f64 |
double |
- 64-bit floating point (52-bit mantissa) |
+ 64-bit floating point (52-bit mantissa) IEEE-754-2008 binary64 |
f128 |
(none) |
- 128-bit floating point (112-bit mantissa) |
+ 128-bit floating point (112-bit mantissa) IEEE-754-2008 binary128 |
bool |
@@ -407,6 +407,16 @@ pub fn main() void {
(none) |
an error code |
+
+ comptime_int |
+ (none) |
+ Only allowed for {#link|comptime#}-known values. The type of integer literals. |
+
+
+ comptime_float |
+ (none) |
+ Only allowed for {#link|comptime#}-known values. The type of float literals. |
+
{#see_also|Integers|Floats|void|Errors#}
@@ -642,7 +652,18 @@ fn divide(a: i32, b: i32) i32 {
{#header_close#}
{#header_close#}
{#header_open|Floats#}
+ Zig has the following floating point types:
+
+ f32 - IEEE-754-2008 binary32
+ f64 - IEEE-754-2008 binary64
+ f128 - IEEE-754-2008 binary128
+ c_longdouble - matches long double for the target C ABI
+
{#header_open|Float Literals#}
+
+ Float literals have type comptime_float which is guaranteed to hold at least all possible values
+ that the largest other floating point type can hold. Float literals implicitly cast to any other type.
+
{#code_begin|syntax#}
const floating_point = 123.0E+77;
const another_float = 123.0;
--
2.54.0
From 3ee4d23ebdd149e734ca33904a4786d5bd3fa8aa Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 16 Jun 2018 19:54:16 -0400
Subject: [PATCH 10/28] posix read can return error.IsDir
---
std/debug/index.zig | 1 +
std/os/file.zig | 11 +++++++++--
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/std/debug/index.zig b/std/debug/index.zig
index 25f7a58b2588fb1534ae4a6600e0acc2b9dfe326..fb1dac537c435b51f43b0b66eda95f9239af4094 100644
--- a/std/debug/index.zig
+++ b/std/debug/index.zig
@@ -639,6 +639,7 @@ const ParseFormValueError = error{
Unexpected,
InvalidDebugInfo,
EndOfFile,
+ IsDir,
OutOfMemory,
};
diff --git a/std/os/file.zig b/std/os/file.zig
index 41d3dfbf956cd9956e0a54314bc91189a14321f5..7e05501831e8995521d436c1ea3c4fd6f6f7e77b 100644
--- a/std/os/file.zig
+++ b/std/os/file.zig
@@ -311,9 +311,15 @@ pub const File = struct {
}
}
- pub const ReadError = error{};
+ pub const ReadError = error{
+ BadFd,
+ Io,
+ IsDir,
- pub fn read(self: *File, buffer: []u8) !usize {
+ Unexpected,
+ };
+
+ pub fn read(self: *File, buffer: []u8) ReadError!usize {
if (is_posix) {
var index: usize = 0;
while (index < buffer.len) {
@@ -326,6 +332,7 @@ pub const File = struct {
posix.EFAULT => unreachable,
posix.EBADF => return error.BadFd,
posix.EIO => return error.Io,
+ posix.EISDIR => return error.IsDir,
else => return os.unexpectedErrorPosix(read_err),
}
}
--
2.54.0
From 06a26f0965deff3d752da3d448b34872010d80f3 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 16 Jun 2018 21:32:53 -0400
Subject: [PATCH 11/28] std.Complex: use better arg passing convention and fix
a TODO
---
std/math/complex/index.zig | 14 +++++++-------
std/math/complex/sqrt.zig | 9 ++++-----
2 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/std/math/complex/index.zig b/std/math/complex/index.zig
index b00296bedae6ed60421d7834243a9ffd1f2021d1..63a261698400f65a6945f4995a4703b965f60893 100644
--- a/std/math/complex/index.zig
+++ b/std/math/complex/index.zig
@@ -37,28 +37,28 @@ pub fn Complex(comptime T: type) type {
};
}
- pub fn add(self: *const Self, other: *const Self) Self {
+ pub fn add(self: Self, other: Self) Self {
return Self{
.re = self.re + other.re,
.im = self.im + other.im,
};
}
- pub fn sub(self: *const Self, other: *const Self) Self {
+ pub fn sub(self: Self, other: Self) Self {
return Self{
.re = self.re - other.re,
.im = self.im - other.im,
};
}
- pub fn mul(self: *const Self, other: *const Self) Self {
+ pub fn mul(self: Self, other: Self) Self {
return Self{
.re = self.re * other.re - self.im * other.im,
.im = self.im * other.re + self.re * other.im,
};
}
- pub fn div(self: *const Self, other: *const Self) Self {
+ pub fn div(self: Self, other: Self) Self {
const re_num = self.re * other.re + self.im * other.im;
const im_num = self.im * other.re - self.re * other.im;
const den = other.re * other.re + other.im * other.im;
@@ -69,14 +69,14 @@ pub fn Complex(comptime T: type) type {
};
}
- pub fn conjugate(self: *const Self) Self {
+ pub fn conjugate(self: Self) Self {
return Self{
.re = self.re,
.im = -self.im,
};
}
- pub fn reciprocal(self: *const Self) Self {
+ pub fn reciprocal(self: Self) Self {
const m = self.re * self.re + self.im * self.im;
return Self{
.re = self.re / m,
@@ -84,7 +84,7 @@ pub fn Complex(comptime T: type) type {
};
}
- pub fn magnitude(self: *const Self) T {
+ pub fn magnitude(self: Self) T {
return math.sqrt(self.re * self.re + self.im * self.im);
}
};
diff --git a/std/math/complex/sqrt.zig b/std/math/complex/sqrt.zig
index d4f5a6752813dd12f320bcea24da0e0d475e80c4..caa3bd28680a712edeede6ee9a22e4ff5f8ff66e 100644
--- a/std/math/complex/sqrt.zig
+++ b/std/math/complex/sqrt.zig
@@ -4,18 +4,17 @@ const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
-// TODO when #733 is solved this can be @typeOf(z) instead of Complex(@typeOf(z.re))
-pub fn sqrt(z: var) Complex(@typeOf(z.re)) {
+pub fn sqrt(z: var) @typeOf(z) {
const T = @typeOf(z.re);
return switch (T) {
f32 => sqrt32(z),
f64 => sqrt64(z),
- else => @compileError("sqrt not implemented for " ++ @typeName(z)),
+ else => @compileError("sqrt not implemented for " ++ @typeName(T)),
};
}
-fn sqrt32(z: *const Complex(f32)) Complex(f32) {
+fn sqrt32(z: Complex(f32)) Complex(f32) {
const x = z.re;
const y = z.im;
@@ -57,7 +56,7 @@ fn sqrt32(z: *const Complex(f32)) Complex(f32) {
}
}
-fn sqrt64(z: *const Complex(f64)) Complex(f64) {
+fn sqrt64(z: Complex(f64)) Complex(f64) {
// may encounter overflow for im,re >= DBL_MAX / (1 + sqrt(2))
const threshold = 0x1.a827999fcef32p+1022;
--
2.54.0
From 79120612267f55901029dd57290ee90c0a3ec987 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sun, 17 Jun 2018 02:57:07 -0400
Subject: [PATCH 12/28] remove integer and float casting syntax
* add `@intCast`
* add `@floatCast`
* add `@floatToInt`
* add `@intToFloat`
See #1061
---
doc/langref.html.in | 12 +-
src/all_types.hpp | 36 ++++
src/codegen.cpp | 8 +
src/ir.cpp | 296 +++++++++++++++++++++++++---
src/ir_print.cpp | 44 +++++
src/main.cpp | 2 +-
std/array_list.zig | 8 +-
std/base64.zig | 4 +-
std/crypto/blake2.zig | 10 +-
std/crypto/md5.zig | 6 +-
std/crypto/sha1.zig | 6 +-
std/crypto/sha2.zig | 12 +-
std/debug/index.zig | 8 +-
std/fmt/errol/index.zig | 78 ++++----
std/fmt/index.zig | 19 +-
std/hash/crc.zig | 4 +-
std/hash/siphash.zig | 6 +-
std/heap.zig | 2 +-
std/json.zig | 2 +-
std/math/acos.zig | 4 +-
std/math/asin.zig | 4 +-
std/math/atan.zig | 4 +-
std/math/atan2.zig | 8 +-
std/math/atanh.zig | 2 +-
std/math/big/int.zig | 22 +--
std/math/cbrt.zig | 6 +-
std/math/ceil.zig | 4 +-
std/math/complex/atan.zig | 10 +-
std/math/complex/cosh.zig | 4 +-
std/math/complex/exp.zig | 6 +-
std/math/complex/ldexp.zig | 13 +-
std/math/complex/sinh.zig | 10 +-
std/math/complex/sqrt.zig | 10 +-
std/math/complex/tanh.zig | 10 +-
std/math/cos.zig | 4 +-
std/math/cosh.zig | 2 +-
std/math/exp.zig | 12 +-
std/math/exp2.zig | 14 +-
std/math/expm1.zig | 20 +-
std/math/floor.zig | 4 +-
std/math/fma.zig | 6 +-
std/math/frexp.zig | 4 +-
std/math/hypot.zig | 2 +-
std/math/ilogb.zig | 4 +-
std/math/index.zig | 25 ++-
std/math/ln.zig | 12 +-
std/math/log.zig | 11 +-
std/math/log10.zig | 14 +-
std/math/log1p.zig | 12 +-
std/math/log2.zig | 12 +-
std/math/modf.zig | 8 +-
std/math/pow.zig | 4 +-
std/math/scalbn.zig | 4 +-
std/math/sin.zig | 4 +-
std/math/sinh.zig | 2 +-
std/math/sqrt.zig | 2 +-
std/math/tan.zig | 4 +-
std/math/tanh.zig | 4 +-
std/math/trunc.zig | 8 +-
std/mem.zig | 2 +-
std/os/child_process.zig | 2 +-
std/os/darwin.zig | 11 +-
std/os/file.zig | 6 +-
std/os/index.zig | 16 +-
std/os/linux/index.zig | 80 ++++----
std/os/linux/test.zig | 6 +-
std/os/linux/vdso.zig | 4 +-
std/os/time.zig | 24 +--
std/os/windows/util.zig | 9 +-
std/rand/index.zig | 16 +-
std/segmented_list.zig | 12 +-
std/special/bootstrap.zig | 2 +-
std/special/builtin.zig | 30 +--
std/special/compiler_rt/divti3.zig | 2 +-
std/special/compiler_rt/fixuint.zig | 8 +-
std/special/compiler_rt/index.zig | 12 +-
std/special/compiler_rt/udivmod.zig | 34 ++--
std/unicode.zig | 20 +-
std/zig/tokenizer.zig | 2 +-
test/cases/cast.zig | 18 +-
test/cases/enum.zig | 2 +-
test/cases/eval.zig | 8 +-
test/cases/fn.zig | 2 +-
test/cases/for.zig | 4 +-
test/cases/struct.zig | 8 +-
85 files changed, 802 insertions(+), 416 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 651629d8fb1285c5c9ab5b427b38be7928a57d19..35ca9a13b43d9c07062d60a55d69541ee139ac2e 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -1355,7 +1355,7 @@ var some_integers: [100]i32 = undefined;
test "modify an array" {
for (some_integers) |*item, i| {
- item.* = i32(i);
+ item.* = @intCast(i32, i);
}
assert(some_integers[10] == 10);
assert(some_integers[99] == 99);
@@ -1397,8 +1397,8 @@ var fancy_array = init: {
var initial_value: [10]Point = undefined;
for (initial_value) |*pt, i| {
pt.* = Point{
- .x = i32(i),
- .y = i32(i) * 2,
+ .x = @intCast(i32, i),
+ .y = @intCast(i32, i) * 2,
};
}
break :init initial_value;
@@ -2410,7 +2410,7 @@ test "for basics" {
var sum2: i32 = 0;
for (items) |value, i| {
assert(@typeOf(i) == usize);
- sum2 += i32(i);
+ sum2 += @intCast(i32, i);
}
assert(sum2 == 10);
}
@@ -5730,7 +5730,7 @@ comptime {
{#code_begin|test_err|attempt to cast negative value to unsigned integer#}
comptime {
const value: i32 = -1;
- const unsigned = u32(value);
+ const unsigned = @intCast(u32, value);
}
{#code_end#}
At runtime crashes with the message attempt to cast negative value to unsigned integer and a stack trace.
@@ -5744,7 +5744,7 @@ comptime {
{#code_begin|test_err|cast from 'u16' to 'u8' truncates bits#}
comptime {
const spartan_count: u16 = 300;
- const byte = u8(spartan_count);
+ const byte = @intCast(u8, spartan_count);
}
{#code_end#}
At runtime crashes with the message integer cast truncated bits and a stack trace.
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 0d364915f98e4f322ca6481d610daecdc18c3296..bc2fe07c188107b6e3011c1eea29740fb7462e08 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1357,6 +1357,10 @@ enum BuiltinFnId {
BuiltinFnIdMod,
BuiltinFnIdSqrt,
BuiltinFnIdTruncate,
+ BuiltinFnIdIntCast,
+ BuiltinFnIdFloatCast,
+ BuiltinFnIdIntToFloat,
+ BuiltinFnIdFloatToInt,
BuiltinFnIdIntType,
BuiltinFnIdSetCold,
BuiltinFnIdSetRuntimeSafety,
@@ -2040,6 +2044,10 @@ enum IrInstructionId {
IrInstructionIdCmpxchg,
IrInstructionIdFence,
IrInstructionIdTruncate,
+ IrInstructionIdIntCast,
+ IrInstructionIdFloatCast,
+ IrInstructionIdIntToFloat,
+ IrInstructionIdFloatToInt,
IrInstructionIdIntType,
IrInstructionIdBoolNot,
IrInstructionIdMemset,
@@ -2632,6 +2640,34 @@ struct IrInstructionTruncate {
IrInstruction *target;
};
+struct IrInstructionIntCast {
+ IrInstruction base;
+
+ IrInstruction *dest_type;
+ IrInstruction *target;
+};
+
+struct IrInstructionFloatCast {
+ IrInstruction base;
+
+ IrInstruction *dest_type;
+ IrInstruction *target;
+};
+
+struct IrInstructionIntToFloat {
+ IrInstruction base;
+
+ IrInstruction *dest_type;
+ IrInstruction *target;
+};
+
+struct IrInstructionFloatToInt {
+ IrInstruction base;
+
+ IrInstruction *dest_type;
+ IrInstruction *target;
+};
+
struct IrInstructionIntType {
IrInstruction base;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 425cdac0249f519665fc1e053c1b60ff48c7a1d4..4108cbbd687fc01123092077e922105fef105f85 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4722,6 +4722,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdPromiseResultType:
case IrInstructionIdAwaitBookkeeping:
case IrInstructionIdAddImplicitReturnType:
+ case IrInstructionIdIntCast:
+ case IrInstructionIdFloatCast:
+ case IrInstructionIdIntToFloat:
+ case IrInstructionIdFloatToInt:
zig_unreachable();
case IrInstructionIdReturn:
@@ -6310,6 +6314,10 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdCmpxchgStrong, "cmpxchgStrong", 6);
create_builtin_fn(g, BuiltinFnIdFence, "fence", 1);
create_builtin_fn(g, BuiltinFnIdTruncate, "truncate", 2);
+ create_builtin_fn(g, BuiltinFnIdIntCast, "intCast", 2);
+ create_builtin_fn(g, BuiltinFnIdFloatCast, "floatCast", 2);
+ create_builtin_fn(g, BuiltinFnIdIntToFloat, "intToFloat", 2);
+ create_builtin_fn(g, BuiltinFnIdFloatToInt, "floatToInt", 2);
create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
diff --git a/src/ir.cpp b/src/ir.cpp
index d008ead1132e6b7acdcd4a8156ce5601fd490e0a..0b847fc4e43f03776b4f1672dd37aa4ab74d87e9 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -460,6 +460,22 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTruncate *) {
return IrInstructionIdTruncate;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionIntCast *) {
+ return IrInstructionIdIntCast;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionFloatCast *) {
+ return IrInstructionIdFloatCast;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToFloat *) {
+ return IrInstructionIdIntToFloat;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionFloatToInt *) {
+ return IrInstructionIdFloatToInt;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionIntType *) {
return IrInstructionIdIntType;
}
@@ -1899,10 +1915,48 @@ static IrInstruction *ir_build_truncate(IrBuilder *irb, Scope *scope, AstNode *s
return &instruction->base;
}
-static IrInstruction *ir_build_truncate_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *dest_type, IrInstruction *target) {
- IrInstruction *new_instruction = ir_build_truncate(irb, old_instruction->scope, old_instruction->source_node, dest_type, target);
- ir_link_new_instruction(new_instruction, old_instruction);
- return new_instruction;
+static IrInstruction *ir_build_int_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) {
+ IrInstructionIntCast *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->dest_type = dest_type;
+ instruction->target = target;
+
+ ir_ref_instruction(dest_type, irb->current_basic_block);
+ ir_ref_instruction(target, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_float_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) {
+ IrInstructionFloatCast *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->dest_type = dest_type;
+ instruction->target = target;
+
+ ir_ref_instruction(dest_type, irb->current_basic_block);
+ ir_ref_instruction(target, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_int_to_float(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) {
+ IrInstructionIntToFloat *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->dest_type = dest_type;
+ instruction->target = target;
+
+ ir_ref_instruction(dest_type, irb->current_basic_block);
+ ir_ref_instruction(target, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_float_to_int(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) {
+ IrInstructionFloatToInt *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->dest_type = dest_type;
+ instruction->target = target;
+
+ ir_ref_instruction(dest_type, irb->current_basic_block);
+ ir_ref_instruction(target, irb->current_basic_block);
+
+ return &instruction->base;
}
static IrInstruction *ir_build_int_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *is_signed, IrInstruction *bit_count) {
@@ -3957,6 +4011,66 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
IrInstruction *truncate = ir_build_truncate(irb, scope, node, arg0_value, arg1_value);
return ir_lval_wrap(irb, scope, truncate, lval);
}
+ case BuiltinFnIdIntCast:
+ {
+ 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_int_cast(irb, scope, node, arg0_value, arg1_value);
+ return ir_lval_wrap(irb, scope, result, lval);
+ }
+ case BuiltinFnIdFloatCast:
+ {
+ 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_float_cast(irb, scope, node, arg0_value, arg1_value);
+ return ir_lval_wrap(irb, scope, result, lval);
+ }
+ case BuiltinFnIdIntToFloat:
+ {
+ 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_int_to_float(irb, scope, node, arg0_value, arg1_value);
+ return ir_lval_wrap(irb, scope, result, lval);
+ }
+ case BuiltinFnIdFloatToInt:
+ {
+ 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_float_to_int(irb, scope, node, arg0_value, arg1_value);
+ return ir_lval_wrap(irb, scope, result, lval);
+ }
case BuiltinFnIdIntType:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -9948,15 +10062,32 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpBoolToInt, false);
}
- // explicit widening or shortening cast
- if ((wanted_type->id == TypeTableEntryIdInt &&
- actual_type->id == TypeTableEntryIdInt) ||
- (wanted_type->id == TypeTableEntryIdFloat &&
- actual_type->id == TypeTableEntryIdFloat))
+ // explicit widening conversion
+ if (wanted_type->id == TypeTableEntryIdInt &&
+ actual_type->id == TypeTableEntryIdInt &&
+ wanted_type->data.integral.is_signed == actual_type->data.integral.is_signed &&
+ wanted_type->data.integral.bit_count >= actual_type->data.integral.bit_count)
{
return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);
}
+ // small enough unsigned ints can get casted to large enough signed ints
+ if (wanted_type->id == TypeTableEntryIdInt && wanted_type->data.integral.is_signed &&
+ actual_type->id == TypeTableEntryIdInt && !actual_type->data.integral.is_signed &&
+ wanted_type->data.integral.bit_count > actual_type->data.integral.bit_count)
+ {
+ return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);
+ }
+
+ // explicit float widening conversion
+ if (wanted_type->id == TypeTableEntryIdFloat &&
+ actual_type->id == TypeTableEntryIdFloat &&
+ wanted_type->data.floating.bit_count >= actual_type->data.floating.bit_count)
+ {
+ return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);
+ }
+
+
// explicit error set cast
if (wanted_type->id == TypeTableEntryIdErrorSet &&
actual_type->id == TypeTableEntryIdErrorSet)
@@ -9964,20 +10095,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
return ir_analyze_err_set_cast(ira, source_instr, value, wanted_type);
}
- // explicit cast from int to float
- if (wanted_type->id == TypeTableEntryIdFloat &&
- actual_type->id == TypeTableEntryIdInt)
- {
- return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpIntToFloat, false);
- }
-
- // explicit cast from float to int
- if (wanted_type->id == TypeTableEntryIdInt &&
- actual_type->id == TypeTableEntryIdFloat)
- {
- return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpFloatToInt, false);
- }
-
// explicit cast from [N]T to []const T
if (is_slice(wanted_type) && actual_type->id == TypeTableEntryIdArray) {
TypeTableEntry *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
@@ -17365,7 +17482,126 @@ static TypeTableEntry *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruc
return dest_type;
}
- ir_build_truncate_from(&ira->new_irb, &instruction->base, dest_type_value, target);
+ IrInstruction *new_instruction = ir_build_truncate(&ira->new_irb, instruction->base.scope,
+ instruction->base.source_node, dest_type_value, target);
+ ir_link_new_instruction(new_instruction, &instruction->base);
+ return dest_type;
+}
+
+static TypeTableEntry *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstructionIntCast *instruction) {
+ TypeTableEntry *dest_type = ir_resolve_type(ira, instruction->dest_type->other);
+ if (type_is_invalid(dest_type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ if (dest_type->id != TypeTableEntryIdInt) {
+ ir_add_error(ira, instruction->dest_type, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name)));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
+ IrInstruction *target = instruction->target->other;
+ if (type_is_invalid(target->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ if (target->value.type->id == TypeTableEntryIdComptimeInt) {
+ if (ir_num_lit_fits_in_other_type(ira, target, dest_type, true)) {
+ IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, dest_type,
+ CastOpNumLitToConcrete, false);
+ if (type_is_invalid(result->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+ ir_link_new_instruction(result, &instruction->base);
+ return dest_type;
+ } else {
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+ }
+
+ if (target->value.type->id != TypeTableEntryIdInt) {
+ ir_add_error(ira, instruction->target, buf_sprintf("expected integer type, found '%s'",
+ buf_ptr(&target->value.type->name)));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
+ IrInstruction *result = ir_analyze_widen_or_shorten(ira, &instruction->base, target, dest_type);
+ if (type_is_invalid(result->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ ir_link_new_instruction(result, &instruction->base);
+ return dest_type;
+}
+
+static TypeTableEntry *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstructionFloatCast *instruction) {
+ TypeTableEntry *dest_type = ir_resolve_type(ira, instruction->dest_type->other);
+ if (type_is_invalid(dest_type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ if (dest_type->id != TypeTableEntryIdFloat) {
+ ir_add_error(ira, instruction->dest_type,
+ buf_sprintf("expected float type, found '%s'", buf_ptr(&dest_type->name)));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
+ IrInstruction *target = instruction->target->other;
+ if (type_is_invalid(target->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ if (target->value.type->id == TypeTableEntryIdComptimeInt ||
+ target->value.type->id == TypeTableEntryIdComptimeFloat)
+ {
+ if (ir_num_lit_fits_in_other_type(ira, target, dest_type, true)) {
+ CastOp op;
+ if (target->value.type->id == TypeTableEntryIdComptimeInt) {
+ op = CastOpIntToFloat;
+ } else {
+ op = CastOpNumLitToConcrete;
+ }
+ IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, dest_type, op, false);
+ if (type_is_invalid(result->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+ ir_link_new_instruction(result, &instruction->base);
+ return dest_type;
+ } else {
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+ }
+
+ if (target->value.type->id != TypeTableEntryIdFloat) {
+ ir_add_error(ira, instruction->target, buf_sprintf("expected float type, found '%s'",
+ buf_ptr(&target->value.type->name)));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
+ IrInstruction *result = ir_analyze_widen_or_shorten(ira, &instruction->base, target, dest_type);
+ if (type_is_invalid(result->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+ ir_link_new_instruction(result, &instruction->base);
+ return dest_type;
+}
+
+static TypeTableEntry *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) {
+ TypeTableEntry *dest_type = ir_resolve_type(ira, instruction->dest_type->other);
+ if (type_is_invalid(dest_type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ IrInstruction *target = instruction->target->other;
+ if (type_is_invalid(target->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpIntToFloat, false);
+ ir_link_new_instruction(result, &instruction->base);
+ return dest_type;
+}
+
+static TypeTableEntry *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrInstructionFloatToInt *instruction) {
+ TypeTableEntry *dest_type = ir_resolve_type(ira, instruction->dest_type->other);
+ if (type_is_invalid(dest_type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ IrInstruction *target = instruction->target->other;
+ if (type_is_invalid(target->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpFloatToInt, false);
+ ir_link_new_instruction(result, &instruction->base);
return dest_type;
}
@@ -19899,6 +20135,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_fence(ira, (IrInstructionFence *)instruction);
case IrInstructionIdTruncate:
return ir_analyze_instruction_truncate(ira, (IrInstructionTruncate *)instruction);
+ case IrInstructionIdIntCast:
+ return ir_analyze_instruction_int_cast(ira, (IrInstructionIntCast *)instruction);
+ case IrInstructionIdFloatCast:
+ return ir_analyze_instruction_float_cast(ira, (IrInstructionFloatCast *)instruction);
+ case IrInstructionIdIntToFloat:
+ return ir_analyze_instruction_int_to_float(ira, (IrInstructionIntToFloat *)instruction);
+ case IrInstructionIdFloatToInt:
+ return ir_analyze_instruction_float_to_int(ira, (IrInstructionFloatToInt *)instruction);
case IrInstructionIdIntType:
return ir_analyze_instruction_int_type(ira, (IrInstructionIntType *)instruction);
case IrInstructionIdBoolNot:
@@ -20242,6 +20486,10 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdPromiseResultType:
case IrInstructionIdSqrt:
case IrInstructionIdAtomicLoad:
+ case IrInstructionIdIntCast:
+ case IrInstructionIdFloatCast:
+ case IrInstructionIdIntToFloat:
+ case IrInstructionIdFloatToInt:
return false;
case IrInstructionIdAsm:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 43907fa9d43bf0917304194218cd7ec41369d145..b5722c52fae799e52c2401cd394ab3cb5fefd816 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -648,6 +648,38 @@ static void ir_print_truncate(IrPrint *irp, IrInstructionTruncate *instruction)
fprintf(irp->f, ")");
}
+static void ir_print_int_cast(IrPrint *irp, IrInstructionIntCast *instruction) {
+ fprintf(irp->f, "@intCast(");
+ ir_print_other_instruction(irp, instruction->dest_type);
+ fprintf(irp->f, ", ");
+ ir_print_other_instruction(irp, instruction->target);
+ fprintf(irp->f, ")");
+}
+
+static void ir_print_float_cast(IrPrint *irp, IrInstructionFloatCast *instruction) {
+ fprintf(irp->f, "@floatCast(");
+ ir_print_other_instruction(irp, instruction->dest_type);
+ fprintf(irp->f, ", ");
+ ir_print_other_instruction(irp, instruction->target);
+ fprintf(irp->f, ")");
+}
+
+static void ir_print_int_to_float(IrPrint *irp, IrInstructionIntToFloat *instruction) {
+ fprintf(irp->f, "@intToFloat(");
+ ir_print_other_instruction(irp, instruction->dest_type);
+ fprintf(irp->f, ", ");
+ ir_print_other_instruction(irp, instruction->target);
+ fprintf(irp->f, ")");
+}
+
+static void ir_print_float_to_int(IrPrint *irp, IrInstructionFloatToInt *instruction) {
+ fprintf(irp->f, "@floatToInt(");
+ ir_print_other_instruction(irp, instruction->dest_type);
+ fprintf(irp->f, ", ");
+ ir_print_other_instruction(irp, instruction->target);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_int_type(IrPrint *irp, IrInstructionIntType *instruction) {
fprintf(irp->f, "@IntType(");
ir_print_other_instruction(irp, instruction->is_signed);
@@ -1417,6 +1449,18 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdTruncate:
ir_print_truncate(irp, (IrInstructionTruncate *)instruction);
break;
+ case IrInstructionIdIntCast:
+ ir_print_int_cast(irp, (IrInstructionIntCast *)instruction);
+ break;
+ case IrInstructionIdFloatCast:
+ ir_print_float_cast(irp, (IrInstructionFloatCast *)instruction);
+ break;
+ case IrInstructionIdIntToFloat:
+ ir_print_int_to_float(irp, (IrInstructionIntToFloat *)instruction);
+ break;
+ case IrInstructionIdFloatToInt:
+ ir_print_float_to_int(irp, (IrInstructionFloatToInt *)instruction);
+ break;
case IrInstructionIdIntType:
ir_print_int_type(irp, (IrInstructionIntType *)instruction);
break;
diff --git a/src/main.cpp b/src/main.cpp
index c63a143bff46b364ec90954bedd54fb2803bc778..0fe12bb0cb67c19f6c9403dda13ae4a53195da88 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -34,7 +34,7 @@ static int usage(const char *arg0) {
" --assembly [source] add assembly file to build\n"
" --cache-dir [path] override the cache directory\n"
" --color [auto|off|on] enable or disable colored error messages\n"
- " --emit [filetype] emit a specific file format as compilation output\n"
+ " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
" --enable-timing-info print timing diagnostics\n"
" --libc-include-dir [path] directory where libc stdlib.h resides\n"
" --name [name] override output name\n"
diff --git a/std/array_list.zig b/std/array_list.zig
index fd1d5cbe26d99a84ddaced248ab60f4ac31f8368..b71f5be6ab94ddf56f4a7a54a7299fb973009d95 100644
--- a/std/array_list.zig
+++ b/std/array_list.zig
@@ -185,23 +185,23 @@ test "basic ArrayList test" {
{
var i: usize = 0;
while (i < 10) : (i += 1) {
- list.append(i32(i + 1)) catch unreachable;
+ list.append(@intCast(i32, i + 1)) catch unreachable;
}
}
{
var i: usize = 0;
while (i < 10) : (i += 1) {
- assert(list.items[i] == i32(i + 1));
+ assert(list.items[i] == @intCast(i32, i + 1));
}
}
for (list.toSlice()) |v, i| {
- assert(v == i32(i + 1));
+ assert(v == @intCast(i32, i + 1));
}
for (list.toSliceConst()) |v, i| {
- assert(v == i32(i + 1));
+ assert(v == @intCast(i32, i + 1));
}
assert(list.pop() == 10);
diff --git a/std/base64.zig b/std/base64.zig
index d27bcbd2012acd3c419bcc21c7eab590e3a4d5ca..45c8e22c7ecfb8346a8ba4d14080ab1aa14bb0a1 100644
--- a/std/base64.zig
+++ b/std/base64.zig
@@ -99,7 +99,7 @@ pub const Base64Decoder = struct {
assert(!result.char_in_alphabet[c]);
assert(c != pad_char);
- result.char_to_index[c] = u8(i);
+ result.char_to_index[c] = @intCast(u8, i);
result.char_in_alphabet[c] = true;
}
@@ -284,7 +284,7 @@ pub const Base64DecoderUnsafe = struct {
};
for (alphabet_chars) |c, i| {
assert(c != pad_char);
- result.char_to_index[c] = u8(i);
+ result.char_to_index[c] = @intCast(u8, i);
}
return result;
}
diff --git a/std/crypto/blake2.zig b/std/crypto/blake2.zig
index f0a9766c00692c05e38151342448a3d831d35f82..947133e4cffc59ceabb6be67d71b5da244a761ed 100644
--- a/std/crypto/blake2.zig
+++ b/std/crypto/blake2.zig
@@ -79,7 +79,7 @@ fn Blake2s(comptime out_len: usize) type {
mem.copy(u32, d.h[0..], iv[0..]);
// No key plus default parameters
- d.h[0] ^= 0x01010000 ^ u32(out_len >> 3);
+ d.h[0] ^= 0x01010000 ^ @intCast(u32, out_len >> 3);
d.t = 0;
d.buf_len = 0;
}
@@ -110,7 +110,7 @@ fn Blake2s(comptime out_len: usize) type {
// Copy any remainder for next pass.
mem.copy(u8, d.buf[d.buf_len..], b[off..]);
- d.buf_len += u8(b[off..].len);
+ d.buf_len += @intCast(u8, b[off..].len);
}
pub fn final(d: *Self, out: []u8) void {
@@ -144,7 +144,7 @@ fn Blake2s(comptime out_len: usize) type {
}
v[12] ^= @truncate(u32, d.t);
- v[13] ^= u32(d.t >> 32);
+ v[13] ^= @intCast(u32, d.t >> 32);
if (last) v[14] = ~v[14];
const rounds = comptime []RoundParam{
@@ -345,7 +345,7 @@ fn Blake2b(comptime out_len: usize) type {
// Copy any remainder for next pass.
mem.copy(u8, d.buf[d.buf_len..], b[off..]);
- d.buf_len += u8(b[off..].len);
+ d.buf_len += @intCast(u8, b[off..].len);
}
pub fn final(d: *Self, out: []u8) void {
@@ -377,7 +377,7 @@ fn Blake2b(comptime out_len: usize) type {
}
v[12] ^= @truncate(u64, d.t);
- v[13] ^= u64(d.t >> 64);
+ v[13] ^= @intCast(u64, d.t >> 64);
if (last) v[14] = ~v[14];
const rounds = comptime []RoundParam{
diff --git a/std/crypto/md5.zig b/std/crypto/md5.zig
index c0d1732d3715fab308cb23f191c23009d9ae5bbb..23fe2313a07686feb291a6b26ba80c6b27816750 100644
--- a/std/crypto/md5.zig
+++ b/std/crypto/md5.zig
@@ -78,7 +78,7 @@ pub const Md5 = struct {
// Copy any remainder for next pass.
mem.copy(u8, d.buf[d.buf_len..], b[off..]);
- d.buf_len += u8(b[off..].len);
+ d.buf_len += @intCast(u8, b[off..].len);
// Md5 uses the bottom 64-bits for length padding
d.total_len +%= b.len;
@@ -103,9 +103,9 @@ pub const Md5 = struct {
// Append message length.
var i: usize = 1;
var len = d.total_len >> 5;
- d.buf[56] = u8(d.total_len & 0x1f) << 3;
+ d.buf[56] = @intCast(u8, d.total_len & 0x1f) << 3;
while (i < 8) : (i += 1) {
- d.buf[56 + i] = u8(len & 0xff);
+ d.buf[56 + i] = @intCast(u8, len & 0xff);
len >>= 8;
}
diff --git a/std/crypto/sha1.zig b/std/crypto/sha1.zig
index 9e46fc92395a52cbd0f2cfda19e77978e10c1f6e..5c91590c88f742c8937afa811fc3c506a71920f1 100644
--- a/std/crypto/sha1.zig
+++ b/std/crypto/sha1.zig
@@ -78,7 +78,7 @@ pub const Sha1 = struct {
// Copy any remainder for next pass.
mem.copy(u8, d.buf[d.buf_len..], b[off..]);
- d.buf_len += u8(b[off..].len);
+ d.buf_len += @intCast(u8, b[off..].len);
d.total_len += b.len;
}
@@ -102,9 +102,9 @@ pub const Sha1 = struct {
// Append message length.
var i: usize = 1;
var len = d.total_len >> 5;
- d.buf[63] = u8(d.total_len & 0x1f) << 3;
+ d.buf[63] = @intCast(u8, d.total_len & 0x1f) << 3;
while (i < 8) : (i += 1) {
- d.buf[63 - i] = u8(len & 0xff);
+ d.buf[63 - i] = @intCast(u8, len & 0xff);
len >>= 8;
}
diff --git a/std/crypto/sha2.zig b/std/crypto/sha2.zig
index d1375d73e8bc50eb488a2c30d9a21b9b0f7197bf..d1b915835cbef78a0d6fe03c0dd5f6792da51245 100644
--- a/std/crypto/sha2.zig
+++ b/std/crypto/sha2.zig
@@ -131,7 +131,7 @@ fn Sha2_32(comptime params: Sha2Params32) type {
// Copy any remainder for next pass.
mem.copy(u8, d.buf[d.buf_len..], b[off..]);
- d.buf_len += u8(b[off..].len);
+ d.buf_len += @intCast(u8, b[off..].len);
d.total_len += b.len;
}
@@ -155,9 +155,9 @@ fn Sha2_32(comptime params: Sha2Params32) type {
// Append message length.
var i: usize = 1;
var len = d.total_len >> 5;
- d.buf[63] = u8(d.total_len & 0x1f) << 3;
+ d.buf[63] = @intCast(u8, d.total_len & 0x1f) << 3;
while (i < 8) : (i += 1) {
- d.buf[63 - i] = u8(len & 0xff);
+ d.buf[63 - i] = @intCast(u8, len & 0xff);
len >>= 8;
}
@@ -472,7 +472,7 @@ fn Sha2_64(comptime params: Sha2Params64) type {
// Copy any remainder for next pass.
mem.copy(u8, d.buf[d.buf_len..], b[off..]);
- d.buf_len += u8(b[off..].len);
+ d.buf_len += @intCast(u8, b[off..].len);
d.total_len += b.len;
}
@@ -496,9 +496,9 @@ fn Sha2_64(comptime params: Sha2Params64) type {
// Append message length.
var i: usize = 1;
var len = d.total_len >> 5;
- d.buf[127] = u8(d.total_len & 0x1f) << 3;
+ d.buf[127] = @intCast(u8, d.total_len & 0x1f) << 3;
while (i < 16) : (i += 1) {
- d.buf[127 - i] = u8(len & 0xff);
+ d.buf[127 - i] = @intCast(u8, len & 0xff);
len >>= 8;
}
diff --git a/std/debug/index.zig b/std/debug/index.zig
index fb1dac537c435b51f43b0b66eda95f9239af4094..198e0f90f61e4a58cd3f01604c3e021345383dd4 100644
--- a/std/debug/index.zig
+++ b/std/debug/index.zig
@@ -554,7 +554,7 @@ const LineNumberProgram = struct {
const file_name = try os.path.join(self.file_entries.allocator, dir_name, file_entry.file_name);
errdefer self.file_entries.allocator.free(file_name);
return LineInfo{
- .line = if (self.prev_line >= 0) usize(self.prev_line) else 0,
+ .line = if (self.prev_line >= 0) @intCast(usize, self.prev_line) else 0,
.column = self.prev_column,
.file_name = file_name,
.allocator = self.file_entries.allocator,
@@ -1070,7 +1070,7 @@ fn readULeb128(in_stream: var) !u64 {
var operand: u64 = undefined;
- if (@shlWithOverflow(u64, byte & 0b01111111, u6(shift), &operand)) return error.InvalidDebugInfo;
+ if (@shlWithOverflow(u64, byte & 0b01111111, @intCast(u6, shift), &operand)) return error.InvalidDebugInfo;
result |= operand;
@@ -1089,13 +1089,13 @@ fn readILeb128(in_stream: var) !i64 {
var operand: i64 = undefined;
- if (@shlWithOverflow(i64, byte & 0b01111111, u6(shift), &operand)) return error.InvalidDebugInfo;
+ if (@shlWithOverflow(i64, byte & 0b01111111, @intCast(u6, shift), &operand)) return error.InvalidDebugInfo;
result |= operand;
shift += 7;
if ((byte & 0b10000000) == 0) {
- if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0) result |= -(i64(1) << u6(shift));
+ if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0) result |= -(i64(1) << @intCast(u6, shift));
return result;
}
}
diff --git a/std/fmt/errol/index.zig b/std/fmt/errol/index.zig
index a906b714ab4d929009d35119d3a9cf462d2646cc..a5fb692857d92f3910d9c56e845bae26a17aadfa 100644
--- a/std/fmt/errol/index.zig
+++ b/std/fmt/errol/index.zig
@@ -29,11 +29,11 @@ pub fn roundToPrecision(float_decimal: *FloatDecimal, precision: usize, mode: Ro
switch (mode) {
RoundMode.Decimal => {
if (float_decimal.exp >= 0) {
- round_digit = precision + usize(float_decimal.exp);
+ round_digit = precision + @intCast(usize, float_decimal.exp);
} else {
// if a small negative exp, then adjust we need to offset by the number
// of leading zeros that will occur.
- const min_exp_required = usize(-float_decimal.exp);
+ const min_exp_required = @intCast(usize, -float_decimal.exp);
if (precision > min_exp_required) {
round_digit = precision - min_exp_required;
}
@@ -107,16 +107,16 @@ fn errol3u(val: f64, buffer: []u8) FloatDecimal {
// normalize the midpoint
const e = math.frexp(val).exponent;
- var exp = i16(math.floor(307 + f64(e) * 0.30103));
+ var exp = @floatToInt(i16, math.floor(307 + @intToFloat(f64, e) * 0.30103));
if (exp < 20) {
exp = 20;
- } else if (usize(exp) >= lookup_table.len) {
- exp = i16(lookup_table.len - 1);
+ } else if (@intCast(usize, exp) >= lookup_table.len) {
+ exp = @intCast(i16, lookup_table.len - 1);
}
- var mid = lookup_table[usize(exp)];
+ var mid = lookup_table[@intCast(usize, exp)];
mid = hpProd(mid, val);
- const lten = lookup_table[usize(exp)].val;
+ const lten = lookup_table[@intCast(usize, exp)].val;
exp -= 307;
@@ -168,25 +168,25 @@ fn errol3u(val: f64, buffer: []u8) FloatDecimal {
// the 0-index for this extra digit.
var buf_index: usize = 1;
while (true) {
- var hdig = u8(math.floor(high.val));
- if ((high.val == f64(hdig)) and (high.off < 0)) hdig -= 1;
+ var hdig = @floatToInt(u8, math.floor(high.val));
+ if ((high.val == @intToFloat(f64, hdig)) and (high.off < 0)) hdig -= 1;
- var ldig = u8(math.floor(low.val));
- if ((low.val == f64(ldig)) and (low.off < 0)) ldig -= 1;
+ var ldig = @floatToInt(u8, math.floor(low.val));
+ if ((low.val == @intToFloat(f64, ldig)) and (low.off < 0)) ldig -= 1;
if (ldig != hdig) break;
buffer[buf_index] = hdig + '0';
buf_index += 1;
- high.val -= f64(hdig);
- low.val -= f64(ldig);
+ high.val -= @intToFloat(f64, hdig);
+ low.val -= @intToFloat(f64, ldig);
hpMul10(&high);
hpMul10(&low);
}
const tmp = (high.val + low.val) / 2.0;
- var mdig = u8(math.floor(tmp + 0.5));
- if ((f64(mdig) - tmp) == 0.5 and (mdig & 0x1) != 0) mdig -= 1;
+ var mdig = @floatToInt(u8, math.floor(tmp + 0.5));
+ if ((@intToFloat(f64, mdig) - tmp) == 0.5 and (mdig & 0x1) != 0) mdig -= 1;
buffer[buf_index] = mdig + '0';
buf_index += 1;
@@ -304,7 +304,7 @@ fn errolInt(val: f64, buffer: []u8) FloatDecimal {
assert((val > 9.007199254740992e15) and val < (3.40282366920938e38));
- var mid = u128(val);
+ var mid = @floatToInt(u128, val);
var low: u128 = mid - fpeint((fpnext(val) - val) / 2.0);
var high: u128 = mid + fpeint((val - fpprev(val)) / 2.0);
@@ -314,11 +314,11 @@ fn errolInt(val: f64, buffer: []u8) FloatDecimal {
low -= 1;
}
- var l64 = u64(low % pow19);
- const lf = u64((low / pow19) % pow19);
+ var l64 = @intCast(u64, low % pow19);
+ const lf = @intCast(u64, (low / pow19) % pow19);
- var h64 = u64(high % pow19);
- const hf = u64((high / pow19) % pow19);
+ var h64 = @intCast(u64, high % pow19);
+ const hf = @intCast(u64, (high / pow19) % pow19);
if (lf != hf) {
l64 = lf;
@@ -348,7 +348,7 @@ fn errolInt(val: f64, buffer: []u8) FloatDecimal {
return FloatDecimal{
.digits = buffer[0..buf_index],
- .exp = i32(buf_index) + mi,
+ .exp = @intCast(i32, buf_index) + mi,
};
}
@@ -359,33 +359,33 @@ fn errolInt(val: f64, buffer: []u8) FloatDecimal {
fn errolFixed(val: f64, buffer: []u8) FloatDecimal {
assert((val >= 16.0) and (val < 9.007199254740992e15));
- const u = u64(val);
- const n = f64(u);
+ const u = @floatToInt(u64, val);
+ const n = @intToFloat(f64, u);
var mid = val - n;
var lo = ((fpprev(val) - n) + mid) / 2.0;
var hi = ((fpnext(val) - n) + mid) / 2.0;
var buf_index = u64toa(u, buffer);
- var exp = i32(buf_index);
+ var exp = @intCast(i32, buf_index);
var j = buf_index;
buffer[j] = 0;
if (mid != 0.0) {
while (mid != 0.0) {
lo *= 10.0;
- const ldig = i32(lo);
- lo -= f64(ldig);
+ const ldig = @floatToInt(i32, lo);
+ lo -= @intToFloat(f64, ldig);
mid *= 10.0;
- const mdig = i32(mid);
- mid -= f64(mdig);
+ const mdig = @floatToInt(i32, mid);
+ mid -= @intToFloat(f64, mdig);
hi *= 10.0;
- const hdig = i32(hi);
- hi -= f64(hdig);
+ const hdig = @floatToInt(i32, hi);
+ hi -= @intToFloat(f64, hdig);
- buffer[j] = u8(mdig + '0');
+ buffer[j] = @intCast(u8, mdig + '0');
j += 1;
if (hdig != ldig or j > 50) break;
@@ -452,7 +452,7 @@ fn u64toa(value_param: u64, buffer: []u8) usize {
var buf_index: usize = 0;
if (value < kTen8) {
- const v = u32(value);
+ const v = @intCast(u32, value);
if (v < 10000) {
const d1: u32 = (v / 100) << 1;
const d2: u32 = (v % 100) << 1;
@@ -507,8 +507,8 @@ fn u64toa(value_param: u64, buffer: []u8) usize {
buf_index += 1;
}
} else if (value < kTen16) {
- const v0: u32 = u32(value / kTen8);
- const v1: u32 = u32(value % kTen8);
+ const v0: u32 = @intCast(u32, value / kTen8);
+ const v1: u32 = @intCast(u32, value % kTen8);
const b0: u32 = v0 / 10000;
const c0: u32 = v0 % 10000;
@@ -578,11 +578,11 @@ fn u64toa(value_param: u64, buffer: []u8) usize {
buffer[buf_index] = c_digits_lut[d8 + 1];
buf_index += 1;
} else {
- const a = u32(value / kTen16); // 1 to 1844
+ const a = @intCast(u32, value / kTen16); // 1 to 1844
value %= kTen16;
if (a < 10) {
- buffer[buf_index] = '0' + u8(a);
+ buffer[buf_index] = '0' + @intCast(u8, a);
buf_index += 1;
} else if (a < 100) {
const i: u32 = a << 1;
@@ -591,7 +591,7 @@ fn u64toa(value_param: u64, buffer: []u8) usize {
buffer[buf_index] = c_digits_lut[i + 1];
buf_index += 1;
} else if (a < 1000) {
- buffer[buf_index] = '0' + u8(a / 100);
+ buffer[buf_index] = '0' + @intCast(u8, a / 100);
buf_index += 1;
const i: u32 = (a % 100) << 1;
@@ -612,8 +612,8 @@ fn u64toa(value_param: u64, buffer: []u8) usize {
buf_index += 1;
}
- const v0 = u32(value / kTen8);
- const v1 = u32(value % kTen8);
+ const v0 = @intCast(u32, value / kTen8);
+ const v1 = @intCast(u32, value % kTen8);
const b0: u32 = v0 / 10000;
const c0: u32 = v0 % 10000;
diff --git a/std/fmt/index.zig b/std/fmt/index.zig
index 90d3a559c4458c6c32b1f62af4268c51e8465e75..f4dfa0e3246bac951bbe38def0f3b31b5408d08b 100644
--- a/std/fmt/index.zig
+++ b/std/fmt/index.zig
@@ -5,6 +5,7 @@ const assert = debug.assert;
const mem = std.mem;
const builtin = @import("builtin");
const errol = @import("errol/index.zig");
+const lossyCast = std.math.lossyCast;
const max_int_digits = 65;
@@ -463,7 +464,7 @@ pub fn formatFloatDecimal(
errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Decimal);
// exp < 0 means the leading is always 0 as errol result is normalized.
- var num_digits_whole = if (float_decimal.exp > 0) usize(float_decimal.exp) else 0;
+ var num_digits_whole = if (float_decimal.exp > 0) @intCast(usize, float_decimal.exp) else 0;
// the actual slice into the buffer, we may need to zero-pad between num_digits_whole and this.
var num_digits_whole_no_pad = math.min(num_digits_whole, float_decimal.digits.len);
@@ -492,7 +493,7 @@ pub fn formatFloatDecimal(
// Zero-fill until we reach significant digits or run out of precision.
if (float_decimal.exp <= 0) {
- const zero_digit_count = usize(-float_decimal.exp);
+ const zero_digit_count = @intCast(usize, -float_decimal.exp);
const zeros_to_print = math.min(zero_digit_count, precision);
var i: usize = 0;
@@ -521,7 +522,7 @@ pub fn formatFloatDecimal(
}
} else {
// exp < 0 means the leading is always 0 as errol result is normalized.
- var num_digits_whole = if (float_decimal.exp > 0) usize(float_decimal.exp) else 0;
+ var num_digits_whole = if (float_decimal.exp > 0) @intCast(usize, float_decimal.exp) else 0;
// the actual slice into the buffer, we may need to zero-pad between num_digits_whole and this.
var num_digits_whole_no_pad = math.min(num_digits_whole, float_decimal.digits.len);
@@ -547,7 +548,7 @@ pub fn formatFloatDecimal(
// Zero-fill until we reach significant digits or run out of precision.
if (float_decimal.exp < 0) {
- const zero_digit_count = usize(-float_decimal.exp);
+ const zero_digit_count = @intCast(usize, -float_decimal.exp);
var i: usize = 0;
while (i < zero_digit_count) : (i += 1) {
@@ -578,7 +579,7 @@ pub fn formatBytes(
1024 => math.min(math.log2(value) / 10, mags_iec.len - 1),
else => unreachable,
};
- const new_value = f64(value) / math.pow(f64, f64(radix), f64(magnitude));
+ const new_value = lossyCast(f64, value) / math.pow(f64, lossyCast(f64, radix), lossyCast(f64, magnitude));
const suffix = switch (radix) {
1000 => mags_si[magnitude],
1024 => mags_iec[magnitude],
@@ -628,15 +629,15 @@ fn formatIntSigned(
if (value < 0) {
const minus_sign: u8 = '-';
try output(context, (*[1]u8)(&minus_sign)[0..]);
- const new_value = uint(-(value + 1)) + 1;
+ const new_value = @intCast(uint, -(value + 1)) + 1;
const new_width = if (width == 0) 0 else (width - 1);
return formatIntUnsigned(new_value, base, uppercase, new_width, context, Errors, output);
} else if (width == 0) {
- return formatIntUnsigned(uint(value), base, uppercase, width, context, Errors, output);
+ return formatIntUnsigned(@intCast(uint, value), base, uppercase, width, context, Errors, output);
} else {
const plus_sign: u8 = '+';
try output(context, (*[1]u8)(&plus_sign)[0..]);
- const new_value = uint(value);
+ const new_value = @intCast(uint, value);
const new_width = if (width == 0) 0 else (width - 1);
return formatIntUnsigned(new_value, base, uppercase, new_width, context, Errors, output);
}
@@ -660,7 +661,7 @@ fn formatIntUnsigned(
while (true) {
const digit = a % base;
index -= 1;
- buf[index] = digitToChar(u8(digit), uppercase);
+ buf[index] = digitToChar(@intCast(u8, digit), uppercase);
a /= base;
if (a == 0) break;
}
diff --git a/std/hash/crc.zig b/std/hash/crc.zig
index ec831cdc2ed36d7f807a48dceb3b8de4d0d40cdf..c4551407850a90f4ba359b9ed3c3e7bb0d504ea8 100644
--- a/std/hash/crc.zig
+++ b/std/hash/crc.zig
@@ -26,7 +26,7 @@ pub fn Crc32WithPoly(comptime poly: u32) type {
var tables: [8][256]u32 = undefined;
for (tables[0]) |*e, i| {
- var crc = u32(i);
+ var crc = @intCast(u32, i);
var j: usize = 0;
while (j < 8) : (j += 1) {
if (crc & 1 == 1) {
@@ -122,7 +122,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type {
var table: [16]u32 = undefined;
for (table) |*e, i| {
- var crc = u32(i * 16);
+ var crc = @intCast(u32, i * 16);
var j: usize = 0;
while (j < 8) : (j += 1) {
if (crc & 1 == 1) {
diff --git a/std/hash/siphash.zig b/std/hash/siphash.zig
index 8a90308a46993cc01f7a96390a61949e7287a04b..cdad77e59ecf0c4600f960067db6a2289ea15d6d 100644
--- a/std/hash/siphash.zig
+++ b/std/hash/siphash.zig
@@ -81,7 +81,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
// Remainder for next pass.
mem.copy(u8, d.buf[d.buf_len..], b[off..]);
- d.buf_len += u8(b[off..].len);
+ d.buf_len += @intCast(u8, b[off..].len);
d.msg_len +%= @truncate(u8, b.len);
}
@@ -233,7 +233,7 @@ test "siphash64-2-4 sanity" {
var buffer: [64]u8 = undefined;
for (vectors) |vector, i| {
- buffer[i] = u8(i);
+ buffer[i] = @intCast(u8, i);
const expected = mem.readInt(vector, u64, Endian.Little);
debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
@@ -312,7 +312,7 @@ test "siphash128-2-4 sanity" {
var buffer: [64]u8 = undefined;
for (vectors) |vector, i| {
- buffer[i] = u8(i);
+ buffer[i] = @intCast(u8, i);
const expected = mem.readInt(vector, u128, Endian.Little);
debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
diff --git a/std/heap.zig b/std/heap.zig
index 172bc2411822ff13601bc061bff2863cdfb23dee..2a2c8c0b59796421c64c13f358cfc5a0072f7aff 100644
--- a/std/heap.zig
+++ b/std/heap.zig
@@ -408,7 +408,7 @@ fn testAllocator(allocator: *mem.Allocator) !void {
for (slice) |*item, i| {
item.* = try allocator.create(i32);
- item.*.* = i32(i);
+ item.*.* = @intCast(i32, i);
}
for (slice) |item, i| {
diff --git a/std/json.zig b/std/json.zig
index 8bbee981e38725173ab0b676ba86339893e89f14..2930cd21bb19889b416a2bd38b176015b08306d3 100644
--- a/std/json.zig
+++ b/std/json.zig
@@ -180,7 +180,7 @@ pub const StreamingParser = struct {
pub fn fromInt(x: var) State {
debug.assert(x == 0 or x == 1);
const T = @TagType(State);
- return State(T(x));
+ return State(@intCast(T, x));
}
};
diff --git a/std/math/acos.zig b/std/math/acos.zig
index 284f73fc9150ddf3476dbde4112d9c4ec490494a..54844e8f6e4fe0131d8213462bdbfd6ec49b4e77 100644
--- a/std/math/acos.zig
+++ b/std/math/acos.zig
@@ -95,12 +95,12 @@ fn acos64(x: f64) f64 {
const pio2_lo: f64 = 6.12323399573676603587e-17;
const ux = @bitCast(u64, x);
- const hx = u32(ux >> 32);
+ const hx = @intCast(u32, ux >> 32);
const ix = hx & 0x7FFFFFFF;
// |x| >= 1 or nan
if (ix >= 0x3FF00000) {
- const lx = u32(ux & 0xFFFFFFFF);
+ const lx = @intCast(u32, ux & 0xFFFFFFFF);
// acos(1) = 0, acos(-1) = pi
if ((ix - 0x3FF00000) | lx == 0) {
diff --git a/std/math/asin.zig b/std/math/asin.zig
index 2ee3aa6048f13e37d0d3045bc09f9d9308852b48..30b3a57e3287e3de57d80b9f19b35f29eefd35e3 100644
--- a/std/math/asin.zig
+++ b/std/math/asin.zig
@@ -87,12 +87,12 @@ fn asin64(x: f64) f64 {
const pio2_lo: f64 = 6.12323399573676603587e-17;
const ux = @bitCast(u64, x);
- const hx = u32(ux >> 32);
+ const hx = @intCast(u32, ux >> 32);
const ix = hx & 0x7FFFFFFF;
// |x| >= 1 or nan
if (ix >= 0x3FF00000) {
- const lx = u32(ux & 0xFFFFFFFF);
+ const lx = @intCast(u32, ux & 0xFFFFFFFF);
// asin(1) = +-pi/2 with inexact
if ((ix - 0x3FF00000) | lx == 0) {
diff --git a/std/math/atan.zig b/std/math/atan.zig
index 7eceef98e3ae885e9f3245b514292df712a4cf87..6ca94dd84ae4a3a5b68e0a7abf3b9d9bd184b724 100644
--- a/std/math/atan.zig
+++ b/std/math/atan.zig
@@ -138,7 +138,7 @@ fn atan64(x_: f64) f64 {
var x = x_;
var ux = @bitCast(u64, x);
- var ix = u32(ux >> 32);
+ var ix = @intCast(u32, ux >> 32);
const sign = ix >> 31;
ix &= 0x7FFFFFFF;
@@ -159,7 +159,7 @@ fn atan64(x_: f64) f64 {
// |x| < 2^(-27)
if (ix < 0x3E400000) {
if (ix < 0x00100000) {
- math.forceEval(f32(x));
+ math.forceEval(@floatCast(f32, x));
}
return x;
}
diff --git a/std/math/atan2.zig b/std/math/atan2.zig
index f0a8e67c46013c176fb2444be3adb49a56dbd42a..b3e45ba0458df87ed852336f46fec1a49cc46c7a 100644
--- a/std/math/atan2.zig
+++ b/std/math/atan2.zig
@@ -124,12 +124,12 @@ fn atan2_64(y: f64, x: f64) f64 {
}
var ux = @bitCast(u64, x);
- var ix = u32(ux >> 32);
- var lx = u32(ux & 0xFFFFFFFF);
+ var ix = @intCast(u32, ux >> 32);
+ var lx = @intCast(u32, ux & 0xFFFFFFFF);
var uy = @bitCast(u64, y);
- var iy = u32(uy >> 32);
- var ly = u32(uy & 0xFFFFFFFF);
+ var iy = @intCast(u32, uy >> 32);
+ var ly = @intCast(u32, uy & 0xFFFFFFFF);
// x = 1.0
if ((ix -% 0x3FF00000) | lx == 0) {
diff --git a/std/math/atanh.zig b/std/math/atanh.zig
index 8ca0cc85bc928164d4b15e1400b97985daae6578..4ae8a66bc039bc776fa736d3425e43534439456b 100644
--- a/std/math/atanh.zig
+++ b/std/math/atanh.zig
@@ -62,7 +62,7 @@ fn atanh_64(x: f64) f64 {
if (e < 0x3FF - 32) {
// underflow
if (e == 0) {
- math.forceEval(f32(y));
+ math.forceEval(@floatCast(f32, y));
}
}
// |x| < 0.5
diff --git a/std/math/big/int.zig b/std/math/big/int.zig
index 5e15cfb895e3d97e9556f555177cc5f33ffcac67..21d9347c011988aef1fd404803b9521bf9b8fea6 100644
--- a/std/math/big/int.zig
+++ b/std/math/big/int.zig
@@ -135,7 +135,7 @@ pub const Int = struct {
self.positive = value >= 0;
self.len = 0;
- var w_value: UT = if (value < 0) UT(-value) else UT(value);
+ var w_value: UT = if (value < 0) @intCast(UT, -value) else @intCast(UT, value);
if (info.bits <= Limb.bit_count) {
self.limbs[0] = Limb(w_value);
@@ -198,7 +198,7 @@ pub const Int = struct {
var r: UT = 0;
if (@sizeOf(UT) <= @sizeOf(Limb)) {
- r = UT(self.limbs[0]);
+ r = @intCast(UT, self.limbs[0]);
} else {
for (self.limbs[0..self.len]) |_, ri| {
const limb = self.limbs[self.len - ri - 1];
@@ -210,7 +210,7 @@ pub const Int = struct {
if (!T.is_signed) {
return if (self.positive) r else error.NegativeIntoUnsigned;
} else {
- return if (self.positive) T(r) else -T(r);
+ return if (self.positive) @intCast(T, r) else -@intCast(T, r);
}
},
else => {
@@ -295,7 +295,7 @@ pub const Int = struct {
for (self.limbs[0..self.len]) |limb| {
var shift: usize = 0;
while (shift < Limb.bit_count) : (shift += base_shift) {
- const r = u8((limb >> Log2Limb(shift)) & Limb(base - 1));
+ const r = @intCast(u8, (limb >> @intCast(Log2Limb, shift)) & Limb(base - 1));
const ch = try digitToChar(r, base);
try digits.append(ch);
}
@@ -329,7 +329,7 @@ pub const Int = struct {
var r_word = r.limbs[0];
var i: usize = 0;
while (i < digits_per_limb) : (i += 1) {
- const ch = try digitToChar(u8(r_word % base), base);
+ const ch = try digitToChar(@intCast(u8, r_word % base), base);
r_word /= base;
try digits.append(ch);
}
@@ -340,7 +340,7 @@ pub const Int = struct {
var r_word = q.limbs[0];
while (r_word != 0) {
- const ch = try digitToChar(u8(r_word % base), base);
+ const ch = try digitToChar(@intCast(u8, r_word % base), base);
r_word /= base;
try digits.append(ch);
}
@@ -801,7 +801,7 @@ pub const Int = struct {
q.limbs[i - t - 1] = @maxValue(Limb);
} else {
const num = (DoubleLimb(x.limbs[i]) << Limb.bit_count) | DoubleLimb(x.limbs[i - 1]);
- const z = Limb(num / DoubleLimb(y.limbs[t]));
+ const z = @intCast(Limb, num / DoubleLimb(y.limbs[t]));
q.limbs[i - t - 1] = if (z > @maxValue(Limb)) @maxValue(Limb) else Limb(z);
}
@@ -860,7 +860,7 @@ pub const Int = struct {
debug.assert(r.len >= a.len + (shift / Limb.bit_count) + 1);
const limb_shift = shift / Limb.bit_count + 1;
- const interior_limb_shift = Log2Limb(shift % Limb.bit_count);
+ const interior_limb_shift = @intCast(Log2Limb, shift % Limb.bit_count);
var carry: Limb = 0;
var i: usize = 0;
@@ -869,7 +869,7 @@ pub const Int = struct {
const dst_i = src_i + limb_shift;
const src_digit = a[src_i];
- r[dst_i] = carry | @inlineCall(math.shr, Limb, src_digit, Limb.bit_count - Limb(interior_limb_shift));
+ r[dst_i] = carry | @inlineCall(math.shr, Limb, src_digit, Limb.bit_count - @intCast(Limb, interior_limb_shift));
carry = (src_digit << interior_limb_shift);
}
@@ -898,7 +898,7 @@ pub const Int = struct {
debug.assert(r.len >= a.len - (shift / Limb.bit_count));
const limb_shift = shift / Limb.bit_count;
- const interior_limb_shift = Log2Limb(shift % Limb.bit_count);
+ const interior_limb_shift = @intCast(Log2Limb, shift % Limb.bit_count);
var carry: Limb = 0;
var i: usize = 0;
@@ -908,7 +908,7 @@ pub const Int = struct {
const src_digit = a[src_i];
r[dst_i] = carry | (src_digit >> interior_limb_shift);
- carry = @inlineCall(math.shl, Limb, src_digit, Limb.bit_count - Limb(interior_limb_shift));
+ carry = @inlineCall(math.shl, Limb, src_digit, Limb.bit_count - @intCast(Limb, interior_limb_shift));
}
}
diff --git a/std/math/cbrt.zig b/std/math/cbrt.zig
index cd3b71ca8a593ee2a5c9599fc7e1dddcbbcb1165..c067c5155a8545a550658c5cda75e44a02b771eb 100644
--- a/std/math/cbrt.zig
+++ b/std/math/cbrt.zig
@@ -54,7 +54,7 @@ fn cbrt32(x: f32) f32 {
r = t * t * t;
t = t * (f64(x) + x + r) / (x + r + r);
- return f32(t);
+ return @floatCast(f32, t);
}
fn cbrt64(x: f64) f64 {
@@ -69,7 +69,7 @@ fn cbrt64(x: f64) f64 {
const P4: f64 = 0.145996192886612446982;
var u = @bitCast(u64, x);
- var hx = u32(u >> 32) & 0x7FFFFFFF;
+ var hx = @intCast(u32, u >> 32) & 0x7FFFFFFF;
// cbrt(nan, inf) = itself
if (hx >= 0x7FF00000) {
@@ -79,7 +79,7 @@ fn cbrt64(x: f64) f64 {
// cbrt to ~5bits
if (hx < 0x00100000) {
u = @bitCast(u64, x * 0x1.0p54);
- hx = u32(u >> 32) & 0x7FFFFFFF;
+ hx = @intCast(u32, u >> 32) & 0x7FFFFFFF;
// cbrt(0) is itself
if (hx == 0) {
diff --git a/std/math/ceil.zig b/std/math/ceil.zig
index a189bb66d2aa1d1dda3c332054d79c98b165012c..1c429504e877649db40c7a1773d2f980d6dede0d 100644
--- a/std/math/ceil.zig
+++ b/std/math/ceil.zig
@@ -20,7 +20,7 @@ pub fn ceil(x: var) @typeOf(x) {
fn ceil32(x: f32) f32 {
var u = @bitCast(u32, x);
- var e = i32((u >> 23) & 0xFF) - 0x7F;
+ var e = @intCast(i32, (u >> 23) & 0xFF) - 0x7F;
var m: u32 = undefined;
// TODO: Shouldn't need this explicit check.
@@ -31,7 +31,7 @@ fn ceil32(x: f32) f32 {
if (e >= 23) {
return x;
} else if (e >= 0) {
- m = u32(0x007FFFFF) >> u5(e);
+ m = u32(0x007FFFFF) >> @intCast(u5, e);
if (u & m == 0) {
return x;
}
diff --git a/std/math/complex/atan.zig b/std/math/complex/atan.zig
index 9bfe5fe724b21aa4eae9053e59847f244e12bb77..de60f2546d4c8fe0ff0a751329e3b8410549d52f 100644
--- a/std/math/complex/atan.zig
+++ b/std/math/complex/atan.zig
@@ -4,7 +4,7 @@ const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
-pub fn atan(z: var) Complex(@typeOf(z.re)) {
+pub fn atan(z: var) @typeOf(z) {
const T = @typeOf(z.re);
return switch (T) {
f32 => atan32(z),
@@ -25,11 +25,11 @@ fn redupif32(x: f32) f32 {
t -= 0.5;
}
- const u = f32(i32(t));
+ const u = @intToFloat(f32, @floatToInt(i32, t));
return ((x - u * DP1) - u * DP2) - t * DP3;
}
-fn atan32(z: *const Complex(f32)) Complex(f32) {
+fn atan32(z: Complex(f32)) Complex(f32) {
const maxnum = 1.0e38;
const x = z.re;
@@ -74,11 +74,11 @@ fn redupif64(x: f64) f64 {
t -= 0.5;
}
- const u = f64(i64(t));
+ const u = @intToFloat(f64, @floatToInt(i64, t));
return ((x - u * DP1) - u * DP2) - t * DP3;
}
-fn atan64(z: *const Complex(f64)) Complex(f64) {
+fn atan64(z: Complex(f64)) Complex(f64) {
const maxnum = 1.0e308;
const x = z.re;
diff --git a/std/math/complex/cosh.zig b/std/math/complex/cosh.zig
index c2f9a47b8db727befa7c66616ec33b73caaf3c25..a2e31631eafff24d90fdec9aa66b90f58cc4ebee 100644
--- a/std/math/complex/cosh.zig
+++ b/std/math/complex/cosh.zig
@@ -83,12 +83,12 @@ fn cosh64(z: *const Complex(f64)) Complex(f64) {
const y = z.im;
const fx = @bitCast(u64, x);
- const hx = u32(fx >> 32);
+ const hx = @intCast(u32, fx >> 32);
const lx = @truncate(u32, fx);
const ix = hx & 0x7fffffff;
const fy = @bitCast(u64, y);
- const hy = u32(fy >> 32);
+ const hy = @intCast(u32, fy >> 32);
const ly = @truncate(u32, fy);
const iy = hy & 0x7fffffff;
diff --git a/std/math/complex/exp.zig b/std/math/complex/exp.zig
index 44c354f2469e73e2e5f1e372aeba1ec029b92571..48fb132d972ba56246e0dc27112438885b42fdce 100644
--- a/std/math/complex/exp.zig
+++ b/std/math/complex/exp.zig
@@ -6,7 +6,7 @@ const Complex = cmath.Complex;
const ldexp_cexp = @import("ldexp.zig").ldexp_cexp;
-pub fn exp(z: var) Complex(@typeOf(z.re)) {
+pub fn exp(z: var) @typeOf(z) {
const T = @typeOf(z.re);
return switch (T) {
@@ -16,7 +16,7 @@ pub fn exp(z: var) Complex(@typeOf(z.re)) {
};
}
-fn exp32(z: *const Complex(f32)) Complex(f32) {
+fn exp32(z: Complex(f32)) Complex(f32) {
@setFloatMode(this, @import("builtin").FloatMode.Strict);
const exp_overflow = 0x42b17218; // max_exp * ln2 ~= 88.72283955
@@ -63,7 +63,7 @@ fn exp32(z: *const Complex(f32)) Complex(f32) {
}
}
-fn exp64(z: *const Complex(f64)) Complex(f64) {
+fn exp64(z: Complex(f64)) Complex(f64) {
const exp_overflow = 0x40862e42; // high bits of max_exp * ln2 ~= 710
const cexp_overflow = 0x4096b8e4; // (max_exp - min_denorm_exp) * ln2
diff --git a/std/math/complex/ldexp.zig b/std/math/complex/ldexp.zig
index a56c2ef2eb2695bfe7d79eaca0cd7083e6da699f..e919ef6bec5728b03e3e0c1a658baf74f9d01ee1 100644
--- a/std/math/complex/ldexp.zig
+++ b/std/math/complex/ldexp.zig
@@ -4,7 +4,7 @@ const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
-pub fn ldexp_cexp(z: var, expt: i32) Complex(@typeOf(z.re)) {
+pub fn ldexp_cexp(z: var, expt: i32) @typeOf(z) {
const T = @typeOf(z.re);
return switch (T) {
@@ -20,11 +20,12 @@ fn frexp_exp32(x: f32, expt: *i32) f32 {
const exp_x = math.exp(x - kln2);
const hx = @bitCast(u32, exp_x);
- expt.* = i32(hx >> 23) - (0x7f + 127) + k;
+ // TODO zig should allow this cast implicitly because it should know the value is in range
+ expt.* = @intCast(i32, hx >> 23) - (0x7f + 127) + k;
return @bitCast(f32, (hx & 0x7fffff) | ((0x7f + 127) << 23));
}
-fn ldexp_cexp32(z: *const Complex(f32), expt: i32) Complex(f32) {
+fn ldexp_cexp32(z: Complex(f32), expt: i32) Complex(f32) {
var ex_expt: i32 = undefined;
const exp_x = frexp_exp32(z.re, &ex_expt);
const exptf = expt + ex_expt;
@@ -45,16 +46,16 @@ fn frexp_exp64(x: f64, expt: *i32) f64 {
const exp_x = math.exp(x - kln2);
const fx = @bitCast(u64, x);
- const hx = u32(fx >> 32);
+ const hx = @intCast(u32, fx >> 32);
const lx = @truncate(u32, fx);
- expt.* = i32(hx >> 20) - (0x3ff + 1023) + k;
+ expt.* = @intCast(i32, hx >> 20) - (0x3ff + 1023) + k;
const high_word = (hx & 0xfffff) | ((0x3ff + 1023) << 20);
return @bitCast(f64, (u64(high_word) << 32) | lx);
}
-fn ldexp_cexp64(z: *const Complex(f64), expt: i32) Complex(f64) {
+fn ldexp_cexp64(z: Complex(f64), expt: i32) Complex(f64) {
var ex_expt: i32 = undefined;
const exp_x = frexp_exp64(z.re, &ex_expt);
const exptf = i64(expt + ex_expt);
diff --git a/std/math/complex/sinh.zig b/std/math/complex/sinh.zig
index 3d196bfd50206ddde58ac1bcabae4fb537b37c8b..ab23c5c74d8275c5f50984bf0b8090de9fbe9c1a 100644
--- a/std/math/complex/sinh.zig
+++ b/std/math/complex/sinh.zig
@@ -6,7 +6,7 @@ const Complex = cmath.Complex;
const ldexp_cexp = @import("ldexp.zig").ldexp_cexp;
-pub fn sinh(z: var) Complex(@typeOf(z.re)) {
+pub fn sinh(z: var) @typeOf(z) {
const T = @typeOf(z.re);
return switch (T) {
f32 => sinh32(z),
@@ -15,7 +15,7 @@ pub fn sinh(z: var) Complex(@typeOf(z.re)) {
};
}
-fn sinh32(z: *const Complex(f32)) Complex(f32) {
+fn sinh32(z: Complex(f32)) Complex(f32) {
const x = z.re;
const y = z.im;
@@ -78,17 +78,17 @@ fn sinh32(z: *const Complex(f32)) Complex(f32) {
return Complex(f32).new((x * x) * (y - y), (x + x) * (y - y));
}
-fn sinh64(z: *const Complex(f64)) Complex(f64) {
+fn sinh64(z: Complex(f64)) Complex(f64) {
const x = z.re;
const y = z.im;
const fx = @bitCast(u64, x);
- const hx = u32(fx >> 32);
+ const hx = @intCast(u32, fx >> 32);
const lx = @truncate(u32, fx);
const ix = hx & 0x7fffffff;
const fy = @bitCast(u64, y);
- const hy = u32(fy >> 32);
+ const hy = @intCast(u32, fy >> 32);
const ly = @truncate(u32, fy);
const iy = hy & 0x7fffffff;
diff --git a/std/math/complex/sqrt.zig b/std/math/complex/sqrt.zig
index caa3bd28680a712edeede6ee9a22e4ff5f8ff66e..47367816f79549e6eb2af0df15b96cad0eb9ca35 100644
--- a/std/math/complex/sqrt.zig
+++ b/std/math/complex/sqrt.zig
@@ -49,10 +49,16 @@ fn sqrt32(z: Complex(f32)) Complex(f32) {
if (dx >= 0) {
const t = math.sqrt((dx + math.hypot(f64, dx, dy)) * 0.5);
- return Complex(f32).new(f32(t), f32(dy / (2.0 * t)));
+ return Complex(f32).new(
+ @floatCast(f32, t),
+ @floatCast(f32, dy / (2.0 * t)),
+ );
} else {
const t = math.sqrt((-dx + math.hypot(f64, dx, dy)) * 0.5);
- return Complex(f32).new(f32(math.fabs(y) / (2.0 * t)), f32(math.copysign(f64, t, y)));
+ return Complex(f32).new(
+ @floatCast(f32, math.fabs(y) / (2.0 * t)),
+ @floatCast(f32, math.copysign(f64, t, y)),
+ );
}
}
diff --git a/std/math/complex/tanh.zig b/std/math/complex/tanh.zig
index 1d754838a3d54740c790490beb0f085d65d3c854..e48d438783e7089deabed9d974bdddb203bed261 100644
--- a/std/math/complex/tanh.zig
+++ b/std/math/complex/tanh.zig
@@ -4,7 +4,7 @@ const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
-pub fn tanh(z: var) Complex(@typeOf(z.re)) {
+pub fn tanh(z: var) @typeOf(z) {
const T = @typeOf(z.re);
return switch (T) {
f32 => tanh32(z),
@@ -13,7 +13,7 @@ pub fn tanh(z: var) Complex(@typeOf(z.re)) {
};
}
-fn tanh32(z: *const Complex(f32)) Complex(f32) {
+fn tanh32(z: Complex(f32)) Complex(f32) {
const x = z.re;
const y = z.im;
@@ -51,12 +51,14 @@ fn tanh32(z: *const Complex(f32)) Complex(f32) {
return Complex(f32).new((beta * rho * s) / den, t / den);
}
-fn tanh64(z: *const Complex(f64)) Complex(f64) {
+fn tanh64(z: Complex(f64)) Complex(f64) {
const x = z.re;
const y = z.im;
const fx = @bitCast(u64, x);
- const hx = u32(fx >> 32);
+ // TODO: zig should allow this conversion implicitly because it can notice that the value necessarily
+ // fits in range.
+ const hx = @intCast(u32, fx >> 32);
const lx = @truncate(u32, fx);
const ix = hx & 0x7fffffff;
diff --git a/std/math/cos.zig b/std/math/cos.zig
index 5e5ec4f1cb6c72579c7c28af0b1eb7b886e9f049..71d5e4a8f66a7d0dd8ddd233044e4eb3a934fe9a 100644
--- a/std/math/cos.zig
+++ b/std/math/cos.zig
@@ -55,7 +55,7 @@ fn cos32(x_: f32) f32 {
}
var y = math.floor(x * m4pi);
- var j = i64(y);
+ var j = @floatToInt(i64, y);
if (j & 1 == 1) {
j += 1;
@@ -106,7 +106,7 @@ fn cos64(x_: f64) f64 {
}
var y = math.floor(x * m4pi);
- var j = i64(y);
+ var j = @floatToInt(i64, y);
if (j & 1 == 1) {
j += 1;
diff --git a/std/math/cosh.zig b/std/math/cosh.zig
index fa4621998607983802d17c0585320e85b9250b0e..52beafb64227f6b3fefa92e1752e16bbbee4f2c9 100644
--- a/std/math/cosh.zig
+++ b/std/math/cosh.zig
@@ -49,7 +49,7 @@ fn cosh32(x: f32) f32 {
fn cosh64(x: f64) f64 {
const u = @bitCast(u64, x);
- const w = u32(u >> 32);
+ const w = @intCast(u32, u >> 32);
const ax = @bitCast(f64, u & (@maxValue(u64) >> 1));
// TODO: Shouldn't need this explicit check.
diff --git a/std/math/exp.zig b/std/math/exp.zig
index 76dc47d04b131493010a49d8fe422ab000849bc9..d6185d4f0be95dfb06bda343919b7986c4c54bd5 100644
--- a/std/math/exp.zig
+++ b/std/math/exp.zig
@@ -29,7 +29,7 @@ fn exp32(x_: f32) f32 {
var x = x_;
var hx = @bitCast(u32, x);
- const sign = i32(hx >> 31);
+ const sign = @intCast(i32, hx >> 31);
hx &= 0x7FFFFFFF;
if (math.isNan(x)) {
@@ -63,12 +63,12 @@ fn exp32(x_: f32) f32 {
if (hx > 0x3EB17218) {
// |x| > 1.5 * ln2
if (hx > 0x3F851592) {
- k = i32(invln2 * x + half[usize(sign)]);
+ k = @floatToInt(i32, invln2 * x + half[@intCast(usize, sign)]);
} else {
k = 1 - sign - sign;
}
- const fk = f32(k);
+ const fk = @intToFloat(f32, k);
hi = x - fk * ln2hi;
lo = fk * ln2lo;
x = hi - lo;
@@ -110,7 +110,7 @@ fn exp64(x_: f64) f64 {
var x = x_;
var ux = @bitCast(u64, x);
var hx = ux >> 32;
- const sign = i32(hx >> 31);
+ const sign = @intCast(i32, hx >> 31);
hx &= 0x7FFFFFFF;
if (math.isNan(x)) {
@@ -148,12 +148,12 @@ fn exp64(x_: f64) f64 {
if (hx > 0x3EB17218) {
// |x| >= 1.5 * ln2
if (hx > 0x3FF0A2B2) {
- k = i32(invln2 * x + half[usize(sign)]);
+ k = @floatToInt(i32, invln2 * x + half[@intCast(usize, sign)]);
} else {
k = 1 - sign - sign;
}
- const dk = f64(k);
+ const dk = @intToFloat(f64, k);
hi = x - dk * ln2hi;
lo = dk * ln2lo;
x = hi - lo;
diff --git a/std/math/exp2.zig b/std/math/exp2.zig
index 62a3eb85b62524a7f8f6678aac18f6de26187c61..90ea0881814e7260263e1fc32164352fc09281ba 100644
--- a/std/math/exp2.zig
+++ b/std/math/exp2.zig
@@ -38,8 +38,8 @@ const exp2ft = []const f64{
fn exp2_32(x: f32) f32 {
@setFloatMode(this, @import("builtin").FloatMode.Strict);
- const tblsiz = u32(exp2ft.len);
- const redux: f32 = 0x1.8p23 / f32(tblsiz);
+ const tblsiz = @intCast(u32, exp2ft.len);
+ const redux: f32 = 0x1.8p23 / @intToFloat(f32, tblsiz);
const P1: f32 = 0x1.62e430p-1;
const P2: f32 = 0x1.ebfbe0p-3;
const P3: f32 = 0x1.c6b348p-5;
@@ -89,7 +89,7 @@ fn exp2_32(x: f32) f32 {
var r: f64 = exp2ft[i0];
const t: f64 = r * z;
r = r + t * (P1 + z * P2) + t * (z * z) * (P3 + z * P4);
- return f32(r * uk);
+ return @floatCast(f32, r * uk);
}
const exp2dt = []f64{
@@ -355,8 +355,8 @@ const exp2dt = []f64{
fn exp2_64(x: f64) f64 {
@setFloatMode(this, @import("builtin").FloatMode.Strict);
- const tblsiz = u32(exp2dt.len / 2);
- const redux: f64 = 0x1.8p52 / f64(tblsiz);
+ const tblsiz = @intCast(u32, exp2dt.len / 2);
+ const redux: f64 = 0x1.8p52 / @intToFloat(f64, tblsiz);
const P1: f64 = 0x1.62e42fefa39efp-1;
const P2: f64 = 0x1.ebfbdff82c575p-3;
const P3: f64 = 0x1.c6b08d704a0a6p-5;
@@ -364,7 +364,7 @@ fn exp2_64(x: f64) f64 {
const P5: f64 = 0x1.5d88003875c74p-10;
const ux = @bitCast(u64, x);
- const ix = u32(ux >> 32) & 0x7FFFFFFF;
+ const ix = @intCast(u32, ux >> 32) & 0x7FFFFFFF;
// TODO: This should be handled beneath.
if (math.isNan(x)) {
@@ -386,7 +386,7 @@ fn exp2_64(x: f64) f64 {
if (ux >> 63 != 0) {
// underflow
if (x <= -1075 or x - 0x1.0p52 + 0x1.0p52 != x) {
- math.forceEval(f32(-0x1.0p-149 / x));
+ math.forceEval(@floatCast(f32, -0x1.0p-149 / x));
}
if (x <= -1075) {
return 0;
diff --git a/std/math/expm1.zig b/std/math/expm1.zig
index 11af1b215f3f9942e8e4d45ccd49e012b4a8eff4..438e44cccec6777d1e07daf8e1f36ebf09f4a5ce 100644
--- a/std/math/expm1.zig
+++ b/std/math/expm1.zig
@@ -78,8 +78,8 @@ fn expm1_32(x_: f32) f32 {
kf += 0.5;
}
- k = i32(kf);
- const t = f32(k);
+ k = @floatToInt(i32, kf);
+ const t = @intToFloat(f32, k);
hi = x - t * ln2_hi;
lo = t * ln2_lo;
}
@@ -123,7 +123,7 @@ fn expm1_32(x_: f32) f32 {
}
}
- const twopk = @bitCast(f32, u32((0x7F +% k) << 23));
+ const twopk = @bitCast(f32, @intCast(u32, (0x7F +% k) << 23));
if (k < 0 or k > 56) {
var y = x - e + 1.0;
@@ -136,7 +136,7 @@ fn expm1_32(x_: f32) f32 {
return y - 1.0;
}
- const uf = @bitCast(f32, u32(0x7F -% k) << 23);
+ const uf = @bitCast(f32, @intCast(u32, 0x7F -% k) << 23);
if (k < 23) {
return (x - e + (1 - uf)) * twopk;
} else {
@@ -158,7 +158,7 @@ fn expm1_64(x_: f64) f64 {
var x = x_;
const ux = @bitCast(u64, x);
- const hx = u32(ux >> 32) & 0x7FFFFFFF;
+ const hx = @intCast(u32, ux >> 32) & 0x7FFFFFFF;
const sign = ux >> 63;
if (math.isNegativeInf(x)) {
@@ -207,8 +207,8 @@ fn expm1_64(x_: f64) f64 {
kf += 0.5;
}
- k = i32(kf);
- const t = f64(k);
+ k = @floatToInt(i32, kf);
+ const t = @intToFloat(f64, k);
hi = x - t * ln2_hi;
lo = t * ln2_lo;
}
@@ -219,7 +219,7 @@ fn expm1_64(x_: f64) f64 {
// |x| < 2^(-54)
else if (hx < 0x3C900000) {
if (hx < 0x00100000) {
- math.forceEval(f32(x));
+ math.forceEval(@floatCast(f32, x));
}
return x;
} else {
@@ -252,7 +252,7 @@ fn expm1_64(x_: f64) f64 {
}
}
- const twopk = @bitCast(f64, u64(0x3FF +% k) << 52);
+ const twopk = @bitCast(f64, @intCast(u64, 0x3FF +% k) << 52);
if (k < 0 or k > 56) {
var y = x - e + 1.0;
@@ -265,7 +265,7 @@ fn expm1_64(x_: f64) f64 {
return y - 1.0;
}
- const uf = @bitCast(f64, u64(0x3FF -% k) << 52);
+ const uf = @bitCast(f64, @intCast(u64, 0x3FF -% k) << 52);
if (k < 20) {
return (x - e + (1 - uf)) * twopk;
} else {
diff --git a/std/math/floor.zig b/std/math/floor.zig
index 7d5364787f7dd45b678802147c3ab976f4b6b3d5..79d1097d083404e7b8df12bf344812550bd870ec 100644
--- a/std/math/floor.zig
+++ b/std/math/floor.zig
@@ -20,7 +20,7 @@ pub fn floor(x: var) @typeOf(x) {
fn floor32(x: f32) f32 {
var u = @bitCast(u32, x);
- const e = i32((u >> 23) & 0xFF) - 0x7F;
+ const e = @intCast(i32, (u >> 23) & 0xFF) - 0x7F;
var m: u32 = undefined;
// TODO: Shouldn't need this explicit check.
@@ -33,7 +33,7 @@ fn floor32(x: f32) f32 {
}
if (e >= 0) {
- m = u32(0x007FFFFF) >> u5(e);
+ m = u32(0x007FFFFF) >> @intCast(u5, e);
if (u & m == 0) {
return x;
}
diff --git a/std/math/fma.zig b/std/math/fma.zig
index 3e9214f35b1b5ee7b84d28e882b63cb11a0d3520..21faf4118d6706e7cfb2d5965aeaa083ed875c25 100644
--- a/std/math/fma.zig
+++ b/std/math/fma.zig
@@ -17,10 +17,10 @@ fn fma32(x: f32, y: f32, z: f32) f32 {
const e = (u >> 52) & 0x7FF;
if ((u & 0x1FFFFFFF) != 0x10000000 or e == 0x7FF or xy_z - xy == z) {
- return f32(xy_z);
+ return @floatCast(f32, xy_z);
} else {
// TODO: Handle inexact case with double-rounding
- return f32(xy_z);
+ return @floatCast(f32, xy_z);
}
}
@@ -124,7 +124,7 @@ fn add_and_denorm(a: f64, b: f64, scale: i32) f64 {
var sum = dd_add(a, b);
if (sum.lo != 0) {
var uhii = @bitCast(u64, sum.hi);
- const bits_lost = -i32((uhii >> 52) & 0x7FF) - scale + 1;
+ const bits_lost = -@intCast(i32, (uhii >> 52) & 0x7FF) - scale + 1;
if ((bits_lost != 1) == (uhii & 1 != 0)) {
const uloi = @bitCast(u64, sum.lo);
uhii += 1 - (((uhii ^ uloi) >> 62) & 2);
diff --git a/std/math/frexp.zig b/std/math/frexp.zig
index b58af0a9bcd38c55a2e4ff7ca9c0601eeeb8a21b..dfc790fdd9386392c062fe0bf6247fccabd76d5c 100644
--- a/std/math/frexp.zig
+++ b/std/math/frexp.zig
@@ -30,7 +30,7 @@ fn frexp32(x: f32) frexp32_result {
var result: frexp32_result = undefined;
var y = @bitCast(u32, x);
- const e = i32(y >> 23) & 0xFF;
+ const e = @intCast(i32, y >> 23) & 0xFF;
if (e == 0) {
if (x != 0) {
@@ -67,7 +67,7 @@ fn frexp64(x: f64) frexp64_result {
var result: frexp64_result = undefined;
var y = @bitCast(u64, x);
- const e = i32(y >> 52) & 0x7FF;
+ const e = @intCast(i32, y >> 52) & 0x7FF;
if (e == 0) {
if (x != 0) {
diff --git a/std/math/hypot.zig b/std/math/hypot.zig
index 494df22ba6cefb93f906126a04bee74c96f7a862..f834f422e66519201d52c4aaed1ebf1044985429 100644
--- a/std/math/hypot.zig
+++ b/std/math/hypot.zig
@@ -49,7 +49,7 @@ fn hypot32(x: f32, y: f32) f32 {
yy *= 0x1.0p-90;
}
- return z * math.sqrt(f32(f64(x) * x + f64(y) * y));
+ return z * math.sqrt(@floatCast(f32, f64(x) * x + f64(y) * y));
}
fn sq(hi: *f64, lo: *f64, x: f64) void {
diff --git a/std/math/ilogb.zig b/std/math/ilogb.zig
index f1f33aff553a614fc3fd6e834fcfcabe484ae231..a24f580a322488e91292c2b9b46646e14177a67f 100644
--- a/std/math/ilogb.zig
+++ b/std/math/ilogb.zig
@@ -23,7 +23,7 @@ const fp_ilogb0 = fp_ilogbnan;
fn ilogb32(x: f32) i32 {
var u = @bitCast(u32, x);
- var e = i32((u >> 23) & 0xFF);
+ var e = @intCast(i32, (u >> 23) & 0xFF);
// TODO: We should be able to merge this with the lower check.
if (math.isNan(x)) {
@@ -59,7 +59,7 @@ fn ilogb32(x: f32) i32 {
fn ilogb64(x: f64) i32 {
var u = @bitCast(u64, x);
- var e = i32((u >> 52) & 0x7FF);
+ var e = @intCast(i32, (u >> 52) & 0x7FF);
if (math.isNan(x)) {
return @maxValue(i32);
diff --git a/std/math/index.zig b/std/math/index.zig
index 99e5b4ecf1597b633cf46d0dd3a9b32bea32fb3d..176293be74affa0fe987cc5b3afb6d3a3cf6a95d 100644
--- a/std/math/index.zig
+++ b/std/math/index.zig
@@ -227,7 +227,7 @@ pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) !T {
/// A negative shift amount results in a right shift.
pub fn shl(comptime T: type, a: T, shift_amt: var) T {
const abs_shift_amt = absCast(shift_amt);
- const casted_shift_amt = if (abs_shift_amt >= T.bit_count) return 0 else Log2Int(T)(abs_shift_amt);
+ const casted_shift_amt = if (abs_shift_amt >= T.bit_count) return 0 else @intCast(Log2Int(T), abs_shift_amt);
if (@typeOf(shift_amt).is_signed) {
if (shift_amt >= 0) {
@@ -251,7 +251,7 @@ test "math.shl" {
/// A negative shift amount results in a lefft shift.
pub fn shr(comptime T: type, a: T, shift_amt: var) T {
const abs_shift_amt = absCast(shift_amt);
- const casted_shift_amt = if (abs_shift_amt >= T.bit_count) return 0 else Log2Int(T)(abs_shift_amt);
+ const casted_shift_amt = if (abs_shift_amt >= T.bit_count) return 0 else @intCast(Log2Int(T), abs_shift_amt);
if (@typeOf(shift_amt).is_signed) {
if (shift_amt >= 0) {
@@ -473,9 +473,9 @@ fn testRem() void {
/// Result is an unsigned integer.
pub fn absCast(x: var) @IntType(false, @typeOf(x).bit_count) {
const uint = @IntType(false, @typeOf(x).bit_count);
- if (x >= 0) return uint(x);
+ if (x >= 0) return @intCast(uint, x);
- return uint(-(x + 1)) + 1;
+ return @intCast(uint, -(x + 1)) + 1;
}
test "math.absCast" {
@@ -499,7 +499,7 @@ pub fn negateCast(x: var) !@IntType(true, @typeOf(x).bit_count) {
if (x == -@minValue(int)) return @minValue(int);
- return -int(x);
+ return -@intCast(int, x);
}
test "math.negateCast" {
@@ -522,7 +522,7 @@ pub fn cast(comptime T: type, x: var) (error{Overflow}!T) {
} else if (@minValue(@typeOf(x)) < @minValue(T) and x < @minValue(T)) {
return error.Overflow;
} else {
- return T(x);
+ return @intCast(T, x);
}
}
@@ -565,7 +565,7 @@ test "math.floorPowerOfTwo" {
pub fn log2_int(comptime T: type, x: T) Log2Int(T) {
assert(x != 0);
- return Log2Int(T)(T.bit_count - 1 - @clz(x));
+ return @intCast(Log2Int(T), T.bit_count - 1 - @clz(x));
}
pub fn log2_int_ceil(comptime T: type, x: T) Log2Int(T) {
@@ -597,3 +597,14 @@ fn testFloorPowerOfTwo() void {
assert(floorPowerOfTwo(u4, 8) == 8);
assert(floorPowerOfTwo(u4, 9) == 8);
}
+
+pub fn lossyCast(comptime T: type, value: var) T {
+ switch (@typeInfo(@typeOf(value))) {
+ builtin.TypeId.Int => return @intToFloat(T, value),
+ builtin.TypeId.Float => return @floatCast(T, value),
+ builtin.TypeId.ComptimeInt => return T(value),
+ builtin.TypeId.ComptimeFloat => return T(value),
+ else => @compileError("bad type"),
+ }
+}
+
diff --git a/std/math/ln.zig b/std/math/ln.zig
index 3fd75977b9f99bc3504a2058c7a8a4fd8163bfd6..e78cc379e00fbd589f2184df6cec7cdf957ff63e 100644
--- a/std/math/ln.zig
+++ b/std/math/ln.zig
@@ -71,7 +71,7 @@ pub fn ln_32(x_: f32) f32 {
// x into [sqrt(2) / 2, sqrt(2)]
ix += 0x3F800000 - 0x3F3504F3;
- k += i32(ix >> 23) - 0x7F;
+ k += @intCast(i32, ix >> 23) - 0x7F;
ix = (ix & 0x007FFFFF) + 0x3F3504F3;
x = @bitCast(f32, ix);
@@ -83,7 +83,7 @@ pub fn ln_32(x_: f32) f32 {
const t2 = z * (Lg1 + w * Lg3);
const R = t2 + t1;
const hfsq = 0.5 * f * f;
- const dk = f32(k);
+ const dk = @intToFloat(f32, k);
return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi;
}
@@ -103,7 +103,7 @@ pub fn ln_64(x_: f64) f64 {
var x = x_;
var ix = @bitCast(u64, x);
- var hx = u32(ix >> 32);
+ var hx = @intCast(u32, ix >> 32);
var k: i32 = 0;
if (hx < 0x00100000 or hx >> 31 != 0) {
@@ -119,7 +119,7 @@ pub fn ln_64(x_: f64) f64 {
// subnormal, scale x
k -= 54;
x *= 0x1.0p54;
- hx = u32(@bitCast(u64, ix) >> 32);
+ hx = @intCast(u32, @bitCast(u64, ix) >> 32);
} else if (hx >= 0x7FF00000) {
return x;
} else if (hx == 0x3FF00000 and ix << 32 == 0) {
@@ -128,7 +128,7 @@ pub fn ln_64(x_: f64) f64 {
// x into [sqrt(2) / 2, sqrt(2)]
hx += 0x3FF00000 - 0x3FE6A09E;
- k += i32(hx >> 20) - 0x3FF;
+ k += @intCast(i32, hx >> 20) - 0x3FF;
hx = (hx & 0x000FFFFF) + 0x3FE6A09E;
ix = (u64(hx) << 32) | (ix & 0xFFFFFFFF);
x = @bitCast(f64, ix);
@@ -141,7 +141,7 @@ pub fn ln_64(x_: f64) f64 {
const t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
const t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
const R = t2 + t1;
- const dk = f64(k);
+ const dk = @intToFloat(f64, k);
return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi;
}
diff --git a/std/math/log.zig b/std/math/log.zig
index 2c876081d87e147417eda2288401cba54741c183..20b6d055e8ad0f8fcfe915afd17f8adc28077017 100644
--- a/std/math/log.zig
+++ b/std/math/log.zig
@@ -13,22 +13,23 @@ pub fn log(comptime T: type, base: T, x: T) T {
return math.ln(x);
}
+ const float_base = math.lossyCast(f64, base);
switch (@typeId(T)) {
TypeId.ComptimeFloat => {
- return @typeOf(1.0)(math.ln(f64(x)) / math.ln(f64(base)));
+ return @typeOf(1.0)(math.ln(f64(x)) / math.ln(float_base));
},
TypeId.ComptimeInt => {
- return @typeOf(1)(math.floor(math.ln(f64(x)) / math.ln(f64(base))));
+ return @typeOf(1)(math.floor(math.ln(f64(x)) / math.ln(float_base)));
},
builtin.TypeId.Int => {
// TODO implement integer log without using float math
- return T(math.floor(math.ln(f64(x)) / math.ln(f64(base))));
+ return @floatToInt(T, math.floor(math.ln(@intToFloat(f64, x)) / math.ln(float_base)));
},
builtin.TypeId.Float => {
switch (T) {
- f32 => return f32(math.ln(f64(x)) / math.ln(f64(base))),
- f64 => return math.ln(x) / math.ln(f64(base)),
+ f32 => return @floatCast(f32, math.ln(f64(x)) / math.ln(float_base)),
+ f64 => return math.ln(x) / math.ln(float_base),
else => @compileError("log not implemented for " ++ @typeName(T)),
}
},
diff --git a/std/math/log10.zig b/std/math/log10.zig
index c444add9ac2a0fe2646245baddbf7df0aa2685f2..a93ce48fb7b47507dcd761d8def38113043c2172 100644
--- a/std/math/log10.zig
+++ b/std/math/log10.zig
@@ -28,7 +28,7 @@ pub fn log10(x: var) @typeOf(x) {
return @typeOf(1)(math.floor(log10_64(f64(x))));
},
TypeId.Int => {
- return T(math.floor(log10_64(f64(x))));
+ return @floatToInt(T, math.floor(log10_64(@intToFloat(f64, x))));
},
else => @compileError("log10 not implemented for " ++ @typeName(T)),
}
@@ -71,7 +71,7 @@ pub fn log10_32(x_: f32) f32 {
// x into [sqrt(2) / 2, sqrt(2)]
ix += 0x3F800000 - 0x3F3504F3;
- k += i32(ix >> 23) - 0x7F;
+ k += @intCast(i32, ix >> 23) - 0x7F;
ix = (ix & 0x007FFFFF) + 0x3F3504F3;
x = @bitCast(f32, ix);
@@ -89,7 +89,7 @@ pub fn log10_32(x_: f32) f32 {
u &= 0xFFFFF000;
hi = @bitCast(f32, u);
const lo = f - hi - hfsq + s * (hfsq + R);
- const dk = f32(k);
+ const dk = @intToFloat(f32, k);
return dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi;
}
@@ -109,7 +109,7 @@ pub fn log10_64(x_: f64) f64 {
var x = x_;
var ix = @bitCast(u64, x);
- var hx = u32(ix >> 32);
+ var hx = @intCast(u32, ix >> 32);
var k: i32 = 0;
if (hx < 0x00100000 or hx >> 31 != 0) {
@@ -125,7 +125,7 @@ pub fn log10_64(x_: f64) f64 {
// subnormal, scale x
k -= 54;
x *= 0x1.0p54;
- hx = u32(@bitCast(u64, x) >> 32);
+ hx = @intCast(u32, @bitCast(u64, x) >> 32);
} else if (hx >= 0x7FF00000) {
return x;
} else if (hx == 0x3FF00000 and ix << 32 == 0) {
@@ -134,7 +134,7 @@ pub fn log10_64(x_: f64) f64 {
// x into [sqrt(2) / 2, sqrt(2)]
hx += 0x3FF00000 - 0x3FE6A09E;
- k += i32(hx >> 20) - 0x3FF;
+ k += @intCast(i32, hx >> 20) - 0x3FF;
hx = (hx & 0x000FFFFF) + 0x3FE6A09E;
ix = (u64(hx) << 32) | (ix & 0xFFFFFFFF);
x = @bitCast(f64, ix);
@@ -157,7 +157,7 @@ pub fn log10_64(x_: f64) f64 {
// val_hi + val_lo ~ log10(1 + f) + k * log10(2)
var val_hi = hi * ivln10hi;
- const dk = f64(k);
+ const dk = @intToFloat(f64, k);
const y = dk * log10_2hi;
var val_lo = dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi;
diff --git a/std/math/log1p.zig b/std/math/log1p.zig
index 57efdaf51c9620c6073bba04d5d0007817a8ebb8..7d3be6bb49ca706e3c64589cc0b006a6aee76bba 100644
--- a/std/math/log1p.zig
+++ b/std/math/log1p.zig
@@ -68,7 +68,7 @@ fn log1p_32(x: f32) f32 {
const uf = 1 + x;
var iu = @bitCast(u32, uf);
iu += 0x3F800000 - 0x3F3504F3;
- k = i32(iu >> 23) - 0x7F;
+ k = @intCast(i32, iu >> 23) - 0x7F;
// correction to avoid underflow in c / u
if (k < 25) {
@@ -90,7 +90,7 @@ fn log1p_32(x: f32) f32 {
const t2 = z * (Lg1 + w * Lg3);
const R = t2 + t1;
const hfsq = 0.5 * f * f;
- const dk = f32(k);
+ const dk = @intToFloat(f32, k);
return s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi;
}
@@ -107,7 +107,7 @@ fn log1p_64(x: f64) f64 {
const Lg7: f64 = 1.479819860511658591e-01;
var ix = @bitCast(u64, x);
- var hx = u32(ix >> 32);
+ var hx = @intCast(u32, ix >> 32);
var k: i32 = 1;
var c: f64 = undefined;
var f: f64 = undefined;
@@ -145,9 +145,9 @@ fn log1p_64(x: f64) f64 {
if (k != 0) {
const uf = 1 + x;
const hu = @bitCast(u64, uf);
- var iu = u32(hu >> 32);
+ var iu = @intCast(u32, hu >> 32);
iu += 0x3FF00000 - 0x3FE6A09E;
- k = i32(iu >> 20) - 0x3FF;
+ k = @intCast(i32, iu >> 20) - 0x3FF;
// correction to avoid underflow in c / u
if (k < 54) {
@@ -170,7 +170,7 @@ fn log1p_64(x: f64) f64 {
const t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
const t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
const R = t2 + t1;
- const dk = f64(k);
+ const dk = @intToFloat(f64, k);
return s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi;
}
diff --git a/std/math/log2.zig b/std/math/log2.zig
index 2530519941c2594a810ded0398570957c46850df..858f6ffa02185cd7079932db92f90168b1eb5180 100644
--- a/std/math/log2.zig
+++ b/std/math/log2.zig
@@ -75,7 +75,7 @@ pub fn log2_32(x_: f32) f32 {
// x into [sqrt(2) / 2, sqrt(2)]
ix += 0x3F800000 - 0x3F3504F3;
- k += i32(ix >> 23) - 0x7F;
+ k += @intCast(i32, ix >> 23) - 0x7F;
ix = (ix & 0x007FFFFF) + 0x3F3504F3;
x = @bitCast(f32, ix);
@@ -93,7 +93,7 @@ pub fn log2_32(x_: f32) f32 {
u &= 0xFFFFF000;
hi = @bitCast(f32, u);
const lo = f - hi - hfsq + s * (hfsq + R);
- return (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + f32(k);
+ return (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + @intToFloat(f32, k);
}
pub fn log2_64(x_: f64) f64 {
@@ -109,7 +109,7 @@ pub fn log2_64(x_: f64) f64 {
var x = x_;
var ix = @bitCast(u64, x);
- var hx = u32(ix >> 32);
+ var hx = @intCast(u32, ix >> 32);
var k: i32 = 0;
if (hx < 0x00100000 or hx >> 31 != 0) {
@@ -125,7 +125,7 @@ pub fn log2_64(x_: f64) f64 {
// subnormal, scale x
k -= 54;
x *= 0x1.0p54;
- hx = u32(@bitCast(u64, x) >> 32);
+ hx = @intCast(u32, @bitCast(u64, x) >> 32);
} else if (hx >= 0x7FF00000) {
return x;
} else if (hx == 0x3FF00000 and ix << 32 == 0) {
@@ -134,7 +134,7 @@ pub fn log2_64(x_: f64) f64 {
// x into [sqrt(2) / 2, sqrt(2)]
hx += 0x3FF00000 - 0x3FE6A09E;
- k += i32(hx >> 20) - 0x3FF;
+ k += @intCast(i32, hx >> 20) - 0x3FF;
hx = (hx & 0x000FFFFF) + 0x3FE6A09E;
ix = (u64(hx) << 32) | (ix & 0xFFFFFFFF);
x = @bitCast(f64, ix);
@@ -159,7 +159,7 @@ pub fn log2_64(x_: f64) f64 {
var val_lo = (lo + hi) * ivln2lo + lo * ivln2hi;
// spadd(val_hi, val_lo, y)
- const y = f64(k);
+ const y = @intToFloat(f64, k);
const ww = y + val_hi;
val_lo += (y - ww) + val_hi;
val_hi = ww;
diff --git a/std/math/modf.zig b/std/math/modf.zig
index a6606ce34c85e9682a1109a58629f9810a1ca35d..b6dd78f022d0a6b01a9a1ae760905f1f907cc602 100644
--- a/std/math/modf.zig
+++ b/std/math/modf.zig
@@ -29,7 +29,7 @@ fn modf32(x: f32) modf32_result {
var result: modf32_result = undefined;
const u = @bitCast(u32, x);
- const e = i32((u >> 23) & 0xFF) - 0x7F;
+ const e = @intCast(i32, (u >> 23) & 0xFF) - 0x7F;
const us = u & 0x80000000;
// TODO: Shouldn't need this.
@@ -57,7 +57,7 @@ fn modf32(x: f32) modf32_result {
return result;
}
- const mask = u32(0x007FFFFF) >> u5(e);
+ const mask = u32(0x007FFFFF) >> @intCast(u5, e);
if (u & mask == 0) {
result.ipart = x;
result.fpart = @bitCast(f32, us);
@@ -74,7 +74,7 @@ fn modf64(x: f64) modf64_result {
var result: modf64_result = undefined;
const u = @bitCast(u64, x);
- const e = i32((u >> 52) & 0x7FF) - 0x3FF;
+ const e = @intCast(i32, (u >> 52) & 0x7FF) - 0x3FF;
const us = u & (1 << 63);
if (math.isInf(x)) {
@@ -101,7 +101,7 @@ fn modf64(x: f64) modf64_result {
return result;
}
- const mask = u64(@maxValue(u64) >> 12) >> u6(e);
+ const mask = u64(@maxValue(u64) >> 12) >> @intCast(u6, e);
if (u & mask == 0) {
result.ipart = x;
result.fpart = @bitCast(f64, us);
diff --git a/std/math/pow.zig b/std/math/pow.zig
index dfe4fc09d6389444634f78b70fd4dd47b6b41dbf..7fc334c06b80a972f0182b92b6b9e504c8cb2af6 100644
--- a/std/math/pow.zig
+++ b/std/math/pow.zig
@@ -146,7 +146,7 @@ pub fn pow(comptime T: type, x: T, y: T) T {
var xe = r2.exponent;
var x1 = r2.significand;
- var i = i32(yi);
+ var i = @floatToInt(i32, yi);
while (i != 0) : (i >>= 1) {
if (i & 1 == 1) {
a1 *= x1;
@@ -171,7 +171,7 @@ pub fn pow(comptime T: type, x: T, y: T) T {
fn isOddInteger(x: f64) bool {
const r = math.modf(x);
- return r.fpart == 0.0 and i64(r.ipart) & 1 == 1;
+ return r.fpart == 0.0 and @floatToInt(i64, r.ipart) & 1 == 1;
}
test "math.pow" {
diff --git a/std/math/scalbn.zig b/std/math/scalbn.zig
index deb5d989d2722773fd4abe5a234a2e2299d41dba..f72c7e866f1e078cc92c9e174eaa037b03254c72 100644
--- a/std/math/scalbn.zig
+++ b/std/math/scalbn.zig
@@ -37,7 +37,7 @@ fn scalbn32(x: f32, n_: i32) f32 {
}
}
- const u = u32(n +% 0x7F) << 23;
+ const u = @intCast(u32, n +% 0x7F) << 23;
return y * @bitCast(f32, u);
}
@@ -67,7 +67,7 @@ fn scalbn64(x: f64, n_: i32) f64 {
}
}
- const u = u64(n +% 0x3FF) << 52;
+ const u = @intCast(u64, n +% 0x3FF) << 52;
return y * @bitCast(f64, u);
}
diff --git a/std/math/sin.zig b/std/math/sin.zig
index 21c324e444f259863994a4f69c8ebdce29e093e8..3796d74812951b5b38b0745e1fb047589aa5f184 100644
--- a/std/math/sin.zig
+++ b/std/math/sin.zig
@@ -60,7 +60,7 @@ fn sin32(x_: f32) f32 {
}
var y = math.floor(x * m4pi);
- var j = i64(y);
+ var j = @floatToInt(i64, y);
if (j & 1 == 1) {
j += 1;
@@ -112,7 +112,7 @@ fn sin64(x_: f64) f64 {
}
var y = math.floor(x * m4pi);
- var j = i64(y);
+ var j = @floatToInt(i64, y);
if (j & 1 == 1) {
j += 1;
diff --git a/std/math/sinh.zig b/std/math/sinh.zig
index 85c9ae979be269ffae7243d986774b0510f4d3a4..bb3af280ab670c547894246197ac38d692c7257c 100644
--- a/std/math/sinh.zig
+++ b/std/math/sinh.zig
@@ -57,7 +57,7 @@ fn sinh64(x: f64) f64 {
@setFloatMode(this, @import("builtin").FloatMode.Strict);
const u = @bitCast(u64, x);
- const w = u32(u >> 32);
+ const w = @intCast(u32, u >> 32);
const ax = @bitCast(f64, u & (@maxValue(u64) >> 1));
if (x == 0.0 or math.isNan(x)) {
diff --git a/std/math/sqrt.zig b/std/math/sqrt.zig
index 7a3ddb3b96d9ed9a6c7e71f66e34ebad2eca614e..599008acff27ddf5eab8291d2bbc12b799a5fbc4 100644
--- a/std/math/sqrt.zig
+++ b/std/math/sqrt.zig
@@ -99,7 +99,7 @@ fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) {
}
const ResultType = @IntType(false, T.bit_count / 2);
- return ResultType(res);
+ return @intCast(ResultType, res);
}
test "math.sqrt_int" {
diff --git a/std/math/tan.zig b/std/math/tan.zig
index f578cf8156b2af6a1b63e7ad163b2b1d201cb699..ff3ed06186b730758e5e9bca10acd73b473c940e 100644
--- a/std/math/tan.zig
+++ b/std/math/tan.zig
@@ -53,7 +53,7 @@ fn tan32(x_: f32) f32 {
}
var y = math.floor(x * m4pi);
- var j = i64(y);
+ var j = @floatToInt(i64, y);
if (j & 1 == 1) {
j += 1;
@@ -102,7 +102,7 @@ fn tan64(x_: f64) f64 {
}
var y = math.floor(x * m4pi);
- var j = i64(y);
+ var j = @floatToInt(i64, y);
if (j & 1 == 1) {
j += 1;
diff --git a/std/math/tanh.zig b/std/math/tanh.zig
index c1f5a0ca467d3f1325b7ec4f630ff3ff327a31c4..6204b2a374482077425e33424ef9672351bd7725 100644
--- a/std/math/tanh.zig
+++ b/std/math/tanh.zig
@@ -68,7 +68,7 @@ fn tanh32(x: f32) f32 {
fn tanh64(x: f64) f64 {
const u = @bitCast(u64, x);
- const w = u32(u >> 32);
+ const w = @intCast(u32, u >> 32);
const ax = @bitCast(f64, u & (@maxValue(u64) >> 1));
var t: f64 = undefined;
@@ -100,7 +100,7 @@ fn tanh64(x: f64) f64 {
}
// |x| is subnormal
else {
- math.forceEval(f32(x));
+ math.forceEval(@floatCast(f32, x));
t = x;
}
diff --git a/std/math/trunc.zig b/std/math/trunc.zig
index 54aa6943f7dbcc0e7a37c8791de731690f5db0e0..92d5bfebc5cb85eceb52819a15d4ef07aa86dec5 100644
--- a/std/math/trunc.zig
+++ b/std/math/trunc.zig
@@ -19,7 +19,7 @@ pub fn trunc(x: var) @typeOf(x) {
fn trunc32(x: f32) f32 {
const u = @bitCast(u32, x);
- var e = i32(((u >> 23) & 0xFF)) - 0x7F + 9;
+ var e = @intCast(i32, ((u >> 23) & 0xFF)) - 0x7F + 9;
var m: u32 = undefined;
if (e >= 23 + 9) {
@@ -29,7 +29,7 @@ fn trunc32(x: f32) f32 {
e = 1;
}
- m = u32(@maxValue(u32)) >> u5(e);
+ m = u32(@maxValue(u32)) >> @intCast(u5, e);
if (u & m == 0) {
return x;
} else {
@@ -40,7 +40,7 @@ fn trunc32(x: f32) f32 {
fn trunc64(x: f64) f64 {
const u = @bitCast(u64, x);
- var e = i32(((u >> 52) & 0x7FF)) - 0x3FF + 12;
+ var e = @intCast(i32, ((u >> 52) & 0x7FF)) - 0x3FF + 12;
var m: u64 = undefined;
if (e >= 52 + 12) {
@@ -50,7 +50,7 @@ fn trunc64(x: f64) f64 {
e = 1;
}
- m = u64(@maxValue(u64)) >> u6(e);
+ m = u64(@maxValue(u64)) >> @intCast(u6, e);
if (u & m == 0) {
return x;
} else {
diff --git a/std/mem.zig b/std/mem.zig
index 10b3eb8fef1a5a101bbb3bf9138866c55d17b281..b02589b0dd3465ad5a3828d19fa933833e221061 100644
--- a/std/mem.zig
+++ b/std/mem.zig
@@ -334,7 +334,7 @@ pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T {
builtin.Endian.Little => {
const ShiftType = math.Log2Int(T);
for (bytes) |b, index| {
- result = result | (T(b) << ShiftType(index * 8));
+ result = result | (T(b) << @intCast(ShiftType, index * 8));
}
},
}
diff --git a/std/os/child_process.zig b/std/os/child_process.zig
index 1e3a732498db94df3f73bff075ea562130c1b789..3a0fa7f46134290b03d529bd0d66333513e987c5 100644
--- a/std/os/child_process.zig
+++ b/std/os/child_process.zig
@@ -413,7 +413,7 @@ pub const ChildProcess = struct {
}
// we are the parent
- const pid = i32(pid_result);
+ const pid = @intCast(i32, pid_result);
if (self.stdin_behavior == StdIo.Pipe) {
self.stdin = os.File.openHandle(stdin_pipe[1]);
} else {
diff --git a/std/os/darwin.zig b/std/os/darwin.zig
index a835959103dc42ec29dca5d5aa9dd6dc97560dfe..15e5608343c39a8c582921ee1acba17d6b88c4ef 100644
--- a/std/os/darwin.zig
+++ b/std/os/darwin.zig
@@ -290,7 +290,7 @@ pub fn WIFSIGNALED(x: i32) bool {
/// 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);
- return if (signed_r > -4096 and signed_r < 0) usize(-signed_r) else 0;
+ return if (signed_r > -4096 and signed_r < 0) @intCast(usize, -signed_r) else 0;
}
pub fn close(fd: i32) usize {
@@ -339,7 +339,14 @@ pub fn write(fd: i32, buf: [*]const u8, nbyte: usize) usize {
}
pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
- const ptr_result = c.mmap(@ptrCast(*c_void, address), length, @bitCast(c_int, c_uint(prot)), @bitCast(c_int, c_uint(flags)), fd, offset);
+ const ptr_result = c.mmap(
+ @ptrCast(*c_void, address),
+ length,
+ @bitCast(c_int, @intCast(c_uint, prot)),
+ @bitCast(c_int, c_uint(flags)),
+ fd,
+ offset,
+ );
const isize_result = @bitCast(isize, @ptrToInt(ptr_result));
return errnoWrap(isize_result);
}
diff --git a/std/os/file.zig b/std/os/file.zig
index 7e05501831e8995521d436c1ea3c4fd6f6f7e77b..055f18512137c5db131084aeba0f87dc9c74abe9 100644
--- a/std/os/file.zig
+++ b/std/os/file.zig
@@ -266,7 +266,7 @@ pub const File = struct {
pub fn getEndPos(self: *File) !usize {
if (is_posix) {
const stat = try os.posixFStat(self.handle);
- return usize(stat.size);
+ return @intCast(usize, stat.size);
} else if (is_windows) {
var file_size: windows.LARGE_INTEGER = undefined;
if (windows.GetFileSizeEx(self.handle, &file_size) == 0) {
@@ -277,7 +277,7 @@ pub const File = struct {
}
if (file_size < 0)
return error.Overflow;
- return math.cast(usize, u64(file_size));
+ return math.cast(usize, @intCast(u64, file_size));
} else {
@compileError("TODO support getEndPos on this OS");
}
@@ -343,7 +343,7 @@ pub const File = struct {
} else if (is_windows) {
var index: usize = 0;
while (index < buffer.len) {
- const want_read_count = windows.DWORD(math.min(windows.DWORD(@maxValue(windows.DWORD)), buffer.len - index));
+ const want_read_count = @intCast(windows.DWORD, math.min(windows.DWORD(@maxValue(windows.DWORD)), buffer.len - index));
var amt_read: windows.DWORD = undefined;
if (windows.ReadFile(self.handle, @ptrCast(*c_void, buffer.ptr + index), want_read_count, &amt_read, null) == 0) {
const err = windows.GetLastError();
diff --git a/std/os/index.zig b/std/os/index.zig
index fb4605fce02d7e42a88d8ee6567e7587ddc8fcb0..f1c3ab2128d938b1d0ad4d0c1cfaf1661da232aa 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -126,7 +126,7 @@ pub fn getRandomBytes(buf: []u8) !void {
}
defer _ = windows.CryptReleaseContext(hCryptProv, 0);
- if (windows.CryptGenRandom(hCryptProv, windows.DWORD(buf.len), buf.ptr) == 0) {
+ if (windows.CryptGenRandom(hCryptProv, @intCast(windows.DWORD, buf.len), buf.ptr) == 0) {
const err = windows.GetLastError();
return switch (err) {
else => unexpectedErrorWindows(err),
@@ -343,7 +343,7 @@ pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 {
else => return unexpectedErrorPosix(err),
}
}
- return i32(result);
+ return @intCast(i32, result);
}
}
@@ -586,7 +586,7 @@ pub fn getCwd(allocator: *Allocator) ![]u8 {
errdefer allocator.free(buf);
while (true) {
- const result = windows.GetCurrentDirectoryA(windows.WORD(buf.len), buf.ptr);
+ const result = windows.GetCurrentDirectoryA(@intCast(windows.WORD, buf.len), buf.ptr);
if (result == 0) {
const err = windows.GetLastError();
@@ -2019,7 +2019,7 @@ pub fn posixSocket(domain: u32, socket_type: u32, protocol: u32) !i32 {
const rc = posix.socket(domain, socket_type, protocol);
const err = posix.getErrno(rc);
switch (err) {
- 0 => return i32(rc),
+ 0 => return @intCast(i32, rc),
posix.EACCES => return PosixSocketError.PermissionDenied,
posix.EAFNOSUPPORT => return PosixSocketError.AddressFamilyNotSupported,
posix.EINVAL => return PosixSocketError.ProtocolFamilyNotAvailable,
@@ -2183,7 +2183,7 @@ pub fn posixAccept(fd: i32, addr: *posix.sockaddr, flags: u32) PosixAcceptError!
const rc = posix.accept4(fd, addr, &sockaddr_size, flags);
const err = posix.getErrno(rc);
switch (err) {
- 0 => return i32(rc),
+ 0 => return @intCast(i32, rc),
posix.EINTR => continue,
else => return unexpectedErrorPosix(err),
@@ -2226,7 +2226,7 @@ pub fn linuxEpollCreate(flags: u32) LinuxEpollCreateError!i32 {
const rc = posix.epoll_create1(flags);
const err = posix.getErrno(rc);
switch (err) {
- 0 => return i32(rc),
+ 0 => return @intCast(i32, rc),
else => return unexpectedErrorPosix(err),
posix.EINVAL => return LinuxEpollCreateError.InvalidSyscall,
@@ -2296,7 +2296,7 @@ pub fn linuxEpollCtl(epfd: i32, op: u32, fd: i32, event: *linux.epoll_event) Lin
pub fn linuxEpollWait(epfd: i32, events: []linux.epoll_event, timeout: i32) usize {
while (true) {
- const rc = posix.epoll_wait(epfd, events.ptr, u32(events.len), timeout);
+ const rc = posix.epoll_wait(epfd, events.ptr, @intCast(u32, events.len), timeout);
const err = posix.getErrno(rc);
switch (err) {
0 => return rc,
@@ -2661,7 +2661,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
posix.EAGAIN => return SpawnThreadError.SystemResources,
posix.EPERM => unreachable,
posix.EINVAL => unreachable,
- else => return unexpectedErrorPosix(usize(err)),
+ else => return unexpectedErrorPosix(@intCast(usize, err)),
}
} else if (builtin.os == builtin.Os.linux) {
// use linux API directly. TODO use posix.CLONE_SETTLS and initialize thread local storage correctly
diff --git a/std/os/linux/index.zig b/std/os/linux/index.zig
index 0e77371ec2e58e6401816f15e7c2efba8f70c7c6..65aa659c820155efb1ae5a5b96306c72077754eb 100644
--- a/std/os/linux/index.zig
+++ b/std/os/linux/index.zig
@@ -642,7 +642,7 @@ pub fn WIFEXITED(s: i32) bool {
return WTERMSIG(s) == 0;
}
pub fn WIFSTOPPED(s: i32) bool {
- return (u16)(((unsigned(s) & 0xffff) *% 0x10001) >> 8) > 0x7f00;
+ return @intCast(u16, ((unsigned(s) & 0xffff) *% 0x10001) >> 8) > 0x7f00;
}
pub fn WIFSIGNALED(s: i32) bool {
return (unsigned(s) & 0xffff) -% 1 < 0xff;
@@ -658,11 +658,11 @@ pub const winsize = extern struct {
/// 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);
- return if (signed_r > -4096 and signed_r < 0) usize(-signed_r) else 0;
+ return if (signed_r > -4096 and signed_r < 0) @intCast(usize, -signed_r) else 0;
}
pub fn dup2(old: i32, new: i32) usize {
- return syscall2(SYS_dup2, usize(old), usize(new));
+ return syscall2(SYS_dup2, @intCast(usize, old), @intCast(usize, new));
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -693,12 +693,12 @@ pub fn getcwd(buf: [*]u8, size: usize) usize {
}
pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize {
- return syscall3(SYS_getdents, usize(fd), @ptrToInt(dirp), count);
+ return syscall3(SYS_getdents, @intCast(usize, fd), @ptrToInt(dirp), count);
}
pub fn isatty(fd: i32) bool {
var wsz: winsize = undefined;
- return syscall3(SYS_ioctl, usize(fd), TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
+ return syscall3(SYS_ioctl, @intCast(usize, fd), TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -727,7 +727,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, usize(fd), @bitCast(usize, offset));
+ return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @intCast(usize, fd), @bitCast(usize, offset));
}
pub fn munmap(address: usize, length: usize) usize {
@@ -735,7 +735,7 @@ pub fn munmap(address: usize, length: usize) usize {
}
pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
- return syscall3(SYS_read, usize(fd), @ptrToInt(buf), count);
+ return syscall3(SYS_read, @intCast(usize, fd), @ptrToInt(buf), count);
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -749,7 +749,7 @@ pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
}
pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize {
- return syscall4(SYS_pread, usize(fd), @ptrToInt(buf), count, offset);
+ return syscall4(SYS_pread, @intCast(usize, fd), @ptrToInt(buf), count, offset);
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -766,11 +766,11 @@ pub fn pipe2(fd: *[2]i32, flags: usize) usize {
}
pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
- return syscall3(SYS_write, usize(fd), @ptrToInt(buf), count);
+ return syscall3(SYS_write, @intCast(usize, fd), @ptrToInt(buf), count);
}
pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
- return syscall4(SYS_pwrite, usize(fd), @ptrToInt(buf), count, offset);
+ return syscall4(SYS_pwrite, @intCast(usize, fd), @ptrToInt(buf), count, offset);
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -790,7 +790,7 @@ 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: usize, mode: usize) usize {
- return syscall4(SYS_openat, usize(dirfd), @ptrToInt(path), flags, mode);
+ return syscall4(SYS_openat, @intCast(usize, dirfd), @ptrToInt(path), flags, mode);
}
/// See also `clone` (from the arch-specific include)
@@ -804,11 +804,11 @@ pub fn clone2(flags: usize, child_stack_ptr: usize) usize {
}
pub fn close(fd: i32) usize {
- return syscall1(SYS_close, usize(fd));
+ return syscall1(SYS_close, @intCast(usize, fd));
}
pub fn lseek(fd: i32, offset: isize, ref_pos: usize) usize {
- return syscall3(SYS_lseek, usize(fd), @bitCast(usize, offset), ref_pos);
+ return syscall3(SYS_lseek, @intCast(usize, fd), @bitCast(usize, offset), ref_pos);
}
pub fn exit(status: i32) noreturn {
@@ -817,11 +817,11 @@ pub fn exit(status: i32) noreturn {
}
pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
- return syscall3(SYS_getrandom, @ptrToInt(buf), count, usize(flags));
+ return syscall3(SYS_getrandom, @ptrToInt(buf), count, @intCast(usize, flags));
}
pub fn kill(pid: i32, sig: i32) usize {
- return syscall2(SYS_kill, @bitCast(usize, isize(pid)), usize(sig));
+ return syscall2(SYS_kill, @bitCast(usize, isize(pid)), @intCast(usize, sig));
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -999,8 +999,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 = i32(syscall0(SYS_gettid));
- const ret = syscall2(SYS_tkill, usize(tid), usize(sig));
+ const tid = @intCast(i32, syscall0(SYS_gettid));
+ const ret = syscall2(SYS_tkill, @intCast(usize, tid), @intCast(usize, sig));
restoreSignals(&set);
return ret;
}
@@ -1019,12 +1019,12 @@ fn restoreSignals(set: *sigset_t) void {
pub fn sigaddset(set: *sigset_t, sig: u6) void {
const s = sig - 1;
- (set.*)[usize(s) / usize.bit_count] |= usize(1) << (s & (usize.bit_count - 1));
+ (set.*)[@intCast(usize, s) / usize.bit_count] |= @intCast(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;
+ return ((set.*)[@intCast(usize, s) / usize.bit_count] & (@intCast(usize, 1) << (s & (usize.bit_count - 1)))) != 0;
}
pub const in_port_t = u16;
@@ -1057,11 +1057,11 @@ pub const iovec = extern struct {
};
pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
- return syscall3(SYS_getsockname, usize(fd), @ptrToInt(addr), @ptrToInt(len));
+ return syscall3(SYS_getsockname, @intCast(usize, fd), @ptrToInt(addr), @ptrToInt(len));
}
pub fn getpeername(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
- return syscall3(SYS_getpeername, usize(fd), @ptrToInt(addr), @ptrToInt(len));
+ return syscall3(SYS_getpeername, @intCast(usize, fd), @ptrToInt(addr), @ptrToInt(len));
}
pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {
@@ -1069,47 +1069,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, usize(fd), level, optname, usize(optval), @ptrToInt(optlen));
+ return syscall5(SYS_setsockopt, @intCast(usize, fd), level, optname, @intCast(usize, optval), @ptrToInt(optlen));
}
pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noalias optlen: *socklen_t) usize {
- return syscall5(SYS_getsockopt, usize(fd), level, optname, @ptrToInt(optval), @ptrToInt(optlen));
+ return syscall5(SYS_getsockopt, @intCast(usize, fd), level, optname, @ptrToInt(optval), @ptrToInt(optlen));
}
pub fn sendmsg(fd: i32, msg: *const msghdr, flags: u32) usize {
- return syscall3(SYS_sendmsg, usize(fd), @ptrToInt(msg), flags);
+ return syscall3(SYS_sendmsg, @intCast(usize, fd), @ptrToInt(msg), flags);
}
pub fn connect(fd: i32, addr: *const sockaddr, len: socklen_t) usize {
- return syscall3(SYS_connect, usize(fd), @ptrToInt(addr), usize(len));
+ return syscall3(SYS_connect, @intCast(usize, fd), @ptrToInt(addr), @intCast(usize, len));
}
pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize {
- return syscall3(SYS_recvmsg, usize(fd), @ptrToInt(msg), flags);
+ return syscall3(SYS_recvmsg, @intCast(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 {
- return syscall6(SYS_recvfrom, usize(fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen));
+ return syscall6(SYS_recvfrom, @intCast(usize, fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen));
}
pub fn shutdown(fd: i32, how: i32) usize {
- return syscall2(SYS_shutdown, usize(fd), usize(how));
+ return syscall2(SYS_shutdown, @intCast(usize, fd), @intCast(usize, how));
}
pub fn bind(fd: i32, addr: *const sockaddr, len: socklen_t) usize {
- return syscall3(SYS_bind, usize(fd), @ptrToInt(addr), usize(len));
+ return syscall3(SYS_bind, @intCast(usize, fd), @ptrToInt(addr), @intCast(usize, len));
}
pub fn listen(fd: i32, backlog: u32) usize {
- return syscall2(SYS_listen, usize(fd), backlog);
+ return syscall2(SYS_listen, @intCast(usize, 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, usize(fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), usize(alen));
+ return syscall6(SYS_sendto, @intCast(usize, 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, usize(domain), usize(socket_type), 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 {
@@ -1117,11 +1117,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, usize(fd), @ptrToInt(addr), @ptrToInt(len), flags);
+ return syscall4(SYS_accept4, @intCast(usize, fd), @ptrToInt(addr), @ptrToInt(len), flags);
}
pub fn fstat(fd: i32, stat_buf: *Stat) usize {
- return syscall2(SYS_fstat, usize(fd), @ptrToInt(stat_buf));
+ return syscall2(SYS_fstat, @intCast(usize, fd), @ptrToInt(stat_buf));
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -1214,15 +1214,15 @@ 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, usize(epoll_fd), usize(op), usize(fd), @ptrToInt(ev));
+ return syscall4(SYS_epoll_ctl, @intCast(usize, epoll_fd), @intCast(usize, op), @intCast(usize, fd), @ptrToInt(ev));
}
pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize {
- return syscall4(SYS_epoll_wait, usize(epoll_fd), @ptrToInt(events), usize(maxevents), usize(timeout));
+ return syscall4(SYS_epoll_wait, @intCast(usize, epoll_fd), @ptrToInt(events), @intCast(usize, maxevents), @intCast(usize, timeout));
}
pub fn timerfd_create(clockid: i32, flags: u32) usize {
- return syscall2(SYS_timerfd_create, usize(clockid), usize(flags));
+ return syscall2(SYS_timerfd_create, @intCast(usize, clockid), @intCast(usize, flags));
}
pub const itimerspec = extern struct {
@@ -1231,11 +1231,11 @@ pub const itimerspec = extern struct {
};
pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize {
- return syscall2(SYS_timerfd_gettime, usize(fd), @ptrToInt(curr_value));
+ return syscall2(SYS_timerfd_gettime, @intCast(usize, 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, usize(fd), usize(flags), @ptrToInt(new_value), @ptrToInt(old_value));
+ return syscall4(SYS_timerfd_settime, @intCast(usize, fd), @intCast(usize, flags), @ptrToInt(new_value), @ptrToInt(old_value));
}
pub const _LINUX_CAPABILITY_VERSION_1 = 0x19980330;
@@ -1345,7 +1345,7 @@ pub const cap_user_data_t = extern struct {
};
pub fn unshare(flags: usize) usize {
- return syscall1(SYS_unshare, usize(flags));
+ return syscall1(SYS_unshare, @intCast(usize, flags));
}
pub fn capget(hdrp: *cap_user_header_t, datap: *cap_user_data_t) usize {
diff --git a/std/os/linux/test.zig b/std/os/linux/test.zig
index 948a3ac96b81b3252d9cc52b2998f90a7af6ba96..e7dae3a58495b3b82154b69e2d5c835646ea2652 100644
--- a/std/os/linux/test.zig
+++ b/std/os/linux/test.zig
@@ -21,7 +21,7 @@ test "timer" {
.it_value = time_interval,
};
- err = linux.timerfd_settime(i32(timer_fd), 0, &new_time, null);
+ err = linux.timerfd_settime(@intCast(i32, timer_fd), 0, &new_time, null);
assert(err == 0);
var event = linux.epoll_event{
@@ -29,12 +29,12 @@ test "timer" {
.data = linux.epoll_data{ .ptr = 0 },
};
- err = linux.epoll_ctl(i32(epoll_fd), linux.EPOLL_CTL_ADD, i32(timer_fd), &event);
+ err = linux.epoll_ctl(@intCast(i32, epoll_fd), linux.EPOLL_CTL_ADD, @intCast(i32, timer_fd), &event);
assert(err == 0);
const events_one: linux.epoll_event = undefined;
var events = []linux.epoll_event{events_one} ** 8;
// TODO implicit cast from *[N]T to [*]T
- err = linux.epoll_wait(i32(epoll_fd), @ptrCast([*]linux.epoll_event, &events), 8, -1);
+ err = linux.epoll_wait(@intCast(i32, epoll_fd), @ptrCast([*]linux.epoll_event, &events), 8, -1);
}
diff --git a/std/os/linux/vdso.zig b/std/os/linux/vdso.zig
index cbd0cd1df50771e695383dea852ce8d6668b66d5..a78e3370e6b4752b02fcc9b800cda9f700b3015c 100644
--- a/std/os/linux/vdso.zig
+++ b/std/os/linux/vdso.zig
@@ -62,8 +62,8 @@ pub fn lookup(vername: []const u8, name: []const u8) usize {
var i: usize = 0;
while (i < hashtab[1]) : (i += 1) {
- if (0 == (u32(1) << u5(syms[i].st_info & 0xf) & OK_TYPES)) continue;
- if (0 == (u32(1) << u5(syms[i].st_info >> 4) & OK_BINDS)) continue;
+ if (0 == (u32(1) << @intCast(u5, syms[i].st_info & 0xf) & OK_TYPES)) continue;
+ if (0 == (u32(1) << @intCast(u5, syms[i].st_info >> 4) & OK_BINDS)) continue;
if (0 == syms[i].st_shndx) continue;
if (!mem.eql(u8, name, cstr.toSliceConst(strings + syms[i].st_name))) continue;
if (maybe_versym) |versym| {
diff --git a/std/os/time.zig b/std/os/time.zig
index ffb506cd7dae6c98e8b853c57effdd4b2cd14d24..73ba5bba827cddf9dbfff4fc90f1a31eae9c256d 100644
--- a/std/os/time.zig
+++ b/std/os/time.zig
@@ -14,12 +14,12 @@ pub const epoch = @import("epoch.zig");
pub fn sleep(seconds: usize, nanoseconds: usize) void {
switch (builtin.os) {
Os.linux, Os.macosx, Os.ios => {
- posixSleep(u63(seconds), u63(nanoseconds));
+ posixSleep(@intCast(u63, seconds), @intCast(u63, nanoseconds));
},
Os.windows => {
const ns_per_ms = ns_per_s / ms_per_s;
const milliseconds = seconds * ms_per_s + nanoseconds / ns_per_ms;
- windows.Sleep(windows.DWORD(milliseconds));
+ windows.Sleep(@intCast(windows.DWORD, milliseconds));
},
else => @compileError("Unsupported OS"),
}
@@ -83,8 +83,8 @@ fn milliTimestampDarwin() u64 {
var tv: darwin.timeval = undefined;
var err = darwin.gettimeofday(&tv, null);
debug.assert(err == 0);
- const sec_ms = u64(tv.tv_sec) * ms_per_s;
- const usec_ms = @divFloor(u64(tv.tv_usec), us_per_s / ms_per_s);
+ const sec_ms = @intCast(u64, tv.tv_sec) * ms_per_s;
+ const usec_ms = @divFloor(@intCast(u64, tv.tv_usec), us_per_s / ms_per_s);
return u64(sec_ms) + u64(usec_ms);
}
@@ -95,8 +95,8 @@ fn milliTimestampPosix() u64 {
var ts: posix.timespec = undefined;
const err = posix.clock_gettime(posix.CLOCK_REALTIME, &ts);
debug.assert(err == 0);
- const sec_ms = u64(ts.tv_sec) * ms_per_s;
- const nsec_ms = @divFloor(u64(ts.tv_nsec), ns_per_s / ms_per_s);
+ const sec_ms = @intCast(u64, ts.tv_sec) * ms_per_s;
+ const nsec_ms = @divFloor(@intCast(u64, ts.tv_nsec), ns_per_s / ms_per_s);
return sec_ms + nsec_ms;
}
@@ -162,13 +162,13 @@ pub const Timer = struct {
var freq: i64 = undefined;
var err = windows.QueryPerformanceFrequency(&freq);
if (err == windows.FALSE) return error.TimerUnsupported;
- self.frequency = u64(freq);
+ self.frequency = @intCast(u64, freq);
self.resolution = @divFloor(ns_per_s, self.frequency);
var start_time: i64 = undefined;
err = windows.QueryPerformanceCounter(&start_time);
debug.assert(err != windows.FALSE);
- self.start_time = u64(start_time);
+ self.start_time = @intCast(u64, start_time);
},
Os.linux => {
//On Linux, seccomp can do arbitrary things to our ability to call
@@ -184,12 +184,12 @@ pub const Timer = struct {
posix.EINVAL => return error.TimerUnsupported,
else => return std.os.unexpectedErrorPosix(errno),
}
- self.resolution = u64(ts.tv_sec) * u64(ns_per_s) + u64(ts.tv_nsec);
+ self.resolution = @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
result = posix.clock_gettime(monotonic_clock_id, &ts);
errno = posix.getErrno(result);
if (errno != 0) return std.os.unexpectedErrorPosix(errno);
- self.start_time = u64(ts.tv_sec) * u64(ns_per_s) + u64(ts.tv_nsec);
+ self.start_time = @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
},
Os.macosx, Os.ios => {
darwin.mach_timebase_info(&self.frequency);
@@ -236,7 +236,7 @@ pub const Timer = struct {
var result: i64 = undefined;
var err = windows.QueryPerformanceCounter(&result);
debug.assert(err != windows.FALSE);
- return u64(result);
+ return @intCast(u64, result);
}
fn clockDarwin() u64 {
@@ -247,7 +247,7 @@ pub const Timer = struct {
var ts: posix.timespec = undefined;
var result = posix.clock_gettime(monotonic_clock_id, &ts);
debug.assert(posix.getErrno(result) == 0);
- return u64(ts.tv_sec) * u64(ns_per_s) + u64(ts.tv_nsec);
+ return @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec);
}
};
diff --git a/std/os/windows/util.zig b/std/os/windows/util.zig
index 88a9e7952efa03d43fa69e9c4f0ee4cdce24ad7f..cb4788ba17cfba66e03141333f5c8a174c48024e 100644
--- a/std/os/windows/util.zig
+++ b/std/os/windows/util.zig
@@ -42,7 +42,7 @@ pub const WriteError = error{
};
pub fn windowsWrite(handle: windows.HANDLE, bytes: []const u8) WriteError!void {
- if (windows.WriteFile(handle, @ptrCast(*const c_void, bytes.ptr), u32(bytes.len), null, null) == 0) {
+ if (windows.WriteFile(handle, @ptrCast(*const c_void, bytes.ptr), @intCast(u32, bytes.len), null, null) == 0) {
const err = windows.GetLastError();
return switch (err) {
windows.ERROR.INVALID_USER_BUFFER => WriteError.SystemResources,
@@ -68,7 +68,12 @@ pub fn windowsIsCygwinPty(handle: windows.HANDLE) bool {
const size = @sizeOf(windows.FILE_NAME_INFO);
var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = []u8{0} ** (size + windows.MAX_PATH);
- if (windows.GetFileInformationByHandleEx(handle, windows.FileNameInfo, @ptrCast(*c_void, &name_info_bytes[0]), u32(name_info_bytes.len)) == 0) {
+ if (windows.GetFileInformationByHandleEx(
+ handle,
+ windows.FileNameInfo,
+ @ptrCast(*c_void, &name_info_bytes[0]),
+ @intCast(u32, name_info_bytes.len),
+ ) == 0) {
return true;
}
diff --git a/std/rand/index.zig b/std/rand/index.zig
index 3a1a559cd92ef6342b0f70dfdd8aabac0fa3e730..13694f4c09a030524ac509f184e4f5bd5c8d7cc9 100644
--- a/std/rand/index.zig
+++ b/std/rand/index.zig
@@ -55,16 +55,16 @@ pub const Random = struct {
if (T.is_signed) {
const uint = @IntType(false, T.bit_count);
if (start >= 0 and end >= 0) {
- return T(r.range(uint, uint(start), uint(end)));
+ return @intCast(T, r.range(uint, @intCast(uint, start), @intCast(uint, end)));
} else if (start < 0 and end < 0) {
// Can't overflow because the range is over signed ints
return math.negateCast(r.range(uint, math.absCast(end), math.absCast(start)) + 1) catch unreachable;
} else if (start < 0 and end >= 0) {
- const end_uint = uint(end);
+ const end_uint = @intCast(uint, end);
const total_range = math.absCast(start) + end_uint;
const value = r.range(uint, 0, total_range);
const result = if (value < end_uint) x: {
- break :x T(value);
+ break :x @intCast(T, value);
} else if (value == end_uint) x: {
break :x start;
} else x: {
@@ -213,9 +213,9 @@ pub const Pcg = struct {
self.s = l *% default_multiplier +% (self.i | 1);
const xor_s = @truncate(u32, ((l >> 18) ^ l) >> 27);
- const rot = u32(l >> 59);
+ const rot = @intCast(u32, l >> 59);
- return (xor_s >> u5(rot)) | (xor_s << u5((0 -% rot) & 31));
+ return (xor_s >> @intCast(u5, rot)) | (xor_s << @intCast(u5, (0 -% rot) & 31));
}
fn seed(self: *Pcg, init_s: u64) void {
@@ -322,7 +322,7 @@ pub const Xoroshiro128 = struct {
inline for (table) |entry| {
var b: usize = 0;
while (b < 64) : (b += 1) {
- if ((entry & (u64(1) << u6(b))) != 0) {
+ if ((entry & (u64(1) << @intCast(u6, b))) != 0) {
s0 ^= self.s[0];
s1 ^= self.s[1];
}
@@ -667,13 +667,13 @@ test "Random range" {
}
fn testRange(r: *Random, start: i32, end: i32) void {
- const count = usize(end - start);
+ const count = @intCast(usize, end - start);
var values_buffer = []bool{false} ** 20;
const values = values_buffer[0..count];
var i: usize = 0;
while (i < count) {
const value = r.range(i32, start, end);
- const index = usize(value - start);
+ const index = @intCast(usize, value - start);
if (!values[index]) {
i += 1;
values[index] = true;
diff --git a/std/segmented_list.zig b/std/segmented_list.zig
index 9f10f4d44a3e43ba9f349fc412cb784a585b62ff..6e3f32e9d6e5bd2e377b30ebe5b295d0005dffc9 100644
--- a/std/segmented_list.zig
+++ b/std/segmented_list.zig
@@ -104,7 +104,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
}
pub fn deinit(self: *Self) void {
- self.freeShelves(ShelfIndex(self.dynamic_segments.len), 0);
+ self.freeShelves(@intCast(ShelfIndex, self.dynamic_segments.len), 0);
self.allocator.free(self.dynamic_segments);
self.* = undefined;
}
@@ -158,7 +158,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
/// Only grows capacity, or retains current capacity
pub fn growCapacity(self: *Self, new_capacity: usize) !void {
const new_cap_shelf_count = shelfCount(new_capacity);
- const old_shelf_count = ShelfIndex(self.dynamic_segments.len);
+ const old_shelf_count = @intCast(ShelfIndex, self.dynamic_segments.len);
if (new_cap_shelf_count > old_shelf_count) {
self.dynamic_segments = try self.allocator.realloc([*]T, self.dynamic_segments, new_cap_shelf_count);
var i = old_shelf_count;
@@ -175,7 +175,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
/// Only shrinks capacity or retains current capacity
pub fn shrinkCapacity(self: *Self, new_capacity: usize) void {
if (new_capacity <= prealloc_item_count) {
- const len = ShelfIndex(self.dynamic_segments.len);
+ const len = @intCast(ShelfIndex, self.dynamic_segments.len);
self.freeShelves(len, 0);
self.allocator.free(self.dynamic_segments);
self.dynamic_segments = [][*]T{};
@@ -183,7 +183,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
}
const new_cap_shelf_count = shelfCount(new_capacity);
- const old_shelf_count = ShelfIndex(self.dynamic_segments.len);
+ const old_shelf_count = @intCast(ShelfIndex, self.dynamic_segments.len);
assert(new_cap_shelf_count <= old_shelf_count);
if (new_cap_shelf_count == old_shelf_count) {
return;
@@ -338,7 +338,7 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void {
{
var i: usize = 0;
while (i < 100) : (i += 1) {
- try list.push(i32(i + 1));
+ try list.push(@intCast(i32, i + 1));
assert(list.len == i + 1);
}
}
@@ -346,7 +346,7 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void {
{
var i: usize = 0;
while (i < 100) : (i += 1) {
- assert(list.at(i).* == i32(i + 1));
+ assert(list.at(i).* == @intCast(i32, i + 1));
}
}
diff --git a/std/special/bootstrap.zig b/std/special/bootstrap.zig
index dd37f1edb6832e98fedbdbf57f7b1a16cb8e3364..5c8a330a92d4a22057ca141e39604e64951362d9 100644
--- a/std/special/bootstrap.zig
+++ b/std/special/bootstrap.zig
@@ -80,7 +80,7 @@ extern fn main(c_argc: i32, c_argv: [*][*]u8, c_envp: [*]?[*]u8) i32 {
var env_count: usize = 0;
while (c_envp[env_count] != null) : (env_count += 1) {}
const envp = @ptrCast([*][*]u8, c_envp)[0..env_count];
- return callMainWithArgs(usize(c_argc), c_argv, envp);
+ return callMainWithArgs(@intCast(usize, c_argc), c_argv, envp);
}
fn callMain() u8 {
diff --git a/std/special/builtin.zig b/std/special/builtin.zig
index e97b0a89e40c8b35190026aff420fd947fd61971..07e735d93175c8d35c7ef8d3848bec1f9c1bfd95 100644
--- a/std/special/builtin.zig
+++ b/std/special/builtin.zig
@@ -135,9 +135,9 @@ fn generic_fmod(comptime T: type, x: T, y: T) T {
const mask = if (T == f32) 0xff else 0x7ff;
var ux = @bitCast(uint, x);
var uy = @bitCast(uint, y);
- var ex = i32((ux >> digits) & mask);
- var ey = i32((uy >> digits) & mask);
- const sx = if (T == f32) u32(ux & 0x80000000) else i32(ux >> bits_minus_1);
+ var ex = @intCast(i32, (ux >> digits) & mask);
+ var ey = @intCast(i32, (uy >> digits) & mask);
+ const sx = if (T == f32) @intCast(u32, ux & 0x80000000) else @intCast(i32, ux >> bits_minus_1);
var i: uint = undefined;
if (uy << 1 == 0 or isNan(uint, uy) or ex == mask)
@@ -156,7 +156,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) T {
ex -= 1;
i <<= 1;
}) {}
- ux <<= log2uint(@bitCast(u32, -ex + 1));
+ ux <<= @intCast(log2uint, @bitCast(u32, -ex + 1));
} else {
ux &= @maxValue(uint) >> exp_bits;
ux |= 1 << digits;
@@ -167,7 +167,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) T {
ey -= 1;
i <<= 1;
}) {}
- uy <<= log2uint(@bitCast(u32, -ey + 1));
+ uy <<= @intCast(log2uint, @bitCast(u32, -ey + 1));
} else {
uy &= @maxValue(uint) >> exp_bits;
uy |= 1 << digits;
@@ -199,12 +199,12 @@ fn generic_fmod(comptime T: type, x: T, y: T) T {
ux -%= 1 << digits;
ux |= uint(@bitCast(u32, ex)) << digits;
} else {
- ux >>= log2uint(@bitCast(u32, -ex + 1));
+ ux >>= @intCast(log2uint, @bitCast(u32, -ex + 1));
}
if (T == f32) {
ux |= sx;
} else {
- ux |= uint(sx) << bits_minus_1;
+ ux |= @intCast(uint, sx) << bits_minus_1;
}
return @bitCast(T, ux);
}
@@ -227,8 +227,8 @@ export fn sqrt(x: f64) f64 {
const sign: u32 = 0x80000000;
const u = @bitCast(u64, x);
- var ix0 = u32(u >> 32);
- var ix1 = u32(u & 0xFFFFFFFF);
+ var ix0 = @intCast(u32, u >> 32);
+ var ix1 = @intCast(u32, u & 0xFFFFFFFF);
// sqrt(nan) = nan, sqrt(+inf) = +inf, sqrt(-inf) = nan
if (ix0 & 0x7FF00000 == 0x7FF00000) {
@@ -245,7 +245,7 @@ export fn sqrt(x: f64) f64 {
}
// normalize x
- var m = i32(ix0 >> 20);
+ var m = @intCast(i32, ix0 >> 20);
if (m == 0) {
// subnormal
while (ix0 == 0) {
@@ -259,9 +259,9 @@ export fn sqrt(x: f64) f64 {
while (ix0 & 0x00100000 == 0) : (i += 1) {
ix0 <<= 1;
}
- m -= i32(i) - 1;
- ix0 |= ix1 >> u5(32 - i);
- ix1 <<= u5(i);
+ m -= @intCast(i32, i) - 1;
+ ix0 |= ix1 >> @intCast(u5, 32 - i);
+ ix1 <<= @intCast(u5, i);
}
// unbias exponent
@@ -345,10 +345,10 @@ export fn sqrt(x: f64) f64 {
// NOTE: musl here appears to rely on signed twos-complement wraparound. +% has the same
// behaviour at least.
- var iix0 = i32(ix0);
+ var iix0 = @intCast(i32, ix0);
iix0 = iix0 +% (m << 20);
- const uz = (u64(iix0) << 32) | ix1;
+ const uz = (@intCast(u64, iix0) << 32) | ix1;
return @bitCast(f64, uz);
}
diff --git a/std/special/compiler_rt/divti3.zig b/std/special/compiler_rt/divti3.zig
index 60460ea62d3a8106bed79ef8bdd21f784322083e..712cccba8234649bc2b76471bf0d990ce8b7eaf3 100644
--- a/std/special/compiler_rt/divti3.zig
+++ b/std/special/compiler_rt/divti3.zig
@@ -13,7 +13,7 @@ pub extern fn __divti3(a: i128, b: i128) i128 {
const r = udivmod(u128, @bitCast(u128, an), @bitCast(u128, bn), null);
const s = s_a ^ s_b;
- return (i128(r) ^ s) -% s;
+ return (@bitCast(i128, r) ^ s) -% s;
}
pub extern fn __divti3_windows_x86_64(a: *const i128, b: *const i128) void {
diff --git a/std/special/compiler_rt/fixuint.zig b/std/special/compiler_rt/fixuint.zig
index bd9b2fc395b76655fa9508ea06c13f603b1e2a22..48d63ed9142022a4436c99c4382150ada05f9e69 100644
--- a/std/special/compiler_rt/fixuint.zig
+++ b/std/special/compiler_rt/fixuint.zig
@@ -32,14 +32,14 @@ pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t
const aAbs: rep_t = aRep & absMask;
const sign = if ((aRep & signBit) != 0) i32(-1) else i32(1);
- const exponent = i32(aAbs >> significandBits) - exponentBias;
+ const exponent = @intCast(i32, aAbs >> significandBits) - exponentBias;
const significand: rep_t = (aAbs & significandMask) | implicitBit;
// If either the value or the exponent is negative, the result is zero.
if (sign == -1 or exponent < 0) return 0;
// If the value is too large for the integer type, saturate.
- if (c_uint(exponent) >= fixuint_t.bit_count) return ~fixuint_t(0);
+ if (@intCast(c_uint, exponent) >= fixuint_t.bit_count) return ~fixuint_t(0);
// If 0 <= exponent < significandBits, right shift to get the result.
// Otherwise, shift left.
@@ -47,11 +47,11 @@ pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t
// TODO this is a workaround for the mysterious "integer cast truncated bits"
// happening on the next line
@setRuntimeSafety(false);
- return fixuint_t(significand >> Log2Int(rep_t)(significandBits - exponent));
+ return @intCast(fixuint_t, significand >> @intCast(Log2Int(rep_t), significandBits - exponent));
} else {
// TODO this is a workaround for the mysterious "integer cast truncated bits"
// happening on the next line
@setRuntimeSafety(false);
- return fixuint_t(significand) << Log2Int(fixuint_t)(exponent - significandBits);
+ return @intCast(fixuint_t, significand) << @intCast(Log2Int(fixuint_t), exponent - significandBits);
}
}
diff --git a/std/special/compiler_rt/index.zig b/std/special/compiler_rt/index.zig
index f95273035397527d0632edfe3a5726bdac415821..dc95aa23f2506934e1267c6850d9954f357f31d8 100644
--- a/std/special/compiler_rt/index.zig
+++ b/std/special/compiler_rt/index.zig
@@ -292,7 +292,7 @@ extern fn __udivmodsi4(a: u32, b: u32, rem: *u32) u32 {
@setRuntimeSafety(is_test);
const d = __udivsi3(a, b);
- rem.* = u32(i32(a) -% (i32(d) * i32(b)));
+ rem.* = @bitCast(u32, @bitCast(i32, a) -% (@bitCast(i32, d) * @bitCast(i32, b)));
return d;
}
@@ -316,12 +316,12 @@ extern fn __udivsi3(n: u32, d: u32) u32 {
sr += 1;
// 1 <= sr <= n_uword_bits - 1
// Not a special case
- var q: u32 = n << u5(n_uword_bits - sr);
- var r: u32 = n >> u5(sr);
+ var q: u32 = n << @intCast(u5, n_uword_bits - sr);
+ var r: u32 = n >> @intCast(u5, sr);
var carry: u32 = 0;
while (sr > 0) : (sr -= 1) {
// r:q = ((r:q) << 1) | carry
- r = (r << 1) | (q >> u5(n_uword_bits - 1));
+ r = (r << 1) | (q >> @intCast(u5, n_uword_bits - 1));
q = (q << 1) | carry;
// carry = 0;
// if (r.all >= d.all)
@@ -329,8 +329,8 @@ extern fn __udivsi3(n: u32, d: u32) u32 {
// r.all -= d.all;
// carry = 1;
// }
- const s = i32(d -% r -% 1) >> u5(n_uword_bits - 1);
- carry = u32(s & 1);
+ const s = @intCast(i32, d -% r -% 1) >> @intCast(u5, n_uword_bits - 1);
+ carry = @intCast(u32, s & 1);
r -= d & @bitCast(u32, s);
}
q = (q << 1) | carry;
diff --git a/std/special/compiler_rt/udivmod.zig b/std/special/compiler_rt/udivmod.zig
index 894dd022393dda124409d0a84f7b59dff22711d6..e6b4ee04824437dc8ef6869ff80c3bdb3d5721fa 100644
--- a/std/special/compiler_rt/udivmod.zig
+++ b/std/special/compiler_rt/udivmod.zig
@@ -71,7 +71,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
r[high] = n[high] & (d[high] - 1);
rem.* = @ptrCast(*align(@alignOf(SingleInt)) DoubleInt, &r[0]).*; // TODO issue #421
}
- return n[high] >> Log2SingleInt(@ctz(d[high]));
+ return n[high] >> @intCast(Log2SingleInt, @ctz(d[high]));
}
// K K
// ---
@@ -88,10 +88,10 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
// 1 <= sr <= SingleInt.bit_count - 1
// q.all = a << (DoubleInt.bit_count - sr);
q[low] = 0;
- q[high] = n[low] << Log2SingleInt(SingleInt.bit_count - sr);
+ q[high] = n[low] << @intCast(Log2SingleInt, SingleInt.bit_count - sr);
// r.all = a >> sr;
- r[high] = n[high] >> Log2SingleInt(sr);
- r[low] = (n[high] << Log2SingleInt(SingleInt.bit_count - sr)) | (n[low] >> Log2SingleInt(sr));
+ r[high] = n[high] >> @intCast(Log2SingleInt, sr);
+ r[low] = (n[high] << @intCast(Log2SingleInt, SingleInt.bit_count - sr)) | (n[low] >> @intCast(Log2SingleInt, sr));
} else {
// d[low] != 0
if (d[high] == 0) {
@@ -107,8 +107,8 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
return a;
}
sr = @ctz(d[low]);
- q[high] = n[high] >> Log2SingleInt(sr);
- q[low] = (n[high] << Log2SingleInt(SingleInt.bit_count - sr)) | (n[low] >> Log2SingleInt(sr));
+ q[high] = n[high] >> @intCast(Log2SingleInt, sr);
+ q[low] = (n[high] << @intCast(Log2SingleInt, SingleInt.bit_count - sr)) | (n[low] >> @intCast(Log2SingleInt, sr));
return @ptrCast(*align(@alignOf(SingleInt)) DoubleInt, &q[0]).*; // TODO issue #421
}
// K X
@@ -126,15 +126,15 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
} else if (sr < SingleInt.bit_count) {
// 2 <= sr <= SingleInt.bit_count - 1
q[low] = 0;
- q[high] = n[low] << Log2SingleInt(SingleInt.bit_count - sr);
- r[high] = n[high] >> Log2SingleInt(sr);
- r[low] = (n[high] << Log2SingleInt(SingleInt.bit_count - sr)) | (n[low] >> Log2SingleInt(sr));
+ q[high] = n[low] << @intCast(Log2SingleInt, SingleInt.bit_count - sr);
+ r[high] = n[high] >> @intCast(Log2SingleInt, sr);
+ r[low] = (n[high] << @intCast(Log2SingleInt, SingleInt.bit_count - sr)) | (n[low] >> @intCast(Log2SingleInt, sr));
} else {
// SingleInt.bit_count + 1 <= sr <= DoubleInt.bit_count - 1
- q[low] = n[low] << Log2SingleInt(DoubleInt.bit_count - sr);
- q[high] = (n[high] << Log2SingleInt(DoubleInt.bit_count - sr)) | (n[low] >> Log2SingleInt(sr - SingleInt.bit_count));
+ q[low] = n[low] << @intCast(Log2SingleInt, DoubleInt.bit_count - sr);
+ q[high] = (n[high] << @intCast(Log2SingleInt, DoubleInt.bit_count - sr)) | (n[low] >> @intCast(Log2SingleInt, sr - SingleInt.bit_count));
r[high] = 0;
- r[low] = n[high] >> Log2SingleInt(sr - SingleInt.bit_count);
+ r[low] = n[high] >> @intCast(Log2SingleInt, sr - SingleInt.bit_count);
}
} else {
// K X
@@ -158,9 +158,9 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
r[high] = 0;
r[low] = n[high];
} else {
- r[high] = n[high] >> Log2SingleInt(sr);
- r[low] = (n[high] << Log2SingleInt(SingleInt.bit_count - sr)) | (n[low] >> Log2SingleInt(sr));
- q[high] = n[low] << Log2SingleInt(SingleInt.bit_count - sr);
+ r[high] = n[high] >> @intCast(Log2SingleInt, sr);
+ r[low] = (n[high] << @intCast(Log2SingleInt, SingleInt.bit_count - sr)) | (n[low] >> @intCast(Log2SingleInt, sr));
+ q[high] = n[low] << @intCast(Log2SingleInt, SingleInt.bit_count - sr);
}
}
}
@@ -184,8 +184,8 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
// carry = 1;
// }
r_all = @ptrCast(*align(@alignOf(SingleInt)) DoubleInt, &r[0]).*; // TODO issue #421
- const s: SignedDoubleInt = SignedDoubleInt(b -% r_all -% 1) >> (DoubleInt.bit_count - 1);
- carry = u32(s & 1);
+ const s: SignedDoubleInt = @intCast(SignedDoubleInt, b -% r_all -% 1) >> (DoubleInt.bit_count - 1);
+ carry = @intCast(u32, s & 1);
r_all -= b & @bitCast(DoubleInt, s);
r = @ptrCast(*[2]SingleInt, &r_all).*; // TODO issue #421
}
diff --git a/std/unicode.zig b/std/unicode.zig
index ec808ca4fe4837a7a8acd7a4e0bee71521b05931..9c329acc6831248248d1f20824efb2f8abbebfd0 100644
--- a/std/unicode.zig
+++ b/std/unicode.zig
@@ -35,22 +35,22 @@ pub fn utf8Encode(c: u32, out: []u8) !u3 {
// - Increasing the initial shift by 6 each time
// - Each time after the first shorten the shifted
// value to a max of 0b111111 (63)
- 1 => out[0] = u8(c), // Can just do 0 + codepoint for initial range
+ 1 => out[0] = @intCast(u8, c), // Can just do 0 + codepoint for initial range
2 => {
- out[0] = u8(0b11000000 | (c >> 6));
- out[1] = u8(0b10000000 | (c & 0b111111));
+ out[0] = @intCast(u8, 0b11000000 | (c >> 6));
+ out[1] = @intCast(u8, 0b10000000 | (c & 0b111111));
},
3 => {
if (0xd800 <= c and c <= 0xdfff) return error.Utf8CannotEncodeSurrogateHalf;
- out[0] = u8(0b11100000 | (c >> 12));
- out[1] = u8(0b10000000 | ((c >> 6) & 0b111111));
- out[2] = u8(0b10000000 | (c & 0b111111));
+ out[0] = @intCast(u8, 0b11100000 | (c >> 12));
+ out[1] = @intCast(u8, 0b10000000 | ((c >> 6) & 0b111111));
+ out[2] = @intCast(u8, 0b10000000 | (c & 0b111111));
},
4 => {
- out[0] = u8(0b11110000 | (c >> 18));
- out[1] = u8(0b10000000 | ((c >> 12) & 0b111111));
- out[2] = u8(0b10000000 | ((c >> 6) & 0b111111));
- out[3] = u8(0b10000000 | (c & 0b111111));
+ out[0] = @intCast(u8, 0b11110000 | (c >> 18));
+ out[1] = @intCast(u8, 0b10000000 | ((c >> 12) & 0b111111));
+ out[2] = @intCast(u8, 0b10000000 | ((c >> 6) & 0b111111));
+ out[3] = @intCast(u8, 0b10000000 | (c & 0b111111));
},
else => unreachable,
}
diff --git a/std/zig/tokenizer.zig b/std/zig/tokenizer.zig
index 4534529f365335d5f8f0ab69fb1310878446531f..79f1871b641001e0afbcf86c3071933b8d28a973 100644
--- a/std/zig/tokenizer.zig
+++ b/std/zig/tokenizer.zig
@@ -1128,7 +1128,7 @@ pub const Tokenizer = struct {
// check utf8-encoded character.
const length = std.unicode.utf8ByteSequenceLength(c0) catch return 1;
if (self.index + length > self.buffer.len) {
- return u3(self.buffer.len - self.index);
+ return @intCast(u3, self.buffer.len - self.index);
}
const bytes = self.buffer[self.index .. self.index + length];
switch (length) {
diff --git a/test/cases/cast.zig b/test/cases/cast.zig
index 4c216010eb00cb53e1806954187cacebb3101ab5..7035740c5487a297ccd1fb833abaa343d50cc351 100644
--- a/test/cases/cast.zig
+++ b/test/cases/cast.zig
@@ -343,7 +343,7 @@ fn testPeerErrorAndArray2(x: u8) error![]const u8 {
test "explicit cast float number literal to integer if no fraction component" {
const x = i32(1e4);
assert(x == 10000);
- const y = i32(f32(1e4));
+ const y = @floatToInt(i32, f32(1e4));
assert(y == 10000);
}
@@ -398,3 +398,19 @@ test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
const x: [*]const ?[*]const u8 = &window_name;
assert(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name"));
}
+
+test "@intCast comptime_int" {
+ const result = @intCast(i32, 1234);
+ assert(@typeOf(result) == i32);
+ assert(result == 1234);
+}
+
+test "@floatCast comptime_int and comptime_float" {
+ const result = @floatCast(f32, 1234);
+ assert(@typeOf(result) == f32);
+ assert(result == 1234.0);
+
+ const result2 = @floatCast(f32, 1234.0);
+ assert(@typeOf(result) == f32);
+ assert(result == 1234.0);
+}
diff --git a/test/cases/enum.zig b/test/cases/enum.zig
index 5c78d73092ff92a64ce726b43f6c032c3397d376..6a02a477841875e9959a7b547b8d445a8626b804 100644
--- a/test/cases/enum.zig
+++ b/test/cases/enum.zig
@@ -99,7 +99,7 @@ test "int to enum" {
testIntToEnumEval(3);
}
fn testIntToEnumEval(x: i32) void {
- assert(IntToEnumNumber(u3(x)) == IntToEnumNumber.Three);
+ assert(IntToEnumNumber(@intCast(u3, x)) == IntToEnumNumber.Three);
}
const IntToEnumNumber = enum {
Zero,
diff --git a/test/cases/eval.zig b/test/cases/eval.zig
index 08d3f3a841cbdd3c60729948b7c926a5e2131a3b..6c919e17a6b7cfb380f07ed7535d886aa9f579a5 100644
--- a/test/cases/eval.zig
+++ b/test/cases/eval.zig
@@ -5,7 +5,7 @@ const builtin = @import("builtin");
test "compile time recursion" {
assert(some_data.len == 21);
}
-var some_data: [usize(fibonacci(7))]u8 = undefined;
+var some_data: [@intCast(usize, fibonacci(7))]u8 = undefined;
fn fibonacci(x: i32) i32 {
if (x <= 1) return 1;
return fibonacci(x - 1) + fibonacci(x - 2);
@@ -356,7 +356,7 @@ const global_array = x: {
test "compile-time downcast when the bits fit" {
comptime {
const spartan_count: u16 = 255;
- const byte = u8(spartan_count);
+ const byte = @intCast(u8, spartan_count);
assert(byte == 255);
}
}
@@ -440,7 +440,7 @@ test "binary math operator in partially inlined function" {
var b: [16]u8 = undefined;
for (b) |*r, i|
- r.* = u8(i + 1);
+ r.* = @intCast(u8, i + 1);
copyWithPartialInline(s[0..], b[0..]);
assert(s[0] == 0x1020304);
@@ -480,7 +480,7 @@ fn generateTable(comptime T: type) [1010]T {
var res: [1010]T = undefined;
var i: usize = 0;
while (i < 1010) : (i += 1) {
- res[i] = T(i);
+ res[i] = @intCast(T, i);
}
return res;
}
diff --git a/test/cases/fn.zig b/test/cases/fn.zig
index 12f22bfc356c4eaf4bb52107e83b8717c37615f7..47f7d5e68881c1da35a1b4eb687b5981c375ef9b 100644
--- a/test/cases/fn.zig
+++ b/test/cases/fn.zig
@@ -80,7 +80,7 @@ test "function pointers" {
fn4,
};
for (fns) |f, i| {
- assert(f() == u32(i) + 5);
+ assert(f() == @intCast(u32, i) + 5);
}
}
fn fn1() u32 {
diff --git a/test/cases/for.zig b/test/cases/for.zig
index bdbab312f6b0225ae3487b3e87325e3281cdc200..59d90c1b851fed17a6075ce7de521e78fea59e9b 100644
--- a/test/cases/for.zig
+++ b/test/cases/for.zig
@@ -46,7 +46,7 @@ test "basic for loop" {
buf_index += 1;
}
for (array) |item, index| {
- buffer[buf_index] = u8(index);
+ buffer[buf_index] = @intCast(u8, index);
buf_index += 1;
}
const unknown_size: []const u8 = array;
@@ -55,7 +55,7 @@ test "basic for loop" {
buf_index += 1;
}
for (unknown_size) |item, index| {
- buffer[buf_index] = u8(index);
+ buffer[buf_index] = @intCast(u8, index);
buf_index += 1;
}
diff --git a/test/cases/struct.zig b/test/cases/struct.zig
index 6952611a8c815d2cfb3450ba99951b89fe7ca0c7..94a2ba633651e5676b8a5ec017ab6a661f37f572 100644
--- a/test/cases/struct.zig
+++ b/test/cases/struct.zig
@@ -365,14 +365,14 @@ test "runtime struct initialization of bitfield" {
.y = x1,
};
const s2 = Nibbles{
- .x = u4(x2),
- .y = u4(x2),
+ .x = @intCast(u4, x2),
+ .y = @intCast(u4, x2),
};
assert(s1.x == x1);
assert(s1.y == x1);
- assert(s2.x == u4(x2));
- assert(s2.y == u4(x2));
+ assert(s2.x == @intCast(u4, x2));
+ assert(s2.y == @intCast(u4, x2));
}
var x1 = u4(1);
--
2.54.0
From 3c12ba718029adac707eeb6e86399f71b74c892e Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sun, 17 Jun 2018 04:32:57 -0400
Subject: [PATCH 13/28] update test cases
---
test/compare_output.zig | 4 ++--
test/compile_errors.zig | 8 ++++----
test/runtime_safety.zig | 4 ++--
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/test/compare_output.zig b/test/compare_output.zig
index eec077ef85057b19deeee83b1d43418fe903f3ec..b60b844b1c60d3b7e0b41db19cc261e581025da7 100644
--- a/test/compare_output.zig
+++ b/test/compare_output.zig
@@ -331,8 +331,8 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\ }
\\ const small: f32 = 3.25;
\\ const x: f64 = small;
- \\ const y = i32(x);
- \\ const z = f64(y);
+ \\ const y = @floatToInt(i32, x);
+ \\ const z = @intToFloat(f64, y);
\\ _ = c.printf(c"%.2f\n%d\n%.2f\n%.2f\n", x, y, z, f64(-0.4));
\\ return 0;
\\}
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index ed46e43066b8904de1194089e47f621e0f1bfa0b..b51a6e97612cca2685eb4ef9f7aed9f54528b20d 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -2931,10 +2931,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"cast negative value to unsigned integer",
\\comptime {
\\ const value: i32 = -1;
- \\ const unsigned = u32(value);
+ \\ const unsigned = @intCast(u32, value);
\\}
,
- ".tmp_source.zig:3:25: error: attempt to cast negative value to unsigned integer",
+ ".tmp_source.zig:3:22: error: attempt to cast negative value to unsigned integer",
);
cases.add(
@@ -2963,10 +2963,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"compile-time integer cast truncates bits",
\\comptime {
\\ const spartan_count: u16 = 300;
- \\ const byte = u8(spartan_count);
+ \\ const byte = @intCast(u8, spartan_count);
\\}
,
- ".tmp_source.zig:3:20: error: cast from 'u16' to 'u8' truncates bits",
+ ".tmp_source.zig:3:18: error: cast from 'u16' to 'u8' truncates bits",
);
cases.add(
diff --git a/test/runtime_safety.zig b/test/runtime_safety.zig
index 61eba9458ebf5e1fed31b297ab55838ce6d602bf..96384066e50456fc5803f2bb8c82a1ad32650fdd 100644
--- a/test/runtime_safety.zig
+++ b/test/runtime_safety.zig
@@ -188,7 +188,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\ if (x == 0) return error.Whatever;
\\}
\\fn shorten_cast(x: i32) i8 {
- \\ return i8(x);
+ \\ return @intCast(i8, x);
\\}
);
@@ -201,7 +201,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\ if (x == 0) return error.Whatever;
\\}
\\fn unsigned_cast(x: i32) u32 {
- \\ return u32(x);
+ \\ return @intCast(u32, x);
\\}
);
--
2.54.0
From 74ccf56a4b1da78b6cd6b0ac34dd6ded1e15b155 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sun, 17 Jun 2018 12:33:24 -0400
Subject: [PATCH 14/28] update more tests
---
example/hello_world/hello_libc.zig | 2 +-
test/compare_output.zig | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/example/hello_world/hello_libc.zig b/example/hello_world/hello_libc.zig
index f64beda40f4094eb784c9550f75df6c208ebf2ed..60a1f7687142714cae2fc2939bf2fe90f5fffa8c 100644
--- a/example/hello_world/hello_libc.zig
+++ b/example/hello_world/hello_libc.zig
@@ -8,7 +8,7 @@ const c = @cImport({
const msg = c"Hello, world!\n";
export fn main(argc: c_int, argv: **u8) c_int {
- if (c.printf(msg) != c_int(c.strlen(msg))) return -1;
+ if (c.printf(msg) != @intCast(c_int, c.strlen(msg))) return -1;
return 0;
}
diff --git a/test/compare_output.zig b/test/compare_output.zig
index b60b844b1c60d3b7e0b41db19cc261e581025da7..a18a78b419c6e14bb8a6cacbb7ff68191ff4edd3 100644
--- a/test/compare_output.zig
+++ b/test/compare_output.zig
@@ -299,7 +299,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\export fn main() c_int {
\\ var array = []u32{ 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 };
\\
- \\ c.qsort(@ptrCast(?*c_void, array[0..].ptr), c_ulong(array.len), @sizeOf(i32), compare_fn);
+ \\ c.qsort(@ptrCast(?*c_void, array[0..].ptr), @intCast(c_ulong, array.len), @sizeOf(i32), compare_fn);
\\
\\ for (array) |item, i| {
\\ if (item != i) {
--
2.54.0
From e5956f23ca702b79a3a4b0f0440a2fe88e0231e5 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sun, 17 Jun 2018 12:47:27 -0400
Subject: [PATCH 15/28] add target C int type information for msp430 target
closes #1125
---
src/target.cpp | 50 +++++++++++++++++++++++++++++++++++---------------
1 file changed, 35 insertions(+), 15 deletions(-)
diff --git a/src/target.cpp b/src/target.cpp
index bd4aa4d4c230b305711ac5980189074fe1ed9116..c717c533dfb15b5c3fe9a9a2f983017d26c50c14 100644
--- a/src/target.cpp
+++ b/src/target.cpp
@@ -686,21 +686,41 @@ static int get_arch_pointer_bit_width(ZigLLVM_ArchType arch) {
uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
switch (target->os) {
case OsFreestanding:
- switch (id) {
- case CIntTypeShort:
- case CIntTypeUShort:
- return 16;
- case CIntTypeInt:
- case CIntTypeUInt:
- return 32;
- case CIntTypeLong:
- case CIntTypeULong:
- return get_arch_pointer_bit_width(target->arch.arch);
- case CIntTypeLongLong:
- case CIntTypeULongLong:
- return 64;
- case CIntTypeCount:
- zig_unreachable();
+ switch (target->arch.arch) {
+ case ZigLLVM_msp430:
+ switch (id) {
+ case CIntTypeShort:
+ case CIntTypeUShort:
+ return 16;
+ case CIntTypeInt:
+ case CIntTypeUInt:
+ return 16;
+ case CIntTypeLong:
+ case CIntTypeULong:
+ return get_arch_pointer_bit_width(target->arch.arch);
+ case CIntTypeLongLong:
+ case CIntTypeULongLong:
+ return 64;
+ case CIntTypeCount:
+ zig_unreachable();
+ }
+ default:
+ switch (id) {
+ case CIntTypeShort:
+ case CIntTypeUShort:
+ return 16;
+ case CIntTypeInt:
+ case CIntTypeUInt:
+ return 32;
+ case CIntTypeLong:
+ case CIntTypeULong:
+ return get_arch_pointer_bit_width(target->arch.arch);
+ case CIntTypeLongLong:
+ case CIntTypeULongLong:
+ return 64;
+ case CIntTypeCount:
+ zig_unreachable();
+ }
}
case OsLinux:
case OsMacOSX:
--
2.54.0
From 906ed059ce7c5c9acb5088d38d9da76ad5c93407 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 18 Jun 2018 00:52:55 -0400
Subject: [PATCH 16/28] update std.DynLib to use @intCast
---
std/dynamic_library.zig | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/std/dynamic_library.zig b/std/dynamic_library.zig
index 8fe5f7f818e6e007c281115cb4b2303503049b1f..ed190f7deb7d091f66694b77911aa2bf460c6e90 100644
--- a/std/dynamic_library.zig
+++ b/std/dynamic_library.zig
@@ -16,7 +16,7 @@ pub const DynLib = struct {
const fd = try std.os.posixOpen(allocator, path, 0, linux.O_RDONLY | linux.O_CLOEXEC);
errdefer std.os.close(fd);
- const size = usize((try std.os.posixFStat(fd)).size);
+ const size = @intCast(usize, (try std.os.posixFStat(fd)).size);
const addr = linux.mmap(
null,
@@ -126,8 +126,8 @@ pub const ElfLib = struct {
var i: usize = 0;
while (i < self.hashtab[1]) : (i += 1) {
- if (0 == (u32(1) << u5(self.syms[i].st_info & 0xf) & OK_TYPES)) continue;
- if (0 == (u32(1) << u5(self.syms[i].st_info >> 4) & OK_BINDS)) continue;
+ if (0 == (u32(1) << @intCast(u5, self.syms[i].st_info & 0xf) & OK_TYPES)) continue;
+ if (0 == (u32(1) << @intCast(u5, self.syms[i].st_info >> 4) & OK_BINDS)) continue;
if (0 == self.syms[i].st_shndx) continue;
if (!mem.eql(u8, name, cstr.toSliceConst(self.strings + self.syms[i].st_name))) continue;
if (maybe_versym) |versym| {
--
2.54.0
From 92a36040b1d0882c1e9439b998d3b855e84b9f2c Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 18 Jun 2018 01:03:45 -0400
Subject: [PATCH 17/28] msp430 target: c_long is always 32 bits
closes #1125
---
src/target.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/target.cpp b/src/target.cpp
index c717c533dfb15b5c3fe9a9a2f983017d26c50c14..91d36c5109e0e070252d73056992c49221d65c0a 100644
--- a/src/target.cpp
+++ b/src/target.cpp
@@ -697,7 +697,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
return 16;
case CIntTypeLong:
case CIntTypeULong:
- return get_arch_pointer_bit_width(target->arch.arch);
+ return 32;
case CIntTypeLongLong:
case CIntTypeULongLong:
return 64;
--
2.54.0
From d52ef95f77478582e5c479cc2bd0a4ecb5591933 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 18 Jun 2018 01:09:51 -0400
Subject: [PATCH 18/28] disable failing macos test. see #1126
I'm unable to reproduce the failure on my mac laptop
more investigation required
---
test/build_examples.zig | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/test/build_examples.zig b/test/build_examples.zig
index b48fcbb698e0e8d3b54d382b3c1adf2244b5bca1..79192c3e9aacd872cab3768af5a66affa651df65 100644
--- a/test/build_examples.zig
+++ b/test/build_examples.zig
@@ -13,7 +13,10 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void {
cases.addBuildFile("example/shared_library/build.zig");
cases.addBuildFile("example/mix_o_files/build.zig");
}
- cases.addBuildFile("test/standalone/issue_339/build.zig");
+ if (builtin.os != builtin.Os.macosx) {
+ // TODO https://github.com/ziglang/zig/issues/1126
+ cases.addBuildFile("test/standalone/issue_339/build.zig");
+ }
cases.addBuildFile("test/standalone/issue_794/build.zig");
cases.addBuildFile("test/standalone/pkg_import/build.zig");
cases.addBuildFile("test/standalone/use_alias/build.zig");
--
2.54.0
From 4210f1f6a0f55fb7c7b287ac691582752340f79d Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 18 Jun 2018 03:07:16 -0400
Subject: [PATCH 19/28] remove bool to int syntax. add @boolToInt
add missing docs
See #1061
---
doc/langref.html.in | 90 ++++++++++++++++++++------
src/all_types.hpp | 8 +++
src/codegen.cpp | 2 +
src/ir.cpp | 60 +++++++++++++++--
src/ir_print.cpp | 9 +++
std/fmt/errol/index.zig | 4 +-
std/math/big/int.zig | 18 +++---
std/special/compiler_rt/comparetf2.zig | 2 +-
test/cases/bool.zig | 8 +--
9 files changed, 158 insertions(+), 43 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 35ca9a13b43d9c07062d60a55d69541ee139ac2e..7c1f9b53d9e680beb494e0baf3d26450ecdb6b0f 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -4560,6 +4560,19 @@ comptime {
{#see_also|Alignment#}
{#header_close#}
+
+ {#header_open|@boolToInt#}
+ @boolToInt(value: bool) u1
+
+ Converts true to u1(1) and false to
+ u1(0).
+
+
+ If the value is known at compile-time, the return type is comptime_int
+ instead of u1.
+
+ {#header_close#}
+
{#header_open|@cDefine#}
@cDefine(comptime name: []u8, value)
@@ -4834,21 +4847,6 @@ test "main" {
Creates a symbol in the output object file.
{#header_close#}
- {#header_open|@tagName#}
- @tagName(value: var) []const u8
-
- Converts an enum value or union value to a slice of bytes representing the name.
-
- {#header_close#}
- {#header_open|@TagType#}
- @TagType(T: type) type
-
- For an enum, returns the integer type that is used to store the enumeration value.
-
-
- For a union, returns the enum type that is used to store the tag value.
-
- {#header_close#}
{#header_open|@errorName#}
@errorName(err: error) []u8
@@ -4883,6 +4881,12 @@ test "main" {
{#see_also|Compile Variables#}
{#header_close#}
+
+ {#header_open|@field#}
+ @field(lhs: var, comptime field_name: []const u8) (field)
+ Preforms field access equivalent to lhs.->field_name-<.
+ {#header_close#}
+
{#header_open|@fieldParentPtr#}
@fieldParentPtr(comptime ParentType: type, comptime field_name: []const u8,
field_ptr: *T) *ParentType
@@ -4890,6 +4894,23 @@ test "main" {
Given a pointer to a field, returns the base pointer of a struct.
{#header_close#}
+
+ {#header_open|@floatCast#}
+ @floatCast(comptime DestType: type, value: var) DestType
+
+ Convert from one float type to another. This cast is safe, but may cause the
+ numeric value to lose precision.
+
+ {#header_close#}
+
+ {#header_open|@floatToInt#}
+ @floatToInt(comptime DestType: type, float: var) DestType
+
+ Converts the integer part of a floating point number to the destination type.
+ To convert the other way, use {#link|@intToFloat#}. This cast is always safe.
+
+ {#header_close#}
+
{#header_open|@frameAddress#}
@frameAddress()
@@ -4944,12 +4965,30 @@ fn add(a: i32, b: i32) i32 { return a + b; }
{#see_also|@noInlineCall#}
{#header_close#}
+
+ {#header_open|@intCast#}
+ @intCast(comptime DestType: type, int: var) DestType
+
+ Converts an integer to another integer while keeping the same numerical value.
+ Attempting to convert a number which is out of range of the destination type results in
+ {#link|Undefined Behavior#}.
+
+ {#header_close#}
+
+ {#header_open|@intToFloat#}
+ @intToFloat(comptime DestType: type, int: var) DestType
+
+ Converts an integer to the closest floating point representation. To convert the other way, use {#link|@floatToInt#}. This cast is always safe.
+
+ {#header_close#}
+
{#header_open|@intToPtr#}
@intToPtr(comptime DestType: type, int: usize) DestType
Converts an integer to a pointer. To convert the other way, use {#link|@ptrToInt#}.
{#header_close#}
+
{#header_open|@IntType#}
@IntType(comptime is_signed: bool, comptime bit_count: u8) type
@@ -4987,10 +5026,6 @@ fn add(a: i32, b: i32) i32 { return a + b; }
It does not include functions, variables, or constants.
{#header_close#}
- {#header_open|@field#}
- @field(lhs: var, comptime field_name: []const u8) (field)
- Preforms field access equivalent to lhs.->field_name-<.
- {#header_close#}
{#header_open|@memberType#}
@memberType(comptime T: type, comptime index: usize) type
Returns the field type of a struct or union.
@@ -5370,6 +5405,21 @@ pub const FloatMode = enum {
If no overflow or underflow occurs, returns false.
{#header_close#}
+ {#header_open|@tagName#}
+ @tagName(value: var) []const u8
+
+ Converts an enum value or union value to a slice of bytes representing the name.
+
+ {#header_close#}
+ {#header_open|@TagType#}
+ @TagType(T: type) type
+
+ For an enum, returns the integer type that is used to store the enumeration value.
+
+
+ For a union, returns the enum type that is used to store the tag value.
+
+ {#header_close#}
{#header_open|@truncate#}
@truncate(comptime T: type, integer) T
@@ -6665,7 +6715,7 @@ hljs.registerLanguage("zig", function(t) {
a = t.IR + "\\s*\\(",
c = {
keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong resume cancel await async orelse",
- built_in: "atomicLoad breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic ptrCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchgStrong cmpxchgWeak fence divExact truncate atomicRmw sqrt field typeInfo typeName newStackCall",
+ built_in: "atomicLoad breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic ptrCast intCast floatCast intToFloat floatToInt boolToInt bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchgStrong cmpxchgWeak fence divExact truncate atomicRmw sqrt field typeInfo typeName newStackCall",
literal: "true false null undefined"
},
n = [e, t.CLCM, t.CBCM, s, r];
diff --git a/src/all_types.hpp b/src/all_types.hpp
index bc2fe07c188107b6e3011c1eea29740fb7462e08..d94dfa0fcbe289097e8cfa7f6887ee0cfe7599b2 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1361,6 +1361,7 @@ enum BuiltinFnId {
BuiltinFnIdFloatCast,
BuiltinFnIdIntToFloat,
BuiltinFnIdFloatToInt,
+ BuiltinFnIdBoolToInt,
BuiltinFnIdIntType,
BuiltinFnIdSetCold,
BuiltinFnIdSetRuntimeSafety,
@@ -2048,6 +2049,7 @@ enum IrInstructionId {
IrInstructionIdFloatCast,
IrInstructionIdIntToFloat,
IrInstructionIdFloatToInt,
+ IrInstructionIdBoolToInt,
IrInstructionIdIntType,
IrInstructionIdBoolNot,
IrInstructionIdMemset,
@@ -2668,6 +2670,12 @@ struct IrInstructionFloatToInt {
IrInstruction *target;
};
+struct IrInstructionBoolToInt {
+ IrInstruction base;
+
+ IrInstruction *target;
+};
+
struct IrInstructionIntType {
IrInstruction base;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 4108cbbd687fc01123092077e922105fef105f85..84335d4e067297adc9d70bbb75a091b0dd1dd9c6 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4726,6 +4726,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdFloatCast:
case IrInstructionIdIntToFloat:
case IrInstructionIdFloatToInt:
+ case IrInstructionIdBoolToInt:
zig_unreachable();
case IrInstructionIdReturn:
@@ -6318,6 +6319,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdFloatCast, "floatCast", 2);
create_builtin_fn(g, BuiltinFnIdIntToFloat, "intToFloat", 2);
create_builtin_fn(g, BuiltinFnIdFloatToInt, "floatToInt", 2);
+ create_builtin_fn(g, BuiltinFnIdBoolToInt, "boolToInt", 1);
create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
diff --git a/src/ir.cpp b/src/ir.cpp
index 0b847fc4e43f03776b4f1672dd37aa4ab74d87e9..e6339a72f6906c8dae263401b08ef00e1cdc873b 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -476,6 +476,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFloatToInt *) {
return IrInstructionIdFloatToInt;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolToInt *) {
+ return IrInstructionIdBoolToInt;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionIntType *) {
return IrInstructionIdIntType;
}
@@ -1959,6 +1963,15 @@ static IrInstruction *ir_build_float_to_int(IrBuilder *irb, Scope *scope, AstNod
return &instruction->base;
}
+static IrInstruction *ir_build_bool_to_int(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target) {
+ IrInstructionBoolToInt *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->target = target;
+
+ ir_ref_instruction(target, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_int_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *is_signed, IrInstruction *bit_count) {
IrInstructionIntType *instruction = ir_build_instruction(irb, scope, source_node);
instruction->is_signed = is_signed;
@@ -4071,6 +4084,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
IrInstruction *result = ir_build_float_to_int(irb, scope, node, arg0_value, arg1_value);
return ir_lval_wrap(irb, scope, result, lval);
}
+ case BuiltinFnIdBoolToInt:
+ {
+ 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;
+
+ IrInstruction *result = ir_build_bool_to_int(irb, scope, node, arg0_value);
+ return ir_lval_wrap(irb, scope, result, lval);
+ }
case BuiltinFnIdIntType:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -10055,13 +10078,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
}
- // explicit cast from bool to int
- if (wanted_type->id == TypeTableEntryIdInt &&
- actual_type->id == TypeTableEntryIdBool)
- {
- return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpBoolToInt, false);
- }
-
// explicit widening conversion
if (wanted_type->id == TypeTableEntryIdInt &&
actual_type->id == TypeTableEntryIdInt &&
@@ -17605,6 +17621,33 @@ static TypeTableEntry *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrIns
return dest_type;
}
+static TypeTableEntry *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, IrInstructionBoolToInt *instruction) {
+ IrInstruction *target = instruction->target->other;
+ if (type_is_invalid(target->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ if (target->value.type->id != TypeTableEntryIdBool) {
+ ir_add_error(ira, instruction->target, buf_sprintf("expected bool, found '%s'",
+ buf_ptr(&target->value.type->name)));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
+ if (instr_is_comptime(target)) {
+ bool is_true;
+ if (!ir_resolve_bool(ira, target, &is_true))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
+ bigint_init_unsigned(&out_val->data.x_bigint, is_true ? 1 : 0);
+ return ira->codegen->builtin_types.entry_num_lit_int;
+ }
+
+ TypeTableEntry *u1_type = get_int_type(ira->codegen, false, 1);
+ IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, u1_type, CastOpBoolToInt, false);
+ ir_link_new_instruction(result, &instruction->base);
+ return u1_type;
+}
+
static TypeTableEntry *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstructionIntType *instruction) {
IrInstruction *is_signed_value = instruction->is_signed->other;
bool is_signed;
@@ -20143,6 +20186,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_int_to_float(ira, (IrInstructionIntToFloat *)instruction);
case IrInstructionIdFloatToInt:
return ir_analyze_instruction_float_to_int(ira, (IrInstructionFloatToInt *)instruction);
+ case IrInstructionIdBoolToInt:
+ return ir_analyze_instruction_bool_to_int(ira, (IrInstructionBoolToInt *)instruction);
case IrInstructionIdIntType:
return ir_analyze_instruction_int_type(ira, (IrInstructionIntType *)instruction);
case IrInstructionIdBoolNot:
@@ -20490,6 +20535,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdFloatCast:
case IrInstructionIdIntToFloat:
case IrInstructionIdFloatToInt:
+ case IrInstructionIdBoolToInt:
return false;
case IrInstructionIdAsm:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index b5722c52fae799e52c2401cd394ab3cb5fefd816..cb917201805a6897b41ae2b8463d1bef33540e9c 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -680,6 +680,12 @@ static void ir_print_float_to_int(IrPrint *irp, IrInstructionFloatToInt *instruc
fprintf(irp->f, ")");
}
+static void ir_print_bool_to_int(IrPrint *irp, IrInstructionBoolToInt *instruction) {
+ fprintf(irp->f, "@boolToInt(");
+ ir_print_other_instruction(irp, instruction->target);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_int_type(IrPrint *irp, IrInstructionIntType *instruction) {
fprintf(irp->f, "@IntType(");
ir_print_other_instruction(irp, instruction->is_signed);
@@ -1461,6 +1467,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdFloatToInt:
ir_print_float_to_int(irp, (IrInstructionFloatToInt *)instruction);
break;
+ case IrInstructionIdBoolToInt:
+ ir_print_bool_to_int(irp, (IrInstructionBoolToInt *)instruction);
+ break;
case IrInstructionIdIntType:
ir_print_int_type(irp, (IrInstructionIntType *)instruction);
break;
diff --git a/std/fmt/errol/index.zig b/std/fmt/errol/index.zig
index a5fb692857d92f3910d9c56e845bae26a17aadfa..3222913107159004ea37d7493d5e91891f8b7a72 100644
--- a/std/fmt/errol/index.zig
+++ b/std/fmt/errol/index.zig
@@ -329,7 +329,7 @@ fn errolInt(val: f64, buffer: []u8) FloatDecimal {
var mi: i32 = mismatch10(l64, h64);
var x: u64 = 1;
{
- var i = i32(lf == hf);
+ var i: i32 = @boolToInt(lf == hf);
while (i < mi) : (i += 1) {
x *= 10;
}
@@ -341,7 +341,7 @@ fn errolInt(val: f64, buffer: []u8) FloatDecimal {
var buf_index = u64toa(m64, buffer) - 1;
if (mi != 0) {
- buffer[buf_index - 1] += u8(buffer[buf_index] >= '5');
+ buffer[buf_index - 1] += @boolToInt(buffer[buf_index] >= '5');
} else {
buf_index += 1;
}
diff --git a/std/math/big/int.zig b/std/math/big/int.zig
index 21d9347c011988aef1fd404803b9521bf9b8fea6..29673538eb86bc14e01c41314f8c564991992507 100644
--- a/std/math/big/int.zig
+++ b/std/math/big/int.zig
@@ -117,7 +117,7 @@ pub const Int = struct {
fn bitcount(self: Int) usize {
const u_bit_count = (self.len - 1) * Limb.bit_count + (Limb.bit_count - @clz(self.limbs[self.len - 1]));
- return usize(!self.positive) + u_bit_count;
+ return usize(@boolToInt(!self.positive)) + u_bit_count;
}
pub fn sizeInBase(self: Int, base: usize) usize {
@@ -499,13 +499,13 @@ pub const Int = struct {
while (i < b.len) : (i += 1) {
var c: Limb = 0;
- c += Limb(@addWithOverflow(Limb, a[i], b[i], &r[i]));
- c += Limb(@addWithOverflow(Limb, r[i], carry, &r[i]));
+ c += @boolToInt(@addWithOverflow(Limb, a[i], b[i], &r[i]));
+ c += @boolToInt(@addWithOverflow(Limb, r[i], carry, &r[i]));
carry = c;
}
while (i < a.len) : (i += 1) {
- carry = Limb(@addWithOverflow(Limb, a[i], carry, &r[i]));
+ carry = @boolToInt(@addWithOverflow(Limb, a[i], carry, &r[i]));
}
r[i] = carry;
@@ -577,13 +577,13 @@ pub const Int = struct {
while (i < b.len) : (i += 1) {
var c: Limb = 0;
- c += Limb(@subWithOverflow(Limb, a[i], b[i], &r[i]));
- c += Limb(@subWithOverflow(Limb, r[i], borrow, &r[i]));
+ c += @boolToInt(@subWithOverflow(Limb, a[i], b[i], &r[i]));
+ c += @boolToInt(@subWithOverflow(Limb, r[i], borrow, &r[i]));
borrow = c;
}
while (i < a.len) : (i += 1) {
- borrow = Limb(@subWithOverflow(Limb, a[i], borrow, &r[i]));
+ borrow = @boolToInt(@subWithOverflow(Limb, a[i], borrow, &r[i]));
}
debug.assert(borrow == 0);
@@ -624,7 +624,7 @@ pub const Int = struct {
var r1: Limb = undefined;
// r1 = a + *carry
- const c1 = Limb(@addWithOverflow(Limb, a, carry.*, &r1));
+ const c1: Limb = @boolToInt(@addWithOverflow(Limb, a, carry.*, &r1));
// r2 = b * c
//
@@ -639,7 +639,7 @@ pub const Int = struct {
const c2 = @truncate(Limb, bc >> Limb.bit_count);
// r1 = r1 + r2
- const c3 = Limb(@addWithOverflow(Limb, r1, r2, &r1));
+ const c3: Limb = @boolToInt(@addWithOverflow(Limb, r1, r2, &r1));
// This never overflows, c1, c3 are either 0 or 1 and if both are 1 then
// c2 is at least <= @maxValue(Limb) - 2.
diff --git a/std/special/compiler_rt/comparetf2.zig b/std/special/compiler_rt/comparetf2.zig
index d63b7a7c924ad204bfa8fd66628a8d9f0096c092..479ba51962b10f391f38165d8b682920aa140f8e 100644
--- a/std/special/compiler_rt/comparetf2.zig
+++ b/std/special/compiler_rt/comparetf2.zig
@@ -91,5 +91,5 @@ pub extern fn __unordtf2(a: f128, b: f128) c_int {
const aAbs = @bitCast(rep_t, a) & absMask;
const bAbs = @bitCast(rep_t, b) & absMask;
- return c_int(aAbs > infRep or bAbs > infRep);
+ return @boolToInt(aAbs > infRep or bAbs > infRep);
}
diff --git a/test/cases/bool.zig b/test/cases/bool.zig
index 07d30454ee6732f366daee7fa3def3e95d035971..3e4ac9c1cfe4d30f72189c27d47e6b4949ead971 100644
--- a/test/cases/bool.zig
+++ b/test/cases/bool.zig
@@ -8,14 +8,14 @@ test "bool literals" {
test "cast bool to int" {
const t = true;
const f = false;
- assert(i32(t) == i32(1));
- assert(i32(f) == i32(0));
+ assert(@boolToInt(t) == u32(1));
+ assert(@boolToInt(f) == u32(0));
nonConstCastBoolToInt(t, f);
}
fn nonConstCastBoolToInt(t: bool, f: bool) void {
- assert(i32(t) == i32(1));
- assert(i32(f) == i32(0));
+ assert(@boolToInt(t) == u32(1));
+ assert(@boolToInt(f) == u32(0));
}
test "bool cmp" {
--
2.54.0
From e6b69151c0d30d2df95d1f92b65784eac7d186d9 Mon Sep 17 00:00:00 2001
From: Bodie Solomon
Date: Sun, 17 Jun 2018 14:35:00 -0400
Subject: [PATCH 20/28] Fix 1117: Use realpath in stage1 Darwin
os_self_exe_path
Issue: https://github.com/ziglang/zig/issues/1117
The macOS stage1 Zig compiler should look in Zig's real absolute path
for the Zig stdlib, but os_self_exe_path looks in its path as returned
by _NSGetExecutablePath, which may be a symlink. This means that a
symlinked Zig cannot find the Zig stdlib.
This patch fixes the issue by resolving the _NSGetExecutablePath result
to the real path using realpath() before copying the result to the
output path.
---
src/os.cpp | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/src/os.cpp b/src/os.cpp
index 97462bd6587bcec2cc6024b0866636727318106b..75e6dd865805bb42e2150e11d031c7e5cca6fefa 100644
--- a/src/os.cpp
+++ b/src/os.cpp
@@ -989,12 +989,28 @@ int os_self_exe_path(Buf *out_path) {
}
#elif defined(ZIG_OS_DARWIN)
+ // How long is the executable's path?
uint32_t u32_len = 0;
int ret1 = _NSGetExecutablePath(nullptr, &u32_len);
assert(ret1 != 0);
- buf_resize(out_path, u32_len);
- int ret2 = _NSGetExecutablePath(buf_ptr(out_path), &u32_len);
+
+ // Allocate a buffer for this path.
+ Buf *path_tmp = buf_alloc_fixed(u32_len);
+ // Fill the buffer with the path, which may be a symlink.
+ int ret2 = _NSGetExecutablePath(buf_ptr(path_tmp), &u32_len);
assert(ret2 == 0);
+
+ // Make a buffer with room for the real path.
+ Buf *resolve_tmp = buf_alloc_fixed(PATH_MAX);
+
+ // Fill it with the real resolved path.
+ char *real_path = realpath(buf_ptr(path_tmp), buf_ptr(resolve_tmp));
+ // IEEE Std 1003.1-2017: realpath() shall return a pointer to the
+ // buffer containing the resolved name.
+ assert(real_path == buf_ptr(resolve_tmp));
+
+ // Resize out_path and copy the resulting resolved absolute path.
+ buf_init_from_buf(out_path, resolve_tmp);
return 0;
#elif defined(ZIG_OS_LINUX)
buf_resize(out_path, 256);
--
2.54.0
From 045682289243c6186363e984babc706c3ed93152 Mon Sep 17 00:00:00 2001
From: Bodie Solomon
Date: Mon, 18 Jun 2018 07:01:59 -0400
Subject: [PATCH 21/28] Fix 1117: Tweak realpath logic to use out_path as
scratch space
---
src/os.cpp | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/src/os.cpp b/src/os.cpp
index 75e6dd865805bb42e2150e11d031c7e5cca6fefa..0e3c3f9a6052831136f82e48bfa68d916ac19c8a 100644
--- a/src/os.cpp
+++ b/src/os.cpp
@@ -994,23 +994,23 @@ int os_self_exe_path(Buf *out_path) {
int ret1 = _NSGetExecutablePath(nullptr, &u32_len);
assert(ret1 != 0);
- // Allocate a buffer for this path.
- Buf *path_tmp = buf_alloc_fixed(u32_len);
- // Fill the buffer with the path, which may be a symlink.
- int ret2 = _NSGetExecutablePath(buf_ptr(path_tmp), &u32_len);
+ // Make room for the executable path and resolved path in out_path,
+ // then subslice it for convenience.
+ buf_resize(out_path, u32_len + PATH_MAX);
+ Buf *tmp = buf_slice(out_path, 0, u32_len);
+ Buf *resolved = buf_slice(out_path, u32_len, u32_len + PATH_MAX);
+
+ // Fill the executable path.
+ int ret2 = _NSGetExecutablePath(buf_ptr(tmp), &u32_len);
assert(ret2 == 0);
- // Make a buffer with room for the real path.
- Buf *resolve_tmp = buf_alloc_fixed(PATH_MAX);
+ // Resolve the real path from that.
+ char *real_path = realpath(buf_ptr(tmp), buf_ptr(resolved));
+ assert(real_path == buf_ptr(resolved));
- // Fill it with the real resolved path.
- char *real_path = realpath(buf_ptr(path_tmp), buf_ptr(resolve_tmp));
- // IEEE Std 1003.1-2017: realpath() shall return a pointer to the
- // buffer containing the resolved name.
- assert(real_path == buf_ptr(resolve_tmp));
-
- // Resize out_path and copy the resulting resolved absolute path.
- buf_init_from_buf(out_path, resolve_tmp);
+ // Write the real path back into the beginning of out_path, resize.
+ buf_init_from_buf(out_path, resolved);
+ assert(buf_len(out_path) == buf_len(resolved));
return 0;
#elif defined(ZIG_OS_LINUX)
buf_resize(out_path, 256);
--
2.54.0
From c7057bd25b2a99e5ac61963efd588f5fe4ba93c6 Mon Sep 17 00:00:00 2001
From: Bodie Solomon
Date: Mon, 18 Jun 2018 07:37:26 -0400
Subject: [PATCH 22/28] Fix 1117: Revise realpath scratch logic
---
src/os.cpp | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/src/os.cpp b/src/os.cpp
index 0e3c3f9a6052831136f82e48bfa68d916ac19c8a..75f748e2f025331217d8c298a1b4093c66aa82ab 100644
--- a/src/os.cpp
+++ b/src/os.cpp
@@ -994,23 +994,24 @@ int os_self_exe_path(Buf *out_path) {
int ret1 = _NSGetExecutablePath(nullptr, &u32_len);
assert(ret1 != 0);
- // Make room for the executable path and resolved path in out_path,
- // then subslice it for convenience.
- buf_resize(out_path, u32_len + PATH_MAX);
- Buf *tmp = buf_slice(out_path, 0, u32_len);
- Buf *resolved = buf_slice(out_path, u32_len, u32_len + PATH_MAX);
+ // Make a buffer having room for the temp path.
+ Buf *tmp = buf_alloc_fixed(u32_len);
// Fill the executable path.
int ret2 = _NSGetExecutablePath(buf_ptr(tmp), &u32_len);
assert(ret2 == 0);
// Resolve the real path from that.
- char *real_path = realpath(buf_ptr(tmp), buf_ptr(resolved));
- assert(real_path == buf_ptr(resolved));
+ buf_resize(out_path, PATH_MAX);
+ char *real_path = realpath(buf_ptr(tmp), buf_ptr(out_path));
+ assert(real_path == buf_ptr(out_path));
+
+ // Deallocate our scratch space.
+ buf_deinit(tmp);
+
+ // Resize out_path for the correct length.
+ buf_resize(out_path, strlen(buf_ptr(out_path)));
- // Write the real path back into the beginning of out_path, resize.
- buf_init_from_buf(out_path, resolved);
- assert(buf_len(out_path) == buf_len(resolved));
return 0;
#elif defined(ZIG_OS_LINUX)
buf_resize(out_path, 256);
--
2.54.0
From d49d6f0cde782f4ec3c1d623d58644c3e51a6ce9 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 18 Jun 2018 11:04:18 -0400
Subject: [PATCH 23/28] fix compiler crash when using @intToFloat with float
literal
closes #1132
---
src/ir.cpp | 6 ++++++
test/cases/cast.zig | 6 ++++++
test/compile_errors.zig | 8 ++++++++
3 files changed, 20 insertions(+)
diff --git a/src/ir.cpp b/src/ir.cpp
index e6339a72f6906c8dae263401b08ef00e1cdc873b..a312b501ab3cefe22fa99c8d23a075d6cb406571 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -17602,6 +17602,12 @@ static TypeTableEntry *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrIns
if (type_is_invalid(target->value.type))
return ira->codegen->builtin_types.entry_invalid;
+ if (target->value.type->id != TypeTableEntryIdInt && target->value.type->id != TypeTableEntryIdComptimeInt) {
+ ir_add_error(ira, instruction->target, buf_sprintf("expected int type, found '%s'",
+ buf_ptr(&target->value.type->name)));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpIntToFloat, false);
ir_link_new_instruction(result, &instruction->base);
return dest_type;
diff --git a/test/cases/cast.zig b/test/cases/cast.zig
index 7035740c5487a297ccd1fb833abaa343d50cc351..f1e49c6d1f3ebbebeae4a0952a4e62f2a29d84e6 100644
--- a/test/cases/cast.zig
+++ b/test/cases/cast.zig
@@ -414,3 +414,9 @@ test "@floatCast comptime_int and comptime_float" {
assert(@typeOf(result) == f32);
assert(result == 1234.0);
}
+
+test "comptime_int @intToFloat" {
+ const result = @intToFloat(f32, 1234);
+ assert(@typeOf(result) == f32);
+ assert(result == 1234.0);
+}
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index b51a6e97612cca2685eb4ef9f7aed9f54528b20d..23337ca4793d2b3f4347a180a322ab26ddedd449 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -1,6 +1,14 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.add(
+ "non int passed to @intToFloat",
+ \\export fn entry() void {
+ \\ const x = @intToFloat(f32, 1.1);
+ \\}
+ ,
+ ".tmp_source.zig:2:32: error: expected int type, found 'comptime_float'",
+ );
cases.add(
"use implicit casts to assign null to non-nullable pointer",
\\export fn entry() void {
--
2.54.0
From 8fd7cc11e167c0b23892d6f22841bb6856d0f499 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 18 Jun 2018 11:12:15 -0400
Subject: [PATCH 24/28] disallow opaque as a return type of fn type syntax
closes #1115
---
src/analyze.cpp | 1 +
src/ir.cpp | 5 +++++
test/compile_errors.zig | 10 ++++++++++
3 files changed, 16 insertions(+)
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 758bc1a045b5fe0c0d3331dcb041e95533a85f23..10cdb0af6f573d8c5f431789b69d43efc49c4a27 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -1022,6 +1022,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
ensure_complete_type(g, fn_type_id->return_type);
if (type_is_invalid(fn_type_id->return_type))
return g->builtin_types.entry_invalid;
+ assert(fn_type_id->return_type->id != TypeTableEntryIdOpaque);
} else {
zig_panic("TODO implement inferred return types https://github.com/ziglang/zig/issues/447");
}
diff --git a/src/ir.cpp b/src/ir.cpp
index a312b501ab3cefe22fa99c8d23a075d6cb406571..c75a3ae7c1fbe0a9ef8035006d7389ef1382564d 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -18676,6 +18676,11 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc
fn_type_id.return_type = ir_resolve_type(ira, return_type_value);
if (type_is_invalid(fn_type_id.return_type))
return ira->codegen->builtin_types.entry_invalid;
+ if (fn_type_id.return_type->id == TypeTableEntryIdOpaque) {
+ ir_add_error(ira, instruction->return_type,
+ buf_sprintf("return type cannot be opaque"));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
if (fn_type_id.cc == CallingConventionAsync) {
if (instruction->async_allocator_type_value == nullptr) {
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 23337ca4793d2b3f4347a180a322ab26ddedd449..8c5abaaccc106394dece003ef827a155c12173a1 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -1,6 +1,15 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.add(
+ "use c_void as return type of fn ptr",
+ \\export fn entry() void {
+ \\ const a: fn () c_void = undefined;
+ \\}
+ ,
+ ".tmp_source.zig:2:20: error: return type cannot be opaque",
+ );
+
cases.add(
"non int passed to @intToFloat",
\\export fn entry() void {
@@ -9,6 +18,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
,
".tmp_source.zig:2:32: error: expected int type, found 'comptime_float'",
);
+
cases.add(
"use implicit casts to assign null to non-nullable pointer",
\\export fn entry() void {
--
2.54.0
From 48985a7e684ff32eb5d419a89eac3b92c08c3ee9 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 18 Jun 2018 12:02:30 -0400
Subject: [PATCH 25/28] langref: add docs for void
see #367
---
doc/langref.html.in | 90 ++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 84 insertions(+), 6 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 7c1f9b53d9e680beb494e0baf3d26450ecdb6b0f..f1ae2bafaa4490372717537154af666b4e997bd0 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -1651,7 +1651,7 @@ fn foo(bytes: []u8) u32 {
@ptrCast(*u32, f32(12.34)).*
Instead, use {#link|@bitCast#}:
@bitCast(u32, f32(12.34))
- As an added benefit, the @bitcast version works at compile-time.
+ As an added benefit, the @bitCast version works at compile-time.
{#see_also|Slices|Memory#}
{#header_close#}
{#header_close#}
@@ -3551,13 +3551,91 @@ const optional_value: ?i32 = null;
TODO: ptrcast builtin
TODO: explain number literals vs concrete types
{#header_close#}
+
{#header_open|void#}
- TODO: assigning void has no codegen
- TODO: hashmap with void becomes a set
- TODO: difference between c_void and void
- TODO: void is the default return value of functions
- TODO: functions require assigning the return value
+
+ void represents a type that has no value. Code that makes use of void values is
+ not included in the final generated code:
+
+ {#code_begin|syntax#}
+export fn entry() void {
+ var x: void = {};
+ var y: void = {};
+ x = y;
+}
+ {#code_end#}
+ When this turns into LLVM IR, there is no code generated in the body of entry,
+ even in debug mode. For example, on x86_64:
+ 0000000000000010 <entry>:
+ 10: 55 push %rbp
+ 11: 48 89 e5 mov %rsp,%rbp
+ 14: 5d pop %rbp
+ 15: c3 retq
+ These assembly instructions do not have any code associated with the void values -
+ they only perform the function call prologue and epilog.
+
+ void can be useful for instantiating generic types. For example, given a
+ Map(Key, Value), one can pass void for the Value
+ type to make it into a Set:
+
+ {#code_begin|test#}
+const std = @import("std");
+const assert = std.debug.assert;
+
+test "turn HashMap into a set with void" {
+ var map = std.HashMap(i32, void, hash_i32, eql_i32).init(std.debug.global_allocator);
+ defer map.deinit();
+
+ _ = try map.put(1, {});
+ _ = try map.put(2, {});
+
+ assert(map.contains(2));
+ assert(!map.contains(3));
+
+ _ = map.remove(2);
+ assert(!map.contains(2));
+}
+
+fn hash_i32(x: i32) u32 {
+ return @bitCast(u32, x);
+}
+
+fn eql_i32(a: i32, b: i32) bool {
+ return a == b;
+}
+ {#code_end#}
+ Note that this is different than using a dummy value for the hash map value.
+ By using void as the type of the value, the hash map entry type has no value field, and
+ thus the hash map takes up less space. Further, all the code that deals with storing and loading the
+ value is deleted, as seen above.
+
+
+ void is distinct from c_void, which is defined like this:
+ pub const c_void = @OpaqueType();.
+ void has a known size of 0 bytes, and c_void has an unknown, but non-zero, size.
+
+
+ Expressions of type void are the only ones whose value can be ignored. For example:
+
+ {#code_begin|test_err|expression value is ignored#}
+test "ignoring expression value" {
+ foo();
+}
+
+fn foo() i32 {
+ return 1234;
+}
+ {#code_end#}
+ However, if the expression has type void:
+ {#code_begin|test#}
+test "ignoring expression value" {
+ foo();
+}
+
+fn foo() void {}
+ {#code_end#}
{#header_close#}
+
{#header_open|this#}
TODO: example of this referring to Self struct
TODO: example of this referring to recursion function
--
2.54.0
From 4ce36a64755b4b2ca8bb28e3ac91b23dfe90ade8 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 18 Jun 2018 12:18:39 -0400
Subject: [PATCH 26/28] adjust logic for finding the path to zig executable on
darwin
---
src/os.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/os.cpp b/src/os.cpp
index 75f748e2f025331217d8c298a1b4093c66aa82ab..14e9effb1e51f6fd8288ebd4f793c7e9afc0e04d 100644
--- a/src/os.cpp
+++ b/src/os.cpp
@@ -1004,10 +1004,10 @@ int os_self_exe_path(Buf *out_path) {
// Resolve the real path from that.
buf_resize(out_path, PATH_MAX);
char *real_path = realpath(buf_ptr(tmp), buf_ptr(out_path));
- assert(real_path == buf_ptr(out_path));
-
- // Deallocate our scratch space.
- buf_deinit(tmp);
+ if (!real_path) {
+ buf_init_from_buf(out_path, tmp);
+ return 0;
+ }
// Resize out_path for the correct length.
buf_resize(out_path, strlen(buf_ptr(out_path)));
--
2.54.0
From cd4676a2338430d9e424f297b8b576143c5be180 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 18 Jun 2018 12:54:03 -0400
Subject: [PATCH 27/28] stage1: update darwin code to workaround old libc bug
See #1128
---
src/os.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/os.cpp b/src/os.cpp
index 14e9effb1e51f6fd8288ebd4f793c7e9afc0e04d..b7d2fd1de026bfd68a0fa0a800b955232c7cff3d 100644
--- a/src/os.cpp
+++ b/src/os.cpp
@@ -994,15 +994,15 @@ int os_self_exe_path(Buf *out_path) {
int ret1 = _NSGetExecutablePath(nullptr, &u32_len);
assert(ret1 != 0);
- // Make a buffer having room for the temp path.
Buf *tmp = buf_alloc_fixed(u32_len);
// Fill the executable path.
int ret2 = _NSGetExecutablePath(buf_ptr(tmp), &u32_len);
assert(ret2 == 0);
- // Resolve the real path from that.
- buf_resize(out_path, PATH_MAX);
+ // According to libuv project, PATH_MAX*2 works around a libc bug where
+ // the resolved path is sometimes bigger than PATH_MAX.
+ buf_resize(out_path, PATH_MAX*2);
char *real_path = realpath(buf_ptr(tmp), buf_ptr(out_path));
if (!real_path) {
buf_init_from_buf(out_path, tmp);
--
2.54.0
From 1ca90b585692c9611c64412844d2f3a7b3e11340 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Mon, 18 Jun 2018 13:55:03 -0400
Subject: [PATCH 28/28] zig fmt: support directories
zig fmt accepts any number of file paths. For each one, if it
is a file, then it formats the file. If it is a directory, then
zig recursively scans the directory, formatting all files that
end in `.zig`.
it maintains a map of paths that have been seen already, to avoid
softlink loops.
closes #1068
---
src-self-hosted/main.zig | 63 +++++++++++++++++++++++++++++++++++-----
1 file changed, 55 insertions(+), 8 deletions(-)
diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig
index ffe23d2ffebdbd949697b991f871179d28ab17c7..f7f38130b56121b587bc0aefcab9721946b0d221 100644
--- a/src-self-hosted/main.zig
+++ b/src-self-hosted/main.zig
@@ -700,6 +700,36 @@ const args_fmt_spec = []Flag{
}),
};
+const Fmt = struct {
+ seen: std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8),
+ queue: std.LinkedList([]const u8),
+ any_error: bool,
+
+ // file_path must outlive Fmt
+ fn addToQueue(self: *Fmt, file_path: []const u8) !void {
+ const new_node = try self.seen.allocator.construct(std.LinkedList([]const u8).Node{
+ .prev = undefined,
+ .next = undefined,
+ .data = file_path,
+ });
+
+ if (try self.seen.put(file_path, {})) |_| return;
+
+ self.queue.append(new_node);
+ }
+
+ fn addDirToQueue(self: *Fmt, file_path: []const u8) !void {
+ var dir = try std.os.Dir.open(self.seen.allocator, file_path);
+ defer dir.close();
+ while (try dir.next()) |entry| {
+ if (entry.kind == std.os.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) {
+ const full_path = try os.path.join(self.seen.allocator, file_path, entry.name);
+ try self.addToQueue(full_path);
+ }
+ }
+ }
+};
+
fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
var flags = try Args.parse(allocator, args_fmt_spec, args);
defer flags.deinit();
@@ -728,21 +758,38 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
}
};
- var fmt_errors = false;
+ var fmt = Fmt{
+ .seen = std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8).init(allocator),
+ .queue = std.LinkedList([]const u8).init(),
+ .any_error = false,
+ };
+
for (flags.positionals.toSliceConst()) |file_path| {
+ try fmt.addToQueue(file_path);
+ }
+
+ while (fmt.queue.popFirst()) |node| {
+ const file_path = node.data;
+
var file = try os.File.openRead(allocator, file_path);
defer file.close();
- const source_code = io.readFileAlloc(allocator, file_path) catch |err| {
- try stderr.print("unable to open '{}': {}\n", file_path, err);
- fmt_errors = true;
- continue;
+ const source_code = io.readFileAlloc(allocator, file_path) catch |err| switch (err) {
+ error.IsDir => {
+ try fmt.addDirToQueue(file_path);
+ continue;
+ },
+ else => {
+ try stderr.print("unable to open '{}': {}\n", file_path, err);
+ fmt.any_error = true;
+ continue;
+ },
};
defer allocator.free(source_code);
var tree = std.zig.parse(allocator, source_code) catch |err| {
try stderr.print("error parsing file '{}': {}\n", file_path, err);
- fmt_errors = true;
+ fmt.any_error = true;
continue;
};
defer tree.deinit();
@@ -755,7 +802,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
try errmsg.printToFile(&stderr_file, msg, color);
}
if (tree.errors.len != 0) {
- fmt_errors = true;
+ fmt.any_error = true;
continue;
}
@@ -769,7 +816,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
}
}
- if (fmt_errors) {
+ if (fmt.any_error) {
os.exit(1);
}
}
--
2.54.0